move JACK audio backend to its own folder and adjust build system to reflect that...
authorPaul Davis <paul@linuxaudiosystems.com>
Sat, 7 Sep 2013 15:03:57 +0000 (11:03 -0400)
committerPaul Davis <paul@linuxaudiosystems.com>
Sat, 7 Sep 2013 15:03:57 +0000 (11:03 -0400)
24 files changed:
gtk2_ardour/ardev_common.sh.in
libs/ardour/ardour/jack_audiobackend.h [deleted file]
libs/ardour/ardour/jack_connection.h [deleted file]
libs/ardour/ardour/jack_portengine.h [deleted file]
libs/ardour/ardour/jack_utils.h [deleted file]
libs/ardour/jack_api.cc [deleted file]
libs/ardour/jack_audiobackend.cc [deleted file]
libs/ardour/jack_connection.cc [deleted file]
libs/ardour/jack_portengine.cc [deleted file]
libs/ardour/jack_slave.cc [deleted file]
libs/ardour/jack_utils.cc [deleted file]
libs/backends/jack/jack_api.cc [new file with mode: 0644]
libs/backends/jack/jack_audiobackend.cc [new file with mode: 0644]
libs/backends/jack/jack_audiobackend.h [new file with mode: 0644]
libs/backends/jack/jack_connection.cc [new file with mode: 0644]
libs/backends/jack/jack_connection.h [new file with mode: 0644]
libs/backends/jack/jack_portengine.cc [new file with mode: 0644]
libs/backends/jack/jack_portengine.h [new file with mode: 0644]
libs/backends/jack/jack_slave.cc [new file with mode: 0644]
libs/backends/jack/jack_utils.cc [new file with mode: 0644]
libs/backends/jack/jack_utils.h [new file with mode: 0644]
libs/backends/jack/wscript [new file with mode: 0644]
libs/backends/wscript [new file with mode: 0644]
wscript

index 2bd9c51515bbe606766664c8d91e13805343a3c5..850a83c954e7218b22ec68c3e631391bd4ec60b7 100644 (file)
@@ -17,7 +17,7 @@ export ARDOUR_DATA_PATH=$TOP:$TOP/build:$TOP/gtk2_ardour:$TOP/build/gtk2_ardour:
 export ARDOUR_MIDIMAPS_PATH=$TOP/midi_maps:.
 export ARDOUR_MCP_PATH=$TOP/mcp:.
 export ARDOUR_EXPORT_FORMATS_PATH=$TOP/export:.
-export ARDOUR_BACKEND_PATH=$TOP/build/libs/ardour
+export ARDOUR_BACKEND_PATH=$libs/backends/jack
 
 #
 # even though we set the above variables, ardour requires that these 
diff --git a/libs/ardour/ardour/jack_audiobackend.h b/libs/ardour/ardour/jack_audiobackend.h
deleted file mode 100644 (file)
index 5ba9ee6..0000000
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
-    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_jack_audiobackend_h__
-#define __libardour_jack_audiobackend_h__
-
-#include <string>
-#include <vector>
-#include <map>
-#include <set>
-
-#include <stdint.h>
-
-#include <boost/shared_ptr.hpp>
-
-#include <jack/jack.h>
-#ifdef HAVE_JACK_SESSION
-#include <jack/session.h>
-#endif
-
-#include "ardour/audio_backend.h"
-
-namespace ARDOUR {
-
-class JackConnection;
-
-class JACKAudioBackend : public AudioBackend {
-  public:
-    JACKAudioBackend (AudioEngine& e, boost::shared_ptr<JackConnection>);
-    ~JACKAudioBackend ();
-
-    std::string name() const;
-    void* private_handle() const;
-    bool connected() const;
-    bool is_realtime () const;
-
-    bool requires_driver_selection() const;
-    std::vector<std::string> enumerate_drivers () const;
-    int set_driver (const std::string&);
-
-    std::vector<DeviceStatus> enumerate_devices () const;
-
-    std::vector<float> available_sample_rates (const std::string& device) const;
-    std::vector<uint32_t> available_buffer_sizes (const std::string& device) const;
-    uint32_t available_input_channel_count (const std::string& device) const;
-    uint32_t available_output_channel_count (const std::string& device) const;
-
-    int set_device_name (const std::string&);
-    int set_sample_rate (float);
-    int set_buffer_size (uint32_t);
-    int set_sample_format (SampleFormat);
-    int set_interleaved (bool yn);
-    int set_input_channels (uint32_t);
-    int set_output_channels (uint32_t);
-    int set_systemic_input_latency (uint32_t);
-    int set_systemic_output_latency (uint32_t);
-
-    std::string  device_name () const;
-    float        sample_rate () const;
-    uint32_t     buffer_size () const;
-    SampleFormat sample_format () const;
-    bool         interleaved () const;
-    uint32_t     input_channels () const;
-    uint32_t     output_channels () const;
-    uint32_t     systemic_input_latency () const;
-    uint32_t     systemic_output_latency () const;
-
-    int start ();
-    int stop ();
-    int pause ();
-    int freewheel (bool);
-
-    float cpu_load() const;
-
-    pframes_t sample_time ();
-    pframes_t sample_time_at_cycle_start ();
-    pframes_t samples_since_cycle_start ();
-
-    size_t raw_buffer_size (DataType t);
-
-    int create_process_thread (boost::function<void()> func, pthread_t*, size_t stacksize);
-
-    void transport_start ();
-    void transport_stop ();
-    void transport_locate (framepos_t /*pos*/);
-    TransportState transport_state () const;
-    framepos_t transport_frame() const;
-
-    int set_time_master (bool /*yn*/);
-    bool get_sync_offset (pframes_t& /*offset*/) const;
-
-    void update_latencies ();
-
-    static bool already_configured();
-
-  private:
-    boost::shared_ptr<JackConnection>  _jack_connection; //< shared with JACKPortEngine
-    bool            _running;
-    bool            _freewheeling;
-    std::map<DataType,size_t> _raw_buffer_sizes;
-
-    static int  _xrun_callback (void *arg);
-    static void* _process_thread (void *arg);
-    static int  _sample_rate_callback (pframes_t nframes, void *arg);
-    static int  _bufsize_callback (pframes_t nframes, void *arg);
-    static void _jack_timebase_callback (jack_transport_state_t, pframes_t, jack_position_t*, int, void*);
-    static int  _jack_sync_callback (jack_transport_state_t, jack_position_t*, void *arg);
-    static void _freewheel_callback (int , void *arg);
-    static void _latency_callback (jack_latency_callback_mode_t, void*);
-#ifdef HAVE_JACK_SESSION
-    static void _session_callback (jack_session_event_t *event, void *arg);
-#endif
-    
-    void jack_timebase_callback (jack_transport_state_t, pframes_t, jack_position_t*, int);
-    int  jack_sync_callback (jack_transport_state_t, jack_position_t*);
-    int  jack_bufsize_callback (pframes_t);
-    int  jack_sample_rate_callback (pframes_t);
-    void freewheel_callback (int);
-    int  process_callback (pframes_t nframes);
-    void jack_latency_callback (jack_latency_callback_mode_t);
-    void disconnected (const char*);
-
-    void set_jack_callbacks ();
-    int reconnect_to_jack ();
-    
-    struct ThreadData {
-       JACKAudioBackend* engine;
-       boost::function<void()> f;
-       size_t stacksize;
-       
-       ThreadData (JACKAudioBackend* e, boost::function<void()> fp, size_t stacksz)
-               : engine (e) , f (fp) , stacksize (stacksz) {}
-    };
-    
-    void*  process_thread ();
-    static void* _start_process_thread (void*);
-
-    ChanCount n_physical (unsigned long) const;
-    
-    void setup_jack_startup_command ();
-
-    /* pffooo */
-
-    std::string  _target_driver;
-    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;
-    uint32_t     _target_systemic_input_latency;
-    uint32_t     _target_systemic_output_latency;
-    uint32_t     _current_sample_rate;
-    uint32_t     _current_buffer_size;
-
-    typedef std::set<std::string> DeviceList;
-    typedef std::map<std::string,DeviceList> DriverDeviceMap;
-    
-    mutable DriverDeviceMap all_devices;
-
-    PBD::ScopedConnection disconnect_connection;
-};
-
-} // namespace
-
-#endif /* __ardour_audiobackend_h__ */
-    
diff --git a/libs/ardour/ardour/jack_connection.h b/libs/ardour/ardour/jack_connection.h
deleted file mode 100644 (file)
index cd45f3b..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-#ifndef __libardour_jack_connection_h__
-#define __libardour_jack_connection_h__
-
-#include <string>
-#include <jack/jack.h>
-
-#include "pbd/signals.h"
-
-namespace ARDOUR {
-
-class JackConnection {
-  public:
-    JackConnection (const std::string& client_name, const std::string& session_uuid);
-    ~JackConnection ();
-
-    const std::string& client_name() const { return _client_name; }
-
-    int open ();
-    int close ();
-    bool connected () const { return _jack != 0; }
-
-    jack_client_t* jack() const { return _jack; }
-
-    PBD::Signal0<void> Connected;
-    PBD::Signal1<void,const char*> Disconnected;
-
-    void halted_callback ();
-    void halted_info_callback (jack_status_t, const char*);
-
-    static bool server_running();
-
-  private:
-    jack_client_t* volatile _jack;
-    std::string _client_name;
-    std::string session_uuid;
-};
-
-} // namespace 
-
-#endif /* __libardour_jack_connection_h__ */
diff --git a/libs/ardour/ardour/jack_portengine.h b/libs/ardour/ardour/jack_portengine.h
deleted file mode 100644 (file)
index 0e1eb48..0000000
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
-    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_jack_portengine_h__
-#define __libardour_jack_portengine_h__
-
-#include <string>
-#include <vector>
-
-#include <stdint.h>
-
-#include <jack/types.h>
-#include <jack/midiport.h>
-
-#include <boost/shared_ptr.hpp>
-
-#include "pbd/signals.h"
-
-#include "ardour/port_engine.h"
-#include "ardour/types.h"
-
-namespace ARDOUR {
-
-class JackConnection;
-
-class JACKPortEngine : public PortEngine 
-{
-  public:
-    JACKPortEngine (PortManager&, boost::shared_ptr<JackConnection>);
-    ~JACKPortEngine();
-
-    void* private_handle() const;
-    bool connected() const;
-
-    const std::string& my_name() const;
-
-    uint32_t port_name_size() const;
-
-    int         set_port_name (PortHandle, const std::string&);
-    std::string get_port_name (PortHandle) const;
-    PortHandle* get_port_by_name (const std::string&) const;
-
-    int get_ports (const std::string& port_name_pattern, DataType type, PortFlags flags, std::vector<std::string>&) const;
-
-    DataType port_data_type (PortHandle) const;
-
-    PortHandle register_port (const std::string& shortname, ARDOUR::DataType, ARDOUR::PortFlags);
-    void  unregister_port (PortHandle);
-
-    bool  connected (PortHandle, bool process_callback_safe);
-    bool  connected_to (PortHandle, const std::string&, bool process_callback_safe);
-    bool  physically_connected (PortHandle, bool process_callback_safe);
-    int   get_connections (PortHandle, std::vector<std::string>&, bool process_callback_safe);
-    int   connect (PortHandle, const std::string&);
-
-    int   disconnect (PortHandle, const std::string&);
-    int   disconnect_all (PortHandle);
-    int   connect (const std::string& src, const std::string& dst);
-    int   disconnect (const std::string& src, const std::string& dst);
-    
-    /* MIDI */
-
-    int      midi_event_get (pframes_t& timestamp, size_t& size, uint8_t** buf, void* port_buffer, uint32_t event_index);
-    int      midi_event_put (void* port_buffer, pframes_t timestamp, const uint8_t* buffer, size_t size);
-    uint32_t get_midi_event_count (void* port_buffer);
-    void     midi_clear (void* port_buffer);
-
-    /* Monitoring */
-
-    bool  can_monitor_input() const;
-    int   request_input_monitoring (PortHandle, bool);
-    int   ensure_input_monitoring (PortHandle, bool);
-    bool  monitoring_input (PortHandle);
-
-    /* Latency management
-     */
-    
-    void          set_latency_range (PortHandle, bool for_playback, LatencyRange);
-    LatencyRange  get_latency_range (PortHandle, bool for_playback);
-
-    /* Physical ports */
-
-    bool      port_is_physical (PortHandle) const;
-    void      get_physical_outputs (DataType type, std::vector<std::string>&);
-    void      get_physical_inputs (DataType type, std::vector<std::string>&);
-    ChanCount n_physical_outputs () const;
-    ChanCount n_physical_inputs () const;
-
-    /* Getting access to the data buffer for a port */
-
-    void* get_buffer (PortHandle, pframes_t);
-
-    /* Miscellany */
-
-    pframes_t sample_time_at_cycle_start ();
-    
-  private:
-    boost::shared_ptr<JackConnection> _jack_connection;
-
-    static int  _graph_order_callback (void *arg);
-    static void _registration_callback (jack_port_id_t, int, void *);
-    static void _connect_callback (jack_port_id_t, jack_port_id_t, int, void *);
-
-    void connect_callback (jack_port_id_t, jack_port_id_t, int);
-
-    ChanCount n_physical (unsigned long flags) const;
-    void get_physical (DataType type, unsigned long flags, std::vector<std::string>& phy) const;
-
-    PBD::ScopedConnection jack_connection_connection;
-    void connected_to_jack ();
-
-};
-
-} // namespace 
-
-#endif /* __libardour_jack_portengine_h__ */
diff --git a/libs/ardour/ardour/jack_utils.h b/libs/ardour/ardour/jack_utils.h
deleted file mode 100644 (file)
index 7565353..0000000
+++ /dev/null
@@ -1,235 +0,0 @@
-/*
-    Copyright (C) 2011 Tim Mayberry
-
-    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 <stdint.h>
-
-#include <vector>
-#include <map>
-#include <string>
-
-namespace ARDOUR {
-
-       // Names for the drivers on all possible systems
-       extern const char * const portaudio_driver_name;
-       extern const char * const coreaudio_driver_name;
-       extern const char * const alsa_driver_name;
-       extern const char * const oss_driver_name;
-       extern const char * const freebob_driver_name;
-       extern const char * const ffado_driver_name;
-       extern const char * const netjack_driver_name;
-       extern const char * const dummy_driver_name;
-
-       /**
-        * Get a list of possible JACK audio driver names based on platform
-        */
-       void get_jack_audio_driver_names (std::vector<std::string>& driver_names);
-
-       /**
-        * Get the default JACK audio driver based on platform
-        */
-       void get_jack_default_audio_driver_name (std::string& driver_name);
-
-       /**
-        * Get a list of possible samplerates supported be JACK
-        */
-       void get_jack_sample_rate_strings (std::vector<std::string>& sample_rates);
-
-       /**
-        * @return The default samplerate
-        */
-       std::string get_jack_default_sample_rate ();
-
-       /**
-        * @return true if sample rate string was able to be converted
-        */
-       bool get_jack_sample_rate_value_from_string (const std::string& srs, uint32_t& srv);
-
-       /**
-        * Get a list of possible period sizes supported be JACK
-        */
-       void get_jack_period_size_strings (std::vector<std::string>& samplerates);
-
-       /**
-        * @return The default period size
-        */
-       std::string get_jack_default_period_size ();
-
-       /**
-        * @return true if period size string was able to be converted
-        */
-       bool get_jack_period_size_value_from_string (const std::string& pss, uint32_t& psv);
-
-       /**
-        * These are driver specific I think, so it may require a driver arg
-        * in future
-        */
-       void get_jack_dither_mode_strings (const std::string& driver, std::vector<std::string>& dither_modes);
-
-       /**
-        * @return The default dither mode
-        */
-       std::string get_jack_default_dither_mode (const std::string& driver);
-
-       /**
-        * @return Estimate of latency
-        *
-        * API matches current use in GUI
-        */
-       std::string get_jack_latency_string (std::string samplerate, float periods, std::string period_size);
-
-       /**
-        * Key being a readable name to display in a GUI
-        * Value being name used in a jack commandline
-        */
-       typedef std::map<std::string, std::string> device_map_t;
-
-       /**
-        * Use library specific code to find out what what devices exist for a given
-        * driver that might work in JACK. There is no easy way to find out what
-        * modules the JACK server supports so guess based on platform. For instance
-        * portaudio is cross-platform but we only return devices if built for
-        * windows etc
-        */
-       void get_jack_alsa_device_names (device_map_t& devices);
-       void get_jack_portaudio_device_names (device_map_t& devices);
-       void get_jack_coreaudio_device_names (device_map_t& devices);
-       void get_jack_oss_device_names (device_map_t& devices);
-       void get_jack_freebob_device_names (device_map_t& devices);
-       void get_jack_ffado_device_names (device_map_t& devices);
-       void get_jack_netjack_device_names (device_map_t& devices);
-       void get_jack_dummy_device_names (device_map_t& devices);
-
-       /*
-        * @return true if there were devices found for the driver
-        *
-        * @param driver The driver name returned by get_jack_audio_driver_names
-        * @param devices The map used to insert the drivers into, devices will be cleared before
-        * adding the available drivers
-        */
-       bool get_jack_device_names_for_audio_driver (const std::string& driver, device_map_t& devices);
-
-       /*
-        * @return a list of readable device names for a specific driver.
-        */
-       std::vector<std::string> get_jack_device_names_for_audio_driver (const std::string& driver);
-
-       /**
-        * @return true if the driver supports playback and recording
-        * on separate devices
-        */
-       bool get_jack_audio_driver_supports_two_devices (const std::string& driver);
-
-       bool get_jack_audio_driver_supports_latency_adjustment (const std::string& driver);
-
-       bool get_jack_audio_driver_supports_setting_period_count (const std::string& driver);
-
-       /**
-        * The possible names to use to try and find servers, this includes
-        * any file extensions like .exe on Windows
-        *
-        * @return true if the JACK application names for this platform could be guessed
-        */
-       bool get_jack_server_application_names (std::vector<std::string>& server_names);
-
-       /**
-        * Sets the PATH environment variable to contain directories likely to contain
-        * JACK servers so that if the JACK server is auto-started it can find the server
-        * executable.
-        *
-        * This is only modifies PATH on the mac at the moment.
-        */
-       void set_path_env_for_jack_autostart (const std::vector<std::string>&);
-
-       /**
-        * Get absolute paths to directories that might contain JACK servers on the system
-        *
-        * @return true if !server_paths.empty()
-        */
-       bool get_jack_server_dir_paths (std::vector<std::string>& server_dir_paths);
-
-       /**
-        * Get absolute paths to JACK servers on the system
-        *
-        * @return true if a server was found
-        */
-       bool get_jack_server_paths (const std::vector<std::string>& server_dir_paths,
-                       const std::vector<std::string>& server_names,
-                       std::vector<std::string>& server_paths);
-
-
-       bool get_jack_server_paths (std::vector<std::string>& server_paths);
-
-       /**
-        * Get absolute path to default JACK server
-        */
-       bool get_jack_default_server_path (std::string& server_path);
-
-       /**
-        * @return The name of the jack server config file
-        */
-       std::string get_jack_server_config_file_name ();
-
-       std::string get_jack_server_user_config_dir_path ();
-
-       std::string get_jack_server_user_config_file_path ();
-
-       bool write_jack_config_file (const std::string& config_file_path, const std::string& command_line);
-
-       struct JackCommandLineOptions {
-
-               // see implementation for defaults
-               JackCommandLineOptions ();
-
-               //operator bool
-               //operator ostream
-
-               std::string      server_path;
-               uint32_t         timeout;
-               bool             no_mlock;
-               uint32_t         ports_max;
-               bool             realtime;
-               uint32_t         priority;
-               bool             unlock_gui_libs;
-               bool             verbose;
-               bool             temporary;
-               bool             playback_only;
-               bool             capture_only;
-               std::string      driver;
-               std::string      input_device;
-               std::string      output_device;
-               uint32_t         num_periods;
-               uint32_t         period_size;
-               uint32_t         samplerate;
-               uint32_t         input_channels;
-               uint32_t         output_channels;
-               uint32_t         input_latency;
-               uint32_t         output_latency;
-               bool             hardware_metering;
-               bool             hardware_monitoring;
-               std::string      dither_mode;
-               bool             force16_bit;
-               bool             soft_mode;
-               std::string      midi_driver;
-       };
-
-       /**
-        * @return true if able to build a valid command line based on options
-        */
-       bool get_jack_command_line_string (const JackCommandLineOptions& options, std::string& command_line);
-}
diff --git a/libs/ardour/jack_api.cc b/libs/ardour/jack_api.cc
deleted file mode 100644 (file)
index fcfc499..0000000
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
-    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 "ardour/jack_connection.h"
-#include "ardour/jack_audiobackend.h"
-#include "ardour/jack_portengine.h"
-
-using namespace ARDOUR;
-
-static boost::shared_ptr<JACKAudioBackend> backend;
-static boost::shared_ptr<JACKPortEngine> port_engine;
-static boost::shared_ptr<JackConnection> jack_connection;
-
-static boost::shared_ptr<AudioBackend>
-backend_factory (AudioEngine& ae)
-{
-       if (!jack_connection) {
-               return boost::shared_ptr<AudioBackend>();
-       }
-
-       if (!backend) {
-               backend.reset (new JACKAudioBackend (ae, jack_connection));
-       }
-
-       return backend;
-}
-
-static boost::shared_ptr<PortEngine>
-portengine_factory (PortManager& pm)
-{
-       if (!jack_connection) {
-               return boost::shared_ptr<PortEngine>();
-       }
-
-       if (!port_engine) {
-               port_engine.reset (new JACKPortEngine (pm, jack_connection));
-       }
-
-       return port_engine;
-}
-
-static int
-instantiate (const std::string& arg1, const std::string& arg2)
-{
-       try {
-               jack_connection.reset (new JackConnection (arg1, arg2));
-       } catch (...) {
-               return -1;
-       }
-
-       return 0;
-}
-
-static int 
-deinstantiate ()
-{
-       port_engine.reset ();
-       backend.reset ();
-       jack_connection.reset ();
-
-       return 0;
-}
-
-static bool
-already_configured ()
-{
-       return JackConnection::server_running ();
-}
-
-extern "C" {
-       
-       
-       /* functions looked up using dlopen-and-cousins, and so naming scope
-        * must be non-mangled.
-        */
-
-       ARDOUR::AudioBackendInfo descriptor = {
-               "JACK",
-               instantiate,
-               deinstantiate,
-               backend_factory,
-               portengine_factory,
-               already_configured,
-       };
-}
-
diff --git a/libs/ardour/jack_audiobackend.cc b/libs/ardour/jack_audiobackend.cc
deleted file mode 100644 (file)
index 8f3dffa..0000000
+++ /dev/null
@@ -1,937 +0,0 @@
-/*
-    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 <math.h>
-
-#include <boost/scoped_ptr.hpp>
-#include <glibmm/timer.h>
-
-#include "pbd/error.h"
-
-#include "jack/jack.h"
-#include "jack/thread.h"
-
-#include "ardour/audioengine.h"
-#include "ardour/session.h"
-#include "ardour/types.h"
-
-#include "ardour/jack_audiobackend.h"
-#include "ardour/jack_connection.h"
-#include "ardour/jack_portengine.h"
-#include "ardour/jack_utils.h"
-
-#include "i18n.h"
-
-using namespace ARDOUR;
-using namespace PBD;
-using std::string;
-using std::vector;
-using std::cerr;
-using std::endl;
-
-#define GET_PRIVATE_JACK_POINTER(localvar)  jack_client_t* localvar = _jack_connection->jack(); if (!(localvar)) { return; }
-#define GET_PRIVATE_JACK_POINTER_RET(localvar,r) jack_client_t* localvar = _jack_connection->jack(); if (!(localvar)) { return r; }
-
-JACKAudioBackend::JACKAudioBackend (AudioEngine& e, boost::shared_ptr<JackConnection> jc)
-       : AudioBackend (e)
-       , _jack_connection (jc)
-       , _running (false)
-       , _freewheeling (false)
-       , _target_sample_rate (48000)
-       , _target_buffer_size (1024)
-       , _target_sample_format (FormatFloat)
-       , _target_interleaved (false)
-       , _target_input_channels (-1)
-       , _target_output_channels (-1)
-       , _target_systemic_input_latency (0)
-       , _target_systemic_output_latency (0)
-       , _current_sample_rate (0)
-       , _current_buffer_size (0)
-{
-       _jack_connection->Disconnected.connect_same_thread (disconnect_connection, boost::bind (&JACKAudioBackend::disconnected, this, _1));
-}
-
-JACKAudioBackend::~JACKAudioBackend()
-{
-}
-
-string
-JACKAudioBackend::name() const 
-{
-       return X_("JACK");
-}
-
-void*
-JACKAudioBackend::private_handle() const
-{
-       return _jack_connection->jack();
-}
-
-bool
-JACKAudioBackend::connected() const
-{
-       return (private_handle() != 0);
-}
-
-bool
-JACKAudioBackend::is_realtime () const
-{
-       GET_PRIVATE_JACK_POINTER_RET (_priv_jack,false);
-       return jack_is_realtime (_priv_jack);
-}
-
-bool
-JACKAudioBackend::requires_driver_selection() const
-{
-       return true;
-}
-
-vector<string>
-JACKAudioBackend::enumerate_drivers () const
-{
-       vector<string> currently_available;
-       get_jack_audio_driver_names (currently_available);
-       return currently_available;
-}
-
-int
-JACKAudioBackend::set_driver (const std::string& name)
-{
-       _target_driver = name;
-       return 0;
-}
-
-vector<AudioBackend::DeviceStatus>
-JACKAudioBackend::enumerate_devices () const
-{
-       vector<string> currently_available = get_jack_device_names_for_audio_driver (_target_driver);
-       vector<DeviceStatus> statuses;
-
-       if (all_devices.find (_target_driver) == all_devices.end()) {
-               all_devices.insert (make_pair (_target_driver, std::set<string>()));
-       }
-       
-       /* store every device we've found, by driver name. 
-        *
-        * This is so we do not confuse ALSA, FFADO, netjack etc. devices
-        * with each other.
-        */
-
-       DeviceList& all (all_devices[_target_driver]);
-
-       for (vector<string>::const_iterator d = currently_available.begin(); d != currently_available.end(); ++d) {
-               all.insert (*d);
-       }
-       
-       for (DeviceList::const_iterator d = all.begin(); d != all.end(); ++d) {
-               if (find (currently_available.begin(), currently_available.end(), *d) == currently_available.end()) {
-                       statuses.push_back (DeviceStatus (*d, false));
-               } else {
-                       statuses.push_back (DeviceStatus (*d, false));
-               }
-       }
-       
-       return statuses;
-}
-
-vector<float>
-JACKAudioBackend::available_sample_rates (const string& /*device*/) const
-{
-       vector<float> f;
-       
-       if (connected()) {
-               f.push_back (sample_rate());
-               return f;
-       }
-
-       /* if JACK is not already running, just list a bunch of reasonable 
-          values and let the future sort it all out.
-       */
-
-       f.push_back (8000.0);
-       f.push_back (16000.0);
-       f.push_back (24000.0);
-       f.push_back (32000.0);
-       f.push_back (44100.0);
-       f.push_back (48000.0);
-       f.push_back (88200.0);
-       f.push_back (96000.0);
-       f.push_back (192000.0);
-       f.push_back (384000.0);
-       
-       return f;
-}
-
-vector<uint32_t>
-JACKAudioBackend::available_buffer_sizes (const string& /*device*/) const
-{
-       vector<uint32_t> s;
-       
-       if (connected()) {
-               s.push_back (buffer_size());
-               return s;
-       }
-
-       s.push_back (8);
-       s.push_back (16);
-       s.push_back (32);
-       s.push_back (64);
-       s.push_back (128);
-       s.push_back (256);
-       s.push_back (512);
-       s.push_back (1024);
-       s.push_back (2048);
-       s.push_back (4096);
-       s.push_back (8192);
-
-       return s;
-}
-
-uint32_t
-JACKAudioBackend::available_input_channel_count (const string& /*device*/) const
-{
-       return 128;
-}
-
-uint32_t
-JACKAudioBackend::available_output_channel_count (const string& /*device*/) const
-{
-       return 128;
-}
-
-/* -- parameter setting -- */
-
-int
-JACKAudioBackend::set_device_name (const string& dev)
-{
-       if (connected()) {
-               /* need to stop and restart JACK for this to work, at present */
-               return -1;
-       }
-
-       _target_device = dev;
-       return 0;
-}
-
-int
-JACKAudioBackend::set_sample_rate (float sr)
-{
-       if (!connected()) {
-               _target_sample_rate = sr;
-               return 0;
-       }
-
-       GET_PRIVATE_JACK_POINTER_RET (_priv_jack, -1);
-
-       if (sr == jack_get_sample_rate (_priv_jack)) {
-                return 0;
-       }
-
-       return -1;
-}
-
-int
-JACKAudioBackend::set_buffer_size (uint32_t nframes)
-{
-       if (!connected()) {
-               _target_buffer_size = nframes;
-               return 0;
-       }
-
-       GET_PRIVATE_JACK_POINTER_RET (_priv_jack, -1);
-
-       if (nframes == jack_get_buffer_size (_priv_jack)) {
-                return 0;
-       }
-
-       return jack_set_buffer_size (_priv_jack, nframes);
-}
-
-int
-JACKAudioBackend::set_sample_format (SampleFormat sf)
-{
-       /* as far as JACK clients are concerned, the hardware is always
-        * floating point format.
-        */
-       if (sf == FormatFloat) {
-               return 0;
-       }
-       return -1;
-}
-
-int
-JACKAudioBackend::set_interleaved (bool yn)
-{
-       /* as far as JACK clients are concerned, the hardware is always
-        * non-interleaved
-        */
-       if (!yn) {
-               return 0;
-       }
-       return -1;
-}
-
-int
-JACKAudioBackend::set_input_channels (uint32_t cnt)
-{
-       if (connected()) {
-               return -1;
-       }
-
-       _target_input_channels = cnt;
-       
-       return 0;
-}
-
-int
-JACKAudioBackend::set_output_channels (uint32_t cnt)
-{
-       if (connected()) {
-               return -1;
-       }
-
-       _target_output_channels = cnt;
-
-       return 0;
-}
-
-int
-JACKAudioBackend::set_systemic_input_latency (uint32_t l)
-{
-       if (connected()) {
-               return -1;
-       }
-
-       _target_systemic_input_latency = l;
-
-       return 0;
-}
-
-int
-JACKAudioBackend::set_systemic_output_latency (uint32_t l)
-{
-       if (connected()) {
-               return -1;
-       }
-
-       _target_systemic_output_latency = l;
-
-       return 0;
-}
-
-/* --- Parameter retrieval --- */
-
-std::string
-JACKAudioBackend::device_name () const
-{
-       return string();
-}
-
-float
-JACKAudioBackend::sample_rate () const
-{
-       if (connected()) {
-               return _current_sample_rate;
-       }
-       return _target_sample_rate;
-}
-
-uint32_t
-JACKAudioBackend::buffer_size () const
-{
-       if (connected()) {
-               return _current_buffer_size;
-       }
-       return _target_buffer_size;
-}
-
-SampleFormat
-JACKAudioBackend::sample_format () const
-{
-       return FormatFloat;
-}
-
-bool
-JACKAudioBackend::interleaved () const
-{
-       return false;
-}
-
-uint32_t
-JACKAudioBackend::input_channels () const
-{
-       if (connected()) {
-               return n_physical (JackPortIsInput).n_audio();
-       } 
-       return _target_input_channels;
-}
-
-uint32_t
-JACKAudioBackend::output_channels () const
-{
-       if (connected()) {
-               return n_physical (JackPortIsOutput).n_audio();
-       } 
-       return _target_output_channels;
-}
-
-uint32_t
-JACKAudioBackend::systemic_input_latency () const
-{
-       return _target_systemic_output_latency;
-}
-
-uint32_t
-JACKAudioBackend::systemic_output_latency () const
-{
-       return _target_systemic_output_latency;
-}
-
-size_t 
-JACKAudioBackend::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;
-}
-
-void
-JACKAudioBackend::setup_jack_startup_command ()
-{
-       /* first we map the parameters that have been set onto a
-        * JackCommandLineOptions object.
-        */
-
-       JackCommandLineOptions options;
-
-       get_jack_default_server_path (options.server_path);
-       options.driver = _target_driver;
-       options.samplerate = _target_sample_rate;
-       options.period_size = _target_buffer_size;
-       options.num_periods = 2;
-       options.input_device = _target_device;
-       options.output_device = _target_device;
-       options.input_latency = _target_systemic_input_latency;
-       options.output_latency = _target_systemic_output_latency;
-       options.input_channels = _target_input_channels;
-       options.output_channels = _target_output_channels;
-       if (_target_sample_format == FormatInt16) {
-               options.force16_bit = _target_sample_format;
-       }
-       options.realtime = true;
-       options.ports_max = 2048;
-       
-       /* this must always be true for any server instance we start ourselves
-        */
-
-       options.temporary = true;
-
-       string cmdline;
-
-       if (!get_jack_command_line_string (options, cmdline)) {
-               /* error, somehow */
-               return;
-       }
-
-       std::cerr << "JACK command line will be: " << cmdline << std::endl;
-
-       write_jack_config_file (get_jack_server_user_config_file_path(), cmdline);
-}
-
-/* ---- BASIC STATE CONTROL API: start/stop/pause/freewheel --- */
-
-int
-JACKAudioBackend::start ()
-{
-       if (!connected()) {
-
-               if (!_jack_connection->server_running()) {
-                       setup_jack_startup_command ();
-               }
-
-               if (_jack_connection->open ()) {
-                       return -1;
-               }
-       }
-       
-       GET_PRIVATE_JACK_POINTER_RET (_priv_jack, -1);
-
-       /* get the buffer size and sample rates established */
-
-       jack_sample_rate_callback (jack_get_sample_rate (_priv_jack));
-       jack_bufsize_callback (jack_get_buffer_size (_priv_jack));
-       
-       /* Now that we have buffer size and sample rate established, the engine 
-          can go ahead and do its stuff
-       */
-       
-       engine.reestablish_ports ();
-
-       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;
-       }
-       
-       set_jack_callbacks ();
-       
-       if (jack_activate (_priv_jack) == 0) {
-               _running = true;
-       } else {
-               // error << _("cannot activate JACK client") << endmsg;
-       }
-
-       engine.reconnect_ports ();
-
-       return 0;
-}
-
-int
-JACKAudioBackend::stop ()
-{
-       GET_PRIVATE_JACK_POINTER_RET (_priv_jack, -1);
-       
-       _jack_connection->close ();
-
-       _current_buffer_size = 0;
-       _current_sample_rate = 0;
-
-       _raw_buffer_sizes.clear();
-
-       return 0;
-}
-
-int
-JACKAudioBackend::pause ()
-{
-       GET_PRIVATE_JACK_POINTER_RET (_priv_jack, -1);
-
-       if (_priv_jack) {
-               jack_deactivate (_priv_jack);
-       }
-
-       return 0;
-}
-
-int
-JACKAudioBackend::freewheel (bool onoff)
-{
-       GET_PRIVATE_JACK_POINTER_RET (_priv_jack, -1);
-
-       if (onoff == _freewheeling) {
-               /* already doing what has been asked for */
-               
-               return 0;
-       }
-
-       if (jack_set_freewheel (_priv_jack, onoff) == 0) {
-               _freewheeling = true;
-               return 0;
-       }
-
-       return -1;
-}
-
-/* --- TRANSPORT STATE MANAGEMENT --- */
-
-void
-JACKAudioBackend::transport_stop ()
-{
-       GET_PRIVATE_JACK_POINTER (_priv_jack);
-       jack_transport_stop (_priv_jack);
-}
-
-void
-JACKAudioBackend::transport_start ()
-{
-       GET_PRIVATE_JACK_POINTER (_priv_jack);
-       jack_transport_start (_priv_jack);
-}
-
-void
-JACKAudioBackend::transport_locate (framepos_t where)
-{
-       GET_PRIVATE_JACK_POINTER (_priv_jack);
-       jack_transport_locate (_priv_jack, where);
-}
-
-framepos_t 
-JACKAudioBackend::transport_frame () const 
-{
-       GET_PRIVATE_JACK_POINTER_RET (_priv_jack, 0);
-       return jack_get_current_transport_frame (_priv_jack);
-}
-
-TransportState
-JACKAudioBackend::transport_state () const
-{
-       GET_PRIVATE_JACK_POINTER_RET (_priv_jack, ((TransportState) JackTransportStopped));
-       jack_position_t pos;
-       return (TransportState) jack_transport_query (_priv_jack, &pos);
-}
-
-int
-JACKAudioBackend::set_time_master (bool yn)
-{
-       GET_PRIVATE_JACK_POINTER_RET (_priv_jack, -1);
-       if (yn) {
-               return jack_set_timebase_callback (_priv_jack, 0, _jack_timebase_callback, this);
-       } else {
-               return jack_release_timebase (_priv_jack);
-       }
-}
-
-/* process-time */
-
-bool
-JACKAudioBackend::get_sync_offset (pframes_t& offset) const
-{
-
-#ifdef HAVE_JACK_VIDEO_SUPPORT
-
-       GET_PRIVATE_JACK_POINTER_RET (_priv_jack, false);
-
-       jack_position_t pos;
-
-       if (_priv_jack) {
-               (void) jack_transport_query (_priv_jack, &pos);
-
-               if (pos.valid & JackVideoFrameOffset) {
-                       offset = pos.video_offset;
-                       return true;
-               }
-       }
-#else
-       /* keep gcc happy */
-       offset = 0;
-#endif
-
-       return false;
-}
-
-pframes_t
-JACKAudioBackend::sample_time ()
-{
-       GET_PRIVATE_JACK_POINTER_RET (_priv_jack, 0);
-       return jack_frame_time (_priv_jack);
-}
-
-pframes_t
-JACKAudioBackend::sample_time_at_cycle_start ()
-{
-       GET_PRIVATE_JACK_POINTER_RET (_priv_jack, 0);
-       return jack_last_frame_time (_priv_jack);
-}
-
-pframes_t
-JACKAudioBackend::samples_since_cycle_start ()
-{
-       GET_PRIVATE_JACK_POINTER_RET (_priv_jack, 0);
-       return jack_frames_since_cycle_start (_priv_jack);
-}
-
-/* JACK Callbacks */
-
-static void
-ardour_jack_error (const char* msg)
-{
-       error << "JACK: " << msg << endmsg;
-}
-
-void
-JACKAudioBackend::set_jack_callbacks ()
-{
-       GET_PRIVATE_JACK_POINTER (_priv_jack);
-
-        jack_set_thread_init_callback (_priv_jack, AudioEngine::thread_init_callback, 0);
-
-        jack_set_process_thread (_priv_jack, _process_thread, this);
-        jack_set_sample_rate_callback (_priv_jack, _sample_rate_callback, this);
-        jack_set_buffer_size_callback (_priv_jack, _bufsize_callback, this);
-        jack_set_xrun_callback (_priv_jack, _xrun_callback, this);
-        jack_set_sync_callback (_priv_jack, _jack_sync_callback, this);
-        jack_set_freewheel_callback (_priv_jack, _freewheel_callback, this);
-
-#ifdef HAVE_JACK_SESSION
-        if( jack_set_session_callback)
-                jack_set_session_callback (_priv_jack, _session_callback, this);
-#endif
-
-        if (jack_set_latency_callback) {
-                jack_set_latency_callback (_priv_jack, _latency_callback, this);
-        }
-
-        jack_set_error_function (ardour_jack_error);
-}
-
-void
-JACKAudioBackend::_jack_timebase_callback (jack_transport_state_t state, pframes_t nframes,
-                                     jack_position_t* pos, int new_position, void *arg)
-{
-       static_cast<JACKAudioBackend*> (arg)->jack_timebase_callback (state, nframes, pos, new_position);
-}
-
-void
-JACKAudioBackend::jack_timebase_callback (jack_transport_state_t state, pframes_t nframes,
-                                         jack_position_t* pos, int new_position)
-{
-       ARDOUR::Session* session = engine.session();
-
-       if (session) {
-               session->jack_timebase_callback (state, nframes, pos, new_position);
-       }
-}
-
-int
-JACKAudioBackend::_jack_sync_callback (jack_transport_state_t state, jack_position_t* pos, void* arg)
-{
-       return static_cast<JACKAudioBackend*> (arg)->jack_sync_callback (state, pos);
-}
-
-int
-JACKAudioBackend::jack_sync_callback (jack_transport_state_t state, jack_position_t* pos)
-{
-       TransportState tstate;
-
-       switch (state) {
-       case JackTransportStopped:
-               tstate = TransportStopped;
-               break;
-       case JackTransportRolling:
-               tstate = TransportRolling;
-               break;
-       case JackTransportLooping:
-               tstate = TransportLooping;
-               break;
-       case JackTransportStarting:
-               tstate = TransportStarting;
-               break;
-       }
-
-       return engine.sync_callback (tstate, pos->frame);
-
-       return true;
-}
-
-int
-JACKAudioBackend::_xrun_callback (void *arg)
-{
-       JACKAudioBackend* ae = static_cast<JACKAudioBackend*> (arg);
-       if (ae->connected()) {
-               ae->engine.Xrun (); /* EMIT SIGNAL */
-       }
-       return 0;
-}
-
-#ifdef HAVE_JACK_SESSION
-void
-JACKAudioBackend::_session_callback (jack_session_event_t *event, void *arg)
-{
-       JACKAudioBackend* ae = static_cast<JACKAudioBackend*> (arg);
-       ARDOUR::Session* session = ae->engine.session();
-
-       if (session) {
-               session->jack_session_event (event);
-       }
-}
-#endif
-
-void
-JACKAudioBackend::_freewheel_callback (int onoff, void *arg)
-{
-       static_cast<JACKAudioBackend*>(arg)->freewheel_callback (onoff);
-}
-
-void
-JACKAudioBackend::freewheel_callback (int onoff)
-{
-       _freewheeling = onoff;
-       engine.freewheel_callback (onoff);
-}
-
-void
-JACKAudioBackend::_latency_callback (jack_latency_callback_mode_t mode, void* arg)
-{
-       return static_cast<JACKAudioBackend*> (arg)->jack_latency_callback (mode);
-}
-
-int
-JACKAudioBackend::create_process_thread (boost::function<void()> f, pthread_t* thread, size_t stacksize)
-{
-        GET_PRIVATE_JACK_POINTER_RET (_priv_jack, 0);
-        ThreadData* td = new ThreadData (this, f, stacksize);
-
-        if (jack_client_create_thread (_priv_jack, thread, jack_client_real_time_priority (_priv_jack),
-                                       jack_is_realtime (_priv_jack), _start_process_thread, td)) {
-                return -1;
-        }
-
-        return 0;
-}
-
-void*
-JACKAudioBackend::_start_process_thread (void* arg)
-{
-        ThreadData* td = reinterpret_cast<ThreadData*> (arg);
-        boost::function<void()> f = td->f;
-        delete td;
-
-        f ();
-
-        return 0;
-}
-
-void*
-JACKAudioBackend::_process_thread (void *arg)
-{
-       return static_cast<JACKAudioBackend*> (arg)->process_thread ();
-}
-
-void*
-JACKAudioBackend::process_thread ()
-{
-        /* JACK doesn't do this for us when we use the wait API
-         */
-
-        AudioEngine::thread_init_callback (this);
-
-        while (1) {
-                GET_PRIVATE_JACK_POINTER_RET(_priv_jack,0);
-
-                pframes_t nframes = jack_cycle_wait (_priv_jack);
-               
-                if (engine.process_callback (nframes)) {
-                        return 0;
-                }
-
-               jack_cycle_signal (_priv_jack, 0);
-        }
-
-        return 0;
-}
-
-int
-JACKAudioBackend::_sample_rate_callback (pframes_t nframes, void *arg)
-{
-       return static_cast<JACKAudioBackend*> (arg)->jack_sample_rate_callback (nframes);
-}
-
-int
-JACKAudioBackend::jack_sample_rate_callback (pframes_t nframes)
-{
-       _current_sample_rate = nframes;
-       return engine.sample_rate_change (nframes);
-}
-
-void
-JACKAudioBackend::jack_latency_callback (jack_latency_callback_mode_t mode)
-{
-       engine.latency_callback (mode == JackPlaybackLatency);
-}
-
-int
-JACKAudioBackend::_bufsize_callback (pframes_t nframes, void *arg)
-{
-       return static_cast<JACKAudioBackend*> (arg)->jack_bufsize_callback (nframes);
-}
-
-int
-JACKAudioBackend::jack_bufsize_callback (pframes_t nframes)
-{
-        /* if the size has not changed, this should be a no-op */
-
-        if (nframes == _current_buffer_size) {
-                return 0;
-        }
-
-       GET_PRIVATE_JACK_POINTER_RET (_priv_jack, 1);
-
-       _current_buffer_size = nframes;
-
-        if (jack_port_type_get_buffer_size) {
-                _raw_buffer_sizes[DataType::AUDIO] = jack_port_type_get_buffer_size (_priv_jack, JACK_DEFAULT_AUDIO_TYPE);
-                _raw_buffer_sizes[DataType::MIDI] = jack_port_type_get_buffer_size (_priv_jack, JACK_DEFAULT_MIDI_TYPE);
-        } else {
-
-                /* Old version of JACK.
-
-                   These crude guesses, see below where we try to get the right answers.
-
-                   Note that our guess for MIDI deliberatey tries to overestimate
-                   by a little. It would be nicer if we could get the actual
-                   size from a port, but we have to use this estimate in the
-                   event that there are no MIDI ports currently. If there are
-                   the value will be adjusted below.
-                */
-
-                _raw_buffer_sizes[DataType::AUDIO] = nframes * sizeof (Sample);
-                _raw_buffer_sizes[DataType::MIDI] = nframes * 4 - (nframes/2);
-        }
-
-       engine.buffer_size_change (nframes);
-
-       return 0;
-}
-
-void
-JACKAudioBackend::disconnected (const char* why)
-{
-       bool was_running = _running;
-
-        _running = false;
-        _current_buffer_size = 0;
-        _current_sample_rate = 0;
-
-        if (was_running) {
-               engine.halted_callback (why); /* EMIT SIGNAL */
-        }
-}
-float 
-JACKAudioBackend::cpu_load() const 
-{
-       GET_PRIVATE_JACK_POINTER_RET(_priv_jack,0);
-       return jack_cpu_load (_priv_jack);
-}
-
-void
-JACKAudioBackend::update_latencies ()
-{
-       GET_PRIVATE_JACK_POINTER (_priv_jack);
-       jack_recompute_total_latencies (_priv_jack);
-}
-
-ChanCount
-JACKAudioBackend::n_physical (unsigned long flags) const
-{
-       ChanCount c;
-
-       GET_PRIVATE_JACK_POINTER_RET (_priv_jack, c);
-
-       const char ** ports = jack_get_ports (_priv_jack, NULL, NULL, JackPortIsPhysical | flags);
-
-       if (ports) {
-               for (uint32_t i = 0; ports[i]; ++i) {
-                       if (!strstr (ports[i], "Midi-Through")) {
-                               DataType t (jack_port_type (jack_port_by_name (_priv_jack, ports[i])));
-                               c.set (t, c.get (t) + 1);
-                       }
-               }
-               
-               jack_free (ports);
-       }
-
-       return c;
-}
diff --git a/libs/ardour/jack_connection.cc b/libs/ardour/jack_connection.cc
deleted file mode 100644 (file)
index 5772d3d..0000000
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
-    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 <boost/scoped_ptr.hpp>
-#include <jack/session.h>
-
-#include "pbd/epa.h"
-
-#include "ardour/jack_connection.h"
-#include "ardour/jack_utils.h"
-
-#define GET_PRIVATE_JACK_POINTER(j)  jack_client_t* _priv_jack = (jack_client_t*) (j); if (!_priv_jack) { return; }
-#define GET_PRIVATE_JACK_POINTER_RET(j,r) jack_client_t* _priv_jack = (jack_client_t*) (j); if (!_priv_jack) { return r; }
-
-using namespace ARDOUR;
-using namespace PBD;
-using std::string;
-using std::vector;
-
-static void jack_halted_callback (void* arg)
-{
-       JackConnection* jc = static_cast<JackConnection*> (arg);
-       jc->halted_callback ();
-}
-
-static void jack_halted_info_callback (jack_status_t code, const char* reason, void* arg)
-{
-       JackConnection* jc = static_cast<JackConnection*> (arg);
-       jc->halted_info_callback (code, reason);
-}
-
-
-JackConnection::JackConnection (const std::string& arg1, const std::string& arg2)
-       : _jack (0)
-       , _client_name (arg1)
-       , session_uuid (arg2)
-{
-}
-
-JackConnection::~JackConnection ()
-{
-       close ();
-}
-
-bool
-JackConnection::server_running ()
-{
-        EnvironmentalProtectionAgency* global_epa = EnvironmentalProtectionAgency::get_global_epa ();
-        boost::scoped_ptr<EnvironmentalProtectionAgency> current_epa;
-
-        /* revert all environment settings back to whatever they were when
-        * ardour started, because ardour's startup script may have reset
-        * something in ways that interfere with finding/starting JACK.
-         */
-
-        if (global_epa) {
-                current_epa.reset (new EnvironmentalProtectionAgency(true)); /* will restore settings when we leave scope */
-                global_epa->restore ();
-        }
-
-       jack_status_t status;
-       jack_client_t* c = jack_client_open ("ardourprobe", JackNoStartServer, &status);
-
-       if (status == 0) {
-               jack_client_close (c);
-               return true;
-       }
-
-       return false;
-}
-
-int
-JackConnection::open ()
-{
-        EnvironmentalProtectionAgency* global_epa = EnvironmentalProtectionAgency::get_global_epa ();
-        boost::scoped_ptr<EnvironmentalProtectionAgency> current_epa;
-       jack_status_t status;
-
-       close ();
-
-        /* revert all environment settings back to whatever they were when ardour started
-         */
-
-        if (global_epa) {
-                current_epa.reset (new EnvironmentalProtectionAgency(true)); /* will restore settings when we leave scope */
-                global_epa->restore ();
-        }
-
-       /* ensure that PATH or equivalent includes likely locations of the JACK
-        * server, in case the user's default does not.
-        */
-
-       vector<string> dirs;
-       get_jack_server_dir_paths (dirs);
-       set_path_env_for_jack_autostart (dirs);
-
-       if ((_jack = jack_client_open (_client_name.c_str(), JackSessionID, &status, session_uuid.c_str())) == 0) {
-               return -1;
-       }
-
-       if (status & JackNameNotUnique) {
-               _client_name = jack_get_client_name (_jack);
-       }
-
-       /* attach halted handler */
-
-        if (jack_on_info_shutdown) {
-                jack_on_info_shutdown (_jack, jack_halted_info_callback, this);
-        } else {
-                jack_on_shutdown (_jack, jack_halted_callback, this);
-        }
-
-
-       Connected(); /* EMIT SIGNAL */
-
-       return 0;
-}
-
-int
-JackConnection::close ()
-{
-       GET_PRIVATE_JACK_POINTER_RET (_jack, -1);
-
-       if (_priv_jack) {
-               int ret = jack_client_close (_priv_jack);
-               _jack = 0;
-               Disconnected (""); /* EMIT SIGNAL */
-               return ret;
-       }
-
-       return 0;
-}
-
-void
-JackConnection::halted_callback ()
-{
-       _jack = 0;
-       Disconnected ("");
-}
-
-void
-JackConnection::halted_info_callback (jack_status_t /*status*/, const char* reason)
-{
-       _jack = 0;
-       Disconnected (reason);
-}
-
-
diff --git a/libs/ardour/jack_portengine.cc b/libs/ardour/jack_portengine.cc
deleted file mode 100644 (file)
index 4595857..0000000
+++ /dev/null
@@ -1,568 +0,0 @@
-/*
-    Copyright (C) 2013 Paul Davis
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-#include <string.h>
-#include <stdint.h>
-
-#include "pbd/error.h"
-
-#include "ardour/jack_portengine.h"
-#include "ardour/jack_connection.h"
-#include "ardour/port_manager.h"
-
-#include "i18n.h"
-
-using namespace ARDOUR;
-using namespace PBD;
-using std::string;
-using std::vector;
-
-#define GET_PRIVATE_JACK_POINTER(localvar)  jack_client_t* localvar = _jack_connection->jack(); if (!(localvar)) { return; }
-#define GET_PRIVATE_JACK_POINTER_RET(localvar,r) jack_client_t* localvar = _jack_connection->jack(); if (!(localvar)) { return r; }
-
-static uint32_t
-ardour_port_flags_to_jack_flags (PortFlags flags)
-{
-       uint32_t jack_flags = 0;
-       
-       if (flags & IsInput) {
-               jack_flags |= JackPortIsInput;
-       }
-       if (flags & IsOutput) {
-               jack_flags |= JackPortIsOutput;
-       }
-       if (flags & IsTerminal) {
-               jack_flags |= JackPortIsTerminal;
-       }
-       if (flags & IsPhysical) {
-               jack_flags |= JackPortIsPhysical;
-       }
-       if (flags & CanMonitor) {
-               jack_flags |= JackPortCanMonitor;
-       }
-
-       return jack_flags;
-}
-
-static DataType
-jack_port_type_to_ardour_data_type (const char* jack_type)
-{
-       if (strcmp (jack_type, JACK_DEFAULT_AUDIO_TYPE) == 0) {
-               return DataType::AUDIO;
-       } else if (strcmp (jack_type, JACK_DEFAULT_MIDI_TYPE) == 0) {
-               return DataType::MIDI;
-       }
-       return DataType::NIL;
-}
-
-static const char*
-ardour_data_type_to_jack_port_type (DataType d)
-{
-       switch (d) {
-       case DataType::AUDIO:
-               return JACK_DEFAULT_AUDIO_TYPE;
-       case DataType::MIDI:
-               return JACK_DEFAULT_MIDI_TYPE;
-       }
-
-       return "";
-}
-
-JACKPortEngine::JACKPortEngine (PortManager& pm, boost::shared_ptr<JackConnection> jc)
-       : PortEngine (pm)
-       , _jack_connection (jc)
-{
-       _jack_connection->Connected.connect_same_thread (jack_connection_connection, boost::bind (&JACKPortEngine::connected_to_jack, this));
-}
-
-JACKPortEngine::~JACKPortEngine ()
-{
-       /* a default destructor would do this, and so would this one,
-          but we'll make it explicit in case we ever need to debug
-          the lifetime of the JACKConnection
-       */
-       _jack_connection.reset ();
-}
-
-void
-JACKPortEngine::connected_to_jack ()
-{
-       /* register callbacks for stuff that is our responsibility */
-
-       jack_client_t* client = _jack_connection->jack();
-
-       if (!client) {
-               /* how could this happen? it could ... */
-               error << _("Already disconnected from JACK before PortEngine could register callbacks") << endmsg;
-               return;
-       }
-
-        jack_set_port_registration_callback (client, _registration_callback, this);
-        jack_set_port_connect_callback (client, _connect_callback, this);
-        jack_set_graph_order_callback (client, _graph_order_callback, this);
-}
-
-void*
-JACKPortEngine::private_handle() const
-{
-       return _jack_connection->jack();
-}
-
-bool
-JACKPortEngine::connected() const
-{
-       return _jack_connection->connected();
-}
-
-int
-JACKPortEngine::set_port_name (PortHandle port, const std::string& name)
-{
-       return jack_port_set_name ((jack_port_t*) port, name.c_str());
-}
-
-string
-JACKPortEngine::get_port_name (PortHandle port) const
-{
-       return jack_port_name ((jack_port_t*) port);
-}
-
-PortEngine::PortHandle*
-JACKPortEngine:: get_port_by_name (const std::string& name) const
-{
-       GET_PRIVATE_JACK_POINTER_RET (_priv_jack, 0);
-       return (PortHandle*) jack_port_by_name (_priv_jack, name.c_str());
-}
-
-void
-JACKPortEngine::_registration_callback (jack_port_id_t /*id*/, int /*reg*/, void* arg)
-{
-       static_cast<JACKPortEngine*> (arg)->manager.registration_callback ();
-}
-
-int
-JACKPortEngine::_graph_order_callback (void *arg)
-{
-       return static_cast<JACKPortEngine*> (arg)->manager.graph_order_callback ();
-}
-
-void
-JACKPortEngine::_connect_callback (jack_port_id_t id_a, jack_port_id_t id_b, int conn, void* arg)
-{
-       static_cast<JACKPortEngine*> (arg)->connect_callback (id_a, id_b, conn);
-}
-
-void
-JACKPortEngine::connect_callback (jack_port_id_t id_a, jack_port_id_t id_b, int conn)
-{
-       if (manager.port_remove_in_progress()) {
-               return;
-       }
-
-       GET_PRIVATE_JACK_POINTER (_priv_jack);
-
-       jack_port_t* a = jack_port_by_id (_priv_jack, id_a);
-       jack_port_t* b = jack_port_by_id (_priv_jack, id_b);
-
-       manager.connect_callback (jack_port_name (a), jack_port_name (b), conn == 0 ? false : true);
-}
-
-bool
-JACKPortEngine::connected (PortHandle port, bool process_callback_safe)
-{
-       bool ret = false;
-
-       const char** ports;
-
-       if (process_callback_safe) {
-               ports = jack_port_get_connections ((jack_port_t*)port);
-       } else {
-               GET_PRIVATE_JACK_POINTER_RET (_priv_jack, false);
-               ports = jack_port_get_all_connections (_priv_jack, (jack_port_t*)port);
-       }
-
-       if (ports) {
-               ret = true;
-       }
-
-       jack_free (ports);
-
-       return ret;
-}
-
-bool
-JACKPortEngine::connected_to (PortHandle port, const std::string& other, bool process_callback_safe)
-{
-       bool ret = false;
-       const char** ports;
-
-       if (process_callback_safe) {
-               ports = jack_port_get_connections ((jack_port_t*)port);
-       } else {
-               GET_PRIVATE_JACK_POINTER_RET (_priv_jack, false);
-               ports = jack_port_get_all_connections (_priv_jack, (jack_port_t*)port);
-       }
-
-       if (ports) {
-               for (int i = 0; ports[i]; ++i) {
-                       if (other == ports[i]) {
-                               ret = true;
-                       }
-               }
-               jack_free (ports);
-       }
-
-       return ret;
-}
-
-bool
-JACKPortEngine::physically_connected (PortHandle p, bool process_callback_safe)
-{
-       GET_PRIVATE_JACK_POINTER_RET (_priv_jack, false);
-       jack_port_t* port = (jack_port_t*) p;
-
-       const char** ports;
-       
-       if (process_callback_safe) {
-               ports = jack_port_get_connections ((jack_port_t*)port);
-       } else {
-               GET_PRIVATE_JACK_POINTER_RET (_priv_jack, false);
-               ports = jack_port_get_all_connections (_priv_jack, (jack_port_t*)port);
-       }
-
-       if (ports) {
-               for (int i = 0; ports[i]; ++i) {
-
-                       jack_port_t* other = jack_port_by_name (_priv_jack, ports[i]);
-
-                       if (other && (jack_port_flags (other) & JackPortIsPhysical)) {
-                               return true;
-                       }
-               }
-               jack_free (ports);
-       }
-
-       return false;
-}
-
-int
-JACKPortEngine::get_connections (PortHandle port, vector<string>& s, bool process_callback_safe)
-{
-       const char** ports;
-
-       if (process_callback_safe) {
-               ports = jack_port_get_connections ((jack_port_t*)port);
-       } else {
-               GET_PRIVATE_JACK_POINTER_RET (_priv_jack, 0);
-               ports = jack_port_get_all_connections (_priv_jack, (jack_port_t*)port);
-       }
-
-       if (ports) {
-               for (int i = 0; ports[i]; ++i) {
-                       s.push_back (ports[i]);
-               }
-               jack_free (ports);
-       }
-
-       return s.size();
-}
-
-DataType
-JACKPortEngine::port_data_type (PortHandle p) const
-{
-       return jack_port_type_to_ardour_data_type (jack_port_type ((jack_port_t*) p));
-}
-
-const string&
-JACKPortEngine::my_name() const
-{
-       return _jack_connection->client_name();
-}
-
-bool
-JACKPortEngine::port_is_physical (PortHandle ph) const
-{
-       if (!ph) {
-                return false;
-        }
-
-        return jack_port_flags ((jack_port_t*) ph) & JackPortIsPhysical;
-}
-
-int
-JACKPortEngine::get_ports (const string& port_name_pattern, DataType type, PortFlags flags, vector<string>& s) const
-{
-
-       GET_PRIVATE_JACK_POINTER_RET (_priv_jack,0);
-
-       const char** ports =  jack_get_ports (_priv_jack, port_name_pattern.c_str(), 
-                                             ardour_data_type_to_jack_port_type (type), 
-                                             ardour_port_flags_to_jack_flags (flags));
-
-       if (ports == 0) {
-               return 0;
-       }
-
-       for (uint32_t i = 0; ports[i]; ++i) {
-               s.push_back (ports[i]);
-       }
-
-       jack_free (ports);
-       
-       return s.size();
-}
-
-ChanCount
-JACKPortEngine::n_physical (unsigned long flags) const
-{
-       ChanCount c;
-
-       GET_PRIVATE_JACK_POINTER_RET (_priv_jack, c);
-
-       const char ** ports = jack_get_ports (_priv_jack, NULL, NULL, JackPortIsPhysical | flags);
-
-       if (ports) {
-               for (uint32_t i = 0; ports[i]; ++i) {
-                       if (!strstr (ports[i], "Midi-Through")) {
-                               DataType t = port_data_type (jack_port_by_name (_priv_jack, ports[i]));
-                               if (t != DataType::NIL) {
-                                       c.set (t, c.get (t) + 1);
-                               }
-                       }
-               }
-               
-               jack_free (ports);
-       }
-
-       return c;
-}
-
-ChanCount
-JACKPortEngine::n_physical_inputs () const
-{
-       return n_physical (JackPortIsInput);
-}
-
-ChanCount
-JACKPortEngine::n_physical_outputs () const
-{
-       return n_physical (JackPortIsOutput);
-}
-
-void
-JACKPortEngine::get_physical (DataType type, unsigned long flags, vector<string>& phy) const
-{
-       GET_PRIVATE_JACK_POINTER (_priv_jack);
-       const char ** ports;
-
-       if ((ports = jack_get_ports (_priv_jack, NULL, ardour_data_type_to_jack_port_type (type), JackPortIsPhysical | flags)) == 0) {
-               return;
-       }
-
-       if (ports) {
-               for (uint32_t i = 0; ports[i]; ++i) {
-                        if (strstr (ports[i], "Midi-Through")) {
-                                continue;
-                        }
-                       phy.push_back (ports[i]);
-               }
-               jack_free (ports);
-       }
-}
-
-/** Get physical ports for which JackPortIsOutput is set; ie those that correspond to
- *  a physical input connector.
- */
-void
-JACKPortEngine::get_physical_inputs (DataType type, vector<string>& ins)
-{
-       get_physical (type, JackPortIsOutput, ins);
-}
-
-/** Get physical ports for which JackPortIsInput is set; ie those that correspond to
- *  a physical output connector.
- */
-void
-JACKPortEngine::get_physical_outputs (DataType type, vector<string>& outs)
-{
-       get_physical (type, JackPortIsInput, outs);
-}
-
-
-bool
-JACKPortEngine::can_monitor_input () const
-{
-       GET_PRIVATE_JACK_POINTER_RET (_priv_jack,false);
-       const char ** ports;
-
-       if ((ports = jack_get_ports (_priv_jack, NULL, JACK_DEFAULT_AUDIO_TYPE, JackPortCanMonitor)) == 0) {
-               return false;
-       }
-
-       jack_free (ports);
-
-       return true;
-}
-
-int
-JACKPortEngine::request_input_monitoring (PortHandle port, bool yn)
-{
-       return jack_port_request_monitor ((jack_port_t*) port, yn);
-}
-int
-JACKPortEngine::ensure_input_monitoring (PortHandle port, bool yn)
-{
-       return jack_port_ensure_monitor ((jack_port_t*) port, yn);
-}
-bool
-JACKPortEngine::monitoring_input (PortHandle port)
-{
-       return jack_port_monitoring_input ((jack_port_t*) port);
-}
-
-
-pframes_t
-JACKPortEngine::sample_time_at_cycle_start ()
-{
-       GET_PRIVATE_JACK_POINTER_RET (_priv_jack, 0);
-       return jack_last_frame_time (_priv_jack);
-}
-
-
-PortEngine::PortHandle
-JACKPortEngine::register_port (const std::string& shortname, ARDOUR::DataType type, ARDOUR::PortFlags flags)
-{
-       GET_PRIVATE_JACK_POINTER_RET (_priv_jack, 0);
-       return jack_port_register (_priv_jack, shortname.c_str(), 
-                                  ardour_data_type_to_jack_port_type (type),
-                                  ardour_port_flags_to_jack_flags (flags),
-                                  0);
-}
-
-void
-JACKPortEngine::unregister_port (PortHandle port)
-{
-       GET_PRIVATE_JACK_POINTER (_priv_jack);
-       (void) jack_port_unregister (_priv_jack, (jack_port_t*) port);
-}
-
-int
-JACKPortEngine::connect (PortHandle port, const std::string& other)
-{
-       GET_PRIVATE_JACK_POINTER_RET (_priv_jack, -1);
-       return jack_connect (_priv_jack, jack_port_name ((jack_port_t*) port), other.c_str());
-}
-int
-JACKPortEngine::connect (const std::string& src, const std::string& dst)
-{
-       GET_PRIVATE_JACK_POINTER_RET (_priv_jack, -1);
-       
-       int r = jack_connect (_priv_jack, src.c_str(), dst.c_str());
-       return r;
-}
-
-int
-JACKPortEngine::disconnect (PortHandle port, const std::string& other)
-{
-       GET_PRIVATE_JACK_POINTER_RET (_priv_jack, -1);
-       return jack_disconnect (_priv_jack, jack_port_name ((jack_port_t*) port), other.c_str());
-}
-
-int
-JACKPortEngine::disconnect (const std::string& src, const std::string& dst)
-{
-       GET_PRIVATE_JACK_POINTER_RET (_priv_jack, -1);
-       return jack_disconnect (_priv_jack, src.c_str(), dst.c_str());
-}
-
-int
-JACKPortEngine::disconnect_all (PortHandle port)
-{
-       GET_PRIVATE_JACK_POINTER_RET (_priv_jack, -1);
-       return jack_port_disconnect (_priv_jack, (jack_port_t*) port);
-}
-
-int
-JACKPortEngine::midi_event_get (pframes_t& timestamp, size_t& size, uint8_t** buf, void* port_buffer, uint32_t event_index)
-{
-       jack_midi_event_t ev;
-       int ret;
-
-       if ((ret = jack_midi_event_get (&ev, port_buffer, event_index)) == 0) {
-               timestamp = ev.time;
-               size = ev.size;
-               *buf = ev.buffer;
-       }
-
-       return ret;
-}
-
-int
-JACKPortEngine::midi_event_put (void* port_buffer, pframes_t timestamp, const uint8_t* buffer, size_t size)
-{
-       return jack_midi_event_write (port_buffer, timestamp, buffer, size);
-}
-
-uint32_t
-JACKPortEngine::get_midi_event_count (void* port_buffer)
-{
-       return jack_midi_get_event_count (port_buffer);
-}
-
-void
-JACKPortEngine::midi_clear (void* port_buffer)
-{
-       jack_midi_clear_buffer (port_buffer);
-}
-
-void
-JACKPortEngine::set_latency_range (PortHandle port, bool for_playback, LatencyRange r)
-{
-       jack_latency_range_t range;
-       
-       range.min = r.min;
-       range.max = r.max;
-
-       jack_port_set_latency_range ((jack_port_t*) port, for_playback ? JackPlaybackLatency : JackCaptureLatency, &range);
-}
-
-LatencyRange
-JACKPortEngine::get_latency_range (PortHandle port, bool for_playback)
-{
-       jack_latency_range_t range;
-       LatencyRange ret;
-       
-       jack_port_get_latency_range ((jack_port_t*) port, for_playback ? JackPlaybackLatency : JackCaptureLatency, &range);
-
-       ret.min = range.min;
-       ret.max = range.max;
-
-       return ret;
-}
-
-void*
-JACKPortEngine::get_buffer (PortHandle port, pframes_t nframes)
-{
-       return jack_port_get_buffer ((jack_port_t*) port, nframes);
-}
-
-uint32_t
-JACKPortEngine::port_name_size() const
-{
-       return jack_port_name_size ();
-}
diff --git a/libs/ardour/jack_slave.cc b/libs/ardour/jack_slave.cc
deleted file mode 100644 (file)
index 4b2f3b1..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
-    Copyright (C) 2004 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 <iostream>
-#include <cerrno>
-
-#include "ardour/audioengine.h"
-#include "ardour/slave.h"
-
-using namespace std;
-using namespace ARDOUR;
-
-JACK_Slave::JACK_Slave (AudioEngine& e)
-       : engine (e)
-{
-       double x;
-       framepos_t p;
-       /* call this to initialize things */
-       speed_and_position (x, p);
-}
-
-JACK_Slave::~JACK_Slave ()
-{
-}
-
-bool
-JACK_Slave::locked() const
-{
-       return true;
-}
-
-bool
-JACK_Slave::ok() const
-{
-       return true;
-}
-
-bool
-JACK_Slave::speed_and_position (double& sp, framepos_t& position)
-{
-       switch (engine.transport_state()) {
-       case TransportStopped:
-               speed = 0;
-               _starting = false;
-               break;
-       case TransportRolling:
-               speed = 1.0;
-               _starting = false;
-               break;
-       case TransportLooping:
-               speed = 1.0;
-               _starting = false;
-               break;
-       case TransportStarting:
-               _starting = true;
-               // don't adjust speed here, just leave it as it was
-               break;
-       }
-
-       sp = speed;
-       position = engine.transport_frame();
-       return true;
-}
diff --git a/libs/ardour/jack_utils.cc b/libs/ardour/jack_utils.cc
deleted file mode 100644 (file)
index 4e2392a..0000000
+++ /dev/null
@@ -1,901 +0,0 @@
-/*
-    Copyright (C) 2010 Paul Davis
-    Copyright (C) 2011 Tim Mayberry
-
-    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.
-
-*/
-
-#ifdef WAF_BUILD
-#include "libardour-config.h"
-#endif
-
-#ifdef HAVE_ALSA
-#include <alsa/asoundlib.h>
-#endif
-
-#ifdef __APPLE__
-#include <CoreAudio/CoreAudio.h>
-#include <CoreFoundation/CFString.h>
-#include <sys/param.h>
-#include <mach-o/dyld.h>
-#endif
-
-#ifdef HAVE_PORTAUDIO
-#include <portaudio.h>
-#endif
-
-#include <jack/jack.h>
-
-#include <fstream>
-
-#include <boost/scoped_ptr.hpp>
-
-#include <glibmm/miscutils.h>
-
-#include "pbd/epa.h"
-#include "pbd/error.h"
-#include "pbd/convert.h"
-#include "pbd/file_utils.h"
-#include "pbd/search_path.h"
-
-#include "ardour/jack_utils.h"
-
-#ifdef __APPLE
-#include <CFBundle.h>
-#endif
-
-#include "i18n.h"
-
-using namespace std;
-using namespace PBD;
-
-namespace ARDOUR {
-       // The pretty driver names
-       const char * const portaudio_driver_name = X_("Portaudio");
-       const char * const coreaudio_driver_name = X_("CoreAudio");
-       const char * const alsa_driver_name = X_("ALSA");
-       const char * const oss_driver_name = X_("OSS");
-       const char * const freebob_driver_name = X_("FreeBoB");
-       const char * const ffado_driver_name = X_("FFADO");
-       const char * const netjack_driver_name = X_("NetJACK");
-       const char * const dummy_driver_name = X_("Dummy");
-}
-
-namespace {
-
-       // The real driver names
-       const char * const portaudio_driver_command_line_name = X_("portaudio");
-       const char * const coreaudio_driver_command_line_name = X_("coreaudio");
-       const char * const alsa_driver_command_line_name = X_("alsa");
-       const char * const oss_driver_command_line_name = X_("oss");
-       const char * const freebob_driver_command_line_name = X_("freebob");
-       const char * const ffado_driver_command_line_name = X_("firewire");
-       const char * const netjack_driver_command_line_name = X_("netjack");
-       const char * const dummy_driver_command_line_name = X_("dummy");
-
-       // should we provide more "pretty" names like above?
-       const char * const alsaseq_midi_driver_name = X_("seq");
-       const char * const alsaraw_midi_driver_name = X_("raw");
-       const char * const winmme_midi_driver_name = X_("winmme");
-       const char * const coremidi_midi_driver_name = X_("coremidi");
-
-       // this should probably be translated
-       const char * const default_device_name = X_("Default");
-}
-
-std::string
-get_none_string ()
-{
-       return _("None");
-}
-
-void
-ARDOUR::get_jack_audio_driver_names (vector<string>& audio_driver_names)
-{
-#ifdef WIN32
-       audio_driver_names.push_back (portaudio_driver_name);
-#elif __APPLE__
-       audio_driver_names.push_back (coreaudio_driver_name);
-#else
-#ifdef HAVE_ALSA
-       audio_driver_names.push_back (alsa_driver_name);
-#endif
-       audio_driver_names.push_back (oss_driver_name);
-       audio_driver_names.push_back (freebob_driver_name);
-       audio_driver_names.push_back (ffado_driver_name);
-#endif
-       audio_driver_names.push_back (netjack_driver_name);
-       audio_driver_names.push_back (dummy_driver_name);
-}
-
-void
-ARDOUR::get_jack_default_audio_driver_name (string& audio_driver_name)
-{
-       vector<string> drivers;
-       get_jack_audio_driver_names (drivers);
-       audio_driver_name = drivers.front ();
-}
-
-void
-ARDOUR::get_jack_sample_rate_strings (vector<string>& samplerates)
-{
-       // do these really need to be translated?
-       samplerates.push_back (_("8000Hz"));
-       samplerates.push_back (_("22050Hz"));
-       samplerates.push_back (_("44100Hz"));
-       samplerates.push_back (_("48000Hz"));
-       samplerates.push_back (_("88200Hz"));
-       samplerates.push_back (_("96000Hz"));
-       samplerates.push_back (_("192000Hz"));
-}
-
-string
-ARDOUR::get_jack_default_sample_rate ()
-{
-       return _("48000Hz");
-}
-
-void
-ARDOUR::get_jack_period_size_strings (std::vector<std::string>& period_sizes)
-{
-       period_sizes.push_back ("32");
-       period_sizes.push_back ("64");
-       period_sizes.push_back ("128");
-       period_sizes.push_back ("256");
-       period_sizes.push_back ("512");
-       period_sizes.push_back ("1024");
-       period_sizes.push_back ("2048");
-       period_sizes.push_back ("4096");
-       period_sizes.push_back ("8192");
-}
-
-string
-ARDOUR::get_jack_default_period_size ()
-{
-       return "1024";
-}
-
-void
-ARDOUR::get_jack_dither_mode_strings (const string& driver, vector<string>& dither_modes)
-{
-       dither_modes.push_back (get_none_string ());
-
-       if (driver == alsa_driver_name ) {
-               dither_modes.push_back (_("Triangular"));
-               dither_modes.push_back (_("Rectangular"));
-               dither_modes.push_back (_("Shaped"));
-       }
-}
-
-string
-ARDOUR::get_jack_default_dither_mode (const string& /*driver*/)
-{
-       return get_none_string ();
-}
-
-string
-ARDOUR::get_jack_latency_string (string samplerate, float periods, string period_size)
-{
-       uint32_t rate = atoi (samplerate);
-       float psize = atof (period_size);
-
-       char buf[32];
-       snprintf (buf, sizeof(buf), "%.1fmsec", (periods * psize) / (rate/1000.0));
-
-       return buf;
-}
-
-bool
-get_jack_command_line_audio_driver_name (const string& driver_name, string& command_line_name)
-{
-       using namespace ARDOUR;
-       if (driver_name == portaudio_driver_name) {
-               command_line_name = portaudio_driver_command_line_name;
-               return true;
-       } else if (driver_name == coreaudio_driver_name) {
-               command_line_name = coreaudio_driver_command_line_name;
-               return true;
-       } else if (driver_name == alsa_driver_name) {
-               command_line_name = alsa_driver_command_line_name;
-               return true;
-       } else if (driver_name == oss_driver_name) {
-               command_line_name = oss_driver_command_line_name;
-               return true;
-       } else if (driver_name == freebob_driver_name) {
-               command_line_name = freebob_driver_command_line_name;
-               return true;
-       } else if (driver_name == ffado_driver_name) {
-               command_line_name = ffado_driver_command_line_name;
-               return true;
-       } else if (driver_name == netjack_driver_name) {
-               command_line_name = netjack_driver_command_line_name;
-               return true;
-       } else if (driver_name == dummy_driver_name) {
-               command_line_name = dummy_driver_command_line_name;
-               return true;
-       }
-       return false;
-}
-
-bool
-get_jack_command_line_audio_device_name (const string& driver_name,
-               const string& device_name, string& command_line_device_name)
-{
-       using namespace ARDOUR;
-       device_map_t devices;
-
-       get_jack_device_names_for_audio_driver (driver_name, devices);
-
-       for (device_map_t::const_iterator i = devices.begin (); i != devices.end(); ++i) {
-               if (i->first == device_name) {
-                       command_line_device_name = i->second;
-                       return true;
-               }
-       }
-       return false;
-}
-
-bool
-get_jack_command_line_dither_mode (const string& dither_mode, string& command_line_dither_mode)
-{
-       using namespace ARDOUR;
-
-       if (dither_mode == _("Triangular")) {
-               command_line_dither_mode = "triangular";
-               return true;
-       } else if (dither_mode == _("Rectangular")) {
-               command_line_dither_mode = "rectangular";
-               return true;
-       } else if (dither_mode == _("Shaped")) {
-               command_line_dither_mode = "shaped";
-               return true;
-       }
-
-       return false;
-}
-
-void
-ARDOUR::get_jack_alsa_device_names (device_map_t& devices)
-{
-#ifdef HAVE_ALSA
-       snd_ctl_t *handle;
-       snd_ctl_card_info_t *info;
-       snd_pcm_info_t *pcminfo;
-       snd_ctl_card_info_alloca(&info);
-       snd_pcm_info_alloca(&pcminfo);
-       string devname;
-       int cardnum = -1;
-       int device = -1;
-
-       while (snd_card_next (&cardnum) >= 0 && cardnum >= 0) {
-
-               devname = "hw:";
-               devname += PBD::to_string (cardnum, std::dec);
-
-               if (snd_ctl_open (&handle, devname.c_str(), 0) >= 0 && snd_ctl_card_info (handle, info) >= 0) {
-
-                       if (snd_ctl_card_info (handle, info) < 0) {
-                               continue;
-                       }
-                       
-                       string card_name = snd_ctl_card_info_get_name (info);
-
-                       /* change devname to use ID, not number */
-
-                       devname = "hw:";
-                       devname += snd_ctl_card_info_get_id (info);
-
-                       while (snd_ctl_pcm_next_device (handle, &device) >= 0 && device >= 0) {
-                               
-                               /* only detect duplex devices here. more
-                                * complex arrangements are beyond our scope
-                                */
-
-                               snd_pcm_info_set_device (pcminfo, device);
-                               snd_pcm_info_set_subdevice (pcminfo, 0);
-                               snd_pcm_info_set_stream (pcminfo, SND_PCM_STREAM_CAPTURE);
-                               
-                               if (snd_ctl_pcm_info (handle, pcminfo) >= 0) {
-
-                                       snd_pcm_info_set_device (pcminfo, device);
-                                       snd_pcm_info_set_subdevice (pcminfo, 0);
-                                       snd_pcm_info_set_stream (pcminfo, SND_PCM_STREAM_PLAYBACK);
-
-                                       if (snd_ctl_pcm_info (handle, pcminfo) >= 0) {
-                                               devname += ',';
-                                               devname += PBD::to_string (device, std::dec);
-                                               devices.insert (std::make_pair (card_name, devname));
-                                       }
-                               }
-                       }
-
-                       snd_ctl_close(handle);
-               }
-       }
-#else
-       /* silence a compiler unused variable warning */
-       (void) devices;
-#endif
-}
-
-#ifdef __APPLE__
-static OSStatus
-getDeviceUIDFromID( AudioDeviceID id, char *name, size_t nsize)
-{
-       UInt32 size = sizeof(CFStringRef);
-       CFStringRef UI;
-       OSStatus res = AudioDeviceGetProperty(id, 0, false,
-               kAudioDevicePropertyDeviceUID, &size, &UI);
-       if (res == noErr)
-               CFStringGetCString(UI,name,nsize,CFStringGetSystemEncoding());
-       CFRelease(UI);
-       return res;
-}
-#endif
-
-void
-ARDOUR::get_jack_coreaudio_device_names (device_map_t& devices)
-{
-#ifdef __APPLE__
-       // Find out how many Core Audio devices are there, if any...
-       // (code snippet gently "borrowed" from St?hane Letz jackdmp;)
-       OSStatus err;
-       Boolean isWritable;
-       UInt32 outSize = sizeof(isWritable);
-
-       err = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices,
-                                          &outSize, &isWritable);
-       if (err == noErr) {
-               // Calculate the number of device available...
-               int numCoreDevices = outSize / sizeof(AudioDeviceID);
-               // Make space for the devices we are about to get...
-               AudioDeviceID *coreDeviceIDs = new AudioDeviceID [numCoreDevices];
-               err = AudioHardwareGetProperty(kAudioHardwarePropertyDevices,
-                                              &outSize, (void *) coreDeviceIDs);
-               if (err == noErr) {
-                       // Look for the CoreAudio device name...
-                       char coreDeviceName[256];
-                       UInt32 nameSize;
-
-                       for (int i = 0; i < numCoreDevices; i++) {
-
-                               nameSize = sizeof (coreDeviceName);
-
-                               /* enforce duplex devices only */
-
-                               err = AudioDeviceGetPropertyInfo(coreDeviceIDs[i],
-                                                                0, true, kAudioDevicePropertyStreams,
-                                                                &outSize, &isWritable);
-
-                               if (err != noErr || outSize == 0) {
-                                       continue;
-                               }
-
-                               err = AudioDeviceGetPropertyInfo(coreDeviceIDs[i],
-                                                                0, false, kAudioDevicePropertyStreams,
-                                                                &outSize, &isWritable);
-
-                               if (err != noErr || outSize == 0) {
-                                       continue;
-                               }
-
-                               err = AudioDeviceGetPropertyInfo(coreDeviceIDs[i],
-                                                                0, true, kAudioDevicePropertyDeviceName,
-                                                                &outSize, &isWritable);
-                               if (err == noErr) {
-                                       err = AudioDeviceGetProperty(coreDeviceIDs[i],
-                                                                    0, true, kAudioDevicePropertyDeviceName,
-                                                                    &nameSize, (void *) coreDeviceName);
-                                       if (err == noErr) {
-                                               char drivername[128];
-
-                                               // this returns the unique id for the device
-                                               // that must be used on the commandline for jack
-
-                                               if (getDeviceUIDFromID(coreDeviceIDs[i], drivername, sizeof (drivername)) == noErr) {
-                                                       devices.insert (make_pair (coreDeviceName, drivername));
-                                               }
-                                       }
-                               }
-                       }
-               }
-               delete [] coreDeviceIDs;
-       }
-#else
-       /* silence a compiler unused variable warning */
-       (void) devices;
-#endif
-}
-
-void
-ARDOUR::get_jack_portaudio_device_names (device_map_t& devices)
-{
-#ifdef HAVE_PORTAUDIO
-       if (Pa_Initialize() != paNoError) {
-               return;
-       }
-
-       for (PaDeviceIndex i = 0; i < Pa_GetDeviceCount (); ++i) {
-               string api_name;
-               string readable_name;
-               string jack_device_name;
-               const PaDeviceInfo* device_info = Pa_GetDeviceInfo(i);
-
-               if (device_info != NULL) { // it should never be ?
-                       api_name = Pa_GetHostApiInfo (device_info->hostApi)->name;
-                       readable_name = api_name + " " + device_info->name;
-                       jack_device_name = api_name + "::" + device_info->name;
-                       devices.insert (make_pair (readable_name, jack_device_name));
-               }
-       }
-       Pa_Terminate();
-#else
-       /* silence a compiler unused variable warning */
-       (void) devices;
-#endif
-}
-
-void
-ARDOUR::get_jack_oss_device_names (device_map_t& devices)
-{
-       devices.insert (make_pair (default_device_name, default_device_name));
-}
-
-void
-ARDOUR::get_jack_freebob_device_names (device_map_t& devices)
-{
-       devices.insert (make_pair (default_device_name, default_device_name));
-}
-
-void
-ARDOUR::get_jack_ffado_device_names (device_map_t& devices)
-{
-       devices.insert (make_pair (default_device_name, default_device_name));
-}
-
-void
-ARDOUR::get_jack_netjack_device_names (device_map_t& devices)
-{
-       devices.insert (make_pair (default_device_name, default_device_name));
-}
-
-void
-ARDOUR::get_jack_dummy_device_names (device_map_t& devices)
-{
-       devices.insert (make_pair (default_device_name, default_device_name));
-}
-
-bool
-ARDOUR::get_jack_device_names_for_audio_driver (const string& driver_name, device_map_t& devices)
-{
-       devices.clear();
-
-       if (driver_name == portaudio_driver_name) {
-               get_jack_portaudio_device_names (devices);
-       } else if (driver_name == coreaudio_driver_name) {
-               get_jack_coreaudio_device_names (devices);
-       } else if (driver_name == alsa_driver_name) {
-               get_jack_alsa_device_names (devices);
-       } else if (driver_name == oss_driver_name) {
-               get_jack_oss_device_names (devices);
-       } else if (driver_name == freebob_driver_name) {
-               get_jack_freebob_device_names (devices);
-       } else if (driver_name == ffado_driver_name) {
-               get_jack_ffado_device_names (devices);
-       } else if (driver_name == netjack_driver_name) {
-               get_jack_netjack_device_names (devices);
-       } else if (driver_name == dummy_driver_name) {
-               get_jack_dummy_device_names (devices);
-       }
-
-       return !devices.empty();
-}
-
-
-std::vector<std::string>
-ARDOUR::get_jack_device_names_for_audio_driver (const string& driver_name)
-{
-       std::vector<std::string> readable_names;
-       device_map_t devices;
-
-       get_jack_device_names_for_audio_driver (driver_name, devices);
-
-       for (device_map_t::const_iterator i = devices.begin (); i != devices.end(); ++i) {
-               readable_names.push_back (i->first);
-       }
-
-       return readable_names;
-}
-
-bool
-ARDOUR::get_jack_audio_driver_supports_two_devices (const string& driver)
-{
-       return (driver == alsa_driver_name || driver == oss_driver_name);
-}
-
-bool
-ARDOUR::get_jack_audio_driver_supports_latency_adjustment (const string& driver)
-{
-       return (driver == alsa_driver_name || driver == coreaudio_driver_name ||
-                       driver == ffado_driver_name || driver == portaudio_driver_name);
-}
-
-bool
-ARDOUR::get_jack_audio_driver_supports_setting_period_count (const string& driver)
-{
-       return !(driver == dummy_driver_name || driver == coreaudio_driver_name ||
-                       driver == portaudio_driver_name);
-}
-
-bool
-ARDOUR::get_jack_server_application_names (std::vector<std::string>& server_names)
-{
-#ifdef WIN32
-       server_names.push_back ("jackd.exe");
-#else
-       server_names.push_back ("jackd");
-       server_names.push_back ("jackdmp");
-#endif
-       return !server_names.empty();
-}
-
-void
-ARDOUR::set_path_env_for_jack_autostart (const vector<std::string>& dirs)
-{
-#ifdef __APPLE__
-       // push it back into the environment so that auto-started JACK can find it.
-       // XXX why can't we just expect OS X users to have PATH set correctly? we can't ...
-       setenv ("PATH", SearchPath(dirs).to_string().c_str(), 1);
-#else
-       /* silence a compiler unused variable warning */
-       (void) dirs;
-#endif
-}
-
-bool
-ARDOUR::get_jack_server_dir_paths (vector<std::string>& server_dir_paths)
-{
-#ifdef __APPLE__
-       /* this magic lets us finds the path to the OSX bundle, and then
-          we infer JACK's location from there
-       */
-
-       char execpath[MAXPATHLEN+1];
-       uint32_t pathsz = sizeof (execpath);
-
-       _NSGetExecutablePath (execpath, &pathsz);
-
-       server_dir_paths.push_back (Glib::path_get_dirname (execpath));
-#endif
-
-       SearchPath sp(string(g_getenv("PATH")));
-
-#ifdef WIN32
-       gchar *install_dir = g_win32_get_package_installation_directory_of_module (NULL);
-       if (install_dir) {
-               sp.push_back (install_dir);
-               g_free (install_dir);
-       }
-       // don't try and use a system wide JACK install yet.
-#else
-       if (sp.empty()) {
-               sp.push_back ("/usr/bin");
-               sp.push_back ("/bin");
-               sp.push_back ("/usr/local/bin");
-               sp.push_back ("/opt/local/bin");
-       }
-#endif
-
-       std::copy (sp.begin(), sp.end(), std::back_inserter(server_dir_paths));
-
-       return !server_dir_paths.empty();
-}
-
-bool
-ARDOUR::get_jack_server_paths (const vector<std::string>& server_dir_paths,
-               const vector<string>& server_names,
-               vector<std::string>& server_paths)
-{
-       for (vector<string>::const_iterator i = server_names.begin(); i != server_names.end(); ++i) {
-                Glib::PatternSpec ps (*i);
-               find_matching_files_in_directories (server_dir_paths, ps, server_paths);
-       }
-       return !server_paths.empty();
-}
-
-bool
-ARDOUR::get_jack_server_paths (vector<std::string>& server_paths)
-{
-       vector<std::string> server_dirs;
-
-       if (!get_jack_server_dir_paths (server_dirs)) {
-               return false;
-       }
-
-       vector<string> server_names;
-
-       if (!get_jack_server_application_names (server_names)) {
-               return false;
-       }
-
-       if (!get_jack_server_paths (server_dirs, server_names, server_paths)) {
-               return false;
-       }
-
-       return !server_paths.empty();
-}
-
-bool
-ARDOUR::get_jack_default_server_path (std::string& server_path)
-{
-       vector<std::string> server_paths;
-
-       if (!get_jack_server_paths (server_paths)) {
-               return false;
-       }
-
-       server_path = server_paths.front ();
-       return true;
-}
-
-string
-quote_string (const string& str)
-{
-       return "\"" + str + "\"";
-}
-
-ARDOUR::JackCommandLineOptions::JackCommandLineOptions ()
-       : server_path ()
-       , timeout(0)
-       , no_mlock(false)
-       , ports_max(128)
-       , realtime(true)
-       , priority(0)
-       , unlock_gui_libs(false)
-       , verbose(false)
-       , temporary(true)
-       , driver()
-       , input_device()
-       , output_device()
-       , num_periods(2)
-       , period_size(1024)
-       , samplerate(48000)
-       , input_latency(0)
-       , output_latency(0)
-       , hardware_metering(false)
-       , hardware_monitoring(false)
-       , dither_mode()
-       , force16_bit(false)
-       , soft_mode(false)
-       , midi_driver()
-{
-
-}
-
-bool
-ARDOUR::get_jack_command_line_string (const JackCommandLineOptions& options, string& command_line)
-{
-       vector<string> args;
-
-       args.push_back (options.server_path);
-
-#ifdef WIN32
-       // must use sync mode on windows
-       args.push_back ("-S");
-
-       // this needs to be added now on windows
-       if (!options.midi_driver.empty () && options.midi_driver != get_none_string ()) {
-               args.push_back ("-X");
-               args.push_back (options.midi_driver);
-       }
-#endif
-
-       if (options.timeout) {
-               args.push_back ("-t");
-               args.push_back (to_string (options.timeout, std::dec));
-       }
-
-       if (options.no_mlock) {
-               args.push_back ("-m");
-       }
-
-       args.push_back ("-p");
-       args.push_back (to_string(options.ports_max, std::dec));
-
-       if (options.realtime) {
-               args.push_back ("-R");
-               if (options.priority != 0) {
-                       args.push_back ("-P");
-                       args.push_back (to_string(options.priority, std::dec));
-               }
-       } else {
-               args.push_back ("-r");
-       }
-
-       if (options.unlock_gui_libs) {
-               args.push_back ("-u");
-       }
-
-       if (options.verbose) {
-               args.push_back ("-v");
-       }
-
-#ifndef WIN32
-       if (options.temporary) {
-               args.push_back ("-T");
-       }
-#endif
-
-       string command_line_driver_name;
-
-       if (!get_jack_command_line_audio_driver_name (options.driver, command_line_driver_name)) {
-               return false;
-       }
-
-       args.push_back ("-d");
-       args.push_back (command_line_driver_name);
-
-       if (options.output_device.empty() && options.input_device.empty()) {
-               return false;
-       }
-
-       string command_line_input_device_name;
-       string command_line_output_device_name;
-
-       if (!get_jack_command_line_audio_device_name (options.driver,
-               options.input_device, command_line_input_device_name)) {
-               return false;
-       }
-
-       if (!get_jack_command_line_audio_device_name (options.driver,
-               options.output_device, command_line_output_device_name)) {
-               return false;
-       }
-
-       if (options.input_device.empty()) {
-               // playback only
-               if (options.output_device.empty()) {
-                       return false;
-               }
-               args.push_back ("-P");
-       } else if (options.output_device.empty()) {
-               // capture only
-               if (options.input_device.empty()) {
-                       return false;
-               }
-               args.push_back ("-C");
-       } else if (options.input_device != options.output_device) {
-               // capture and playback on two devices if supported
-               if (get_jack_audio_driver_supports_two_devices (options.driver)) {
-                       args.push_back ("-C");
-                       args.push_back (command_line_input_device_name);
-                       args.push_back ("-P");
-                       args.push_back (command_line_output_device_name);
-               } else {
-                       return false;
-               }
-       }
-
-       if (options.input_channels) {
-               args.push_back ("-i");
-               args.push_back (to_string (options.input_channels, std::dec));
-       }
-
-       if (options.output_channels) {
-               args.push_back ("-o");
-               args.push_back (to_string (options.output_channels, std::dec));
-       }
-
-       if (get_jack_audio_driver_supports_setting_period_count (options.driver)) {
-               args.push_back ("-n");
-               args.push_back (to_string (options.num_periods, std::dec));
-       }
-
-       args.push_back ("-r");
-       args.push_back (to_string (options.samplerate, std::dec));
-
-       args.push_back ("-p");
-       args.push_back (to_string (options.period_size, std::dec));
-
-       if (get_jack_audio_driver_supports_latency_adjustment (options.driver)) {
-               if (options.input_latency) {
-                       args.push_back ("-I");
-                       args.push_back (to_string (options.input_latency, std::dec));
-               }
-               if (options.output_latency) {
-                       args.push_back ("-O");
-                       args.push_back (to_string (options.output_latency, std::dec));
-               }
-       }
-
-       if (options.input_device == options.output_device && options.input_device != default_device_name) {
-               args.push_back ("-d");
-               args.push_back (command_line_input_device_name);
-       }
-
-       if (options.driver == alsa_driver_name) {
-               if (options.hardware_metering) {
-                       args.push_back ("-M");
-               }
-               if (options.hardware_monitoring) {
-                       args.push_back ("-H");
-               }
-
-               string command_line_dither_mode;
-               if (get_jack_command_line_dither_mode (options.dither_mode, command_line_dither_mode)) {
-                       args.push_back ("-z");
-                       args.push_back (command_line_dither_mode);
-               }
-               if (options.force16_bit) {
-                       args.push_back ("-S");
-               }
-               if (options.soft_mode) {
-                       args.push_back ("-s");
-               }
-
-               if (!options.midi_driver.empty() && options.midi_driver != get_none_string ()) {
-                       args.push_back ("-X");
-                       args.push_back (options.midi_driver);
-               }
-       }
-
-       ostringstream oss;
-
-       for (vector<string>::const_iterator i = args.begin(); i != args.end();) {
-#ifdef WIN32
-               oss << quote_string (*i);
-#else
-               oss << *i;
-#endif
-               if (++i != args.end()) oss << ' ';
-       }
-
-       command_line = oss.str();
-       return true;
-}
-
-string
-ARDOUR::get_jack_server_config_file_name ()
-{
-       return ".jackdrc";
-}
-
-std::string
-ARDOUR::get_jack_server_user_config_dir_path ()
-{
-       return Glib::get_home_dir ();
-}
-
-std::string
-ARDOUR::get_jack_server_user_config_file_path ()
-{
-       return Glib::build_filename (get_jack_server_user_config_dir_path (), get_jack_server_config_file_name ());
-}
-
-bool
-ARDOUR::write_jack_config_file (const std::string& config_file_path, const string& command_line)
-{
-       ofstream jackdrc (config_file_path.c_str());
-
-       if (!jackdrc) {
-               error << string_compose (_("cannot open JACK rc file %1 to store parameters"), config_file_path) << endmsg;
-               return false;
-       }
-
-       jackdrc << command_line << endl;
-       jackdrc.close ();
-       return true;
-}
diff --git a/libs/backends/jack/jack_api.cc b/libs/backends/jack/jack_api.cc
new file mode 100644 (file)
index 0000000..0136161
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+    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 "jack_connection.h"
+#include "jack_audiobackend.h"
+#include "jack_portengine.h"
+
+using namespace ARDOUR;
+
+static boost::shared_ptr<JACKAudioBackend> backend;
+static boost::shared_ptr<JACKPortEngine> port_engine;
+static boost::shared_ptr<JackConnection> jack_connection;
+
+static boost::shared_ptr<AudioBackend>
+backend_factory (AudioEngine& ae)
+{
+       if (!jack_connection) {
+               return boost::shared_ptr<AudioBackend>();
+       }
+
+       if (!backend) {
+               backend.reset (new JACKAudioBackend (ae, jack_connection));
+       }
+
+       return backend;
+}
+
+static boost::shared_ptr<PortEngine>
+portengine_factory (PortManager& pm)
+{
+       if (!jack_connection) {
+               return boost::shared_ptr<PortEngine>();
+       }
+
+       if (!port_engine) {
+               port_engine.reset (new JACKPortEngine (pm, jack_connection));
+       }
+
+       return port_engine;
+}
+
+static int
+instantiate (const std::string& arg1, const std::string& arg2)
+{
+       try {
+               jack_connection.reset (new JackConnection (arg1, arg2));
+       } catch (...) {
+               return -1;
+       }
+
+       return 0;
+}
+
+static int 
+deinstantiate ()
+{
+       port_engine.reset ();
+       backend.reset ();
+       jack_connection.reset ();
+
+       return 0;
+}
+
+static bool
+already_configured ()
+{
+       return JackConnection::server_running ();
+}
+
+extern "C" {
+       
+       
+       /* functions looked up using dlopen-and-cousins, and so naming scope
+        * must be non-mangled.
+        */
+
+       ARDOUR::AudioBackendInfo descriptor = {
+               "JACK",
+               instantiate,
+               deinstantiate,
+               backend_factory,
+               portengine_factory,
+               already_configured,
+       };
+}
+
diff --git a/libs/backends/jack/jack_audiobackend.cc b/libs/backends/jack/jack_audiobackend.cc
new file mode 100644 (file)
index 0000000..22e5a52
--- /dev/null
@@ -0,0 +1,937 @@
+/*
+    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 <math.h>
+
+#include <boost/scoped_ptr.hpp>
+#include <glibmm/timer.h>
+
+#include "pbd/error.h"
+
+#include "jack/jack.h"
+#include "jack/thread.h"
+
+#include "ardour/audioengine.h"
+#include "ardour/session.h"
+#include "ardour/types.h"
+
+#include "jack_audiobackend.h"
+#include "jack_connection.h"
+#include "jack_portengine.h"
+#include "jack_utils.h"
+
+#include "i18n.h"
+
+using namespace ARDOUR;
+using namespace PBD;
+using std::string;
+using std::vector;
+using std::cerr;
+using std::endl;
+
+#define GET_PRIVATE_JACK_POINTER(localvar)  jack_client_t* localvar = _jack_connection->jack(); if (!(localvar)) { return; }
+#define GET_PRIVATE_JACK_POINTER_RET(localvar,r) jack_client_t* localvar = _jack_connection->jack(); if (!(localvar)) { return r; }
+
+JACKAudioBackend::JACKAudioBackend (AudioEngine& e, boost::shared_ptr<JackConnection> jc)
+       : AudioBackend (e)
+       , _jack_connection (jc)
+       , _running (false)
+       , _freewheeling (false)
+       , _target_sample_rate (48000)
+       , _target_buffer_size (1024)
+       , _target_sample_format (FormatFloat)
+       , _target_interleaved (false)
+       , _target_input_channels (-1)
+       , _target_output_channels (-1)
+       , _target_systemic_input_latency (0)
+       , _target_systemic_output_latency (0)
+       , _current_sample_rate (0)
+       , _current_buffer_size (0)
+{
+       _jack_connection->Disconnected.connect_same_thread (disconnect_connection, boost::bind (&JACKAudioBackend::disconnected, this, _1));
+}
+
+JACKAudioBackend::~JACKAudioBackend()
+{
+}
+
+string
+JACKAudioBackend::name() const 
+{
+       return X_("JACK");
+}
+
+void*
+JACKAudioBackend::private_handle() const
+{
+       return _jack_connection->jack();
+}
+
+bool
+JACKAudioBackend::connected() const
+{
+       return (private_handle() != 0);
+}
+
+bool
+JACKAudioBackend::is_realtime () const
+{
+       GET_PRIVATE_JACK_POINTER_RET (_priv_jack,false);
+       return jack_is_realtime (_priv_jack);
+}
+
+bool
+JACKAudioBackend::requires_driver_selection() const
+{
+       return true;
+}
+
+vector<string>
+JACKAudioBackend::enumerate_drivers () const
+{
+       vector<string> currently_available;
+       get_jack_audio_driver_names (currently_available);
+       return currently_available;
+}
+
+int
+JACKAudioBackend::set_driver (const std::string& name)
+{
+       _target_driver = name;
+       return 0;
+}
+
+vector<AudioBackend::DeviceStatus>
+JACKAudioBackend::enumerate_devices () const
+{
+       vector<string> currently_available = get_jack_device_names_for_audio_driver (_target_driver);
+       vector<DeviceStatus> statuses;
+
+       if (all_devices.find (_target_driver) == all_devices.end()) {
+               all_devices.insert (make_pair (_target_driver, std::set<string>()));
+       }
+       
+       /* store every device we've found, by driver name. 
+        *
+        * This is so we do not confuse ALSA, FFADO, netjack etc. devices
+        * with each other.
+        */
+
+       DeviceList& all (all_devices[_target_driver]);
+
+       for (vector<string>::const_iterator d = currently_available.begin(); d != currently_available.end(); ++d) {
+               all.insert (*d);
+       }
+       
+       for (DeviceList::const_iterator d = all.begin(); d != all.end(); ++d) {
+               if (find (currently_available.begin(), currently_available.end(), *d) == currently_available.end()) {
+                       statuses.push_back (DeviceStatus (*d, false));
+               } else {
+                       statuses.push_back (DeviceStatus (*d, false));
+               }
+       }
+       
+       return statuses;
+}
+
+vector<float>
+JACKAudioBackend::available_sample_rates (const string& /*device*/) const
+{
+       vector<float> f;
+       
+       if (connected()) {
+               f.push_back (sample_rate());
+               return f;
+       }
+
+       /* if JACK is not already running, just list a bunch of reasonable 
+          values and let the future sort it all out.
+       */
+
+       f.push_back (8000.0);
+       f.push_back (16000.0);
+       f.push_back (24000.0);
+       f.push_back (32000.0);
+       f.push_back (44100.0);
+       f.push_back (48000.0);
+       f.push_back (88200.0);
+       f.push_back (96000.0);
+       f.push_back (192000.0);
+       f.push_back (384000.0);
+       
+       return f;
+}
+
+vector<uint32_t>
+JACKAudioBackend::available_buffer_sizes (const string& /*device*/) const
+{
+       vector<uint32_t> s;
+       
+       if (connected()) {
+               s.push_back (buffer_size());
+               return s;
+       }
+
+       s.push_back (8);
+       s.push_back (16);
+       s.push_back (32);
+       s.push_back (64);
+       s.push_back (128);
+       s.push_back (256);
+       s.push_back (512);
+       s.push_back (1024);
+       s.push_back (2048);
+       s.push_back (4096);
+       s.push_back (8192);
+
+       return s;
+}
+
+uint32_t
+JACKAudioBackend::available_input_channel_count (const string& /*device*/) const
+{
+       return 128;
+}
+
+uint32_t
+JACKAudioBackend::available_output_channel_count (const string& /*device*/) const
+{
+       return 128;
+}
+
+/* -- parameter setting -- */
+
+int
+JACKAudioBackend::set_device_name (const string& dev)
+{
+       if (connected()) {
+               /* need to stop and restart JACK for this to work, at present */
+               return -1;
+       }
+
+       _target_device = dev;
+       return 0;
+}
+
+int
+JACKAudioBackend::set_sample_rate (float sr)
+{
+       if (!connected()) {
+               _target_sample_rate = sr;
+               return 0;
+       }
+
+       GET_PRIVATE_JACK_POINTER_RET (_priv_jack, -1);
+
+       if (sr == jack_get_sample_rate (_priv_jack)) {
+                return 0;
+       }
+
+       return -1;
+}
+
+int
+JACKAudioBackend::set_buffer_size (uint32_t nframes)
+{
+       if (!connected()) {
+               _target_buffer_size = nframes;
+               return 0;
+       }
+
+       GET_PRIVATE_JACK_POINTER_RET (_priv_jack, -1);
+
+       if (nframes == jack_get_buffer_size (_priv_jack)) {
+                return 0;
+       }
+
+       return jack_set_buffer_size (_priv_jack, nframes);
+}
+
+int
+JACKAudioBackend::set_sample_format (SampleFormat sf)
+{
+       /* as far as JACK clients are concerned, the hardware is always
+        * floating point format.
+        */
+       if (sf == FormatFloat) {
+               return 0;
+       }
+       return -1;
+}
+
+int
+JACKAudioBackend::set_interleaved (bool yn)
+{
+       /* as far as JACK clients are concerned, the hardware is always
+        * non-interleaved
+        */
+       if (!yn) {
+               return 0;
+       }
+       return -1;
+}
+
+int
+JACKAudioBackend::set_input_channels (uint32_t cnt)
+{
+       if (connected()) {
+               return -1;
+       }
+
+       _target_input_channels = cnt;
+       
+       return 0;
+}
+
+int
+JACKAudioBackend::set_output_channels (uint32_t cnt)
+{
+       if (connected()) {
+               return -1;
+       }
+
+       _target_output_channels = cnt;
+
+       return 0;
+}
+
+int
+JACKAudioBackend::set_systemic_input_latency (uint32_t l)
+{
+       if (connected()) {
+               return -1;
+       }
+
+       _target_systemic_input_latency = l;
+
+       return 0;
+}
+
+int
+JACKAudioBackend::set_systemic_output_latency (uint32_t l)
+{
+       if (connected()) {
+               return -1;
+       }
+
+       _target_systemic_output_latency = l;
+
+       return 0;
+}
+
+/* --- Parameter retrieval --- */
+
+std::string
+JACKAudioBackend::device_name () const
+{
+       return string();
+}
+
+float
+JACKAudioBackend::sample_rate () const
+{
+       if (connected()) {
+               return _current_sample_rate;
+       }
+       return _target_sample_rate;
+}
+
+uint32_t
+JACKAudioBackend::buffer_size () const
+{
+       if (connected()) {
+               return _current_buffer_size;
+       }
+       return _target_buffer_size;
+}
+
+SampleFormat
+JACKAudioBackend::sample_format () const
+{
+       return FormatFloat;
+}
+
+bool
+JACKAudioBackend::interleaved () const
+{
+       return false;
+}
+
+uint32_t
+JACKAudioBackend::input_channels () const
+{
+       if (connected()) {
+               return n_physical (JackPortIsInput).n_audio();
+       } 
+       return _target_input_channels;
+}
+
+uint32_t
+JACKAudioBackend::output_channels () const
+{
+       if (connected()) {
+               return n_physical (JackPortIsOutput).n_audio();
+       } 
+       return _target_output_channels;
+}
+
+uint32_t
+JACKAudioBackend::systemic_input_latency () const
+{
+       return _target_systemic_output_latency;
+}
+
+uint32_t
+JACKAudioBackend::systemic_output_latency () const
+{
+       return _target_systemic_output_latency;
+}
+
+size_t 
+JACKAudioBackend::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;
+}
+
+void
+JACKAudioBackend::setup_jack_startup_command ()
+{
+       /* first we map the parameters that have been set onto a
+        * JackCommandLineOptions object.
+        */
+
+       JackCommandLineOptions options;
+
+       get_jack_default_server_path (options.server_path);
+       options.driver = _target_driver;
+       options.samplerate = _target_sample_rate;
+       options.period_size = _target_buffer_size;
+       options.num_periods = 2;
+       options.input_device = _target_device;
+       options.output_device = _target_device;
+       options.input_latency = _target_systemic_input_latency;
+       options.output_latency = _target_systemic_output_latency;
+       options.input_channels = _target_input_channels;
+       options.output_channels = _target_output_channels;
+       if (_target_sample_format == FormatInt16) {
+               options.force16_bit = _target_sample_format;
+       }
+       options.realtime = true;
+       options.ports_max = 2048;
+       
+       /* this must always be true for any server instance we start ourselves
+        */
+
+       options.temporary = true;
+
+       string cmdline;
+
+       if (!get_jack_command_line_string (options, cmdline)) {
+               /* error, somehow */
+               return;
+       }
+
+       std::cerr << "JACK command line will be: " << cmdline << std::endl;
+
+       write_jack_config_file (get_jack_server_user_config_file_path(), cmdline);
+}
+
+/* ---- BASIC STATE CONTROL API: start/stop/pause/freewheel --- */
+
+int
+JACKAudioBackend::start ()
+{
+       if (!connected()) {
+
+               if (!_jack_connection->server_running()) {
+                       setup_jack_startup_command ();
+               }
+
+               if (_jack_connection->open ()) {
+                       return -1;
+               }
+       }
+       
+       GET_PRIVATE_JACK_POINTER_RET (_priv_jack, -1);
+
+       /* get the buffer size and sample rates established */
+
+       jack_sample_rate_callback (jack_get_sample_rate (_priv_jack));
+       jack_bufsize_callback (jack_get_buffer_size (_priv_jack));
+       
+       /* Now that we have buffer size and sample rate established, the engine 
+          can go ahead and do its stuff
+       */
+       
+       engine.reestablish_ports ();
+
+       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;
+       }
+       
+       set_jack_callbacks ();
+       
+       if (jack_activate (_priv_jack) == 0) {
+               _running = true;
+       } else {
+               // error << _("cannot activate JACK client") << endmsg;
+       }
+
+       engine.reconnect_ports ();
+
+       return 0;
+}
+
+int
+JACKAudioBackend::stop ()
+{
+       GET_PRIVATE_JACK_POINTER_RET (_priv_jack, -1);
+       
+       _jack_connection->close ();
+
+       _current_buffer_size = 0;
+       _current_sample_rate = 0;
+
+       _raw_buffer_sizes.clear();
+
+       return 0;
+}
+
+int
+JACKAudioBackend::pause ()
+{
+       GET_PRIVATE_JACK_POINTER_RET (_priv_jack, -1);
+
+       if (_priv_jack) {
+               jack_deactivate (_priv_jack);
+       }
+
+       return 0;
+}
+
+int
+JACKAudioBackend::freewheel (bool onoff)
+{
+       GET_PRIVATE_JACK_POINTER_RET (_priv_jack, -1);
+
+       if (onoff == _freewheeling) {
+               /* already doing what has been asked for */
+               
+               return 0;
+       }
+
+       if (jack_set_freewheel (_priv_jack, onoff) == 0) {
+               _freewheeling = true;
+               return 0;
+       }
+
+       return -1;
+}
+
+/* --- TRANSPORT STATE MANAGEMENT --- */
+
+void
+JACKAudioBackend::transport_stop ()
+{
+       GET_PRIVATE_JACK_POINTER (_priv_jack);
+       jack_transport_stop (_priv_jack);
+}
+
+void
+JACKAudioBackend::transport_start ()
+{
+       GET_PRIVATE_JACK_POINTER (_priv_jack);
+       jack_transport_start (_priv_jack);
+}
+
+void
+JACKAudioBackend::transport_locate (framepos_t where)
+{
+       GET_PRIVATE_JACK_POINTER (_priv_jack);
+       jack_transport_locate (_priv_jack, where);
+}
+
+framepos_t 
+JACKAudioBackend::transport_frame () const 
+{
+       GET_PRIVATE_JACK_POINTER_RET (_priv_jack, 0);
+       return jack_get_current_transport_frame (_priv_jack);
+}
+
+TransportState
+JACKAudioBackend::transport_state () const
+{
+       GET_PRIVATE_JACK_POINTER_RET (_priv_jack, ((TransportState) JackTransportStopped));
+       jack_position_t pos;
+       return (TransportState) jack_transport_query (_priv_jack, &pos);
+}
+
+int
+JACKAudioBackend::set_time_master (bool yn)
+{
+       GET_PRIVATE_JACK_POINTER_RET (_priv_jack, -1);
+       if (yn) {
+               return jack_set_timebase_callback (_priv_jack, 0, _jack_timebase_callback, this);
+       } else {
+               return jack_release_timebase (_priv_jack);
+       }
+}
+
+/* process-time */
+
+bool
+JACKAudioBackend::get_sync_offset (pframes_t& offset) const
+{
+
+#ifdef HAVE_JACK_VIDEO_SUPPORT
+
+       GET_PRIVATE_JACK_POINTER_RET (_priv_jack, false);
+
+       jack_position_t pos;
+
+       if (_priv_jack) {
+               (void) jack_transport_query (_priv_jack, &pos);
+
+               if (pos.valid & JackVideoFrameOffset) {
+                       offset = pos.video_offset;
+                       return true;
+               }
+       }
+#else
+       /* keep gcc happy */
+       offset = 0;
+#endif
+
+       return false;
+}
+
+pframes_t
+JACKAudioBackend::sample_time ()
+{
+       GET_PRIVATE_JACK_POINTER_RET (_priv_jack, 0);
+       return jack_frame_time (_priv_jack);
+}
+
+pframes_t
+JACKAudioBackend::sample_time_at_cycle_start ()
+{
+       GET_PRIVATE_JACK_POINTER_RET (_priv_jack, 0);
+       return jack_last_frame_time (_priv_jack);
+}
+
+pframes_t
+JACKAudioBackend::samples_since_cycle_start ()
+{
+       GET_PRIVATE_JACK_POINTER_RET (_priv_jack, 0);
+       return jack_frames_since_cycle_start (_priv_jack);
+}
+
+/* JACK Callbacks */
+
+static void
+ardour_jack_error (const char* msg)
+{
+       error << "JACK: " << msg << endmsg;
+}
+
+void
+JACKAudioBackend::set_jack_callbacks ()
+{
+       GET_PRIVATE_JACK_POINTER (_priv_jack);
+
+        jack_set_thread_init_callback (_priv_jack, AudioEngine::thread_init_callback, 0);
+
+        jack_set_process_thread (_priv_jack, _process_thread, this);
+        jack_set_sample_rate_callback (_priv_jack, _sample_rate_callback, this);
+        jack_set_buffer_size_callback (_priv_jack, _bufsize_callback, this);
+        jack_set_xrun_callback (_priv_jack, _xrun_callback, this);
+        jack_set_sync_callback (_priv_jack, _jack_sync_callback, this);
+        jack_set_freewheel_callback (_priv_jack, _freewheel_callback, this);
+
+#ifdef HAVE_JACK_SESSION
+        if( jack_set_session_callback)
+                jack_set_session_callback (_priv_jack, _session_callback, this);
+#endif
+
+        if (jack_set_latency_callback) {
+                jack_set_latency_callback (_priv_jack, _latency_callback, this);
+        }
+
+        jack_set_error_function (ardour_jack_error);
+}
+
+void
+JACKAudioBackend::_jack_timebase_callback (jack_transport_state_t state, pframes_t nframes,
+                                     jack_position_t* pos, int new_position, void *arg)
+{
+       static_cast<JACKAudioBackend*> (arg)->jack_timebase_callback (state, nframes, pos, new_position);
+}
+
+void
+JACKAudioBackend::jack_timebase_callback (jack_transport_state_t state, pframes_t nframes,
+                                         jack_position_t* pos, int new_position)
+{
+       ARDOUR::Session* session = engine.session();
+
+       if (session) {
+               session->jack_timebase_callback (state, nframes, pos, new_position);
+       }
+}
+
+int
+JACKAudioBackend::_jack_sync_callback (jack_transport_state_t state, jack_position_t* pos, void* arg)
+{
+       return static_cast<JACKAudioBackend*> (arg)->jack_sync_callback (state, pos);
+}
+
+int
+JACKAudioBackend::jack_sync_callback (jack_transport_state_t state, jack_position_t* pos)
+{
+       TransportState tstate;
+
+       switch (state) {
+       case JackTransportStopped:
+               tstate = TransportStopped;
+               break;
+       case JackTransportRolling:
+               tstate = TransportRolling;
+               break;
+       case JackTransportLooping:
+               tstate = TransportLooping;
+               break;
+       case JackTransportStarting:
+               tstate = TransportStarting;
+               break;
+       }
+
+       return engine.sync_callback (tstate, pos->frame);
+
+       return true;
+}
+
+int
+JACKAudioBackend::_xrun_callback (void *arg)
+{
+       JACKAudioBackend* ae = static_cast<JACKAudioBackend*> (arg);
+       if (ae->connected()) {
+               ae->engine.Xrun (); /* EMIT SIGNAL */
+       }
+       return 0;
+}
+
+#ifdef HAVE_JACK_SESSION
+void
+JACKAudioBackend::_session_callback (jack_session_event_t *event, void *arg)
+{
+       JACKAudioBackend* ae = static_cast<JACKAudioBackend*> (arg);
+       ARDOUR::Session* session = ae->engine.session();
+
+       if (session) {
+               session->jack_session_event (event);
+       }
+}
+#endif
+
+void
+JACKAudioBackend::_freewheel_callback (int onoff, void *arg)
+{
+       static_cast<JACKAudioBackend*>(arg)->freewheel_callback (onoff);
+}
+
+void
+JACKAudioBackend::freewheel_callback (int onoff)
+{
+       _freewheeling = onoff;
+       engine.freewheel_callback (onoff);
+}
+
+void
+JACKAudioBackend::_latency_callback (jack_latency_callback_mode_t mode, void* arg)
+{
+       return static_cast<JACKAudioBackend*> (arg)->jack_latency_callback (mode);
+}
+
+int
+JACKAudioBackend::create_process_thread (boost::function<void()> f, pthread_t* thread, size_t stacksize)
+{
+        GET_PRIVATE_JACK_POINTER_RET (_priv_jack, 0);
+        ThreadData* td = new ThreadData (this, f, stacksize);
+
+        if (jack_client_create_thread (_priv_jack, thread, jack_client_real_time_priority (_priv_jack),
+                                       jack_is_realtime (_priv_jack), _start_process_thread, td)) {
+                return -1;
+        }
+
+        return 0;
+}
+
+void*
+JACKAudioBackend::_start_process_thread (void* arg)
+{
+        ThreadData* td = reinterpret_cast<ThreadData*> (arg);
+        boost::function<void()> f = td->f;
+        delete td;
+
+        f ();
+
+        return 0;
+}
+
+void*
+JACKAudioBackend::_process_thread (void *arg)
+{
+       return static_cast<JACKAudioBackend*> (arg)->process_thread ();
+}
+
+void*
+JACKAudioBackend::process_thread ()
+{
+        /* JACK doesn't do this for us when we use the wait API
+         */
+
+        AudioEngine::thread_init_callback (this);
+
+        while (1) {
+                GET_PRIVATE_JACK_POINTER_RET(_priv_jack,0);
+
+                pframes_t nframes = jack_cycle_wait (_priv_jack);
+               
+                if (engine.process_callback (nframes)) {
+                        return 0;
+                }
+
+               jack_cycle_signal (_priv_jack, 0);
+        }
+
+        return 0;
+}
+
+int
+JACKAudioBackend::_sample_rate_callback (pframes_t nframes, void *arg)
+{
+       return static_cast<JACKAudioBackend*> (arg)->jack_sample_rate_callback (nframes);
+}
+
+int
+JACKAudioBackend::jack_sample_rate_callback (pframes_t nframes)
+{
+       _current_sample_rate = nframes;
+       return engine.sample_rate_change (nframes);
+}
+
+void
+JACKAudioBackend::jack_latency_callback (jack_latency_callback_mode_t mode)
+{
+       engine.latency_callback (mode == JackPlaybackLatency);
+}
+
+int
+JACKAudioBackend::_bufsize_callback (pframes_t nframes, void *arg)
+{
+       return static_cast<JACKAudioBackend*> (arg)->jack_bufsize_callback (nframes);
+}
+
+int
+JACKAudioBackend::jack_bufsize_callback (pframes_t nframes)
+{
+        /* if the size has not changed, this should be a no-op */
+
+        if (nframes == _current_buffer_size) {
+                return 0;
+        }
+
+       GET_PRIVATE_JACK_POINTER_RET (_priv_jack, 1);
+
+       _current_buffer_size = nframes;
+
+        if (jack_port_type_get_buffer_size) {
+                _raw_buffer_sizes[DataType::AUDIO] = jack_port_type_get_buffer_size (_priv_jack, JACK_DEFAULT_AUDIO_TYPE);
+                _raw_buffer_sizes[DataType::MIDI] = jack_port_type_get_buffer_size (_priv_jack, JACK_DEFAULT_MIDI_TYPE);
+        } else {
+
+                /* Old version of JACK.
+
+                   These crude guesses, see below where we try to get the right answers.
+
+                   Note that our guess for MIDI deliberatey tries to overestimate
+                   by a little. It would be nicer if we could get the actual
+                   size from a port, but we have to use this estimate in the
+                   event that there are no MIDI ports currently. If there are
+                   the value will be adjusted below.
+                */
+
+                _raw_buffer_sizes[DataType::AUDIO] = nframes * sizeof (Sample);
+                _raw_buffer_sizes[DataType::MIDI] = nframes * 4 - (nframes/2);
+        }
+
+       engine.buffer_size_change (nframes);
+
+       return 0;
+}
+
+void
+JACKAudioBackend::disconnected (const char* why)
+{
+       bool was_running = _running;
+
+        _running = false;
+        _current_buffer_size = 0;
+        _current_sample_rate = 0;
+
+        if (was_running) {
+               engine.halted_callback (why); /* EMIT SIGNAL */
+        }
+}
+float 
+JACKAudioBackend::cpu_load() const 
+{
+       GET_PRIVATE_JACK_POINTER_RET(_priv_jack,0);
+       return jack_cpu_load (_priv_jack);
+}
+
+void
+JACKAudioBackend::update_latencies ()
+{
+       GET_PRIVATE_JACK_POINTER (_priv_jack);
+       jack_recompute_total_latencies (_priv_jack);
+}
+
+ChanCount
+JACKAudioBackend::n_physical (unsigned long flags) const
+{
+       ChanCount c;
+
+       GET_PRIVATE_JACK_POINTER_RET (_priv_jack, c);
+
+       const char ** ports = jack_get_ports (_priv_jack, NULL, NULL, JackPortIsPhysical | flags);
+
+       if (ports) {
+               for (uint32_t i = 0; ports[i]; ++i) {
+                       if (!strstr (ports[i], "Midi-Through")) {
+                               DataType t (jack_port_type (jack_port_by_name (_priv_jack, ports[i])));
+                               c.set (t, c.get (t) + 1);
+                       }
+               }
+               
+               jack_free (ports);
+       }
+
+       return c;
+}
diff --git a/libs/backends/jack/jack_audiobackend.h b/libs/backends/jack/jack_audiobackend.h
new file mode 100644 (file)
index 0000000..5ba9ee6
--- /dev/null
@@ -0,0 +1,184 @@
+/*
+    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_jack_audiobackend_h__
+#define __libardour_jack_audiobackend_h__
+
+#include <string>
+#include <vector>
+#include <map>
+#include <set>
+
+#include <stdint.h>
+
+#include <boost/shared_ptr.hpp>
+
+#include <jack/jack.h>
+#ifdef HAVE_JACK_SESSION
+#include <jack/session.h>
+#endif
+
+#include "ardour/audio_backend.h"
+
+namespace ARDOUR {
+
+class JackConnection;
+
+class JACKAudioBackend : public AudioBackend {
+  public:
+    JACKAudioBackend (AudioEngine& e, boost::shared_ptr<JackConnection>);
+    ~JACKAudioBackend ();
+
+    std::string name() const;
+    void* private_handle() const;
+    bool connected() const;
+    bool is_realtime () const;
+
+    bool requires_driver_selection() const;
+    std::vector<std::string> enumerate_drivers () const;
+    int set_driver (const std::string&);
+
+    std::vector<DeviceStatus> enumerate_devices () const;
+
+    std::vector<float> available_sample_rates (const std::string& device) const;
+    std::vector<uint32_t> available_buffer_sizes (const std::string& device) const;
+    uint32_t available_input_channel_count (const std::string& device) const;
+    uint32_t available_output_channel_count (const std::string& device) const;
+
+    int set_device_name (const std::string&);
+    int set_sample_rate (float);
+    int set_buffer_size (uint32_t);
+    int set_sample_format (SampleFormat);
+    int set_interleaved (bool yn);
+    int set_input_channels (uint32_t);
+    int set_output_channels (uint32_t);
+    int set_systemic_input_latency (uint32_t);
+    int set_systemic_output_latency (uint32_t);
+
+    std::string  device_name () const;
+    float        sample_rate () const;
+    uint32_t     buffer_size () const;
+    SampleFormat sample_format () const;
+    bool         interleaved () const;
+    uint32_t     input_channels () const;
+    uint32_t     output_channels () const;
+    uint32_t     systemic_input_latency () const;
+    uint32_t     systemic_output_latency () const;
+
+    int start ();
+    int stop ();
+    int pause ();
+    int freewheel (bool);
+
+    float cpu_load() const;
+
+    pframes_t sample_time ();
+    pframes_t sample_time_at_cycle_start ();
+    pframes_t samples_since_cycle_start ();
+
+    size_t raw_buffer_size (DataType t);
+
+    int create_process_thread (boost::function<void()> func, pthread_t*, size_t stacksize);
+
+    void transport_start ();
+    void transport_stop ();
+    void transport_locate (framepos_t /*pos*/);
+    TransportState transport_state () const;
+    framepos_t transport_frame() const;
+
+    int set_time_master (bool /*yn*/);
+    bool get_sync_offset (pframes_t& /*offset*/) const;
+
+    void update_latencies ();
+
+    static bool already_configured();
+
+  private:
+    boost::shared_ptr<JackConnection>  _jack_connection; //< shared with JACKPortEngine
+    bool            _running;
+    bool            _freewheeling;
+    std::map<DataType,size_t> _raw_buffer_sizes;
+
+    static int  _xrun_callback (void *arg);
+    static void* _process_thread (void *arg);
+    static int  _sample_rate_callback (pframes_t nframes, void *arg);
+    static int  _bufsize_callback (pframes_t nframes, void *arg);
+    static void _jack_timebase_callback (jack_transport_state_t, pframes_t, jack_position_t*, int, void*);
+    static int  _jack_sync_callback (jack_transport_state_t, jack_position_t*, void *arg);
+    static void _freewheel_callback (int , void *arg);
+    static void _latency_callback (jack_latency_callback_mode_t, void*);
+#ifdef HAVE_JACK_SESSION
+    static void _session_callback (jack_session_event_t *event, void *arg);
+#endif
+    
+    void jack_timebase_callback (jack_transport_state_t, pframes_t, jack_position_t*, int);
+    int  jack_sync_callback (jack_transport_state_t, jack_position_t*);
+    int  jack_bufsize_callback (pframes_t);
+    int  jack_sample_rate_callback (pframes_t);
+    void freewheel_callback (int);
+    int  process_callback (pframes_t nframes);
+    void jack_latency_callback (jack_latency_callback_mode_t);
+    void disconnected (const char*);
+
+    void set_jack_callbacks ();
+    int reconnect_to_jack ();
+    
+    struct ThreadData {
+       JACKAudioBackend* engine;
+       boost::function<void()> f;
+       size_t stacksize;
+       
+       ThreadData (JACKAudioBackend* e, boost::function<void()> fp, size_t stacksz)
+               : engine (e) , f (fp) , stacksize (stacksz) {}
+    };
+    
+    void*  process_thread ();
+    static void* _start_process_thread (void*);
+
+    ChanCount n_physical (unsigned long) const;
+    
+    void setup_jack_startup_command ();
+
+    /* pffooo */
+
+    std::string  _target_driver;
+    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;
+    uint32_t     _target_systemic_input_latency;
+    uint32_t     _target_systemic_output_latency;
+    uint32_t     _current_sample_rate;
+    uint32_t     _current_buffer_size;
+
+    typedef std::set<std::string> DeviceList;
+    typedef std::map<std::string,DeviceList> DriverDeviceMap;
+    
+    mutable DriverDeviceMap all_devices;
+
+    PBD::ScopedConnection disconnect_connection;
+};
+
+} // namespace
+
+#endif /* __ardour_audiobackend_h__ */
+    
diff --git a/libs/backends/jack/jack_connection.cc b/libs/backends/jack/jack_connection.cc
new file mode 100644 (file)
index 0000000..da0127c
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+    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 <boost/scoped_ptr.hpp>
+#include <jack/session.h>
+
+#include "pbd/epa.h"
+
+#include "jack_connection.h"
+#include "jack_utils.h"
+
+#define GET_PRIVATE_JACK_POINTER(j)  jack_client_t* _priv_jack = (jack_client_t*) (j); if (!_priv_jack) { return; }
+#define GET_PRIVATE_JACK_POINTER_RET(j,r) jack_client_t* _priv_jack = (jack_client_t*) (j); if (!_priv_jack) { return r; }
+
+using namespace ARDOUR;
+using namespace PBD;
+using std::string;
+using std::vector;
+
+static void jack_halted_callback (void* arg)
+{
+       JackConnection* jc = static_cast<JackConnection*> (arg);
+       jc->halted_callback ();
+}
+
+static void jack_halted_info_callback (jack_status_t code, const char* reason, void* arg)
+{
+       JackConnection* jc = static_cast<JackConnection*> (arg);
+       jc->halted_info_callback (code, reason);
+}
+
+
+JackConnection::JackConnection (const std::string& arg1, const std::string& arg2)
+       : _jack (0)
+       , _client_name (arg1)
+       , session_uuid (arg2)
+{
+}
+
+JackConnection::~JackConnection ()
+{
+       close ();
+}
+
+bool
+JackConnection::server_running ()
+{
+        EnvironmentalProtectionAgency* global_epa = EnvironmentalProtectionAgency::get_global_epa ();
+        boost::scoped_ptr<EnvironmentalProtectionAgency> current_epa;
+
+        /* revert all environment settings back to whatever they were when
+        * ardour started, because ardour's startup script may have reset
+        * something in ways that interfere with finding/starting JACK.
+         */
+
+        if (global_epa) {
+                current_epa.reset (new EnvironmentalProtectionAgency(true)); /* will restore settings when we leave scope */
+                global_epa->restore ();
+        }
+
+       jack_status_t status;
+       jack_client_t* c = jack_client_open ("ardourprobe", JackNoStartServer, &status);
+
+       if (status == 0) {
+               jack_client_close (c);
+               return true;
+       }
+
+       return false;
+}
+
+int
+JackConnection::open ()
+{
+        EnvironmentalProtectionAgency* global_epa = EnvironmentalProtectionAgency::get_global_epa ();
+        boost::scoped_ptr<EnvironmentalProtectionAgency> current_epa;
+       jack_status_t status;
+
+       close ();
+
+        /* revert all environment settings back to whatever they were when ardour started
+         */
+
+        if (global_epa) {
+                current_epa.reset (new EnvironmentalProtectionAgency(true)); /* will restore settings when we leave scope */
+                global_epa->restore ();
+        }
+
+       /* ensure that PATH or equivalent includes likely locations of the JACK
+        * server, in case the user's default does not.
+        */
+
+       vector<string> dirs;
+       get_jack_server_dir_paths (dirs);
+       set_path_env_for_jack_autostart (dirs);
+
+       if ((_jack = jack_client_open (_client_name.c_str(), JackSessionID, &status, session_uuid.c_str())) == 0) {
+               return -1;
+       }
+
+       if (status & JackNameNotUnique) {
+               _client_name = jack_get_client_name (_jack);
+       }
+
+       /* attach halted handler */
+
+        if (jack_on_info_shutdown) {
+                jack_on_info_shutdown (_jack, jack_halted_info_callback, this);
+        } else {
+                jack_on_shutdown (_jack, jack_halted_callback, this);
+        }
+
+
+       Connected(); /* EMIT SIGNAL */
+
+       return 0;
+}
+
+int
+JackConnection::close ()
+{
+       GET_PRIVATE_JACK_POINTER_RET (_jack, -1);
+
+       if (_priv_jack) {
+               int ret = jack_client_close (_priv_jack);
+               _jack = 0;
+               Disconnected (""); /* EMIT SIGNAL */
+               return ret;
+       }
+
+       return 0;
+}
+
+void
+JackConnection::halted_callback ()
+{
+       _jack = 0;
+       Disconnected ("");
+}
+
+void
+JackConnection::halted_info_callback (jack_status_t /*status*/, const char* reason)
+{
+       _jack = 0;
+       Disconnected (reason);
+}
+
+
diff --git a/libs/backends/jack/jack_connection.h b/libs/backends/jack/jack_connection.h
new file mode 100644 (file)
index 0000000..cd45f3b
--- /dev/null
@@ -0,0 +1,40 @@
+#ifndef __libardour_jack_connection_h__
+#define __libardour_jack_connection_h__
+
+#include <string>
+#include <jack/jack.h>
+
+#include "pbd/signals.h"
+
+namespace ARDOUR {
+
+class JackConnection {
+  public:
+    JackConnection (const std::string& client_name, const std::string& session_uuid);
+    ~JackConnection ();
+
+    const std::string& client_name() const { return _client_name; }
+
+    int open ();
+    int close ();
+    bool connected () const { return _jack != 0; }
+
+    jack_client_t* jack() const { return _jack; }
+
+    PBD::Signal0<void> Connected;
+    PBD::Signal1<void,const char*> Disconnected;
+
+    void halted_callback ();
+    void halted_info_callback (jack_status_t, const char*);
+
+    static bool server_running();
+
+  private:
+    jack_client_t* volatile _jack;
+    std::string _client_name;
+    std::string session_uuid;
+};
+
+} // namespace 
+
+#endif /* __libardour_jack_connection_h__ */
diff --git a/libs/backends/jack/jack_portengine.cc b/libs/backends/jack/jack_portengine.cc
new file mode 100644 (file)
index 0000000..bd352a2
--- /dev/null
@@ -0,0 +1,569 @@
+/*
+    Copyright (C) 2013 Paul Davis
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include <string.h>
+#include <stdint.h>
+
+#include "pbd/error.h"
+
+#include "jack_portengine.h"
+#include "jack_connection.h"
+
+#include "ardour/port_manager.h"
+
+#include "i18n.h"
+
+using namespace ARDOUR;
+using namespace PBD;
+using std::string;
+using std::vector;
+
+#define GET_PRIVATE_JACK_POINTER(localvar)  jack_client_t* localvar = _jack_connection->jack(); if (!(localvar)) { return; }
+#define GET_PRIVATE_JACK_POINTER_RET(localvar,r) jack_client_t* localvar = _jack_connection->jack(); if (!(localvar)) { return r; }
+
+static uint32_t
+ardour_port_flags_to_jack_flags (PortFlags flags)
+{
+       uint32_t jack_flags = 0;
+       
+       if (flags & IsInput) {
+               jack_flags |= JackPortIsInput;
+       }
+       if (flags & IsOutput) {
+               jack_flags |= JackPortIsOutput;
+       }
+       if (flags & IsTerminal) {
+               jack_flags |= JackPortIsTerminal;
+       }
+       if (flags & IsPhysical) {
+               jack_flags |= JackPortIsPhysical;
+       }
+       if (flags & CanMonitor) {
+               jack_flags |= JackPortCanMonitor;
+       }
+
+       return jack_flags;
+}
+
+static DataType
+jack_port_type_to_ardour_data_type (const char* jack_type)
+{
+       if (strcmp (jack_type, JACK_DEFAULT_AUDIO_TYPE) == 0) {
+               return DataType::AUDIO;
+       } else if (strcmp (jack_type, JACK_DEFAULT_MIDI_TYPE) == 0) {
+               return DataType::MIDI;
+       }
+       return DataType::NIL;
+}
+
+static const char*
+ardour_data_type_to_jack_port_type (DataType d)
+{
+       switch (d) {
+       case DataType::AUDIO:
+               return JACK_DEFAULT_AUDIO_TYPE;
+       case DataType::MIDI:
+               return JACK_DEFAULT_MIDI_TYPE;
+       }
+
+       return "";
+}
+
+JACKPortEngine::JACKPortEngine (PortManager& pm, boost::shared_ptr<JackConnection> jc)
+       : PortEngine (pm)
+       , _jack_connection (jc)
+{
+       _jack_connection->Connected.connect_same_thread (jack_connection_connection, boost::bind (&JACKPortEngine::connected_to_jack, this));
+}
+
+JACKPortEngine::~JACKPortEngine ()
+{
+       /* a default destructor would do this, and so would this one,
+          but we'll make it explicit in case we ever need to debug
+          the lifetime of the JACKConnection
+       */
+       _jack_connection.reset ();
+}
+
+void
+JACKPortEngine::connected_to_jack ()
+{
+       /* register callbacks for stuff that is our responsibility */
+
+       jack_client_t* client = _jack_connection->jack();
+
+       if (!client) {
+               /* how could this happen? it could ... */
+               error << _("Already disconnected from JACK before PortEngine could register callbacks") << endmsg;
+               return;
+       }
+
+        jack_set_port_registration_callback (client, _registration_callback, this);
+        jack_set_port_connect_callback (client, _connect_callback, this);
+        jack_set_graph_order_callback (client, _graph_order_callback, this);
+}
+
+void*
+JACKPortEngine::private_handle() const
+{
+       return _jack_connection->jack();
+}
+
+bool
+JACKPortEngine::connected() const
+{
+       return _jack_connection->connected();
+}
+
+int
+JACKPortEngine::set_port_name (PortHandle port, const std::string& name)
+{
+       return jack_port_set_name ((jack_port_t*) port, name.c_str());
+}
+
+string
+JACKPortEngine::get_port_name (PortHandle port) const
+{
+       return jack_port_name ((jack_port_t*) port);
+}
+
+PortEngine::PortHandle*
+JACKPortEngine:: get_port_by_name (const std::string& name) const
+{
+       GET_PRIVATE_JACK_POINTER_RET (_priv_jack, 0);
+       return (PortHandle*) jack_port_by_name (_priv_jack, name.c_str());
+}
+
+void
+JACKPortEngine::_registration_callback (jack_port_id_t /*id*/, int /*reg*/, void* arg)
+{
+       static_cast<JACKPortEngine*> (arg)->manager.registration_callback ();
+}
+
+int
+JACKPortEngine::_graph_order_callback (void *arg)
+{
+       return static_cast<JACKPortEngine*> (arg)->manager.graph_order_callback ();
+}
+
+void
+JACKPortEngine::_connect_callback (jack_port_id_t id_a, jack_port_id_t id_b, int conn, void* arg)
+{
+       static_cast<JACKPortEngine*> (arg)->connect_callback (id_a, id_b, conn);
+}
+
+void
+JACKPortEngine::connect_callback (jack_port_id_t id_a, jack_port_id_t id_b, int conn)
+{
+       if (manager.port_remove_in_progress()) {
+               return;
+       }
+
+       GET_PRIVATE_JACK_POINTER (_priv_jack);
+
+       jack_port_t* a = jack_port_by_id (_priv_jack, id_a);
+       jack_port_t* b = jack_port_by_id (_priv_jack, id_b);
+
+       manager.connect_callback (jack_port_name (a), jack_port_name (b), conn == 0 ? false : true);
+}
+
+bool
+JACKPortEngine::connected (PortHandle port, bool process_callback_safe)
+{
+       bool ret = false;
+
+       const char** ports;
+
+       if (process_callback_safe) {
+               ports = jack_port_get_connections ((jack_port_t*)port);
+       } else {
+               GET_PRIVATE_JACK_POINTER_RET (_priv_jack, false);
+               ports = jack_port_get_all_connections (_priv_jack, (jack_port_t*)port);
+       }
+
+       if (ports) {
+               ret = true;
+       }
+
+       jack_free (ports);
+
+       return ret;
+}
+
+bool
+JACKPortEngine::connected_to (PortHandle port, const std::string& other, bool process_callback_safe)
+{
+       bool ret = false;
+       const char** ports;
+
+       if (process_callback_safe) {
+               ports = jack_port_get_connections ((jack_port_t*)port);
+       } else {
+               GET_PRIVATE_JACK_POINTER_RET (_priv_jack, false);
+               ports = jack_port_get_all_connections (_priv_jack, (jack_port_t*)port);
+       }
+
+       if (ports) {
+               for (int i = 0; ports[i]; ++i) {
+                       if (other == ports[i]) {
+                               ret = true;
+                       }
+               }
+               jack_free (ports);
+       }
+
+       return ret;
+}
+
+bool
+JACKPortEngine::physically_connected (PortHandle p, bool process_callback_safe)
+{
+       GET_PRIVATE_JACK_POINTER_RET (_priv_jack, false);
+       jack_port_t* port = (jack_port_t*) p;
+
+       const char** ports;
+       
+       if (process_callback_safe) {
+               ports = jack_port_get_connections ((jack_port_t*)port);
+       } else {
+               GET_PRIVATE_JACK_POINTER_RET (_priv_jack, false);
+               ports = jack_port_get_all_connections (_priv_jack, (jack_port_t*)port);
+       }
+
+       if (ports) {
+               for (int i = 0; ports[i]; ++i) {
+
+                       jack_port_t* other = jack_port_by_name (_priv_jack, ports[i]);
+
+                       if (other && (jack_port_flags (other) & JackPortIsPhysical)) {
+                               return true;
+                       }
+               }
+               jack_free (ports);
+       }
+
+       return false;
+}
+
+int
+JACKPortEngine::get_connections (PortHandle port, vector<string>& s, bool process_callback_safe)
+{
+       const char** ports;
+
+       if (process_callback_safe) {
+               ports = jack_port_get_connections ((jack_port_t*)port);
+       } else {
+               GET_PRIVATE_JACK_POINTER_RET (_priv_jack, 0);
+               ports = jack_port_get_all_connections (_priv_jack, (jack_port_t*)port);
+       }
+
+       if (ports) {
+               for (int i = 0; ports[i]; ++i) {
+                       s.push_back (ports[i]);
+               }
+               jack_free (ports);
+       }
+
+       return s.size();
+}
+
+DataType
+JACKPortEngine::port_data_type (PortHandle p) const
+{
+       return jack_port_type_to_ardour_data_type (jack_port_type ((jack_port_t*) p));
+}
+
+const string&
+JACKPortEngine::my_name() const
+{
+       return _jack_connection->client_name();
+}
+
+bool
+JACKPortEngine::port_is_physical (PortHandle ph) const
+{
+       if (!ph) {
+                return false;
+        }
+
+        return jack_port_flags ((jack_port_t*) ph) & JackPortIsPhysical;
+}
+
+int
+JACKPortEngine::get_ports (const string& port_name_pattern, DataType type, PortFlags flags, vector<string>& s) const
+{
+
+       GET_PRIVATE_JACK_POINTER_RET (_priv_jack,0);
+
+       const char** ports =  jack_get_ports (_priv_jack, port_name_pattern.c_str(), 
+                                             ardour_data_type_to_jack_port_type (type), 
+                                             ardour_port_flags_to_jack_flags (flags));
+
+       if (ports == 0) {
+               return 0;
+       }
+
+       for (uint32_t i = 0; ports[i]; ++i) {
+               s.push_back (ports[i]);
+       }
+
+       jack_free (ports);
+       
+       return s.size();
+}
+
+ChanCount
+JACKPortEngine::n_physical (unsigned long flags) const
+{
+       ChanCount c;
+
+       GET_PRIVATE_JACK_POINTER_RET (_priv_jack, c);
+
+       const char ** ports = jack_get_ports (_priv_jack, NULL, NULL, JackPortIsPhysical | flags);
+
+       if (ports) {
+               for (uint32_t i = 0; ports[i]; ++i) {
+                       if (!strstr (ports[i], "Midi-Through")) {
+                               DataType t = port_data_type (jack_port_by_name (_priv_jack, ports[i]));
+                               if (t != DataType::NIL) {
+                                       c.set (t, c.get (t) + 1);
+                               }
+                       }
+               }
+               
+               jack_free (ports);
+       }
+
+       return c;
+}
+
+ChanCount
+JACKPortEngine::n_physical_inputs () const
+{
+       return n_physical (JackPortIsInput);
+}
+
+ChanCount
+JACKPortEngine::n_physical_outputs () const
+{
+       return n_physical (JackPortIsOutput);
+}
+
+void
+JACKPortEngine::get_physical (DataType type, unsigned long flags, vector<string>& phy) const
+{
+       GET_PRIVATE_JACK_POINTER (_priv_jack);
+       const char ** ports;
+
+       if ((ports = jack_get_ports (_priv_jack, NULL, ardour_data_type_to_jack_port_type (type), JackPortIsPhysical | flags)) == 0) {
+               return;
+       }
+
+       if (ports) {
+               for (uint32_t i = 0; ports[i]; ++i) {
+                        if (strstr (ports[i], "Midi-Through")) {
+                                continue;
+                        }
+                       phy.push_back (ports[i]);
+               }
+               jack_free (ports);
+       }
+}
+
+/** Get physical ports for which JackPortIsOutput is set; ie those that correspond to
+ *  a physical input connector.
+ */
+void
+JACKPortEngine::get_physical_inputs (DataType type, vector<string>& ins)
+{
+       get_physical (type, JackPortIsOutput, ins);
+}
+
+/** Get physical ports for which JackPortIsInput is set; ie those that correspond to
+ *  a physical output connector.
+ */
+void
+JACKPortEngine::get_physical_outputs (DataType type, vector<string>& outs)
+{
+       get_physical (type, JackPortIsInput, outs);
+}
+
+
+bool
+JACKPortEngine::can_monitor_input () const
+{
+       GET_PRIVATE_JACK_POINTER_RET (_priv_jack,false);
+       const char ** ports;
+
+       if ((ports = jack_get_ports (_priv_jack, NULL, JACK_DEFAULT_AUDIO_TYPE, JackPortCanMonitor)) == 0) {
+               return false;
+       }
+
+       jack_free (ports);
+
+       return true;
+}
+
+int
+JACKPortEngine::request_input_monitoring (PortHandle port, bool yn)
+{
+       return jack_port_request_monitor ((jack_port_t*) port, yn);
+}
+int
+JACKPortEngine::ensure_input_monitoring (PortHandle port, bool yn)
+{
+       return jack_port_ensure_monitor ((jack_port_t*) port, yn);
+}
+bool
+JACKPortEngine::monitoring_input (PortHandle port)
+{
+       return jack_port_monitoring_input ((jack_port_t*) port);
+}
+
+
+pframes_t
+JACKPortEngine::sample_time_at_cycle_start ()
+{
+       GET_PRIVATE_JACK_POINTER_RET (_priv_jack, 0);
+       return jack_last_frame_time (_priv_jack);
+}
+
+
+PortEngine::PortHandle
+JACKPortEngine::register_port (const std::string& shortname, ARDOUR::DataType type, ARDOUR::PortFlags flags)
+{
+       GET_PRIVATE_JACK_POINTER_RET (_priv_jack, 0);
+       return jack_port_register (_priv_jack, shortname.c_str(), 
+                                  ardour_data_type_to_jack_port_type (type),
+                                  ardour_port_flags_to_jack_flags (flags),
+                                  0);
+}
+
+void
+JACKPortEngine::unregister_port (PortHandle port)
+{
+       GET_PRIVATE_JACK_POINTER (_priv_jack);
+       (void) jack_port_unregister (_priv_jack, (jack_port_t*) port);
+}
+
+int
+JACKPortEngine::connect (PortHandle port, const std::string& other)
+{
+       GET_PRIVATE_JACK_POINTER_RET (_priv_jack, -1);
+       return jack_connect (_priv_jack, jack_port_name ((jack_port_t*) port), other.c_str());
+}
+int
+JACKPortEngine::connect (const std::string& src, const std::string& dst)
+{
+       GET_PRIVATE_JACK_POINTER_RET (_priv_jack, -1);
+       
+       int r = jack_connect (_priv_jack, src.c_str(), dst.c_str());
+       return r;
+}
+
+int
+JACKPortEngine::disconnect (PortHandle port, const std::string& other)
+{
+       GET_PRIVATE_JACK_POINTER_RET (_priv_jack, -1);
+       return jack_disconnect (_priv_jack, jack_port_name ((jack_port_t*) port), other.c_str());
+}
+
+int
+JACKPortEngine::disconnect (const std::string& src, const std::string& dst)
+{
+       GET_PRIVATE_JACK_POINTER_RET (_priv_jack, -1);
+       return jack_disconnect (_priv_jack, src.c_str(), dst.c_str());
+}
+
+int
+JACKPortEngine::disconnect_all (PortHandle port)
+{
+       GET_PRIVATE_JACK_POINTER_RET (_priv_jack, -1);
+       return jack_port_disconnect (_priv_jack, (jack_port_t*) port);
+}
+
+int
+JACKPortEngine::midi_event_get (pframes_t& timestamp, size_t& size, uint8_t** buf, void* port_buffer, uint32_t event_index)
+{
+       jack_midi_event_t ev;
+       int ret;
+
+       if ((ret = jack_midi_event_get (&ev, port_buffer, event_index)) == 0) {
+               timestamp = ev.time;
+               size = ev.size;
+               *buf = ev.buffer;
+       }
+
+       return ret;
+}
+
+int
+JACKPortEngine::midi_event_put (void* port_buffer, pframes_t timestamp, const uint8_t* buffer, size_t size)
+{
+       return jack_midi_event_write (port_buffer, timestamp, buffer, size);
+}
+
+uint32_t
+JACKPortEngine::get_midi_event_count (void* port_buffer)
+{
+       return jack_midi_get_event_count (port_buffer);
+}
+
+void
+JACKPortEngine::midi_clear (void* port_buffer)
+{
+       jack_midi_clear_buffer (port_buffer);
+}
+
+void
+JACKPortEngine::set_latency_range (PortHandle port, bool for_playback, LatencyRange r)
+{
+       jack_latency_range_t range;
+       
+       range.min = r.min;
+       range.max = r.max;
+
+       jack_port_set_latency_range ((jack_port_t*) port, for_playback ? JackPlaybackLatency : JackCaptureLatency, &range);
+}
+
+LatencyRange
+JACKPortEngine::get_latency_range (PortHandle port, bool for_playback)
+{
+       jack_latency_range_t range;
+       LatencyRange ret;
+       
+       jack_port_get_latency_range ((jack_port_t*) port, for_playback ? JackPlaybackLatency : JackCaptureLatency, &range);
+
+       ret.min = range.min;
+       ret.max = range.max;
+
+       return ret;
+}
+
+void*
+JACKPortEngine::get_buffer (PortHandle port, pframes_t nframes)
+{
+       return jack_port_get_buffer ((jack_port_t*) port, nframes);
+}
+
+uint32_t
+JACKPortEngine::port_name_size() const
+{
+       return jack_port_name_size ();
+}
diff --git a/libs/backends/jack/jack_portengine.h b/libs/backends/jack/jack_portengine.h
new file mode 100644 (file)
index 0000000..0e1eb48
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+    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_jack_portengine_h__
+#define __libardour_jack_portengine_h__
+
+#include <string>
+#include <vector>
+
+#include <stdint.h>
+
+#include <jack/types.h>
+#include <jack/midiport.h>
+
+#include <boost/shared_ptr.hpp>
+
+#include "pbd/signals.h"
+
+#include "ardour/port_engine.h"
+#include "ardour/types.h"
+
+namespace ARDOUR {
+
+class JackConnection;
+
+class JACKPortEngine : public PortEngine 
+{
+  public:
+    JACKPortEngine (PortManager&, boost::shared_ptr<JackConnection>);
+    ~JACKPortEngine();
+
+    void* private_handle() const;
+    bool connected() const;
+
+    const std::string& my_name() const;
+
+    uint32_t port_name_size() const;
+
+    int         set_port_name (PortHandle, const std::string&);
+    std::string get_port_name (PortHandle) const;
+    PortHandle* get_port_by_name (const std::string&) const;
+
+    int get_ports (const std::string& port_name_pattern, DataType type, PortFlags flags, std::vector<std::string>&) const;
+
+    DataType port_data_type (PortHandle) const;
+
+    PortHandle register_port (const std::string& shortname, ARDOUR::DataType, ARDOUR::PortFlags);
+    void  unregister_port (PortHandle);
+
+    bool  connected (PortHandle, bool process_callback_safe);
+    bool  connected_to (PortHandle, const std::string&, bool process_callback_safe);
+    bool  physically_connected (PortHandle, bool process_callback_safe);
+    int   get_connections (PortHandle, std::vector<std::string>&, bool process_callback_safe);
+    int   connect (PortHandle, const std::string&);
+
+    int   disconnect (PortHandle, const std::string&);
+    int   disconnect_all (PortHandle);
+    int   connect (const std::string& src, const std::string& dst);
+    int   disconnect (const std::string& src, const std::string& dst);
+    
+    /* MIDI */
+
+    int      midi_event_get (pframes_t& timestamp, size_t& size, uint8_t** buf, void* port_buffer, uint32_t event_index);
+    int      midi_event_put (void* port_buffer, pframes_t timestamp, const uint8_t* buffer, size_t size);
+    uint32_t get_midi_event_count (void* port_buffer);
+    void     midi_clear (void* port_buffer);
+
+    /* Monitoring */
+
+    bool  can_monitor_input() const;
+    int   request_input_monitoring (PortHandle, bool);
+    int   ensure_input_monitoring (PortHandle, bool);
+    bool  monitoring_input (PortHandle);
+
+    /* Latency management
+     */
+    
+    void          set_latency_range (PortHandle, bool for_playback, LatencyRange);
+    LatencyRange  get_latency_range (PortHandle, bool for_playback);
+
+    /* Physical ports */
+
+    bool      port_is_physical (PortHandle) const;
+    void      get_physical_outputs (DataType type, std::vector<std::string>&);
+    void      get_physical_inputs (DataType type, std::vector<std::string>&);
+    ChanCount n_physical_outputs () const;
+    ChanCount n_physical_inputs () const;
+
+    /* Getting access to the data buffer for a port */
+
+    void* get_buffer (PortHandle, pframes_t);
+
+    /* Miscellany */
+
+    pframes_t sample_time_at_cycle_start ();
+    
+  private:
+    boost::shared_ptr<JackConnection> _jack_connection;
+
+    static int  _graph_order_callback (void *arg);
+    static void _registration_callback (jack_port_id_t, int, void *);
+    static void _connect_callback (jack_port_id_t, jack_port_id_t, int, void *);
+
+    void connect_callback (jack_port_id_t, jack_port_id_t, int);
+
+    ChanCount n_physical (unsigned long flags) const;
+    void get_physical (DataType type, unsigned long flags, std::vector<std::string>& phy) const;
+
+    PBD::ScopedConnection jack_connection_connection;
+    void connected_to_jack ();
+
+};
+
+} // namespace 
+
+#endif /* __libardour_jack_portengine_h__ */
diff --git a/libs/backends/jack/jack_slave.cc b/libs/backends/jack/jack_slave.cc
new file mode 100644 (file)
index 0000000..4b2f3b1
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+    Copyright (C) 2004 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 <iostream>
+#include <cerrno>
+
+#include "ardour/audioengine.h"
+#include "ardour/slave.h"
+
+using namespace std;
+using namespace ARDOUR;
+
+JACK_Slave::JACK_Slave (AudioEngine& e)
+       : engine (e)
+{
+       double x;
+       framepos_t p;
+       /* call this to initialize things */
+       speed_and_position (x, p);
+}
+
+JACK_Slave::~JACK_Slave ()
+{
+}
+
+bool
+JACK_Slave::locked() const
+{
+       return true;
+}
+
+bool
+JACK_Slave::ok() const
+{
+       return true;
+}
+
+bool
+JACK_Slave::speed_and_position (double& sp, framepos_t& position)
+{
+       switch (engine.transport_state()) {
+       case TransportStopped:
+               speed = 0;
+               _starting = false;
+               break;
+       case TransportRolling:
+               speed = 1.0;
+               _starting = false;
+               break;
+       case TransportLooping:
+               speed = 1.0;
+               _starting = false;
+               break;
+       case TransportStarting:
+               _starting = true;
+               // don't adjust speed here, just leave it as it was
+               break;
+       }
+
+       sp = speed;
+       position = engine.transport_frame();
+       return true;
+}
diff --git a/libs/backends/jack/jack_utils.cc b/libs/backends/jack/jack_utils.cc
new file mode 100644 (file)
index 0000000..77f3d95
--- /dev/null
@@ -0,0 +1,897 @@
+/*
+    Copyright (C) 2010 Paul Davis
+    Copyright (C) 2011 Tim Mayberry
+
+    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.
+
+*/
+
+#ifdef HAVE_ALSA
+#include <alsa/asoundlib.h>
+#endif
+
+#ifdef __APPLE__
+#include <CoreAudio/CoreAudio.h>
+#include <CoreFoundation/CFString.h>
+#include <sys/param.h>
+#include <mach-o/dyld.h>
+#endif
+
+#ifdef HAVE_PORTAUDIO
+#include <portaudio.h>
+#endif
+
+#include <jack/jack.h>
+
+#include <fstream>
+
+#include <boost/scoped_ptr.hpp>
+
+#include <glibmm/miscutils.h>
+
+#include "pbd/epa.h"
+#include "pbd/error.h"
+#include "pbd/convert.h"
+#include "pbd/file_utils.h"
+#include "pbd/search_path.h"
+
+#include "jack_utils.h"
+
+#ifdef __APPLE
+#include <CFBundle.h>
+#endif
+
+#include "i18n.h"
+
+using namespace std;
+using namespace PBD;
+
+namespace ARDOUR {
+       // The pretty driver names
+       const char * const portaudio_driver_name = X_("Portaudio");
+       const char * const coreaudio_driver_name = X_("CoreAudio");
+       const char * const alsa_driver_name = X_("ALSA");
+       const char * const oss_driver_name = X_("OSS");
+       const char * const freebob_driver_name = X_("FreeBoB");
+       const char * const ffado_driver_name = X_("FFADO");
+       const char * const netjack_driver_name = X_("NetJACK");
+       const char * const dummy_driver_name = X_("Dummy");
+}
+
+namespace {
+
+       // The real driver names
+       const char * const portaudio_driver_command_line_name = X_("portaudio");
+       const char * const coreaudio_driver_command_line_name = X_("coreaudio");
+       const char * const alsa_driver_command_line_name = X_("alsa");
+       const char * const oss_driver_command_line_name = X_("oss");
+       const char * const freebob_driver_command_line_name = X_("freebob");
+       const char * const ffado_driver_command_line_name = X_("firewire");
+       const char * const netjack_driver_command_line_name = X_("netjack");
+       const char * const dummy_driver_command_line_name = X_("dummy");
+
+       // should we provide more "pretty" names like above?
+       const char * const alsaseq_midi_driver_name = X_("seq");
+       const char * const alsaraw_midi_driver_name = X_("raw");
+       const char * const winmme_midi_driver_name = X_("winmme");
+       const char * const coremidi_midi_driver_name = X_("coremidi");
+
+       // this should probably be translated
+       const char * const default_device_name = X_("Default");
+}
+
+std::string
+get_none_string ()
+{
+       return _("None");
+}
+
+void
+ARDOUR::get_jack_audio_driver_names (vector<string>& audio_driver_names)
+{
+#ifdef WIN32
+       audio_driver_names.push_back (portaudio_driver_name);
+#elif __APPLE__
+       audio_driver_names.push_back (coreaudio_driver_name);
+#else
+#ifdef HAVE_ALSA
+       audio_driver_names.push_back (alsa_driver_name);
+#endif
+       audio_driver_names.push_back (oss_driver_name);
+       audio_driver_names.push_back (freebob_driver_name);
+       audio_driver_names.push_back (ffado_driver_name);
+#endif
+       audio_driver_names.push_back (netjack_driver_name);
+       audio_driver_names.push_back (dummy_driver_name);
+}
+
+void
+ARDOUR::get_jack_default_audio_driver_name (string& audio_driver_name)
+{
+       vector<string> drivers;
+       get_jack_audio_driver_names (drivers);
+       audio_driver_name = drivers.front ();
+}
+
+void
+ARDOUR::get_jack_sample_rate_strings (vector<string>& samplerates)
+{
+       // do these really need to be translated?
+       samplerates.push_back (_("8000Hz"));
+       samplerates.push_back (_("22050Hz"));
+       samplerates.push_back (_("44100Hz"));
+       samplerates.push_back (_("48000Hz"));
+       samplerates.push_back (_("88200Hz"));
+       samplerates.push_back (_("96000Hz"));
+       samplerates.push_back (_("192000Hz"));
+}
+
+string
+ARDOUR::get_jack_default_sample_rate ()
+{
+       return _("48000Hz");
+}
+
+void
+ARDOUR::get_jack_period_size_strings (std::vector<std::string>& period_sizes)
+{
+       period_sizes.push_back ("32");
+       period_sizes.push_back ("64");
+       period_sizes.push_back ("128");
+       period_sizes.push_back ("256");
+       period_sizes.push_back ("512");
+       period_sizes.push_back ("1024");
+       period_sizes.push_back ("2048");
+       period_sizes.push_back ("4096");
+       period_sizes.push_back ("8192");
+}
+
+string
+ARDOUR::get_jack_default_period_size ()
+{
+       return "1024";
+}
+
+void
+ARDOUR::get_jack_dither_mode_strings (const string& driver, vector<string>& dither_modes)
+{
+       dither_modes.push_back (get_none_string ());
+
+       if (driver == alsa_driver_name ) {
+               dither_modes.push_back (_("Triangular"));
+               dither_modes.push_back (_("Rectangular"));
+               dither_modes.push_back (_("Shaped"));
+       }
+}
+
+string
+ARDOUR::get_jack_default_dither_mode (const string& /*driver*/)
+{
+       return get_none_string ();
+}
+
+string
+ARDOUR::get_jack_latency_string (string samplerate, float periods, string period_size)
+{
+       uint32_t rate = atoi (samplerate);
+       float psize = atof (period_size);
+
+       char buf[32];
+       snprintf (buf, sizeof(buf), "%.1fmsec", (periods * psize) / (rate/1000.0));
+
+       return buf;
+}
+
+bool
+get_jack_command_line_audio_driver_name (const string& driver_name, string& command_line_name)
+{
+       using namespace ARDOUR;
+       if (driver_name == portaudio_driver_name) {
+               command_line_name = portaudio_driver_command_line_name;
+               return true;
+       } else if (driver_name == coreaudio_driver_name) {
+               command_line_name = coreaudio_driver_command_line_name;
+               return true;
+       } else if (driver_name == alsa_driver_name) {
+               command_line_name = alsa_driver_command_line_name;
+               return true;
+       } else if (driver_name == oss_driver_name) {
+               command_line_name = oss_driver_command_line_name;
+               return true;
+       } else if (driver_name == freebob_driver_name) {
+               command_line_name = freebob_driver_command_line_name;
+               return true;
+       } else if (driver_name == ffado_driver_name) {
+               command_line_name = ffado_driver_command_line_name;
+               return true;
+       } else if (driver_name == netjack_driver_name) {
+               command_line_name = netjack_driver_command_line_name;
+               return true;
+       } else if (driver_name == dummy_driver_name) {
+               command_line_name = dummy_driver_command_line_name;
+               return true;
+       }
+       return false;
+}
+
+bool
+get_jack_command_line_audio_device_name (const string& driver_name,
+               const string& device_name, string& command_line_device_name)
+{
+       using namespace ARDOUR;
+       device_map_t devices;
+
+       get_jack_device_names_for_audio_driver (driver_name, devices);
+
+       for (device_map_t::const_iterator i = devices.begin (); i != devices.end(); ++i) {
+               if (i->first == device_name) {
+                       command_line_device_name = i->second;
+                       return true;
+               }
+       }
+       return false;
+}
+
+bool
+get_jack_command_line_dither_mode (const string& dither_mode, string& command_line_dither_mode)
+{
+       using namespace ARDOUR;
+
+       if (dither_mode == _("Triangular")) {
+               command_line_dither_mode = "triangular";
+               return true;
+       } else if (dither_mode == _("Rectangular")) {
+               command_line_dither_mode = "rectangular";
+               return true;
+       } else if (dither_mode == _("Shaped")) {
+               command_line_dither_mode = "shaped";
+               return true;
+       }
+
+       return false;
+}
+
+void
+ARDOUR::get_jack_alsa_device_names (device_map_t& devices)
+{
+#ifdef HAVE_ALSA
+       snd_ctl_t *handle;
+       snd_ctl_card_info_t *info;
+       snd_pcm_info_t *pcminfo;
+       snd_ctl_card_info_alloca(&info);
+       snd_pcm_info_alloca(&pcminfo);
+       string devname;
+       int cardnum = -1;
+       int device = -1;
+
+       while (snd_card_next (&cardnum) >= 0 && cardnum >= 0) {
+
+               devname = "hw:";
+               devname += PBD::to_string (cardnum, std::dec);
+
+               if (snd_ctl_open (&handle, devname.c_str(), 0) >= 0 && snd_ctl_card_info (handle, info) >= 0) {
+
+                       if (snd_ctl_card_info (handle, info) < 0) {
+                               continue;
+                       }
+                       
+                       string card_name = snd_ctl_card_info_get_name (info);
+
+                       /* change devname to use ID, not number */
+
+                       devname = "hw:";
+                       devname += snd_ctl_card_info_get_id (info);
+
+                       while (snd_ctl_pcm_next_device (handle, &device) >= 0 && device >= 0) {
+                               
+                               /* only detect duplex devices here. more
+                                * complex arrangements are beyond our scope
+                                */
+
+                               snd_pcm_info_set_device (pcminfo, device);
+                               snd_pcm_info_set_subdevice (pcminfo, 0);
+                               snd_pcm_info_set_stream (pcminfo, SND_PCM_STREAM_CAPTURE);
+                               
+                               if (snd_ctl_pcm_info (handle, pcminfo) >= 0) {
+
+                                       snd_pcm_info_set_device (pcminfo, device);
+                                       snd_pcm_info_set_subdevice (pcminfo, 0);
+                                       snd_pcm_info_set_stream (pcminfo, SND_PCM_STREAM_PLAYBACK);
+
+                                       if (snd_ctl_pcm_info (handle, pcminfo) >= 0) {
+                                               devname += ',';
+                                               devname += PBD::to_string (device, std::dec);
+                                               devices.insert (std::make_pair (card_name, devname));
+                                       }
+                               }
+                       }
+
+                       snd_ctl_close(handle);
+               }
+       }
+#else
+       /* silence a compiler unused variable warning */
+       (void) devices;
+#endif
+}
+
+#ifdef __APPLE__
+static OSStatus
+getDeviceUIDFromID( AudioDeviceID id, char *name, size_t nsize)
+{
+       UInt32 size = sizeof(CFStringRef);
+       CFStringRef UI;
+       OSStatus res = AudioDeviceGetProperty(id, 0, false,
+               kAudioDevicePropertyDeviceUID, &size, &UI);
+       if (res == noErr)
+               CFStringGetCString(UI,name,nsize,CFStringGetSystemEncoding());
+       CFRelease(UI);
+       return res;
+}
+#endif
+
+void
+ARDOUR::get_jack_coreaudio_device_names (device_map_t& devices)
+{
+#ifdef __APPLE__
+       // Find out how many Core Audio devices are there, if any...
+       // (code snippet gently "borrowed" from St?hane Letz jackdmp;)
+       OSStatus err;
+       Boolean isWritable;
+       UInt32 outSize = sizeof(isWritable);
+
+       err = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices,
+                                          &outSize, &isWritable);
+       if (err == noErr) {
+               // Calculate the number of device available...
+               int numCoreDevices = outSize / sizeof(AudioDeviceID);
+               // Make space for the devices we are about to get...
+               AudioDeviceID *coreDeviceIDs = new AudioDeviceID [numCoreDevices];
+               err = AudioHardwareGetProperty(kAudioHardwarePropertyDevices,
+                                              &outSize, (void *) coreDeviceIDs);
+               if (err == noErr) {
+                       // Look for the CoreAudio device name...
+                       char coreDeviceName[256];
+                       UInt32 nameSize;
+
+                       for (int i = 0; i < numCoreDevices; i++) {
+
+                               nameSize = sizeof (coreDeviceName);
+
+                               /* enforce duplex devices only */
+
+                               err = AudioDeviceGetPropertyInfo(coreDeviceIDs[i],
+                                                                0, true, kAudioDevicePropertyStreams,
+                                                                &outSize, &isWritable);
+
+                               if (err != noErr || outSize == 0) {
+                                       continue;
+                               }
+
+                               err = AudioDeviceGetPropertyInfo(coreDeviceIDs[i],
+                                                                0, false, kAudioDevicePropertyStreams,
+                                                                &outSize, &isWritable);
+
+                               if (err != noErr || outSize == 0) {
+                                       continue;
+                               }
+
+                               err = AudioDeviceGetPropertyInfo(coreDeviceIDs[i],
+                                                                0, true, kAudioDevicePropertyDeviceName,
+                                                                &outSize, &isWritable);
+                               if (err == noErr) {
+                                       err = AudioDeviceGetProperty(coreDeviceIDs[i],
+                                                                    0, true, kAudioDevicePropertyDeviceName,
+                                                                    &nameSize, (void *) coreDeviceName);
+                                       if (err == noErr) {
+                                               char drivername[128];
+
+                                               // this returns the unique id for the device
+                                               // that must be used on the commandline for jack
+
+                                               if (getDeviceUIDFromID(coreDeviceIDs[i], drivername, sizeof (drivername)) == noErr) {
+                                                       devices.insert (make_pair (coreDeviceName, drivername));
+                                               }
+                                       }
+                               }
+                       }
+               }
+               delete [] coreDeviceIDs;
+       }
+#else
+       /* silence a compiler unused variable warning */
+       (void) devices;
+#endif
+}
+
+void
+ARDOUR::get_jack_portaudio_device_names (device_map_t& devices)
+{
+#ifdef HAVE_PORTAUDIO
+       if (Pa_Initialize() != paNoError) {
+               return;
+       }
+
+       for (PaDeviceIndex i = 0; i < Pa_GetDeviceCount (); ++i) {
+               string api_name;
+               string readable_name;
+               string jack_device_name;
+               const PaDeviceInfo* device_info = Pa_GetDeviceInfo(i);
+
+               if (device_info != NULL) { // it should never be ?
+                       api_name = Pa_GetHostApiInfo (device_info->hostApi)->name;
+                       readable_name = api_name + " " + device_info->name;
+                       jack_device_name = api_name + "::" + device_info->name;
+                       devices.insert (make_pair (readable_name, jack_device_name));
+               }
+       }
+       Pa_Terminate();
+#else
+       /* silence a compiler unused variable warning */
+       (void) devices;
+#endif
+}
+
+void
+ARDOUR::get_jack_oss_device_names (device_map_t& devices)
+{
+       devices.insert (make_pair (default_device_name, default_device_name));
+}
+
+void
+ARDOUR::get_jack_freebob_device_names (device_map_t& devices)
+{
+       devices.insert (make_pair (default_device_name, default_device_name));
+}
+
+void
+ARDOUR::get_jack_ffado_device_names (device_map_t& devices)
+{
+       devices.insert (make_pair (default_device_name, default_device_name));
+}
+
+void
+ARDOUR::get_jack_netjack_device_names (device_map_t& devices)
+{
+       devices.insert (make_pair (default_device_name, default_device_name));
+}
+
+void
+ARDOUR::get_jack_dummy_device_names (device_map_t& devices)
+{
+       devices.insert (make_pair (default_device_name, default_device_name));
+}
+
+bool
+ARDOUR::get_jack_device_names_for_audio_driver (const string& driver_name, device_map_t& devices)
+{
+       devices.clear();
+
+       if (driver_name == portaudio_driver_name) {
+               get_jack_portaudio_device_names (devices);
+       } else if (driver_name == coreaudio_driver_name) {
+               get_jack_coreaudio_device_names (devices);
+       } else if (driver_name == alsa_driver_name) {
+               get_jack_alsa_device_names (devices);
+       } else if (driver_name == oss_driver_name) {
+               get_jack_oss_device_names (devices);
+       } else if (driver_name == freebob_driver_name) {
+               get_jack_freebob_device_names (devices);
+       } else if (driver_name == ffado_driver_name) {
+               get_jack_ffado_device_names (devices);
+       } else if (driver_name == netjack_driver_name) {
+               get_jack_netjack_device_names (devices);
+       } else if (driver_name == dummy_driver_name) {
+               get_jack_dummy_device_names (devices);
+       }
+
+       return !devices.empty();
+}
+
+
+std::vector<std::string>
+ARDOUR::get_jack_device_names_for_audio_driver (const string& driver_name)
+{
+       std::vector<std::string> readable_names;
+       device_map_t devices;
+
+       get_jack_device_names_for_audio_driver (driver_name, devices);
+
+       for (device_map_t::const_iterator i = devices.begin (); i != devices.end(); ++i) {
+               readable_names.push_back (i->first);
+       }
+
+       return readable_names;
+}
+
+bool
+ARDOUR::get_jack_audio_driver_supports_two_devices (const string& driver)
+{
+       return (driver == alsa_driver_name || driver == oss_driver_name);
+}
+
+bool
+ARDOUR::get_jack_audio_driver_supports_latency_adjustment (const string& driver)
+{
+       return (driver == alsa_driver_name || driver == coreaudio_driver_name ||
+                       driver == ffado_driver_name || driver == portaudio_driver_name);
+}
+
+bool
+ARDOUR::get_jack_audio_driver_supports_setting_period_count (const string& driver)
+{
+       return !(driver == dummy_driver_name || driver == coreaudio_driver_name ||
+                       driver == portaudio_driver_name);
+}
+
+bool
+ARDOUR::get_jack_server_application_names (std::vector<std::string>& server_names)
+{
+#ifdef WIN32
+       server_names.push_back ("jackd.exe");
+#else
+       server_names.push_back ("jackd");
+       server_names.push_back ("jackdmp");
+#endif
+       return !server_names.empty();
+}
+
+void
+ARDOUR::set_path_env_for_jack_autostart (const vector<std::string>& dirs)
+{
+#ifdef __APPLE__
+       // push it back into the environment so that auto-started JACK can find it.
+       // XXX why can't we just expect OS X users to have PATH set correctly? we can't ...
+       setenv ("PATH", SearchPath(dirs).to_string().c_str(), 1);
+#else
+       /* silence a compiler unused variable warning */
+       (void) dirs;
+#endif
+}
+
+bool
+ARDOUR::get_jack_server_dir_paths (vector<std::string>& server_dir_paths)
+{
+#ifdef __APPLE__
+       /* this magic lets us finds the path to the OSX bundle, and then
+          we infer JACK's location from there
+       */
+
+       char execpath[MAXPATHLEN+1];
+       uint32_t pathsz = sizeof (execpath);
+
+       _NSGetExecutablePath (execpath, &pathsz);
+
+       server_dir_paths.push_back (Glib::path_get_dirname (execpath));
+#endif
+
+       SearchPath sp(string(g_getenv("PATH")));
+
+#ifdef WIN32
+       gchar *install_dir = g_win32_get_package_installation_directory_of_module (NULL);
+       if (install_dir) {
+               sp.push_back (install_dir);
+               g_free (install_dir);
+       }
+       // don't try and use a system wide JACK install yet.
+#else
+       if (sp.empty()) {
+               sp.push_back ("/usr/bin");
+               sp.push_back ("/bin");
+               sp.push_back ("/usr/local/bin");
+               sp.push_back ("/opt/local/bin");
+       }
+#endif
+
+       std::copy (sp.begin(), sp.end(), std::back_inserter(server_dir_paths));
+
+       return !server_dir_paths.empty();
+}
+
+bool
+ARDOUR::get_jack_server_paths (const vector<std::string>& server_dir_paths,
+               const vector<string>& server_names,
+               vector<std::string>& server_paths)
+{
+       for (vector<string>::const_iterator i = server_names.begin(); i != server_names.end(); ++i) {
+                Glib::PatternSpec ps (*i);
+               find_matching_files_in_directories (server_dir_paths, ps, server_paths);
+       }
+       return !server_paths.empty();
+}
+
+bool
+ARDOUR::get_jack_server_paths (vector<std::string>& server_paths)
+{
+       vector<std::string> server_dirs;
+
+       if (!get_jack_server_dir_paths (server_dirs)) {
+               return false;
+       }
+
+       vector<string> server_names;
+
+       if (!get_jack_server_application_names (server_names)) {
+               return false;
+       }
+
+       if (!get_jack_server_paths (server_dirs, server_names, server_paths)) {
+               return false;
+       }
+
+       return !server_paths.empty();
+}
+
+bool
+ARDOUR::get_jack_default_server_path (std::string& server_path)
+{
+       vector<std::string> server_paths;
+
+       if (!get_jack_server_paths (server_paths)) {
+               return false;
+       }
+
+       server_path = server_paths.front ();
+       return true;
+}
+
+string
+quote_string (const string& str)
+{
+       return "\"" + str + "\"";
+}
+
+ARDOUR::JackCommandLineOptions::JackCommandLineOptions ()
+       : server_path ()
+       , timeout(0)
+       , no_mlock(false)
+       , ports_max(128)
+       , realtime(true)
+       , priority(0)
+       , unlock_gui_libs(false)
+       , verbose(false)
+       , temporary(true)
+       , driver()
+       , input_device()
+       , output_device()
+       , num_periods(2)
+       , period_size(1024)
+       , samplerate(48000)
+       , input_latency(0)
+       , output_latency(0)
+       , hardware_metering(false)
+       , hardware_monitoring(false)
+       , dither_mode()
+       , force16_bit(false)
+       , soft_mode(false)
+       , midi_driver()
+{
+
+}
+
+bool
+ARDOUR::get_jack_command_line_string (const JackCommandLineOptions& options, string& command_line)
+{
+       vector<string> args;
+
+       args.push_back (options.server_path);
+
+#ifdef WIN32
+       // must use sync mode on windows
+       args.push_back ("-S");
+
+       // this needs to be added now on windows
+       if (!options.midi_driver.empty () && options.midi_driver != get_none_string ()) {
+               args.push_back ("-X");
+               args.push_back (options.midi_driver);
+       }
+#endif
+
+       if (options.timeout) {
+               args.push_back ("-t");
+               args.push_back (to_string (options.timeout, std::dec));
+       }
+
+       if (options.no_mlock) {
+               args.push_back ("-m");
+       }
+
+       args.push_back ("-p");
+       args.push_back (to_string(options.ports_max, std::dec));
+
+       if (options.realtime) {
+               args.push_back ("-R");
+               if (options.priority != 0) {
+                       args.push_back ("-P");
+                       args.push_back (to_string(options.priority, std::dec));
+               }
+       } else {
+               args.push_back ("-r");
+       }
+
+       if (options.unlock_gui_libs) {
+               args.push_back ("-u");
+       }
+
+       if (options.verbose) {
+               args.push_back ("-v");
+       }
+
+#ifndef WIN32
+       if (options.temporary) {
+               args.push_back ("-T");
+       }
+#endif
+
+       string command_line_driver_name;
+
+       if (!get_jack_command_line_audio_driver_name (options.driver, command_line_driver_name)) {
+               return false;
+       }
+
+       args.push_back ("-d");
+       args.push_back (command_line_driver_name);
+
+       if (options.output_device.empty() && options.input_device.empty()) {
+               return false;
+       }
+
+       string command_line_input_device_name;
+       string command_line_output_device_name;
+
+       if (!get_jack_command_line_audio_device_name (options.driver,
+               options.input_device, command_line_input_device_name)) {
+               return false;
+       }
+
+       if (!get_jack_command_line_audio_device_name (options.driver,
+               options.output_device, command_line_output_device_name)) {
+               return false;
+       }
+
+       if (options.input_device.empty()) {
+               // playback only
+               if (options.output_device.empty()) {
+                       return false;
+               }
+               args.push_back ("-P");
+       } else if (options.output_device.empty()) {
+               // capture only
+               if (options.input_device.empty()) {
+                       return false;
+               }
+               args.push_back ("-C");
+       } else if (options.input_device != options.output_device) {
+               // capture and playback on two devices if supported
+               if (get_jack_audio_driver_supports_two_devices (options.driver)) {
+                       args.push_back ("-C");
+                       args.push_back (command_line_input_device_name);
+                       args.push_back ("-P");
+                       args.push_back (command_line_output_device_name);
+               } else {
+                       return false;
+               }
+       }
+
+       if (options.input_channels) {
+               args.push_back ("-i");
+               args.push_back (to_string (options.input_channels, std::dec));
+       }
+
+       if (options.output_channels) {
+               args.push_back ("-o");
+               args.push_back (to_string (options.output_channels, std::dec));
+       }
+
+       if (get_jack_audio_driver_supports_setting_period_count (options.driver)) {
+               args.push_back ("-n");
+               args.push_back (to_string (options.num_periods, std::dec));
+       }
+
+       args.push_back ("-r");
+       args.push_back (to_string (options.samplerate, std::dec));
+
+       args.push_back ("-p");
+       args.push_back (to_string (options.period_size, std::dec));
+
+       if (get_jack_audio_driver_supports_latency_adjustment (options.driver)) {
+               if (options.input_latency) {
+                       args.push_back ("-I");
+                       args.push_back (to_string (options.input_latency, std::dec));
+               }
+               if (options.output_latency) {
+                       args.push_back ("-O");
+                       args.push_back (to_string (options.output_latency, std::dec));
+               }
+       }
+
+       if (options.input_device == options.output_device && options.input_device != default_device_name) {
+               args.push_back ("-d");
+               args.push_back (command_line_input_device_name);
+       }
+
+       if (options.driver == alsa_driver_name) {
+               if (options.hardware_metering) {
+                       args.push_back ("-M");
+               }
+               if (options.hardware_monitoring) {
+                       args.push_back ("-H");
+               }
+
+               string command_line_dither_mode;
+               if (get_jack_command_line_dither_mode (options.dither_mode, command_line_dither_mode)) {
+                       args.push_back ("-z");
+                       args.push_back (command_line_dither_mode);
+               }
+               if (options.force16_bit) {
+                       args.push_back ("-S");
+               }
+               if (options.soft_mode) {
+                       args.push_back ("-s");
+               }
+
+               if (!options.midi_driver.empty() && options.midi_driver != get_none_string ()) {
+                       args.push_back ("-X");
+                       args.push_back (options.midi_driver);
+               }
+       }
+
+       ostringstream oss;
+
+       for (vector<string>::const_iterator i = args.begin(); i != args.end();) {
+#ifdef WIN32
+               oss << quote_string (*i);
+#else
+               oss << *i;
+#endif
+               if (++i != args.end()) oss << ' ';
+       }
+
+       command_line = oss.str();
+       return true;
+}
+
+string
+ARDOUR::get_jack_server_config_file_name ()
+{
+       return ".jackdrc";
+}
+
+std::string
+ARDOUR::get_jack_server_user_config_dir_path ()
+{
+       return Glib::get_home_dir ();
+}
+
+std::string
+ARDOUR::get_jack_server_user_config_file_path ()
+{
+       return Glib::build_filename (get_jack_server_user_config_dir_path (), get_jack_server_config_file_name ());
+}
+
+bool
+ARDOUR::write_jack_config_file (const std::string& config_file_path, const string& command_line)
+{
+       ofstream jackdrc (config_file_path.c_str());
+
+       if (!jackdrc) {
+               error << string_compose (_("cannot open JACK rc file %1 to store parameters"), config_file_path) << endmsg;
+               return false;
+       }
+
+       jackdrc << command_line << endl;
+       jackdrc.close ();
+       return true;
+}
diff --git a/libs/backends/jack/jack_utils.h b/libs/backends/jack/jack_utils.h
new file mode 100644 (file)
index 0000000..7565353
--- /dev/null
@@ -0,0 +1,235 @@
+/*
+    Copyright (C) 2011 Tim Mayberry
+
+    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 <stdint.h>
+
+#include <vector>
+#include <map>
+#include <string>
+
+namespace ARDOUR {
+
+       // Names for the drivers on all possible systems
+       extern const char * const portaudio_driver_name;
+       extern const char * const coreaudio_driver_name;
+       extern const char * const alsa_driver_name;
+       extern const char * const oss_driver_name;
+       extern const char * const freebob_driver_name;
+       extern const char * const ffado_driver_name;
+       extern const char * const netjack_driver_name;
+       extern const char * const dummy_driver_name;
+
+       /**
+        * Get a list of possible JACK audio driver names based on platform
+        */
+       void get_jack_audio_driver_names (std::vector<std::string>& driver_names);
+
+       /**
+        * Get the default JACK audio driver based on platform
+        */
+       void get_jack_default_audio_driver_name (std::string& driver_name);
+
+       /**
+        * Get a list of possible samplerates supported be JACK
+        */
+       void get_jack_sample_rate_strings (std::vector<std::string>& sample_rates);
+
+       /**
+        * @return The default samplerate
+        */
+       std::string get_jack_default_sample_rate ();
+
+       /**
+        * @return true if sample rate string was able to be converted
+        */
+       bool get_jack_sample_rate_value_from_string (const std::string& srs, uint32_t& srv);
+
+       /**
+        * Get a list of possible period sizes supported be JACK
+        */
+       void get_jack_period_size_strings (std::vector<std::string>& samplerates);
+
+       /**
+        * @return The default period size
+        */
+       std::string get_jack_default_period_size ();
+
+       /**
+        * @return true if period size string was able to be converted
+        */
+       bool get_jack_period_size_value_from_string (const std::string& pss, uint32_t& psv);
+
+       /**
+        * These are driver specific I think, so it may require a driver arg
+        * in future
+        */
+       void get_jack_dither_mode_strings (const std::string& driver, std::vector<std::string>& dither_modes);
+
+       /**
+        * @return The default dither mode
+        */
+       std::string get_jack_default_dither_mode (const std::string& driver);
+
+       /**
+        * @return Estimate of latency
+        *
+        * API matches current use in GUI
+        */
+       std::string get_jack_latency_string (std::string samplerate, float periods, std::string period_size);
+
+       /**
+        * Key being a readable name to display in a GUI
+        * Value being name used in a jack commandline
+        */
+       typedef std::map<std::string, std::string> device_map_t;
+
+       /**
+        * Use library specific code to find out what what devices exist for a given
+        * driver that might work in JACK. There is no easy way to find out what
+        * modules the JACK server supports so guess based on platform. For instance
+        * portaudio is cross-platform but we only return devices if built for
+        * windows etc
+        */
+       void get_jack_alsa_device_names (device_map_t& devices);
+       void get_jack_portaudio_device_names (device_map_t& devices);
+       void get_jack_coreaudio_device_names (device_map_t& devices);
+       void get_jack_oss_device_names (device_map_t& devices);
+       void get_jack_freebob_device_names (device_map_t& devices);
+       void get_jack_ffado_device_names (device_map_t& devices);
+       void get_jack_netjack_device_names (device_map_t& devices);
+       void get_jack_dummy_device_names (device_map_t& devices);
+
+       /*
+        * @return true if there were devices found for the driver
+        *
+        * @param driver The driver name returned by get_jack_audio_driver_names
+        * @param devices The map used to insert the drivers into, devices will be cleared before
+        * adding the available drivers
+        */
+       bool get_jack_device_names_for_audio_driver (const std::string& driver, device_map_t& devices);
+
+       /*
+        * @return a list of readable device names for a specific driver.
+        */
+       std::vector<std::string> get_jack_device_names_for_audio_driver (const std::string& driver);
+
+       /**
+        * @return true if the driver supports playback and recording
+        * on separate devices
+        */
+       bool get_jack_audio_driver_supports_two_devices (const std::string& driver);
+
+       bool get_jack_audio_driver_supports_latency_adjustment (const std::string& driver);
+
+       bool get_jack_audio_driver_supports_setting_period_count (const std::string& driver);
+
+       /**
+        * The possible names to use to try and find servers, this includes
+        * any file extensions like .exe on Windows
+        *
+        * @return true if the JACK application names for this platform could be guessed
+        */
+       bool get_jack_server_application_names (std::vector<std::string>& server_names);
+
+       /**
+        * Sets the PATH environment variable to contain directories likely to contain
+        * JACK servers so that if the JACK server is auto-started it can find the server
+        * executable.
+        *
+        * This is only modifies PATH on the mac at the moment.
+        */
+       void set_path_env_for_jack_autostart (const std::vector<std::string>&);
+
+       /**
+        * Get absolute paths to directories that might contain JACK servers on the system
+        *
+        * @return true if !server_paths.empty()
+        */
+       bool get_jack_server_dir_paths (std::vector<std::string>& server_dir_paths);
+
+       /**
+        * Get absolute paths to JACK servers on the system
+        *
+        * @return true if a server was found
+        */
+       bool get_jack_server_paths (const std::vector<std::string>& server_dir_paths,
+                       const std::vector<std::string>& server_names,
+                       std::vector<std::string>& server_paths);
+
+
+       bool get_jack_server_paths (std::vector<std::string>& server_paths);
+
+       /**
+        * Get absolute path to default JACK server
+        */
+       bool get_jack_default_server_path (std::string& server_path);
+
+       /**
+        * @return The name of the jack server config file
+        */
+       std::string get_jack_server_config_file_name ();
+
+       std::string get_jack_server_user_config_dir_path ();
+
+       std::string get_jack_server_user_config_file_path ();
+
+       bool write_jack_config_file (const std::string& config_file_path, const std::string& command_line);
+
+       struct JackCommandLineOptions {
+
+               // see implementation for defaults
+               JackCommandLineOptions ();
+
+               //operator bool
+               //operator ostream
+
+               std::string      server_path;
+               uint32_t         timeout;
+               bool             no_mlock;
+               uint32_t         ports_max;
+               bool             realtime;
+               uint32_t         priority;
+               bool             unlock_gui_libs;
+               bool             verbose;
+               bool             temporary;
+               bool             playback_only;
+               bool             capture_only;
+               std::string      driver;
+               std::string      input_device;
+               std::string      output_device;
+               uint32_t         num_periods;
+               uint32_t         period_size;
+               uint32_t         samplerate;
+               uint32_t         input_channels;
+               uint32_t         output_channels;
+               uint32_t         input_latency;
+               uint32_t         output_latency;
+               bool             hardware_metering;
+               bool             hardware_monitoring;
+               std::string      dither_mode;
+               bool             force16_bit;
+               bool             soft_mode;
+               std::string      midi_driver;
+       };
+
+       /**
+        * @return true if able to build a valid command line based on options
+        */
+       bool get_jack_command_line_string (const JackCommandLineOptions& options, std::string& command_line);
+}
diff --git a/libs/backends/jack/wscript b/libs/backends/jack/wscript
new file mode 100644 (file)
index 0000000..3c47f3a
--- /dev/null
@@ -0,0 +1,51 @@
+#!/usr/bin/env python
+from waflib.extras import autowaf as autowaf
+import os
+import sys
+import re
+
+# Library version (UNIX style major, minor, micro)
+# major increment <=> incompatible changes
+# minor increment <=> compatible changes (additions)
+# micro increment <=> no interface changes
+JACKBACKEND_VERSION = '1.0.0'
+I18N_PACKAGE = 'jack-backend'
+
+# Mandatory variables
+top = '.'
+out = 'build'
+
+def options(opt):
+    autowaf.set_options(opt)
+
+def configure(conf):
+    autowaf.configure(conf)
+
+def build(bld):
+    obj = bld(features = 'cxx cxxshlib')
+    obj.source = [ 
+            'jack_api.cc',
+            'jack_connection.cc',
+            'jack_audiobackend.cc',
+            'jack_portengine.cc',
+            'jack_utils.cc'
+            ]
+    obj.includes = ['.']
+    obj.cxxflags = [ '-fPIC' ]
+    obj.name     = 'jack_audiobackend'
+    obj.target   = 'jack_audiobackend'
+    obj.uselib   = [ 'JACK' ]
+    obj.use      = 'ardour libpbd'
+    obj.vnum     = JACKBACKEND_VERSION
+    obj.install_path  = os.path.join(bld.env['LIBDIR'], 'ardour3', 'backends')
+    obj.defines = ['PACKAGE="' + I18N_PACKAGE + '"']
+    
+
+    #
+    # device discovery code in the jack backend needs ALSA
+    # on Linux.
+    # 
+
+    if re.search ("linux", sys.platform) != None:
+       obj.uselib += [ 'ALSA' ]
+
diff --git a/libs/backends/wscript b/libs/backends/wscript
new file mode 100644 (file)
index 0000000..b8779b7
--- /dev/null
@@ -0,0 +1,27 @@
+#!/usr/bin/env python
+from waflib.extras import autowaf as autowaf
+import os
+
+# Mandatory variables
+top = '.'
+out = 'build'
+
+backends = [ 'jack' ]
+
+def options(opt):
+    autowaf.set_options(opt)
+
+def sub_config_and_use(conf, name, has_objects = True):
+    conf.recurse(name)
+    autowaf.set_local_lib(conf, name, has_objects)
+
+def configure(conf):
+    autowaf.set_recursive()
+    autowaf.configure(conf)
+
+    for i in backends:
+        sub_config_and_use(conf, i)
+
+def build(bld):
+    for i in backends:
+        bld.recurse(i)
diff --git a/wscript b/wscript
index 6691f06dee8189893b0e1d2d58bcd4669df9843a..c4cba628dd598d6463a61f46eb237874af653f78 100644 (file)
--- a/wscript
+++ b/wscript
@@ -29,6 +29,7 @@ children = [
         'libs/rubberband',
         'libs/surfaces',
         'libs/panners',
+        'libs/backends',
         'libs/timecode',
         'libs/ardour',
         'libs/gtkmm2ext',