FP8: handle backend changes + reconnect
authorRobin Gareus <robin@gareus.org>
Tue, 18 Apr 2017 13:14:00 +0000 (15:14 +0200)
committerRobin Gareus <robin@gareus.org>
Tue, 18 Apr 2017 13:14:00 +0000 (15:14 +0200)
When the backend is dropped or changed, on engine-restart
the connection_handler() re-establishes already connected ports.
There's no disconnect when the backend dies or is hard-stopped.

libs/surfaces/faderport8/faderport8.cc
libs/surfaces/faderport8/faderport8.h

index 802942cbe780b0c41e67b38e6066c6ea2ab2d217..be5f60a824f2c96786915f7d68319999137ef9c2 100644 (file)
@@ -124,7 +124,9 @@ FaderPort8::FaderPort8 (Session& s)
                session->engine().make_port_name_non_relative (outp->name())
                );
 
-       ARDOUR::AudioEngine::instance()->PortConnectedOrDisconnected.connect (port_connection, MISSING_INVALIDATOR, boost::bind (&FaderPort8::connection_handler, this, _1, _2, _3, _4, _5), this);
+       ARDOUR::AudioEngine::instance()->PortConnectedOrDisconnected.connect (port_connections, MISSING_INVALIDATOR, boost::bind (&FaderPort8::connection_handler, this, _2, _4), this);
+       ARDOUR::AudioEngine::instance()->Stopped.connect (port_connections, MISSING_INVALIDATOR, boost::bind (&FaderPort8::engine_reset, this), this);
+       ARDOUR::Port::PortDrop.connect (port_connections, MISSING_INVALIDATOR, boost::bind (&FaderPort8::engine_reset, this), this);
 
        StripableSelectionChanged.connect (selection_connection, MISSING_INVALIDATOR, boost::bind (&FaderPort8::gui_track_selection_changed, this), this);
 
@@ -265,13 +267,14 @@ FaderPort8::set_active (bool yn)
 void
 FaderPort8::close ()
 {
+       DEBUG_TRACE (DEBUG::FaderPort8, "FaderPort8::close\n");
        stop_midi_handling ();
        session_connections.drop_connections ();
        automation_state_connections.drop_connections ();
        assigned_stripable_connections.drop_connections ();
        _assigned_strips.clear ();
        drop_ctrl_connections ();
-       port_connection.disconnect ();
+       port_connections.drop_connections ();
        selection_connection.disconnect ();
 }
 
@@ -290,6 +293,12 @@ void
 FaderPort8::connected ()
 {
        DEBUG_TRACE (DEBUG::FaderPort8, "initializing\n");
+       assert (!_device_active);
+
+       if (_device_active) {
+               stop_midi_handling (); // re-init
+       }
+
        // ideally check firmware version >= 1.01 (USB bcdDevice 0x0101) (vendor 0x194f prod 0x0202)
        // but we don't have a handle to the underlying USB device here.
 
@@ -336,8 +345,18 @@ FaderPort8::disconnected ()
        }
 }
 
+void
+FaderPort8::engine_reset ()
+{
+       /* Port::PortDrop is called when the engine is halted or stopped */
+       DEBUG_TRACE (DEBUG::FaderPort8, "FaderPort8::engine_reset\n");
+       _connection_state = 0;
+       _device_active = false;
+       disconnected ();
+}
+
 bool
-FaderPort8::connection_handler (boost::weak_ptr<ARDOUR::Port>, std::string name1, boost::weak_ptr<ARDOUR::Port>, std::string name2, bool yn)
+FaderPort8::connection_handler (std::string name1, std::string name2)
 {
 #ifdef VERBOSE_DEBUG
        DEBUG_TRACE (DEBUG::FaderPort8, "FaderPort8::connection_handler: start\n");
@@ -350,13 +369,21 @@ FaderPort8::connection_handler (boost::weak_ptr<ARDOUR::Port>, std::string name1
        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) {
+               DEBUG_TRACE (DEBUG::FaderPort8, string_compose ("Connection notify %1 and %2\n", name1, name2));
+               if (_input_port->connected ()) {
+                       if (_connection_state & InputConnected) {
+                               return false;
+                       }
                        _connection_state |= InputConnected;
                } else {
                        _connection_state &= ~InputConnected;
                }
        } else if (no == name1 || no == name2) {
-               if (yn) {
+               DEBUG_TRACE (DEBUG::FaderPort8, string_compose ("Connection notify %1 and %2\n", name1, name2));
+               if (_output_port->connected ()) {
+                       if (_connection_state & OutputConnected) {
+                               return false;
+                       }
                        _connection_state |= OutputConnected;
                } else {
                        _connection_state &= ~OutputConnected;
@@ -382,7 +409,9 @@ FaderPort8::connection_handler (boost::weak_ptr<ARDOUR::Port>, std::string name1
 
        } else {
                DEBUG_TRACE (DEBUG::FaderPort8, "Device disconnected (input or output or both) or not yet fully connected\n");
-               disconnected ();
+               if (_device_active) {
+                       disconnected ();
+               }
                _device_active = false;
        }
 
index e258612bcc51bcea224b5593aca5eba7aa2f1c1a..00ffe827dfe7158fa70b8ad8f56fc0bf753b72d2 100644 (file)
@@ -100,7 +100,7 @@ private:
        void stop_midi_handling ();
 
        /* I/O Ports */
-       PBD::ScopedConnection port_connection;
+       PBD::ScopedConnectionList port_connections;
        boost::shared_ptr<ARDOUR::AsyncMIDIPort> _input_port;
        boost::shared_ptr<ARDOUR::AsyncMIDIPort> _output_port;
        boost::shared_ptr<ARDOUR::Bundle>        _input_bundle;
@@ -108,7 +108,8 @@ private:
 
        bool midi_input_handler (Glib::IOCondition ioc, boost::weak_ptr<ARDOUR::AsyncMIDIPort> port);
 
-       bool connection_handler (boost::weak_ptr<ARDOUR::Port>, std::string name1, boost::weak_ptr<ARDOUR::Port>, std::string name2, bool yn);
+       bool connection_handler (std::string name1, std::string name2);
+       void engine_reset ();
 
        enum ConnectionState {
                InputConnected = 0x1,