From 5e0c6af4062a2982fb90ad318973ab1d4beed2b9 Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Tue, 30 Jul 2013 17:48:57 -0400 Subject: [PATCH] jack_audiobackend.cc finally compiles --- gtk2_ardour/ardour_ui.cc | 6 +- libs/ardour/ardour/audio_backend.h | 41 +- libs/ardour/ardour/audioengine.h | 21 +- libs/ardour/ardour/jack_audiobackend.h | 57 ++- libs/ardour/ardour/jack_portengine.h | 75 ++- libs/ardour/ardour/port_manager.h | 8 +- libs/ardour/ardour/session.h | 4 +- libs/ardour/audioengine.cc | 144 +++++- libs/ardour/jack_audiobackend.cc | 636 ++++++++----------------- libs/ardour/jack_connection.cc | 2 + libs/ardour/jack_portengine.cc | 71 +++ libs/ardour/lv2_plugin.cc | 4 +- libs/ardour/port_manager.cc | 39 ++ libs/ardour/session_time.cc | 26 +- libs/ardour/wscript | 8 +- 15 files changed, 626 insertions(+), 516 deletions(-) diff --git a/gtk2_ardour/ardour_ui.cc b/gtk2_ardour/ardour_ui.cc index aa71040f46..155826492b 100644 --- a/gtk2_ardour/ardour_ui.cc +++ b/gtk2_ardour/ardour_ui.cc @@ -396,7 +396,7 @@ ARDOUR_UI::create_engine () loading_message (_("Starting audio engine")); try { - engine = new ARDOUR::AudioEngine (ARDOUR_COMMAND_LINE::backend_client_name, ARDOUR_COMMAND_LINE::backend_session_uuid); + engine = ARDOUR::AudioEngine::create (ARDOUR_COMMAND_LINE::backend_client_name, ARDOUR_COMMAND_LINE::backend_session_uuid); } catch (...) { @@ -487,7 +487,7 @@ ARDOUR_UI::post_engine () update_disk_space (); update_cpu_load (); - update_sample_rate (engine->frame_rate()); + update_sample_rate (engine->sample_rate()); update_timecode_format (); Config->ParameterChanged.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::parameter_changed, this, _1), gui_context()); @@ -923,7 +923,7 @@ If you still wish to quit, please use the\n\n\ _session = 0; } - engine->stop (true); + engine->stop (); quit (); } diff --git a/libs/ardour/ardour/audio_backend.h b/libs/ardour/ardour/audio_backend.h index e8511d0c57..4d6d6a6dd8 100644 --- a/libs/ardour/ardour/audio_backend.h +++ b/libs/ardour/ardour/audio_backend.h @@ -28,6 +28,8 @@ #include +#include "ardour/types.h" + namespace ARDOUR { class AudioEngine; @@ -45,6 +47,8 @@ class AudioBackend { */ virtual std::string name() const = 0; + virtual void* private_handle() const = 0; + /** return true if the underlying mechanism/API is still available * for us to utilize. return false if some or all of the AudioBackend * API can no longer be effectively used. @@ -98,13 +102,6 @@ class AudioBackend { */ virtual uint32_t available_output_channel_count (const std::string& device) const = 0; - enum SampleFormat { - Signed16bitInteger, - Signed24bitInteger, - Signed32bitInteger, - FloatingPoint - }; - /* Set the hardware parameters. * * If called when the current state is stopped or paused, @@ -163,15 +160,15 @@ class AudioBackend { */ virtual int set_systemic_output_latency (uint32_t) = 0; - virtual std::string get_device_name () const = 0; - virtual float get_sample_rate () const = 0; - virtual uint32_t get_buffer_size () const = 0; - virtual SampleFormat get_sample_format () const = 0; - virtual bool get_interleaved () const = 0; - virtual uint32_t get_input_channels () const = 0; - virtual uint32_t get_output_channels () const = 0; - virtual uint32_t get_systemic_input_latency () const = 0; - virtual uint32_t get_systemic_output_latency () const = 0; + virtual std::string device_name () const = 0; + virtual float sample_rate () const = 0; + virtual uint32_t buffer_size () const = 0; + virtual SampleFormat sample_format () const = 0; + virtual bool interleaved () const = 0; + virtual uint32_t input_channels () const = 0; + virtual uint32_t output_channels () const = 0; + virtual uint32_t systemic_input_latency () const = 0; + virtual uint32_t systemic_output_latency () const = 0; /* Basic state control */ @@ -246,7 +243,7 @@ class AudioBackend { * Implementations can feel free to smooth the values returned over * time (e.g. high pass filtering, or its equivalent). */ - virtual float get_cpu_load() const = 0; + virtual float cpu_load() const = 0; /* Transport Control (JACK is the only audio API that currently offers the concept of shared transport control) @@ -260,14 +257,14 @@ class AudioBackend { virtual void transport_stop () {} /** return the current transport state */ - virtual TransportState transport_state () { return TransportStopped; } + virtual TransportState transport_state () const { return TransportStopped; } /** Attempt to locate the transport to @param pos */ virtual void transport_locate (framepos_t /*pos*/) {} /** Return the current transport location, in samples measured * from the origin (defined by the transport time master) */ - virtual framepos_t transport_frame() { return 0; } + virtual framepos_t transport_frame() const { return 0; } /** If @param yn is true, become the time master for any inter-application transport * timebase, otherwise cease to be the time master for the same. @@ -279,9 +276,7 @@ class AudioBackend { */ virtual int set_time_master (bool /*yn*/) { return 0; } - virtual framecnt_t sample_rate () const; - virtual pframes_t samples_per_cycle () const; - virtual int usecs_per_cycle () const { return 1000000 * (samples_per_cycle() / sample_rate()); } + virtual int usecs_per_cycle () const { return 1000000 * (buffer_size() / sample_rate()); } virtual size_t raw_buffer_size (DataType t); /* Process time */ @@ -338,7 +333,7 @@ class AudioBackend { */ virtual int create_process_thread (boost::function func, pthread_t*, size_t stacksize) = 0; - private: + protected: AudioEngine& engine; }; diff --git a/libs/ardour/ardour/audioengine.h b/libs/ardour/ardour/audioengine.h index d7d9ca8224..4ac9221238 100644 --- a/libs/ardour/ardour/audioengine.h +++ b/libs/ardour/ardour/audioengine.h @@ -104,7 +104,8 @@ public: pframes_t samples_since_cycle_start (); bool get_sync_offset (pframes_t& offset) const; int create_process_thread (boost::function func, pthread_t*, size_t stacksize); - + bool is_realtime() const; + /* END BACKEND PROXY API */ bool freewheeling() const { return _freewheeling; } @@ -180,13 +181,21 @@ public: static void destroy(); void died (); - /* The backend will cause this at the appropriate time(s) + /* The backend will cause these at the appropriate time(s) */ - int process_callback (pframes_t nframes); + int process_callback (pframes_t nframes); + int buffer_size_change (pframes_t nframes); + int sample_rate_change (pframes_t nframes); + void freewheel_callback (bool); + void timebase_callback (TransportState state, pframes_t nframes, framepos_t pos, int new_position); + int sync_callback (TransportState state, framepos_t position); + int port_registration_callback (); + void latency_callback (bool for_playback); + void halted_callback (const char* reason); + + /* sets up the process callback thread */ + static void thread_init_callback (void *); - int buffer_size_change (pframes_t nframes); - int sample_rate_change (pframes_t nframes); - private: AudioEngine (const std::string& client_name, const std::string& session_uuid); diff --git a/libs/ardour/ardour/jack_audiobackend.h b/libs/ardour/ardour/jack_audiobackend.h index 6d2683790c..8f6e636d1a 100644 --- a/libs/ardour/ardour/jack_audiobackend.h +++ b/libs/ardour/ardour/jack_audiobackend.h @@ -22,6 +22,7 @@ #include #include +#include #include @@ -38,10 +39,11 @@ class JackConnection; class JACKAudioBackend : public AudioBackend { public: - JACKAudioBackend (AudioEngine& e); + JACKAudioBackend (AudioEngine& e, void*); ~JACKAudioBackend (); std::string name() const; + void* private_handle() const; bool connected() const; bool is_realtime () const; @@ -61,34 +63,53 @@ class JACKAudioBackend : public AudioBackend { int set_systemic_input_latency (uint32_t); int set_systemic_output_latency (uint32_t); - std::string get_device_name () const; - float get_sample_rate () const; - uint32_t get_buffer_size () const; - SampleFormat get_sample_format () const; - bool get_interleaved () const; - uint32_t get_input_channels () const; - uint32_t get_output_channels () const; - uint32_t get_systemic_input_latency () const; - uint32_t get_systemic_output_latency () const; + 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 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; + private: - JackConnection* _jack_connection; + JackConnection* _jack_connection; //< shared with JACKPortEngine + bool _running; + bool _freewheeling; + std::map _raw_buffer_sizes; static int _xrun_callback (void *arg); - static int _graph_order_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 _registration_callback (jack_port_id_t, int, void *); - static void _connect_callback (jack_port_id_t, jack_port_id_t, int, void *); 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); @@ -99,12 +120,12 @@ class JACKAudioBackend : public AudioBackend { int jack_bufsize_callback (pframes_t); int jack_sample_rate_callback (pframes_t); void freewheel_callback (int); - void connect_callback (jack_port_id_t, jack_port_id_t, 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 connect_to_jack (std::string client_name, std::string session_uuid); + int reconnect_to_jack (); struct ThreadData { JACKAudioBackend* engine; @@ -136,6 +157,8 @@ class JACKAudioBackend : public AudioBackend { uint32_t _current_sample_rate; uint32_t _current_buffer_size; uint32_t _current_usecs_per_cycle; + uint32_t _current_systemic_input_latency; + uint32_t _current_systemic_output_latency; }; diff --git a/libs/ardour/ardour/jack_portengine.h b/libs/ardour/ardour/jack_portengine.h index 2456adc272..60aa52fb6b 100644 --- a/libs/ardour/ardour/jack_portengine.h +++ b/libs/ardour/ardour/jack_portengine.h @@ -20,13 +20,84 @@ #ifndef __libardour_jack_portengine_h__ #define __libardour_jack_portengine_h__ +#include +#include + +#include + +#include "ardour/port_engine.h" +#include "ardour/types.h" + namespace ARDOUR { +class JackConnection; + class JACKPortEngine : public PortEngine { public: - JACKPortEngine (const std::string& client_name, - const std::string& session_uuid); + JACKPortEngine (void* arg); // argument is a JackConnection + + bool connected() const; + void* private_handle() 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; + + std::string make_port_name_relative (const std::string& name) const; + std::string make_port_name_non_relative (const std::string& name) const; + bool port_is_mine (const std::string& fullname) const; + + PortHandle register_port (const std::string& shortname, ARDOUR::DataType, ARDOUR::PortFlags); + void unregister_port (PortHandle); + + bool connected (PortHandle); + bool connected_to (PortHandle, const std::string&); + bool physically_connected (PortHandle); + + int get_connections (PortHandle, std::vector&); + + int connect (PortHandle, const std::string&); + int disconnect (PortHandle, const std::string&); + int disconnect_all (PortHandle); + + int connect (const std::string& src, const std::string& dst); + int disconnect (const std::string& src, const std::string& dst); + + /* MIDI */ + + void midi_event_get (pframes_t& timestamp, size_t& size, uint8_t** buf, void* port_buffer, uint32_t event_index); + int midi_event_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); + LatencyRange get_connected_latency_range (PortHandle, int dir); + + void* get_buffer (PortHandle, pframes_t); + + pframes_t last_frame_time () const; + + private: + 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); + }; } // namespace diff --git a/libs/ardour/ardour/port_manager.h b/libs/ardour/ardour/port_manager.h index 0e9a84ea8c..29a566aa2d 100644 --- a/libs/ardour/ardour/port_manager.h +++ b/libs/ardour/ardour/port_manager.h @@ -55,10 +55,12 @@ class PortManager /* Port connectivity */ - int connect (const std::string& source, const std::string& destination); - int disconnect (const std::string& source, const std::string& destination); - int disconnect (boost::shared_ptr); + int connect (const std::string& source, const std::string& destination); + int disconnect (const std::string& source, const std::string& destination); + int disconnect (boost::shared_ptr); bool connected (const std::string&); + int reestablish_ports (); + int reconnect_ports (); /* other Port management */ diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index a782680082..4c005ffa74 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -1426,8 +1426,8 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi */ std::list _current_trans_quarks; - 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*); + // void timebase_callback (TransportState, pframes_t, jack_position_t*, int); + int jack_sync_callback (TransportState, framepos_t); void reset_jack_connection (jack_client_t* jack); void process_rtop (SessionEvent*); diff --git a/libs/ardour/audioengine.cc b/libs/ardour/audioengine.cc index 1e43c590a0..1f26e12a3b 100644 --- a/libs/ardour/audioengine.cc +++ b/libs/ardour/audioengine.cc @@ -165,6 +165,33 @@ AudioEngine::split_cycle (pframes_t offset) } } +int +AudioEngine::sample_rate_change (pframes_t nframes) +{ + /* check for monitor input change every 1/10th of second */ + + monitor_check_interval = nframes / 10; + last_monitor_check = 0; + + if (_session) { + _session->set_frame_rate (nframes); + } + + SampleRateChanged (nframes); /* EMIT SIGNAL */ + + return 0; +} + +int +AudioEngine::buffer_size_change (pframes_t bufsiz) +{ + if (_session) { + _session->set_block_size (bufsiz); + last_monitor_check = 0; + } + + return 0; +} /** Method called by our ::process_thread when there is work to be done. * @param nframes Number of frames to process. @@ -399,7 +426,7 @@ AudioEngine::set_session (Session *s) start_metering_thread (); - pframes_t blocksize = _backend->get_buffer_size (); + pframes_t blocksize = _backend->buffer_size (); /* page in as much of the session process code as we can before we really start running. @@ -558,6 +585,12 @@ AudioEngine::start () if (_backend->start() == 0) { _running = true; _has_run = true; + last_monitor_check = 0; + + if (_session && _session->config.get_jack_time_master()) { + _backend->set_time_master (true); + } + Running(); /* EMIT SIGNAL */ } else { /* should report error? */ @@ -573,8 +606,19 @@ AudioEngine::stop () if (!_backend) { return 0; } - - return _backend->stop (); + + Glib::Threads::Mutex::Lock lm (_process_lock); + + if (_backend->stop () == 0) { + _running = false; + stop_metering_thread (); + + Stopped (); /* EMIT SIGNAL */ + + return 0; + } + + return -1; } int @@ -584,7 +628,13 @@ AudioEngine::pause () return 0; } - return _backend->pause (); + if (_backend->pause () == 0) { + _running = false; + Stopped(); /* EMIT SIGNAL */ + return 0; + } + + return -1; } int @@ -605,7 +655,17 @@ AudioEngine::get_cpu_load() const if (!_backend) { return 0.0; } - return _backend->get_cpu_load (); + return _backend->cpu_load (); +} + +bool +AudioEngine::is_realtime() const +{ + if (!_backend) { + return false; + } + + return _backend->is_realtime(); } void @@ -668,7 +728,7 @@ AudioEngine::samples_per_cycle () const if (!_backend) { return 0; } - return _backend->samples_per_cycle (); + return _backend->buffer_size (); } int @@ -677,7 +737,7 @@ AudioEngine::usecs_per_cycle () const if (!_backend) { return -1; } - return _backend->start (); + return _backend->usecs_per_cycle (); } size_t @@ -734,3 +794,73 @@ AudioEngine::create_process_thread (boost::function func, pthread_t* thr return _backend->create_process_thread (func, thr, stacksize); } + +void +AudioEngine::thread_init_callback (void* arg) +{ + /* make sure that anybody who needs to know about this thread + knows about it. + */ + + pthread_set_name (X_("audioengine")); + + PBD::notify_gui_about_thread_creation ("gui", pthread_self(), X_("AudioEngine"), 4096); + PBD::notify_gui_about_thread_creation ("midiui", pthread_self(), X_("AudioEngine"), 128); + + SessionEvent::create_per_thread_pool (X_("AudioEngine"), 512); + + MIDI::JackMIDIPort::set_process_thread (pthread_self()); + + if (arg) { + AudioEngine* ae = static_cast (arg); + /* the special thread created/managed by the backend */ + ae->_main_thread = new ProcessThread; + } +} + +/* XXXX +void +AudioEngine::timebase_callback (TransportState state, pframes_t nframes, jack_position_t pos, int new_position) +{ + if (_session && _session->synced_to_jack()) { + // _session->timebase_callback (state, nframes, pos, new_position); + } +} +*/ + +int +AudioEngine::sync_callback (TransportState state, framepos_t position) +{ + if (_session) { + return _session->jack_sync_callback (state, position); + } + return 0; +} + +void +AudioEngine::freewheel_callback (bool onoff) +{ + if (onoff) { + _pre_freewheel_mmc_enabled = MIDI::Manager::instance()->mmc()->send_enabled (); + MIDI::Manager::instance()->mmc()->enable_send (false); + } else { + MIDI::Manager::instance()->mmc()->enable_send (_pre_freewheel_mmc_enabled); + } +} + +void +AudioEngine::latency_callback (bool for_playback) +{ + if (_session) { + _session->update_latency (for_playback); + } +} + +void +AudioEngine::halted_callback (const char* why) +{ + stop_metering_thread (); + + MIDI::JackMIDIPort::EngineHalted (); /* EMIT SIGNAL */ + Halted (why); /* EMIT SIGNAL */ +} diff --git a/libs/ardour/jack_audiobackend.cc b/libs/ardour/jack_audiobackend.cc index bc2a1b9e3b..7575e8387e 100644 --- a/libs/ardour/jack_audiobackend.cc +++ b/libs/ardour/jack_audiobackend.cc @@ -20,6 +20,11 @@ #include #include +#include + +#include "pbd/error.h" + +#include "midi++/manager.h" #include "ardour/audioengine.h" #include "ardour/types.h" @@ -27,59 +32,24 @@ #include "ardour/jack_connection.h" #include "ardour/jack_portengine.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 (!(v)) { return; } -#define GET_PRIVATE_JACK_POINTER_RET(localvar,r) jack_client_t* localvar = _jack_connection->jack(); if (!(v)) { return r; } - -extern "C" { - - - /* functions looked up using dlopen-and-cousins, and so naming scope - * must be non-mangled. - */ - - AudioBackend* backend_factory (AudioEngine& ae, void* backend_data) - { - JACKAudioBackend* ab = new JACKAudioBackend (ae, backend_data); - return ab; - } - - PortEngine* portengine_factory (PortEngine& ae, void* backend_data) - { - JACKPortEngine* pe = new JACKPortEngine (ae, backend_data); - return pe; - } - - int - instantiate (const std::string& arg1, const std::string& arg2, void** backend_data) - { - JackConnection *jc; - try { - jc = new JackConnection (arg1, arg2); - } catch { - return -1; - } - - *backend_data = (void*) jc; - return 0; - } - - int - deinstantiate (void* backend_data) - { - JackConnection* jc = static_cast (backend_data); - delete jc; - } -} +#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, void* jc) : AudioBackend (e) - , _jack_connection (jc) + , _jack_connection (static_cast(jc)) + , _running (false) + , _freewheeling (false) , _target_sample_rate (48000) , _target_buffer_size (1024) - , _target_sample_format (FloatingPoint) + , _target_sample_format (FormatFloat) , _target_interleaved (false) , _target_input_channels (-1) , _target_output_channels (-1) @@ -95,9 +65,9 @@ JACKAudioBackend::name() const } void* -JACKAudioBackend::private_handle() +JACKAudioBackend::private_handle() const { - return _jack_connection->jack() + return _jack_connection->jack(); } bool @@ -107,7 +77,7 @@ JACKAudioBackend::connected() const } bool -JACKAudioBackend::is_realtime () +JACKAudioBackend::is_realtime () const { GET_PRIVATE_JACK_POINTER_RET (_priv_jack,false); return jack_is_realtime (_priv_jack); @@ -125,8 +95,8 @@ JACKAudioBackend::available_sample_rates (const string& /*device*/) const { vector f; - if (_jack) { - f.push_back (get_sample_rate()); + if (connected()) { + f.push_back (sample_rate()); return f; } @@ -153,8 +123,8 @@ JACKAudioBackend::available_buffer_sizes (const string& /*device*/) const { vector s; - if (_jack) { - s.push_back (get_buffer_size()); + if (connected()) { + s.push_back (buffer_size()); return s; } @@ -174,13 +144,13 @@ JACKAudioBackend::available_buffer_sizes (const string& /*device*/) const } uint32_t -JACKAudioBackend::available_input_channel_count (const string& /*device*/) +JACKAudioBackend::available_input_channel_count (const string& /*device*/) const { return 128; } uint32_t -JACKAudioBackend::available_output_channel_count (const string& /*device*/) +JACKAudioBackend::available_output_channel_count (const string& /*device*/) const { return 128; } @@ -190,7 +160,7 @@ JACKAudioBackend::available_output_channel_count (const string& /*device*/) int JACKAudioBackend::set_device_name (const string& dev) { - if (_jack) { + if (connected()) { /* need to stop and restart JACK for this to work, at present */ return -1; } @@ -203,12 +173,17 @@ int JACKAudioBackend::set_sample_rate (float sr) { GET_PRIVATE_JACK_POINTER_RET (_priv_jack, -1); + + if (!connected()) { + _target_sample_rate = sr; + return 0; + } if (sr == jack_get_sample_rate (_priv_jack)) { return 0; } - return jack_set_sample_rate (_priv_jack, lrintf (sr)); + return -1; } int @@ -216,6 +191,11 @@ JACKAudioBackend::set_buffer_size (uint32_t nframes) { GET_PRIVATE_JACK_POINTER_RET (_priv_jack, -1); + if (!connected()) { + _target_buffer_size = nframes; + return 0; + } + if (nframes == jack_get_buffer_size (_priv_jack)) { return 0; } @@ -229,7 +209,7 @@ JACKAudioBackend::set_sample_format (SampleFormat sf) /* as far as JACK clients are concerned, the hardware is always * floating point format. */ - if (sf == FloatingPoint) { + if (sf == FormatFloat) { return 0; } return -1; @@ -250,167 +230,179 @@ JACKAudioBackend::set_interleaved (bool yn) int JACKAudioBackend::set_input_channels (uint32_t cnt) { - if (_jack) { + if (connected()) { return -1; } _target_input_channels = cnt; + + return 0; } int JACKAudioBackend::set_output_channels (uint32_t cnt) { - if (_jack) { + if (connected()) { return -1; } _target_output_channels = cnt; + + return 0; } int JACKAudioBackend::set_systemic_input_latency (uint32_t l) { - if (_jack) { + if (connected()) { return -1; } _target_systemic_input_latency = l; + + return 0; } int JACKAudioBackend::set_systemic_output_latency (uint32_t l) { - if (_jack) { + if (connected()) { return -1; } _target_systemic_output_latency = l; + + return 0; } /* --- Parameter retrieval --- */ std::string -JACKAudioBackend::get_device_name () const +JACKAudioBackend::device_name () const { + return string(); } float -JACKAudioBackend::get_sample_rate () const +JACKAudioBackend::sample_rate () const { - if (_jack) { + if (connected()) { return _current_sample_rate; } return _target_sample_rate; } uint32_t -JACKAudioBackend::get_buffer_size () const +JACKAudioBackend::buffer_size () const { - if (_jack) { + if (connected()) { return _current_buffer_size; } return _target_buffer_size; } SampleFormat -JACKAudioBackend::get_sample_format () const +JACKAudioBackend::sample_format () const { - return FloatingPoint; + return FormatFloat; } bool -JACKAudioBackend::get_interleaved () const +JACKAudioBackend::interleaved () const { return false; } uint32_t -JACKAudioBackend::get_input_channels () const +JACKAudioBackend::input_channels () const { - if (_jack) { - return n_physical (JackPortIsInput); + if (connected()) { + return n_physical (JackPortIsInput).n_audio(); } return _target_input_channels; } uint32_t -JACKAudioBackend::get_output_channels () const +JACKAudioBackend::output_channels () const { - if (_jack) { - return n_physical (JackPortIsOutput); + if (connected()) { + return n_physical (JackPortIsOutput).n_audio(); } return _target_output_channels; } uint32_t -JACKAudioBackend::get_systemic_input_latency () const +JACKAudioBackend::systemic_input_latency () const { return _current_systemic_output_latency; } uint32_t -JACKAudioBackend::get_systemic_output_latency () const +JACKAudioBackend::systemic_output_latency () const { return _current_systemic_output_latency; } +size_t +JACKAudioBackend::raw_buffer_size(DataType t) +{ + std::map::const_iterator s = _raw_buffer_sizes.find(t); + return (s != _raw_buffer_sizes.end()) ? s->second : 0; +} + /* ---- BASIC STATE CONTROL API: start/stop/pause/freewheel --- */ int JACKAudioBackend::start () { + if (!connected()) { + _jack_connection->open (); + } + + 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; + } + GET_PRIVATE_JACK_POINTER_RET (_priv_jack, -1); - if (!_running) { - - if (!jack_port_type_get_buffer_size) { - warning << _("This version of JACK is old - you should upgrade to a newer version that supports jack_port_type_get_buffer_size()") << endmsg; - } - - if (_session) { - BootMessage (_("Connect session to engine")); - _session->set_frame_rate (jack_get_sample_rate (_priv_jack)); - } - - /* a proxy for whether jack_activate() will definitely call the buffer size - * callback. with older versions of JACK, this function symbol will be null. - * this is reliable, but not clean. - */ - - if (!jack_port_type_get_buffer_size) { - jack_bufsize_callback (jack_get_buffer_size (_priv_jack)); - } - - _processed_frames = 0; - last_monitor_check = 0; - - set_jack_callbacks (); - - if (jack_activate (_priv_jack) == 0) { - _running = true; - _has_run = true; - Running(); /* EMIT SIGNAL */ - } else { - // error << _("cannot activate JACK client") << endmsg; - } + engine.sample_rate_change (jack_get_sample_rate (_priv_jack)); + + /* testing the nullity of this function name is a proxy for + * whether jack_activate() will definitely call the buffer size + * callback. with older versions of JACK, this function symbol + * will be null. this is sort of reliable, but not clean since + * weak symbol support is highly platform and compiler + * specific. + */ + if (!jack_port_type_get_buffer_size) { + jack_bufsize_callback (jack_get_buffer_size (_priv_jack)); } - - return _running ? 0 : -1; + + 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 (); - { - Glib::Threads::Mutex::Lock lm (_process_lock); - jack_client_close (_priv_jack); - _jack = 0; - } + _current_buffer_size = 0; + _current_sample_rate = 0; - _buffer_size = 0; - _frame_rate = 0; _raw_buffer_sizes.clear(); return 0; @@ -439,121 +431,12 @@ JACKAudioBackend::freewheel (bool onoff) return 0; } - return jack_set_freewheel (_priv_jack, onoff); -} - -int -JACKAudioBackend::set_parameters (const Parameters& params) -{ - return 0; -} - -int -JACKAudioBackend::get_parameters (Parameters& params) const -{ - return 0; -} - -/* parameters */ - -ARDOUR::pframes_t -AudioEngine::frames_per_cycle () const -{ - GET_PRIVATE_JACK_POINTER_RET (_priv_jack,0); - - if (_buffer_size == 0) { - return jack_get_buffer_size (_priv_jack); - } else { - return _buffer_size; - } -} - -ARDOUR::framecnt_t -AudioEngine::frame_rate () const -{ - GET_PRIVATE_JACK_POINTER_RET (_priv_jack, 0); - if (_frame_rate == 0) { - return (_frame_rate = jack_get_sample_rate (_priv_jack)); - } else { - return _frame_rate; - } -} - -size_t -AudioEngine::raw_buffer_size (DataType t) -{ - std::map::const_iterator s = _raw_buffer_sizes.find(t); - return (s != _raw_buffer_sizes.end()) ? s->second : 0; -} - - - -/*--- private support methods ---*/ - -int -JACKAudioBackend::reconnect_to_jack () -{ - if (_jack_connection->connected()) { - _jack_connection->close (); - /* XXX give jackd a chance */ - Glib::usleep (250000); + if (jack_set_freewheel (_priv_jack, onoff) == 0) { + _freewheeling = true; + return 0; } - if (_jack_connection->open()) { - error << _("failed to connect to JACK") << endmsg; - return -1; - } - - Ports::iterator i; - - boost::shared_ptr p = ports.reader (); - - for (i = p->begin(); i != p->end(); ++i) { - if (i->second->reestablish ()) { - break; - } - } - - if (i != p->end()) { - /* failed */ - remove_all_ports (); - return -1; - } - - GET_PRIVATE_JACK_POINTER_RET (_priv_jack,-1); - - MIDI::Manager::instance()->reestablish (_priv_jack); - - if (_session) { - _session->reset_jack_connection (_priv_jack); - jack_bufsize_callback (jack_get_buffer_size (_priv_jack)); - _session->set_frame_rate (jack_get_sample_rate (_priv_jack)); - } - - last_monitor_check = 0; - - set_jack_callbacks (); - - if (jack_activate (_priv_jack) == 0) { - _running = true; - _has_run = true; - } else { - return -1; - } - - /* re-establish connections */ - - for (i = p->begin(); i != p->end(); ++i) { - i->second->reconnect (); - } - - MIDI::Manager::instance()->reconnect (); - - Running (); /* EMIT SIGNAL*/ - - start_metering_thread (); - - return 0; + return -1; } /* --- TRANSPORT STATE MANAGEMENT --- */ @@ -586,8 +469,8 @@ JACKAudioBackend::transport_frame () const return jack_get_current_transport_frame (_priv_jack); } -JACKAudioBackend::TransportState -JACKAudioBackend::transport_state () +TransportState +JACKAudioBackend::transport_state () const { GET_PRIVATE_JACK_POINTER_RET (_priv_jack, ((TransportState) JackTransportStopped)); jack_position_t pos; @@ -601,29 +484,12 @@ JACKAudioBackend::set_time_master (bool yn) if (yn) { return jack_set_timebase_callback (_priv_jack, 0, _jack_timebase_callback, this); } else { - return jack_release_timebase (_jack); + return jack_release_timebase (_priv_jack); } } /* process-time */ -framecnt_t -JACKAudioBackend::sample_rate () const -{ - -} -pframes_t -JACKAudioBackend::samples_per_cycle () const -{ -} - -size_t -JACKAudioBackend::raw_buffer_size(DataType t) -{ - std::map::const_iterator s = _raw_buffer_sizes.find(t); - return (s != _raw_buffer_sizes.end()) ? s->second : 0; -} - bool JACKAudioBackend::get_sync_offset (pframes_t& offset) const { @@ -651,35 +517,26 @@ JACKAudioBackend::get_sync_offset (pframes_t& offset) const } pframes_t -JACKAudioBackend::frames_since_cycle_start () +JACKAudioBackend::sample_time () { - jack_client_t* _priv_jack = _jack; - if (!_running || !_priv_jack) { - return 0; - } - return jack_frames_since_cycle_start (_priv_jack); -} - -pframes_t -JACKAudioBackend::frame_time () -{ - jack_client_t* _priv_jack = _jack; - if (!_running || !_priv_jack) { - return 0; - } + GET_PRIVATE_JACK_POINTER_RET (_priv_jack, 0); return jack_frame_time (_priv_jack); } pframes_t -JACKAudioBackend::frame_time_at_cycle_start () +JACKAudioBackend::sample_time_at_cycle_start () { - jack_client_t* _priv_jack = _jack; - if (!_running || !_priv_jack) { - return 0; - } + 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 @@ -693,21 +550,15 @@ JACKAudioBackend::set_jack_callbacks () { GET_PRIVATE_JACK_POINTER (_priv_jack); - jack_set_thread_init_callback (_priv_jack, _thread_init_callback, this); + 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_graph_order_callback (_priv_jack, _graph_order_callback, this); - jack_set_port_registration_callback (_priv_jack, _registration_callback, this); - jack_set_port_connect_callback (_priv_jack, _connect_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); - if (_session && _session->config.get_jack_time_master()) { - jack_set_timebase_callback (_priv_jack, 0, _jack_timebase_callback, this); - } - #ifdef HAVE_JACK_SESSION if( jack_set_session_callback) jack_set_session_callback (_priv_jack, _session_callback, this); @@ -724,40 +575,75 @@ void JACKAudioBackend::_jack_timebase_callback (jack_transport_state_t state, pframes_t nframes, jack_position_t* pos, int new_position, void *arg) { - static_cast (arg)->jack_timebase_callback (state, nframes, pos, new_position); + static_cast (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) +JACKAudioBackend::jack_timebase_callback (jack_transport_state_t state, pframes_t /*nframes*/, + jack_position_t* pos, int /*new_position*/) { - if (_jack && _session && _session->synced_to_jack()) { - _session->jack_timebase_callback (state, nframes, pos, new_position); + TransportState tstate; + framepos_t position; + + switch (state) { + case JackTransportStopped: + tstate = TransportStopped; + break; + case JackTransportRolling: + tstate = TransportRolling; + break; + case JackTransportLooping: + tstate = TransportLooping; + break; + case JackTransportStarting: + tstate = TransportStarting; + break; } + + if (pos) { + position = pos->frame; + } + + // engine.timebase_callback (tstate, nframes, position, new_position); } int JACKAudioBackend::_jack_sync_callback (jack_transport_state_t state, jack_position_t* pos, void* arg) { - return static_cast (arg)->jack_sync_callback (state, pos); + return static_cast (arg)->jack_sync_callback (state, pos); } int JACKAudioBackend::jack_sync_callback (jack_transport_state_t state, jack_position_t* pos) { - if (_jack && _session) { - return _session->jack_sync_callback (state, 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) { - AudioEngine* ae = static_cast (arg); + JACKAudioBackend* ae = static_cast (arg); if (ae->connected()) { - ae->Xrun (); /* EMIT SIGNAL */ + ae->engine.Xrun (); /* EMIT SIGNAL */ } return 0; } @@ -766,99 +652,30 @@ JACKAudioBackend::_xrun_callback (void *arg) void JACKAudioBackend::_session_callback (jack_session_event_t *event, void *arg) { - AudioEngine* ae = static_cast (arg); + JACKAudioBackend* ae = static_cast (arg); if (ae->connected()) { - ae->JackSessionEvent ( event ); /* EMIT SIGNAL */ + ae->engine.JackSessionEvent (event); /* EMIT SIGNAL */ } } #endif -int -JACKAudioBackend::_graph_order_callback (void *arg) -{ - AudioEngine* ae = static_cast (arg); - - if (ae->connected() && !ae->port_remove_in_progress) { - ae->GraphReordered (); /* EMIT SIGNAL */ - } - - return 0; -} - void JACKAudioBackend::_freewheel_callback (int onoff, void *arg) { - static_cast(arg)->freewheel_callback (onoff); + static_cast(arg)->freewheel_callback (onoff); } void JACKAudioBackend::freewheel_callback (int onoff) { _freewheeling = onoff; - - if (onoff) { - _pre_freewheel_mmc_enabled = MIDI::Manager::instance()->mmc()->send_enabled (); - MIDI::Manager::instance()->mmc()->enable_send (false); - } else { - MIDI::Manager::instance()->mmc()->enable_send (_pre_freewheel_mmc_enabled); - } -} - -void -JACKAudioBackend::_registration_callback (jack_port_id_t /*id*/, int /*reg*/, void* arg) -{ - AudioEngine* ae = static_cast (arg); - - if (!ae->port_remove_in_progress) { - ae->PortRegisteredOrUnregistered (); /* EMIT SIGNAL */ - } + engine.freewheel_callback (onoff); } void JACKAudioBackend::_latency_callback (jack_latency_callback_mode_t mode, void* arg) { - return static_cast (arg)->jack_latency_callback (mode); -} - -void -JACKAudioBackend::_connect_callback (jack_port_id_t id_a, jack_port_id_t id_b, int conn, void* arg) -{ - AudioEngine* ae = static_cast (arg); - ae->connect_callback (id_a, id_b, conn); -} - -void -JACKAudioBackend::connect_callback (jack_port_id_t id_a, jack_port_id_t id_b, int conn) -{ - if (port_remove_in_progress) { - return; - } - - GET_PRIVATE_JACK_POINTER (_priv_jack); - - jack_port_t* jack_port_a = jack_port_by_id (_priv_jack, id_a); - jack_port_t* jack_port_b = jack_port_by_id (_priv_jack, id_b); - - boost::shared_ptr port_a; - boost::shared_ptr port_b; - Ports::iterator x; - boost::shared_ptr pr = ports.reader (); - - x = pr->find (make_port_name_relative (jack_port_name (jack_port_a))); - if (x != pr->end()) { - port_a = x->second; - } - - x = pr->find (make_port_name_relative (jack_port_name (jack_port_b))); - if (x != pr->end()) { - port_b = x->second; - } - - PortConnectedOrDisconnected ( - port_a, jack_port_name (jack_port_a), - port_b, jack_port_name (jack_port_b), - conn == 0 ? false : true - ); /* EMIT SIGNAL */ + return static_cast (arg)->jack_latency_callback (mode); } int @@ -890,7 +707,7 @@ JACKAudioBackend::_start_process_thread (void* arg) void* JACKAudioBackend::_process_thread (void *arg) { - return static_cast (arg)->process_thread (); + return static_cast (arg)->process_thread (); } void* @@ -899,9 +716,7 @@ JACKAudioBackend::process_thread () /* JACK doesn't do this for us when we use the wait API */ - _thread_init_callback (0); - - _main_thread = new ProcessThread; + AudioEngine::thread_init_callback (this); while (1) { GET_PRIVATE_JACK_POINTER_RET(_priv_jack,0); @@ -921,41 +736,26 @@ JACKAudioBackend::process_thread () int JACKAudioBackend::_sample_rate_callback (pframes_t nframes, void *arg) { - return static_cast (arg)->jack_sample_rate_callback (nframes); + return static_cast (arg)->jack_sample_rate_callback (nframes); } int JACKAudioBackend::jack_sample_rate_callback (pframes_t nframes) { - _frame_rate = nframes; - _usecs_per_cycle = (int) floor ((((double) frames_per_cycle() / nframes)) * 1000000.0); - - /* check for monitor input change every 1/10th of second */ - - monitor_check_interval = nframes / 10; - last_monitor_check = 0; - - if (_session) { - _session->set_frame_rate (nframes); - } - - SampleRateChanged (nframes); /* EMIT SIGNAL */ - - return 0; + _current_sample_rate = nframes; + return engine.sample_rate_change (nframes); } void JACKAudioBackend::jack_latency_callback (jack_latency_callback_mode_t mode) { - if (_session) { - _session->update_latency (mode == JackPlaybackLatency); - } + engine.latency_callback (mode == JackPlaybackLatency); } int JACKAudioBackend::_bufsize_callback (pframes_t nframes, void *arg) { - return static_cast (arg)->jack_bufsize_callback (nframes); + return static_cast (arg)->jack_bufsize_callback (nframes); } int @@ -970,8 +770,7 @@ JACKAudioBackend::jack_bufsize_callback (pframes_t nframes) GET_PRIVATE_JACK_POINTER_RET (_priv_jack, 1); _current_buffer_size = nframes; - _current_usecs_per_cycle = (int) floor ((((double) nframes / frame_rate())) * 1000000.0); - last_monitor_check = 0; + _current_usecs_per_cycle = (int) floor ((((double) nframes / sample_rate())) * 1000000.0); if (jack_port_type_get_buffer_size) { _raw_buffer_sizes[DataType::AUDIO] = jack_port_type_get_buffer_size (_priv_jack, JACK_DEFAULT_AUDIO_TYPE); @@ -993,66 +792,29 @@ JACKAudioBackend::jack_bufsize_callback (pframes_t nframes) _raw_buffer_sizes[DataType::MIDI] = nframes * 4 - (nframes/2); } - BufferSizeChange (nframes); - - if (_session) { - _session->set_block_size (_buffer_size); - } + engine.buffer_size_change (nframes); return 0; } void -JACKAudioBackend::halted_info (jack_status_t code, const char* reason, void *arg) +JACKAudioBackend::disconnected (const char* why) { /* called from jack shutdown handler */ - AudioEngine* ae = static_cast (arg); - bool was_running = ae->_running; + bool was_running = _running; - ae->stop_metering_thread (); - - ae->_running = false; - ae->_buffer_size = 0; - ae->_frame_rate = 0; - ae->_jack = 0; + _running = false; + _current_buffer_size = 0; + _current_sample_rate = 0; if (was_running) { - MIDI::JackMIDIPort::JackHalted (); /* EMIT SIGNAL */ -#ifdef HAVE_JACK_ON_INFO_SHUTDOWN - switch (code) { - case JackBackendError: - ae->Halted(reason); /* EMIT SIGNAL */ - break; - default: - ae->Halted(""); /* EMIT SIGNAL */ - } -#else - ae->Halted(""); /* EMIT SIGNAL */ -#endif + engine.halted_callback (why); /* EMIT SIGNAL */ } } - -void -JACKAudioBackend::halted (void *arg) +float +JACKAudioBackend::cpu_load() const { - cerr << "HALTED by JACK\n"; - - /* called from jack shutdown handler */ - - AudioEngine* ae = static_cast (arg); - bool was_running = ae->_running; - - ae->stop_metering_thread (); - - ae->_running = false; - ae->_buffer_size = 0; - ae->_frame_rate = 0; - ae->_jack = 0; - - if (was_running) { - MIDI::JackMIDIPort::JackHalted (); /* EMIT SIGNAL */ - ae->Halted(""); /* EMIT SIGNAL */ - } + GET_PRIVATE_JACK_POINTER_RET(_priv_jack,0); + return jack_cpu_load (_priv_jack); } - diff --git a/libs/ardour/jack_connection.cc b/libs/ardour/jack_connection.cc index e0937ea767..b6ac28b22a 100644 --- a/libs/ardour/jack_connection.cc +++ b/libs/ardour/jack_connection.cc @@ -62,6 +62,8 @@ JackConnection::open () boost::scoped_ptr current_epa; jack_status_t status; + close (); + /* revert all environment settings back to whatever they were when ardour started */ diff --git a/libs/ardour/jack_portengine.cc b/libs/ardour/jack_portengine.cc index f830785bae..99b0bd2b9a 100644 --- a/libs/ardour/jack_portengine.cc +++ b/libs/ardour/jack_portengine.cc @@ -1,3 +1,74 @@ +JACKPortEngine::init () +{ + jack_set_port_registration_callback (_priv_jack, _registration_callback, this); + jack_set_port_connect_callback (_priv_jack, _connect_callback, this); + jack_set_graph_order_callback (_priv_jack, _graph_order_callback, this); +} + +void +JACKPortEngine::_registration_callback (jack_port_id_t /*id*/, int /*reg*/, void* arg) +{ + JACKPortEngine* pm = static_cast (arg); + + if (!pm->port_remove_in_progress) { + pm->engine.PortRegisteredOrUnregistered (); /* EMIT SIGNAL */ + } +} + +void +JACKPortEngine::_connect_callback (jack_port_id_t id_a, jack_port_id_t id_b, int conn, void* arg) +{ + JACKPortEngine* pm = static_cast (arg); + pm->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 (port_remove_in_progress) { + return; + } + + GET_PRIVATE_JACK_POINTER (_priv_jack); + + jack_port_t* jack_port_a = jack_port_by_id (_priv_jack, id_a); + jack_port_t* jack_port_b = jack_port_by_id (_priv_jack, id_b); + + boost::shared_ptr port_a; + boost::shared_ptr port_b; + Ports::iterator x; + boost::shared_ptr pr = ports.reader (); + + x = pr->find (make_port_name_relative (jack_port_name (jack_port_a))); + if (x != pr->end()) { + port_a = x->second; + } + + x = pr->find (make_port_name_relative (jack_port_name (jack_port_b))); + if (x != pr->end()) { + port_b = x->second; + } + + PortConnectedOrDisconnected ( + port_a, jack_port_name (jack_port_a), + port_b, jack_port_name (jack_port_b), + conn == 0 ? false : true + ); /* EMIT SIGNAL */ +} + +int +JACKPortEngine::_graph_order_callback (void *arg) +{ + JACKPortEngine* pm = static_cast (arg); + + if (pm->connected() && !pm->port_remove_in_progress) { + pm->engine.GraphReordered (); /* EMIT SIGNAL */ + } + + return 0; +} + + JACKPortEngine::physically_connected (PortHandle p) { jack_port_t* _jack_port = (jack_port_t*) p; diff --git a/libs/ardour/lv2_plugin.cc b/libs/ardour/lv2_plugin.cc index 5ea76934a5..1f0859bc8d 100644 --- a/libs/ardour/lv2_plugin.cc +++ b/libs/ardour/lv2_plugin.cc @@ -289,7 +289,7 @@ LV2Plugin::init(const void* c_plugin, framecnt_t rate) _latency_control_port = 0; _next_cycle_start = std::numeric_limits::max(); _next_cycle_speed = 1.0; - _block_length = _engine.frames_per_cycle(); + _block_length = _engine.samples_per_cycle(); _seq_size = _engine.raw_buffer_size(DataType::MIDI); _state_version = 0; _was_activated = false; @@ -1901,7 +1901,7 @@ LV2Plugin::Impl::designated_input (const char* uri, void** bufptrs[], void** buf return port; } -static bool lv2_filter (const string& str, void *arg) +static bool lv2_filter (const string& str, void* /*arg*/) { /* Not a dotfile, has a prefix before a period, suffix is "lv2" */ diff --git a/libs/ardour/port_manager.cc b/libs/ardour/port_manager.cc index c279cf6d27..1a08849791 100644 --- a/libs/ardour/port_manager.cc +++ b/libs/ardour/port_manager.cc @@ -473,3 +473,42 @@ AudioEngine::disconnect (boost::shared_ptr port) return port->disconnect_all (); } +int +PortManager::reestablish_ports () +{ + Ports::iterator i; + + boost::shared_ptr p = ports.reader (); + + for (i = p->begin(); i != p->end(); ++i) { + if (i->second->reestablish ()) { + break; + } + } + + if (i != p->end()) { + /* failed */ + remove_all_ports (); + return -1; + } + + MIDI::Manager::instance()->reestablish (); + + return 0; +} + +int +PortManager::reconnect_ports () +{ + boost::shared_ptr p = ports.reader (); + + /* re-establish connections */ + + for (i = p->begin(); i != p->end(); ++i) { + i->second->reconnect (); + } + + MIDI::Manager::instance()->reconnect (); + + return 0; +} diff --git a/libs/ardour/session_time.cc b/libs/ardour/session_time.cc index 18805afa90..088712f625 100644 --- a/libs/ardour/session_time.cc +++ b/libs/ardour/session_time.cc @@ -180,31 +180,30 @@ Session::timecode_time (Timecode::Time &t) } int -Session::jack_sync_callback (jack_transport_state_t state, - jack_position_t* pos) +Session::jack_sync_callback (TransportState state, framepos_t pos) { bool slave = synced_to_jack(); switch (state) { - case JackTransportStopped: - if (slave && _transport_frame != pos->frame && post_transport_work() == 0) { - request_locate (pos->frame, false); + case TransportStopped: + if (slave && _transport_frame != pos && post_transport_work() == 0) { + request_locate (pos, false); // cerr << "SYNC: stopped, locate to " << pos->frame << " from " << _transport_frame << endl; return false; } else { return true; } - case JackTransportStarting: + case TransportStarting: // cerr << "SYNC: starting @ " << pos->frame << " a@ " << _transport_frame << " our work = " << post_transport_work() << " pos matches ? " << (_transport_frame == pos->frame) << endl; if (slave) { - return _transport_frame == pos->frame && post_transport_work() == 0; + return _transport_frame == pos && post_transport_work() == 0; } else { return true; } break; - case JackTransportRolling: + case TransportRolling: // cerr << "SYNC: rolling slave = " << slave << endl; if (slave) { start_transport (); @@ -212,17 +211,21 @@ Session::jack_sync_callback (jack_transport_state_t state, break; default: - error << string_compose (_("Unknown JACK transport state %1 in sync callback"), state) + error << string_compose (_("Unknown transport state %1 in sync callback"), state) << endmsg; } return true; } +/* XXX REQUIRES SOMEWAY TO EFFICIENTLY ACCESS jack_position_t WITHOUT BRIDGING + * THE ENTIRE DATA STRUCTURE + */ +#if 0 void -Session::jack_timebase_callback (jack_transport_state_t /*state*/, +Session::jack_timebase_callback (TransportState /*state*/, pframes_t /*nframes*/, - jack_position_t* pos, + framepos_t pos, int /*new_position*/) { Timecode::BBT_Time bbt; @@ -299,6 +302,7 @@ Session::jack_timebase_callback (jack_transport_state_t /*state*/, } #endif } +#endif /* jack data structure issues */ ARDOUR::framecnt_t Session::convert_to_frames (AnyTime const & position) diff --git a/libs/ardour/wscript b/libs/ardour/wscript index 8eb52436e9..a4749d95aa 100644 --- a/libs/ardour/wscript +++ b/libs/ardour/wscript @@ -435,9 +435,11 @@ def build(bld): # the JACK audio backend obj = bld.shlib (features = 'c cxx cshlib cxxshlib', - source = [ 'jack_connection.cc', - 'jack_audiobackend.cc' - ]) + source = [ + 'jack_api.cc', + 'jack_connection.cc', + 'jack_audiobackend.cc' + ]) obj.cxxflags = [ '-fPIC' ] obj.name = 'jack_audiobackend' obj.target = 'jack_audiobackend'