part-way through getting the audioengine changes to compile
authorPaul Davis <paul@linuxaudiosystems.com>
Wed, 24 Jul 2013 23:29:45 +0000 (19:29 -0400)
committerPaul Davis <paul@linuxaudiosystems.com>
Wed, 24 Jul 2013 23:29:45 +0000 (19:29 -0400)
43 files changed:
libs/ardour/ardour/audio_backend.h
libs/ardour/ardour/audio_diskstream.h
libs/ardour/ardour/audio_port.h
libs/ardour/ardour/audioengine.h
libs/ardour/ardour/backend_search_path.h [new file with mode: 0644]
libs/ardour/ardour/data_type.h
libs/ardour/ardour/directory_names.h
libs/ardour/ardour/jack_audiobackend.h
libs/ardour/ardour/midi_buffer.h
libs/ardour/ardour/midi_port.h
libs/ardour/ardour/port.h
libs/ardour/ardour/port_engine.h [new file with mode: 0644]
libs/ardour/ardour/port_manager.h
libs/ardour/ardour/types.h
libs/ardour/audio_diskstream.cc
libs/ardour/audio_port.cc
libs/ardour/audioengine.cc
libs/ardour/backend_search_path.cc [new file with mode: 0644]
libs/ardour/bundle.cc
libs/ardour/capturing_processor.cc
libs/ardour/directory_names.cc
libs/ardour/export_channel.cc
libs/ardour/export_graph_builder.cc
libs/ardour/globals.cc
libs/ardour/internal_send.cc
libs/ardour/jack_audiobackend.cc
libs/ardour/ltc_slave.cc
libs/ardour/midi_buffer.cc
libs/ardour/midi_diskstream.cc
libs/ardour/midi_port.cc
libs/ardour/midi_ui.cc
libs/ardour/mtc_slave.cc
libs/ardour/port.cc
libs/ardour/wscript
libs/midi++2/jack_midi_port.cc
libs/midi++2/manager.cc
libs/midi++2/midi++/jack_midi_port.h
libs/midi++2/midi++/manager.h
libs/midi++2/midi++/mmc.h
libs/midi++2/mmc.cc
libs/midi++2/wscript
libs/surfaces/mackie/mackie_control_protocol.cc
libs/surfaces/mackie/surface_port.cc

index 98f6c4d8a7782f054aa4d1517bbdc0a4df72d8bd..7ae48c4c46522a14cb5f617a12cecc92273afb55 100644 (file)
@@ -33,16 +33,16 @@ class AudioEngine;
 class AudioBackend {
   public:
 
-    enum State {
-           Stopped = 0x1,
-           Running = 0x2,
-           Paused =  0x4,
-           Freewheeling = 0x8,
-    };
-
-    AudioBackend (AudioEngine& e) : engine (e), _state (Stopped) {}
+    AudioBackend (AudioEngine& e) : engine (e){}
     virtual ~AudioBackend () {}
 
+    /** Return the name of this backend.
+     *
+     * Should use a well-known, unique term. Expected examples
+     * might include "JACK", "CoreAudio", "ASIO" etc.
+     */
+    virtual std::string name() const = 0;
+
     /** return true if the underlying mechanism/API is still available
      * for us to utilize. return false if some or all of the AudioBackend
      * API can no longer be effectively used.
@@ -261,7 +261,7 @@ class AudioBackend {
     virtual TransportState transport_state () { return TransportStopped; }
     /** Attempt to locate the transport to @param pos
      */
-    virtual void transport_locate (framepos_t pos) {}
+    virtual void transport_locate (framepos_t /*pos*/) {}
     /** Return the current transport location, in samples measured
      * from the origin (defined by the transport time master)
      */
@@ -275,11 +275,11 @@ class AudioBackend {
      * JACK is the only currently known audio API with the concept of a shared
      * transport timebase.
      */
-    virtual int set_time_master (bool yn) { return 0; }
+    virtual int set_time_master (bool /*yn*/) { return 0; }
 
     virtual framecnt_t sample_rate () const;
     virtual pframes_t  samples_per_cycle () const;
-    virtual int        usecs_per_cycle () const { return _usecs_per_cycle; }
+    virtual int        usecs_per_cycle () const { return 1000000 * (samples_per_cycle() / sample_rate()); }
     virtual size_t     raw_buffer_size (DataType t);
     
     /* Process time */
@@ -326,7 +326,7 @@ class AudioBackend {
      * Can ONLY be called from within a process() callback tree (which implies
      * that it can only be called by a process thread)
      */
-    virtual bool get_sync_offset (pframes_t& offset) const { return 0; }
+    virtual bool get_sync_offset (pframes_t& /*offset*/) const { return false; }
 
     /** Create a new thread suitable for running part of the buffer process
      * cycle (i.e. Realtime scheduling, memory allocation, etc. etc are all
@@ -338,17 +338,6 @@ class AudioBackend {
     
   private:
     AudioEngine&          engine;
-    State                _state;
-
-    std::string  _target_device;
-    float        _target_sample_rate;
-    uint32_t     _target_buffer_size;
-    SampleFormat _target_sample_format;
-    bool         _target_interleaved;
-    uint32_t     _target_input_channels;
-    uint32_t     _target_output_channels;
-    uin32_t      _target_systemic_input_latency;
-    uin32_t      _target_systemic_input_latency;
 };
 
 }
index cbc6b93fe0d4b53d86ac5ce80502c9d84ab107e9..21efc5c20c7ac4421fe1fc6b2236888347b6f3a1 100644 (file)
@@ -114,7 +114,7 @@ class AudioDiskstream : public Diskstream
        XMLNode& get_state(void);
        int      set_state(const XMLNode& node, int version);
 
-       void request_jack_monitors_input (bool);
+       void request_input_monitoring (bool);
 
        static void swap_by_ptr (Sample *first, Sample *last) {
                while (first < last) {
@@ -159,7 +159,7 @@ class AudioDiskstream : public Diskstream
                std::string name;
 
                bool is_physical () const;
-               void request_jack_monitors_input (bool) const;
+               void request_input_monitoring (bool) const;
        };
 
        /** Information about one of our channels */
index 7f084a5c85fb12d56897cb384fa242f6d614b745..a473dda418ca92a0c2fcc506a8c4c75b99e0a60e 100644 (file)
@@ -48,7 +48,7 @@ class AudioPort : public Port
   protected:
        friend class AudioEngine;
 
-       AudioPort (std::string const &, Flags);
+       AudioPort (std::string const &, PortFlags);
         /* special access for engine only */
         Sample* engine_get_whole_audio_buffer ();
 
index a3f16ff376eb1dbeeb2610f6c7a7300f162b244d..422e12e9d8b59499b09d3399ac72c1061b032472 100644 (file)
@@ -47,6 +47,7 @@
 #include "ardour/session_handle.h"
 #include "ardour/types.h"
 #include "ardour/chan_count.h"
+#include "ardour/port_manager.h"
 
 #ifdef HAVE_JACK_SESSION
 #include <jack/session.h>
@@ -61,37 +62,60 @@ class Session;
 class ProcessThread;
 class AudioBackend;
 
-class AudioEngine : public SessionHandlePtr
+class AudioEngine : public SessionHandlePtr, public PortManager
 {
 public:
-    typedef std::map<std::string,boost::shared_ptr<Port> > Ports;
-    
-    AudioEngine (std::string client_name, std::string session_uuid);
+
+    static AudioEngine* create (const std::string&  client_name, const std::string& session_uuid);
+
     virtual ~AudioEngine ();
     
-    static int discover_backends();
+    int discover_backends();
     std::vector<std::string> available_backends() const;
     std::string current_backend_name () const;
+    int set_backend (const std::string&);
 
     ProcessThread* main_thread() const { return _main_thread; }
     
     std::string client_name() const { return backend_client_name; }
-    
-    int stop (bool forever = false);
-    int start ();
-    int pause ();
-    int freewheel (bool onoff);
+
+    /* START BACKEND PROXY API 
+     *
+     * See audio_backend.h for full documentation and semantics. These wrappers
+     * just forward to a backend implementation.
+     */
+
+    int            start ();
+    int            stop ();
+    int            pause ();
+    int            freewheel (bool start_stop);
+    float          get_cpu_load() const ;
+    void           transport_start ();
+    void           transport_stop ();
+    TransportState transport_state ();
+    void           transport_locate (framepos_t pos);
+    framepos_t     transport_frame();
+    framecnt_t     sample_rate () const;
+    pframes_t      samples_per_cycle () const;
+    int            usecs_per_cycle () const;
+    size_t         raw_buffer_size (DataType t);
+    pframes_t      sample_time ();
+    pframes_t      sample_time_at_cycle_start ();
+    pframes_t      samples_since_cycle_start ();
+    bool           get_sync_offset (pframes_t& offset) const;
+    int            create_process_thread (boost::function<void()> func, pthread_t*, size_t stacksize);
+    
+    /* END BACKEND PROXY API */
+
     bool freewheeling() const { return _freewheeling; }
-   
     bool running() const { return _running; }
+
     Glib::Threads::Mutex& process_lock() { return _process_lock; }
 
     int request_buffer_size (pframes_t);
 
     framecnt_t processed_frames() const { return _processed_frames; }
     
-    float get_cpu_load();
-    
     void set_session (Session *);
     void remove_session (); // not a replacement for SessionHandle::session_going_away()
     
@@ -161,8 +185,11 @@ public:
     int    process_callback (pframes_t nframes);
     
   private:
+    AudioEngine (const std::string&  client_name, const std::string& session_uuid);
+
     static AudioEngine*       _instance;
-    
+
+    AudioBackend*             _backend;
     Glib::Threads::Mutex      _process_lock;
     Glib::Threads::Cond        session_removed;
     bool                       session_remove_pending;
@@ -187,6 +214,8 @@ public:
     Glib::Threads::Thread*     m_meter_thread;
     ProcessThread*            _main_thread;
     
+    std::string               backend_client_name;
+    std::string               backend_session_uuid;
     
     void meter_thread ();
     void start_metering_thread ();
@@ -196,6 +225,11 @@ public:
     
     void parameter_changed (const std::string&);
     PBD::ScopedConnection config_connection;
+
+    typedef std::map<std::string,AudioBackend*> BackendMap;
+    BackendMap _backends;
+    AudioBackend* backend_discover (const std::string&);
+    void drop_backend ();
 };
        
 } // namespace ARDOUR
diff --git a/libs/ardour/ardour/backend_search_path.h b/libs/ardour/ardour/backend_search_path.h
new file mode 100644 (file)
index 0000000..2adc22b
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+    Copyright (C) 2011 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.
+*/
+
+#ifndef __ardour_backend_search_path_h__
+#define __ardour_backend_search_path_h__
+
+#include "pbd/search_path.h"
+
+namespace ARDOUR {
+
+       /**
+        * return a SearchPath containing directories in which to look for
+        * backend plugins.
+        *
+        * If ARDOUR_BACKEND_PATH is defined then the SearchPath returned
+        * will contain only those directories specified in it, otherwise it will
+        * contain the user and system directories which may contain audio/MIDI
+        * backends.
+        */
+       PBD::SearchPath backend_search_path ();
+
+} // namespace ARDOUR
+
+#endif /* __ardour_backend_search_path_h__ */
index 6a016ae75a0fe3ccdfd1401d4e3d989f08bb9f07..b4129e26296f4b61a2a721f3c4ad1ee765d71d8a 100644 (file)
 #define __ardour_data_type_h__
 
 #include <string>
-#include <jack/jack.h>
+#include <stdint.h>
+#include <glib.h>
 
 namespace ARDOUR {
 
-
 /** A type of Data Ardour is capable of processing.
  *
  * The majority of this class is dedicated to conversion to and from various
@@ -61,33 +61,25 @@ public:
 
        /** Construct from a string (Used for loading from XML and Ports)
         * The string can be as in an XML file (eg "audio" or "midi"), or a
-        * Jack type string (from jack_port_type) */
+        */
        DataType(const std::string& str)
        : _symbol(NIL) {
-               if (str == "audio" || str == JACK_DEFAULT_AUDIO_TYPE)
+               if (!g_ascii_strncasecmp(str.c_str(), "audio", str.length())) {
                        _symbol = AUDIO;
-               else if (str == "midi" || str == JACK_DEFAULT_MIDI_TYPE)
+               } else if (!g_ascii_strncasecmp(str.c_str(), "midi", str.length())) {
                        _symbol = MIDI;
-       }
-
-       /** Get the Jack type this DataType corresponds to */
-       const char* to_jack_type() const {
-               switch (_symbol) {
-                       case AUDIO: return JACK_DEFAULT_AUDIO_TYPE;
-                       case MIDI:  return JACK_DEFAULT_MIDI_TYPE;
-                       default:    return "";
                }
        }
 
        /** Inverse of the from-string constructor */
        const char* to_string() const {
                switch (_symbol) {
-                       case AUDIO: return "audio";
-                       case MIDI:  return "midi";
-                       default:    return "unknown"; // reeeally shouldn't ever happen
+               case AUDIO: return "audio";
+               case MIDI:  return "midi";
+               default:    return "unknown"; // reeeally shouldn't ever happen
                }
        }
-
+    
        const char* to_i18n_string () const;
 
        inline operator uint32_t() const { return (uint32_t)_symbol; }
@@ -125,7 +117,6 @@ private:
 };
 
 
-
 } // namespace ARDOUR
 
 #endif // __ardour_data_type_h__
index 9f7c778d33a72c7e5a88ba372b146629cf72d9fe..935cdd977bc44bdf642dbc4437195ed907adc87b 100644 (file)
@@ -38,6 +38,7 @@ extern const char* const route_templates_dir_name;
 extern const char* const surfaces_dir_name;
 extern const char* const user_config_dir_name;
 extern const char* const panner_dir_name;
+extern const char* const backend_dir_name;
 
 };
 
index 07214ee77a4950bb90e5f3b417ab0b4a77affb9f..2e12d521cdcab4b843ad8e2f1071dcbfe0714e01 100644 (file)
@@ -93,6 +93,18 @@ ifdef HAVE_JACK_SESSION
 
     ChanCount n_physical (unsigned long) const;
     void get_physical (DataType, unsigned long, std::vector<std::string> &);
+
+    /* pffooo */
+
+    std::string  _target_device;
+    float        _target_sample_rate;
+    uint32_t     _target_buffer_size;
+    SampleFormat _target_sample_format;
+    bool         _target_interleaved;
+    uint32_t     _target_input_channels;
+    uint32_t     _target_output_channels;
+    uin32_t      _target_systemic_input_latency;
+    uin32_t      _target_systemic_input_latency;
 };
 
 }
index 5ef5e4c8457a8778447c07fa11a47fe686e805bd..781396a598778fc6977e97c005e1840e4f2c17e5 100644 (file)
@@ -44,7 +44,6 @@ public:
        void copy(const MidiBuffer& copy);
 
        bool     push_back(const Evoral::MIDIEvent<TimeType>& event);
-       bool     push_back(const jack_midi_event_t& event);
        bool     push_back(TimeType time, size_t size, const uint8_t* data);
        uint8_t* reserve(TimeType time, size_t size);
 
index 5dc55398cb9c7fdb1441e3202488d534ee47a5f1..e14c7926fbc34bd0af182943dacdbc78cdd5fd45 100644 (file)
@@ -59,7 +59,7 @@ class MidiPort : public Port {
   protected:
        friend class AudioEngine;
 
-       MidiPort (const std::string& name, Flags);
+       MidiPort (const std::string& name, PortFlags);
 
   private:
        MidiBuffer* _buffer;
index 5afe8e28068bc59a7d531c0665ce37d9773bcf08..6186ce7748bd7c2a660903b24b64db1d458c1d0b 100644 (file)
@@ -30,6 +30,7 @@
 #include "pbd/signals.h"
 
 #include "ardour/data_type.h"
+#include "ardour/port_engine.h"
 #include "ardour/types.h"
 
 namespace ARDOUR {
@@ -40,11 +41,6 @@ class Buffer;
 class Port : public boost::noncopyable
 {
 public:
-       enum Flags {
-               IsInput = JackPortIsInput,
-               IsOutput = JackPortIsOutput,
-       };
-
        virtual ~Port ();
 
        static void set_connecting_blocked( bool yn ) {
@@ -62,7 +58,7 @@ public:
        int set_name (std::string const &);
 
        /** @return flags */
-       Flags flags () const {
+        PortFlags flags () const {
                return _flags;
        }
 
@@ -90,8 +86,8 @@ public:
        virtual int connect (Port *);
        int disconnect (Port *);
 
-       void request_monitor_input (bool);
-       void ensure_monitor_input (bool);
+       void request_input_monitoring (bool);
+       void ensure_input_monitoring (bool);
        bool monitoring_input () const;
        int reestablish ();
        int reconnect ();
@@ -99,7 +95,7 @@ public:
        bool last_monitor() const { return _last_monitor; }
        void set_last_monitor (bool yn) { _last_monitor = yn; }
 
-       jack_port_t* jack_port() const { return _jack_port; }
+        PortEngine::PortHandle port_handle() { return _port_handle; }
 
        void get_connected_latency_range (jack_latency_range_t& range, bool playback) const;
 
@@ -122,8 +118,6 @@ public:
 
        bool physically_connected () const;
 
-       static void set_engine (AudioEngine *);
-
        PBD::Signal1<void,bool> MonitorInputChanged;
        static PBD::Signal2<void,boost::shared_ptr<Port>,boost::shared_ptr<Port> > PostDisconnect;
        static PBD::Signal0<void> PortDrop;
@@ -143,9 +137,9 @@ public:
 
 protected:
 
-       Port (std::string const &, DataType, Flags);
+       Port (std::string const &, DataType, PortFlags);
 
-       jack_port_t* _jack_port; ///< JACK port
+        PortEngine::PortHandle _port_handle;
 
        static bool       _connecting_blocked;
        static pframes_t  _global_port_buffer_offset;   /* access only from process() tree */
@@ -156,15 +150,13 @@ protected:
        jack_latency_range_t _private_playback_latency;
        jack_latency_range_t _private_capture_latency;
 
-       static AudioEngine* _engine; ///< the AudioEngine
-
 private:
        std::string _name;  ///< port short name
-       Flags       _flags; ///< flags
+       PortFlags       _flags; ///< flags
        bool        _last_monitor;
 
        /** ports that we are connected to, kept so that we can
-           reconnect to JACK when required
+           reconnect to the backend when required
        */
        std::set<std::string> _connections;
 
diff --git a/libs/ardour/ardour/port_engine.h b/libs/ardour/ardour/port_engine.h
new file mode 100644 (file)
index 0000000..3bea326
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+    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.
+
+*/
+
+#ifndef __libardour_port_engine_h__
+#define __libardour_port_engine_h__
+
+#include <vector>
+#include <string>
+
+#include <stdint.h>
+
+#include "ardour/data_type.h"
+#include "ardour/types.h"
+
+namespace ARDOUR {
+
+/** PortEngine is an abstract base class that defines the functionality
+ * required by Ardour. 
+ * 
+ * A Port is basically an endpoint for a datastream (which can either be
+ * continuous, like audio, or event-based, like MIDI). Ports have buffers
+ * associated with them into which data can be written (if they are output
+ * ports) and from which data can be read (if they input ports). Ports can be
+ * connected together so that data written to an output port can be read from
+ * an input port. These connections can be 1:1, 1:N OR N:1. 
+ *
+ * Ports may be associated with software only, or with hardware.  Hardware
+ * related ports are often referred to as physical, and correspond to some
+ * relevant physical entity on a hardware device, such as an audio jack or a
+ * MIDI connector. Physical ports may be potentially asked to monitor their
+ * inputs, though some implementations may not support this.
+ *
+ * Most physical ports will also be considered "terminal", which means that
+ * data delivered there or read from there will go to or comes from a system
+ * outside of the PortEngine implementation's control (e.g. the analog domain
+ * for audio, or external MIDI devices for MIDI). Non-physical ports can also
+ * be considered "terminal". For example, the output port of a software
+ * synthesizer is a terminal port, because the data contained in its buffer
+ * does not and cannot be considered to come from any other port - it is
+ * synthesized by its owner.
+ *
+ * Ports also have latency associated with them. Each port has a playback
+ * latency and a capture latency:
+ *
+ * <b>capture latency</b>: how long since the data read from the buffer of a
+ *                  port arrived at at a terminal port.  The data will have
+ *                  come from the "outside world" if the terminal port is also
+ *                  physical, or will have been synthesized by the entity that
+ *                  owns the terminal port.
+ *                  
+ * <b>playback latency</b>: how long until the data written to the buffer of
+ *                   port will reach a terminal port.
+ *
+ *
+ * For more detailed questions about the PortEngine API, consult the JACK API
+ * documentation, on which this entire object is based.
+ */
+
+class PortEngine {
+  public:
+    PortEngine() {}
+    virtual ~PortEngine();
+    
+    /* We use void* here so that the API can be defined for any implementation.
+     * 
+     * We could theoretically use a template (PortEngine<T>) and define
+     * PortHandle as T, but this complicates the desired inheritance
+     * pattern in which FooPortEngine handles things for the Foo API,
+     * rather than being a derivative of PortEngine<Foo>.
+    */
+       
+    typedef void* PortHandle;
+
+    virtual bool connected() const = 0;
+
+    virtual int         set_port_name (PortHandle, const std::string&) = 0;
+    virtual std::string get_port_name (PortHandle) const = 0;
+    virtual PortHandle* get_port_by_name (const std::string&) const = 0;
+
+    virtual PortHandle register_port (const std::string&, DataType::Symbol, ARDOUR::PortFlags) = 0;
+    virtual void  unregister_port (PortHandle) = 0;
+    virtual bool  connected (PortHandle) = 0;
+    virtual int   disconnect_all (PortHandle) = 0;
+    virtual bool  connected_to (PortHandle, const std::string&) = 0;
+    virtual int   get_connections (PortHandle, std::vector<std::string>&) = 0;
+    virtual bool  physically_connected (PortHandle) = 0;
+    virtual int   connect (PortHandle, const std::string&) = 0;
+    virtual int   disconnect (PortHandle, const std::string&) = 0;
+    
+    /* 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_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);
+
+    /* Monitoring */
+
+    virtual bool  can_monitor_input() const = 0;
+    virtual int   request_input_monitoring (PortHandle, bool) = 0;
+    virtual int   ensure_input_monitoring (PortHandle, bool) = 0;
+    virtual bool  monitoring_input (PortHandle) = 0;
+
+    /* Latency management
+     */
+    
+    struct LatencyRange {
+       uint32_t min;
+       uint32_t max;
+    };
+    
+    virtual void          set_latency_range (PortHandle, int dir, LatencyRange) = 0;
+    virtual LatencyRange  get_latency_range (PortHandle, int dir) = 0;
+    virtual LatencyRange  get_connected_latency_range (PortHandle, int dir) = 0;
+
+    virtual void* get_buffer (PortHandle, pframes_t) = 0;
+
+    virtual pframes_t last_frame_time () const = 0;
+};
+
+}
+
+#endif /* __libardour_port_engine_h__ */
index f6aedc02a17fad709a41e51aa210f9df7f9f41b0..399ab46b34b25c9dbd8d3a97f12875a30a7152c7 100644 (file)
 #include "pbd/rcu.h"
 
 #include "ardour/chan_count.h"
+#include "ardour/port.h"
+#include "ardour/port_engine.h"
 
 namespace ARDOUR {
 
-class Port;
-
 class PortManager 
 {
   public:
@@ -44,36 +44,44 @@ class PortManager
     
     PortManager();
     virtual ~PortManager() {}
+
+    PortEngine& port_engine() { return *_impl; }
     
     /* Port registration */
     
-    virtual boost::shared_ptr<Port> register_input_port (DataType, const std::string& portname) = 0;
-    virtual boost::shared_ptr<Port> register_output_port (DataType, const std::string& portname) = 0;
-    virtual int unregister_port (boost::shared_ptr<Port>) = 0;
+    boost::shared_ptr<Port> register_input_port (DataType, const std::string& portname);
+    boost::shared_ptr<Port> register_output_port (DataType, const std::string& portname);
+    int unregister_port (boost::shared_ptr<Port>);
     
     /* Port connectivity */
     
-    virtual int connect (const std::string& source, const std::string& destination) = 0;
-    virtual int disconnect (const std::string& source, const std::string& destination) = 0;
-    virtual int disconnect (boost::shared_ptr<Port>) = 0;
-    
+    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 connected (const std::string&);
+
     /* other Port management */
     
-    virtual bool port_is_physical (const std::string&) const = 0;
-    virtual void get_physical_outputs (DataType type, std::vector<std::string>&) = 0;
-    virtual void get_physical_inputs (DataType type, std::vector<std::string>&) = 0;
-    virtual boost::shared_ptr<Port> get_port_by_name (const std::string &) = 0;
-    virtual void port_renamed (const std::string&, const std::string&) = 0;
-    virtual ChanCount n_physical_outputs () const = 0;
-    virtual ChanCount n_physical_inputs () const = 0;
-    virtual const char ** get_ports (const std::string& port_name_pattern, const std::string& type_name_pattern, uint32_t flags) = 0;
+    bool port_is_physical (const std::string&) const;
+    void get_physical_outputs (DataType type, std::vector<std::string>&);
+    void get_physical_inputs (DataType type, std::vector<std::string>&);
+    boost::shared_ptr<Port> get_port_by_name (const std::string &);
+    void port_renamed (const std::string&, const std::string&);
+    ChanCount n_physical_outputs () const;
+    ChanCount n_physical_inputs () const;
+    const char ** get_ports (const std::string& port_name_pattern, const std::string& type_name_pattern, uint32_t flags);
     
     void remove_all_ports ();
     
     /* per-Port monitoring */
     
-    virtual bool can_request_input_monitoring () const = 0;
-    virtual void request_input_monitoring (const std::string&, bool) const = 0;
+    bool can_request_input_monitoring () const;
+    void request_input_monitoring (const std::string&, bool) const;
+    void ensure_input_monitoring (const std::string&, bool) const;
+
+    std::string make_port_name_relative (const std::string&) const;
+    std::string make_port_name_non_relative (const std::string&) const;
+    bool port_is_mine (const std::string&) const;
     
     class PortRegistrationFailure : public std::exception {
       public:
@@ -82,23 +90,17 @@ class PortManager
        
        ~PortRegistrationFailure () throw () {}
        
-       virtual const char *what() const throw () { return reason.c_str(); }
+       const char *what() const throw () { return reason.c_str(); }
        
       private:
        std::string reason;
     };
 
+
   protected:
-    typedef void* PortHandle;
-    PortHandle register (const std::string&, DataType type, Port::Flags);
-    void  unregister (PortHandle);
-    bool  connected (PortHandle);
-    int   disconnect_all (PortHandle);
-    bool  connected_to (PortHandle, const std::string);
-    int   get_connections (PortHandle, std::vector<std::string>&);
-
-  private:
+    PortEngine* _impl;
     SerializedRCUManager<Ports> ports;
+
     boost::shared_ptr<Port> register_port (DataType type, const std::string& portname, bool input);
     void port_registration_failure (const std::string& portname);
 };
index 11cdb79575038619cb1e435647a6941d5c5e3c44..390f1e4fec21f425857ecdbc1af8633f01e33aa8 100644 (file)
@@ -584,6 +584,25 @@ namespace ARDOUR {
                FadeSymmetric,
        };
 
+       enum TransportState {
+               /* these values happen to match the constants used by JACK but
+                  this equality cannot be assumed.
+               */
+               TransportStopped = 0,
+               TransportRolling = 1, 
+               TransportLooping = 2, 
+               TransportStarting = 3,
+       };
+
+       enum PortFlags {
+               /* these values happen to match the constants used by JACK but
+                  this equality cannot be assumed.
+               */
+               IsInput = 1, 
+               IsOutput = 2,
+       };
+
+
 } // namespace ARDOUR
 
 
index c302e06681ca05f394b14c7451eafafb6e27501b..5c98271e5fc162e81f29001b4d98b8171f7b7da7 100644 (file)
@@ -1729,7 +1729,7 @@ AudioDiskstream::prep_record_enable ()
        if (Config->get_monitoring_model() == HardwareMonitoring) {
 
                for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan) {
-                       (*chan)->source.request_jack_monitors_input (!(_session.config.get_auto_input() && rolling));
+                       (*chan)->source.request_input_monitoring (!(_session.config.get_auto_input() && rolling));
                        capturing_sources.push_back ((*chan)->write_source);
                        (*chan)->write_source->mark_streaming_write_started ();
                }
@@ -1750,7 +1750,7 @@ AudioDiskstream::prep_record_disable ()
        boost::shared_ptr<ChannelList> c = channels.reader();
        if (Config->get_monitoring_model() == HardwareMonitoring) {
                for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan) {
-                       (*chan)->source.request_jack_monitors_input (false);
+                       (*chan)->source.request_input_monitoring (false);
                }
        }
        capturing_sources.clear ();
@@ -2016,12 +2016,12 @@ AudioDiskstream::allocate_temporary_buffers ()
 }
 
 void
-AudioDiskstream::request_jack_monitors_input (bool yn)
+AudioDiskstream::request_input_monitoring (bool yn)
 {
        boost::shared_ptr<ChannelList> c = channels.reader();
 
        for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan) {
-               (*chan)->source.request_jack_monitors_input (yn);
+               (*chan)->source.request_input_monitoring (yn);
        }
 }
 
@@ -2344,13 +2344,13 @@ AudioDiskstream::ChannelSource::is_physical () const
 }
 
 void
-AudioDiskstream::ChannelSource::request_jack_monitors_input (bool yn) const
+AudioDiskstream::ChannelSource::request_input_monitoring (bool yn) const
 {
        if (name.empty()) {
                return;
        }
 
-       return AudioEngine::instance()->request_jack_monitors_input (name, yn);
+       return AudioEngine::instance()->request_input_monitoring (name, yn);
 }
 
 AudioDiskstream::ChannelInfo::ChannelInfo (framecnt_t playback_bufsize, framecnt_t capture_bufsize, framecnt_t speed_size, framecnt_t wrap_size)
index 240224ea5e5b33112ae3e72f5e6c21ca5851eac8..6a86360b6937522333d77d84daa0fe5c3f0322cb 100644 (file)
 #include "pbd/stacktrace.h"
 
 #include "ardour/audio_buffer.h"
+#include "ardour/audioengine.h"
 #include "ardour/audio_port.h"
 #include "ardour/data_type.h"
+#include "ardour/port_engine.h"
 
 using namespace ARDOUR;
 using namespace std;
 
-AudioPort::AudioPort (const std::string& name, Flags flags)
+#define port_engine AudioEngine::instance()->port_engine()
+
+AudioPort::AudioPort (const std::string& name, PortFlags flags)
        : Port (name, DataType::AUDIO, flags)
        , _buffer (new AudioBuffer (0))
 {
@@ -73,7 +77,7 @@ AudioBuffer&
 AudioPort::get_audio_buffer (pframes_t nframes)
 {
        /* caller must hold process lock */
-       _buffer->set_data ((Sample *) jack_port_get_buffer (_jack_port, _cycle_nframes) +
+       _buffer->set_data ((Sample *) port_engine.get_buffer (_port_handle, _cycle_nframes) +
                           _global_port_buffer_offset + _port_buffer_offset, nframes);
        return *_buffer;
 }
@@ -82,7 +86,7 @@ Sample*
 AudioPort::engine_get_whole_audio_buffer ()
 {
        /* caller must hold process lock */
-       return (Sample *) jack_port_get_buffer (_jack_port, _cycle_nframes);
+       return (Sample *) port_engine.get_buffer (_port_handle, _cycle_nframes);
 }
 
 
index 25a55b5aaf01bb19cc9adb9ecc15891ace852be4..1e43c590a0fb8c3d7cac829607c8acf25bf2d48c 100644 (file)
 #include <sstream>
 
 #include <glibmm/timer.h>
+#include <glibmm/pattern.h>
+#include <glibmm/module.h>
 
+#include "pbd/epa.h"
+#include "pbd/file_utils.h"
 #include "pbd/pthread_utils.h"
 #include "pbd/stacktrace.h"
 #include "pbd/unknown_type.h"
-#include "pbd/epa.h"
 
 #include <jack/weakjack.h>
 
@@ -39,7 +42,9 @@
 #include "midi++/manager.h"
 
 #include "ardour/audio_port.h"
+#include "ardour/audio_backend.h"
 #include "ardour/audioengine.h"
+#include "ardour/backend_search_path.h"
 #include "ardour/buffer.h"
 #include "ardour/cycle_timer.h"
 #include "ardour/internal_send.h"
@@ -58,8 +63,9 @@ using namespace PBD;
 gint AudioEngine::m_meter_exit;
 AudioEngine* AudioEngine::_instance = 0;
 
-AudioEngine::AudioEngine ()
-       : session_remove_pending (false)
+AudioEngine::AudioEngine (const std::string& bcn, const std::string& bsu)
+       : _backend (0)
+       , session_remove_pending (false)
        , session_removal_countdown (-1)
        , monitor_check_interval (INT32_MAX)
        , last_monitor_check (0)
@@ -70,14 +76,16 @@ AudioEngine::AudioEngine ()
        , port_remove_in_progress (false)
        , m_meter_thread (0)
        , _main_thread (0)
+       , backend_client_name (bcn)
+       , backend_session_uuid (bsu)
 {
        g_atomic_int_set (&m_meter_exit, 0);
-
-       Port::set_engine (this);
 }
 
 AudioEngine::~AudioEngine ()
 {
+       drop_backend ();
+
        config_connection.disconnect ();
 
        {
@@ -88,18 +96,38 @@ AudioEngine::~AudioEngine ()
 }
 
 AudioEngine*
-AudioEngine::create ()
+AudioEngine::create (const std::string& bcn, const std::string& bsu)
 {
        if (_instance) {
                return _instance;
        }
-       return new AudioEngine;
+       return new AudioEngine (bcn, bsu);
 }
 
-jack_client_t*
-AudioEngine::jack() const
+void
+AudioEngine::drop_backend ()
 {
-       return _jack;
+       if (_backend) {
+               _backend->stop ();
+               delete _backend;
+               _backend = 0;
+       }
+}
+
+int
+AudioEngine::set_backend (const std::string& name)
+{
+       BackendMap::iterator b = _backends.find (name);
+
+       if (b == _backends.end()) {
+               return -1;
+       }
+
+       drop_backend ();
+
+       _backend = b->second;
+
+       return 0;
 }
 
 void
@@ -120,70 +148,6 @@ _thread_init_callback (void * /*arg*/)
 }
 
 
-int
-AudioEngine::start ()
-{
-       GET_PRIVATE_JACK_POINTER_RET (_jack, -1);
-
-       if (!_running) {
-
-                if (!jack_port_type_get_buffer_size) {
-                        warning << _("This version of JACK is old - you should upgrade to a newer version that supports jack_port_type_get_buffer_size()") << endmsg;
-               }
-
-               if (_session) {
-                       BootMessage (_("Connect session to engine"));
-                       _session->set_frame_rate (jack_get_sample_rate (_priv_jack));
-               }
-
-                /* a proxy for whether jack_activate() will definitely call the buffer size
-                 * callback. with older versions of JACK, this function symbol will be null.
-                 * this is reliable, but not clean.
-                 */
-
-                if (!jack_port_type_get_buffer_size) {
-                       jack_bufsize_callback (jack_get_buffer_size (_priv_jack));
-                }
-               
-               _processed_frames = 0;
-               last_monitor_check = 0;
-
-                set_jack_callbacks ();
-
-               if (jack_activate (_priv_jack) == 0) {
-                       _running = true;
-                       _has_run = true;
-                       Running(); /* EMIT SIGNAL */
-               } else {
-                       // error << _("cannot activate JACK client") << endmsg;
-               }
-       }
-               
-       return _running ? 0 : -1;
-}
-
-int
-AudioEngine::stop (bool forever)
-{
-       GET_PRIVATE_JACK_POINTER_RET (_jack, -1);
-
-       if (_priv_jack) {
-               if (forever) {
-                       disconnect_from_jack ();
-               } else {
-                       jack_deactivate (_priv_jack);
-                       MIDI::JackMIDIPort::JackHalted (); /* EMIT SIGNAL */
-                       Stopped(); /* EMIT SIGNAL */
-               }
-       }
-
-        if (forever) {
-                stop_metering_thread ();
-        }
-
-       return _running ? -1 : 0;
-}
-
 
 void
 AudioEngine::split_cycle (pframes_t offset)
@@ -208,7 +172,6 @@ AudioEngine::split_cycle (pframes_t offset)
 int
 AudioEngine::process_callback (pframes_t nframes)
 {
-       GET_PRIVATE_JACK_POINTER_RET(_jack,0);
        Glib::Threads::Mutex::Lock tm (_process_lock, Glib::Threads::TRY_LOCK);
 
        PT_TIMING_REF;
@@ -436,7 +399,7 @@ AudioEngine::set_session (Session *s)
 
                start_metering_thread ();
 
-               pframes_t blocksize = jack_get_buffer_size (_jack);
+               pframes_t blocksize = _backend->get_buffer_size ();
 
                /* page in as much of the session process code as we
                   can before we really start running.
@@ -484,549 +447,290 @@ AudioEngine::remove_session ()
        remove_all_ports ();
 }
 
+
 void
-AudioEngine::port_registration_failure (const std::string& portname)
+AudioEngine::died ()
 {
-       GET_PRIVATE_JACK_POINTER (_jack);
-       string full_portname = jack_client_name;
-       full_portname += ':';
-       full_portname += portname;
-
-
-       jack_port_t* p = jack_port_by_name (_priv_jack, full_portname.c_str());
-       string reason;
+        /* called from a signal handler for SIGPIPE */
 
-       if (p) {
-               reason = string_compose (_("a port with the name \"%1\" already exists: check for duplicated track/bus names"), portname);
-       } else {
-               reason = string_compose (_("No more JACK ports are available. You will need to stop %1 and restart JACK with more ports if you need this many tracks."), PROGRAM_NAME);
-       }
+       stop_metering_thread ();
 
-       throw PortRegistrationFailure (string_compose (_("AudioEngine: cannot register port \"%1\": %2"), portname, reason).c_str());
+        _running = false;
+       _buffer_size = 0;
+       _frame_rate = 0;
 }
 
-boost::shared_ptr<Port>
-AudioEngine::register_port (DataType dtype, const string& portname, bool input)
+int
+AudioEngine::reset_timebase ()
 {
-       boost::shared_ptr<Port> newport;
-
-       try {
-               if (dtype == DataType::AUDIO) {
-                       newport.reset (new AudioPort (portname, (input ? Port::IsInput : Port::IsOutput)));
-               } else if (dtype == DataType::MIDI) {
-                       newport.reset (new MidiPort (portname, (input ? Port::IsInput : Port::IsOutput)));
+       if (_session) {
+               if (_session->config.get_jack_time_master()) {
+                       _backend->set_time_master (true);
                } else {
-                       throw PortRegistrationFailure("unable to create port (unknown type)");
+                       _backend->set_time_master (false);
                }
-
-               RCUWriter<Ports> writer (ports);
-               boost::shared_ptr<Ports> ps = writer.get_copy ();
-               ps->insert (make_pair (make_port_name_relative (portname), newport));
-
-               /* writer goes out of scope, forces update */
-
-               return newport;
-       }
-
-       catch (PortRegistrationFailure& err) {
-               throw err;
-       } catch (std::exception& e) {
-               throw PortRegistrationFailure(string_compose(
-                               _("unable to create port: %1"), e.what()).c_str());
-       } catch (...) {
-               throw PortRegistrationFailure("unable to create port (unknown error)");
        }
+       return 0;
 }
 
-boost::shared_ptr<Port>
-AudioEngine::register_input_port (DataType type, const string& portname)
-{
-       return register_port (type, portname, true);
-}
 
-boost::shared_ptr<Port>
-AudioEngine::register_output_port (DataType type, const string& portname)
+void
+AudioEngine::destroy ()
 {
-       return register_port (type, portname, false);
+       delete _instance;
+       _instance = 0;
 }
 
 int
-AudioEngine::unregister_port (boost::shared_ptr<Port> port)
+AudioEngine::discover_backends ()
 {
-       /* caller must hold process lock */
-
-       if (!_running) {
-               /* 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 ();
-               Ports::iterator x = ps->find (make_port_name_relative (port->name()));
+       vector<std::string> backend_modules;
+       AudioBackend* backend;
 
-               if (x != ps->end()) {
-                       ps->erase (x);
-               }
+       _backends.clear ();
 
-               /* writer goes out of scope, forces update */
-       }
+       Glib::PatternSpec so_extension_pattern("*.so");
+       Glib::PatternSpec dylib_extension_pattern("*.dylib");
 
-       ports.flush ();
+       find_matching_files_in_search_path (backend_search_path (),
+                                           so_extension_pattern, backend_modules);
 
-       return 0;
-}
+       find_matching_files_in_search_path (backend_search_path (),
+                                           dylib_extension_pattern, backend_modules);
 
-int
-AudioEngine::connect (const string& source, const string& destination)
-{
-       int ret;
+       DEBUG_TRACE (DEBUG::Panning, string_compose (_("looking for backends in %1"), backend_search_path().to_string()));
 
-       if (!_running) {
-               if (!_has_run) {
-                       fatal << _("connect called before engine was started") << endmsg;
-                       /*NOTREACHED*/
-               } else {
-                       return -1;
+       for (vector<std::string>::iterator i = backend_modules.begin(); i != backend_modules.end(); ++i) {
+               if ((backend = backend_discover (*i)) != 0) {
+                       _backends.insert (make_pair (backend->name(), backend));
                }
        }
 
-       string s = make_port_name_non_relative (source);
-       string d = make_port_name_non_relative (destination);
-
+       return _backends.size();
+}
 
-       boost::shared_ptr<Port> src = get_port_by_name (s);
-       boost::shared_ptr<Port> dst = get_port_by_name (d);
+AudioBackend*
+AudioEngine::backend_discover (const string& path)
+{
+       Glib::Module* module = new Glib::Module(path);
+       AudioBackend* (*dfunc)(void);
+       void* func = 0;
 
-       if (src) {
-               ret = src->connect (d);
-       } else if (dst) {
-               ret = dst->connect (s);
-       } else {
-               /* neither port is known to us, and this API isn't intended for use as a general patch bay */
-               ret = -1;
+       if (!module) {
+               error << string_compose(_("AudioEngine: cannot load module \"%1\" (%2)"), path,
+                               Glib::Module::get_last_error()) << endmsg;
+               delete module;
+               return 0;
        }
 
-       if (ret > 0) {
-               /* already exists - no error, no warning */
-       } else if (ret < 0) {
-               error << string_compose(_("AudioEngine: cannot connect %1 (%2) to %3 (%4)"),
-                                       source, s, destination, d)
-                     << endmsg;
+       if (!module->get_symbol("backend_factory", func)) {
+               error << string_compose(_("AudioEngine: module \"%1\" has no factory function."), path) << endmsg;
+               error << Glib::Module::get_last_error() << endmsg;
+               delete module;
+               return 0;
        }
 
-       return ret;
+       dfunc = (AudioBackend* (*)(void))func;
+       AudioBackend* backend = dfunc();
+
+       return backend;
 }
 
+/* BACKEND PROXY WRAPPERS */
+
 int
-AudioEngine::disconnect (const string& source, const string& destination)
+AudioEngine::start ()
 {
-       int ret;
-
-       if (!_running) {
-               if (!_has_run) {
-                       fatal << _("disconnect called before engine was started") << endmsg;
-                       /*NOTREACHED*/
-               } else {
-                       return -1;
-               }
+       if (!_backend) {
+               return -1;
        }
 
-       string s = make_port_name_non_relative (source);
-       string d = make_port_name_non_relative (destination);
-
-       boost::shared_ptr<Port> src = get_port_by_name (s);
-       boost::shared_ptr<Port> dst = get_port_by_name (d);
+       if (!_running) {
 
-       if (src) {
-                       ret = src->disconnect (d);
-       } else if (dst) {
-                       ret = dst->disconnect (s);
-       } else {
-               /* neither port is known to us, and this API isn't intended for use as a general patch bay */
-               ret = -1;
-       }
-       return ret;
-}
+               if (_session) {
+                       BootMessage (_("Connect session to engine"));
+                       _session->set_frame_rate (_backend->sample_rate());
+               }
 
-int
-AudioEngine::disconnect (boost::shared_ptr<Port> port)
-{
-       GET_PRIVATE_JACK_POINTER_RET (_jack,-1);
+               _processed_frames = 0;
+               last_monitor_check = 0;
 
-       if (!_running) {
-               if (!_has_run) {
-                       fatal << _("disconnect called before engine was started") << endmsg;
-                       /*NOTREACHED*/
+               if (_backend->start() == 0) {
+                       _running = true;
+                       _has_run = true;
+                       Running(); /* EMIT SIGNAL */
                } else {
-                       return -1;
+                       /* should report error? */
                }
        }
-
-       return port->disconnect_all ();
+               
+       return _running ? 0 : -1;
 }
 
-ARDOUR::framecnt_t
-AudioEngine::frame_rate () const
+int
+AudioEngine::stop ()
 {
-       GET_PRIVATE_JACK_POINTER_RET (_jack, 0);
-       if (_frame_rate == 0) {
-               return (_frame_rate = jack_get_sample_rate (_priv_jack));
-       } else {
-               return _frame_rate;
+       if (!_backend) {
+               return 0;
        }
+       
+       return _backend->stop ();
 }
 
-size_t
-AudioEngine::raw_buffer_size (DataType t)
-{
-       std::map<DataType,size_t>::const_iterator s = _raw_buffer_sizes.find(t);
-       return (s != _raw_buffer_sizes.end()) ? s->second : 0;
-}
-
-ARDOUR::pframes_t
-AudioEngine::frames_per_cycle () const
+int
+AudioEngine::pause ()
 {
-       GET_PRIVATE_JACK_POINTER_RET (_jack,0);
-       if (_buffer_size == 0) {
-               return jack_get_buffer_size (_jack);
-       } else {
-               return _buffer_size;
+       if (!_backend) {
+               return 0;
        }
+       
+       return _backend->pause ();
 }
 
-/** @param name Full or short name of port
- *  @return Corresponding Port or 0.
- */
-
-boost::shared_ptr<Port>
-AudioEngine::get_port_by_name (const string& portname)
+int
+AudioEngine::freewheel (bool start_stop)
 {
-       if (!_running) {
-               if (!_has_run) {
-                       fatal << _("get_port_by_name() called before engine was started") << endmsg;
-                       /*NOTREACHED*/
-               } else {
-                       boost::shared_ptr<Port> ();
-               }
+       if (!_backend) {
+               return -1;
        }
 
-        if (!port_is_mine (portname)) {
-                /* not an ardour port */
-                return boost::shared_ptr<Port> ();
-        }
-
-       boost::shared_ptr<Ports> pr = ports.reader();
-       std::string rel = make_port_name_relative (portname);
-       Ports::iterator x = pr->find (rel);
+       /* _freewheeling will be set when first Freewheel signal occurs */
 
-       if (x != pr->end()) {
-               /* its possible that the port was renamed by some 3rd party and
-                  we don't know about it. check for this (the check is quick
-                  and cheap), and if so, rename the port (which will alter
-                  the port map as a side effect).
-               */
-               const std::string check = make_port_name_relative (jack_port_name (x->second->jack_port()));
-               if (check != rel) {
-                       x->second->set_name (check);
-               }
-               return x->second;
-       }
-
-        return boost::shared_ptr<Port> ();
+       return _backend->freewheel (start_stop);
 }
 
-void
-AudioEngine::port_renamed (const std::string& old_relative_name, const std::string& new_relative_name)
+float
+AudioEngine::get_cpu_load() const 
 {
-       RCUWriter<Ports> writer (ports);
-       boost::shared_ptr<Ports> p = writer.get_copy();
-       Ports::iterator x = p->find (old_relative_name);
-       
-       if (x != p->end()) {
-               boost::shared_ptr<Port> port = x->second;
-               p->erase (x);
-               p->insert (make_pair (new_relative_name, port));
+       if (!_backend) {
+               return 0.0;
        }
+       return _backend->get_cpu_load ();
 }
 
-const char **
-AudioEngine::get_ports (const string& port_name_pattern, const string& type_name_pattern, uint32_t flags)
+void
+AudioEngine::transport_start ()
 {
-       GET_PRIVATE_JACK_POINTER_RET (_jack,0);
-       if (!_running) {
-               if (!_has_run) {
-                       fatal << _("get_ports called before engine was started") << endmsg;
-                       /*NOTREACHED*/
-               } else {
-                       return 0;
-               }
+       if (!_backend) {
+               return;
        }
-       return jack_get_ports (_priv_jack, port_name_pattern.c_str(), type_name_pattern.c_str(), flags);
+       return _backend->transport_start ();
 }
 
 void
-AudioEngine::died ()
-{
-        /* called from a signal handler for SIGPIPE */
-
-       stop_metering_thread ();
-
-        _running = false;
-       _buffer_size = 0;
-       _frame_rate = 0;
-       _jack = 0;
-}
-
-bool
-AudioEngine::can_request_hardware_monitoring ()
+AudioEngine::transport_stop ()
 {
-       GET_PRIVATE_JACK_POINTER_RET (_jack,false);
-       const char ** ports;
-
-       if ((ports = jack_get_ports (_priv_jack, NULL, JACK_DEFAULT_AUDIO_TYPE, JackPortCanMonitor)) == 0) {
-               return false;
+       if (!_backend) {
+               return;
        }
-
-       free (ports);
-
-       return true;
+       return _backend->transport_stop ();
 }
 
-ChanCount
-AudioEngine::n_physical (unsigned long flags) const
+TransportState
+AudioEngine::transport_state ()
 {
-       ChanCount c;
-
-       GET_PRIVATE_JACK_POINTER_RET (_jack, c);
-
-       const char ** ports = jack_get_ports (_priv_jack, NULL, NULL, JackPortIsPhysical | flags);
-       if (ports == 0) {
-               return c;
+       if (!_backend) {
+               return TransportStopped;
        }
-
-       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])));
-                       c.set (t, c.get (t) + 1);
-               }
-       }
-
-       free (ports);
-
-       return c;
-}
-
-ChanCount
-AudioEngine::n_physical_inputs () const
-{
-       return n_physical (JackPortIsInput);
-}
-
-ChanCount
-AudioEngine::n_physical_outputs () const
-{
-       return n_physical (JackPortIsOutput);
+       return _backend->transport_state ();
 }
 
 void
-AudioEngine::get_physical (DataType type, unsigned long flags, vector<string>& phy)
+AudioEngine::transport_locate (framepos_t pos)
 {
-       GET_PRIVATE_JACK_POINTER (_jack);
-       const char ** ports;
-
-       if ((ports = jack_get_ports (_priv_jack, NULL, type.to_jack_type(), JackPortIsPhysical | flags)) == 0) {
+       if (!_backend) {
                return;
        }
+       return _backend->transport_locate (pos);
+}
 
-       if (ports) {
-               for (uint32_t i = 0; ports[i]; ++i) {
-                        if (strstr (ports[i], "Midi-Through")) {
-                                continue;
-                        }
-                       phy.push_back (ports[i]);
-               }
-               free (ports);
+framepos_t
+AudioEngine::transport_frame()
+{
+       if (!_backend) {
+               return 0;
        }
+       return _backend->transport_frame ();
 }
 
-/** Get physical ports for which JackPortIsOutput is set; ie those that correspond to
- *  a physical input connector.
- */
-void
-AudioEngine::get_physical_inputs (DataType type, vector<string>& ins)
+framecnt_t
+AudioEngine::sample_rate () const
 {
-       get_physical (type, JackPortIsOutput, ins);
+       if (!_backend) {
+               return 0;
+       }
+       return _backend->sample_rate ();
 }
 
-/** Get physical ports for which JackPortIsInput is set; ie those that correspond to
- *  a physical output connector.
- */
-void
-AudioEngine::get_physical_outputs (DataType type, vector<string>& outs)
+pframes_t
+AudioEngine::samples_per_cycle () const
 {
-       get_physical (type, JackPortIsInput, outs);
+       if (!_backend) {
+               return 0;
+       }
+       return _backend->samples_per_cycle ();
 }
 
-
 int
-AudioEngine::reset_timebase ()
+AudioEngine::usecs_per_cycle () const
 {
-       GET_PRIVATE_JACK_POINTER_RET (_jack, -1);
-       if (_session) {
-               if (_session->config.get_jack_time_master()) {
-                       _backend->set_time_master (true);
-               } else {
-                       _backend->set_time_master (false);
-               }
+       if (!_backend) {
+               return -1;
        }
-       return 0;
+       return _backend->start ();
 }
 
-void
-AudioEngine::remove_all_ports ()
+size_t
+AudioEngine::raw_buffer_size (DataType t)
 {
-       /* make sure that JACK callbacks that will be invoked as we cleanup
-        * ports know that they have nothing to do.
-        */
-
-       port_remove_in_progress = true;
-
-       /* process lock MUST be held by caller
-       */
-
-       {
-               RCUWriter<Ports> writer (ports);
-               boost::shared_ptr<Ports> ps = writer.get_copy ();
-               ps->clear ();
+       if (!_backend) {
+               return -1;
        }
-
-       /* clear dead wood list in RCU */
-
-       ports.flush ();
-
-       port_remove_in_progress = false;
+       return _backend->raw_buffer_size (t);
 }
 
-
-string
-AudioEngine::make_port_name_relative (string portname) const
+pframes_t
+AudioEngine::sample_time ()
 {
-       string::size_type len;
-       string::size_type n;
-
-       len = portname.length();
-
-       for (n = 0; n < len; ++n) {
-               if (portname[n] == ':') {
-                       break;
-               }
-       }
-
-       if ((n != len) && (portname.substr (0, n) == jack_client_name)) {
-               return portname.substr (n+1);
+       if (!_backend) {
+               return 0;
        }
-
-       return portname;
+       return _backend->sample_time ();
 }
 
-string
-AudioEngine::make_port_name_non_relative (string portname) const
+pframes_t
+AudioEngine::sample_time_at_cycle_start ()
 {
-       string str;
-
-       if (portname.find_first_of (':') != string::npos) {
-               return portname;
+       if (!_backend) {
+               return 0;
        }
-
-       str  = jack_client_name;
-       str += ':';
-       str += portname;
-
-       return str;
+       return _backend->sample_time_at_cycle_start ();
 }
 
-bool
-AudioEngine::port_is_mine (const string& portname) const
+pframes_t
+AudioEngine::samples_since_cycle_start ()
 {
-       if (portname.find_first_of (':') != string::npos) {
-               if (portname.substr (0, jack_client_name.length ()) != jack_client_name) {
-                        return false;
-                }
-        }
-        return true;
+       if (!_backend) {
+               return 0;
+       }
+       return _backend->samples_since_cycle_start ();
 }
 
 bool
-AudioEngine::port_is_physical (const std::string& portname) const
-{
-        GET_PRIVATE_JACK_POINTER_RET(_jack, false);
-
-        jack_port_t *port = jack_port_by_name (_priv_jack, portname.c_str());
-
-        if (!port) {
-                return false;
-        }
-
-        return jack_port_flags (port) & JackPortIsPhysical;
-}
-
-void
-AudioEngine::destroy ()
+AudioEngine::get_sync_offset (pframes_t& offset) const
 {
-       delete _instance;
-       _instance = 0;
+       if (!_backend) {
+               return false;
+       }
+       return _backend->get_sync_offset (offset);
 }
 
 int
-AudioEngine::discover_backends ()
+AudioEngine::create_process_thread (boost::function<void()> func, pthread_t* thr, size_t stacksize)
 {
-       vector<std::string> backend_modules;
-       AudioBackend* backend;
-
-       Glib::PatternSpec so_extension_pattern("*.so");
-       Glib::PatternSpec dylib_extension_pattern("*.dylib");
-
-       find_matching_files_in_search_path (backend_search_path (),
-                                           so_extension_pattern, backend_modules);
-
-       find_matching_files_in_search_path (backend_search_path (),
-                                           dylib_extension_pattern, backend_modules);
-
-       DEBUG_TRACE (DEBUG::Panning, string_compose (_("looking for backends in %1"), backend_search_path().to_string()));
-
-       for (vector<std::string>::iterator i = backend_modules.begin(); i != backend_modules.end(); ++i) {
-               if ((backend = backend_discover (*i)) != 0) {
-                       _backends.insert (make_pair (backend->name(), backend));
-               }
+       if (!_backend) {
+               return -1;
        }
+       return _backend->create_process_thread (func, thr, stacksize);
 }
 
-AudioBackend*
-AudioEngine::backend_discover (string path)
-{
-       Glib::Module* module = new Glib::Module(path);
-       AudioBackend* (*dfunc)(void);
-       void* func = 0;
-
-       if (!module) {
-               error << string_compose(_("AudioEngine: cannot load module \"%1\" (%2)"), path,
-                               Glib::Module::get_last_error()) << endmsg;
-               delete module;
-               return 0;
-       }
-
-       if (!module->get_symbol("backend_factory", func)) {
-               error << string_compose(_("AudioEngine: module \"%1\" has no factory function."), path) << endmsg;
-               error << Glib::Module::get_last_error() << endmsg;
-               delete module;
-               return 0;
-       }
-
-       dfunc = (AudioBackend* (*)(void))func;
-       AudioBackend* backend = dfunc();
-
-       return backend;
-}
diff --git a/libs/ardour/backend_search_path.cc b/libs/ardour/backend_search_path.cc
new file mode 100644 (file)
index 0000000..9a04250
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+    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 <glibmm/miscutils.h>
+
+#include "ardour/backend_search_path.h"
+#include "ardour/directory_names.h"
+#include "ardour/filesystem_paths.h"
+
+namespace {
+       const char * const backend_env_variable_name = "ARDOUR_BACKEND_PATH";
+} // anonymous
+
+using namespace PBD;
+
+namespace ARDOUR {
+
+SearchPath
+backend_search_path ()
+{
+       SearchPath spath(user_config_directory ());
+       spath += ardour_dll_directory ();
+       spath.add_subdirectory_to_paths(backend_dir_name);
+
+       spath += SearchPath(Glib::getenv(backend_env_variable_name));
+       return spath;
+}
+
+} // namespace ARDOUR
index 0ac62d70762d6a78fbccd8b692bfecee97728810..9d5640491f8aeee229ade4d6cb3678388ecd6d70 100644 (file)
@@ -454,16 +454,13 @@ Bundle::connected_to_anything (AudioEngine& engine)
                Bundle::PortList const & ports = channel_ports (i);
 
                for (uint32_t j = 0; j < ports.size(); ++j) {
-                       /* ports[j] may not be an Ardour port, so use JACK directly
+
+                       /* ports[j] may not be an Ardour port, so use the port manager directly
                           rather than doing it with Port.
                        */
-                       jack_port_t* jp = jack_port_by_name (engine.jack(), ports[j].c_str());
-                       if (jp) {
-                               const char ** c = jack_port_get_all_connections (engine.jack(), jp);
-                               if (c) {
-                                       jack_free (c);
-                                       return true;
-                               }
+
+                       if (engine.connected (ports[j])) {
+                               return true;
                        }
                }
        }
index c4b463aba7f2ee3b4f110ebcf92de25a42a6680b..f14e01809765af1045ff9fa4a2123385fc421b50 100644 (file)
@@ -28,7 +28,7 @@ namespace ARDOUR {
 
 CapturingProcessor::CapturingProcessor (Session & session)
        : Processor (session, X_("capture point"))
-       , block_size (session.engine().frames_per_cycle())
+       , block_size (AudioEngine::instance()->samples_per_cycle())
 {
        realloc_buffers ();
 }
index 0632c6f8f25c6534bf8db83bf22d63616c550afd..af7f7f550c33cf9fe1ac57256cad27819098750f 100644 (file)
@@ -37,6 +37,7 @@ const char* const templates_dir_name = X_("templates");
 const char* const route_templates_dir_name = X_("route_templates");
 const char* const surfaces_dir_name = X_("surfaces");
 const char* const panner_dir_name = X_("panners");
+const char* const backend_dir_name = X_("backends");
 
 /* these should end up using variants of PROGRAM_NAME */
 #ifdef __APPLE__
index 9b3f50e85d85906e728433fa51876bf39647283e..82e5d80244ff21d63f40277addc117822aef5c0d 100644 (file)
@@ -117,7 +117,7 @@ RegionExportChannelFactory::RegionExportChannelFactory (Session * session, Audio
        : region (region)
        , track (track)
        , type (type)
-       , frames_per_cycle (session->engine().frames_per_cycle ())
+       , frames_per_cycle (session->engine().samples_per_cycle ())
        , buffers_up_to_date (false)
        , region_start (region.position())
        , position (region_start)
index c7875c0b9b62ab1429f2e5ce23cc93d830f42f9d..301914b0ae0b6ae70cd0f3a36d6f3f4b8d32a944 100644 (file)
@@ -54,7 +54,7 @@ ExportGraphBuilder::ExportGraphBuilder (Session const & session)
   : session (session)
   , thread_pool (hardware_concurrency())
 {
-       process_buffer_frames = session.engine().frames_per_cycle();
+       process_buffer_frames = session.engine().samples_per_cycle();
 }
 
 ExportGraphBuilder::~ExportGraphBuilder ()
@@ -505,7 +505,7 @@ ExportGraphBuilder::ChannelConfig::ChannelConfig (ExportGraphBuilder & parent, F
 
        config = new_config;
 
-       framecnt_t max_frames = parent.session.engine().frames_per_cycle();
+       framecnt_t max_frames = parent.session.engine().samples_per_cycle();
        interleaver.reset (new Interleaver<Sample> ());
        interleaver->init (new_config.channel_config->get_n_chans(), max_frames);
 
index 4c91956ffda0d1151f98b34e43dd27899578b5eb..b2833db4fa521a397bcc7f49e587e9e9a65fc7d1 100644 (file)
@@ -338,7 +338,7 @@ void
 ARDOUR::init_post_engine ()
 {
        /* the MIDI Manager is needed by the ControlProtocolManager */
-       MIDI::Manager::create (AudioEngine::instance()->jack());
+       MIDI::Manager::create (AudioEngine::instance()->port_engine());
 
        ControlProtocolManager::instance().discover_control_protocols ();
 
index 26631d0fadc031e9998fa274f492d11e1b09bae1..4b8c469a9df517d9b944ceb07cf1590bcce4a98c 100644 (file)
@@ -310,7 +310,7 @@ bool
 InternalSend::configure_io (ChanCount in, ChanCount out)
 {
        bool ret = Send::configure_io (in, out);
-       set_block_size (_session.engine().frames_per_cycle());
+       set_block_size (_session.engine().samples_per_cycle());
        return ret;
 }
 
index 2d614a80a04549c9e8763570be437019ecd14295..46e270f0cad7dc9700c1688081396d47875dad98 100644 (file)
@@ -6,12 +6,43 @@
 int
 JACKAudioBackend::start ()
 {
-       Glib::Threads::Mutex::Lock lm (_state_lock);
+       GET_PRIVATE_JACK_POINTER_RET (_jack, -1);
+
+       if (!_running) {
+
+                if (!jack_port_type_get_buffer_size) {
+                        warning << _("This version of JACK is old - you should upgrade to a newer version that supports jack_port_type_get_buffer_size()") << endmsg;
+               }
+
+               if (_session) {
+                       BootMessage (_("Connect session to engine"));
+                       _session->set_frame_rate (jack_get_sample_rate (_priv_jack));
+               }
+
+                /* a proxy for whether jack_activate() will definitely call the buffer size
+                 * callback. with older versions of JACK, this function symbol will be null.
+                 * this is reliable, but not clean.
+                 */
+
+                if (!jack_port_type_get_buffer_size) {
+                       jack_bufsize_callback (jack_get_buffer_size (_priv_jack));
+                }
+               
+               _processed_frames = 0;
+               last_monitor_check = 0;
 
-       if (running()) {
-               /* already running */
-               return 1;
+                set_jack_callbacks ();
+
+               if (jack_activate (_priv_jack) == 0) {
+                       _running = true;
+                       _has_run = true;
+                       Running(); /* EMIT SIGNAL */
+               } else {
+                       // error << _("cannot activate JACK client") << endmsg;
+               }
        }
+               
+       return _running ? 0 : -1;
 }
 
 int
@@ -70,6 +101,39 @@ JACKAudioBackend::get_parameters (Parameters& params) const
        return 0;
 }
 
+/* parameters */
+
+ARDOUR::pframes_t
+AudioEngine::frames_per_cycle () const
+{
+       GET_PRIVATE_JACK_POINTER_RET (_jack,0);
+       if (_buffer_size == 0) {
+               return jack_get_buffer_size (_jack);
+       } else {
+               return _buffer_size;
+       }
+}
+
+ARDOUR::framecnt_t
+AudioEngine::frame_rate () const
+{
+       GET_PRIVATE_JACK_POINTER_RET (_jack, 0);
+       if (_frame_rate == 0) {
+               return (_frame_rate = jack_get_sample_rate (_priv_jack));
+       } else {
+               return _frame_rate;
+       }
+}
+
+size_t
+AudioEngine::raw_buffer_size (DataType t)
+{
+       std::map<DataType,size_t>::const_iterator s = _raw_buffer_sizes.find(t);
+       return (s != _raw_buffer_sizes.end()) ? s->second : 0;
+}
+
+
+
 /*--- private support methods ---*/
 
 int
@@ -539,8 +603,8 @@ JACKAudioBackend::process_thread ()
                 GET_PRIVATE_JACK_POINTER_RET(_jack,0);
 
                 pframes_t nframes = jack_cycle_wait (_priv_jack);
-
-                if (process_callback (nframes)) {
+               
+                if (engine.process_callback (nframes)) {
                         return 0;
                 }
 
index 8d08fd6bb5ab9184e77ba559d65ed6843af0bf7a..fecab5b6061e89cfceb595a1948ec0fa4628cd4f 100644 (file)
@@ -420,15 +420,15 @@ bool
 LTC_Slave::speed_and_position (double& speed, framepos_t& pos)
 {
        bool engine_init_called = false;
-       framepos_t now = session.engine().frame_time_at_cycle_start();
+       framepos_t now = session.engine().sample_time_at_cycle_start();
        framepos_t sess_pos = session.transport_frame(); // corresponds to now
-       framecnt_t nframes = session.engine().frames_per_cycle();
+       framecnt_t nframes = session.engine().samples_per_cycle();
 
-       jack_default_audio_sample_t *in;
+       Sample* in;
 
        boost::shared_ptr<Port> ltcport = session.ltc_input_port();
 
-       in = (jack_default_audio_sample_t*) jack_port_get_buffer (ltcport->jack_port(), nframes);
+       in = (Sample*) AudioEngine::instance()->port_engine().get_buffer (ltcport->port_handle(), nframes);
 
        frameoffset_t skip = now - (monotonic_cnt + nframes);
        monotonic_cnt = now;
@@ -441,7 +441,7 @@ LTC_Slave::speed_and_position (double& speed, framepos_t& pos)
        else if (engine_dll_initstate != transport_direction && ltc_speed != 0) {
                engine_dll_initstate = transport_direction;
                init_engine_dll(last_ltc_frame + rint(ltc_speed * double(2 * nframes + now - last_timestamp)),
-                               session.engine().frames_per_cycle());
+                               session.engine().samples_per_cycle());
                engine_init_called = true;
        }
 
@@ -521,8 +521,8 @@ LTC_Slave::speed_and_position (double& speed, framepos_t& pos)
                t0 = t1;
                t1 += b * e + e2;
                e2 += c * e;
-               speed_flt = (t1 - t0) / double(session.engine().frames_per_cycle());
-               DEBUG_TRACE (DEBUG::LTC, string_compose ("LTC engine DLL t0:%1 t1:%2 err:%3 spd:%4 ddt:%5\n", t0, t1, e, speed_flt, e2 - session.engine().frames_per_cycle() ));
+               speed_flt = (t1 - t0) / double(session.engine().samples_per_cycle());
+               DEBUG_TRACE (DEBUG::LTC, string_compose ("LTC engine DLL t0:%1 t1:%2 err:%3 spd:%4 ddt:%5\n", t0, t1, e, speed_flt, e2 - session.engine().samples_per_cycle() ));
        } else {
                DEBUG_TRACE (DEBUG::LTC, string_compose ("LTC adjusting elapsed (no DLL) from %1 by %2\n", elapsed, (2 * nframes * ltc_speed)));
                speed_flt = 0;
index b47c3ca1523ff4ee3b8a3f7e4d2ac853adbfe1f8..0b0e61000de81cbfd5af13e6e11c26fc3f570761 100644 (file)
@@ -190,55 +190,6 @@ MidiBuffer::push_back(TimeType time, size_t size, const uint8_t* data)
        return true;
 }
 
-
-/** Push an event into the buffer.
- *
- * Note that the raw MIDI pointed to by ev will be COPIED and unmodified.
- * That is, the caller still owns it, if it needs freeing it's Not My Problem(TM).
- * Realtime safe.
- * @return false if operation failed (not enough room)
- */
-bool
-MidiBuffer::push_back(const jack_midi_event_t& ev)
-{
-       const size_t stamp_size = sizeof(TimeType);
-
-       if (_size + stamp_size + ev.size >= _capacity) {
-               cerr << "MidiBuffer::push_back failed (buffer is full)" << endl;
-               return false;
-       }
-
-       if (!Evoral::midi_event_is_valid(ev.buffer, ev.size)) {
-               cerr << "WARNING: MidiBuffer ignoring illegal MIDI event" << endl;
-               return false;
-       }
-
-#ifndef NDEBUG
-       if (DEBUG::MidiIO & PBD::debug_bits) {
-               DEBUG_STR_DECL(a);
-               DEBUG_STR_APPEND(a, string_compose ("midibuffer %1 push jack event @ %2 sz %3 ", this, ev.time, ev.size));
-               for (size_t i=0; i < ev.size; ++i) {
-                       DEBUG_STR_APPEND(a,hex);
-                       DEBUG_STR_APPEND(a,"0x");
-                       DEBUG_STR_APPEND(a,(int)ev.buffer[i]);
-                       DEBUG_STR_APPEND(a,' ');
-               }
-               DEBUG_STR_APPEND(a,'\n');
-               DEBUG_TRACE (DEBUG::MidiIO, DEBUG_STR(a).str());
-       }
-#endif
-
-       uint8_t* const write_loc = _data + _size;
-       *((TimeType*)write_loc) = ev.time;
-       memcpy(write_loc + stamp_size, ev.buffer, ev.size);
-
-       _size += stamp_size + ev.size;
-       _silent = false;
-
-       return true;
-}
-
-
 /** Reserve space for a new event in the buffer.
  *
  * This call is for copying MIDI directly into the buffer, the data location
index 9c11e818ace714a3cea21f30c8dda569f93b8039..ff6147d285bdf10e8fc294244b5130be929a0588 100644 (file)
@@ -1097,7 +1097,7 @@ MidiDiskstream::prep_record_enable ()
        boost::shared_ptr<MidiPort> sp = _source_port.lock ();
        
        if (sp && Config->get_monitoring_model() == HardwareMonitoring) {
-               sp->request_jack_monitors_input (!(_session.config.get_auto_input() && rolling));
+               sp->request_input_monitoring (!(_session.config.get_auto_input() && rolling));
        }
 
        return true;
@@ -1250,7 +1250,7 @@ MidiDiskstream::ensure_jack_monitors_input (bool yn)
        boost::shared_ptr<MidiPort> sp = _source_port.lock ();
        
        if (sp) {
-               sp->ensure_jack_monitors_input (yn);
+               sp->ensure_input_monitoring (yn);
        }
 }
 
index 72150f8cfc852f17471556be65c9131fa5d7eb7d..9191a570803ac3b4f4640fe4ced310fc50fab606 100644 (file)
@@ -26,7 +26,9 @@
 using namespace ARDOUR;
 using namespace std;
 
-MidiPort::MidiPort (const std::string& name, Flags flags)
+#define port_engine AudioEngine::instance()->port_engine()
+
+MidiPort::MidiPort (const std::string& name, PortFlags flags)
        : Port (name, DataType::MIDI, flags)
        , _has_been_mixed_down (false)
        , _resolve_required (false)
@@ -48,7 +50,7 @@ MidiPort::cycle_start (pframes_t nframes)
        _buffer->clear ();
 
        if (sends_output ()) {
-               jack_midi_clear_buffer (jack_port_get_buffer (_jack_port, nframes));
+               port_engine.midi_clear (port_engine.get_buffer (_port_handle, nframes));
        }
 }
 
@@ -63,31 +65,33 @@ MidiPort::get_midi_buffer (pframes_t nframes)
 
                if (_input_active) {
 
-                       void* jack_buffer = jack_port_get_buffer (_jack_port, nframes);
-                       const pframes_t event_count = jack_midi_get_event_count (jack_buffer);
+                       void* buffer = port_engine.get_buffer (_port_handle, nframes);
+                       const pframes_t event_count = port_engine.get_midi_event_count (buffer);
                        
-                       /* suck all relevant MIDI events from the JACK MIDI port buffer
+                       /* suck all relevant MIDI events from the MIDI port buffer
                           into our MidiBuffer
                        */
                        
                        for (pframes_t i = 0; i < event_count; ++i) {
                                
-                               jack_midi_event_t ev;
+                               pframes_t timestamp;
+                               size_t size;
+                               uint8_t* buf;
                                
-                               jack_midi_event_get (&ev, jack_buffer, i);
+                               port_engine.midi_event_get (timestamp, size, &buf, buffer, i);
                                
-                               if (ev.buffer[0] == 0xfe) {
+                               if (buf[0] == 0xfe) {
                                        /* throw away active sensing */
                                        continue;
                                }
                                
                                /* check that the event is in the acceptable time range */
                                
-                               if ((ev.time >= (_global_port_buffer_offset + _port_buffer_offset)) &&
-                                   (ev.time < (_global_port_buffer_offset + _port_buffer_offset + nframes))) {
-                                       _buffer->push_back (ev);
+                               if ((timestamp >= (_global_port_buffer_offset + _port_buffer_offset)) &&
+                                   (timestamp < (_global_port_buffer_offset + _port_buffer_offset + nframes))) {
+                                       _buffer->push_back (timestamp, size, buf);
                                } else {
-                                       cerr << "Dropping incoming MIDI at time " << ev.time << "; offset="
+                                       cerr << "Dropping incoming MIDI at time " << timestamp << "; offset="
                                             << _global_port_buffer_offset << " limit="
                                             << (_global_port_buffer_offset + _port_buffer_offset + nframes) << "\n";
                                }
@@ -121,7 +125,7 @@ MidiPort::cycle_split ()
 }
 
 void
-MidiPort::resolve_notes (void* jack_buffer, MidiBuffer::TimeType when)
+MidiPort::resolve_notes (void* port_buffer, MidiBuffer::TimeType when)
 {
        for (uint8_t channel = 0; channel <= 0xF; channel++) {
 
@@ -132,13 +136,13 @@ MidiPort::resolve_notes (void* jack_buffer, MidiBuffer::TimeType when)
                 * that prioritize sustain over AllNotesOff
                 */
 
-               if (jack_midi_event_write (jack_buffer, when, ev, 3) != 0) {
+               if (port_engine.midi_event_put (port_buffer, when, ev, 3) != 0) {
                        cerr << "failed to deliver sustain-zero on channel " << channel << " on port " << name() << endl;
                }
 
                ev[1] = MIDI_CTL_ALL_NOTES_OFF;
 
-               if (jack_midi_event_write (jack_buffer, 0, ev, 3) != 0) {
+               if (port_engine.midi_event_put (port_buffer, 0, ev, 3) != 0) {
                        cerr << "failed to deliver ALL NOTES OFF on channel " << channel << " on port " << name() << endl;
                }
        }
@@ -149,11 +153,11 @@ MidiPort::flush_buffers (pframes_t nframes)
 {
        if (sends_output ()) {
 
-               void* jack_buffer = jack_port_get_buffer (_jack_port, nframes);
-
+               void* port_buffer = port_engine.get_buffer (_port_handle, nframes);
+               
                if (_resolve_required) {
                        /* resolve all notes at the start of the buffer */
-                       resolve_notes (jack_buffer, 0);
+                       resolve_notes (port_buffer, 0);
                        _resolve_required = false;
                }
 
@@ -166,7 +170,7 @@ MidiPort::flush_buffers (pframes_t nframes)
                        assert (ev.time() < (nframes + _global_port_buffer_offset + _port_buffer_offset));
 
                        if (ev.time() >= _global_port_buffer_offset + _port_buffer_offset) {
-                               if (jack_midi_event_write (jack_buffer, (jack_nframes_t) ev.time(), ev.buffer(), ev.size()) != 0) {
+                               if (port_engine.midi_event_put (port_buffer, (pframes_t) ev.time(), ev.buffer(), ev.size()) != 0) {
                                        cerr << "write failed, drop flushed note off on the floor, time "
                                             << ev.time() << " > " << _global_port_buffer_offset + _port_buffer_offset << endl;
                                }
index 78da32e4273472449e6b023f889c24e3e5854c4b..0d9ac1760150c54b7bc5e612dd34c7216d76d17a 100644 (file)
@@ -107,7 +107,7 @@ MidiControlUI::midi_input_handler (IOCondition ioc, MIDI::Port* port)
                CrossThreadChannel::drain (port->selectable());
 
                DEBUG_TRACE (DEBUG::MidiIO, string_compose ("data available on %1\n", port->name()));
-               framepos_t now = _session.engine().frame_time();
+               framepos_t now = _session.engine().sample_time();
                port->parse (now);
        }
 
index 8ce0722d8b790b5e1f6616050bce3803d141b55a..0f2761c35092eb0186737430380321934115035e 100644 (file)
@@ -579,7 +579,7 @@ MTC_Slave::init_engine_dll (framepos_t pos, framepos_t inc)
 bool
 MTC_Slave::speed_and_position (double& speed, framepos_t& pos)
 {
-       framepos_t now = session.engine().frame_time_at_cycle_start();
+       framepos_t now = session.engine().sample_time_at_cycle_start();
        framepos_t sess_pos = session.transport_frame(); // corresponds to now
        //sess_pos -= session.engine().frames_since_cycle_start();
 
@@ -593,7 +593,7 @@ MTC_Slave::speed_and_position (double& speed, framepos_t& pos)
        if (last.timestamp == 0) { engine_dll_initstate = 0; }
        else if (engine_dll_initstate != transport_direction && last.speed != 0) {
                engine_dll_initstate = transport_direction;
-               init_engine_dll(last.position, session.engine().frames_per_cycle());
+               init_engine_dll(last.position, session.engine().samples_per_cycle());
                engine_dll_reinitialized = true;
        }
 
@@ -643,8 +643,8 @@ MTC_Slave::speed_and_position (double& speed, framepos_t& pos)
                        te0 = te1;
                        te1 += be * e + ee2;
                        ee2 += ce * e;
-                       speed_flt = (te1 - te0) / double(session.engine().frames_per_cycle());
-                       DEBUG_TRACE (DEBUG::MTC, string_compose ("engine DLL t0:%1 t1:%2 err:%3 spd:%4 ddt:%5\n", te0, te1, e, speed_flt, ee2 - session.engine().frames_per_cycle() ));
+                       speed_flt = (te1 - te0) / double(session.engine().samples_per_cycle());
+                       DEBUG_TRACE (DEBUG::MTC, string_compose ("engine DLL t0:%1 t1:%2 err:%3 spd:%4 ddt:%5\n", te0, te1, e, speed_flt, ee2 - session.engine().samples_per_cycle() ));
                }
        }
 
index 859f1ff8ab3f45a6e805b7d6dd884496825c0d21..5a1750a878c0384e23a936906fc893806ca106d2 100644 (file)
@@ -30,6 +30,7 @@
 #include "ardour/audioengine.h"
 #include "ardour/debug.h"
 #include "ardour/port.h"
+#include "ardour/port_engine.h"
 
 #include "i18n.h"
 
@@ -40,13 +41,17 @@ 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;
 pframes_t    Port::_cycle_nframes = 0;
 
+/* a handy define to shorten what would otherwise be a needlessly verbose
+ * repeated phrase
+ */
+#define port_engine AudioEngine::instance()->port_engine()
+
 /** @param n Port short name */
-Port::Port (std::string const & n, DataType t, Flags f)
+Port::Port (std::string const & n, DataType t, PortFlags f)
        : _port_buffer_offset (0)
        , _name (n)
        , _flags (f)
@@ -64,15 +69,15 @@ Port::Port (std::string const & n, DataType t, Flags f)
 
        assert (_name.find_first_of (':') == std::string::npos);
 
-       if (!_engine->connected()) {
+       if (!port_engine.connected()) {
                throw failed_constructor ();
        }
 
-       if ((_jack_port = jack_port_register (_engine->jack (), _name.c_str (), t.to_jack_type (), _flags, 0)) == 0) {
+       if ((_jack_port = port_engine.register_port (_name, t.to_port_type (), _flags)) == 0) {
                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));
 }
 
@@ -85,11 +90,9 @@ Port::~Port ()
 void
 Port::drop ()
 {
-       if (_jack_port) {
-               if (_engine->jack ()) {
-                       jack_port_unregister (_engine->jack (), _jack_port);
-               }
-               _jack_port = 0;
+       if (_port_handle) {
+               port_engine.unregister_port (port_handle);
+               _port_handle = 0;
        }
 }
 
@@ -97,7 +100,7 @@ Port::drop ()
 bool
 Port::connected () const
 {
-       return (jack_port_connected (_jack_port) != 0);
+       return (port_engine.connected (_port_handle) != 0);
 }
 
 int
@@ -191,9 +194,9 @@ Port::disconnect (std::string const & other)
        int r = 0;
 
        if (sends_output ()) {
-               r = jack_disconnect (_engine->jack (), this_fullname.c_str (), other_fullname.c_str ());
+               r = _engine->disconnect (this_fullname, other_fullname);
        } else {
-               r = jack_disconnect (_engine->jack (), other_fullname.c_str (), this_fullname.c_str ());
+               r = _engine->disconnect (other_fullname, this_fullname);
        }
 
        if (r == 0) {
@@ -236,27 +239,22 @@ Port::disconnect (Port* o)
 }
 
 void
-Port::set_engine (AudioEngine* e)
-{
-       _engine = e;
-}
-
-void
-Port::request_monitor_input (bool yn)
+Port::request_input_monitoring (bool yn)
 {
-       jack_port_request_monitor (_jack_port, yn);
+       port_eengine.request_input_monitoring (_port_handle, yn);
 }
 
 void
-Port::ensure_monitor_input (bool yn)
+Port::ensure_input_monitoring (bool yn)
 {
-       jack_port_ensure_monitor (_jack_port, yn);
+       port_engine.ensure_input_monitoring (_port_handle, yn);
 }
 
 bool
 Port::monitoring_input () const
 {
-       return jack_port_monitoring_input (_jack_port);
+       
+       return port_engine.monitoring_input (_port_handle);
 }
 
 void
index ea08636ea8290259eb8e3f1719cf7d765cb727ab..20908e5260704420228d42662bdbdeca4dc32476 100644 (file)
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+1#!/usr/bin/env python
 from waflib.extras import autowaf as autowaf
 from waflib import Options
 import os
@@ -432,6 +432,25 @@ def build(bld):
         elif bld.env['build_target'] == 'x86_64':
             obj.source += [ 'sse_functions_xmm.cc', 'sse_functions_64bit.s' ]
 
+    # the JACK audio backend
+
+    obj = bld.shlib (features = 'c cxx cshlib cxxshlib', source='jack_audiobackend.cc')
+    obj.cxxflags = [ '-fPIC' ]
+    obj.name     = 'jack_audiobackend'
+    obj.target   = 'jack_audiobackend'
+    obj.uselib   = [ 'JACK' ]
+    obj.use      = [ 'ardour' ]
+    obj.vnum     = '1.0.0'
+    obj.install_path = os.path.join(bld.env['LIBDIR'], 'ardour3')
+    obj.includes = [ '.' ]
+    obj.defines = [
+        'PACKAGE="' + I18N_PACKAGE + '"',
+        'DATA_DIR="' + os.path.normpath(bld.env['DATADIR']) + '"',
+        'CONFIG_DIR="' + os.path.normpath(bld.env['SYSCONFDIR']) + '"',
+        'PROGRAM_NAME="' + bld.env['PROGRAM_NAME'] + '"',
+        ]
+    
+
     # i18n
     if bld.is_defined('ENABLE_NLS'):
         mo_files = bld.path.ant_glob('po/*.mo')
index 05df3171fa46a0c721c71f913a7309e14e23a429..372a7891c913e95a522008a00c6426a65b64230e 100644 (file)
@@ -22,9 +22,6 @@
 #include <fcntl.h>
 #include <errno.h>
 
-#include <jack/jack.h>
-#include <jack/midiport.h>
-
 #include "pbd/xml++.h"
 #include "pbd/error.h"
 #include "pbd/failed_constructor.h"
@@ -45,37 +42,34 @@ template class EventRingBuffer<timestamp_t>;
 }
 
 pthread_t JackMIDIPort::_process_thread;
-Signal0<void> JackMIDIPort::JackHalted;
+Signal0<void> JackMIDIPort::EngineHalted;
 Signal0<void> JackMIDIPort::MakeConnections;
 
-JackMIDIPort::JackMIDIPort (string const & name, Flags flags, jack_client_t* jack_client)
+JackMIDIPort::JackMIDIPort (string const & name, Flags flags, ARDOUR::PortEngine& pengine)
        : Port (name, flags)
+       , _port_engine (pengine)
+       , _port_handle (0)
        , _currently_in_cycle (false)
        , _nframes_this_cycle (0)
-       , _jack_client (jack_client)
-       , _jack_port (0)
        , _last_write_timestamp (0)
        , output_fifo (512)
        , input_fifo (1024)
        , xthread (true)
 {
-       assert (jack_client);
        init (name, flags);
 }
 
-JackMIDIPort::JackMIDIPort (const XMLNode& node, jack_client_t* jack_client)
+JackMIDIPort::JackMIDIPort (const XMLNode& node, ARDOUR::PortEngine& pengine)
        : Port (node)
+       , _port_engine (pengine)
+       , _port_handle (0)
        , _currently_in_cycle (false)
        , _nframes_this_cycle (0)
-       , _jack_client (jack_client)
-       , _jack_port (0)
        , _last_write_timestamp (0)
        , output_fifo (512)
        , input_fifo (1024)
        , xthread (true)
 {
-       assert (jack_client);
-
        Descriptor desc (node);
        init (desc.tag, desc.flags);
        set_state (node);
@@ -89,17 +83,15 @@ JackMIDIPort::init (const string& /*name*/, Flags /*flags*/)
        }
 
        MakeConnections.connect_same_thread (connect_connection, boost::bind (&JackMIDIPort::make_connections, this));
-       JackHalted.connect_same_thread (halt_connection, boost::bind (&JackMIDIPort::jack_halted, this));
+       EngineHalted.connect_same_thread (halt_connection, boost::bind (&JackMIDIPort::engine_halted, this));
 }
 
 
 JackMIDIPort::~JackMIDIPort ()
 {
-       if (_jack_port) {
-               if (_jack_client) {
-                       jack_port_unregister (_jack_client, _jack_port);
-                       _jack_port = 0;
-               }
+       if (_port_handle) {
+               _port_engine.unregister_port (_port_handle);
+               _port_handle = 0;
        }
 }
 
@@ -143,7 +135,7 @@ JackMIDIPort::parse (framecnt_t timestamp)
 void
 JackMIDIPort::cycle_start (pframes_t nframes)
 {
-       assert (_jack_port);
+       assert (_port_handle);
        
        _currently_in_cycle = true;
        _nframes_this_cycle = nframes;
@@ -151,21 +143,23 @@ JackMIDIPort::cycle_start (pframes_t nframes)
        assert(_nframes_this_cycle == nframes);
 
        if (sends_output()) {
-               void *buffer = jack_port_get_buffer (_jack_port, nframes);
+               void *buffer = _port_engine.get_buffer (_port_handle, nframes);
                jack_midi_clear_buffer (buffer);
                flush (buffer); 
        }
        
        if (receives_input()) {
-               void* jack_buffer = jack_port_get_buffer(_jack_port, nframes);
-               const pframes_t event_count = jack_midi_get_event_count(jack_buffer);
+               void* buffer = _port_engine.get_buffer (_port_handle, nframes);
+               const pframes_t event_count = _port_engine.get_midi_event_count (buffer);
 
-               jack_midi_event_t ev;
-               timestamp_t cycle_start_frame = jack_last_frame_time (_jack_client);
+               pframes_t time;
+               size_t size;
+               uint8_t* buf;
+               timestamp_t cycle_start_frame = _port_engine.last_frame_time ();
 
                for (pframes_t i = 0; i < event_count; ++i) {
-                       jack_midi_event_get (&ev, jack_buffer, i);
-                       input_fifo.write (cycle_start_frame + ev.time, (Evoral::EventType) 0, ev.size, ev.buffer);
+                       _port_engine.midi_event_get (time, size, &buf, buffer, i);
+                       input_fifo.write (cycle_start_frame + time, (Evoral::EventType) 0, size, buf);
                }       
                
                if (event_count) {
@@ -178,7 +172,7 @@ void
 JackMIDIPort::cycle_end ()
 {
        if (sends_output()) {
-               flush (jack_port_get_buffer (_jack_port, _nframes_this_cycle));
+               flush (_port_engine.get_buffer (_port_handle, _nframes_this_cycle));
        }
 
        _currently_in_cycle = false;
@@ -186,10 +180,9 @@ JackMIDIPort::cycle_end ()
 }
 
 void
-JackMIDIPort::jack_halted ()
+JackMIDIPort::engine_halted ()
 {
-       _jack_client = 0;
-       _jack_port = 0;
+       _port_handle = 0;
 }
 
 void
@@ -216,7 +209,7 @@ JackMIDIPort::write (const byte * msg, size_t msglen, timestamp_t timestamp)
 {
        int ret = 0;
 
-       if (!_jack_client || !_jack_port) {
+       if (!_port_handle) {
                /* poof ! make it just vanish into thin air, since we are no
                   longer connected to JACK.
                */
@@ -268,18 +261,18 @@ JackMIDIPort::write (const byte * msg, size_t msglen, timestamp_t timestamp)
                        if (timestamp == 0) {
                                timestamp = _last_write_timestamp;
                        } 
-
-                       if ((ret = jack_midi_event_write (jack_port_get_buffer (_jack_port, _nframes_this_cycle), 
-                                                         timestamp, msg, msglen)) == 0) {
+                       
+                       if ((ret = _port_engine.midi_event_put (_port_engine.get_buffer (_port_handle, _nframes_this_cycle), 
+                                                               timestamp, msg, msglen)) == 0) {
                                ret = msglen;
                                _last_write_timestamp = timestamp;
 
                        } else {
                                cerr << "write of " << msglen << " @ " << timestamp << " failed, port holds "
-                                       << jack_midi_get_event_count (jack_port_get_buffer (_jack_port, _nframes_this_cycle))
-                                    << " port is " << _jack_port
+                                       << _port_engine.get_midi_event_count (_port_engine.get_buffer (_port_handle, _nframes_this_cycle))
+                                    << " port is " << _port_handle
                                     << " ntf = " << _nframes_this_cycle
-                                    << " buf = " << jack_port_get_buffer (_jack_port, _nframes_this_cycle)
+                                    << " buf = " << _port_engine.get_buffer (_port_handle, _nframes_this_cycle)
                                     << " ret = " << ret
                                     << endl;
                                PBD::stacktrace (cerr, 20);
@@ -305,7 +298,7 @@ JackMIDIPort::write (const byte * msg, size_t msglen, timestamp_t timestamp)
 }
 
 void
-JackMIDIPort::flush (void* jack_port_buffer)
+JackMIDIPort::flush (void* port_buffer)
 {
        RingBuffer< Evoral::Event<double> >::rw_vector vec = { { 0, 0 }, { 0, 0 } };
        size_t written;
@@ -320,8 +313,7 @@ JackMIDIPort::flush (void* jack_port_buffer)
                Evoral::Event<double>* evp = vec.buf[0];
                
                for (size_t n = 0; n < vec.len[0]; ++n, ++evp) {
-                       jack_midi_event_write (jack_port_buffer,
-                                              (timestamp_t) evp->time(), evp->buffer(), evp->size());
+                       _port_engine.midi_event_put (port_buffer, (timestamp_t) evp->time(), evp->buffer(), evp->size());
                }
        }
        
@@ -329,8 +321,7 @@ JackMIDIPort::flush (void* jack_port_buffer)
                Evoral::Event<double>* evp = vec.buf[1];
 
                for (size_t n = 0; n < vec.len[1]; ++n, ++evp) {
-                       jack_midi_event_write (jack_port_buffer,
-                                              (timestamp_t) evp->time(), evp->buffer(), evp->size());
+                       _port_engine.midi_event_put (port_buffer, (timestamp_t) evp->time(), evp->buffer(), evp->size());
                }
        }
        
@@ -364,8 +355,21 @@ JackMIDIPort::read (byte *, size_t)
 int
 JackMIDIPort::create_port ()
 {
-       _jack_port = jack_port_register(_jack_client, _tagname.c_str(), JACK_DEFAULT_MIDI_TYPE, _flags, 0);
-       return _jack_port == 0 ? -1 : 0;
+       ARDOUR::PortFlags f = ARDOUR::PortFlags (0);
+
+       /* convert MIDI::Port::Flags to ARDOUR::PortFlags ... sigh */
+
+       if (_flags & IsInput) {
+               f = ARDOUR::PortFlags (f | ARDOUR::IsInput);
+       } 
+
+       if (_flags & IsOutput) {
+               f = ARDOUR::PortFlags (f | ARDOUR::IsOutput);
+       }
+
+       _port_handle = _port_engine.register_port (_tagname, ARDOUR::DataType::MIDI, f);
+
+       return _port_handle == 0 ? -1 : 0;
 }
 
 XMLNode& 
@@ -386,18 +390,16 @@ JackMIDIPort::get_state () const
        write (device_inquiry, sizeof (device_inquiry), 0);
 #endif
 
-       if (_jack_port) {
+       if (_port_handle) {
                
-               const char** jc = jack_port_get_connections (_jack_port);
+               vector<string> connections;
+               _port_engine.get_connections (_port_handle, connections);
                string connection_string;
-               if (jc) {
-                       for (int i = 0; jc[i]; ++i) {
-                               if (i > 0) {
-                                       connection_string += ',';
-                               }
-                               connection_string += jc[i];
+               for (vector<string>::iterator i = connections.begin(); i != connections.end(); ++i) {
+                       if (i != connections.begin()) {
+                               connection_string += ',';
                        }
-                       free (jc);
+                       connection_string += *i;
                }
                
                if (!connection_string.empty()) {
@@ -435,14 +437,8 @@ JackMIDIPort::make_connections ()
                vector<string> ports;
                split (_connections, ports, ',');
                for (vector<string>::iterator x = ports.begin(); x != ports.end(); ++x) {
-                       if (_jack_client) {
-                               if (receives_input()) {
-                                       jack_connect (_jack_client, (*x).c_str(), jack_port_name (_jack_port));
-                               } else {
-                                       jack_connect (_jack_client, jack_port_name (_jack_port), (*x).c_str());
-                               }
-                               /* ignore failures */
-                       }
+                       _port_engine.connect (_port_handle, *x);
+                       /* ignore failures */
                }
        }
 
@@ -462,9 +458,8 @@ JackMIDIPort::is_process_thread()
 }
 
 void
-JackMIDIPort::reestablish (jack_client_t* jack)
+JackMIDIPort::reestablish ()
 {
-       _jack_client = jack;
        int const r = create_port ();
 
        if (r) {
index 822c74e1254ae1d5d48daebfe59345c78d3807d4..3df9681dd3318eaaf3143d145d04300f1e4a7244 100644 (file)
@@ -36,17 +36,17 @@ using namespace PBD;
 
 Manager *Manager::theManager = 0;
 
-Manager::Manager (jack_client_t* jack)
+Manager::Manager (ARDOUR::PortEngine& eng)
        : _ports (new PortList)
 {
-       _mmc = new MachineControl (this, jack);
+       _mmc = new MachineControl (this, eng);
        
-       _mtc_input_port = add_port (new MIDI::JackMIDIPort ("MTC in", Port::IsInput, jack));
-       _mtc_output_port = add_port (new MIDI::JackMIDIPort ("MTC out", Port::IsOutput, jack));
-       _midi_input_port = add_port (new MIDI::JackMIDIPort ("MIDI control in", Port::IsInput, jack));
-       _midi_output_port = add_port (new MIDI::JackMIDIPort ("MIDI control out", Port::IsOutput, jack));
-       _midi_clock_input_port = add_port (new MIDI::JackMIDIPort ("MIDI clock in", Port::IsInput, jack));
-       _midi_clock_output_port = add_port (new MIDI::JackMIDIPort ("MIDI clock out", Port::IsOutput, jack));
+       _mtc_input_port = add_port (new MIDI::JackMIDIPort ("MTC in", Port::IsInput, eng));
+       _mtc_output_port = add_port (new MIDI::JackMIDIPort ("MTC out", Port::IsOutput, eng));
+       _midi_input_port = add_port (new MIDI::JackMIDIPort ("MIDI control in", Port::IsInput, eng));
+       _midi_output_port = add_port (new MIDI::JackMIDIPort ("MIDI control out", Port::IsOutput, eng));
+       _midi_clock_input_port = add_port (new MIDI::JackMIDIPort ("MIDI clock in", Port::IsInput, eng));
+       _midi_clock_output_port = add_port (new MIDI::JackMIDIPort ("MIDI clock out", Port::IsOutput, eng));
 }
 
 Manager::~Manager ()
@@ -113,14 +113,14 @@ Manager::cycle_end()
 
 /** Re-register ports that disappear on JACK shutdown */
 void
-Manager::reestablish (jack_client_t* jack)
+Manager::reestablish ()
 {
        boost::shared_ptr<PortList> pr = _ports.reader ();
 
        for (PortList::const_iterator p = pr->begin(); p != pr->end(); ++p) {
                JackMIDIPort* pp = dynamic_cast<JackMIDIPort*> (*p);
                if (pp) {
-                       pp->reestablish (jack);
+                       pp->reestablish ();
                }
        }
 }
@@ -157,10 +157,10 @@ Manager::port (string const & n)
 }
 
 void
-Manager::create (jack_client_t* jack)
+Manager::create (ARDOUR::PortEngine& eng)
 {
        assert (theManager == 0);
-       theManager = new Manager (jack);
+       theManager = new Manager (eng);
 }
 
 void
index a8859387a4be77aae3dc7db2d3621143013ca75f..492756067cfa6228cc97eed7c17bdc098262e909 100644 (file)
@@ -22,8 +22,6 @@
 #include <string>
 #include <iostream>
 
-#include <jack/types.h>
-
 #include "pbd/xml++.h"
 #include "pbd/crossthread.h"
 #include "pbd/signals.h"
@@ -36,6 +34,8 @@
 #include "midi++/parser.h"
 #include "midi++/port.h"
 
+#include "ardour/port_engine.h"
+
 namespace MIDI {
 
 class Channel;
@@ -43,8 +43,8 @@ class PortRequest;
 
 class JackMIDIPort : public Port {
   public:
-       JackMIDIPort (std::string const &, Port::Flags, jack_client_t *);
-       JackMIDIPort (const XMLNode&, jack_client_t *);
+        JackMIDIPort (std::string const &, Port::Flags, ARDOUR::PortEngine&);
+        JackMIDIPort (const XMLNode&, ARDOUR::PortEngine&);
        ~JackMIDIPort ();
 
        XMLNode& get_state () const;
@@ -61,7 +61,7 @@ class JackMIDIPort : public Port {
 
        pframes_t nframes_this_cycle() const { return _nframes_this_cycle; }
 
-       void reestablish (jack_client_t *);
+       void reestablish ();
        void reconnect ();
 
        static void set_process_thread (pthread_t);
@@ -69,13 +69,14 @@ class JackMIDIPort : public Port {
        static bool is_process_thread();
 
        static PBD::Signal0<void> MakeConnections;
-       static PBD::Signal0<void> JackHalted;
+       static PBD::Signal0<void> EngineHalted;
 
 private:       
+        ARDOUR::PortEngine&            _port_engine;
+        ARDOUR::PortEngine::PortHandle _port_handle;
+
        bool              _currently_in_cycle;
        pframes_t         _nframes_this_cycle;
-       jack_client_t*    _jack_client;
-       jack_port_t*      _jack_port;
        timestamp_t       _last_write_timestamp;
        RingBuffer< Evoral::Event<double> > output_fifo;
        Evoral::EventRingBuffer<timestamp_t> input_fifo;
@@ -89,8 +90,8 @@ private:
        std::string _connections;
        PBD::ScopedConnection connect_connection;
        PBD::ScopedConnection halt_connection;
-       void flush (void* jack_port_buffer);
-       void jack_halted ();
+       void flush (void* port_buffer);
+       void engine_halted ();
        void make_connections ();
        void init (std::string const &, Flags);
 
index c37ba392b4f14954ffc203f53cb79f981f1beff9..7f4df5c6c8477a9238659ed779e30dab53396a09 100644 (file)
 #include "midi++/types.h"
 #include "midi++/port.h"
 
+namespace ARDOUR {
+       class PortEngine;
+}
+
 namespace MIDI {
 
 class MachineControl;  
@@ -69,14 +73,14 @@ class Manager {
 
        boost::shared_ptr<const PortList> get_midi_ports() const { return _ports.reader (); } 
 
-       static void create (jack_client_t* jack);
+        static void create (ARDOUR::PortEngine&);
        
        static Manager *instance () {
                return theManager;
        }
        static void destroy ();
 
-       void reestablish (jack_client_t *);
+       void reestablish ();
        void reconnect ();
 
        PBD::Signal0<void> PortsChanged;
@@ -84,7 +88,7 @@ class Manager {
   private:
        /* This is a SINGLETON pattern */
        
-       Manager (jack_client_t *);
+        Manager (ARDOUR::PortEngine&);
        static Manager *theManager;
 
        MIDI::MachineControl*   _mmc;
index 18204e3fa8afdf75b8994dec708a8f289b2bb302..0f362678ce4b766e2e171827837fdabe3e79c8d0 100644 (file)
 
 #include <jack/types.h>
 #include "timecode/time.h"
+
 #include "pbd/signals.h"
 #include "pbd/ringbuffer.h"
+
 #include "midi++/types.h"
 #include "midi++/parser.h"
 
+namespace ARDOUR {
+       class PortEngine;
+}
+
 namespace MIDI {
 
 class Port;
@@ -89,7 +95,7 @@ class MachineControl
                cmdResume = 0x7F
        };
        
-       MachineControl (Manager *, jack_client_t *);
+        MachineControl (Manager *, ARDOUR::PortEngine&);
 
        Port* input_port() { return _input_port; }
        Port* output_port() { return _output_port; }
index 06eadb5b34adcead348030f8061b05d769cc5b02..0a71463721ff47e638aa8807fca1a874b233d091 100644 (file)
@@ -22,7 +22,9 @@
 #include <map>
 
 #include "timecode/time.h"
+
 #include "pbd/error.h"
+
 #include "midi++/mmc.h"
 #include "midi++/port.h"
 #include "midi++/jack_midi_port.h"
@@ -196,15 +198,15 @@ static void build_mmc_cmd_map ()
 }
 
 
-MachineControl::MachineControl (Manager* m, jack_client_t* jack)
+MachineControl::MachineControl (Manager* m, ARDOUR::PortEngine& pengine)
 {
        build_mmc_cmd_map ();
 
        _receive_device_id = 0x7f;
        _send_device_id = 0x7f;
 
-       _input_port = m->add_port (new JackMIDIPort ("MMC in", Port::IsInput, jack));
-       _output_port = m->add_port (new JackMIDIPort ("MMC out", Port::IsOutput, jack));
+       _input_port = m->add_port (new JackMIDIPort ("MMC in", Port::IsInput, pengine));
+       _output_port = m->add_port (new JackMIDIPort ("MMC out", Port::IsOutput, pengine));
 
        _input_port->parser()->mmc.connect_same_thread (port_connections, boost::bind (&MachineControl::process_mmc_message, this, _1, _2, _3));
        _input_port->parser()->start.connect_same_thread (port_connections, boost::bind (&MachineControl::spp_start, this));
index ea8988110def73850b53a7ce86246af1af8d6ee1..8a4f2f6c69838686e7c890b81c8d743f873ec8e5 100644 (file)
@@ -26,6 +26,7 @@ out = 'build'
 
 path_prefix = 'libs/midi++2/'
 
+
 libmidi_sources = [
         'midi.cc',
         'channel.cc',
@@ -68,7 +69,7 @@ def build(bld):
         obj.cxxflags = [ '-fPIC', '-DWITH_JACK_MIDI' ]
     # everybody loves JACK
     obj.export_includes = ['.']
-    obj.includes     = ['.', '../surfaces/control_protocol']
+    obj.includes     = ['.', '../surfaces/control_protocol', '../ardour' ]
     obj.name         = 'libmidipp'
     obj.target       = 'midipp'
     obj.uselib       = 'GLIBMM SIGCPP XML JACK OSX'
index cfa6524f70d4a8dfe2df28dfa0622bb95786a6a7..ffda2435d038d6a78faa4d14ecf19c4feed86ca1 100644 (file)
@@ -1236,7 +1236,7 @@ MackieControlProtocol::midi_input_handler (IOCondition ioc, MIDI::Port* port)
                }
 
                DEBUG_TRACE (DEBUG::MackieControl, string_compose ("data available on %1\n", port->name()));
-               framepos_t now = session->engine().frame_time();
+               framepos_t now = session->engine().sample_time();
                port->parse (now);
        }
 
index 9f52f0dccdd38d5c994bdc0772cfd3a089c5d4d7..44db30ab1ba99b1af7e3b7ed35569f60320b6a13 100644 (file)
@@ -59,10 +59,10 @@ SurfacePort::SurfacePort (Surface& s)
                _input_port = new MIDI::IPMIDIPort (_surface->mcp().ipmidi_base() +_surface->number());
                _output_port = _input_port;
        } else {
-               jack_client_t* jack = MackieControlProtocol::instance()->get_session().engine().jack();
+               ARDOUR::PortEngine& port_engine (ARDOUR::AudioEngine::instance()->port_engine());
                
-               _input_port = new MIDI::JackMIDIPort (string_compose (_("%1 in"),  _surface->name()), MIDI::Port::IsInput, jack);
-               _output_port =new MIDI::JackMIDIPort (string_compose (_("%1 out"), _surface->name()), MIDI::Port::IsOutput, jack);
+               _input_port = new MIDI::JackMIDIPort (string_compose (_("%1 in"),  _surface->name()), MIDI::Port::IsInput, port_engine);
+               _output_port =new MIDI::JackMIDIPort (string_compose (_("%1 out"), _surface->name()), MIDI::Port::IsOutput, port_engine);
                
                /* MackieControl has its own thread for handling input from the input
                 * port, and we don't want anything handling output from the output