#include "ardour/source_factory.h"
#include "ardour/speakers.h"
#include "ardour/tempo.h"
+#include "ardour/ticker.h"
#include "ardour/track.h"
#include "ardour/user_bundle.h"
#include "ardour/utils.h"
, _speakers (new Speakers)
, _order_hint (-1)
, ignore_route_processor_changes (false)
+ , midi_clock (0)
, _scene_changer (0)
, _midi_ports (0)
, _mmc (0)
#ifdef USE_TRACKS_CODE_FEATURES
sr = EngineStateController::instance()->get_current_sample_rate();
#endif
- if (ensure_engine (sr)) {
+ if (ensure_engine (sr, true)) {
destroy ();
throw SessionException (_("Cannot connect to audio/midi engine"));
}
}
}
- if (ensure_engine (sr)) {
+ if (ensure_engine (sr, false)) {
destroy ();
throw SessionException (_("Cannot connect to audio/midi engine"));
}
}
int
-Session::ensure_engine (uint32_t desired_sample_rate)
+Session::ensure_engine (uint32_t desired_sample_rate, bool isnew)
{
if (_engine.current_backend() == 0) {
/* backend is unknown ... */
if (r.get_value_or (-1) != 0) {
return -1;
}
+ } else if (!isnew && _engine.running() && _engine.sample_rate () == desired_sample_rate) {
+ /* keep engine */
} else if (_engine.setup_required()) {
/* backend is known, but setup is needed */
boost::optional<int> r = AudioEngineSetupRequired (desired_sample_rate);
}
}
- /* at this point the engine should be running
- */
+ /* at this point the engine should be running */
if (!_engine.running()) {
return -1;
/* disconnect from any and all signals that we are connected to */
+ Port::PortSignalDrop (); /* EMIT SIGNAL */
drop_connections ();
/* shutdown control surface protocols while we still have ports
* callbacks from the engine any more.
*/
- Port::PortSignalDrop (); /* EMIT SIGNAL */
Port::PortDrop (); /* EMIT SIGNAL */
ltc_tx_cleanup();
delete _midi_ports; _midi_ports = 0;
delete _locations; _locations = 0;
+ delete midi_clock;
delete _tempo_map;
DEBUG_TRACE (DEBUG::Destruction, "Session::destroy() done\n");
}
remove_route (_monitor_out);
+ if (_state_of_the_state & Deletion) {
+ return;
+ }
+
auto_connect_master_bus ();
if (auditioner) {
auditioner->connect ();
}
+
Config->ParameterChanged ("use-monitor-bus");
}
}
#ifndef NDEBUG
- boost::shared_ptr<RouteList> rl = routes.reader ();
- for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
- DEBUG_TRACE (DEBUG::Graph, string_compose ("%1 fed by ...\n", (*i)->name()));
+ if (DEBUG_ENABLED(DEBUG::Graph)) {
+ boost::shared_ptr<RouteList> rl = routes.reader ();
+ for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
+ DEBUG_TRACE (DEBUG::Graph, string_compose ("%1 fed by ...\n", (*i)->name()));
- const Route::FedBy& fb ((*i)->fed_by());
+ const Route::FedBy& fb ((*i)->fed_by());
- for (Route::FedBy::const_iterator f = fb.begin(); f != fb.end(); ++f) {
- boost::shared_ptr<Route> sf = f->r.lock();
- if (sf) {
- DEBUG_TRACE (DEBUG::Graph, string_compose ("\t%1 (sends only ? %2)\n", sf->name(), f->sends_only));
+ for (Route::FedBy::const_iterator f = fb.begin(); f != fb.end(); ++f) {
+ boost::shared_ptr<Route> sf = f->r.lock();
+ if (sf) {
+ DEBUG_TRACE (DEBUG::Graph, string_compose ("\t%1 (sends only ? %2)\n", sf->name(), f->sends_only));
+ }
}
}
}
resort_routes ();
#endif
- if (_process_graph) {
+ if (_process_graph && !(_state_of_the_state & Deletion)) {
_process_graph->clear_other_chain ();
}
(*iter)->drop_references ();
}
+ if (_state_of_the_state & Deletion) {
+ return;
+ }
+
Route::RemoteControlIDChange(); /* EMIT SIGNAL */
/* save the new state of the world */
return;
}
- //why would we need the process lock ??
- //Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
-
/* If both inputs and outputs are auto-connected to physical ports,
* use the max of input and output offsets to ensure auto-connected
* port numbers always match up (e.g. the first audio input and the
Session::auto_connect_thread_run ()
{
pthread_set_name (X_("autoconnect"));
- SessionEvent::create_per_thread_pool (X_("autoconnect"), 256);
- PBD::notify_event_loops_about_thread_creation (pthread_self(), X_("autoconnect"), 256);
+ SessionEvent::create_per_thread_pool (X_("autoconnect"), 1024);
+ PBD::notify_event_loops_about_thread_creation (pthread_self(), X_("autoconnect"), 1024);
pthread_mutex_lock (&_auto_connect_mutex);
while (_ac_thread_active) {
- while (!_auto_connect_queue.empty ()) {
+ if (!_auto_connect_queue.empty ()) {
+ // Why would we need the process lock ??
+ // A: if ports are added while we're connecting, the backend's iterator may be invalidated:
+ // graph_order_callback() -> resort_routes() -> direct_feeds_according_to_reality () -> backend::connected_to()
+ // All ardour-internal backends use a std::vector xxxAudioBackend::find_port()
+ // We have control over those, but what does jack do?
+ Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
+
Glib::Threads::Mutex::Lock lx (_auto_connect_queue_lock);
- if (_auto_connect_queue.empty ()) { break; } // re-check with lock
- const AutoConnectRequest ar (_auto_connect_queue.front());
- _auto_connect_queue.pop ();
- lx.release ();
- auto_connect (ar);
+ while (!_auto_connect_queue.empty ()) {
+ const AutoConnectRequest ar (_auto_connect_queue.front());
+ _auto_connect_queue.pop ();
+ lx.release ();
+ auto_connect (ar);
+ lx.acquire ();
+ }
}
pthread_cond_wait (&_auto_connect_cond, &_auto_connect_mutex);