void set_custom_cfg (bool b);
bool add_sidechain (uint32_t n_audio = 1);
bool del_sidechain ();
+ boost::shared_ptr<SideChain> sidechain () const { return _sidechain; }
// end C++ class slavery!
uint32_t get_count () const { return _plugins.size(); }
return _sidechain ? true : false;
}
- // XXX dangerous
- boost::shared_ptr<SideChain> sidechain () const {
- return _sidechain;
- }
-
- // XXX even more dangerous (adding/removing ports
- // must be done by the owning route and the plugin
- // needs to be reconfigured afterwards)
boost::shared_ptr<IO> sidechain_input () const {
if (_sidechain) {
return _sidechain->input ();
void input_change_handler (IOChange, void *src);
void output_change_handler (IOChange, void *src);
+ void sidechain_change_handler (IOChange, void *src);
bool input_port_count_changing (ChanCount);
bool output_port_count_changing (ChanCount);
bool _in_configure_processors;
bool _initial_io_setup;
+ bool _in_sidechain_setup;
int configure_processors_unlocked (ProcessorStreams*);
bool set_meter_point_unlocked ();
ChanMapping in_map (natural_input_streams ());
ChanMapping out_map (natural_output_streams ());
- // TODO fake run sidechain, too? (maybe once it has meters)
+ // TODO run sidechain (delaylines)
for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
(*i)->connect_and_run (_session.get_scratch_buffers ((*i)->get_info()->n_inputs, true), in_map, out_map, nframes, 0);
}
/* run as normal if we are active or moving from inactive to active */
if (_sidechain) {
- // collect sidechain input for complete cycle.
+ // collect sidechain input for complete cycle (!)
+ // TODO we need delaylines here for latency compensation
_sidechain->run (bufs, start_frame, end_frame, nframes, true);
}
, _track_number (0)
, _in_configure_processors (false)
, _initial_io_setup (false)
+ , _in_sidechain_setup (false)
, _strict_io (false)
, _custom_meter_position_noted (false)
{
{
Glib::Threads::Mutex::Lock lx (AudioEngine::instance()->process_lock ()); // take before Writerlock to avoid deadlock
Glib::Threads::RWLock::WriterLock lm (_processor_lock);
+ PBD::Unwinder<bool> uw (_in_sidechain_setup, true);
lx.release (); // IO::add_port() and ~IO takes process lock - XXX check if this is safe
if (add) {
configure_processors_unlocked (0);
}
+ if (pi->has_sidechain ()) {
+ pi->sidechain_input ()->changed.connect_same_thread (*this, boost::bind (&Route::sidechain_change_handler, this, _1, _2));
+ }
+
processors_changed (RouteProcessorChange ()); /* EMIT SIGNAL */
_session.set_dirty ();
return true;
processor.reset (new UnknownProcessor (_session, **niter));
}
+ /* subscribe to Sidechain IO changes */
+ boost::shared_ptr<PluginInsert> pi = boost::dynamic_pointer_cast<PluginInsert> (processor);
+ if (pi && pi->has_sidechain ()) {
+ pi->sidechain_input ()->changed.connect_same_thread (*this, boost::bind (&Route::sidechain_change_handler, this, _1, _2));
+ }
+
/* we have to note the monitor send here, otherwise a new one will be created
and the state of this one will be lost.
*/
}
}
+void
+Route::sidechain_change_handler (IOChange change, void * /*src*/)
+{
+ if (_initial_io_setup || _in_sidechain_setup) {
+ return;
+ }
+
+ if ((change.type & IOChange::ConfigurationChanged)) {
+ /* This is called with the process lock held if change
+ contains ConfigurationChanged
+ */
+ configure_processors (0);
+ }
+}
+
uint32_t
Route::pans_required () const
{