From f9d08daa477230f90c194edc555f77c267b5078c Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Fri, 13 Sep 2013 11:21:15 -0400 Subject: [PATCH] change inheritance so that an AudioBackend IS-A PortEngine This allows a derived (concrete) implementation to share information (e.g. sample rate, buffer size) between the audio backend side of things and the port management side of things. --- libs/ardour/ardour/audio_backend.h | 36 ++++++----- libs/ardour/ardour/audioengine.h | 2 - libs/ardour/ardour/port_engine.h | 22 +++---- libs/ardour/ardour/port_manager.h | 9 +-- libs/ardour/audioengine.cc | 5 +- libs/ardour/port.cc | 4 +- libs/ardour/port_manager.cc | 96 ++++++++++++++++-------------- 7 files changed, 89 insertions(+), 85 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 #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 (*backend_factory) (AudioEngine&); - boost::shared_ptr (*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 (*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 5762e709b3..201d960479 100644 --- a/libs/ardour/ardour/audioengine.h +++ b/libs/ardour/ardour/audioengine.h @@ -200,8 +200,6 @@ public: static AudioEngine* _instance; - boost::shared_ptr _backend; - Glib::Threads::Mutex _process_lock; Glib::Threads::Cond session_removed; bool session_remove_pending; 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) 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, std::string, boost::weak_ptr, std::string, bool> PortConnectedOrDisconnected; protected: - boost::shared_ptr _impl; + boost::shared_ptr _backend; SerializedRCUManager ports; bool _port_remove_in_progress; diff --git a/libs/ardour/audioengine.cc b/libs/ardour/audioengine.cc index 9c810a186f..73dee76a92 100644 --- a/libs/ardour/audioengine.cc +++ b/libs/ardour/audioengine.cc @@ -572,8 +572,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; @@ -704,7 +703,7 @@ AudioEngine::connected() const return false; } - return _backend->connected(); + return _backend->available(); } void diff --git a/libs/ardour/port.cc b/libs/ardour/port.cc index e8629cbf14..cf961d6828 100644 --- a/libs/ardour/port.cc +++ b/libs/ardour/port.cc @@ -122,7 +122,7 @@ Port::disconnect_all () bool Port::connected_to (std::string const & o) const { - if (!port_engine.connected()) { + if (!port_engine.available()) { return false; } @@ -132,7 +132,7 @@ Port::connected_to (std::string const & o) const int Port::get_connections (std::vector & 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& 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& 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 PortManager::get_port_by_name (const string& portname) { - if (!_impl) { + if (!_backend) { return boost::shared_ptr(); } @@ -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& 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) 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; +}