initial incorporation of Tracks' automatic reconnect features, based on current Tracks code

This commit is contained in:
Paul Davis 2015-05-08 20:30:30 -04:00
parent de4efe73a6
commit c46ec135e5
4 changed files with 208 additions and 14 deletions

View File

@ -720,6 +720,8 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
PBD::Signal0<void> SoloChanged;
PBD::Signal0<void> IsolatedChanged;
PBD::Signal0<void> 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;

View File

@ -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
}

View File

@ -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

View File

@ -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> 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> route, ChanCount& existing
}
}
#ifdef USE_TRACKS_CODE_FEATURES
static bool
compare_routes_by_remote_id (const boost::shared_ptr<Route>& route1, const boost::shared_ptr<Route>& 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<bool> protect_ignore_changes (_reconnecting_routes_in_progress, true);
#ifdef USE_TRACKS_CODE_FEATURES
vector<string> physinputs;
vector<string> 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<RouteList> 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