adjust generic MIDI surface support to (1) properly use boost::shared_ptr<Port> ...
authorPaul Davis <paul@linuxaudiosystems.com>
Mon, 7 Dec 2015 17:04:23 +0000 (12:04 -0500)
committerPaul Davis <paul@linuxaudiosystems.com>
Mon, 7 Dec 2015 17:38:17 +0000 (12:38 -0500)
libs/surfaces/generic_midi/generic_midi_control_protocol.cc
libs/surfaces/generic_midi/generic_midi_control_protocol.h
libs/surfaces/generic_midi/gmcp_gui.cc

index 54bb65cb906703511bd5d5eaae99a807423518f3..e319f65e1f8e0d1d6fc1488b9cc270dfb34b0b3d 100644 (file)
@@ -34,6 +34,8 @@
 
 #include "midi++/port.h"
 
+#include "ardour/async_midi_port.h"
+#include "ardour/audioengine.h"
 #include "ardour/audioengine.h"
 #include "ardour/filesystem_paths.h"
 #include "ardour/session.h"
@@ -58,12 +60,13 @@ using namespace std;
 
 GenericMidiControlProtocol::GenericMidiControlProtocol (Session& s)
        : ControlProtocol (s, _("Generic MIDI"))
+       , connection_state (ConnectionState (0))
        , _motorised (false)
        , _threshold (10)
        , gui (0)
 {
-       _input_port = s.midi_input_port ();
-       _output_port = s.midi_output_port ();
+       _input_port = boost::dynamic_pointer_cast<AsyncMIDIPort> (s.midi_input_port ());
+       _output_port = boost::dynamic_pointer_cast<AsyncMIDIPort> (s.midi_output_port ());
 
        do_feedback = false;
        _feedback_interval = 10000; // microseconds
@@ -94,6 +97,11 @@ GenericMidiControlProtocol::GenericMidiControlProtocol (Session& s)
 
        Route::RemoteControlIDChange.connect (*this, MISSING_INVALIDATOR, boost::bind (&GenericMidiControlProtocol::reset_controllables, this), midi_ui_context());
 
+       /* Catch port connections and disconnections (cross-thread) */
+       ARDOUR::AudioEngine::instance()->PortConnectedOrDisconnected.connect (port_connection, MISSING_INVALIDATOR,
+                                                                             boost::bind (&GenericMidiControlProtocol::connection_handler, this, _1, _2, _3, _4, _5),
+                                                                             midi_ui_context());
+
        reload_maps ();
 }
 
@@ -229,7 +237,9 @@ GenericMidiControlProtocol::drop_bindings ()
 int
 GenericMidiControlProtocol::set_active (bool /*yn*/)
 {
-       /* start/stop delivery/outbound thread */
+       /* nothing to do here: the MIDI UI thread in libardour handles all our
+          I/O needs.
+       */
        return 0;
 }
 
@@ -1137,3 +1147,67 @@ GenericMidiControlProtocol::set_threshold (int t)
 {
        _threshold = t;
 }
+
+bool
+GenericMidiControlProtocol::connection_handler (boost::weak_ptr<ARDOUR::Port>, std::string name1, boost::weak_ptr<ARDOUR::Port>, std::string name2, bool yn)
+{
+       if (!_input_port || !_output_port) {
+               return false;
+       }
+
+       string ni = ARDOUR::AudioEngine::instance()->make_port_name_non_relative (boost::shared_ptr<ARDOUR::Port>(_input_port)->name());
+       string no = ARDOUR::AudioEngine::instance()->make_port_name_non_relative (boost::shared_ptr<ARDOUR::Port>(_output_port)->name());
+
+       if (ni == name1 || ni == name2) {
+               if (yn) {
+                       connection_state |= InputConnected;
+               } else {
+                       connection_state &= ~InputConnected;
+               }
+       } else if (no == name1 || no == name2) {
+               if (yn) {
+                       connection_state |= OutputConnected;
+               } else {
+                       connection_state &= ~OutputConnected;
+               }
+       } else {
+               /* not our ports */
+               return false;
+       }
+
+       if ((connection_state & (InputConnected|OutputConnected)) == (InputConnected|OutputConnected)) {
+
+               /* XXX this is a horrible hack. Without a short sleep here,
+                  something prevents the device wakeup messages from being
+                  sent and/or the responses from being received.
+               */
+
+               g_usleep (100000);
+               connected ();
+
+       } else {
+
+       }
+
+       ConnectionChange (); /* emit signal for our GUI */
+
+       return true; /* connection status changed */
+}
+
+void
+GenericMidiControlProtocol::connected ()
+{
+       cerr << "Now connected\n";
+}
+
+boost::shared_ptr<Port>
+GenericMidiControlProtocol::output_port() const
+{
+       return _output_port;
+}
+
+boost::shared_ptr<Port>
+GenericMidiControlProtocol::input_port() const
+{
+       return _input_port;
+}
index 9d51efc97d32afeed451fdccf08181b6009e8df2..a453716e9523c3986e61bd08c3806ea22ee078a9 100644 (file)
@@ -34,8 +34,9 @@ namespace PBD {
 }
 
 namespace ARDOUR {
-       class Session;
+       class AsyncMIDIPort;
        class MidiPort;
+       class Session;
 }
 
 namespace MIDI {
@@ -54,9 +55,9 @@ class GenericMidiControlProtocol : public ARDOUR::ControlProtocol {
        int set_active (bool yn);
        static bool probe() { return true; }
 
-        ARDOUR::Port* input_port () const { return ((ARDOUR::Port*) _input_port); }
-        ARDOUR::Port* output_port () const { return ((ARDOUR::Port*) _output_port); }
-       
+       boost::shared_ptr<ARDOUR::Port> input_port () const;
+       boost::shared_ptr<ARDOUR::Port> output_port () const;
+
        void set_feedback_interval (ARDOUR::microseconds_t);
 
        int set_feedback (bool yn);
@@ -103,9 +104,11 @@ class GenericMidiControlProtocol : public ARDOUR::ControlProtocol {
        }
 
        PBD::Signal0<void> ConnectionChange;
+
   private:
-        MIDI::Port* _input_port;
-        MIDI::Port* _output_port;
+       boost::shared_ptr<ARDOUR::AsyncMIDIPort> _input_port;
+       boost::shared_ptr<ARDOUR::AsyncMIDIPort> _output_port;
+
        ARDOUR::microseconds_t _feedback_interval;
        ARDOUR::microseconds_t last_feedback_time;
 
@@ -143,6 +146,16 @@ class GenericMidiControlProtocol : public ARDOUR::ControlProtocol {
        void reset_controllables ();
        void drop_all ();
 
+       enum ConnectionState {
+               InputConnected = 0x1,
+               OutputConnected = 0x2
+       };
+
+       int connection_state;
+       bool connection_handler (boost::weak_ptr<ARDOUR::Port>, std::string name1, boost::weak_ptr<ARDOUR::Port>, std::string name2, bool yn);
+       PBD::ScopedConnection port_connection;
+       void connected();
+
        std::string _current_binding;
        uint32_t _bank_size;
        uint32_t _current_bank;
@@ -156,6 +169,8 @@ class GenericMidiControlProtocol : public ARDOUR::ControlProtocol {
 
        mutable void *gui;
        void build_gui ();
+
+
 };
 
 #endif /* ardour_generic_midi_control_protocol_h */
index 427ed1d32778711fde96ebec482180d6a4aa69b5..8e861b370d92fdce645bfd5b52ad85482ccf5559 100644 (file)
@@ -65,7 +65,7 @@ private:
        void bank_changed ();
        void motorised_changed ();
        void threshold_changed ();
-       
+
        void update_port_combos ();
        PBD::ScopedConnection connection_change_connection;
        void connection_handler ();
@@ -131,6 +131,7 @@ GMCPGUI::GMCPGUI (GenericMidiControlProtocol& p)
        , motorised_button ("Motorised")
        , threshold_adjustment (p.threshold(), 1, 127, 1, 10)
        , threshold_spinner (threshold_adjustment)
+       , ignore_active_change (false)
 {
        vector<string> popdowns;
        popdowns.push_back (_("Reset All"));
@@ -179,7 +180,7 @@ GMCPGUI::GMCPGUI (GenericMidiControlProtocol& p)
        table->attach (*label, 0, 1, n, n+1, AttachOptions(FILL|EXPAND), AttachOptions(0));
        table->attach (output_combo, 1, 2, n, n+1, AttachOptions(FILL|EXPAND), AttachOptions(0), 0, 0);
        n++;
-       
+
        //MIDI binding file selector...
        label = manage (new Label (_("MIDI Bindings:")));
        label->set_alignment (0, 0.5);