major fixes for MIDI patch change and note undo/redo. Patch change handling was compl...
[ardour.git] / libs / ardour / port.cc
index b418943bbab908512f44b422c832f2aaa4dab693..3473b73617a84226bb442a1bc421bc717fc1ce57 100644 (file)
 #include "libardour-config.h"
 #endif
 
-#include <stdexcept>
-
 #include <jack/weakjack.h> // so that we can test for new functions at runtime
 
-#include "pbd/error.h"
 #include "pbd/compose.h"
+#include "pbd/error.h"
+#include "pbd/failed_constructor.h"
 
+#include "ardour/audioengine.h"
 #include "ardour/debug.h"
 #include "ardour/port.h"
-#include "ardour/audioengine.h"
-#include "pbd/failed_constructor.h"
 
 #include "i18n.h"
 
@@ -39,6 +37,9 @@ using namespace std;
 using namespace ARDOUR;
 using namespace PBD;
 
+PBD::Signal2<void,boost::shared_ptr<Port>, boost::shared_ptr<Port> > Port::PostDisconnect;
+PBD::Signal0<void> Port::PortDrop;
+
 AudioEngine* Port::_engine = 0;
 bool         Port::_connecting_blocked = false;
 pframes_t    Port::_global_port_buffer_offset = 0;
@@ -68,16 +69,27 @@ Port::Port (std::string const & n, DataType t, Flags f)
        }
 
        if ((_jack_port = jack_port_register (_engine->jack (), _name.c_str (), t.to_jack_type (), _flags, 0)) == 0) {
-               cerr << "Failed to register JACK port, reason is unknown from here\n";
+               cerr << "Failed to register JACK port \"" << _name << "\", reason is unknown from here\n";
                throw failed_constructor ();
        }
+
+       PortDrop.connect_same_thread (drop_connection, boost::bind (&Port::drop, this));
 }
 
 /** Port destructor */
 Port::~Port ()
 {
-       if (_engine->jack ()) {
-               jack_port_unregister (_engine->jack (), _jack_port);
+       drop ();
+}
+
+void
+Port::drop ()
+{
+       if (_jack_port) {
+               if (_engine->jack ()) {
+                       jack_port_unregister (_engine->jack (), _jack_port);
+               }
+               _jack_port = 0;
        }
 }
 
@@ -94,6 +106,11 @@ Port::disconnect_all ()
        jack_port_disconnect (_engine->jack(), _jack_port);
        _connections.clear ();
 
+       /* a cheaper, less hacky way to do boost::shared_from_this() ... 
+        */
+       boost::shared_ptr<Port> pself = _engine->get_port_by_name (name());
+       PostDisconnect (pself, boost::shared_ptr<Port>()); // emit signal
+
        return 0;
 }
 
@@ -168,21 +185,34 @@ Port::connect (std::string const & other)
 int
 Port::disconnect (std::string const & other)
 {
-       std::string const other_shrt = _engine->make_port_name_non_relative (other);
-       std::string const this_shrt = _engine->make_port_name_non_relative (_name);
+       std::string const other_fullname = _engine->make_port_name_non_relative (other);
+       std::string const this_fullname = _engine->make_port_name_non_relative (_name);
 
        int r = 0;
 
        if (sends_output ()) {
-               r = jack_disconnect (_engine->jack (), this_shrt.c_str (), other_shrt.c_str ());
+               r = jack_disconnect (_engine->jack (), this_fullname.c_str (), other_fullname.c_str ());
        } else {
-               r = jack_disconnect (_engine->jack (), other_shrt.c_str (), this_shrt.c_str ());
+               r = jack_disconnect (_engine->jack (), other_fullname.c_str (), this_fullname.c_str ());
        }
 
        if (r == 0) {
                _connections.erase (other);
        }
 
+       /* a cheaper, less hacky way to do boost::shared_from_this() ... 
+        */
+       boost::shared_ptr<Port> pself = _engine->get_port_by_name (name());
+       boost::shared_ptr<Port> pother = _engine->get_port_by_name (other);
+
+       if (pself && pother) {
+               /* Disconnecting from another Ardour port: need to allow
+                  a check on whether this may affect anything that we
+                  need to know about.
+               */
+               PostDisconnect (pself, pother); // emit signal 
+       }
+
        return r;
 }
 
@@ -212,13 +242,13 @@ Port::set_engine (AudioEngine* e)
 }
 
 void
-Port::ensure_monitor_input (bool yn)
+Port::ensure_jack_monitors_input (bool yn)
 {
        jack_port_ensure_monitor (_jack_port, yn);
 }
 
 bool
-Port::monitoring_input () const
+Port::jack_monitoring_input () const
 {
        return jack_port_monitoring_input (_jack_port);
 }
@@ -383,7 +413,7 @@ Port::get_connected_latency_range (jack_latency_range_t& range, bool playback) c
                                    latency compensation.
                                 */
 
-                                Port* remote_port = AudioEngine::instance()->get_port_by_name (*c);
+                                boost::shared_ptr<Port> remote_port = AudioEngine::instance()->get_port_by_name (*c);
                                 if (remote_port) {
                                         lr = remote_port->private_latency_range ((playback ? JackPlaybackLatency : JackCaptureLatency));
                                         DEBUG_TRACE (DEBUG::Latency, string_compose (
@@ -452,14 +482,16 @@ Port::set_name (std::string const & n)
        int const r = jack_port_set_name (_jack_port, n.c_str());
 
        if (r == 0) {
+               _engine->port_renamed (_name, n);
                _name = n;
        }
 
+
        return r;
 }
 
 void
-Port::request_monitor_input (bool yn)
+Port::request_jack_monitors_input (bool yn)
 {
        jack_port_request_monitor (_jack_port, yn);
 }