X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Faudioengine.cc;h=82564ebaf2e5c4def9a2eb83aecbe7559acd090d;hb=2644aaddb19eda57551129c4e6ca6ca02fdb066a;hp=2a1ca2c8521c364b44cc2a9a5ef7e4e8957cd5c1;hpb=7c3535ebf808056f65df50a38c7b2202ca1e27aa;p=ardour.git diff --git a/libs/ardour/audioengine.cc b/libs/ardour/audioengine.cc index 2a1ca2c852..82564ebaf2 100644 --- a/libs/ardour/audioengine.cc +++ b/libs/ardour/audioengine.cc @@ -79,6 +79,9 @@ AudioEngine::AudioEngine () , _latency_input_port (0) , _latency_output_port (0) , _latency_flush_frames (0) + , _latency_signal_latency (0) + , _stopped_for_latency (false) + , _in_destructor (false) { g_atomic_int_set (&m_meter_exit, 0); discover_backends (); @@ -86,15 +89,9 @@ AudioEngine::AudioEngine () AudioEngine::~AudioEngine () { + _in_destructor = true; + stop_metering_thread (); drop_backend (); - - config_connection.disconnect (); - - { - Glib::Threads::Mutex::Lock tm (_process_lock); - session_removed.signal (); - stop_metering_thread (); - } } AudioEngine* @@ -201,6 +198,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); @@ -416,8 +420,6 @@ AudioEngine::remove_session () if (_running) { - stop_metering_thread (); - if (_session) { session_remove_pending = true; session_removal_countdown = 0; @@ -472,6 +474,7 @@ AudioEngine::discover_backends () Glib::PatternSpec so_extension_pattern("*backend.so"); Glib::PatternSpec dylib_extension_pattern("*backend.dylib"); + Glib::PatternSpec dll_extension_pattern("*backend.dll"); find_matching_files_in_search_path (backend_search_path (), so_extension_pattern, backend_modules); @@ -479,6 +482,9 @@ AudioEngine::discover_backends () find_matching_files_in_search_path (backend_search_path (), dylib_extension_pattern, backend_modules); + find_matching_files_in_search_path (backend_search_path (), + dll_extension_pattern, backend_modules); + DEBUG_TRACE (DEBUG::Panning, string_compose (_("looking for backends in %1\n"), backend_search_path().to_string())); for (vector::iterator i = backend_modules.begin(); i != backend_modules.end(); ++i) { @@ -498,7 +504,8 @@ AudioEngine::backend_discover (const string& path) { Glib::Module module (path); AudioBackendInfo* info; - void* sym = 0; + AudioBackendInfo* (*dfunc)(void); + void* func = 0; if (!module) { error << string_compose(_("AudioEngine: cannot load module \"%1\" (%2)"), path, @@ -506,15 +513,16 @@ AudioEngine::backend_discover (const string& path) return 0; } - if (!module.get_symbol ("descriptor", sym)) { - error << string_compose(_("AudioEngine: backend at \"%1\" has no descriptor."), path) << endmsg; + if (!module.get_symbol ("descriptor", func)) { + error << string_compose(_("AudioEngine: backend at \"%1\" has no descriptor function."), path) << endmsg; error << Glib::Module::get_last_error() << endmsg; return 0; } module.make_resident (); - info = (AudioBackendInfo*) sym; + dfunc = (AudioBackendInfo* (*)(void))func; + info = dfunc(); return info; } @@ -549,6 +557,16 @@ AudioEngine::drop_backend () } } +boost::shared_ptr +AudioEngine::set_default_backend () +{ + if (_backends.empty()) { + return boost::shared_ptr(); + } + + return set_backend (_backends.begin()->first, "", ""); +} + boost::shared_ptr AudioEngine::set_backend (const std::string& name, const std::string& arg1, const std::string& arg2) { @@ -565,8 +583,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; @@ -579,7 +596,7 @@ AudioEngine::set_backend (const std::string& name, const std::string& arg1, cons /* BACKEND PROXY WRAPPERS */ int -AudioEngine::start () +AudioEngine::start (bool for_latency) { if (!_backend) { return -1; @@ -592,7 +609,7 @@ AudioEngine::start () _processed_frames = 0; last_monitor_check = 0; - if (_backend->start()) { + if (_backend->start (for_latency)) { return -1; } @@ -608,13 +625,15 @@ AudioEngine::start () start_metering_thread (); - Running(); /* EMIT SIGNAL */ + if (!for_latency) { + Running(); /* EMIT SIGNAL */ + } return 0; } int -AudioEngine::stop () +AudioEngine::stop (bool for_latency) { if (!_backend) { return 0; @@ -631,28 +650,15 @@ AudioEngine::stop () _measuring_latency = false; _latency_output_port = 0; _latency_input_port = 0; + _started_for_latency = false; stop_metering_thread (); Port::PortDrop (); - Stopped (); /* EMIT SIGNAL */ - - return 0; -} -int -AudioEngine::pause () -{ - if (!_backend) { - return 0; + if (!for_latency) { + Stopped (); /* EMIT SIGNAL */ } - if (_backend->pause ()) { - return -1; - } - - _running = false; - - Stopped(); /* EMIT SIGNAL */ return 0; } @@ -669,12 +675,12 @@ AudioEngine::freewheel (bool start_stop) } float -AudioEngine::get_cpu_load() const +AudioEngine::get_dsp_load() const { if (!_backend) { return 0.0; } - return _backend->cpu_load (); + return _backend->dsp_load (); } bool @@ -694,7 +700,7 @@ AudioEngine::connected() const return false; } - return _backend->connected(); + return _backend->available(); } void @@ -815,14 +821,40 @@ AudioEngine::get_sync_offset (pframes_t& offset) const } int -AudioEngine::create_process_thread (boost::function func, pthread_t* thr, size_t stacksize) +AudioEngine::create_process_thread (boost::function func) +{ + if (!_backend) { + return -1; + } + return _backend->create_process_thread (func); +} + +int +AudioEngine::join_process_threads () { if (!_backend) { return -1; } - return _backend->create_process_thread (func, thr, stacksize); + return _backend->join_process_threads (); } +bool +AudioEngine::in_process_thread () +{ + if (!_backend) { + return false; + } + return _backend->in_process_thread (); +} + +uint32_t +AudioEngine::process_thread_count () +{ + if (!_backend) { + return 0; + } + return _backend->process_thread_count (); +} int AudioEngine::set_device_name (const std::string& name) @@ -963,16 +995,31 @@ AudioEngine::update_latencies () void AudioEngine::halted_callback (const char* why) { + if (_in_destructor) { + /* everything is under control */ + return; + } + stop_metering_thread (); _running = false; Port::PortDrop (); /* EMIT SIGNAL */ - Halted (why); /* EMIT SIGNAL */ + + if (!_started_for_latency) { + Halted (why); /* EMIT SIGNAL */ + } } 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; } @@ -986,48 +1033,108 @@ AudioEngine::mtdm() return _mtdm; } -void +int +AudioEngine::prepare_for_latency_measurement () +{ + if (running()) { + _stopped_for_latency = true; + stop (true); + } + + if (start (true)) { + _started_for_latency = true; + return -1; + } + + return 0; +} + +int AudioEngine::start_latency_detection () { + if (!running()) { + if (prepare_for_latency_measurement ()) { + return -1; + } + } + PortEngine& pe (port_engine()); delete _mtdm; _mtdm = 0; + /* find the ports we will connect to */ + + PortEngine::PortHandle out = pe.get_port_by_name (_latency_output_name); + PortEngine::PortHandle in = pe.get_port_by_name (_latency_input_name); + + if (!out || !in) { + stop (true); + return -1; + } + /* create the ports we will use to read/write data */ if ((_latency_output_port = pe.register_port ("latency_out", DataType::AUDIO, IsOutput)) == 0) { - return; + stop (true); + return -1; } if (pe.connect (_latency_output_port, _latency_output_name)) { - return; + pe.unregister_port (_latency_output_port); + stop (true); + return -1; } const string portname ("latency_in"); if ((_latency_input_port = pe.register_port (portname, DataType::AUDIO, IsInput)) == 0) { pe.unregister_port (_latency_output_port); - return; + stop (true); + return -1; } if (pe.connect (_latency_input_name, make_port_name_non_relative (portname))) { pe.unregister_port (_latency_output_port); - return; + stop (true); + return -1; } - + + LatencyRange lr; + _latency_signal_latency = 0; + lr = pe.get_latency_range (in, false); + _latency_signal_latency = lr.max; + lr = pe.get_latency_range (out, true); + _latency_signal_latency += lr.max; + /* all created and connected, lets go */ _mtdm = new MTDM (sample_rate()); _measuring_latency = true; _latency_flush_frames = samples_per_cycle(); - + return 0; } void AudioEngine::stop_latency_detection () { - port_engine().unregister_port (_latency_output_port); - port_engine().unregister_port (_latency_input_port); _measuring_latency = false; + + if (_latency_output_port) { + port_engine().unregister_port (_latency_output_port); + _latency_output_port = 0; + } + if (_latency_input_port) { + port_engine().unregister_port (_latency_input_port); + _latency_input_port = 0; + } + + stop (true); + + if (_stopped_for_latency) { + start (); + } + + _stopped_for_latency = false; + _started_for_latency = false; } void