Fix crash on MIDI region split.
[ardour.git] / libs / ardour / port.cc
index 9e77128e4ca8f57aecb0c22ba854b897c79a78a3..1c79e0c4388cada25e5a51698ac685c588044469 100644 (file)
@@ -15,7 +15,6 @@
     along with this program; if not, write to the Free Software
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
-    $Id$
 */
 
 #include <ardour/port.h>
 using namespace ARDOUR;
 using namespace std;
 
-Port::Port (jack_port_t *p) 
-       : _port (p)
-       , _metering(0)
-       , _last_monitor(false)
+AudioEngine* Port::engine = 0;
+
+Port::Port (const std::string& name, Flags flgs)
+       : _flags (flgs)
+       , _name (name)
+       , _metering (0)
+       , _last_monitor (false)
 {
-       if (_port == 0) {
-               throw failed_constructor();
-       }
-       
-       _flags = JackPortFlags (jack_port_flags (_port));
-       _type  = jack_port_type (_port); 
-       _name = jack_port_name (_port);
+}
 
-       reset ();
+Port::~Port ()
+{
+       disconnect_all ();
 }
 
 void
@@ -45,16 +43,337 @@ Port::reset ()
        _last_monitor = false;
 }
 
-int 
-Port::set_name (string str)
+void
+Port::set_engine (AudioEngine* e) 
+{
+       engine = e;
+}
+
+int
+Port::connect (Port& other)
+{
+       /* caller must hold process lock */
+
+       pair<set<Port*>::iterator,bool> result;
+
+       result = _connections.insert (&other);
+
+       if (result.second) {
+               return 0;
+       } else {
+               return 1;
+       }
+}
+
+int
+Port::disconnect (Port& other)
+{
+       /* caller must hold process lock */
+       
+       for (set<Port*>::iterator i = _connections.begin(); i != _connections.end(); ++i) {
+               if ((*i) == &other) {
+                       _connections.erase (i);
+                       return 0;
+               }
+       }
+
+       return -1;
+}
+
+
+int
+Port::disconnect_all ()
+{
+       /* caller must hold process lock */
+
+       _connections.clear ();
+       return 0;
+}
+
+void
+Port::set_latency (nframes_t val)
+{
+       _latency = val;
+}
+
+bool
+Port::connected() const
+{
+       /* caller must hold process lock */
+       return !_connections.empty();
+}
+
+bool
+Port::connected_to (const string& portname) const
+{
+       /* caller must hold process lock */
+
+       for (set<Port*>::const_iterator p = _connections.begin(); p != _connections.end(); ++p) {
+               if ((*p)->name() == portname) {
+                       return true;
+               }
+       }
+
+       return false;
+}
+
+int
+Port::get_connections (vector<string>& names) const
+{
+       /* caller must hold process lock */
+       int i = 0;
+       set<Port*>::const_iterator p;
+
+       for (i = 0, p = _connections.begin(); p != _connections.end(); ++p, ++i) {
+               names.push_back ((*p)->name());
+       }
+
+       return i;
+}
+
+
+//-------------------------------------
+
+int
+PortFacade::set_name (const std::string& str)
 {
        int ret;
 
-       if ((ret = jack_port_set_name (_port, str.c_str())) == 0) {
+       if (_ext_port) {
+               if ((ret = _ext_port->set_name (str)) == 0) {
+                       _name = _ext_port->name();
+               }
+       } else {
                _name = str;
+               ret = 0;
+       }
+
+       return ret;
+}
+
+string
+PortFacade::short_name ()  const
+{
+       if (_ext_port) {
+               return _ext_port->short_name(); 
+       } else {
+               return _name;
+       }
+}
+
+
+int
+PortFacade::reestablish ()
+{
+       if (_ext_port) {
+               return _ext_port->reestablish ();
+       } else {
+               return 0;
+       }
+}
+
+
+int
+PortFacade::reconnect()
+{
+       if (_ext_port) {
+               return _ext_port->reconnect ();
+       } else {
+               return 0;
+       }
+}
+
+void
+PortFacade::set_latency (nframes_t val)
+{
+       if (_ext_port) {
+               _ext_port->set_latency (val);
+       } else {
+               _latency = val;
+       }
+}
+
+nframes_t
+PortFacade::latency() const
+{
+       if (_ext_port) {
+               return _ext_port->latency();
+       } else {
+               return _latency;
+       }
+}
+
+nframes_t
+PortFacade::total_latency() const
+{
+       if (_ext_port) {
+               return _ext_port->total_latency();
+       } else {
+               return _latency;
+       }
+}
+
+bool
+PortFacade::monitoring_input() const
+{
+       if (_ext_port) {
+               return _ext_port->monitoring_input ();
+       } else {
+               return false;
        }
+}
+
+void
+PortFacade::ensure_monitor_input (bool yn)
+{
+       if (_ext_port) {
+               _ext_port->ensure_monitor_input (yn);
+       }
+}
+
+void
+PortFacade::request_monitor_input (bool yn)
+{
+       if (_ext_port) {
+               _ext_port->request_monitor_input (yn);
+       } 
+}
+
+int
+PortFacade::connect (Port& other)
+{
+       int ret;
        
+       if (_ext_port) {
+               ret = _ext_port->connect (other);
+       } else {
+               ret = 0;
+       }
+
+       if (ret == 0) {
+               ret = Port::connect (other);
+       }
+
        return ret;
 }
 
+int
+PortFacade::connect (const std::string& other)
+{
+       PortConnectableByName* pcn;
+
+       if (!_ext_port) {
+               return -1;
+       }
+               
+       pcn = dynamic_cast<PortConnectableByName*>(_ext_port);
+
+       if (pcn) {
+               return pcn->connect (other);
+       } else {
+               return -1;
+       }
+}
+
+
+int
+PortFacade::disconnect (Port& other)
+{
+       int reta;
+       int retb;
        
+       if (_ext_port) {
+               reta = _ext_port->disconnect (other);
+       } else {
+               reta = 0;
+       }
+
+       retb = Port::disconnect (other);
+
+       return reta || retb;
+}
+
+int 
+PortFacade::disconnect_all ()
+{
+       int reta;
+       int retb;
+
+       if (_ext_port) {
+               reta = _ext_port->disconnect_all ();
+       } 
+
+       retb = Port::disconnect_all ();
+
+       return reta || retb;
+}
+               
+int
+PortFacade::disconnect (const std::string& other)
+{
+       PortConnectableByName* pcn;
+
+       if (!_ext_port) {
+               return -1;
+       }
+               
+       pcn = dynamic_cast<PortConnectableByName*>(_ext_port);
+
+       if (pcn) {
+               return pcn->disconnect (other);
+       } else {
+               return -1;
+       }
+}
+
+bool
+PortFacade::connected () const 
+{
+       if (Port::connected()) {
+               return true;
+       }
+
+       if (_ext_port) {
+               return _ext_port->connected();
+       }
+
+       return false;
+}
+bool
+PortFacade::connected_to (const std::string& portname) const 
+{
+       if (Port::connected_to (portname)) {
+               return true;
+       }
+
+       if (_ext_port) {
+               return _ext_port->connected_to (portname);
+       }
+
+       return false;
+
+}
+
+int
+PortFacade::get_connections (vector<string>& names) const 
+{
+       int i = 0;
+
+       if (_ext_port) {
+               i = _ext_port->get_connections (names);
+       }
+
+       i += Port::get_connections (names);
+
+       return i;
+}
+
+void
+PortFacade::reset ()
+{
+       Port::reset ();
+
+       if (_ext_port) {
+               _ext_port->reset ();
+       }
+}