Merge windows+cc branch into cairocanvas branch. Not finished, need to now merge...
[ardour.git] / libs / surfaces / mackie / mackie_control_protocol.cc
index 194e35a26ffe6439cdcd05cf797f6da1de6d96cc..c83ce819d950edae1ce168b036ea4ffdddbfa03e 100644 (file)
@@ -95,8 +95,6 @@ MackieControlProtocol::MackieControlProtocol (Session& session)
        , AbstractUI<MackieControlUIRequest> ("mackie")
        , _current_initial_bank (0)
        , _timecode_type (ARDOUR::AnyTime::BBT)
-       , _input_bundle (new ARDOUR::Bundle (_("Mackie Control In"), true))
-       , _output_bundle (new ARDOUR::Bundle (_("Mackie Control Out"), false))
        , _gui (0)
        , _zoom_mode (false)
        , _scrub_mode (false)
@@ -108,6 +106,8 @@ MackieControlProtocol::MackieControlProtocol (Session& session)
        , needs_ipmidi_restart (false)
        , _metering_active (true)
        , _initialized (false)
+       , _surfaces_state (0)
+       , _surfaces_version (0)
 {
        DEBUG_TRACE (DEBUG::MackieControl, "MackieControlProtocol::MackieControlProtocol\n");
 
@@ -131,7 +131,7 @@ MackieControlProtocol::~MackieControlProtocol()
        DEBUG_TRACE (DEBUG::MackieControl, "MackieControlProtocol::~MackieControlProtocol tear_down_gui ()\n");
        tear_down_gui ();
 
-       _active = false;
+       delete _surfaces_state;
 
        /* stop event loop */
        DEBUG_TRACE (DEBUG::MackieControl, "MackieControlProtocol::~MackieControlProtocol BaseUI::quit ()\n");
@@ -382,7 +382,7 @@ MackieControlProtocol::set_active (bool yn)
 {
        DEBUG_TRACE (DEBUG::MackieControl, string_compose("MackieControlProtocol::set_active init with yn: '%1'\n", yn));
 
-       if (yn == _active) {
+       if (yn == active()) {
                return 0;
        }
 
@@ -396,7 +396,6 @@ MackieControlProtocol::set_active (bool yn)
                        return -1;
                }
                connect_session_signals ();
-               _active = true;
                update_surfaces ();
                
                /* set up periodic task for metering and automation
@@ -410,10 +409,11 @@ MackieControlProtocol::set_active (bool yn)
 
                BaseUI::quit ();
                close ();
-               _active = false;
 
        }
 
+       ControlProtocol::set_active (yn);
+
        DEBUG_TRACE (DEBUG::MackieControl, string_compose("MackieControlProtocol::set_active done with yn: '%1'\n", yn));
 
        return 0;
@@ -422,7 +422,7 @@ MackieControlProtocol::set_active (bool yn)
 bool
 MackieControlProtocol::periodic ()
 {
-       if (!_active) {
+       if (!active()) {
                return false;
        }
 
@@ -525,7 +525,7 @@ void
 MackieControlProtocol::update_surfaces()
 {
        DEBUG_TRACE (DEBUG::MackieControl, "MackieControlProtocol::update_surfaces() init\n");
-       if (!_active) {
+       if (!active()) {
                return;
        }
 
@@ -608,34 +608,36 @@ MackieControlProtocol::set_profile (const string& profile_name)
 }      
 
 int
-MackieControlProtocol::set_device (const string& device_name, bool allow_activation)
+MackieControlProtocol::set_device_info (const string& device_name)
 {
        map<string,DeviceInfo>::iterator d = DeviceInfo::device_info.find (device_name);
 
-       DEBUG_TRACE (DEBUG::MackieControl, string_compose ("new device chosen %1, activation allowed ? %2\n",
-                                                          device_name, allow_activation));
+       DEBUG_TRACE (DEBUG::MackieControl, string_compose ("new device chosen %1\n", device_name));
 
        if (d == DeviceInfo::device_info.end()) {
                return -1;
        }
        
-       if (_active) {
-               clear_ports ();
-               clear_surfaces ();
+       _device_info = d->second;
+
+       return 0;
+}
+
+int
+MackieControlProtocol::set_device (const string& device_name)
+{
+       if (set_device_info (device_name)) {
+               return -1;
        }
 
-       _device_info = d->second;
+       clear_surfaces ();
 
-       if (allow_activation) {
-               set_active (true);
-       } else {
-               if (_active) {
-                       if (create_surfaces ()) {
-                               return -1;
-                       }
-                       switch_banks (0, true);
-               }
+       if (create_surfaces ()) {
+               return -1;
        }
+
+       switch_banks (0, true);
+
        return 0;
 }
 
@@ -664,6 +666,10 @@ MackieControlProtocol::create_surfaces ()
                        return -1;
                }
 
+               if (_surfaces_state) {
+                       surface->set_state (*_surfaces_state, _surfaces_version);
+               }
+
                {
                        Glib::Threads::Mutex::Lock lm (surfaces_lock);
                        surfaces.push_back (surface);
@@ -680,6 +686,10 @@ MackieControlProtocol::create_surfaces ()
                stype = ext;
 
                if (!_device_info.uses_ipmidi()) {
+
+                       _input_bundle.reset (new ARDOUR::Bundle (_("Mackie Control In"), true));
+                       _output_bundle.reset (new ARDOUR::Bundle (_("Mackie Control Out"), false));
+
                        _input_bundle->add_channel (
                                surface->port().input_port().name(),
                                ARDOUR::DataType::MIDI,
@@ -691,6 +701,16 @@ MackieControlProtocol::create_surfaces ()
                                ARDOUR::DataType::MIDI,
                                session->engine().make_port_name_non_relative (surface->port().output_port().name())
                                );
+
+                       session->BundleAdded (_input_bundle);
+                       session->BundleAdded (_output_bundle);
+
+               } else {
+                       _input_bundle.reset ((ARDOUR::Bundle*) 0);
+                       _output_bundle.reset ((ARDOUR::Bundle*) 0);
+
+                       session->BundleRemoved (_input_bundle);
+                       session->BundleRemoved (_output_bundle);
                }
 
                int fd;
@@ -715,9 +735,6 @@ MackieControlProtocol::create_surfaces ()
 void 
 MackieControlProtocol::close()
 {
-       clear_ports ();
-
-       port_connections.drop_connections ();
        session_connections.drop_connections ();
        route_connections.drop_connections ();
        periodic_connection.disconnect ();
@@ -728,38 +745,42 @@ MackieControlProtocol::close()
 XMLNode& 
 MackieControlProtocol::get_state()
 {
+       XMLNode& node (ControlProtocol::get_state());
+
        DEBUG_TRACE (DEBUG::MackieControl, "MackieControlProtocol::get_state init\n");
        char buf[16];
 
-       // add name of protocol
-       XMLNode* node = new XMLNode (X_("Protocol"));
-       node->add_property (X_("name"), ARDOUR::ControlProtocol::_name);
-
        // add current bank
        snprintf (buf, sizeof (buf), "%d", _current_initial_bank);
-       node->add_property (X_("bank"), buf);
+       node.add_property (X_("bank"), buf);
 
        // ipMIDI base port (possibly not used)
        snprintf (buf, sizeof (buf), "%d", _ipmidi_base);
-       node->add_property (X_("ipmidi-base"), buf);
+       node.add_property (X_("ipmidi-base"), buf);
+
+       node.add_property (X_("device-profile"), _device_profile.name());
+       node.add_property (X_("device-name"), _device_info.name());
+
+       XMLNode* snode = new XMLNode (X_("Surfaces"));
+       for (Surfaces::iterator s = surfaces.begin(); s != surfaces.end(); ++s) {
+               snode->add_child_nocopy ((*s)->get_state());
+       }
 
-       node->add_property (X_("device-profile"), _device_profile.name());
-       node->add_property (X_("device-name"), _device_info.name());
+       node.add_child_nocopy (*snode);
 
        DEBUG_TRACE (DEBUG::MackieControl, "MackieControlProtocol::get_state done\n");
 
-       return *node;
+       return node;
 }
 
 int 
-MackieControlProtocol::set_state (const XMLNode & node, int /*version*/)
+MackieControlProtocol::set_state (const XMLNode & node, int version)
 {
-       DEBUG_TRACE (DEBUG::MackieControl, string_compose ("MackieControlProtocol::set_state: active %1\n", _active));
+       DEBUG_TRACE (DEBUG::MackieControl, string_compose ("MackieControlProtocol::set_state: active %1\n", active()));
 
        int retval = 0;
        const XMLProperty* prop;
        uint32_t bank = 0;
-       bool active = _active;
 
        if ((prop = node.property (X_("ipmidi-base"))) != 0) {
                set_ipmidi_base (atoi (prop->value()));
@@ -770,24 +791,26 @@ MackieControlProtocol::set_state (const XMLNode & node, int /*version*/)
                bank = atoi (prop->value());
        }
        
-       if ((prop = node.property (X_("active"))) != 0) {
-               active = string_is_affirmative (prop->value());
-       }
-
        if ((prop = node.property (X_("device-name"))) != 0) {
-               set_device (prop->value(), false);
+               set_device_info (prop->value());
        }
 
        if ((prop = node.property (X_("device-profile"))) != 0) {
                set_profile (prop->value());
        }
+       
+       XMLNode* snode = node.child (X_("Surfaces"));
+       
+       delete _surfaces_state;
+       _surfaces_state = 0;
 
-       set_active (active);
-
-       if (_active) {
-               switch_banks (bank, true);
+       if (snode) {
+               _surfaces_state = new XMLNode (*snode);
+               _surfaces_version = version;
        }
 
+       switch_banks (bank, true);
+       
        DEBUG_TRACE (DEBUG::MackieControl, "MackieControlProtocol::set_state done\n");
 
        return retval;
@@ -1034,8 +1057,12 @@ list<boost::shared_ptr<ARDOUR::Bundle> >
 MackieControlProtocol::bundles ()
 {
        list<boost::shared_ptr<ARDOUR::Bundle> > b;
-       b.push_back (_input_bundle);
-       b.push_back (_output_bundle);
+
+       if (_input_bundle) {
+               b.push_back (_input_bundle);
+               b.push_back (_output_bundle);
+       }
+
        return b;
 }
 
@@ -1260,8 +1287,10 @@ MackieControlProtocol::midi_input_handler (IOCondition ioc, MIDI::Port* port)
 void
 MackieControlProtocol::clear_ports ()
 {
-       _input_bundle->remove_channels ();
-       _output_bundle->remove_channels ();
+       if (_input_bundle) {
+               _input_bundle->remove_channels ();
+               _output_bundle->remove_channels ();
+       }
 
        for (PortSources::iterator i = port_sources.begin(); i != port_sources.end(); ++i) {
                g_source_destroy (*i);
@@ -1383,7 +1412,7 @@ MackieControlProtocol::add_down_select_button (int surface, int strip)
 void
 MackieControlProtocol::remove_down_select_button (int surface, int strip)
 {
-       DownButtonList::iterator x = find (_down_select_buttons.begin(), _down_select_buttons.end(), (surface<<8)|(strip&0xf));
+       DownButtonList::iterator x = find (_down_select_buttons.begin(), _down_select_buttons.end(), (uint32_t) (surface<<8)|(strip&0xf));
        DEBUG_TRACE (DEBUG::MackieControl, string_compose ("removing surface %1 strip %2 from down select buttons\n", surface, strip));
        if (x != _down_select_buttons.end()) {
                _down_select_buttons.erase (x);
@@ -1582,7 +1611,7 @@ MackieControlProtocol::set_ipmidi_base (int16_t portnum)
           to restart.
        */
 
-       if (_active && _device_info.uses_ipmidi()) {
+       if (active() && _device_info.uses_ipmidi()) {
                needs_ipmidi_restart = true;
        }
 }
@@ -1590,7 +1619,6 @@ MackieControlProtocol::set_ipmidi_base (int16_t portnum)
 int
 MackieControlProtocol::ipmidi_restart ()
 {
-       clear_ports ();
        clear_surfaces ();
        if (create_surfaces ()) {
                return -1;
@@ -1603,6 +1631,7 @@ MackieControlProtocol::ipmidi_restart ()
 void
 MackieControlProtocol::clear_surfaces ()
 {
+       clear_ports ();
        Glib::Threads::Mutex::Lock lm (surfaces_lock);
        surfaces.clear ();      
 }