start code reorganization needed to deal with backend choices. compiles, links and runs as far as the startup screen now

This commit is contained in:
Paul Davis 2013-08-01 18:49:40 -04:00
parent 682ebad62b
commit df59a000b7
13 changed files with 217 additions and 45 deletions

View File

@ -395,30 +395,25 @@ ARDOUR_UI::create_engine ()
loading_message (_("Starting audio engine"));
try {
engine = ARDOUR::AudioEngine::create (ARDOUR_COMMAND_LINE::backend_client_name, ARDOUR_COMMAND_LINE::backend_session_uuid);
} catch (...) {
return -1;
}
AudioEngine* engine = AudioEngine::instance();
engine->Stopped.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::engine_stopped, this), gui_context());
engine->Running.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::engine_running, this), gui_context());
engine->SampleRateChanged.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::update_sample_rate, this, _1), gui_context());
engine->Halted.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::engine_halted, this, _1, false));
engine->BackendAvailable.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::post_engine, this));
ARDOUR::Port::set_connecting_blocked (ARDOUR_COMMAND_LINE::no_connect_ports);
post_engine ();
return 0;
}
void
ARDOUR_UI::post_engine ()
{
cerr << "Backend available!\n";
/* Things to be done once we create the AudioEngine
*/
@ -689,6 +684,7 @@ ARDOUR_UI::startup ()
{
Application* app = Application::instance ();
char *nsm_url;
app->ShouldQuit.connect (sigc::mem_fun (*this, &ARDOUR_UI::queue_finish));
app->ShouldLoad.connect (sigc::mem_fun (*this, &ARDOUR_UI::idle_load));

View File

@ -284,7 +284,7 @@ class AudioBackend {
virtual int set_time_master (bool /*yn*/) { return 0; }
virtual int usecs_per_cycle () const { return 1000000 * (buffer_size() / sample_rate()); }
virtual size_t raw_buffer_size (DataType t);
virtual size_t raw_buffer_size (DataType t) = 0;
/* Process time */

View File

@ -67,19 +67,17 @@ class AudioEngine : public SessionHandlePtr, public PortManager
{
public:
static AudioEngine* create (const std::string& client_name, const std::string& session_uuid);
static AudioEngine* create ();
virtual ~AudioEngine ();
int discover_backends();
std::vector<std::string> available_backends() const;
std::string current_backend_name () const;
int set_backend (const std::string&);
int set_backend (const std::string&, const std::string& arg1, const std::string& arg2);
ProcessThread* main_thread() const { return _main_thread; }
std::string client_name() const { return backend_client_name; }
/* START BACKEND PROXY API
*
* See audio_backend.h for full documentation and semantics. These wrappers
@ -144,7 +142,6 @@ public:
int reset_timebase ();
void update_latencies ();
/* this signal is sent for every process() cycle while freewheeling.
(the regular process() call to session->process() is not made)
@ -154,10 +151,7 @@ public:
PBD::Signal0<void> Xrun;
/* this signal is if the backend notifies us of a graph order event */
PBD::Signal0<void> GraphReordered;
#ifdef HAVE_JACK_SESSION
PBD::Signal1<void,jack_session_event_t *> JackSessionEvent;
#endif
@ -176,6 +170,13 @@ public:
PBD::Signal0<void> Running;
PBD::Signal0<void> Stopped;
/* these two are emitted as we create backends that
can actually be used to do stuff (e.g. register ports)
*/
PBD::Signal0<void> BackendAvailable;
PBD::Signal0<void> BackendRemoved;
static AudioEngine* instance() { return _instance; }
static void destroy();
@ -197,7 +198,7 @@ public:
static void thread_init_callback (void *);
private:
AudioEngine (const std::string& client_name, const std::string& session_uuid);
AudioEngine ();
static AudioEngine* _instance;
@ -227,9 +228,6 @@ public:
Glib::Threads::Thread* m_meter_thread;
ProcessThread* _main_thread;
std::string backend_client_name;
std::string backend_session_uuid;
void meter_thread ();
void start_metering_thread ();
void stop_metering_thread ();

View File

@ -144,7 +144,6 @@ class JACKAudioBackend : public AudioBackend {
static void* _start_process_thread (void*);
ChanCount n_physical (unsigned long) const;
void get_physical (DataType, unsigned long, std::vector<std::string> &);
/* pffooo */

View File

@ -44,6 +44,8 @@ class JACKPortEngine : public PortEngine
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;

View File

@ -93,6 +93,8 @@ class PortEngine {
virtual const std::string& my_name() const = 0;
virtual uint32_t port_name_size() const = 0;
virtual int set_port_name (PortHandle, const std::string&) = 0;
virtual std::string get_port_name (PortHandle) const = 0;
virtual PortHandle* get_port_by_name (const std::string&) const = 0;

View File

@ -47,7 +47,10 @@ class PortManager
void set_port_engine (PortEngine& pe);
PortEngine& port_engine() { return *_impl; }
uint32_t port_name_size() const;
std::string my_name() const;
/* Port registration */
boost::shared_ptr<Port> register_input_port (DataType, const std::string& portname);
@ -114,6 +117,9 @@ class PortManager
bool port_remove_in_progress() const { return _port_remove_in_progress; }
/** Emitted if the backend notifies us of a graph order event */
PBD::Signal0<void> GraphReordered;
/** Emitted if a Port is registered or unregistered */
PBD::Signal0<void> PortRegisteredOrUnregistered;

View File

@ -63,7 +63,7 @@ using namespace PBD;
gint AudioEngine::m_meter_exit;
AudioEngine* AudioEngine::_instance = 0;
AudioEngine::AudioEngine (const std::string& bcn, const std::string& bsu)
AudioEngine::AudioEngine ()
: session_remove_pending (false)
, session_removal_countdown (-1)
, monitor_check_interval (INT32_MAX)
@ -75,10 +75,9 @@ AudioEngine::AudioEngine (const std::string& bcn, const std::string& bsu)
, port_remove_in_progress (false)
, m_meter_thread (0)
, _main_thread (0)
, backend_client_name (bcn)
, backend_session_uuid (bsu)
{
g_atomic_int_set (&m_meter_exit, 0);
discover_backends ();
}
AudioEngine::~AudioEngine ()
@ -95,12 +94,15 @@ AudioEngine::~AudioEngine ()
}
AudioEngine*
AudioEngine::create (const std::string& bcn, const std::string& bsu)
AudioEngine::create ()
{
if (_instance) {
return _instance;
}
return new AudioEngine (bcn, bsu);
_instance = new AudioEngine ();
return _instance;
}
void
@ -120,8 +122,6 @@ _thread_init_callback (void * /*arg*/)
MIDI::JackMIDIPort::set_process_thread (pthread_self());
}
void
AudioEngine::split_cycle (pframes_t offset)
{
@ -488,8 +488,8 @@ AudioEngine::discover_backends ()
_backends.clear ();
Glib::PatternSpec so_extension_pattern("*.so");
Glib::PatternSpec dylib_extension_pattern("*.dylib");
Glib::PatternSpec so_extension_pattern("*backend.so");
Glib::PatternSpec dylib_extension_pattern("*backend.dylib");
find_matching_files_in_search_path (backend_search_path (),
so_extension_pattern, backend_modules);
@ -497,7 +497,7 @@ AudioEngine::discover_backends ()
find_matching_files_in_search_path (backend_search_path (),
dylib_extension_pattern, backend_modules);
DEBUG_TRACE (DEBUG::Panning, string_compose (_("looking for backends in %1"), backend_search_path().to_string()));
DEBUG_TRACE (DEBUG::Panning, string_compose (_("looking for backends in %1\n"), backend_search_path().to_string()));
for (vector<std::string>::iterator i = backend_modules.begin(); i != backend_modules.end(); ++i) {
@ -514,26 +514,26 @@ AudioEngine::discover_backends ()
AudioBackendInfo*
AudioEngine::backend_discover (const string& path)
{
Glib::Module* module = new Glib::Module(path);
Glib::Module module (path);
AudioBackendInfo* info;
void* sym = 0;
if (!module) {
error << string_compose(_("AudioEngine: cannot load module \"%1\" (%2)"), path,
Glib::Module::get_last_error()) << endmsg;
delete module;
Glib::Module::get_last_error()) << endmsg;
return 0;
}
if (!module->get_symbol("descriptor", sym)) {
if (!module.get_symbol ("descriptor", sym)) {
error << string_compose(_("AudioEngine: backend at \"%1\" has no descriptor."), path) << endmsg;
error << Glib::Module::get_last_error() << endmsg;
delete module;
return 0;
}
module.make_resident ();
info = (AudioBackendInfo*) sym;
return info;
}
@ -564,11 +564,13 @@ AudioEngine::drop_backend ()
if (_backend) {
_backend->stop ();
_backend.reset ();
BackendRemoved(); /* EMIT SIGNAL */
}
}
int
AudioEngine::set_backend (const std::string& name)
AudioEngine::set_backend (const std::string& name, const std::string& arg1, const std::string& arg2)
{
BackendMap::iterator b = _backends.find (name);
@ -580,14 +582,21 @@ AudioEngine::set_backend (const std::string& name)
try {
if (b->second->instantiate (arg1, arg2)) {
throw failed_constructor ();
}
_backend = b->second->backend_factory (*this);
_impl = b->second->portengine_factory (*this);
} catch (...) {
error << string_compose (_("Could not create backend for %1"), name) << endmsg;
return -1;
}
BackendAvailable (); /* EMIT SIGNAL */
return 0;
}
@ -993,3 +1002,4 @@ AudioEngine::halted_callback (const char* why)
MIDI::JackMIDIPort::EngineHalted (); /* EMIT SIGNAL */
Halted (why); /* EMIT SIGNAL */
}

View File

@ -331,6 +331,17 @@ ARDOUR::init (bool use_windows_vst, bool try_optimization, const char* localedir
EventTypeMap::instance().new_parameter(EnvelopeAutomation);
EventTypeMap::instance().new_parameter(MidiCCAutomation);
ARDOUR::AudioEngine::create ();
uint32_t backend_cnt;
if ((backend_cnt = AudioEngine::instance()->available_backends().size()) == 0) {
error << _("No audio/MIDI backends are available") << endmsg;
return -1;
}
cerr << "We have " << backend_cnt << endl;
return 0;
}

View File

@ -1337,7 +1337,7 @@ IO::bundle_changed (Bundle::Change /*c*/)
string
IO::build_legal_port_name (DataType type)
{
const int name_size = jack_port_name_size();
const int name_size = AudioEngine::instance()->port_name_size();
int limit;
string suffix;
@ -1371,7 +1371,7 @@ IO::build_legal_port_name (DataType type)
// allow up to 4 digits for the output port number, plus the slash, suffix and extra space
limit = name_size - _session.engine().client_name().length() - (suffix.length() + 5);
limit = name_size - AudioEngine::instance()->my_name().length() - (suffix.length() + 5);
char buf1[name_size+1];
char buf2[name_size+1];

View File

@ -58,6 +58,10 @@ JACKAudioBackend::JACKAudioBackend (AudioEngine& e, boost::shared_ptr<JackConnec
{
}
JACKAudioBackend::~JACKAudioBackend()
{
}
string
JACKAudioBackend::name() const
{
@ -825,3 +829,26 @@ 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;
}

View File

@ -222,6 +222,21 @@ JACKPortEngine::physically_connected (PortHandle p)
return false;
}
int
JACKPortEngine::get_connections (PortHandle port, vector<string>& s)
{
const char** ports = jack_port_get_connections ((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
{
@ -357,6 +372,23 @@ JACKPortEngine::can_monitor_input () const
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 ()
{
@ -480,3 +512,9 @@ 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 ();
}

View File

@ -67,6 +67,10 @@ PortManager::remove_all_ports ()
string
PortManager::make_port_name_relative (const string& portname) const
{
if (!_impl) {
return portname;
}
string::size_type len;
string::size_type n;
string self = _impl->my_name();
@ -105,6 +109,10 @@ PortManager::make_port_name_non_relative (const string& portname) const
bool
PortManager::port_is_mine (const string& portname) const
{
if (!_impl) {
return true;
}
string self = _impl->my_name();
if (portname.find_first_of (':') != string::npos) {
@ -119,6 +127,10 @@ PortManager::port_is_mine (const string& portname) const
bool
PortManager::port_is_physical (const std::string& portname) const
{
if (!_impl) {
return false;
}
PortEngine::PortHandle ph = _impl->get_port_by_name (portname);
if (!ph) {
return false;
@ -130,24 +142,38 @@ PortManager::port_is_physical (const std::string& portname) const
void
PortManager::get_physical_outputs (DataType type, std::vector<std::string>& s)
{
if (!_impl) {
return;
}
_impl->get_physical_outputs (type, s);
}
void
PortManager::get_physical_inputs (DataType type, std::vector<std::string>& s)
{
if (!_impl) {
return;
}
_impl->get_physical_inputs (type, s);
}
ChanCount
PortManager::n_physical_outputs () const
{
if (!_impl) {
return ChanCount::ZERO;
}
return _impl->n_physical_outputs ();
}
ChanCount
PortManager::n_physical_inputs () const
{
if (!_impl) {
return ChanCount::ZERO;
}
return _impl->n_physical_inputs ();
}
@ -158,6 +184,10 @@ PortManager::n_physical_inputs () const
boost::shared_ptr<Port>
PortManager::get_port_by_name (const string& portname)
{
if (!_impl) {
return boost::shared_ptr<Port>();
}
if (!port_is_mine (portname)) {
/* not an ardour port */
return boost::shared_ptr<Port> ();
@ -200,12 +230,20 @@ PortManager::port_renamed (const std::string& old_relative_name, const std::stri
int
PortManager::get_ports (const string& port_name_pattern, DataType type, PortFlags flags, vector<string>& s)
{
if (!_impl) {
return 0;
}
return _impl->get_ports (port_name_pattern, type, flags, s);
}
void
PortManager::port_registration_failure (const std::string& portname)
{
if (!_impl) {
return;
}
string full_portname = _impl->my_name();
full_portname += ':';
full_portname += portname;
@ -293,6 +331,10 @@ PortManager::unregister_port (boost::shared_ptr<Port> port)
bool
PortManager::connected (const string& port_name)
{
if (!_impl) {
return false;
}
PortEngine::PortHandle handle = _impl->get_port_by_name (port_name);
if (!handle) {
@ -437,12 +479,20 @@ PortManager::registration_callback ()
bool
PortManager::can_request_input_monitoring () const
{
if (!_impl) {
return false;
}
return _impl->can_monitor_input ();
}
void
PortManager::request_input_monitoring (const string& name, bool yn) const
{
if (!_impl) {
return;
}
PortEngine::PortHandle ph = _impl->get_port_by_name (name);
if (ph) {
@ -453,6 +503,10 @@ PortManager::request_input_monitoring (const string& name, bool yn) const
void
PortManager::ensure_input_monitoring (const string& name, bool yn) const
{
if (!_impl) {
return;
}
PortEngine::PortHandle ph = _impl->get_port_by_name (name);
if (ph) {
@ -460,3 +514,32 @@ PortManager::ensure_input_monitoring (const string& name, bool yn) const
}
}
uint32_t
PortManager::port_name_size() const
{
if (!_impl) {
return 0;
}
return _impl->port_name_size ();
}
string
PortManager::my_name() const
{
if (!_impl) {
return string();
}
return _impl->my_name();
}
int
PortManager::graph_order_callback ()
{
if (!_port_remove_in_progress) {
GraphReordered(); /* EMIT SIGNAL */
}
return 0;
}