full compilation and linking (coding not finished, will not run)
authorPaul Davis <paul@linuxaudiosystems.com>
Thu, 1 Aug 2013 18:43:12 +0000 (14:43 -0400)
committerPaul Davis <paul@linuxaudiosystems.com>
Thu, 1 Aug 2013 18:43:12 +0000 (14:43 -0400)
21 files changed:
libs/ardour/ardour/audio_backend.h
libs/ardour/ardour/audioengine.h
libs/ardour/ardour/jack_audiobackend.h
libs/ardour/ardour/jack_portengine.h
libs/ardour/ardour/port_engine.h
libs/ardour/ardour/port_manager.h
libs/ardour/ardour/slave.h
libs/ardour/audioengine.cc
libs/ardour/bundle.cc
libs/ardour/jack_audiobackend.cc
libs/ardour/jack_portengine.cc
libs/ardour/jack_slave.cc
libs/ardour/port.cc
libs/ardour/port_manager.cc
libs/ardour/route.cc
libs/ardour/session.cc
libs/ardour/session_export.cc
libs/ardour/session_state.cc
libs/ardour/session_transport.cc
libs/ardour/wscript
libs/midi++2/jack_midi_port.cc

index 44525c83537015dcac77bcc52961a2ea87a14f5f..3b68432b6ff6e2b1cc31db91ebd71380e7f80c1c 100644 (file)
@@ -296,18 +296,17 @@ class AudioBackend {
      * It is extremely likely that any implementation will use a DLL, since
      * this function can be called from any thread, at any time, and must be 
      * able to accurately determine the correct sample time.
+     *
+     * Can be called from any thread.
      */
     virtual pframes_t sample_time () = 0;
 
-    /** return the time according to the sample clock in use when the current 
-     * buffer process cycle began. 
-     * 
-     * Can ONLY be called from within a process() callback tree (which
-     * implies that it can only be called by a process thread)
+    /** Return the time according to the sample clock in use when the most
+     * recent buffer process cycle began. Can be called from any thread.
      */
     virtual pframes_t sample_time_at_cycle_start () = 0;
 
-    /** return the time since the current buffer process cycle started,
+    /** Return the time since the current buffer process cycle started,
      * in samples, according to the sample clock in use.
      * 
      * Can ONLY be called from within a process() callback tree (which
@@ -315,7 +314,7 @@ class AudioBackend {
      */
     virtual pframes_t samples_since_cycle_start () = 0;
 
-    /** return true if it possible to determine the offset in samples of the
+    /** Return true if it possible to determine the offset in samples of the
      * first video frame that starts within the current buffer process cycle,
      * measured from the first sample of the cycle. If returning true,
      * set @param offset to that offset.
@@ -339,6 +338,8 @@ class AudioBackend {
      * when that function returns.
      */
     virtual int create_process_thread (boost::function<void()> func, pthread_t*, size_t stacksize) = 0;
+
+    virtual void update_latencies () = 0;
     
   protected:
     AudioEngine&          engine;
index 9e9da62ce09afa92f7ec56368f0d62a1fdf47977..0bbbe90ef43dedfd47212e14d954d47f36bb66b1 100644 (file)
@@ -108,6 +108,16 @@ public:
     bool           is_realtime() const;
     bool           connected() const;
 
+    int set_device_name (const std::string&);
+    int set_sample_rate (float);
+    int set_buffer_size (uint32_t);
+    int set_sample_format (SampleFormat);
+    int set_interleaved (bool yn);
+    int set_input_channels (uint32_t);
+    int set_output_channels (uint32_t);
+    int set_systemic_input_latency (uint32_t);
+    int set_systemic_output_latency (uint32_t);
+
     /* END BACKEND PROXY API */
 
     bool freewheeling() const { return _freewheeling; }
@@ -115,7 +125,9 @@ public:
 
     Glib::Threads::Mutex& process_lock() { return _process_lock; }
 
-    int request_buffer_size (pframes_t);
+    int request_buffer_size (pframes_t samples) {
+           return set_buffer_size (samples);
+    }
 
     framecnt_t processed_frames() const { return _processed_frames; }
     
@@ -165,10 +177,6 @@ public:
     PBD::Signal0<void> Running;
     PBD::Signal0<void> Stopped;
     
-    std::string make_port_name_relative (std::string) const;
-    std::string make_port_name_non_relative (std::string) const;
-    bool port_is_mine (const std::string&) const;
-    
     static AudioEngine* instance() { return _instance; }
     static void destroy();
     void died ();
index 0855b8e90fcdbf0d631902c6b202d81efc6a3475..7104b814c2e0e715938c87d4b81c15652e028147 100644 (file)
@@ -99,6 +99,8 @@ class JACKAudioBackend : public AudioBackend {
     int set_time_master (bool /*yn*/);
     bool get_sync_offset (pframes_t& /*offset*/) const;
 
+    void update_latencies ();
+
   private:
     boost::shared_ptr<JackConnection>  _jack_connection; //< shared with JACKPortEngine
     bool            _running;
index 80e34f3c92aa9d7184f88f2e4557490f8aaed10a..bee87532d3e9cd0f5397bc1f57709f5dbb65ae89 100644 (file)
@@ -38,8 +38,8 @@ class JACKPortEngine : public PortEngine
 {
   public:
     JACKPortEngine (PortManager&, boost::shared_ptr<JackConnection>);
+    ~JACKPortEngine();
 
-    bool  connected() const;
     void* private_handle() const;
 
     const std::string& my_name() const;
@@ -48,10 +48,6 @@ class JACKPortEngine : public PortEngine
     std::string get_port_name (PortHandle) const;
     PortHandle* get_port_by_name (const std::string&) const;
 
-    std::string make_port_name_relative (const std::string& name) const;
-    std::string make_port_name_non_relative (const std::string& name) const;
-    bool        port_is_mine (const std::string& fullname) const;
-
     int get_ports (const std::string& port_name_pattern, DataType type, PortFlags flags, std::vector<std::string>&) const;
 
     DataType port_data_type (PortHandle) const;
@@ -62,19 +58,16 @@ class JACKPortEngine : public PortEngine
     bool  connected (PortHandle);
     bool  connected_to (PortHandle, const std::string&);
     bool  physically_connected (PortHandle);
-
     int   get_connections (PortHandle, std::vector<std::string>&);
-
     int   connect (PortHandle, const std::string&);
     int   disconnect (PortHandle, const std::string&);
     int   disconnect_all (PortHandle);
-
     int   connect (const std::string& src, const std::string& dst);
     int   disconnect (const std::string& src, const std::string& dst);
     
     /* MIDI */
 
-    void     midi_event_get (pframes_t& timestamp, size_t& size, uint8_t** buf, void* port_buffer, uint32_t event_index);
+    int      midi_event_get (pframes_t& timestamp, size_t& size, uint8_t** buf, void* port_buffer, uint32_t event_index);
     int      midi_event_put (void* port_buffer, pframes_t timestamp, const uint8_t* buffer, size_t size);
     uint32_t get_midi_event_count (void* port_buffer);
     void     midi_clear (void* port_buffer);
@@ -91,7 +84,8 @@ class JACKPortEngine : public PortEngine
     
     void          set_latency_range (PortHandle, bool for_playback, LatencyRange);
     LatencyRange  get_latency_range (PortHandle, bool for_playback);
-    LatencyRange  get_connected_latency_range (PortHandle, int dir);
+
+    /* Physical ports */
 
     bool      port_is_physical (PortHandle) const;
     void      get_physical_outputs (DataType type, std::vector<std::string>&);
@@ -99,9 +93,13 @@ class JACKPortEngine : public PortEngine
     ChanCount n_physical_outputs () const;
     ChanCount n_physical_inputs () const;
 
+    /* Getting access to the data buffer for a port */
+
     void* get_buffer (PortHandle, pframes_t);
 
-    framecnt_t last_frame_time () const;
+    /* Miscellany */
+
+    pframes_t sample_time_at_cycle_start ();
     
   private:
     boost::shared_ptr<JackConnection> _jack_connection;
@@ -110,10 +108,11 @@ class JACKPortEngine : public PortEngine
     static void _registration_callback (jack_port_id_t, int, void *);
     static void _connect_callback (jack_port_id_t, jack_port_id_t, int, void *);
 
-    int graph_order_callback ();
-
     void connect_callback (jack_port_id_t, jack_port_id_t, int);
 
+    ChanCount n_physical (unsigned long flags) const;
+    void get_physical (DataType type, unsigned long flags, std::vector<std::string>& phy) const;
+
 };
 
 } // namespace 
index 5992a48a855368f429bd93a5a71495ee2db984bd..e63c52630d5e33b51ad6262e72f20b4538378c6d 100644 (file)
@@ -77,7 +77,7 @@ class PortManager;
 class PortEngine {
   public:
     PortEngine (PortManager& pm) : manager (pm) {}
-    virtual ~PortEngine();
+    virtual ~PortEngine() {}
     
     /* We use void* here so that the API can be defined for any implementation.
      * 
@@ -89,7 +89,6 @@ class PortEngine {
        
     typedef void* PortHandle;
 
-    virtual bool  connected() const = 0;
     virtual void* private_handle() const = 0;
 
     virtual const std::string& my_name() const = 0;
@@ -125,10 +124,10 @@ class PortEngine {
 
     /* MIDI */
 
-    virtual void     midi_event_get (pframes_t& timestamp, size_t& size, uint8_t** buf, void* port_buffer, uint32_t event_index) = 0;
+    virtual int      midi_event_get (pframes_t& timestamp, size_t& size, uint8_t** buf, void* port_buffer, uint32_t event_index) = 0;
     virtual int      midi_event_put (void* port_buffer, pframes_t timestamp, const uint8_t* buffer, size_t size) = 0;
-    virtual uint32_t get_midi_event_count (void* port_buffer);
-    virtual void     midi_clear (void* port_buffer);
+    virtual uint32_t get_midi_event_count (void* port_buffer) = 0;
+    virtual void     midi_clear (void* port_buffer) = 0;
 
     /* Monitoring */
 
@@ -142,7 +141,6 @@ class PortEngine {
     
     virtual void          set_latency_range (PortHandle, bool for_playback, LatencyRange) = 0;
     virtual LatencyRange  get_latency_range (PortHandle, bool for_playback) = 0;
-    virtual LatencyRange  get_connected_latency_range (PortHandle, int dir) = 0;
 
     /* Discovering physical ports */
 
@@ -158,7 +156,16 @@ class PortEngine {
 
     virtual void* get_buffer (PortHandle, pframes_t) = 0;
 
-    virtual framecnt_t last_frame_time() const = 0;
+    /* MIDI ports (the ones in libmidi++) need this to be able to correctly
+     * schedule MIDI events within their buffers. It is a bit odd that we
+     * expose this here, because it is also exposed by AudioBackend, but they
+     * only have access to a PortEngine object, not an AudioBackend.
+     * 
+     * Return the time according to the sample clock in use when the current 
+     * buffer process cycle began. 
+     * 
+     */
+    virtual pframes_t sample_time_at_cycle_start () = 0;
 
   protected:
     PortManager& manager;
index 5838ac66af8fd5491f6c2567689014f3c499e833..d88143d1102e23510789f40b6d4019f4a01c73a9 100644 (file)
@@ -59,7 +59,6 @@ class PortManager
     int  connect (const std::string& source, const std::string& destination);
     int  disconnect (const std::string& source, const std::string& destination);
     int  disconnect (boost::shared_ptr<Port>);
-    bool has_connections (const std::string&);
     int  reestablish_ports ();
     int  reconnect_ports ();
 
index 88c9a09be7b8f3a026223232d330a2ee548d1ace..4408da2d25ceddc8d92ef00096775619e9f6671d 100644 (file)
@@ -48,6 +48,7 @@ namespace ARDOUR {
 
 class TempoMap;
 class Session;
+class AudioEngine;
 
 /**
  * @class Slave
@@ -492,7 +493,7 @@ class MIDIClock_Slave : public Slave {
 class JACK_Slave : public Slave
 {
   public:
-       JACK_Slave (jack_client_t*);
+       JACK_Slave (AudioEngine&);
        ~JACK_Slave ();
 
        bool speed_and_position (double& speed, framepos_t& pos);
@@ -502,11 +503,10 @@ class JACK_Slave : public Slave
        bool ok() const;
        framecnt_t resolution () const { return 1; }
        bool requires_seekahead () const { return false; }
-       void reset_client (jack_client_t* jack);
        bool is_always_synced() const { return true; }
 
   private:
-       jack_client_t* jack;
+        AudioEngine& engine;
        double speed;
        bool _starting;
 };
index 3d1bf6e77e36bffbc591d9c12f7bb122e63fef2b..05f59707a8227e2897e845afcd96d92a210eb131 100644 (file)
@@ -103,39 +103,6 @@ AudioEngine::create (const std::string& bcn, const std::string& bsu)
        return new AudioEngine (bcn, bsu);
 }
 
-void
-AudioEngine::drop_backend ()
-{
-       if (_backend) {
-               _backend->stop ();
-               _backend.reset ();
-       }
-}
-
-int
-AudioEngine::set_backend (const std::string& name)
-{
-       BackendMap::iterator b = _backends.find (name);
-
-       if (b == _backends.end()) {
-               return -1;
-       }
-
-       drop_backend ();
-
-       try {
-
-               _backend = b->second->backend_factory (*this);
-               _impl = b->second->portengine_factory (*this);
-
-       } catch (...) {
-               error << string_compose (_("Could not create backend for %1"), name) << endmsg;
-               return -1;
-       }
-
-       return 0;
-}
-
 void
 _thread_init_callback (void * /*arg*/)
 {
@@ -570,6 +537,60 @@ AudioEngine::backend_discover (const string& path)
        return info;
 }
 
+vector<string>
+AudioEngine::available_backends() const
+{
+       vector<string> r;
+       
+       for (BackendMap::const_iterator i = _backends.begin(); i != _backends.end(); ++i) {
+               r.push_back (i->first);
+       }
+
+       return r;
+}
+
+string
+AudioEngine::current_backend_name() const
+{
+       if (_backend) {
+               return _backend->name();
+       } 
+       return string();
+}
+
+void
+AudioEngine::drop_backend ()
+{
+       if (_backend) {
+               _backend->stop ();
+               _backend.reset ();
+       }
+}
+
+int
+AudioEngine::set_backend (const std::string& name)
+{
+       BackendMap::iterator b = _backends.find (name);
+
+       if (b == _backends.end()) {
+               return -1;
+       }
+
+       drop_backend ();
+
+       try {
+
+               _backend = b->second->backend_factory (*this);
+               _impl = b->second->portengine_factory (*this);
+
+       } catch (...) {
+               error << string_compose (_("Could not create backend for %1"), name) << endmsg;
+               return -1;
+       }
+
+       return 0;
+}
+
 /* BACKEND PROXY WRAPPERS */
 
 int
@@ -812,6 +833,89 @@ AudioEngine::create_process_thread (boost::function<void()> func, pthread_t* thr
 }
 
 
+int
+AudioEngine::set_device_name (const std::string& name)
+{
+       if (!_backend) {
+               return -1;
+       }
+       return _backend->set_device_name  (name);
+}
+
+int
+AudioEngine::set_sample_rate (float sr)
+{
+       if (!_backend) {
+               return -1;
+       }
+       return _backend->set_sample_rate  (sr);
+}
+
+int
+AudioEngine::set_buffer_size (uint32_t bufsiz)
+{
+       if (!_backend) {
+               return -1;
+       }
+       return _backend->set_buffer_size  (bufsiz);
+}
+
+int
+AudioEngine::set_sample_format (SampleFormat sf)
+{
+       if (!_backend) {
+               return -1;
+       }
+       return _backend->set_sample_format  (sf);
+}
+
+int
+AudioEngine::set_interleaved (bool yn)
+{
+       if (!_backend) {
+               return -1;
+       }
+       return _backend->set_interleaved  (yn);
+}
+
+int
+AudioEngine::set_input_channels (uint32_t ic)
+{
+       if (!_backend) {
+               return -1;
+       }
+       return _backend->set_input_channels  (ic);
+}
+
+int
+AudioEngine::set_output_channels (uint32_t oc)
+{
+       if (!_backend) {
+               return -1;
+       }
+       return _backend->set_output_channels (oc);
+}
+
+int
+AudioEngine::set_systemic_input_latency (uint32_t il)
+{
+       if (!_backend) {
+               return -1;
+       }
+       return _backend->set_systemic_input_latency  (il);
+}
+
+int
+AudioEngine::set_systemic_output_latency (uint32_t ol)
+{
+       if (!_backend) {
+               return -1;
+       }
+       return _backend->set_systemic_output_latency  (ol);
+}
+
+/* END OF BACKEND PROXY API */
+
 void
 AudioEngine::thread_init_callback (void* arg)
 {
@@ -873,6 +977,14 @@ AudioEngine::latency_callback (bool for_playback)
         }
 }
 
+void
+AudioEngine::update_latencies ()
+{
+       if (_backend) {
+               _backend->update_latencies ();
+       }
+}
+
 void
 AudioEngine::halted_callback (const char* why)
 {
index 162db6c7936485812ba0f671ba21a00713db66e9..be4b04e36a4966b69691256cb4b32394ff2fa876 100644 (file)
@@ -450,6 +450,8 @@ Bundle::connected_to (boost::shared_ptr<Bundle> other, AudioEngine & engine)
 bool
 Bundle::connected_to_anything (AudioEngine& engine)
 {
+       PortManager& pm (engine);
+
        for (uint32_t i = 0; i < nchannels().n_total(); ++i) {
                Bundle::PortList const & ports = channel_ports (i);
 
@@ -459,7 +461,7 @@ Bundle::connected_to_anything (AudioEngine& engine)
                           rather than doing it with Port.
                        */
 
-                       if (engine.has_connections (ports[j])) {
+                       if (pm.connected (ports[j])) {
                                return true;
                        }
                }
index b993135f5aef2f87113d16cf091db49fa377a1cf..04ee94a80ce74642ccaa6c8db9fd13a26999b2fb 100644 (file)
@@ -818,3 +818,10 @@ JACKAudioBackend::cpu_load() const
        GET_PRIVATE_JACK_POINTER_RET(_priv_jack,0);
        return jack_cpu_load (_priv_jack);
 }
+
+void
+JACKAudioBackend::update_latencies ()
+{
+       GET_PRIVATE_JACK_POINTER (_priv_jack);
+       jack_recompute_total_latencies (_priv_jack);
+}
index 4a6f3a1fca51108e8ba2fe1d5afd75adeb095421..7280c9ff2479ab7eb4554d21c00423e8e2295f49 100644 (file)
@@ -1,3 +1,35 @@
+/*
+    Copyright (C) 2013 Paul Davis
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include <string.h>
+#include <stdint.h>
+
+#include "pbd/failed_constructor.h"
+
+#include "ardour/jack_portengine.h"
+#include "ardour/jack_connection.h"
+#include "ardour/port_manager.h"
+
+using namespace ARDOUR;
+using std::string;
+using std::vector;
+
 #define GET_PRIVATE_JACK_POINTER(localvar)  jack_client_t* localvar = _jack_connection->jack(); if (!(localvar)) { return; }
 #define GET_PRIVATE_JACK_POINTER_RET(localvar,r) jack_client_t* localvar = _jack_connection->jack(); if (!(localvar)) { return r; }
 
@@ -6,13 +38,13 @@ ardour_port_flags_to_jack_flags (PortFlags flags)
 {
        uint32_t jack_flags = 0;
        
-       if (flags & PortIsInput) {
+       if (flags & IsInput) {
                jack_flags |= JackPortIsInput;
        }
-       if (flags & IsInput) {
+       if (flags & IsOutput) {
                jack_flags |= JackPortIsOutput;
        }
-       if (flags & IsOutput) {
+       if (flags & IsTerminal) {
                jack_flags |= JackPortIsTerminal;
        }
        if (flags & IsPhysical) {
@@ -53,17 +85,63 @@ JACKPortEngine::JACKPortEngine (PortManager& pm, boost::shared_ptr<JackConnectio
        : PortEngine (pm)
        , _jack_connection (jc)
 {
-       jack_client_t* client = _jack_connection->
+       jack_client_t* client = _jack_connection->jack();
+
+       if (!client) {
+               throw failed_constructor ();
+       }
+
+       /* register callbacks for stuff that is our responsibility */
+
+        jack_set_port_registration_callback (client, _registration_callback, this);
+        jack_set_port_connect_callback (client, _connect_callback, this);
+        jack_set_graph_order_callback (client, _graph_order_callback, this);
+}
+
+JACKPortEngine::~JACKPortEngine ()
+{
+       /* a default destructor would do this, and so would this one,
+          but we'll make it explicit in case we ever need to debug
+          the lifetime of the JACKConnection
+       */
+       _jack_connection.reset ();
+}
+
+void*
+JACKPortEngine::private_handle() const
+{
+       return _jack_connection->jack();
+}
+
+int
+JACKPortEngine::set_port_name (PortHandle port, const std::string& name)
+{
+       return jack_port_set_name ((jack_port_t*) port, name.c_str());
+}
+
+string
+JACKPortEngine::get_port_name (PortHandle port) const
+{
+       return jack_port_name ((jack_port_t*) port);
+}
 
-        jack_set_port_registration_callback (_priv_jack, _registration_callback, this);
-        jack_set_port_connect_callback (_priv_jack, _connect_callback, this);
-        jack_set_graph_order_callback (_priv_jack, _graph_order_callback, this);
+PortEngine::PortHandle*
+JACKPortEngine:: get_port_by_name (const std::string& name) const
+{
+       GET_PRIVATE_JACK_POINTER_RET (_priv_jack, 0);
+       return (PortHandle*) jack_port_by_name (_priv_jack, name.c_str());
 }
 
 void
 JACKPortEngine::_registration_callback (jack_port_id_t /*id*/, int /*reg*/, void* arg)
 {
-       static_cast<JACKPortEngine*> (arg)->_manager->registration_callback ();
+       static_cast<JACKPortEngine*> (arg)->manager.registration_callback ();
+}
+
+int
+JACKPortEngine::_graph_order_callback (void *arg)
+{
+       return static_cast<JACKPortEngine*> (arg)->manager.graph_order_callback ();
 }
 
 void
@@ -75,7 +153,7 @@ JACKPortEngine::_connect_callback (jack_port_id_t id_a, jack_port_id_t id_b, int
 void
 JACKPortEngine::connect_callback (jack_port_id_t id_a, jack_port_id_t id_b, int conn)
 {
-       if (_manager->port_remove_in_progress()) {
+       if (manager.port_remove_in_progress()) {
                return;
        }
 
@@ -84,79 +162,90 @@ JACKPortEngine::connect_callback (jack_port_id_t id_a, jack_port_id_t id_b, int
        jack_port_t* a = jack_port_by_id (_priv_jack, id_a);
        jack_port_t* b = jack_port_by_id (_priv_jack, id_b);
 
-       _manager->connect_callback (jack_port_name (a), jack_port_name (b), conn == 0 ? false : true);
+       manager.connect_callback (jack_port_name (a), jack_port_name (b), conn == 0 ? false : true);
 }
 
-int
-JACKPortEngine::_graph_order_callback (void *arg)
+bool
+JACKPortEngine::connected (PortHandle port)
 {
-       return static_cast<JACKPortEngine*> (arg)->graph_order_callback ();
+       bool ret = false;
+
+       const char** ports = jack_port_get_connections ((jack_port_t*) port);
+
+       if (ports) {
+               ret = true;
+       }
+
+       jack_free (ports);
+
+       return ret;
 }
 
-int
-JACKPortEngine::graph_order_callback ()
+bool
+JACKPortEngine::connected_to (PortHandle port, const std::string& other)
 {
-       if (_jack_connection->connected()) {
-               _manager->graph_order_callback ();
+       bool ret = false;
+       const char** ports = jack_port_get_connections ((jack_port_t*) port);
+
+       if (ports) {
+               for (int i = 0; ports[i]; ++i) {
+                       if (other == ports[i]) {
+                               ret = true;
+                       }
+               }
+               jack_free (ports);
        }
 
-       return 0;
+       return ret;
 }
 
+bool
 JACKPortEngine::physically_connected (PortHandle p)
 {
-       jack_port_t* _jack_port = (jack_port_t*) p;
+       GET_PRIVATE_JACK_POINTER_RET (_priv_jack, false);
+       jack_port_t* port = (jack_port_t*) p;
 
-       const char** jc = jack_port_get_connections (_jack_port);
+       const char** ports = jack_port_get_connections (port);
 
-       if (jc) {
-               for (int i = 0; jc[i]; ++i) {
+       if (ports) {
+               for (int i = 0; ports[i]; ++i) {
 
-                       jack_port_t* port = jack_port_by_name (_engine->jack(), jc[i]);
+                       jack_port_t* other = jack_port_by_name (_priv_jack, ports[i]);
 
-                       if (port && (jack_port_flags (port) & JackPortIsPhysical)) {
-                                if (jack_free) {
-                                        jack_free (jc);
-                                } else {
-                                        free (jc);
-                                }
+                       if (other && (jack_port_flags (other) & JackPortIsPhysical)) {
                                return true;
                        }
                }
-                if (jack_free) {
-                        jack_free (jc);
-                } else {
-                        free (jc);
-                }
+               jack_free (ports);
        }
 
        return false;
 }
 
 DataType
-JACKPortEngine::port_data_type (PortHandle p)
+JACKPortEngine::port_data_type (PortHandle p) const
 {
-       return jack_port_type_to_ardour_data_type (jack_port_type (p));
+       return jack_port_type_to_ardour_data_type (jack_port_type ((jack_port_t*) p));
 }
 
 const string&
 JACKPortEngine::my_name() const
 {
-       return _client_name;
+       return _jack_connection->client_name();
 }
 
 bool
-JACKPortEngine::port_is_physical (PortHandle* ph) const
+JACKPortEngine::port_is_physical (PortHandle ph) const
 {
        if (!ph) {
                 return false;
         }
 
-        return jack_port_flags (ph) & JackPortIsPhysical;
+        return jack_port_flags ((jack_port_t*) ph) & JackPortIsPhysical;
 }
 
 int
-JACKPortEngine::get_ports (const string& port_name_pattern, DataType type, PortFlags flags, vector<string>& s)
+JACKPortEngine::get_ports (const string& port_name_pattern, DataType type, PortFlags flags, vector<string>& s) const
 {
 
        GET_PRIVATE_JACK_POINTER_RET (_priv_jack,0);
@@ -166,12 +255,11 @@ JACKPortEngine::get_ports (const string& port_name_pattern, DataType type, PortF
                                              ardour_port_flags_to_jack_flags (flags));
 
        if (ports == 0) {
-               return s;
+               return 0;
        }
 
        for (uint32_t i = 0; ports[i]; ++i) {
                s.push_back (ports[i]);
-               jack_free (ports[i]);
        }
 
        jack_free (ports);
@@ -184,16 +272,15 @@ JACKPortEngine::n_physical (unsigned long flags) const
 {
        ChanCount c;
 
-       GET_PRIVATE_JACK_POINTER_RET (_jack, c);
+       GET_PRIVATE_JACK_POINTER_RET (_priv_jack, c);
 
        const char ** ports = jack_get_ports (_priv_jack, NULL, NULL, JackPortIsPhysical | flags);
 
        if (ports) {
                for (uint32_t i = 0; ports[i]; ++i) {
                        if (!strstr (ports[i], "Midi-Through")) {
-                               DataType t (jack_port_type (jack_port_by_name (_jack, ports[i])));
+                               DataType t (jack_port_type (jack_port_by_name (_priv_jack, ports[i])));
                                c.set (t, c.get (t) + 1);
-                               jack_free (ports[i]);
                        }
                }
                
@@ -216,12 +303,12 @@ JACKPortEngine::n_physical_outputs () const
 }
 
 void
-JACKPortEngine::get_physical (DataType type, unsigned long flags, vector<string>& phy)
+JACKPortEngine::get_physical (DataType type, unsigned long flags, vector<string>& phy) const
 {
        GET_PRIVATE_JACK_POINTER (_priv_jack);
        const char ** ports;
 
-       if ((ports = jack_get_ports (_priv_jack, NULL, type.to_jack_type(), JackPortIsPhysical | flags)) == 0) {
+       if ((ports = jack_get_ports (_priv_jack, NULL, ardour_data_type_to_jack_port_type (type), JackPortIsPhysical | flags)) == 0) {
                return;
        }
 
@@ -231,7 +318,6 @@ JACKPortEngine::get_physical (DataType type, unsigned long flags, vector<string>
                                 continue;
                         }
                        phy.push_back (ports[i]);
-                       jack_free (ports[i]);
                }
                jack_free (ports);
        }
@@ -257,7 +343,7 @@ JACKPortEngine::get_physical_outputs (DataType type, vector<string>& outs)
 
 
 bool
-JACKPortEngine::can_request_hardware_monitoring ()
+JACKPortEngine::can_monitor_input () const
 {
        GET_PRIVATE_JACK_POINTER_RET (_priv_jack,false);
        const char ** ports;
@@ -266,18 +352,131 @@ JACKPortEngine::can_request_hardware_monitoring ()
                return false;
        }
 
-       for (uint32_t i = 0; ports[i]; ++i) {
-               jack_free (ports[i]);
-       }
-
        jack_free (ports);
 
        return true;
 }
 
-framecnt_t
-JACKPortEngine::last_frame_time () const
+pframes_t
+JACKPortEngine::sample_time_at_cycle_start ()
 {
        GET_PRIVATE_JACK_POINTER_RET (_priv_jack, 0);
        return jack_last_frame_time (_priv_jack);
 }
+
+
+PortEngine::PortHandle
+JACKPortEngine::register_port (const std::string& shortname, ARDOUR::DataType type, ARDOUR::PortFlags flags)
+{
+       GET_PRIVATE_JACK_POINTER_RET (_priv_jack, 0);
+       return jack_port_register (_priv_jack, shortname.c_str(), 
+                                  ardour_data_type_to_jack_port_type (type),
+                                  ardour_port_flags_to_jack_flags (flags),
+                                  0);
+}
+
+void
+JACKPortEngine::unregister_port (PortHandle port)
+{
+       GET_PRIVATE_JACK_POINTER (_priv_jack);
+       (void) jack_port_unregister (_priv_jack, (jack_port_t*) port);
+}
+
+int
+JACKPortEngine::connect (PortHandle port, const std::string& other)
+{
+       GET_PRIVATE_JACK_POINTER_RET (_priv_jack, -1);
+       return jack_connect (_priv_jack, jack_port_name ((jack_port_t*) port), other.c_str());
+}
+int
+JACKPortEngine::connect (const std::string& src, const std::string& dst)
+{
+       GET_PRIVATE_JACK_POINTER_RET (_priv_jack, -1);
+       return jack_connect (_priv_jack, src.c_str(), dst.c_str());
+}
+
+int
+JACKPortEngine::disconnect (PortHandle port, const std::string& other)
+{
+       GET_PRIVATE_JACK_POINTER_RET (_priv_jack, -1);
+       return jack_disconnect (_priv_jack, jack_port_name ((jack_port_t*) port), other.c_str());
+}
+
+int
+JACKPortEngine::disconnect (const std::string& src, const std::string& dst)
+{
+       GET_PRIVATE_JACK_POINTER_RET (_priv_jack, -1);
+       return jack_disconnect (_priv_jack, src.c_str(), dst.c_str());
+}
+
+int
+JACKPortEngine::disconnect_all (PortHandle port)
+{
+       GET_PRIVATE_JACK_POINTER_RET (_priv_jack, -1);
+       return jack_port_disconnect (_priv_jack, (jack_port_t*) port);
+}
+
+
+int
+JACKPortEngine::midi_event_get (pframes_t& timestamp, size_t& size, uint8_t** buf, void* port_buffer, uint32_t event_index)
+{
+       jack_midi_event_t ev;
+       int ret;
+
+       if ((ret = jack_midi_event_get (&ev, port_buffer, event_index)) == 0) {
+               timestamp = ev.time;
+               size = ev.size;
+               *buf = ev.buffer;
+       }
+
+       return ret;
+}
+
+int
+JACKPortEngine::midi_event_put (void* port_buffer, pframes_t timestamp, const uint8_t* buffer, size_t size)
+{
+       return jack_midi_event_write (port_buffer, timestamp, buffer, size);
+}
+
+uint32_t
+JACKPortEngine::get_midi_event_count (void* port_buffer)
+{
+       return jack_midi_get_event_count (port_buffer);
+}
+
+void
+JACKPortEngine::midi_clear (void* port_buffer)
+{
+       jack_midi_clear_buffer (port_buffer);
+}
+
+void
+JACKPortEngine::set_latency_range (PortHandle port, bool for_playback, LatencyRange r)
+{
+       jack_latency_range_t range;
+       
+       range.min = r.min;
+       range.max = r.max;
+
+       jack_port_set_latency_range ((jack_port_t*) port, for_playback ? JackPlaybackLatency : JackCaptureLatency, &range);
+}
+
+LatencyRange
+JACKPortEngine::get_latency_range (PortHandle port, bool for_playback)
+{
+       jack_latency_range_t range;
+       LatencyRange ret;
+       
+       jack_port_get_latency_range ((jack_port_t*) port, for_playback ? JackPlaybackLatency : JackCaptureLatency, &range);
+
+       ret.min = range.min;
+       ret.max = range.max;
+
+       return ret;
+}
+
+void*
+JACKPortEngine::get_buffer (PortHandle port, pframes_t nframes)
+{
+       return jack_port_get_buffer ((jack_port_t*) port, nframes);
+}
index 4c2da4c6c45287a7a57aea78dde464ed28ab641d..4b2f3b18609dbfecf176dc808918624de64b2bba 100644 (file)
 #include <iostream>
 #include <cerrno>
 
-#include <jack/jack.h>
-#include <jack/transport.h>
-
+#include "ardour/audioengine.h"
 #include "ardour/slave.h"
 
 using namespace std;
 using namespace ARDOUR;
 
-JACK_Slave::JACK_Slave (jack_client_t* j)
-       : jack (j)
+JACK_Slave::JACK_Slave (AudioEngine& e)
+       : engine (e)
 {
        double x;
        framepos_t p;
@@ -41,12 +39,6 @@ JACK_Slave::~JACK_Slave ()
 {
 }
 
-void
-JACK_Slave::reset_client (jack_client_t* j)
-{
-       jack = j;
-}
-
 bool
 JACK_Slave::locked() const
 {
@@ -62,33 +54,26 @@ JACK_Slave::ok() const
 bool
 JACK_Slave::speed_and_position (double& sp, framepos_t& position)
 {
-       jack_position_t pos;
-       jack_transport_state_t state;
-
-       state = jack_transport_query (jack, &pos);
-
-       switch (state) {
-       case JackTransportStopped:
+       switch (engine.transport_state()) {
+       case TransportStopped:
                speed = 0;
                _starting = false;
                break;
-       case JackTransportRolling:
+       case TransportRolling:
                speed = 1.0;
                _starting = false;
                break;
-       case JackTransportLooping:
+       case TransportLooping:
                speed = 1.0;
                _starting = false;
                break;
-       case JackTransportStarting:
+       case TransportStarting:
                _starting = true;
                // don't adjust speed here, just leave it as it was
                break;
-       default:
-               cerr << "WARNING: Unknown JACK transport state: " << state << endl;
        }
 
        sp = speed;
-       position = pos.frame;
+       position = engine.transport_frame();
        return true;
 }
index 5aa6ad0ae728dfd9ec772cd764f0139758309bbb..571d227711669f9fbd64b8feafdd395d1baeacb0 100644 (file)
@@ -70,10 +70,6 @@ Port::Port (std::string const & n, DataType t, PortFlags f)
 
        assert (_name.find_first_of (':') == std::string::npos);
 
-       if (!port_engine.connected()) {
-               throw failed_constructor ();
-       }
-
        if ((_port_handle = port_engine.register_port (_name, t, _flags)) == 0) {
                cerr << "Failed to register port \"" << _name << "\", reason is unknown from here\n";
                throw failed_constructor ();
@@ -124,14 +120,6 @@ Port::disconnect_all ()
 bool
 Port::connected_to (std::string const & o) const
 {
-       if (!port_engine.connected()) {
-               /* in some senses, this answer isn't the right one all the time,
-                  because we know about our connections and will re-establish
-                  them when we reconnect to the port engine.
-               */
-               return false;
-       }
-
        return port_engine.connected_to (_port_handle, AudioEngine::instance()->make_port_name_non_relative (o));
 }
 
index 9c5eaa998b817598e32f39b2021a02b1c5a64f3a..b5f280292e4fc785718ac13d8616be5b3418ff2e 100644 (file)
@@ -127,6 +127,30 @@ PortManager::port_is_physical (const std::string& portname) const
        return _impl->port_is_physical (ph);
 }
 
+void
+PortManager::get_physical_outputs (DataType type, std::vector<std::string>& s)
+{
+       _impl->get_physical_outputs (type, s);
+}
+void
+PortManager::get_physical_inputs (DataType type, std::vector<std::string>& s)
+{
+       _impl->get_physical_inputs (type, s);
+}
+ChanCount
+PortManager::n_physical_outputs () const
+{
+       return _impl->n_physical_outputs ();
+}
+ChanCount
+PortManager::n_physical_inputs () const
+{
+       return _impl->n_physical_inputs ();
+}
+
 /** @param name Full or short name of port
  *  @return Corresponding Port or 0.
  */
@@ -134,11 +158,6 @@ PortManager::port_is_physical (const std::string& portname) const
 boost::shared_ptr<Port>
 PortManager::get_port_by_name (const string& portname)
 {
-       if (!_impl->connected()) {
-               fatal << _("get_port_by_name() called before engine was started") << endmsg;
-               /*NOTREACHED*/
-       }
-
         if (!port_is_mine (portname)) {
                 /* not an ardour port */
                 return boost::shared_ptr<Port> ();
@@ -254,13 +273,6 @@ PortManager::unregister_port (boost::shared_ptr<Port> port)
 {
        /* caller must hold process lock */
 
-       if (!_impl->connected()) {
-               /* probably happening when the engine has been halted by JACK,
-                  in which case, there is nothing we can do here.
-                  */
-               return 0;
-       }
-
        {
                RCUWriter<Ports> writer (ports);
                boost::shared_ptr<Ports> ps = writer.get_copy ();
@@ -295,10 +307,6 @@ PortManager::connect (const string& source, const string& destination)
 {
        int ret;
 
-       if (!_impl->connected()) {
-               return -1;
-       }
-
        string s = make_port_name_non_relative (source);
        string d = make_port_name_non_relative (destination);
 
@@ -330,10 +338,6 @@ PortManager::disconnect (const string& source, const string& destination)
 {
        int ret;
 
-       if (!_impl->connected()) {
-               return -1;
-       }
-
        string s = make_port_name_non_relative (source);
        string d = make_port_name_non_relative (destination);
 
@@ -429,3 +433,30 @@ PortManager::registration_callback ()
                PortRegisteredOrUnregistered (); /* EMIT SIGNAL */
        }
 }
+
+bool
+PortManager::can_request_input_monitoring () const
+{
+       return _impl->can_monitor_input ();
+}
+void
+PortManager::request_input_monitoring (const string& name, bool yn) const
+{
+       PortEngine::PortHandle ph = _impl->get_port_by_name (name);
+
+       if (ph) {
+               _impl->request_input_monitoring (ph, yn);
+       }
+}
+void
+PortManager::ensure_input_monitoring (const string& name, bool yn) const
+{
+       PortEngine::PortHandle ph = _impl->get_port_by_name (name);
+
+       if (ph) {
+               _impl->ensure_input_monitoring (ph, yn);
+       }
+}
+
index c2965a46175733f8fa489ca5bafcc42990fdafab..eabfbaacc0ac6ab1ea8350d15cedd768d0238015 100644 (file)
@@ -967,7 +967,7 @@ Route::add_processor (boost::shared_ptr<Processor> processor, boost::shared_ptr<
        DEBUG_TRACE (DEBUG::Processors, string_compose (
                             "%1 adding processor %2\n", name(), processor->name()));
 
-       if (!AudioEngine::instance()->port_engine().connected() || !processor) {
+       if (!AudioEngine::instance()->connected() || !processor) {
                return 1;
        }
 
@@ -1132,7 +1132,7 @@ Route::add_processors (const ProcessorList& others, boost::shared_ptr<Processor>
                loc = _processors.end ();
        }
 
-       if (!_session.engine().port_engine().connected()) {
+       if (!_session.engine().connected()) {
                return 1;
        }
 
@@ -1329,7 +1329,7 @@ Route::ab_plugins (bool forward)
 void
 Route::clear_processors (Placement p)
 {
-       if (!_session.engine().port_engine().connected()) {
+       if (!_session.engine().connected()) {
                return;
        }
 
@@ -1416,7 +1416,7 @@ Route::remove_processor (boost::shared_ptr<Processor> processor, ProcessorStream
                return 0;
        }
 
-       if (!_session.engine().port_engine().connected()) {
+       if (!_session.engine().connected()) {
                return 1;
        }
 
@@ -1508,7 +1508,7 @@ Route::remove_processors (const ProcessorList& to_be_deleted, ProcessorStreams*
 {
        ProcessorList deleted;
 
-       if (!_session.engine().port_engine().connected()) {
+       if (!_session.engine().connected()) {
                return 1;
        }
 
index 1ea3732e3ffb201feb8d5631868c646d005017c7..e1634db536ed980a8ea424e16f80ff3a415c27f0 100644 (file)
@@ -170,7 +170,7 @@ Session::Session (AudioEngine &eng,
 
        interpolation.add_channel_to (0, 0);
 
-       if (!eng.port_engine().connected()) {
+       if (!eng.connected()) {
                throw failed_constructor();
        }
 
@@ -4677,7 +4677,7 @@ Session::set_worst_playback_latency ()
 
        _worst_output_latency = 0;
 
-       if (!_engine.port_engine().connected()) {
+       if (!_engine.connected()) {
                return;
        }
 
@@ -4699,7 +4699,7 @@ Session::set_worst_capture_latency ()
 
        _worst_input_latency = 0;
 
-       if (!_engine.port_engine().connected()) {
+       if (!_engine.connected()) {
                return;
        }
 
index 02bf48a0d672f7d33961c4f9dbf0b5aa5bd1cc7f..0db4fc33bb61d19e5abc6fb96223783e448ad6fb 100644 (file)
@@ -147,7 +147,7 @@ Session::start_audio_export (framepos_t position)
 
        /* we are ready to go ... */
 
-       if (!_engine.port_engine().connected()) {
+       if (!_engine.connected()) {
                return -1;
        }
 
index aa0c90204d0137b252b046af774b2b43f7f9e005..cae3b9720acf7233030d13206066a4617a45de63 100644 (file)
@@ -765,7 +765,7 @@ Session::save_state (string snapshot_name, bool pending, bool switch_to_snapshot
                return 1;
        }
 
-       if (!_engine.port_engine().connected ()) {
+       if (!_engine.connected ()) {
                error << string_compose (_("the %1 audio engine is not connected and state saving would lose all I/O connections. Session not saved"),
                                          PROGRAM_NAME)
                      << endmsg;
index fea2fcd96aaed660c98dab929c76816e5ab98ac5..0b0351f5063992aaf13f5630ba066a2ec7d62ab3 100644 (file)
@@ -44,7 +44,6 @@
 #include "ardour/session.h"
 #include "ardour/slave.h"
 #include "ardour/operations.h"
-#include "ardour/jack_portengine.h"
 
 #include "i18n.h"
 
@@ -1417,13 +1416,6 @@ Session::switch_to_sync_source (SyncSource src)
                break;
 
        case JACK:
-               /* if we are not using JACK as the port engine, we can't do
-                * this
-                */
-               if (dynamic_cast<JACKPortEngine*>(&AudioEngine::instance()->port_engine())) {
-                       return;
-               }
-
                if (_slave && dynamic_cast<JACK_Slave*>(_slave)) {
                        return;
                }
@@ -1432,7 +1424,7 @@ Session::switch_to_sync_source (SyncSource src)
                        return;
                }
 
-               new_slave = new JACK_Slave ((jack_client_t*) AudioEngine::instance()->port_engine().private_handle());
+               new_slave = new JACK_Slave (*AudioEngine::instance());
                break;
 
        default:
@@ -1622,16 +1614,6 @@ Session::allow_auto_play (bool yn)
        auto_play_legal = yn;
 }
 
-void
-Session::reset_jack_connection (jack_client_t* jack)
-{
-       JACK_Slave* js;
-
-       if (_slave && ((js = dynamic_cast<JACK_Slave*> (_slave)) != 0)) {
-               js->reset_client (jack);
-       }
-}
-
 bool
 Session::maybe_stop (framepos_t limit)
 {
index 48cfda7bc2fe87d7773185cc2054eabf3fe09616..07bb10f08d37b9831a5d86ce29f315634aebe925 100644 (file)
@@ -43,6 +43,7 @@ libardour_sources = [
         'automation_control.cc',
         'automation_list.cc',
         'automation_watch.cc',
+        'backend_search_path.cc',
         'beats_frames_converter.cc',
         'broadcast_info.cc',
         'buffer.cc',
@@ -439,7 +440,8 @@ def build(bld):
                      source = [ 
             'jack_api.cc',
             'jack_connection.cc',
-            'jack_audiobackend.cc'
+            'jack_audiobackend.cc',
+            'jack_portengine.cc'
             ])
     obj.cxxflags = [ '-fPIC' ]
     obj.name     = 'jack_audiobackend'
index 372a7891c913e95a522008a00c6426a65b64230e..8ba27759bc15f81ba2203b0bc18283a38eddc8db 100644 (file)
@@ -155,7 +155,7 @@ JackMIDIPort::cycle_start (pframes_t nframes)
                pframes_t time;
                size_t size;
                uint8_t* buf;
-               timestamp_t cycle_start_frame = _port_engine.last_frame_time ();
+               timestamp_t cycle_start_frame = _port_engine.sample_time_at_cycle_start ();
 
                for (pframes_t i = 0; i < event_count; ++i) {
                        _port_engine.midi_event_get (time, size, &buf, buffer, i);