diff options
Diffstat (limited to 'libs/ardour')
-rw-r--r-- | libs/ardour/ardour/audio_backend.h | 36 | ||||
-rw-r--r-- | libs/ardour/ardour/audioengine.h | 4 | ||||
-rw-r--r-- | libs/ardour/ardour/port_engine.h | 22 | ||||
-rw-r--r-- | libs/ardour/ardour/port_manager.h | 9 | ||||
-rw-r--r-- | libs/ardour/ardour/session.h | 1 | ||||
-rw-r--r-- | libs/ardour/audioengine.cc | 56 | ||||
-rw-r--r-- | libs/ardour/port.cc | 4 | ||||
-rw-r--r-- | libs/ardour/port_manager.cc | 96 | ||||
-rw-r--r-- | libs/ardour/session.cc | 48 | ||||
-rw-r--r-- | libs/ardour/session_state.cc | 2 |
10 files changed, 171 insertions, 107 deletions
diff --git a/libs/ardour/ardour/audio_backend.h b/libs/ardour/ardour/audio_backend.h index 6c4a54da3e..d9561a62e5 100644 --- a/libs/ardour/ardour/audio_backend.h +++ b/libs/ardour/ardour/audio_backend.h @@ -29,17 +29,15 @@ #include <boost/function.hpp> #include "ardour/types.h" +#include "ardour/audioengine.h" +#include "ardour/port_engine.h" namespace ARDOUR { -class AudioEngine; -class PortEngine; -class PortManager; - -class AudioBackend { +class AudioBackend : public PortEngine { public: - AudioBackend (AudioEngine& e) : engine (e){} + AudioBackend (AudioEngine& e) : PortEngine (e), engine (e) {} virtual ~AudioBackend () {} /** Return the name of this backend. @@ -49,17 +47,6 @@ class AudioBackend { */ virtual std::string name() const = 0; - /** Return a private, type-free pointer to any data - * that might be useful to a concrete implementation - */ - 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. - */ - virtual bool connected() const = 0; - /** Return true if the callback from the underlying mechanism/API * (CoreAudio, JACK, ASIO etc.) occurs in a thread subject to realtime * constraints. Return false otherwise. @@ -416,11 +403,22 @@ class AudioBackend { struct AudioBackendInfo { const char* name; + /** Using arg1 and arg2, initialize this audiobackend. + * + * Returns zero on success, non-zero otherwise. + */ int (*instantiate) (const std::string& arg1, const std::string& arg2); + + /** Release all resources associated with this audiobackend + */ int (*deinstantiate) (void); - boost::shared_ptr<AudioBackend> (*backend_factory) (AudioEngine&); - boost::shared_ptr<PortEngine> (*portengine_factory) (PortManager&); + /** Factory method to create an AudioBackend-derived class. + * + * Returns a valid shared_ptr to the object if successfull, + * or a "null" shared_ptr otherwise. + */ + boost::shared_ptr<AudioBackend> (*factory) (AudioEngine&); /** Return true if the underlying mechanism/API has been * configured and does not need (re)configuration in order diff --git a/libs/ardour/ardour/audioengine.h b/libs/ardour/ardour/audioengine.h index 21206da8fc..201d960479 100644 --- a/libs/ardour/ardour/audioengine.h +++ b/libs/ardour/ardour/audioengine.h @@ -188,6 +188,7 @@ public: /* latency measurement */ MTDM* mtdm(); + int prepare_for_latency_measurement (); void start_latency_detection (); void stop_latency_detection (); void set_latency_input_port (const std::string&); @@ -199,8 +200,6 @@ public: static AudioEngine* _instance; - boost::shared_ptr<AudioBackend> _backend; - Glib::Threads::Mutex _process_lock; Glib::Threads::Cond session_removed; bool session_remove_pending; @@ -225,6 +224,7 @@ public: std::string _latency_input_name; std::string _latency_output_name; framecnt_t _latency_signal_latency; + bool _started_for_latency; void meter_thread (); void start_metering_thread (); diff --git a/libs/ardour/ardour/port_engine.h b/libs/ardour/ardour/port_engine.h index 71f93ea05e..8c0ec9e754 100644 --- a/libs/ardour/ardour/port_engine.h +++ b/libs/ardour/ardour/port_engine.h @@ -79,6 +79,11 @@ class PortEngine { PortEngine (PortManager& pm) : manager (pm) {} virtual ~PortEngine() {} + /** Return a private, type-free pointer to any data + * that might be useful to a concrete implementation + */ + virtual void* private_handle() const = 0; + /* We use void* here so that the API can be defined for any implementation. * * We could theoretically use a template (PortEngine<T>) and define @@ -89,21 +94,16 @@ class PortEngine { typedef void* PortHandle; - /** Return a typeless pointer to an object that may be of interest - * that understands the internals of a particular PortEngine - * implementation. - * - * XXX the existence of this method is a band-aid over some design - * issues and will it will be removed in the future - */ - virtual void* private_handle() const = 0; - - virtual bool connected() const = 0; - /** Return the name of this process as used by the port manager * when naming ports. */ virtual const std::string& my_name() const = 0; + + /** Return true if the underlying mechanism/API is still available + * for us to utilize. return false if some or all of the AudioBackend + * API can no longer be effectively used. + */ + virtual bool available() const = 0; /** Return the maximum size of a port name */ diff --git a/libs/ardour/ardour/port_manager.h b/libs/ardour/ardour/port_manager.h index 6d45597a41..ba15142d83 100644 --- a/libs/ardour/ardour/port_manager.h +++ b/libs/ardour/ardour/port_manager.h @@ -34,10 +34,12 @@ #include "ardour/chan_count.h" #include "ardour/midiport_manager.h" #include "ardour/port.h" -#include "ardour/port_engine.h" namespace ARDOUR { +class PortEngine; +class AudioBackend; + class PortManager { public: @@ -47,8 +49,7 @@ class PortManager PortManager (); virtual ~PortManager() {} - void set_port_engine (PortEngine& pe); - PortEngine& port_engine() { return *_impl; } + PortEngine& port_engine(); uint32_t port_name_size() const; std::string my_name() const; @@ -134,7 +135,7 @@ class PortManager PBD::Signal5<void, boost::weak_ptr<Port>, std::string, boost::weak_ptr<Port>, std::string, bool> PortConnectedOrDisconnected; protected: - boost::shared_ptr<PortEngine> _impl; + boost::shared_ptr<AudioBackend> _backend; SerializedRCUManager<Ports> ports; bool _port_remove_in_progress; diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index 43660d41cc..d0cd3fa06e 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -1624,6 +1624,7 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi void setup_ltc (); void setup_click (); void setup_bundles (); + int ensure_engine (uint32_t desired_sample_rate); }; } // namespace ARDOUR diff --git a/libs/ardour/audioengine.cc b/libs/ardour/audioengine.cc index ded8bf39b5..63bed97ecc 100644 --- a/libs/ardour/audioengine.cc +++ b/libs/ardour/audioengine.cc @@ -78,6 +78,7 @@ AudioEngine::AudioEngine () , _latency_output_port (0) , _latency_flush_frames (0) , _latency_signal_latency (0) + , _started_for_latency (false) { g_atomic_int_set (&m_meter_exit, 0); discover_backends (); @@ -200,6 +201,13 @@ AudioEngine::process_callback (pframes_t nframes) bool return_after_remove_check = false; if (_measuring_latency && _mtdm) { + /* run a normal cycle from the perspective of the PortManager + so that we get silence on all registered ports. + + we overwrite the silence on the two ports used for latency + measurement. + */ + PortManager::cycle_start (nframes); PortManager::silence (nframes); @@ -415,8 +423,6 @@ AudioEngine::remove_session () if (_running) { - stop_metering_thread (); - if (_session) { session_remove_pending = true; session_removal_countdown = 0; @@ -564,8 +570,7 @@ AudioEngine::set_backend (const std::string& name, const std::string& arg1, cons throw failed_constructor (); } - _backend = b->second->backend_factory (*this); - _impl = b->second->portengine_factory (*this); + _backend = b->second->factory (*this); } catch (exception& e) { error << string_compose (_("Could not create backend for %1: %2"), name, e.what()) << endmsg; @@ -607,7 +612,9 @@ AudioEngine::start () start_metering_thread (); - Running(); /* EMIT SIGNAL */ + if (!_started_for_latency) { + Running(); /* EMIT SIGNAL */ + } return 0; } @@ -630,6 +637,7 @@ AudioEngine::stop () _measuring_latency = false; _latency_output_port = 0; _latency_input_port = 0; + _started_for_latency = false; stop_metering_thread (); Port::PortDrop (); @@ -693,7 +701,7 @@ AudioEngine::connected() const return false; } - return _backend->connected(); + return _backend->available(); } void @@ -980,6 +988,13 @@ AudioEngine::halted_callback (const char* why) bool AudioEngine::setup_required () const { + /* If there is only a single backend and it claims to be configured + * already there is no setup to be done. + * + * Primarily for a case where there is only a JACK backend and + * JACK is already running. + */ + if (_backends.size() == 1 && _backends.begin()->second->already_configured()) { return false; } @@ -993,9 +1008,28 @@ AudioEngine::mtdm() return _mtdm; } +int +AudioEngine::prepare_for_latency_measurement () +{ + if (!running()) { + _started_for_latency = true; + + if (start()) { + _started_for_latency = false; + return -1; + } + } + + return 0; +} + void AudioEngine::start_latency_detection () { + if (prepare_for_latency_measurement ()) { + return; + } + PortEngine& pe (port_engine()); delete _mtdm; @@ -1027,23 +1061,25 @@ AudioEngine::start_latency_detection () lr = pe.get_latency_range (_latency_output_port, true); _latency_signal_latency += lr.max; - cerr << "latency signal pathway = " << _latency_signal_latency << endl; - /* all created and connected, lets go */ _mtdm = new MTDM (sample_rate()); _measuring_latency = true; _latency_flush_frames = samples_per_cycle(); - } void AudioEngine::stop_latency_detection () { + _measuring_latency = false; + port_engine().unregister_port (_latency_output_port); port_engine().unregister_port (_latency_input_port); - _measuring_latency = false; + + if (_started_for_latency) { + stop (); + } } void diff --git a/libs/ardour/port.cc b/libs/ardour/port.cc index d8a32e3467..bc5d26fb80 100644 --- a/libs/ardour/port.cc +++ b/libs/ardour/port.cc @@ -124,7 +124,7 @@ Port::disconnect_all () bool Port::connected_to (std::string const & o) const { - if (!port_engine.connected()) { + if (!port_engine.available()) { return false; } @@ -134,7 +134,7 @@ Port::connected_to (std::string const & o) const int Port::get_connections (std::vector<std::string> & c) const { - if (!port_engine.connected()) { + if (!port_engine.available()) { c.insert (c.end(), _connections.begin(), _connections.end()); return c.size(); } diff --git a/libs/ardour/port_manager.cc b/libs/ardour/port_manager.cc index 1758ea4a3f..c7adefc531 100644 --- a/libs/ardour/port_manager.cc +++ b/libs/ardour/port_manager.cc @@ -20,11 +20,12 @@ #include "pbd/error.h" #include "ardour/async_midi_port.h" -#include "ardour/debug.h" -#include "ardour/port_manager.h" +#include "ardour/audio_backend.h" #include "ardour/audio_port.h" +#include "ardour/debug.h" #include "ardour/midi_port.h" #include "ardour/midiport_manager.h" +#include "ardour/port_manager.h" #include "i18n.h" @@ -68,13 +69,13 @@ PortManager::remove_all_ports () string PortManager::make_port_name_relative (const string& portname) const { - if (!_impl) { + if (!_backend) { return portname; } string::size_type len; string::size_type n; - string self = _impl->my_name(); + string self = _backend->my_name(); len = portname.length(); @@ -100,7 +101,7 @@ PortManager::make_port_name_non_relative (const string& portname) const return portname; } - str = _impl->my_name(); + str = _backend->my_name(); str += ':'; str += portname; @@ -110,11 +111,11 @@ PortManager::make_port_name_non_relative (const string& portname) const bool PortManager::port_is_mine (const string& portname) const { - if (!_impl) { + if (!_backend) { return true; } - string self = _impl->my_name(); + string self = _backend->my_name(); if (portname.find_first_of (':') != string::npos) { if (portname.substr (0, self.length ()) != self) { @@ -128,54 +129,54 @@ PortManager::port_is_mine (const string& portname) const bool PortManager::port_is_physical (const std::string& portname) const { - if (!_impl) { + if (!_backend) { return false; } - PortEngine::PortHandle ph = _impl->get_port_by_name (portname); + PortEngine::PortHandle ph = _backend->get_port_by_name (portname); if (!ph) { return false; } - return _impl->port_is_physical (ph); + return _backend->port_is_physical (ph); } void PortManager::get_physical_outputs (DataType type, std::vector<std::string>& s) { - if (!_impl) { + if (!_backend) { return; } - _impl->get_physical_outputs (type, s); + _backend->get_physical_outputs (type, s); } void PortManager::get_physical_inputs (DataType type, std::vector<std::string>& s) { - if (!_impl) { + if (!_backend) { return; } - _impl->get_physical_inputs (type, s); + _backend->get_physical_inputs (type, s); } ChanCount PortManager::n_physical_outputs () const { - if (!_impl) { + if (!_backend) { return ChanCount::ZERO; } - return _impl->n_physical_outputs (); + return _backend->n_physical_outputs (); } ChanCount PortManager::n_physical_inputs () const { - if (!_impl) { + if (!_backend) { return ChanCount::ZERO; } - return _impl->n_physical_inputs (); + return _backend->n_physical_inputs (); } /** @param name Full or short name of port @@ -185,7 +186,7 @@ PortManager::n_physical_inputs () const boost::shared_ptr<Port> PortManager::get_port_by_name (const string& portname) { - if (!_impl) { + if (!_backend) { return boost::shared_ptr<Port>(); } @@ -204,7 +205,7 @@ PortManager::get_port_by_name (const string& portname) and cheap), and if so, rename the port (which will alter the port map as a side effect). */ - const std::string check = make_port_name_relative (_impl->get_port_name (x->second->port_handle())); + const std::string check = make_port_name_relative (_backend->get_port_name (x->second->port_handle())); if (check != rel) { x->second->set_name (check); } @@ -243,26 +244,26 @@ PortManager::get_ports (DataType type, PortList& pl) int PortManager::get_ports (const string& port_name_pattern, DataType type, PortFlags flags, vector<string>& s) { - if (!_impl) { + if (!_backend) { return 0; } - return _impl->get_ports (port_name_pattern, type, flags, s); + return _backend->get_ports (port_name_pattern, type, flags, s); } void PortManager::port_registration_failure (const std::string& portname) { - if (!_impl) { + if (!_backend) { return; } - string full_portname = _impl->my_name(); + string full_portname = _backend->my_name(); full_portname += ':'; full_portname += portname; - PortEngine::PortHandle p = _impl->get_port_by_name (full_portname); + PortEngine::PortHandle p = _backend->get_port_by_name (full_portname); string reason; if (p) { @@ -356,17 +357,17 @@ PortManager::unregister_port (boost::shared_ptr<Port> port) bool PortManager::connected (const string& port_name) { - if (!_impl) { + if (!_backend) { return false; } - PortEngine::PortHandle handle = _impl->get_port_by_name (port_name); + PortEngine::PortHandle handle = _backend->get_port_by_name (port_name); if (!handle) { return false; } - return _impl->connected (handle); + return _backend->connected (handle); } int @@ -387,8 +388,8 @@ PortManager::connect (const string& source, const string& destination) } else { /* neither port is known to us ...hand-off to the PortEngine */ - if (_impl) { - ret = _impl->connect (s, d); + if (_backend) { + ret = _backend->connect (s, d); } else { ret = -1; } @@ -423,8 +424,8 @@ PortManager::disconnect (const string& source, const string& destination) } else { /* neither port is known to us ...hand-off to the PortEngine */ - if (_impl) { - ret = _impl->disconnect (s, d); + if (_backend) { + ret = _backend->disconnect (s, d); } else { ret = -1; } @@ -516,59 +517,59 @@ PortManager::registration_callback () bool PortManager::can_request_input_monitoring () const { - if (!_impl) { + if (!_backend) { return false; } - return _impl->can_monitor_input (); + return _backend->can_monitor_input (); } void PortManager::request_input_monitoring (const string& name, bool yn) const { - if (!_impl) { + if (!_backend) { return; } - PortEngine::PortHandle ph = _impl->get_port_by_name (name); + PortEngine::PortHandle ph = _backend->get_port_by_name (name); if (ph) { - _impl->request_input_monitoring (ph, yn); + _backend->request_input_monitoring (ph, yn); } } void PortManager::ensure_input_monitoring (const string& name, bool yn) const { - if (!_impl) { + if (!_backend) { return; } - PortEngine::PortHandle ph = _impl->get_port_by_name (name); + PortEngine::PortHandle ph = _backend->get_port_by_name (name); if (ph) { - _impl->ensure_input_monitoring (ph, yn); + _backend->ensure_input_monitoring (ph, yn); } } uint32_t PortManager::port_name_size() const { - if (!_impl) { + if (!_backend) { return 0; } - return _impl->port_name_size (); + return _backend->port_name_size (); } string PortManager::my_name() const { - if (!_impl) { + if (!_backend) { return string(); } - return _impl->my_name(); + return _backend->my_name(); } int @@ -657,3 +658,10 @@ PortManager::fade_out (gain_t base_gain, gain_t gain_step, pframes_t nframes) } } } + +PortEngine& +PortManager::port_engine() +{ + assert (_backend); + return *_backend; +} diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index 135df7c2cd..4be42c769a 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -285,23 +285,10 @@ Session::Session (AudioEngine &eng, } } } - - if (_engine.current_backend() == 0 || _engine.setup_required()) { - boost::optional<int> r = AudioEngineSetupRequired (sr); - if (r.get_value_or (-1) != 0) { - destroy (); - throw failed_constructor(); - } - } - - /* at this point the engine should be connected (i.e. interacting - with a backend device (or psuedo-device) and available to us - for determinining sample rates and other settings. - */ - if (!_engine.connected()) { + if (ensure_engine (sr)) { destroy (); - throw failed_constructor(); + throw failed_constructor (); } if (post_engine_init ()) { @@ -346,6 +333,37 @@ Session::~Session () destroy (); } +int +Session::ensure_engine (uint32_t desired_sample_rate) +{ + if (_engine.current_backend() == 0) { + /* backend is unknown ... */ + boost::optional<int> r = AudioEngineSetupRequired (desired_sample_rate); + if (r.get_value_or (-1) != 0) { + return -1; + } + } else if (_engine.setup_required()) { + /* backend is known, but setup is needed */ + boost::optional<int> r = AudioEngineSetupRequired (desired_sample_rate); + if (r.get_value_or (-1) != 0) { + return -1; + } + } else if (!_engine.running()) { + if (_engine.start()) { + return -1; + } + } + + /* at this point the engine should be running + */ + + if (!_engine.running()) { + return -1; + } + + return 0; +} + void Session::destroy () { diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc index 64f8e387be..88a8a2ae04 100644 --- a/libs/ardour/session_state.cc +++ b/libs/ardour/session_state.cc @@ -309,6 +309,8 @@ Session::post_engine_init () _state_of_the_state = Clean; + Port::set_connecting_blocked (false); + DirtyChanged (); /* EMIT SIGNAL */ if (_is_new) { |