MCP: dynamic ipMIDI ports, more default key bindings, various minor fixes
authorPaul Davis <paul@linuxaudiosystems.com>
Wed, 25 Apr 2012 21:21:36 +0000 (21:21 +0000)
committerPaul Davis <paul@linuxaudiosystems.com>
Wed, 25 Apr 2012 21:21:36 +0000 (21:21 +0000)
git-svn-id: svn://localhost/ardour2/branches/3.0@12092 d708f5d6-7413-0410-9779-e7cbd77b26cf

13 files changed:
libs/ardour/ardour/rc_configuration_vars.h
libs/ardour/control_protocol_manager.cc
libs/ardour/midi_ui.cc
libs/surfaces/mackie/button.cc
libs/surfaces/mackie/device_info.cc
libs/surfaces/mackie/device_profile.cc
libs/surfaces/mackie/gui.cc
libs/surfaces/mackie/gui.h
libs/surfaces/mackie/interface.cc
libs/surfaces/mackie/mackie_control_protocol.cc
libs/surfaces/mackie/mackie_control_protocol.h
libs/surfaces/mackie/surface_port.cc
mcp/paul-nucleus.profile

index cd093d1d8021d36ab2b1374282cbc11913dab617..1f9e3c1037ddc887f4cfb3d2fdc9905659b43492 100644 (file)
@@ -50,8 +50,6 @@ CONFIG_VARIABLE (bool, first_midi_bank_is_zero, "diplay-first-midi-bank-as-zero"
 
 CONFIG_VARIABLE (uint32_t, feedback_interval_ms,  "feedback-interval-ms", 100)
 CONFIG_VARIABLE (bool, use_tranzport,  "use-tranzport", false)
-CONFIG_VARIABLE (std::string, mackie_device_name, "mackie-device-name", "Mackie Control Universal Pro")
-CONFIG_VARIABLE (std::string, mackie_device_profile, "mackie-device-profile", "default")
 CONFIG_VARIABLE (RemoteModel, remote_model, "remote-model", MixerOrdered)
 
 /* disk operations */
index 876091fa7d7ef3055155dac44b60383690b33774..c72d3f31d04beab581e924d35546268c193c0b89 100644 (file)
@@ -75,8 +75,16 @@ ControlProtocolManager::set_session (Session* s)
                                instantiate (**i);
                                (*i)->requested = false;
 
-                               if ((*i)->protocol && (*i)->state) {
-                                       (*i)->protocol->set_state (*(*i)->state, Stateful::loading_state_version);
+                               if ((*i)->protocol) {
+                                       if ((*i)->state) {
+                                               (*i)->protocol->set_state (*(*i)->state, Stateful::loading_state_version);
+                                       } else {
+                                               /* guarantee a call to
+                                                  set_state() whether we have
+                                                  existing state or not
+                                               */
+                                               (*i)->protocol->set_state (XMLNode(""), Stateful::loading_state_version);
+                                       }
                                }
                        }
                }
index e9e9eafb99da1aec51d207b166b1b469f4396607..770a3714575db47e53427c97d79a6a25dfca3e62 100644 (file)
@@ -134,8 +134,6 @@ MidiControlUI::reset_ports ()
 
        for (MIDI::Manager::PortList::const_iterator i = plist->begin(); i != plist->end(); ++i) {
 
-               cerr << "MIDI UI looking at port " << (*i)->name() << endl;
-
                if (!(*i)->centrally_parsed()) {
                        continue;
                }
index 11fc3919309ec42921a7d892b997b4e6ab9a70bf..dc26429a63b20f29ac827cc62c7fdbe5ab4b34a0 100644 (file)
@@ -51,8 +51,8 @@ Button::name_to_id (const std::string& name)
        if (!g_strcasecmp (name.c_str(), "ChannelRight")) { return ChannelRight; }
        if (!g_strcasecmp (name.c_str(), "Flip")) { return Flip; }
        if (!g_strcasecmp (name.c_str(), "Edit")) { return Edit; }
-       if (!g_strcasecmp (name.c_str(), "NameValue")) { return NameValue; }
-       if (!g_strcasecmp (name.c_str(), "TimecodeBeats")) { return TimecodeBeats; }
+       if (!g_strcasecmp (name.c_str(), "Name/Value")) { return NameValue; }
+       if (!g_strcasecmp (name.c_str(), "Timecode/Beats")) { return TimecodeBeats; }
        if (!g_strcasecmp (name.c_str(), "F1")) { return F1; }
        if (!g_strcasecmp (name.c_str(), "F2")) { return F2; }
        if (!g_strcasecmp (name.c_str(), "F3")) { return F3; }
index ba14d9f8fdc94b582fb70e7b3e0dbac5b28841f8..e9e5d1b04b73db59a4f23ab483952a8aa2eba467 100644 (file)
@@ -209,12 +209,16 @@ DeviceInfo::set_state (const XMLNode& node, int /* version */)
                }
        }
 
+       /* strip count is mandatory */
+
        if ((child = node.child ("Strips")) != 0) {
                if ((prop = child->property ("value")) != 0) {
                        if ((_strip_cnt = atoi (prop->value())) == 0) {
                                _strip_cnt = 8;
                        }
                }
+       } else {
+               return -1;
        }
 
        if ((child = node.child ("Extenders")) != 0) {
index 462c43b6789bbae99115feb71e861b3cab6265e0..04975270abe41ea4a90875f86647c487ea6ac7f9 100644 (file)
@@ -107,13 +107,11 @@ DeviceProfile::reload_device_profiles ()
 
        if (!devprofiles) {
                error << "No MCP device info files found using " << spath.to_string() << endmsg;
-               std::cerr << "No MCP device info files found using " << spath.to_string() << std::endl;
                return;
        }
 
        if (devprofiles->empty()) {
                error << "No MCP device info files found using " << spath.to_string() << endmsg;
-               std::cerr << "No MCP device info files found using " << spath.to_string() << std::endl;
                return;
        }
 
@@ -288,7 +286,7 @@ DeviceProfile::set_button_action (Button::ID id, int modifier_state, const strin
        ButtonActionMap::iterator i = _button_map.find (id);
 
        if (i == _button_map.end()) {
-               return;
+               i = _button_map.insert (std::make_pair (id, ButtonActions())).first;
        }
 
        string action (act);
@@ -360,6 +358,7 @@ DeviceProfile::save ()
        
        XMLTree tree;
        tree.set_root (&get_state());
+
        if (!tree.write (fullpath.to_string())) {
                error << string_compose ("MCP profile not saved to %1", fullpath.to_string()) << endmsg;
        }
index 1ecadec540918f20d7b246fc79feff1dc9a1c277..adaf2df94507f646aff0c6a02e0920696ddb8a9a 100644 (file)
@@ -72,7 +72,7 @@ MackieControlProtocolGUI::MackieControlProtocolGUI (MackieControlProtocol& p)
        , touch_sensitivity_adjustment (0, 0, 9, 1, 4)
        , touch_sensitivity_scale (touch_sensitivity_adjustment)
        , recalibrate_fader_button (_("Recalibrate Faders"))
-       , ipmidi_base_port_adjustment (21928, 0, 32767, 1, 1000)
+       , ipmidi_base_port_adjustment (_cp.ipmidi_base(), 0, 32767, 1, 1000)
        , ipmidi_base_port_spinner (ipmidi_base_port_adjustment)
 {
        Gtk::Label* l;
@@ -141,6 +141,7 @@ MackieControlProtocolGUI::MackieControlProtocolGUI (MackieControlProtocol& p)
        table->attach (ipmidi_base_port_spinner, 1, 2, 7, 8, AttachOptions(FILL|EXPAND), AttachOptions (0));
 
        ipmidi_base_port_spinner.set_sensitive (_cp.device_info().uses_ipmidi());
+       ipmidi_base_port_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &MackieControlProtocolGUI::ipmidi_spinner_changed));
 
        vector<string> profiles;
        
@@ -344,7 +345,7 @@ MackieControlProtocolGUI::refresh_function_key_editor ()
 
                Glib::RefPtr<Gtk::Action> act;
                string action;
-               const string defstring = "def";
+               const string defstring = "\u2022";
 
                action = dp.get_button_action (bid, 0);
                if (action.empty()) {
@@ -432,12 +433,12 @@ MackieControlProtocolGUI::action_changed (const Glib::ustring &sPath, const Glib
 
                std::map<std::string,std::string>::iterator i = action_map.find (text);
                
-               cerr << "Changed to " << text << endl;
-
                if (i == action_map.end()) {
                        return;
                }
 
+               cerr << "Changed to " << i->first << " aka " << i->second << endl;
+
                Glib::RefPtr<Gtk::Action> act = ActionManager::get_action (i->second.c_str());
 
                if (act) {
@@ -474,8 +475,9 @@ MackieControlProtocolGUI::action_changed (const Glib::ustring &sPath, const Glib
                        }
 
                        _cp.device_profile().set_button_action ((*row)[function_key_columns.id], modifier, i->second);
+               } else {
+                       std::cerr << "no such action\n";
                }
-                       
        }
 }
 
@@ -497,7 +499,13 @@ MackieControlProtocolGUI::profile_combo_changed ()
        string profile = _profile_combo.get_active_text();
 
        _cp.set_profile (profile);
-       ARDOUR::Config->set_mackie_device_profile (profile);
 
        refresh_function_key_editor ();
 }
+
+void
+MackieControlProtocolGUI::ipmidi_spinner_changed ()
+{
+       cerr << "Set IP MIDI base to " << ipmidi_base_port_spinner.get_value() << endl;
+       _cp.set_ipmidi_base ((int16_t) lrintf (ipmidi_base_port_spinner.get_value()));
+}
index f8268b9e35d645c823f7e485f12e096ba7e39583..9af0c21cab094291e1f058139f20687486884cd2 100644 (file)
@@ -92,6 +92,7 @@ class MackieControlProtocolGUI : public Gtk::Notebook
 
     void surface_combo_changed ();
     void profile_combo_changed ();
+    void ipmidi_spinner_changed ();
 
     std::map<std::string,std::string> action_map; // map from action names to paths
 
index a32ad42bb7a2eda5da23178c5cec6193c0efea86..294a222a6bee8ecff3836504f5f205358ee612c7 100644 (file)
@@ -36,7 +36,7 @@ new_mackie_protocol (ControlProtocolDescriptor*, Session* s)
        
        try {
                mcp = new MackieControlProtocol (*s);
-               mcp->set_active (true);
+               /* do not set active here - wait for set_state() */
        }
        catch (exception & e) {
                error << "Error instantiating MackieControlProtocol: " << e.what() << endmsg;
index f93379f3e77f076df18c03b033b3b0c16b7278d9..93202f607b198d6bb60b0482f838c17acee7c9db 100644 (file)
@@ -35,6 +35,7 @@
 
 #include "midi++/types.h"
 #include "midi++/port.h"
+#include "midi++/ipmidi_port.h"
 #include "pbd/pthread_utils.h"
 #include "pbd/error.h"
 #include "pbd/memento_command.h"
@@ -104,15 +105,14 @@ MackieControlProtocol::MackieControlProtocol (Session& session)
        , _view_mode (Mixer)
        , _current_selected_track (-1)
        , _modifier_state (0)
+       , _ipmidi_base (MIDI::IPMIDIPort::lowest_ipmidi_port_default)
+       , needs_ipmidi_restart (false)
 {
        DEBUG_TRACE (DEBUG::MackieControl, "MackieControlProtocol::MackieControlProtocol\n");
 
        DeviceInfo::reload_device_info ();
        DeviceProfile::reload_device_profiles ();
 
-       set_device (Config->get_mackie_device_name());
-       set_profile (Config->get_mackie_device_profile());
-       
        TrackSelectionChanged.connect (gui_connections, MISSING_INVALIDATOR, boost::bind (&MackieControlProtocol::gui_track_selection_changed, this, _1), this);
 
        _instance = this;
@@ -353,37 +353,30 @@ MackieControlProtocol::set_active (bool yn)
                return 0;
        }
 
-       try
-       {
-               if (yn) {
-
-                       /* start event loop */
-
-                       BaseUI::run ();
-
-                       create_surfaces ();
-                       connect_session_signals ();
-                       _active = true;
-                       update_surfaces ();
-
-                       /* set up periodic task for metering and automation
-                        */
-
-                       Glib::RefPtr<Glib::TimeoutSource> periodic_timeout = Glib::TimeoutSource::create (100); // milliseconds
-                       periodic_connection = periodic_timeout->connect (sigc::mem_fun (*this, &MackieControlProtocol::periodic));
-                       periodic_timeout->attach (main_loop()->get_context());
+       if (yn) {
+               
+               /* start event loop */
+               
+               BaseUI::run ();
+               
+               create_surfaces ();
+               connect_session_signals ();
+               _active = true;
+               update_surfaces ();
+               
+               /* set up periodic task for metering and automation
+                */
+               
+               Glib::RefPtr<Glib::TimeoutSource> periodic_timeout = Glib::TimeoutSource::create (100); // milliseconds
+               periodic_connection = periodic_timeout->connect (sigc::mem_fun (*this, &MackieControlProtocol::periodic));
+               periodic_timeout->attach (main_loop()->get_context());
+               
+       } else {
 
-               } else {
-                       BaseUI::quit ();
-                       close();
-                       _active = false;
-               }
-       }
-       
-       catch (exception & e) {
-               DEBUG_TRACE (DEBUG::MackieControl, string_compose ("set_active to false because exception caught: %1\n", e.what()));
+               BaseUI::quit ();
+               close ();
                _active = false;
-               throw;
+
        }
 
        return 0;
@@ -396,6 +389,11 @@ MackieControlProtocol::periodic ()
                return false;
        }
 
+       if (needs_ipmidi_restart) {
+               ipmidi_restart ();
+               return true;
+       }
+
        struct timeval now;
        uint64_t now_usecs;
        gettimeofday (&now, 0);
@@ -475,8 +473,6 @@ MackieControlProtocol::update_surfaces()
                return;
        }
 
-
-
        // do the initial bank switch to connect signals
        // _current_initial_bank is initialised by set_state
        switch_banks (_current_initial_bank, true);
@@ -549,10 +545,6 @@ MackieControlProtocol::set_device (const string& device_name)
 
        _device_info = d->second;
 
-       /* store it away in a global location */
-       
-       Config->set_mackie_device_name (device_name);
-
        if (_active) {
                create_surfaces ();
                switch_banks (0, true);
@@ -637,15 +629,22 @@ XMLNode&
 MackieControlProtocol::get_state()
 {
        DEBUG_TRACE (DEBUG::MackieControl, "MackieControlProtocol::get_state\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
-       ostringstream os;
-       os << _current_initial_bank;
-       node->add_property (X_("bank"), os.str());
+       snprintf (buf, sizeof (buf), "%d", _current_initial_bank);
+       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_("device-profile"), _device_profile.name());
+       node->add_property (X_("device-name"), _device_info.name());
 
        return *node;
 }
@@ -657,15 +656,34 @@ MackieControlProtocol::set_state (const XMLNode & node, int /*version*/)
 
        int retval = 0;
        const XMLProperty* prop;
+       uint32_t bank;
+       bool active = _active;
+
+       if ((prop = node.property (X_("ipmidi-base"))) != 0) {
+               set_ipmidi_base (atoi (prop->value()));
+       }
 
        // fetch current bank
        if ((prop = node.property (X_("bank"))) != 0) {
-               string bank = prop->value();
-               set_active (true);
-               uint32_t new_bank = atoi (bank.c_str());
-               if (_current_initial_bank != new_bank) {
-                       switch_banks (new_bank);
-               }
+               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());
+       }
+
+       if ((prop = node.property (X_("device-profile"))) != 0) {
+               set_profile (prop->value());
+       }
+
+       set_active (active);
+
+       if (_active) {
+               switch_banks (bank, true);
        }
 
        return retval;
@@ -1166,8 +1184,6 @@ MackieControlProtocol::force_special_route_to_strip (boost::shared_ptr<Route> r,
 void
 MackieControlProtocol::gui_track_selection_changed (ARDOUR::RouteNotificationListPtr rl)
 {
-       cerr << "GUI Selection changed, " << rl->size() << " routes\n";
-
        for (Surfaces::iterator s = surfaces.begin(); s != surfaces.end(); ++s) {
                (*s)->gui_selection_changed (rl);
        }
@@ -1366,3 +1382,31 @@ MackieControlProtocol::pull_route_range (DownButtonList& down, RouteList& select
                }
        }
 }
+
+void
+MackieControlProtocol::set_ipmidi_base (int16_t portnum)
+{
+       /* this will not be saved without a session save, so .. */
+
+       session->set_dirty ();
+
+       _ipmidi_base = portnum;
+
+       /* if the current device uses ipMIDI we need
+          to restart.
+       */
+
+       if (_active && _device_info.uses_ipmidi()) {
+               needs_ipmidi_restart = true;
+       }
+}
+
+void
+MackieControlProtocol::ipmidi_restart ()
+{
+       clear_ports ();
+       surfaces.clear ();      
+       create_surfaces ();
+       switch_banks (_current_initial_bank, true);
+       needs_ipmidi_restart = false;
+}
index ad01c2d1de9a86f104b6b00a8df69bdec0879302..d092a372cd1a5a6576a723e6fb60280979922c76 100644 (file)
@@ -192,6 +192,9 @@ class MackieControlProtocol
        void add_down_select_button (int surface, int strip);
        void remove_down_select_button (int surface, int strip);
        void select_range ();
+
+       int16_t ipmidi_base() const { return _ipmidi_base; }
+       void    set_ipmidi_base (int16_t);
        
   protected:
        // shut down the surface
@@ -278,6 +281,8 @@ class MackieControlProtocol
        int                      _modifier_state;
        PortSources               port_sources;
        ButtonMap                 button_map;
+       int16_t                  _ipmidi_base;
+       bool                      needs_ipmidi_restart;
 
        void create_surfaces ();
        bool periodic();
@@ -286,10 +291,9 @@ class MackieControlProtocol
        void clear_ports ();
        void force_special_route_to_strip (boost::shared_ptr<ARDOUR::Route> r, uint32_t surface, uint32_t strip_number);
        void build_button_map ();
-
        void gui_track_selection_changed (ARDOUR::RouteNotificationListPtr);
-
-
+       void ipmidi_restart ();
+       
        /* BUTTON HANDLING */
 
        typedef std::set<uint32_t> DownButtonList;
index 77d71b1a6add74e2cfc6d4121863d180eaf642be..bf5e7417ab5259be6c304ee3abd958b7cc6b46f4 100644 (file)
@@ -56,7 +56,7 @@ SurfacePort::SurfacePort (Surface& s)
        , _output_port (0)
 {
        if (_surface->mcp().device_info().uses_ipmidi()) {
-               _input_port = new MIDI::IPMIDIPort (MIDI::IPMIDIPort::lowest_ipmidi_port_default+_surface->number());
+               _input_port = new MIDI::IPMIDIPort (_surface->mcp().ipmidi_base() +_surface->number());
                _output_port = _input_port;
        } else {
                jack_client_t* jack = MackieControlProtocol::instance()->get_session().engine().jack();
index 91073da6b5aaf1b06b7e16c9deaedf98dbb0479b..fec778b9dc0d1c552310938fe06b14a905aaa46c 100644 (file)
@@ -1,9 +1,19 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <MackieDeviceProfile>
   <Name value="Basic SSL Nucleus"/>
-  <MasterOn value="14"/>
-  <MonitorOn value="15"/>
   <Buttons>
-    <Button name="f1" plain="Editor/goto-visual-state-1"/>
+    <Button name="Name/Value" shift="Transport/ToggleExternalSync"/>
+    <Button name="F1" plain="MouseMode/set-mouse-mode-object" shift="Transport/GotoStart" cmdalt="options/SendMidiClock"/>
+    <Button name="F2" plain="MouseMode/set-mouse-mode-range" shift="Transport/ToggleExternalSync"/>
+    <Button name="F3" plain="Transport/ToggleClick" control="Transport/ToggleAutoReturn" shift="Transport/ToggleAutoPlay"/>
+    <Button name="F4" plain="Transport/TogglePunch" control="Transport/TogglePunchOut" shift="Transport/TogglePunchIn" option="Transport/ToggleExternalSync"/>
+    <Button name="F5" plain="Zoom/zoom-focus-center" control="Zoom/zoom-focus-mouse" shift="Zoom/zoom-focus-left" option="Zoom/zoom-focus-playhead" cmdalt="Zoom/zoom-focus-right" shiftcontrol="Zoom/zoom-focus-edit"/>
+    <Button name="F6" plain="Common/toggle-audio-connection-manager" control="Common/ToggleBigClock" shift="Common/toggle-midi-connection-manager" option="Common/toggle-mixer-on-top"/>
+    <Button name="F7" plain="Transport/ToggleExternalSync"/>
+    <Button name="F8" plain="Editor/cycle-snap-mode" control="Editor/prev-snap-choice" shift="Editor/next-snap-choice" option="Editor/prev-snap-choice"/>
+    <Button name="Marker" plain="Editor/jump-forward-to-mark"/>
+    <Button name="Loop" shift="Region/loop-region"/>
+    <Button name="Nudge" plain="Region/nudge-forward" control="Region/naturalize-region" shift="Region/nudge-backward" option="Transport/ToggleExternalSync"/>
+    <Button name="Drop" plain="Editor/jump-backward-to-mark"/>
   </Buttons>
 </MackieDeviceProfile>