#include "pbd/xml++.h"
#include "pbd/enumwriter.h"
#include "pbd/memento_command.h"
+#include "pbd/stacktrace.h"
#include "evoral/Curve.hpp"
using namespace PBD;
uint32_t Route::order_key_cnt = 0;
-boost::signals2::signal<void(string const&)> Route::SyncOrderKeys;
+PBD::Signal1<void,string const&> Route::SyncOrderKeys;
+PBD::Signal0<void> Route::RemoteControlIDChange;
Route::Route (Session& sess, string name, Flag flg, DataType default_type)
: SessionObject (sess, name)
, AutomatableControls (sess)
, _flags (flg)
, _solo_control (new SoloControllable (X_("solo"), *this))
+ , _mute_control (new MuteControllable (X_("mute"), *this))
, _mute_master (new MuteMaster (sess, name))
, _default_type (default_type)
/* now that we have _meter, its safe to connect to this */
- scoped_connect (Metering::Meter, (boost::bind (&Route::meter, this)));
+ Metering::Meter.connect_same_thread (*this, (boost::bind (&Route::meter, this)));
}
Route::Route (Session& sess, const XMLNode& node, DataType default_type)
: SessionObject (sess, "toBeReset")
, AutomatableControls (sess)
, _solo_control (new SoloControllable (X_("solo"), *this))
+ , _mute_control (new MuteControllable (X_("mute"), *this))
, _mute_master (new MuteMaster (sess, "toBeReset"))
, _default_type (default_type)
{
/* now that we have _meter, its safe to connect to this */
- scoped_connect (Metering::Meter, (boost::bind (&Route::meter, this)));
+ Metering::Meter.connect_same_thread (*this, (boost::bind (&Route::meter, this)));
}
void
/* add standard controls */
+ _solo_control->set_flags (Controllable::Flag (_solo_control->flags() | Controllable::Toggle));
+ _mute_control->set_flags (Controllable::Flag (_solo_control->flags() | Controllable::Toggle));
+
add_control (_solo_control);
- add_control (_mute_master);
+ add_control (_mute_control);
/* input and output objects */
_input.reset (new IO (_session, _name, IO::Input, _default_type));
_output.reset (new IO (_session, _name, IO::Output, _default_type));
- scoped_connect (_input->changed, boost::bind (&Route::input_change_handler, this, _1, _2));
- scoped_connect (_output->changed, boost::bind (&Route::output_change_handler, this, _1, _2));
+ _input->changed.connect_same_thread (*this, boost::bind (&Route::input_change_handler, this, _1, _2));
+ _output->changed.connect_same_thread (*this, boost::bind (&Route::output_change_handler, this, _1, _2));
/* add amp processor */
{
DEBUG_TRACE (DEBUG::Destruction, string_compose ("route %1 destructor\n", _name));
+ /* do this early so that we don't get incoming signals as we are going through destruction
+ */
+
+ drop_connections ();
+
/* don't use clear_processors here, as it depends on the session which may
- be half-destroyed by now */
+ be half-destroyed by now
+ */
Glib::RWLock::WriterLock lm (_processor_lock);
for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
}
void
-Route::set_remote_control_id (uint32_t id)
+Route::set_remote_control_id (uint32_t id, bool notify_class_listeners)
{
if (id != _remote_control_id) {
_remote_control_id = id;
RemoteControlIDChanged ();
+ if (notify_class_listeners) {
+ RemoteControlIDChange ();
+ }
}
}
assert (bufs.count() == (*i)->input_streams());
(*i)->run (bufs, start_frame, end_frame, nframes, *i != _processors.back());
- bufs.set_count (ChanCount::max(bufs.count(), (*i)->output_streams()));
- }
-
- if (!_processors.empty()) {
- bufs.set_count (ChanCount::max (bufs.count(), _processors.back()->output_streams()));
+ bufs.set_count ((*i)->output_streams());
}
}
}
// XXX: do we want to emit the signal here ? change call order.
processor->activate ();
}
- scoped_connect (processor->ActiveChanged, boost::bind (&Session::update_latency_compensation, &_session, false, false));
+
+ processor->ActiveChanged.connect_same_thread (*this, boost::bind (&Session::update_latency_compensation, &_session, false, false));
_output->set_user_latency (0);
}
return -1;
}
- scoped_connect ((*i)->ActiveChanged, boost::bind (&Session::update_latency_compensation, &_session, false, false));
+ (*i)->ActiveChanged.connect_same_thread (*this, boost::bind (&Session::update_latency_compensation, &_session, false, false));
}
_output->set_user_latency (0);
Route::SoloControllable::set_value (float val)
{
bool bval = ((val >= 0.5f) ? true: false);
+# if 0
+ this is how it should be done
+ boost::shared_ptr<RouteList> rl (new RouteList);
+ rl->push_back (route);
+
+ if (Config->get_solo_control_is_listen_control()) {
+ _session.set_listen (rl, bval);
+ } else {
+ _session.set_solo (rl, bval);
+ }
+#else
route.set_solo (bval, this);
+#endif
}
float
Route::SoloControllable::get_value (void) const
{
- return route.self_soloed() ? 1.0f : 0.0f;
+ if (Config->get_solo_control_is_listen_control()) {
+ return route.listening() ? 1.0f : 0.0f;
+ } else {
+ return route.self_soloed() ? 1.0f : 0.0f;
+ }
+}
+
+Route::MuteControllable::MuteControllable (std::string name, Route& r)
+ : AutomationControl (r.session(), Evoral::Parameter (MuteAutomation),
+ boost::shared_ptr<AutomationList>(), name)
+ , route (r)
+{
+ boost::shared_ptr<AutomationList> gl(new AutomationList(Evoral::Parameter(MuteAutomation)));
+ set_list (gl);
+}
+
+void
+Route::MuteControllable::set_value (float val)
+{
+ bool bval = ((val >= 0.5f) ? true: false);
+# if 0
+ this is how it should be done
+
+ boost::shared_ptr<RouteList> rl (new RouteList);
+ rl->push_back (route);
+ _session.set_mute (rl, bval);
+#else
+ route.set_mute (bval, this);
+#endif
+}
+
+float
+Route::MuteControllable::get_value (void) const
+{
+ return route.muted() ? 1.0f : 0.0f;
}
void
return c;
}
+
+boost::shared_ptr<Processor>
+Route::nth_plugin (uint32_t n)
+{
+ Glib::RWLock::ReaderLock lm (_processor_lock);
+ ProcessorList::iterator i;
+
+ for (i = _processors.begin(); i != _processors.end(); ++i) {
+ if (boost::dynamic_pointer_cast<PluginInsert> (*i)) {
+ if (n-- == 0) {
+ return *i;
+ }
+ }
+ }
+
+ return boost::shared_ptr<Processor> ();
+}
+
+boost::shared_ptr<Processor>
+Route::nth_send (uint32_t n)
+{
+ Glib::RWLock::ReaderLock lm (_processor_lock);
+ ProcessorList::iterator i;
+
+ for (i = _processors.begin(); i != _processors.end(); ++i) {
+ cerr << "check " << (*i)->name() << endl;
+ if (boost::dynamic_pointer_cast<Send> (*i)) {
+ if (n-- == 0) {
+ return *i;
+ }
+ } else {
+ cerr << "\tnot a send\n";
+ }
+ }
+
+ return boost::shared_ptr<Processor> ();
+}