make MMC work again, make tracing MIDI input work again, add GUI control for MMC...
authorPaul Davis <paul@linuxaudiosystems.com>
Tue, 20 Feb 2007 21:26:20 +0000 (21:26 +0000)
committerPaul Davis <paul@linuxaudiosystems.com>
Tue, 20 Feb 2007 21:26:20 +0000 (21:26 +0000)
git-svn-id: svn://localhost/ardour2/trunk@1480 d708f5d6-7413-0410-9779-e7cbd77b26cf

17 files changed:
gtk2_ardour/ardour_ui.cc
gtk2_ardour/ardour_ui.h
gtk2_ardour/ardour_ui2.cc
gtk2_ardour/keyboard.cc
gtk2_ardour/option_editor.cc
gtk2_ardour/option_editor.h
libs/ardour/ardour/configuration_vars.h
libs/ardour/ardour/session.h
libs/ardour/session_midi.cc
libs/ardour/session_state.cc
libs/midi++2/midi++/mmc.h
libs/midi++2/midiparser.cc
libs/midi++2/mmc.cc
libs/pbd/controllable.cc
libs/pbd/pbd/controllable.h
libs/surfaces/generic_midi/generic_midi_control_protocol.cc
libs/surfaces/mackie/mackie_control_protocol.cc

index 71ef0387cfa08b6c0f8505632228f26205e96c13..bd2b7fced0b594a6405d2e294611458078fbda1e 100644 (file)
@@ -707,40 +707,6 @@ ARDOUR_UI::update_wall_clock ()
 
        return TRUE;
 }
-void
-ARDOUR_UI::control_methods_adjusted ()
-
-{
-       int which_method;
-
-       which_method = (int) online_control_button->adjustment.get_value();
-       switch (which_method) {
-       case 0:
-               allow_mmc_and_local ();
-               break;
-       case 1:
-               allow_mmc_only ();
-               break;
-       case 2:
-               allow_local_only ();
-               break;
-       default:
-               fatal << _("programming error: impossible control method") << endmsg;
-       }
-}
-       
-
-void
-ARDOUR_UI::mmc_device_id_adjusted ()
-
-{
-#if 0
-       if (mmc) {
-               int dev_id = (int) mmc_id_button->adjustment.get_value();
-               mmc->set_device_id (dev_id);
-       }
-#endif
-}
 
 gint
 ARDOUR_UI::session_menu (GdkEventButton *ev)
@@ -1309,24 +1275,6 @@ ARDOUR_UI::map_transport_state ()
        }
 }
 
-void
-ARDOUR_UI::allow_local_only ()
-{
-
-}
-
-void
-ARDOUR_UI::allow_mmc_only ()
-{
-
-}
-
-void
-ARDOUR_UI::allow_mmc_and_local ()
-{
-
-}
-
 void
 ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
 {
index dfef964c67aa807f7e2cc666bfb5dd102cc343b0..00d8deacbf3032f029a20f5c1fd49434aed7b101 100644 (file)
@@ -273,9 +273,6 @@ class ARDOUR_UI : public Gtkmm2ext::UI
        GlobalClickBox    *crossfade_time_button;
        vector<string>     crossfade_time_strings;
 
-       GlobalClickBox    *mmc_id_button;
-       vector<string>     mmc_id_strings;
-
        Gtk::ToggleButton   preroll_button;
        Gtk::ToggleButton   postroll_button;
 
@@ -285,7 +282,6 @@ class ARDOUR_UI : public Gtkmm2ext::UI
        int  setup_windows ();
        void setup_transport ();
        void setup_clock ();
-       void setup_adjustables ();
 
        static ARDOUR_UI *theArdourUI;
 
@@ -313,9 +309,6 @@ class ARDOUR_UI : public Gtkmm2ext::UI
        void start_blinking ();
        void stop_blinking ();
 
-       void control_methods_adjusted ();
-       void mmc_device_id_adjusted ();
-
        void about_signal_response(int response);
 
   private:
@@ -467,14 +460,6 @@ class ARDOUR_UI : public Gtkmm2ext::UI
 
        void transport_rec_enable_blink (bool onoff);
 
-       /* These change where we accept control from:
-          MMC, X (local) or both.
-       */
-
-       void allow_mmc_only ();
-       void allow_mmc_and_local ();
-       void allow_local_only ();
-
        Gtk::Menu*        session_popup_menu;
 
        struct RecentSessionModelColumns : public Gtk::TreeModel::ColumnRecord {
index 5f1f0e3b7b285b5a7ae03c36d687a46dae6f2a37..bb7e306c8d901178fd4630bea82a34a2d73c3d00 100644 (file)
@@ -73,7 +73,6 @@ ARDOUR_UI::setup_windows ()
 
        setup_clock ();
        setup_transport();
-       setup_adjustables ();
        build_menu_bar ();
 
        top_packer.pack_start (menu_bar_base, false, false);
@@ -84,38 +83,6 @@ ARDOUR_UI::setup_windows ()
        return 0;
 }
 
-void
-ARDOUR_UI::setup_adjustables ()
-{
-       adjuster_table.set_homogeneous (true);
-
-       online_control_strings.push_back (_("MMC + Local"));
-       online_control_strings.push_back (_("MMC"));
-       online_control_strings.push_back (_("Local"));
-
-       online_control_button = new GlobalClickBox ("CONTROL",
-                                                   online_control_strings);
-
-       online_control_button->adjustment.signal_value_changed().connect(mem_fun(*this,&ARDOUR_UI::control_methods_adjusted));
-
-       mmc_id_strings.push_back ("1");
-       mmc_id_strings.push_back ("2");
-       mmc_id_strings.push_back ("3");
-       mmc_id_strings.push_back ("4");
-       mmc_id_strings.push_back ("5");
-       mmc_id_strings.push_back ("6");
-       mmc_id_strings.push_back ("7");
-       mmc_id_strings.push_back ("8");
-       mmc_id_strings.push_back ("9");
-
-       mmc_id_button = new GlobalClickBox (_("MMC ID"), mmc_id_strings);
-
-       mmc_id_button->adjustment.signal_value_changed().connect (mem_fun(*this,&ARDOUR_UI::mmc_device_id_adjusted));
-
-       adjuster_table.attach (*online_control_button, 0, 2, 1, 2, FILL|EXPAND, FILL, 5, 5);
-       adjuster_table.attach (*mmc_id_button, 2, 3, 1, 2, FILL, FILL, 5, 5);
-}
-
 void
 ARDOUR_UI::transport_stopped ()
 {
index 517ef973d4cef5bc4930bb5b6d72b27b18ad3f2a..e7a537716e3709b62c7c4eacb8d693a70b350510 100644 (file)
@@ -76,12 +76,6 @@ Keyboard::Keyboard ()
        }
        Meta = possible_meta[i];
 
-       if (Meta) {
-               cerr << "Using " << possible_meta[i] << " for Meta\n";
-       } else {
-               cerr << "NO Meta\n";
-       }
-
        snooper_id = gtk_key_snooper_install (_snooper, (gpointer) this);
 
        XMLNode* node = ARDOUR_UI::instance()->keyboard_settings();
index 13acfbf5ab1284b3c6539ea85c13f82184a7cf98..79fe5dd2e34c6620fe8d336904e88c8a94a0d187 100644 (file)
@@ -75,6 +75,9 @@ OptionEditor::OptionEditor (ARDOUR_UI& uip, PublicEditor& ed, Mixer_UI& mixui)
 
          /* MIDI */
 
+         mmc_device_id_adjustment (0.0, 0.0, (double) 0x7f, 1.0, 16.0),
+         mmc_device_id_spinner (mmc_device_id_adjustment),
+
          /* Click */
 
          click_table (2, 3),
@@ -368,23 +371,28 @@ OptionEditor::setup_midi_options ()
        ToggleButton* tb;
        RadioButton* rb;
 
-       Gtk::Table* table = manage (new Table (ports.size() + 4, 9));
+       Gtk::Table* table = manage (new Table (ports.size() + 4, 10));
 
        table->set_row_spacings (6);
        table->set_col_spacings (10);
 
-       table->attach (*(manage (new Label (X_("Port")))), 0, 1, 0, 1);
-       table->attach (*(manage (new Label (X_("Offline")))), 1, 2, 0, 1);
-       table->attach (*(manage (new Label (X_("Trace\nInput")))), 2, 3, 0, 1);
-       table->attach (*(manage (new Label (X_("Trace\nOutput")))), 3, 4, 0, 1);
-       table->attach (*(manage (new Label (X_("MTC")))), 4, 5, 0, 1);
-       table->attach (*(manage (new Label (X_("MMC")))), 6, 7, 0, 1);
-       table->attach (*(manage (new Label (X_("MIDI Parameter\nControl")))), 8, 9, 0, 1);
+       table->attach (*(manage (new Label (_("Port")))), 0, 1, 0, 1);
+       table->attach (*(manage (new Label (_("Offline")))), 1, 2, 0, 1);
+       table->attach (*(manage (new Label (_("Trace\nInput")))), 2, 3, 0, 1);
+       table->attach (*(manage (new Label (_("Trace\nOutput")))), 3, 4, 0, 1);
+       table->attach (*(manage (new Label (_("MTC")))), 4, 5, 0, 1);
+       table->attach (*(manage (new Label (_("MMC")))), 6, 7, 0, 1);
+       table->attach (*(manage (new Label (_("MIDI Parameter\nControl")))), 8, 9, 0, 1);
 
        table->attach (*(manage (new HSeparator())), 0, 9, 1, 2);
        table->attach (*(manage (new VSeparator())), 5, 6, 0, 8);
        table->attach (*(manage (new VSeparator())), 7, 8, 0, 8);
        
+       table->attach (*(manage (new Label (_("MMC Device ID")))), 9, 10, 0, 1);
+       table->attach (mmc_device_id_spinner, 9, 10, 1, 2);
+       
+       mmc_device_id_adjustment.signal_value_changed().connect (mem_fun (*this, &OptionEditor::mmc_device_id_adjusted));
+
        for (n = 0, i = ports.begin(); i != ports.end(); ++n, ++i) {
 
                pair<MIDI::Port*,vector<RadioButton*> > newpair;
@@ -553,13 +561,23 @@ OptionEditor::map_port_online (MIDI::Port* port, ToggleButton* tb)
        }
 }
 
+void
+OptionEditor::mmc_device_id_adjusted ()
+{
+       uint8_t id = (uint8_t) mmc_device_id_spinner.get_value();
+
+       if (id != Config->get_mmc_device_id()) {
+               Config->set_mmc_device_id (id);
+       }
+}
+
 void
 OptionEditor::port_trace_in_toggled (MIDI::Port* port, ToggleButton* tb)
 {
        bool trace = tb->get_active();
 
        if (port->input()->tracing() != trace) {
-               port->output()->trace (trace, &cerr, string (port->name()) + string (" input: "));
+               port->input()->trace (trace, &cerr, string (port->name()) + string (" input: "));
        }
 }
 
index cc28a74e603620e5e0b292b2e91338ab8a8726f7..009ac90de4cfc49a492443ac41b5856c2efe25a8 100644 (file)
@@ -111,6 +111,9 @@ class OptionEditor : public Gtk::Dialog
        Gtk::RadioButton::Group mmc_button_group;
        Gtk::RadioButton::Group midi_button_group;
 
+       Gtk::Adjustment mmc_device_id_adjustment;
+       Gtk::SpinButton mmc_device_id_spinner;
+
        void port_online_toggled (MIDI::Port*,Gtk::ToggleButton*);
        void port_trace_in_toggled (MIDI::Port*,Gtk::ToggleButton*);
        void port_trace_out_toggled (MIDI::Port*,Gtk::ToggleButton*);
@@ -119,6 +122,8 @@ class OptionEditor : public Gtk::Dialog
        void mtc_port_chosen (MIDI::Port*,Gtk::RadioButton*);
        void midi_port_chosen (MIDI::Port*,Gtk::RadioButton*);
 
+       void mmc_device_id_adjusted ();
+
        void map_port_online (MIDI::Port*, Gtk::ToggleButton*);
 
        void setup_midi_options();
index c1e59baf35f8faadf642ae8ead06a2e8561f639a..1296ab0dad2906aa5290d22075ab9b1519fd6d7c 100644 (file)
@@ -18,6 +18,7 @@ CONFIG_VARIABLE (bool, send_mmc, "send-mmc", false)
 CONFIG_VARIABLE (bool, mmc_control, "mmc-control", false)
 CONFIG_VARIABLE (bool, midi_feedback, "midi-feedback", false)
 CONFIG_VARIABLE (bool, midi_control, "midi-control", false)
+CONFIG_VARIABLE (uint8_t, mmc_device_id, "mmc-device-id", 0)
 
 /* control surfaces */
 
index f03a067edf0407addfdbec75fefb0e50ca161a48..39bb9c3e6848cd98343c9b7c2396bf3dd6946375 100644 (file)
@@ -724,6 +724,8 @@ class Session : public PBD::StatefulDestructible
 
        void deliver_midi (MIDI::Port*, MIDI::byte*, int32_t size);
 
+       void set_mmc_device_id (uint32_t id);
+       
        /* Scrubbing */
 
        void start_scrub (nframes_t where);
@@ -1267,8 +1269,7 @@ class Session : public PBD::StatefulDestructible
        void mmc_record_pause (MIDI::MachineControl &);
        void mmc_record_strobe (MIDI::MachineControl &);
        void mmc_record_exit (MIDI::MachineControl &);
-       void mmc_track_record_status (MIDI::MachineControl &, 
-                                     uint32_t track, bool enabled);
+       void mmc_track_record_status (MIDI::MachineControl &, uint32_t track, bool enabled);
        void mmc_fast_forward (MIDI::MachineControl &);
        void mmc_rewind (MIDI::MachineControl &);
        void mmc_locate (MIDI::MachineControl &, const MIDI::byte *);
index 8a553fb12dfe689fa43701fc205c1c97677ad6ac..24ba406087796366cb9350ab393e91e29e4d0487 100644 (file)
@@ -126,9 +126,20 @@ Session::set_mtc_port (string port_tag)
        return 0;
 }
 
+void
+Session::set_mmc_device_id (uint32_t device_id)
+{
+       if (mmc) {
+               mmc->set_device_id (device_id);
+       }
+}
+
 int
 Session::set_mmc_port (string port_tag)
 {
+       MIDI::byte old_device_id;
+       bool reset_id = false;
+
        if (port_tag.length() == 0) {
                if (_mmc_port == 0) {
                        return 0;
@@ -146,6 +157,8 @@ Session::set_mmc_port (string port_tag)
        _mmc_port = port;
 
        if (mmc) {
+               old_device_id = mmc->device_id();
+               reset_id = true;
                delete mmc;
        }
 
@@ -153,6 +166,9 @@ Session::set_mmc_port (string port_tag)
                                        MMC_CommandSignature,
                                        MMC_ResponseSignature);
 
+       if (reset_id) {
+               mmc->set_device_id (old_device_id);
+       }
 
        mmc->Play.connect 
                (mem_fun (*this, &Session::mmc_deferred_play));
@@ -181,6 +197,7 @@ Session::set_mmc_port (string port_tag)
        mmc->TrackRecordStatusChange.connect
                (mem_fun (*this, &Session::mmc_record_enable));
 
+
        /* also handle MIDI SPP because its so common */
 
        _mmc_port->input()->start.connect (mem_fun (*this, &Session::spp_start));
@@ -543,7 +560,6 @@ Session::mmc_pause (MIDI::MachineControl &mmc)
 static bool step_queued = false;
 
 void
-
 Session::mmc_step (MIDI::MachineControl &mmc, int steps)
 {
        if (!Config->get_mmc_control()) {
index 861e03302ff65414a33f6932c13d36a39a4d856a..3c58a448c204417287b2fe73e18e8da34180b47f 100644 (file)
@@ -2832,6 +2832,12 @@ Session::set_deletion_in_progress ()
 void
 Session::add_controllable (Controllable* c)
 {
+       /* this adds a controllable to the list managed by the Session.
+          this is a subset of those managed by the Controllable class
+          itself, and represents the only ones whose state will be saved
+          as part of the session.
+       */
+
        Glib::Mutex::Lock lm (controllables_lock);
        controllables.insert (c);
 }
@@ -3065,6 +3071,12 @@ Session::config_changed (const char* parameter_name)
 
                poke_midi_thread ();
 
+       } else if (PARAM_IS ("mmc-device-id")) {
+
+               if (mmc) {
+                       mmc->set_device_id (Config->get_mmc_device_id());
+               }
+
        } else if (PARAM_IS ("midi-control")) {
                
                poke_midi_thread ();
index 2d569f122c1bc141b80ce96fb2d27c75d9f7de2e..23e07f51511d10ccce99834914aaa3339ff2df1a 100644 (file)
@@ -93,6 +93,8 @@ class MachineControl : public sigc::trackable
        Port &port() { return _port; }
        
        void set_device_id (byte id);
+       byte device_id () const { return _device_id; }
+
        static bool is_mmc (byte *sysex_buf, size_t len);
 
        /* Signals to connect to if you want to run "callbacks"
index 424bfa04f8581b6bc9eeda0fd19b2ea01f5178d5..782c3a82395595f60d88a517a181632eb6ee6ca4 100644 (file)
@@ -25,6 +25,7 @@
 #include <unistd.h>
 #include <string>
 #include <iostream>
+#include <iterator>
 
 #include <midi++/types.h>
 #include <midi++/parser.h>
@@ -138,7 +139,6 @@ Parser::~Parser ()
 
 void
 Parser::trace_event (Parser &p, byte *msg, size_t len)
-
 {
        eventType type;
        ostream *o;
@@ -309,15 +309,13 @@ Parser::trace_event (Parser &p, byte *msg, size_t len)
 
 void
 Parser::trace (bool onoff, ostream *o, const string &prefix)
-
 {
        trace_connection.disconnect ();
 
        if (onoff) {
                trace_stream = o;
                trace_prefix = prefix;
-               trace_connection = any.connect 
-                       (mem_fun (*this, &Parser::trace_event));
+               trace_connection = any.connect (mem_fun (*this, &Parser::trace_event));
        } else {
                trace_prefix = "";
                trace_stream = 0;
index 61c47e856f96d82edd7e21ab74b6d17ccc40c116..28d6393fb453c154c0bc5707a3a3a9af24c19479 100644 (file)
@@ -202,7 +202,7 @@ MachineControl::MachineControl (Port &p, float version,
        
        build_mmc_cmd_map ();
 
-       _device_id = 1;
+       _device_id = 0;
        
        if ((parser = _port.input()) != 0) {
                parser->mmc.connect 
@@ -258,7 +258,7 @@ MachineControl::process_mmc_message (Parser &p, byte *msg, size_t len)
        */
 
 #if 0
-       cerr << "*** MMC message: len = " << len << "\n\t";
+       cerr << "*** me = " << (int) _device_id << " MMC message: len = " << len << "\n\t";
        for (size_t i = 0; i < len; i++) {
                cerr << hex << (int) msg[i] << dec << ' ';
        }
index 049ad0aa213543677b907de12146e34e8bd509c8..00638e6c06cc3312b159723913b3671523ef49aa 100644 (file)
@@ -10,9 +10,64 @@ sigc::signal<void,Controllable*> Controllable::Destroyed;
 sigc::signal<bool,Controllable*> Controllable::StartLearning;
 sigc::signal<void,Controllable*> Controllable::StopLearning;
 
+Glib::Mutex* Controllable::registry_lock = 0;
+Controllable::Controllables Controllable::registry;
+
 Controllable::Controllable (std::string name)
        : _name (name)
 {
+       if (registry_lock == 0) {
+               registry_lock = new Glib::Mutex;
+       }
+
+       add ();
+}
+
+void
+Controllable::add ()
+{
+       Glib::Mutex::Lock lm (*registry_lock);
+       registry.insert (this);
+       this->GoingAway.connect (mem_fun (this, &Controllable::remove));
+}
+
+void
+Controllable::remove ()
+{
+       Glib::Mutex::Lock lm (*registry_lock);
+       for (Controllables::iterator i = registry.begin(); i != registry.end(); ++i) {
+               if ((*i) == this) {
+                       registry.erase (i);
+                       break;
+               }
+       }
+}
+
+Controllable*
+Controllable::by_id (const ID& id)
+{
+       Glib::Mutex::Lock lm (*registry_lock);
+
+       for (Controllables::iterator i = registry.begin(); i != registry.end(); ++i) {
+               if ((*i)->id() == id) {
+                       return (*i);
+               }
+       }
+       return 0;
+}
+
+
+Controllable*
+Controllable::by_name (const std::string& str)
+{
+       Glib::Mutex::Lock lm (*registry_lock);
+
+       for (Controllables::iterator i = registry.begin(); i != registry.end(); ++i) {
+               if ((*i)->_name == str) {
+                       return (*i);
+               }
+       }
+       return 0;
 }
 
 XMLNode&
index c88eb298bcca4193dc57a5408d3a35d3fc2dcd31..c152013c663f896c5d43b4ce6fbb4a23c5cd165d 100644 (file)
@@ -2,6 +2,7 @@
 #define __pbd_controllable_h__
 
 #include <string>
+#include <set>
 
 #include <sigc++/trackable.h>
 #include <sigc++/signal.h>
@@ -36,8 +37,18 @@ class Controllable : public PBD::StatefulDestructible {
 
        std::string name() const { return _name; }
 
+       static Controllable* by_id (const PBD::ID&);
+       static Controllable* by_name (const std::string&);
+
   private:
        std::string _name;
+
+       void add ();
+       void remove ();
+
+       typedef std::set<PBD::Controllable*> Controllables;
+       static Glib::Mutex* registry_lock;
+       static Controllables registry;
 };
 
 }
index e81a45b47ab64b3ea93f50f0da215468e77c7e1a..2289bc0726a4bce894450285aac6cf39635a49a4 100644 (file)
@@ -171,6 +171,8 @@ void
 GenericMidiControlProtocol::stop_learning (Controllable* c)
 {
        Glib::Mutex::Lock lm (pending_lock);
+       Glib::Mutex::Lock lm2 (controllables_lock);
+       MIDIControllable* dptr = 0;
 
        /* learning timed out, and we've been told to consider this attempt to learn to be cancelled. find the
           relevant MIDIControllable and remove it from the pending list.
@@ -179,11 +181,22 @@ GenericMidiControlProtocol::stop_learning (Controllable* c)
        for (MIDIControllables::iterator i = pending_controllables.begin(); i != pending_controllables.end(); ++i) {
                if (&(*i)->get_controllable() == c) {
                        (*i)->stop_learning ();
-                       delete (*i);
+                       dptr = *i;
                        pending_controllables.erase (i);
                        break;
                }
        }
+
+       for (MIDIControllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
+               if (&(*i)->get_controllable() == c) {
+                       controllables.erase (i);
+                       break;
+               }
+       }
+       
+       if (dptr) {
+               delete dptr;
+       }
 }
 
 XMLNode&
@@ -255,7 +268,7 @@ GenericMidiControlProtocol::set_state (const XMLNode& node)
                        
                        ID id = prop->value ();
                        
-                       c = session->controllable_by_id (id);
+                       c = Controllable::by_id (id);
                        
                        if (c) {
                                MIDIControllable* mc = new MIDIControllable (*_port, *c);
@@ -264,8 +277,7 @@ GenericMidiControlProtocol::set_state (const XMLNode& node)
                                }
                                
                        } else {
-                               warning << string_compose (_("Generic MIDI control: controllable %1 not found in session (ignored)"),
-                                                          id)
+                               warning << string_compose (_("Generic MIDI control: controllable %1 not found (ignored)"), id)
                                        << endmsg;
                        }
                }
index 476391585417e70e5e70e006ca981cc1611fcaaa..2535c190441f5a14998cd1e1a5c158926ae23f4a 100644 (file)
@@ -1160,7 +1160,7 @@ void MackieControlProtocol::notify_remote_id_changed()
        if ( sorted.size() - _current_initial_bank < route_signals.size() )
        {
                // but don't shift backwards past the zeroth channel
-               switch_banks( max( (unsigned int)0, sorted.size() - route_signals.size() ) );
+               switch_banks( max(0UL, sorted.size() - route_signals.size() ) );
        }
        // Otherwise just refresh the current bank
        else