From c46ec135e57e4e71d3e296503ee61b4ea527b0eb Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Fri, 8 May 2015 20:30:30 -0400 Subject: initial incorporation of Tracks' automatic reconnect features, based on current Tracks code --- libs/ardour/ardour/session.h | 3 + libs/ardour/audioengine.cc | 8 +- libs/ardour/filesystem_paths.cc | 7 ++ libs/ardour/session.cc | 204 +++++++++++++++++++++++++++++++++++++--- 4 files changed, 208 insertions(+), 14 deletions(-) diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index b6f7fc1bb8..f6837a6e47 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -720,6 +720,8 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop PBD::Signal0 SoloChanged; PBD::Signal0 IsolatedChanged; + PBD::Signal0 session_routes_reconnected; + /* monitor/master out */ void add_monitor_section (); @@ -1453,6 +1455,7 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop void add_routes (RouteList&, bool input_auto_connect, bool output_auto_connect, bool save); void add_routes_inner (RouteList&, bool input_auto_connect, bool output_auto_connect); bool _adding_routes_in_progress; + bool _reconnecting_routes_in_progress; bool _route_deletion_in_progress; uint32_t destructive_index; diff --git a/libs/ardour/audioengine.cc b/libs/ardour/audioengine.cc index 86fc5f0221..de41caae46 100644 --- a/libs/ardour/audioengine.cc +++ b/libs/ardour/audioengine.cc @@ -623,9 +623,11 @@ AudioEngine::remove_session () void AudioEngine::reconnect_session_routes (bool reconnect_inputs, bool reconnect_outputs) { - if (_session) { - _session->reconnect_existing_routes(true, true, reconnect_inputs, reconnect_outputs); - } +#ifdef USE_TRACKS_CODE_FEATURES + if (_session) { + _session->reconnect_existing_routes(true, true, reconnect_inputs, reconnect_outputs); + } +#endif } diff --git a/libs/ardour/filesystem_paths.cc b/libs/ardour/filesystem_paths.cc index 231bc84a3c..ecb75f7f69 100644 --- a/libs/ardour/filesystem_paths.cc +++ b/libs/ardour/filesystem_paths.cc @@ -49,6 +49,12 @@ user_config_directory_name (int version = -1) version = atoi (X_(PROGRAM_VERSION)); } +#ifdef USE_TRACKS_CODE_FEATURES + /* Tracks does not use versioned configuration folders, which may or + may not be problematic in the future. + */ + const string config_dir_name = X_(PROGRAM_NAME) +#else const string config_dir_name = string_compose ("%1%2", X_(PROGRAM_NAME), version); #if defined (__APPLE__) || defined (PLATFORM_WINDOWS) @@ -56,6 +62,7 @@ user_config_directory_name (int version = -1) #else return downcase (config_dir_name); #endif +#endif } std::string diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index 72e61b8084..b7585691c4 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -244,6 +244,7 @@ Session::Session (AudioEngine &eng, , _all_route_group (new RouteGroup (*this, "all")) , routes (new RouteList) , _adding_routes_in_progress (false) + , _reconnecting_routes_in_progress (false) , _route_deletion_in_progress (false) , destructive_index (0) , _track_number_decimals(1) @@ -883,7 +884,7 @@ Session::auto_connect_master_bus () void Session::remove_monitor_section () { - if (!_monitor_out) { + if (!_monitor_out || Profile->get_trx()) { return; } @@ -937,7 +938,7 @@ Session::add_monitor_section () { RouteList rl; - if (_monitor_out || !_master_out) { + if (_monitor_out || !_master_out || Profile->get_trx()) { return; } @@ -1085,7 +1086,7 @@ Session::reset_monitor_section () { /* Process lock should be held by the caller.*/ - if (!_monitor_out) { + if (!_monitor_out || Profile->get_trx()) { return; } @@ -2346,6 +2347,17 @@ Session::auto_connect_route (boost::shared_ptr route, ChanCount& existing for (uint32_t i = output_start.get(*t); i < route->n_outputs().get(*t); ++i) { string port; + /* Waves Tracks: + * do not create new connections if we reached the limit of physical outputs + * in Multi Out mode + */ + + if (!(Config->get_output_auto_connect() & AutoConnectMaster) && + ARDOUR::Profile->get_trx () && + existing_outputs.get(*t) == nphysical_out ) { + break; + } + if ((*t) == DataType::MIDI && (Config->get_output_auto_connect() & AutoConnectPhysical)) { port = physoutputs[(out_offset.get(*t) + i) % nphysical_out]; } else if ((*t) == DataType::AUDIO && (Config->get_output_auto_connect() & AutoConnectMaster)) { @@ -2371,14 +2383,176 @@ Session::auto_connect_route (boost::shared_ptr route, ChanCount& existing } } +#ifdef USE_TRACKS_CODE_FEATURES + +static bool +compare_routes_by_remote_id (const boost::shared_ptr& route1, const boost::shared_ptr& route2) +{ + return route1->remote_control_id() < route2->remote_control_id(); +} + void Session::reconnect_existing_routes (bool withLock, bool reconnect_master, bool reconnect_inputs, bool reconnect_outputs) { - /* TRX does stuff here, ardour does not (but probably should). This is called after an engine reset (in particular). - */ -} + // it is not allowed to perform connection + if (!IO::connecting_legal) { + return; + } + + // if we are deleting routes we will call this once at the end + if (_route_deletion_in_progress) { + return; + } + + Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock (), Glib::Threads::NOT_LOCK); + + if (withLock) { + lm.acquire (); + } + + // We need to disconnect the route's inputs and outputs first + // basing on autoconnect configuration + bool reconnectIputs = !(Config->get_input_auto_connect() & ManualConnect) && reconnect_inputs; + bool reconnectOutputs = !(Config->get_output_auto_connect() & ManualConnect) && reconnect_outputs; + + ChanCount existing_inputs; + ChanCount existing_outputs; + count_existing_track_channels (existing_inputs, existing_outputs); + + //ChanCount inputs = ChanCount::ZERO; + //ChanCount outputs = ChanCount::ZERO; + + RouteList existing_routes = *routes.reader (); + existing_routes.sort (compare_routes_by_remote_id); + + { + PBD::Unwinder protect_ignore_changes (_reconnecting_routes_in_progress, true); -#ifdef USE_TRACKS_CODE_FEATURES + vector physinputs; + vector physoutputs; + + EngineStateController::instance()->get_physical_audio_outputs(physoutputs); + EngineStateController::instance()->get_physical_audio_inputs(physinputs); + + uint32_t input_n = 0; + uint32_t output_n = 0; + RouteList::iterator rIter = existing_routes.begin(); + const AutoConnectOption current_input_auto_connection (Config->get_input_auto_connect()); + const AutoConnectOption current_output_auto_connection (Config->get_output_auto_connect()); + for (; rIter != existing_routes.end(); ++rIter) { + if (*rIter == _master_out || *rIter == _monitor_out ) { + continue; + } + + if (current_output_auto_connection == AutoConnectPhysical) { + (*rIter)->amp()->deactivate(); + } else if (current_output_auto_connection == AutoConnectMaster) { + (*rIter)->amp()->activate(); + } + + if (reconnectIputs) { + (*rIter)->input()->disconnect (this); //GZ: check this; could be heavy + + for (uint32_t route_input_n = 0; route_input_n < (*rIter)->n_inputs().get(DataType::AUDIO); ++route_input_n) { + + if (current_input_auto_connection & AutoConnectPhysical) { + + if ( input_n == physinputs.size() ) { + break; + } + + string port = physinputs[input_n]; + + if (port.empty() ) { + error << "Physical Input number "<< input_n << " is unavailable and cannot be connected" << endmsg; + } + + //GZ: check this; could be heavy + (*rIter)->input()->connect ((*rIter)->input()->ports().port(DataType::AUDIO, route_input_n), port, this); + ++input_n; + } + } + } + + if (reconnectOutputs) { + + //normalize route ouptuts: reduce the amount outputs to be equal to the amount of inputs + if (current_output_auto_connection & AutoConnectPhysical) { + + //GZ: check this; could be heavy + (*rIter)->output()->disconnect (this); + size_t route_inputs_count = (*rIter)->n_inputs().get(DataType::AUDIO); + + //GZ: check this; could be heavy + (*rIter)->output()->ensure_io(ChanCount(DataType::AUDIO, route_inputs_count), false, this ); + + } else if (current_output_auto_connection & AutoConnectMaster){ + + if (!reconnect_master) { + continue; + } + + //GZ: check this; could be heavy + (*rIter)->output()->disconnect (this); + + if (_master_out) { + uint32_t master_inputs_count = _master_out->n_inputs().get(DataType::AUDIO); + (*rIter)->output()->ensure_io(ChanCount(DataType::AUDIO, master_inputs_count), false, this ); + } else { + error << error << "Master bus is not available" << endmsg; + break; + } + } + + for (uint32_t route_output_n = 0; route_output_n < (*rIter)->n_outputs().get(DataType::AUDIO); ++route_output_n) { + if (current_output_auto_connection & AutoConnectPhysical) { + + if ( output_n == physoutputs.size() ) { + break; + } + + string port = physoutputs[output_n]; + + if (port.empty() ) { + error << "Physical Output number "<< output_n << " is unavailable and cannot be connected" << endmsg; + } + + //GZ: check this; could be heavy + (*rIter)->output()->connect ((*rIter)->output()->ports().port(DataType::AUDIO, route_output_n), port, this); + ++output_n; + + } else if (current_output_auto_connection & AutoConnectMaster) { + + if ( route_output_n == _master_out->n_inputs().get(DataType::AUDIO) ) { + break; + } + + // connect to master bus + string port = _master_out->input()->ports().port(DataType::AUDIO, route_output_n)->name(); + + if (port.empty() ) { + error << "MasterBus Input number "<< route_output_n << " is unavailable and cannot be connected" << endmsg; + } + + + //GZ: check this; could be heavy + (*rIter)->output()->connect ((*rIter)->output()->ports().port(DataType::AUDIO, route_output_n), port, this); + + } + } + } + + //auto_connect_route (*rIter, inputs, outputs, false, reconnectIputs); + } + + _master_out->output()->disconnect (this); + auto_connect_master_bus (); + } + + graph_reordered (); + + session_routes_reconnected (); /* EMIT SIGNAL */ +} void Session::reconnect_midi_scene_ports(bool inputs) @@ -3037,11 +3211,11 @@ Session::remove_routes (boost::shared_ptr routes_to_remove) * Wave Tracks: reconnect routes */ - if (ARDOUR::Profile->get_trx () ) { +#ifdef USE_TRACKS_CODE_FEATURES reconnect_existing_routes(true, false); - } else { +#else resort_routes (); - } +#endif if (_process_graph) { _process_graph->clear_other_chain (); @@ -4352,7 +4526,7 @@ Session::graph_reordered () from a set_state() call or creating new tracks. Ditto for deletion. */ - if ((_state_of_the_state & (InitialConnecting|Deletion)) || _adding_routes_in_progress) { + if ((_state_of_the_state & (InitialConnecting|Deletion)) || _adding_routes_in_progress || _reconnecting_routes_in_progress) { return; } @@ -5681,6 +5855,14 @@ Session::notify_remote_id_change () default: break; } + +#ifdef USE_TRACKS_CODE_FEATURES + /* Waves Tracks: for Waves Tracks session it's required to reconnect their IOs + * if track order has been changed by user + */ + reconnect_existing_routes(true, true); +#endif + } void -- cgit v1.2.3