#include "ardour/session_directory.h"
#include "ardour/session_playlists.h"
#include "ardour/smf_source.h"
+#include "ardour/solo_isolate_control.h"
#include "ardour/source_factory.h"
#include "ardour/speakers.h"
#include "ardour/tempo.h"
#include "ardour/track.h"
#include "ardour/user_bundle.h"
#include "ardour/utils.h"
+#include "ardour/vca_manager.h"
#include "midi++/port.h"
#include "midi++/mmc.h"
, _scene_changer (0)
, _midi_ports (0)
, _mmc (0)
+ , _vca_manager (new VCAManager (*this))
{
uint32_t sr = 0;
DEBUG_TRACE (DEBUG::Destruction, "delete regions\n");
RegionFactory::delete_all_regions ();
+ /* Do this early so that VCAs no longer hold references to routes */
+
+ DEBUG_TRACE (DEBUG::Destruction, "delete vcas\n");
+ delete _vca_manager;
+
DEBUG_TRACE (DEBUG::Destruction, "delete routes\n");
/* reset these three references to special routes before we do the usual route delete thing */
boost::shared_ptr<RouteList> rl = routes.reader ();
for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
boost::shared_ptr<AudioTrack> tr = boost::dynamic_pointer_cast<AudioTrack> (*i);
- if (tr && tr->record_enabled ()) {
+ if (tr && tr->rec_enable_control()->get_value()) {
//cerr << "switching to input = " << !auto_input << __FILE__ << __LINE__ << endl << endl;
tr->request_input_monitoring (yn);
}
Session::set_all_tracks_record_enabled (bool enable )
{
boost::shared_ptr<RouteList> rl = routes.reader();
- for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
- boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
- if (tr) {
- tr->set_record_enabled (enable, Controllable::NoGroup);
- }
- }
+ set_controls (route_list_to_control_list (rl, &Track::rec_enable_control), enable, Controllable::NoGroup);
}
-
void
Session::disable_record (bool rt_context, bool force)
{
// 0 for Stereo Out mode
// 0 Multi Out mode
if (Config->get_output_auto_connect() & AutoConnectMaster) {
- track->set_gain (dB_to_coefficient (0), Controllable::NoGroup);
+ track->gain_control()->set_value (dB_to_coefficient (0), Controllable::NoGroup);
}
}
case NewPlaylist:
rename_playlist = true;
break;
+ default:
case CopyPlaylist:
case SharePlaylist:
rename_playlist = false;
boost::weak_ptr<Route> wpr (*x);
boost::shared_ptr<Route> r (*x);
- r->listen_changed.connect_same_thread (*this, boost::bind (&Session::route_listen_changed, this, _1, wpr));
- r->solo_changed.connect_same_thread (*this, boost::bind (&Session::route_solo_changed, this, _1, _2, wpr));
- r->solo_isolated_changed.connect_same_thread (*this, boost::bind (&Session::route_solo_isolated_changed, this, wpr));
- r->mute_changed.connect_same_thread (*this, boost::bind (&Session::route_mute_changed, this));
+ r->solo_control()->Changed.connect_same_thread (*this, boost::bind (&Session::route_solo_changed, this, _1, _2, wpr));
+ r->solo_isolate_control()->Changed.connect_same_thread (*this, boost::bind (&Session::route_solo_isolated_changed, this, wpr));
+ r->mute_control()->Changed.connect_same_thread (*this, boost::bind (&Session::route_mute_changed, this));
+
r->output()->changed.connect_same_thread (*this, boost::bind (&Session::set_worst_io_latencies_x, this, _1, _2));
r->processors_changed.connect_same_thread (*this, boost::bind (&Session::route_processors_changed, this, _1));
if (tr) {
tr->PlaylistChanged.connect_same_thread (*this, boost::bind (&Session::track_playlist_changed, this, boost::weak_ptr<Track> (tr)));
track_playlist_changed (boost::weak_ptr<Track> (tr));
- tr->RecordEnableChanged.connect_same_thread (*this, boost::bind (&Session::update_route_record_state, this));
+ tr->rec_enable_control()->Changed.connect_same_thread (*this, boost::bind (&Session::update_route_record_state, this));
boost::shared_ptr<MidiTrack> mt = boost::dynamic_pointer_cast<MidiTrack> (tr);
if (mt) {
continue;
}
- (*iter)->set_solo (false, Controllable::NoGroup);
+ (*iter)->solo_control()->set_value (0.0, Controllable::NoGroup);
rs->remove (*iter);
void
Session::route_listen_changed (Controllable::GroupControlDisposition group_override, boost::weak_ptr<Route> wpr)
{
- boost::shared_ptr<Route> route = wpr.lock();
+ boost::shared_ptr<Route> route (wpr.lock());
+
if (!route) {
- error << string_compose (_("programming error: %1"), X_("invalid route weak ptr passed to route_listen_changed")) << endmsg;
return;
}
continue;
}
- if ((*i)->solo_isolated() || (*i)->is_master() || (*i)->is_monitor() || (*i)->is_auditioner()) {
+ if ((*i)->solo_isolate_control()->solo_isolated() || !(*i)->can_solo()) {
/* route does not get solo propagated to it */
continue;
}
*/
continue;
}
- (*i)->set_listen (false, Controllable::NoGroup);
+ (*i)->solo_control()->set_value (0.0, Controllable::NoGroup);
}
}
update_route_solo_state ();
}
+
void
Session::route_solo_isolated_changed (boost::weak_ptr<Route> wpr)
{
- boost::shared_ptr<Route> route = wpr.lock ();
+ boost::shared_ptr<Route> route (wpr.lock());
if (!route) {
- /* should not happen */
- error << string_compose (_("programming error: %1"), X_("invalid route weak ptr passed to route_solo_isolated_changed")) << endmsg;
return;
}
bool send_changed = false;
- if (route->solo_isolated()) {
+ if (route->solo_isolate_control()->solo_isolated()) {
if (_solo_isolated_cnt == 0) {
send_changed = true;
}
{
DEBUG_TRACE (DEBUG::Solo, string_compose ("route solo change, self = %1\n", self_solo_change));
+ boost::shared_ptr<Route> route (wpr.lock());
+
+ if (!route) {
+ return;
+ }
+
+ if (Config->get_solo_control_is_listen_control()) {
+ route_listen_changed (group_override, wpr);
+ return;
+ }
+
if (!self_solo_change) {
// session doesn't care about changes to soloed-by-others
return;
}
- boost::shared_ptr<Route> route = wpr.lock ();
- assert (route);
-
boost::shared_ptr<RouteList> r = routes.reader ();
int32_t delta;
continue;
}
- if ((*i)->solo_isolated() || (*i)->is_master() || (*i)->is_monitor() || (*i)->is_auditioner()) {
+ if ((*i)->solo_isolate_control()->solo_isolated() || !(*i)->can_solo()) {
/* route does not get solo propagated to it */
continue;
}
continue;
}
- (*i)->set_solo (false, group_override);
+ (*i)->solo_control()->set_value (0.0, group_override);
}
}
continue;
}
- if ((*i)->solo_isolated() || (*i)->is_master() || (*i)->is_monitor() || (*i)->is_auditioner()) {
+ if ((*i)->solo_isolate_control()->solo_isolated() || !(*i)->can_solo()) {
/* route does not get solo propagated to it */
continue;
}
DEBUG_TRACE (DEBUG::Solo, string_compose ("\tthere is a feed from %1\n", (*i)->name()));
if (!via_sends_only) {
if (!route->soloed_by_others_upstream()) {
- (*i)->mod_solo_by_others_downstream (delta);
+ (*i)->solo_control()->mod_solo_by_others_downstream (delta);
} else {
DEBUG_TRACE (DEBUG::Solo, "\talready soloed by others upstream\n");
}
if (!via_sends_only) {
//NB. Triggers Invert Push, which handles soloed by downstream
DEBUG_TRACE (DEBUG::Solo, string_compose ("\tmod %1 by %2\n", (*i)->name(), delta));
- (*i)->mod_solo_by_others_upstream (delta);
+ (*i)->solo_control()->mod_solo_by_others_upstream (delta);
} else {
DEBUG_TRACE (DEBUG::Solo, string_compose ("\tfeed to %1 ignored, sends-only\n", (*i)->name()));
}
for (RouteList::iterator i = uninvolved.begin(); i != uninvolved.end(); ++i) {
DEBUG_TRACE (DEBUG::Solo, string_compose ("mute change for %1, which neither feeds or is fed by %2\n", (*i)->name(), route->name()));
(*i)->act_on_mute ();
- (*i)->mute_changed ();
+ (*i)->mute_control()->Changed (false, Controllable::NoGroup);
}
SoloChanged (); /* EMIT SIGNAL */
}
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
- if (!(*i)->is_master() && !(*i)->is_monitor() && !(*i)->is_auditioner() && (*i)->self_soloed()) {
- something_soloed = true;
- }
-
- if (!(*i)->is_auditioner() && (*i)->listening_via_monitor()) {
+ if ((*i)->can_solo()) {
if (Config->get_solo_control_is_listen_control()) {
- listeners++;
- something_listening = true;
+ if ((*i)->self_soloed()) {
+ listeners++;
+ something_listening = true;
+ }
} else {
- (*i)->set_listen (false, Controllable::NoGroup);
+ (*i)->set_listen (false);
+ if ((*i)->can_solo() && (*i)->self_soloed()) {
+ something_soloed = true;
+ }
}
}
- if ((*i)->solo_isolated()) {
+ if ((*i)->solo_isolate_control()->solo_isolated()) {
isolated++;
}
}
}
+boost::shared_ptr<Stripable>
+Session::stripable_by_remote_id (uint32_t id)
+{
+ boost::shared_ptr<RouteList> r = routes.reader ();
+
+ for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
+ if ((*i)->remote_control_id() == id) {
+ return *i;
+ }
+ }
+
+ return boost::shared_ptr<Route> ((Route*) 0);
+}
+
+
boost::shared_ptr<Route>
Session::route_by_selected_count (uint32_t id)
{
while (i != rl->end ()) {
boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
- if (tr && tr->record_enabled ()) {
+ if (tr && tr->rec_enable_control()->get_value()) {
break;
}
for (i = rl->begin(); i != rl->end (); ++i) {
boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
- if (tr && !tr->record_enabled ()) {
+ if (tr && !tr->rec_enable_control()->get_value()) {
break;
}
}
void
Session::solo_control_mode_changed ()
{
- /* cancel all solo or all listen when solo control mode changes */
-
- if (soloing()) {
- set_solo (get_routes(), false);
- } else if (listening()) {
- set_listen (get_routes(), false);
+ if (soloing() || listening()) {
+ /* We can't use ::clear_all_solo_state() here because during
+ session loading at program startup, that will queue a call
+ to rt_clear_all_solo_state() that will not execute until
+ AFTER solo states have been established (thus throwing away
+ the session's saved solo state). So just explicitly turn
+ them all off.
+ */
+ set_controls (route_list_to_control_list (get_routes(), &Route::solo_control), 0.0, Controllable::NoGroup);
}
}