summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gtk2_ardour/actions.cc4
-rw-r--r--gtk2_ardour/ardour_ui.cc38
-rw-r--r--gtk2_ardour/ardour_ui.h2
-rw-r--r--gtk2_ardour/audio_time_axis.cc20
-rw-r--r--gtk2_ardour/automation_time_axis.cc7
-rw-r--r--gtk2_ardour/editor_route_list.cc8
-rw-r--r--gtk2_ardour/export_channel_selector.cc16
-rw-r--r--gtk2_ardour/gain_meter.cc180
-rw-r--r--gtk2_ardour/gain_meter.h17
-rw-r--r--gtk2_ardour/io_selector.cc68
-rw-r--r--gtk2_ardour/io_selector.h4
-rw-r--r--gtk2_ardour/midi_time_axis.cc8
-rw-r--r--gtk2_ardour/mixer_strip.cc175
-rw-r--r--gtk2_ardour/mixer_strip.h11
-rw-r--r--gtk2_ardour/panner_ui.cc128
-rw-r--r--gtk2_ardour/panner_ui.h7
-rw-r--r--gtk2_ardour/port_group.cc108
-rw-r--r--gtk2_ardour/port_group.h5
-rw-r--r--gtk2_ardour/processor_box.cc24
-rw-r--r--gtk2_ardour/processor_box.h2
-rw-r--r--gtk2_ardour/return_ui.cc23
-rw-r--r--gtk2_ardour/route_params_ui.cc6
-rw-r--r--gtk2_ardour/route_time_axis.cc9
-rw-r--r--gtk2_ardour/route_ui.cc52
-rw-r--r--gtk2_ardour/route_ui.h10
-rw-r--r--gtk2_ardour/send_ui.cc11
-rw-r--r--gtk2_ardour/session_option_editor.cc14
-rw-r--r--gtk2_ardour/sfdb_ui.cc6
-rw-r--r--libs/ardour/SConscript1
-rw-r--r--libs/ardour/amp.cc211
-rw-r--r--libs/ardour/ardour/amp.h67
-rw-r--r--libs/ardour/ardour/automatable.h2
-rw-r--r--libs/ardour/ardour/click.h2
-rw-r--r--libs/ardour/ardour/delivery.h85
-rw-r--r--libs/ardour/ardour/io.h274
-rw-r--r--libs/ardour/ardour/io_processor.h28
-rw-r--r--libs/ardour/ardour/meter.h18
-rw-r--r--libs/ardour/ardour/mute_master.h77
-rw-r--r--libs/ardour/ardour/panner.h8
-rw-r--r--libs/ardour/ardour/port_insert.h13
-rw-r--r--libs/ardour/ardour/processor.h22
-rw-r--r--libs/ardour/ardour/rc_configuration_vars.h1
-rw-r--r--libs/ardour/ardour/return.h20
-rw-r--r--libs/ardour/ardour/route.h165
-rw-r--r--libs/ardour/ardour/send.h26
-rw-r--r--libs/ardour/ardour/session.h13
-rw-r--r--libs/ardour/audio_diskstream.cc24
-rw-r--r--libs/ardour/audio_track.cc36
-rw-r--r--libs/ardour/audioengine.cc8
-rw-r--r--libs/ardour/auditioner.cc22
-rw-r--r--libs/ardour/automatable.cc7
-rw-r--r--libs/ardour/delivery.cc384
-rw-r--r--libs/ardour/diskstream.cc14
-rw-r--r--libs/ardour/enums.cc33
-rw-r--r--libs/ardour/io.cc1996
-rw-r--r--libs/ardour/io_processor.cc191
-rw-r--r--libs/ardour/meter.cc46
-rw-r--r--libs/ardour/midi_diskstream.cc10
-rw-r--r--libs/ardour/midi_track.cc16
-rw-r--r--libs/ardour/mute_master.cc109
-rw-r--r--libs/ardour/panner.cc33
-rw-r--r--libs/ardour/port_insert.cc51
-rw-r--r--libs/ardour/processor.cc3
-rw-r--r--libs/ardour/return.cc51
-rw-r--r--libs/ardour/route.cc1013
-rw-r--r--libs/ardour/route_group.cc5
-rw-r--r--libs/ardour/send.cc87
-rw-r--r--libs/ardour/session.cc224
-rw-r--r--libs/ardour/session_click.cc2
-rw-r--r--libs/ardour/session_state.cc8
-rw-r--r--libs/ardour/session_transport.cc5
-rw-r--r--libs/ardour/track.cc38
-rw-r--r--libs/ardour/wscript5
-rw-r--r--libs/gtkmm2ext/gtkmm2ext/barcontroller.h3
-rw-r--r--libs/midi++2/midi.cc2
-rw-r--r--libs/surfaces/control_protocol/control_protocol.cc15
-rw-r--r--wscript2
77 files changed, 2663 insertions, 3776 deletions
diff --git a/gtk2_ardour/actions.cc b/gtk2_ardour/actions.cc
index 74daa23a9a..a39283c977 100644
--- a/gtk2_ardour/actions.cc
+++ b/gtk2_ardour/actions.cc
@@ -324,7 +324,7 @@ ActionManager::set_sensitive (vector<RefPtr<Action> >& actions, bool state)
void
ActionManager::uncheck_toggleaction (const char * name)
{
- char *last_slash = strrchr (name, '/');
+ const char *last_slash = strrchr (name, '/');
if (last_slash == 0) {
fatal << string_compose (_("programmer error: %1 %2"), X_("illegal toggle action name"), name) << endmsg;
@@ -339,7 +339,7 @@ ActionManager::uncheck_toggleaction (const char * name)
memcpy (group_name, name + 10, len);
group_name[len] = '\0';
- char* action_name = last_slash + 1;
+ const char* action_name = last_slash + 1;
RefPtr<Action> act = get_action (group_name, action_name);
if (act) {
diff --git a/gtk2_ardour/ardour_ui.cc b/gtk2_ardour/ardour_ui.cc
index 0af0a88e11..0b9b9f1f74 100644
--- a/gtk2_ardour/ardour_ui.cc
+++ b/gtk2_ardour/ardour_ui.cc
@@ -1835,44 +1835,6 @@ ARDOUR_UI::stop_blinking ()
}
}
-void
-ARDOUR_UI::name_io_setup (AudioEngine& engine,
- string& buf,
- IO& io,
- bool in)
-{
- vector<string> connections;
-
- if (in) {
- if (io.n_inputs().n_total() == 0) {
- buf = _("none");
- return;
- }
-
- /* XXX we're not handling multiple ports yet. */
-
- if (io.input(0)->get_connections(connections) == 0) {
- buf = _("off");
- } else {
- buf = connections.front();
- }
-
- } else {
-
- if (io.n_outputs().n_total() == 0) {
- buf = _("none");
- return;
- }
-
- /* XXX we're not handling multiple ports yet. */
-
- if (io.output(0)->get_connections(connections) == 0) {
- buf = _("off");
- } else {
- buf = connections.front();
- }
- }
-}
/** Ask the user for the name of a new shapshot and then take it.
*/
diff --git a/gtk2_ardour/ardour_ui.h b/gtk2_ardour/ardour_ui.h
index 2c840324e0..aae644dbec 100644
--- a/gtk2_ardour/ardour_ui.h
+++ b/gtk2_ardour/ardour_ui.h
@@ -176,8 +176,6 @@ class ARDOUR_UI : public Gtkmm2ext::UI
static sigc::signal<void> SuperRapidScreenUpdate;
static sigc::signal<void,nframes_t, bool, nframes_t> Clock;
- void name_io_setup (ARDOUR::AudioEngine&, std::string&, ARDOUR::IO& io, bool in);
-
XMLNode* editor_settings() const;
XMLNode* mixer_settings () const;
XMLNode* keyboard_settings () const;
diff --git a/gtk2_ardour/audio_time_axis.cc b/gtk2_ardour/audio_time_axis.cc
index 6ce54f7882..8f0c25bdb0 100644
--- a/gtk2_ardour/audio_time_axis.cc
+++ b/gtk2_ardour/audio_time_axis.cc
@@ -37,6 +37,7 @@
#include <gtkmm2ext/bindable_button.h>
#include <gtkmm2ext/utils.h>
+#include "ardour/amp.h"
#include "ardour/audio_diskstream.h"
#include "ardour/audioplaylist.h"
#include "ardour/event_type_map.h"
@@ -347,13 +348,14 @@ AudioTimeAxisView::create_automation_child (const Evoral::Parameter& param, bool
return;
}
- boost::shared_ptr<AutomationTimeAxisView> gain_track(new AutomationTimeAxisView (_session,
- _route, _route, c,
- _editor,
- *this,
- false,
- parent_canvas,
- _route->describe_parameter(param)));
+ boost::shared_ptr<AutomationTimeAxisView>
+ gain_track(new AutomationTimeAxisView (_session,
+ _route, _route->amp(), c,
+ _editor,
+ *this,
+ false,
+ parent_canvas,
+ _route->amp()->describe_parameter(param)));
add_automation_child(Evoral::Parameter(GainAutomation), gain_track, show);
@@ -396,11 +398,11 @@ AudioTimeAxisView::ensure_pan_views (bool show)
/* we don't already have an AutomationTimeAxisView for this parameter */
- std::string const name = _route->describe_parameter (pan_control->parameter ());
+ std::string const name = _route->panner()->describe_parameter (pan_control->parameter ());
boost::shared_ptr<AutomationTimeAxisView> pan_track (
new AutomationTimeAxisView (_session,
- _route, _route, pan_control,
+ _route, _route->panner(), pan_control,
_editor,
*this,
false,
diff --git a/gtk2_ardour/automation_time_axis.cc b/gtk2_ardour/automation_time_axis.cc
index 78faf66944..e72c5add00 100644
--- a/gtk2_ardour/automation_time_axis.cc
+++ b/gtk2_ardour/automation_time_axis.cc
@@ -255,15 +255,20 @@ void
AutomationTimeAxisView::set_automation_state (AutoState state)
{
if (!ignore_state_request) {
+ _automatable->set_parameter_automation_state (_control->parameter(), state);
+#if 0
if (_route == _automatable) { // This is a time axis for route (not region) automation
_route->set_parameter_automation_state (_control->parameter(), state);
}
if (_control->list())
_control->alist()->set_automation_state(state);
+#endif
}
- if (_view)
+
+ if (_view) {
_view->set_automation_state (state);
+ }
}
void
diff --git a/gtk2_ardour/editor_route_list.cc b/gtk2_ardour/editor_route_list.cc
index 00b4a3656d..964ee38712 100644
--- a/gtk2_ardour/editor_route_list.cc
+++ b/gtk2_ardour/editor_route_list.cc
@@ -67,10 +67,12 @@ Editor::handle_new_route (RouteList& routes)
if (route->is_hidden()) {
continue;
}
-
- if (route->default_type() == ARDOUR::DataType::AUDIO)
+
+ DataType dt = route->input()->default_type();
+
+ if (dt == ARDOUR::DataType::AUDIO)
tv = new AudioTimeAxisView (*this, *session, route, *track_canvas);
- else if (route->default_type() == ARDOUR::DataType::MIDI)
+ else if (dt == ARDOUR::DataType::MIDI)
tv = new MidiTimeAxisView (*this, *session, route, *track_canvas);
else
throw unknown_type();
diff --git a/gtk2_ardour/export_channel_selector.cc b/gtk2_ardour/export_channel_selector.cc
index 2f66e58fe5..7b665a6087 100644
--- a/gtk2_ardour/export_channel_selector.cc
+++ b/gtk2_ardour/export_channel_selector.cc
@@ -112,14 +112,14 @@ PortExportChannelSelector::fill_route_list ()
/* Add master bus and then everything else */
- ARDOUR::IO * master = session->master_out().get();
+ ARDOUR::IO* master = session->master_out()->output().get();
channel_view.add_route (master);
for (RouteList::iterator it = routes.begin(); it != routes.end(); ++it) {
- if (it->get() == master) {
+ if ((*it)->output().get() == master) {
continue;
}
- channel_view.add_route (it->get());
+ channel_view.add_route ((*it)->output().get());
}
update_channel_count ();
@@ -261,27 +261,27 @@ PortExportChannelSelector::ChannelTreeView::set_config (ChannelConfigPtr c)
}
void
-PortExportChannelSelector::ChannelTreeView::add_route (ARDOUR::IO * route)
+PortExportChannelSelector::ChannelTreeView::add_route (ARDOUR::IO * io)
{
Gtk::TreeModel::iterator iter = route_list->append();
Gtk::TreeModel::Row row = *iter;
row[route_cols.selected] = false;
- row[route_cols.name] = route->name();
- row[route_cols.io] = route;
+ row[route_cols.name] = io->name();
+ row[route_cols.io] = io;
/* Initialize port list */
Glib::RefPtr<Gtk::ListStore> port_list = Gtk::ListStore::create (route_cols.port_cols);
row[route_cols.port_list_col] = port_list;
- uint32_t outs = route->n_outputs().n_audio();
+ uint32_t outs = io->n_ports().n_audio();
for (uint32_t i = 0; i < outs; ++i) {
iter = port_list->append();
row = *iter;
row[route_cols.port_cols.selected] = false;
- row[route_cols.port_cols.port] = route->audio_output (i);
+ row[route_cols.port_cols.port] = io->audio (i);
std::ostringstream oss;
oss << "Out-" << (i + 1);
diff --git a/gtk2_ardour/gain_meter.cc b/gtk2_ardour/gain_meter.cc
index 85e591a8cc..045c93173e 100644
--- a/gtk2_ardour/gain_meter.cc
+++ b/gtk2_ardour/gain_meter.cc
@@ -160,57 +160,58 @@ GainMeterBase::~GainMeterBase ()
}
void
-GainMeterBase::set_io (boost::shared_ptr<IO> io)
+GainMeterBase::set_controls (boost::shared_ptr<Route> r,
+ boost::shared_ptr<PeakMeter> pm,
+ boost::shared_ptr<AutomationControl> gc,
+ boost::shared_ptr<Automatable> gc_owner)
{
connections.clear ();
- _io = io;
-
- if (!_io) {
+ if (!pm && !gc) {
level_meter->set_meter (0);
gain_slider->set_controllable (boost::shared_ptr<PBD::Controllable>());
+ _meter.reset ();
+ _gain_control.reset ();
+ _route.reset ();
return;
}
- level_meter->set_meter (&_io->peak_meter());
- gain_slider->set_controllable (_io->gain_control());
-
- boost::shared_ptr<Route> r;
-
- if ((r = boost::dynamic_pointer_cast<Route> (_io)) != 0) {
+ _meter = pm;
+ _gain_control = gc;
+ _route = r;
- if (!r->is_hidden()) {
-
- using namespace Menu_Helpers;
+ level_meter->set_meter (pm.get());
+ gain_slider->set_controllable (gc);
- gain_astate_menu.items().clear ();
-
- gain_astate_menu.items().push_back (MenuElem (_("Manual"),
- bind (mem_fun (*_io, &IO::set_parameter_automation_state),
- Evoral::Parameter(GainAutomation), (AutoState) Off)));
- gain_astate_menu.items().push_back (MenuElem (_("Play"),
- bind (mem_fun (*_io, &IO::set_parameter_automation_state),
- Evoral::Parameter(GainAutomation), (AutoState) Play)));
- gain_astate_menu.items().push_back (MenuElem (_("Write"),
- bind (mem_fun (*_io, &IO::set_parameter_automation_state),
- Evoral::Parameter(GainAutomation), (AutoState) Write)));
- gain_astate_menu.items().push_back (MenuElem (_("Touch"),
- bind (mem_fun (*_io, &IO::set_parameter_automation_state),
- Evoral::Parameter(GainAutomation), (AutoState) Touch)));
-
- connections.push_back (gain_automation_style_button.signal_button_press_event().connect (mem_fun(*this, &GainMeterBase::gain_automation_style_button_event), false));
- connections.push_back (gain_automation_state_button.signal_button_press_event().connect (mem_fun(*this, &GainMeterBase::gain_automation_state_button_event), false));
-
- connections.push_back (r->gain_control()->alist()->automation_state_changed.connect (mem_fun(*this, &GainMeter::gain_automation_state_changed)));
- connections.push_back (r->gain_control()->alist()->automation_style_changed.connect (mem_fun(*this, &GainMeter::gain_automation_style_changed)));
-
- gain_automation_state_changed ();
- }
+ if (!_route || !_route->is_hidden()) {
+
+ using namespace Menu_Helpers;
+
+ gain_astate_menu.items().clear ();
+
+ gain_astate_menu.items().push_back (MenuElem (_("Manual"),
+ bind (mem_fun (*(gc_owner.get()), &Automatable::set_parameter_automation_state),
+ Evoral::Parameter(GainAutomation), (AutoState) Off)));
+ gain_astate_menu.items().push_back (MenuElem (_("Play"),
+ bind (mem_fun (*(gc_owner.get()), &Automatable::set_parameter_automation_state),
+ Evoral::Parameter(GainAutomation), (AutoState) Play)));
+ gain_astate_menu.items().push_back (MenuElem (_("Write"),
+ bind (mem_fun (*(gc_owner.get()), &Automatable::set_parameter_automation_state),
+ Evoral::Parameter(GainAutomation), (AutoState) Write)));
+ gain_astate_menu.items().push_back (MenuElem (_("Touch"),
+ bind (mem_fun (*(gc_owner.get()), &Automatable::set_parameter_automation_state),
+ Evoral::Parameter(GainAutomation), (AutoState) Touch)));
+
+ connections.push_back (gain_automation_style_button.signal_button_press_event().connect (mem_fun(*this, &GainMeterBase::gain_automation_style_button_event), false));
+ connections.push_back (gain_automation_state_button.signal_button_press_event().connect (mem_fun(*this, &GainMeterBase::gain_automation_state_button_event), false));
+
+ connections.push_back (gc->alist()->automation_state_changed.connect (mem_fun(*this, &GainMeter::gain_automation_state_changed)));
+ connections.push_back (gc->alist()->automation_style_changed.connect (mem_fun(*this, &GainMeter::gain_automation_style_changed)));
+
+ gain_automation_state_changed ();
}
- //cerr << "Connect " << this << " to gain change for " << _io->name() << endl;
-
- connections.push_back (_io->gain_control()->Changed.connect (mem_fun(*this, &GainMeterBase::gain_changed)));
+ connections.push_back (gc->Changed.connect (mem_fun (*this, &GainMeterBase::gain_changed)));
gain_changed ();
show_gain ();
@@ -272,10 +273,8 @@ GainMeterBase::peak_button_release (GdkEventButton* ev)
if (ev->button == 1 && Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier|Keyboard::TertiaryModifier)) {
ResetAllPeakDisplays ();
} else if (ev->button == 1 && Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
- boost::shared_ptr<Route> r;
-
- if ((r = boost::dynamic_pointer_cast<Route> (_io)) != 0) {
- ResetGroupPeakDisplays (r->mix_group());
+ if (_route) {
+ ResetGroupPeakDisplays (_route->mix_group());
}
} else {
reset_peak_display ();
@@ -287,12 +286,7 @@ GainMeterBase::peak_button_release (GdkEventButton* ev)
void
GainMeterBase::reset_peak_display ()
{
- boost::shared_ptr<Route> r;
-
- if ((r = boost::dynamic_pointer_cast<Route> (_io)) != 0) {
- r->peak_meter().reset_max();
- }
-
+ _meter->reset_max();
level_meter->clear_meters();
max_peak = -INFINITY;
peak_display.set_label (_("-Inf"));
@@ -302,13 +296,9 @@ GainMeterBase::reset_peak_display ()
void
GainMeterBase::reset_group_peak_display (RouteGroup* group)
{
- boost::shared_ptr<Route> r;
-
- if ((r = boost::dynamic_pointer_cast<Route> (_io)) != 0) {
- if (group == r->mix_group()) {
- reset_peak_display ();
+ if (_route && group == _route->mix_group()) {
+ reset_peak_display ();
}
- }
}
void
@@ -354,7 +344,7 @@ GainMeterBase::gain_activated ()
f = min (f, 6.0f);
- _io->gain_control()->set_value (dB_to_coefficient(f));
+ _gain_control->set_value (dB_to_coefficient(f));
if (gain_display.has_focus()) {
PublicEditor::instance().reset_focus();
@@ -384,7 +374,7 @@ GainMeterBase::gain_adjusted ()
//cerr << this << " for " << _io->name() << " GAIN ADJUSTED\n";
if (!ignore_toggle) {
//cerr << "Set GC\n";
- _io->gain_control()->set_value (slider_position_to_gain (gain_adjustment.get_value()));
+ _gain_control->set_value (slider_position_to_gain (gain_adjustment.get_value()));
//cerr << "Set GC OUT\n";
}
show_gain ();
@@ -393,7 +383,7 @@ GainMeterBase::gain_adjusted ()
void
GainMeterBase::effective_gain_display ()
{
- gfloat value = gain_to_slider_position (_io->effective_gain());
+ gfloat value = gain_to_slider_position (_gain_control->get_value());
//cerr << this << " for " << _io->name() << " EGAIN = " << value
// << " AGAIN = " << gain_adjustment.get_value () << endl;
@@ -428,7 +418,7 @@ void
GainMeterBase::update_gain_sensitive ()
{
static_cast<Gtkmm2ext::SliderController*>(gain_slider)->set_sensitive (
- !(_io->gain_control()->alist()->automation_state() & Play));
+ !(_gain_control->alist()->automation_state() & Play));
}
@@ -459,7 +449,7 @@ GainMeterBase::meter_press(GdkEventButton* ev)
wait_for_release = false;
- if ((_route = boost::dynamic_pointer_cast<Route>(_io)) == 0) {
+ if (!_route) {
return FALSE;
}
@@ -482,10 +472,10 @@ GainMeterBase::meter_press(GdkEventButton* ev)
}
}
- if (ev->button == 1 || Keyboard::is_button2_event (ev)) {
+ if (_route && (ev->button == 1 || Keyboard::is_button2_event (ev))) {
if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
-
+
/* Primary+Tertiary-click applies change to all routes */
_session.begin_reversible_command (_("meter point change"));
@@ -534,10 +524,8 @@ GainMeterBase::meter_release(GdkEventButton* ev)
if (wait_for_release){
wait_for_release = false;
- boost::shared_ptr<Route> r;
-
- if ((r = boost::dynamic_pointer_cast<Route>(_io)) != 0) {
- set_meter_point (*r, old_meter_point);
+ if (_route) {
+ set_meter_point (*_route, old_meter_point);
}
}
}
@@ -566,9 +554,7 @@ GainMeterBase::set_mix_group_meter_point (Route& route, MeterPoint mp)
void
GainMeterBase::meter_point_clicked ()
{
- boost::shared_ptr<Route> r;
-
- if ((r = boost::dynamic_pointer_cast<Route> (_io)) != 0) {
+ if (_route) {
/* WHAT? */
}
}
@@ -576,14 +562,14 @@ GainMeterBase::meter_point_clicked ()
gint
GainMeterBase::start_gain_touch (GdkEventButton* ev)
{
- _io->gain_control()->start_touch ();
+ _gain_control->start_touch ();
return FALSE;
}
gint
GainMeterBase::end_gain_touch (GdkEventButton* ev)
{
- _io->gain_control()->stop_touch ();
+ _gain_control->stop_touch ();
return FALSE;
}
@@ -686,10 +672,10 @@ GainMeterBase::gain_automation_style_changed ()
{
switch (_width) {
case Wide:
- gain_automation_style_button.set_label (astyle_string(_io->gain_control()->alist()->automation_style()));
+ gain_automation_style_button.set_label (astyle_string(_gain_control->alist()->automation_style()));
break;
case Narrow:
- gain_automation_style_button.set_label (short_astyle_string(_io->gain_control()->alist()->automation_style()));
+ gain_automation_style_button.set_label (short_astyle_string(_gain_control->alist()->automation_style()));
break;
}
}
@@ -703,14 +689,14 @@ GainMeterBase::gain_automation_state_changed ()
switch (_width) {
case Wide:
- gain_automation_state_button.set_label (astate_string(_io->gain_control()->alist()->automation_state()));
+ gain_automation_state_button.set_label (astate_string(_gain_control->alist()->automation_state()));
break;
case Narrow:
- gain_automation_state_button.set_label (short_astate_string(_io->gain_control()->alist()->automation_state()));
+ gain_automation_state_button.set_label (short_astate_string(_gain_control->alist()->automation_state()));
break;
}
- x = (_io->gain_control()->alist()->automation_state() != Off);
+ x = (_gain_control->alist()->automation_state() != Off);
if (gain_automation_state_button.get_active() != x) {
ignore_toggle = true;
@@ -811,8 +797,11 @@ GainMeter::GainMeter (Session& s)
meter_metric_area.signal_expose_event().connect (mem_fun(*this, &GainMeter::meter_metrics_expose));
}
-void
-GainMeter::set_io (boost::shared_ptr<IO> io)
+void
+GainMeter::set_controls (boost::shared_ptr<Route> r,
+ boost::shared_ptr<PeakMeter> meter,
+ boost::shared_ptr<AutomationControl> gain_control,
+ boost::shared_ptr<Automatable> gc_owner)
{
if (level_meter->get_parent()) {
hbox.remove (*level_meter);
@@ -826,30 +815,17 @@ GainMeter::set_io (boost::shared_ptr<IO> io)
fader_vbox->remove (gain_automation_state_button);
}
- GainMeterBase::set_io (io);
+ GainMeterBase::set_controls (r, meter, gain_control, gc_owner);
- boost::shared_ptr<Route> r;
-
- if ((r = boost::dynamic_pointer_cast<Route> (_io)) != 0) {
-
- /*
- if we have a non-hidden route (ie. we're not the click or the auditioner),
- pack some route-dependent stuff.
- */
-
- gain_display_box.pack_end (peak_display, true, true);
- hbox.pack_end (*level_meter, true, true);
-
- if (!r->is_hidden()) {
- fader_vbox->pack_start (gain_automation_state_button, false, false, 0);
- }
-
- } else {
-
- /* we're managing a non-Route IO (e.g. Send) */
-
- gain_display_box.pack_end (peak_display, true, true);
- hbox.pack_end (*level_meter, true, true);
+ /*
+ if we have a non-hidden route (ie. we're not the click or the auditioner),
+ pack some route-dependent stuff.
+ */
+
+ gain_display_box.pack_end (peak_display, true, true);
+ hbox.pack_end (*level_meter, true, true);
+
+ if (!r->is_hidden()) {
fader_vbox->pack_start (gain_automation_state_button, false, false, 0);
}
}
@@ -941,7 +917,7 @@ GainMeter::meter_metrics_expose (GdkEventExpose *ev)
boost::shared_ptr<PBD::Controllable>
GainMeterBase::get_controllable()
{
- return _io->gain_control();
+ return _gain_control;
}
diff --git a/gtk2_ardour/gain_meter.h b/gtk2_ardour/gain_meter.h
index ea817bcae2..7feaf5c0e4 100644
--- a/gtk2_ardour/gain_meter.h
+++ b/gtk2_ardour/gain_meter.h
@@ -46,6 +46,8 @@ namespace ARDOUR {
class Session;
class Route;
class RouteGroup;
+ class PeakMeter;
+ class Automatable;
}
namespace Gtkmm2ext {
class FastMeter;
@@ -62,8 +64,10 @@ class GainMeterBase : virtual public sigc::trackable
bool horizontal);
virtual ~GainMeterBase ();
- virtual void set_io (boost::shared_ptr<ARDOUR::IO>);
- boost::shared_ptr<ARDOUR::IO> io() const { return _io; }
+ virtual void set_controls (boost::shared_ptr<ARDOUR::Route> route,
+ boost::shared_ptr<ARDOUR::PeakMeter> meter,
+ boost::shared_ptr<ARDOUR::AutomationControl> gain_control,
+ boost::shared_ptr<ARDOUR::Automatable> gc_owner);
void update_gain_sensitive ();
void update_meters ();
@@ -83,7 +87,9 @@ class GainMeterBase : virtual public sigc::trackable
protected:
friend class MixerStrip;
- boost::shared_ptr<ARDOUR::IO> _io;
+ boost::shared_ptr<ARDOUR::Route> _route;
+ boost::shared_ptr<ARDOUR::PeakMeter> _meter;
+ boost::shared_ptr<ARDOUR::AutomationControl> _gain_control;
ARDOUR::Session& _session;
std::vector<sigc::connection> connections;
@@ -176,7 +182,10 @@ class GainMeter : public GainMeterBase, public Gtk::VBox
GainMeter (ARDOUR::Session&);
~GainMeter () {}
- void set_io (boost::shared_ptr<ARDOUR::IO>);
+ virtual void set_controls (boost::shared_ptr<ARDOUR::Route> route,
+ boost::shared_ptr<ARDOUR::PeakMeter> meter,
+ boost::shared_ptr<ARDOUR::AutomationControl> gain_control,
+ boost::shared_ptr<ARDOUR::Automatable> gc_owner);
int get_gm_width ();
void setup_meters (int len=0);
diff --git a/gtk2_ardour/io_selector.cc b/gtk2_ardour/io_selector.cc
index fb7d946f7d..4333efd8ea 100644
--- a/gtk2_ardour/io_selector.cc
+++ b/gtk2_ardour/io_selector.cc
@@ -41,12 +41,14 @@
using namespace ARDOUR;
using namespace Gtk;
-IOSelector::IOSelector (ARDOUR::Session& session, boost::shared_ptr<ARDOUR::IO> io, bool in)
+IOSelector::IOSelector (ARDOUR::Session& session, boost::shared_ptr<ARDOUR::IO> io)
: PortMatrix (session, io->default_type())
, _io (io)
- , _find_inputs_for_io_outputs (in)
{
/* signal flow from 0 to 1 */
+
+ _find_inputs_for_io_outputs = (_io->direction() == IO::Output);
+
if (_find_inputs_for_io_outputs) {
_other = 1;
_ours = 0;
@@ -73,9 +75,7 @@ IOSelector::setup_ports (int dim)
} else {
_port_group->clear ();
- _port_group->add_bundle (
- _find_inputs_for_io_outputs ? _io->bundle_for_outputs() : _io->bundle_for_inputs()
- );
+ _port_group->add_bundle (_io->bundle ());
}
_ports[dim].resume_signals ();
@@ -96,17 +96,9 @@ IOSelector::set_state (ARDOUR::BundleChannel c[2], bool s)
}
if (s) {
- if (!_find_inputs_for_io_outputs) {
- _io->connect_input (f, *j, 0);
- } else {
- _io->connect_output (f, *j, 0);
- }
+ _io->connect (f, *j, 0);
} else {
- if (!_find_inputs_for_io_outputs) {
- _io->disconnect_input (f, *j, 0);
- } else {
- _io->disconnect_output (f, *j, 0);
- }
+ _io->disconnect (f, *j, 0);
}
}
}
@@ -147,9 +139,9 @@ uint32_t
IOSelector::n_io_ports () const
{
if (!_find_inputs_for_io_outputs) {
- return _io->inputs().num_ports (_io->default_type());
+ return _io->n_ports().get (_io->default_type());
} else {
- return _io->outputs().num_ports (_io->default_type());
+ return _io->n_ports().get (_io->default_type());
}
}
@@ -161,27 +153,13 @@ IOSelector::add_channel (boost::shared_ptr<ARDOUR::Bundle> b)
// The IO selector only works for single typed IOs
const ARDOUR::DataType t = _io->default_type ();
- if (!_find_inputs_for_io_outputs) {
-
- try {
- _io->add_input_port ("", this);
- }
-
- catch (AudioEngine::PortRegistrationFailure& err) {
- MessageDialog msg (_("There are no more JACK ports available."));
- msg.run ();
- }
-
- } else {
-
- try {
- _io->add_output_port ("", this);
- }
-
- catch (AudioEngine::PortRegistrationFailure& err) {
- MessageDialog msg (_("There are no more JACK ports available."));
- msg.run ();
- }
+ try {
+ _io->add_port ("", this);
+ }
+
+ catch (AudioEngine::PortRegistrationFailure& err) {
+ MessageDialog msg (_("There are no more JACK ports available."));
+ msg.run ();
}
}
@@ -193,11 +171,7 @@ IOSelector::remove_channel (ARDOUR::BundleChannel bc)
return;
}
- if (_find_inputs_for_io_outputs) {
- _io->remove_output_port (f, this);
- } else {
- _io->remove_input_port (f, this);
- }
+ _io->remove_port (f, this);
}
bool
@@ -206,9 +180,9 @@ IOSelector::list_is_global (int dim) const
return (dim == _other);
}
-IOSelectorWindow::IOSelectorWindow (ARDOUR::Session& session, boost::shared_ptr<ARDOUR::IO> io, bool for_input, bool can_cancel)
+IOSelectorWindow::IOSelectorWindow (ARDOUR::Session& session, boost::shared_ptr<ARDOUR::IO> io, bool can_cancel)
: ArdourDialog ("I/O selector")
- , _selector (session, io, !for_input)
+ , _selector (session, io)
, add_button (_("Add Port"))
, disconnect_button (_("Disconnect All"))
, ok_button (can_cancel ? _("OK"): _("Close"))
@@ -327,8 +301,8 @@ IOSelectorWindow::io_name_changed (void* src)
}
PortInsertUI::PortInsertUI (ARDOUR::Session& sess, boost::shared_ptr<ARDOUR::PortInsert> pi)
- : input_selector (sess, pi->io(), true),
- output_selector (sess, pi->io(), false)
+ : input_selector (sess, pi->input())
+ , output_selector (sess, pi->output())
{
output_selector.set_min_height_divisor (2);
input_selector.set_min_height_divisor (2);
diff --git a/gtk2_ardour/io_selector.h b/gtk2_ardour/io_selector.h
index 872fd5d7d6..d6b00254be 100644
--- a/gtk2_ardour/io_selector.h
+++ b/gtk2_ardour/io_selector.h
@@ -30,7 +30,7 @@ namespace ARDOUR {
class IOSelector : public PortMatrix
{
public:
- IOSelector (ARDOUR::Session&, boost::shared_ptr<ARDOUR::IO>, bool);
+ IOSelector (ARDOUR::Session&, boost::shared_ptr<ARDOUR::IO>);
void set_state (ARDOUR::BundleChannel c[2], bool);
PortMatrixNode::State get_state (ARDOUR::BundleChannel c[2]) const;
@@ -74,7 +74,7 @@ class IOSelector : public PortMatrix
class IOSelectorWindow : public ArdourDialog
{
public:
- IOSelectorWindow (ARDOUR::Session&, boost::shared_ptr<ARDOUR::IO>, bool for_input, bool can_cancel = false);
+ IOSelectorWindow (ARDOUR::Session&, boost::shared_ptr<ARDOUR::IO>, bool can_cancel = false);
IOSelector& selector() { return _selector; }
diff --git a/gtk2_ardour/midi_time_axis.cc b/gtk2_ardour/midi_time_axis.cc
index 18786fe54a..c8cd5fe464 100644
--- a/gtk2_ardour/midi_time_axis.cc
+++ b/gtk2_ardour/midi_time_axis.cc
@@ -506,13 +506,7 @@ MidiTimeAxisView::create_automation_child (const Evoral::Parameter& param, bool
if (existing != _automation_tracks.end())
return;
- boost::shared_ptr<AutomationControl> c
- = boost::dynamic_pointer_cast<AutomationControl>(_route->data().control(param));
-
- if (!c) {
- c = boost::dynamic_pointer_cast<AutomationControl>(_route->control_factory(param));
- _route->add_control(c);
- }
+ boost::shared_ptr<AutomationControl> c = _route->get_control (param);
assert(c);
diff --git a/gtk2_ardour/mixer_strip.cc b/gtk2_ardour/mixer_strip.cc
index fdc1e2f39b..13e077c12f 100644
--- a/gtk2_ardour/mixer_strip.cc
+++ b/gtk2_ardour/mixer_strip.cc
@@ -34,6 +34,7 @@
#include <gtkmm2ext/bindable_button.h>
#include "ardour/ardour.h"
+#include "ardour/amp.h"
#include "ardour/session.h"
#include "ardour/audioengine.h"
#include "ardour/route.h"
@@ -71,20 +72,6 @@ sigc::signal<void,boost::shared_ptr<Route> > MixerStrip::SwitchIO;
int MixerStrip::scrollbar_height = 0;
-#ifdef VARISPEED_IN_MIXER_STRIP
-static void
-speed_printer (char buf[32], Gtk::Adjustment& adj, void* arg)
-{
- float val = adj.get_value ();
-
- if (val == 1.0) {
- strcpy (buf, "1");
- } else {
- snprintf (buf, 32, "%.3f", val);
- }
-}
-#endif
-
MixerStrip::MixerStrip (Mixer_UI& mx, Session& sess, bool in_mixer)
: AxisView(sess)
, RouteUI (sess, _("Mute"), _("Solo"), _("Record"))
@@ -99,8 +86,6 @@ MixerStrip::MixerStrip (Mixer_UI& mx, Session& sess, bool in_mixer)
, bottom_button_table (1, 2)
, meter_point_label (_("pre"))
, comment_button (_("Comments"))
- , speed_adjustment (1.0, 0.001, 4.0, 0.001, 0.1)
- , speed_spinner (&speed_adjustment, "MixerStripSpeedBase", true)
{
init ();
@@ -128,8 +113,6 @@ MixerStrip::MixerStrip (Mixer_UI& mx, Session& sess, boost::shared_ptr<Route> rt
, bottom_button_table (1, 2)
, meter_point_label (_("pre"))
, comment_button (_("Comments"))
- , speed_adjustment (1.0, 0.001, 4.0, 0.001, 0.1)
- , speed_spinner (&speed_adjustment, "MixerStripSpeedBase", true)
{
init ();
@@ -146,7 +129,6 @@ MixerStrip::init ()
route_ops_menu = 0;
ignore_comment_edit = false;
ignore_toggle = false;
- ignore_speed_adjustment = false;
comment_window = 0;
comment_area = 0;
_width_owner = 0;
@@ -340,12 +322,6 @@ MixerStrip::set_route (boost::shared_ptr<Route> rt)
button_table.remove (*show_sends_button);
}
-#ifdef VARISPEED_IN_MIXER_STRIP
- if (speed_frame->get_parent()) {
- button_table.remove (*speed_frame);
- }
-#endif
-
RouteUI::set_route (rt);
delete input_selector;
@@ -354,14 +330,16 @@ MixerStrip::set_route (boost::shared_ptr<Route> rt)
delete output_selector;
output_selector = 0;
- if (_current_send) {
- _current_send->set_metering (false);
+ boost::shared_ptr<Send> send;
+
+ if (_current_delivery && (send = boost::dynamic_pointer_cast<Send>(_current_delivery))) {
+ send->set_metering (false);
}
- _current_send.reset ();
+ _current_delivery = _route->main_outs ();
- panners.set_io (rt);
- gpm.set_io (rt);
+ panners.set_panner (rt->main_outs()->panner());
+ gpm.set_controls (rt, rt->shared_peak_meter(), rt->gain_control(), rt->amp());
pre_processor_box.set_route (rt);
post_processor_box.set_route (rt);
@@ -388,20 +366,6 @@ MixerStrip::set_route (boost::shared_ptr<Route> rt)
connections.push_back (at->FreezeChange.connect (mem_fun(*this, &MixerStrip::map_frozen)));
-#ifdef VARISPEED_IN_MIXER_STRIP
- speed_adjustment.signal_value_changed().connect (mem_fun(*this, &MixerStrip::speed_adjustment_changed));
-
- speed_frame.set_name ("BaseFrame");
- speed_frame.set_shadow_type (Gtk::SHADOW_IN);
- speed_frame.add (speed_spinner);
-
- speed_spinner.set_print_func (speed_printer, 0);
-
- ARDOUR_UI::instance()->tooltips().set_tip (speed_spinner, _("Varispeed"));
-
- button_table.attach (speed_frame, 0, 2, 5, 6);
-#endif /* VARISPEED_IN_MIXER_STRIP */
-
button_table.attach (*rec_enable_button, 0, 2, 2, 3);
rec_enable_button->show();
@@ -443,9 +407,9 @@ MixerStrip::set_route (boost::shared_ptr<Route> rt)
connections.push_back (_route->meter_change.connect (
mem_fun(*this, &MixerStrip::meter_changed)));
- connections.push_back (_route->input_changed.connect (
+ connections.push_back (_route->input()->changed.connect (
mem_fun(*this, &MixerStrip::input_changed)));
- connections.push_back (_route->output_changed.connect (
+ connections.push_back (_route->output()->changed.connect (
mem_fun(*this, &MixerStrip::output_changed)));
connections.push_back (_route->mix_group_changed.connect (
mem_fun(*this, &MixerStrip::mix_group_changed)));
@@ -458,8 +422,6 @@ MixerStrip::set_route (boost::shared_ptr<Route> rt)
if (is_audio_track()) {
connections.push_back (audio_track()->DiskstreamChanged.connect (
mem_fun(*this, &MixerStrip::diskstream_changed)));
- connections.push_back (get_diskstream()->SpeedChanged.connect (
- mem_fun(*this, &MixerStrip::speed_changed)));
}
connections.push_back (_route->NameChanged.connect (
@@ -485,10 +447,6 @@ MixerStrip::set_route (boost::shared_ptr<Route> rt)
panners.setup_pan ();
- if (is_audio_track()) {
- speed_changed ();
- }
-
update_diskstream_display ();
update_input_display ();
update_output_display ();
@@ -530,9 +488,6 @@ MixerStrip::set_route (boost::shared_ptr<Route> rt)
comment_button.show();
group_button.show();
group_label.show();
- speed_spinner.show();
- speed_label.show();
- speed_frame.show();
show ();
}
@@ -703,7 +658,7 @@ MixerStrip::output_press (GdkEventButton *ev)
citems.push_back (MenuElem (_("Disconnect"), mem_fun (*(static_cast<RouteUI*>(this)), &RouteUI::disconnect_output)));
citems.push_back (SeparatorElem());
- ARDOUR::BundleList current = _route->bundles_connected_to_outputs ();
+ ARDOUR::BundleList current = _route->output()->bundles_connected ();
boost::shared_ptr<ARDOUR::BundleList> b = _session.bundles ();
for (ARDOUR::BundleList::iterator i = b->begin(); i != b->end(); ++i) {
@@ -712,7 +667,7 @@ MixerStrip::output_press (GdkEventButton *ev)
boost::shared_ptr<ARDOUR::RouteList> routes = _session.get_routes ();
for (ARDOUR::RouteList::const_iterator i = routes->begin(); i != routes->end(); ++i) {
- maybe_add_bundle_to_output_menu ((*i)->bundle_for_inputs(), current);
+ maybe_add_bundle_to_output_menu ((*i)->input()->bundle(), current);
}
if (citems.size() == 2) {
@@ -734,7 +689,7 @@ void
MixerStrip::edit_output_configuration ()
{
if (output_selector == 0) {
- output_selector = new IOSelectorWindow (_session, _route, false);
+ output_selector = new IOSelectorWindow (_session, _route->output());
}
if (output_selector->is_visible()) {
@@ -748,7 +703,7 @@ void
MixerStrip::edit_input_configuration ()
{
if (input_selector == 0) {
- input_selector = new IOSelectorWindow (_session, _route, true);
+ input_selector = new IOSelectorWindow (_session, _route->input());
}
if (input_selector->is_visible()) {
@@ -784,7 +739,7 @@ MixerStrip::input_press (GdkEventButton *ev)
citems.push_back (MenuElem (_("Disconnect"), mem_fun (*(static_cast<RouteUI*>(this)), &RouteUI::disconnect_input)));
citems.push_back (SeparatorElem());
- ARDOUR::BundleList current = _route->bundles_connected_to_inputs ();
+ ARDOUR::BundleList current = _route->input()->bundles_connected ();
boost::shared_ptr<ARDOUR::BundleList> b = _session.bundles ();
for (ARDOUR::BundleList::iterator i = b->begin(); i != b->end(); ++i) {
@@ -793,7 +748,7 @@ MixerStrip::input_press (GdkEventButton *ev)
boost::shared_ptr<ARDOUR::RouteList> routes = _session.get_routes ();
for (ARDOUR::RouteList::const_iterator i = routes->begin(); i != routes->end(); ++i) {
- maybe_add_bundle_to_input_menu ((*i)->bundle_for_outputs(), current);
+ maybe_add_bundle_to_input_menu ((*i)->output()->bundle(), current);
}
if (citems.size() == 2) {
@@ -817,12 +772,12 @@ MixerStrip::bundle_input_toggled (boost::shared_ptr<ARDOUR::Bundle> c)
return;
}
- ARDOUR::BundleList current = _route->bundles_connected_to_inputs ();
+ ARDOUR::BundleList current = _route->input()->bundles_connected ();
if (std::find (current.begin(), current.end(), c) == current.end()) {
- _route->connect_input_ports_to_bundle (c, this);
+ _route->input()->connect_ports_to_bundle (c, this);
} else {
- _route->disconnect_input_ports_from_bundle (c, this);
+ _route->input()->disconnect_ports_from_bundle (c, this);
}
}
@@ -833,12 +788,12 @@ MixerStrip::bundle_output_toggled (boost::shared_ptr<ARDOUR::Bundle> c)
return;
}
- ARDOUR::BundleList current = _route->bundles_connected_to_outputs ();
+ ARDOUR::BundleList current = _route->output()->bundles_connected ();
if (std::find (current.begin(), current.end(), c) == current.end()) {
- _route->connect_output_ports_to_bundle (c, this);
+ _route->output()->connect_ports_to_bundle (c, this);
} else {
- _route->disconnect_output_ports_from_bundle (c, this);
+ _route->output()->disconnect_ports_from_bundle (c, this);
}
}
@@ -848,7 +803,7 @@ MixerStrip::maybe_add_bundle_to_input_menu (boost::shared_ptr<Bundle> b, ARDOUR:
using namespace Menu_Helpers;
if (b->ports_are_outputs() == false ||
- route()->default_type() != b->type() ||
+ route()->input()->default_type() != b->type() ||
b->nchannels() != _route->n_inputs().get (b->type ())) {
return;
@@ -874,7 +829,7 @@ MixerStrip::maybe_add_bundle_to_output_menu (boost::shared_ptr<Bundle> b, ARDOUR
using namespace Menu_Helpers;
if (b->ports_are_inputs() == false ||
- route()->default_type() != b->type() ||
+ route()->output()->default_type() != b->type() ||
b->nchannels() != _route->n_outputs().get (b->type ())) {
return;
@@ -938,7 +893,7 @@ MixerStrip::connect_to_pan ()
void
MixerStrip::update_input_display ()
{
- ARDOUR::BundleList const c = _route->bundles_connected_to_inputs ();
+ ARDOUR::BundleList const c = _route->input()->bundles_connected();
if (c.size() > 1) {
input_label.set_text (_("Inputs"));
@@ -960,7 +915,7 @@ MixerStrip::update_input_display ()
void
MixerStrip::update_output_display ()
{
- ARDOUR::BundleList const c = _route->bundles_connected_to_outputs ();
+ ARDOUR::BundleList const c = _route->output()->bundles_connected ();
/* XXX: how do we represent >1 connected bundle? */
if (c.size() > 1) {
@@ -1269,43 +1224,6 @@ MixerStrip::list_route_operations ()
refresh_remote_control_menu();
}
-
-void
-MixerStrip::speed_adjustment_changed ()
-{
- /* since there is a usable speed adjustment, there has to be a diskstream */
- if (!ignore_speed_adjustment) {
- get_diskstream()->set_speed (speed_adjustment.get_value());
- }
-}
-
-void
-MixerStrip::speed_changed ()
-{
- Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &MixerStrip::update_speed_display));
-}
-
-void
-MixerStrip::update_speed_display ()
-{
- float val;
-
- val = get_diskstream()->speed();
-
- if (val != 1.0) {
- speed_spinner.set_name ("MixerStripSpeedBaseNotOne");
- } else {
- speed_spinner.set_name ("MixerStripSpeedBase");
- }
-
- if (speed_adjustment.get_value() != val) {
- ignore_speed_adjustment = true;
- speed_adjustment.set_value (val);
- ignore_speed_adjustment = false;
- }
-}
-
-
void
MixerStrip::set_selected (bool yn)
{
@@ -1383,12 +1301,10 @@ MixerStrip::map_frozen ()
case AudioTrack::Frozen:
pre_processor_box.set_sensitive (false);
post_processor_box.set_sensitive (false);
- speed_spinner.set_sensitive (false);
break;
default:
pre_processor_box.set_sensitive (true);
post_processor_box.set_sensitive (true);
- speed_spinner.set_sensitive (true);
// XXX need some way, maybe, to retoggle redirect editors
break;
}
@@ -1499,8 +1415,6 @@ MixerStrip::meter_changed (void *src)
void
MixerStrip::switch_io (boost::shared_ptr<Route> target)
{
- boost::shared_ptr<IO> to_display;
-
if (_route == target || _route->is_master()) {
/* don't change the display for the target or the master bus */
return;
@@ -1519,22 +1433,28 @@ MixerStrip::switch_io (boost::shared_ptr<Route> target)
return;
}
- if (_current_send) {
- _current_send->set_metering (false);
+ boost::shared_ptr<Send> send;
+
+ if (_current_delivery && (send = boost::dynamic_pointer_cast<Send>(_current_delivery))) {
+ send->set_metering (false);
}
- _current_send = _route->send_for (target);
+ _current_delivery = _route->send_for (target->input());
- if (_current_send) {
- to_display = _current_send->io();
+ if (_current_delivery) {
+ send = boost::dynamic_pointer_cast<Send>(_current_delivery);
+ send->set_metering (true);
+ _current_delivery->GoingAway.connect (mem_fun (*this, &MixerStrip::revert_to_default_display));
+ gain_meter().set_controls (_route, send->meter(), send->amp()->gain_control(), send->amp());
+ panner_ui().set_panner (_current_delivery->panner());
- _current_send->set_metering (true);
- _current_send->GoingAway.connect (mem_fun (*this, &MixerStrip::revert_to_default_display));
+ } else {
+ _current_delivery = _route->main_outs ();
+ gain_meter().set_controls (_route, _route->shared_peak_meter(), _route->gain_control(), _route->amp());
+ panner_ui().set_panner (_route->main_outs()->panner());
}
- gain_meter().set_io (to_display);
gain_meter().setup_meters ();
- panner_ui().set_io (to_display);
panner_ui().setup_pan ();
}
@@ -1544,14 +1464,17 @@ MixerStrip::revert_to_default_display ()
{
show_sends_button->set_active (false);
- if (_current_send) {
- _current_send->set_metering (false);
- _current_send.reset();
+ boost::shared_ptr<Send> send;
+
+ if (_current_delivery && (send = boost::dynamic_pointer_cast<Send>(_current_delivery))) {
+ send->set_metering (false);
}
+
+ _current_delivery = _route->main_outs();
- gain_meter().set_io (_route);
+ gain_meter().set_controls (_route, _route->shared_peak_meter(), _route->gain_control(), _route->amp());
gain_meter().setup_meters ();
- panner_ui().set_io (_route);
+ panner_ui().set_panner (_route->main_outs()->panner());
panner_ui().setup_pan ();
}
diff --git a/gtk2_ardour/mixer_strip.h b/gtk2_ardour/mixer_strip.h
index f0cc4c67c6..43c2e197fd 100644
--- a/gtk2_ardour/mixer_strip.h
+++ b/gtk2_ardour/mixer_strip.h
@@ -242,15 +242,6 @@ class MixerStrip : public RouteUI, public Gtk::EventBox
void route_active_changed ();
- /* speed control (for tracks only) */
-
- Gtk::Adjustment speed_adjustment;
- Gtkmm2ext::ClickBox speed_spinner;
- Gtk::Label speed_label;
- Gtk::Frame speed_frame;
-
- void speed_adjustment_changed ();
- void speed_changed ();
void name_changed ();
void update_speed_display ();
void map_frozen ();
@@ -263,7 +254,7 @@ class MixerStrip : public RouteUI, public Gtk::EventBox
void engine_stopped();
void switch_io (boost::shared_ptr<ARDOUR::Route>);
- boost::shared_ptr<ARDOUR::Send> _current_send;
+ boost::shared_ptr<ARDOUR::Delivery> _current_delivery;
void revert_to_default_display ();
static int scrollbar_height;
diff --git a/gtk2_ardour/panner_ui.cc b/gtk2_ardour/panner_ui.cc
index b35ebe5f22..29c991a995 100644
--- a/gtk2_ardour/panner_ui.cc
+++ b/gtk2_ardour/panner_ui.cc
@@ -25,6 +25,7 @@
#include <gtkmm2ext/barcontroller.h>
#include "midi++/manager.h"
#include "pbd/fastlog.h"
+#include "pbd/stacktrace.h"
#include "ardour_ui.h"
#include "panner_ui.h"
@@ -33,6 +34,7 @@
#include "panner.h"
#include "gui_thread.h"
+#include "ardour/delivery.h"
#include "ardour/session.h"
#include "ardour/panner.h"
#include "ardour/route.h"
@@ -131,13 +133,8 @@ PannerUI::PannerUI (Session& s)
}
void
-PannerUI::set_io (boost::shared_ptr<IO> io)
+PannerUI::set_panner (boost::shared_ptr<Panner> p)
{
- if (io && !io->panner()) {
- cerr << "PannerUI::set_io IO has no panners" << endl;
- return;
- }
-
connections.clear ();
delete pan_astyle_menu;
@@ -146,18 +143,18 @@ PannerUI::set_io (boost::shared_ptr<IO> io)
delete pan_astate_menu;
pan_astate_menu = 0;
- _io = io;
-
+ _panner = p;
+
delete panner;
panner = 0;
- if (!_io) {
+ if (!_panner) {
return;
}
- connections.push_back (_io->panner()->Changed.connect (mem_fun(*this, &PannerUI::panner_changed)));
- connections.push_back (_io->panner()->LinkStateChanged.connect (mem_fun(*this, &PannerUI::update_pan_linkage)));
- connections.push_back (_io->panner()->StateChanged.connect (mem_fun(*this, &PannerUI::update_pan_state)));
+ connections.push_back (_panner->Changed.connect (mem_fun(*this, &PannerUI::panner_changed)));
+ connections.push_back (_panner->LinkStateChanged.connect (mem_fun(*this, &PannerUI::update_pan_linkage)));
+ connections.push_back (_panner->StateChanged.connect (mem_fun(*this, &PannerUI::update_pan_state)));
setup_pan ();
@@ -196,16 +193,16 @@ PannerUI::build_astate_menu ()
}
pan_astate_menu->items().push_back (MenuElem (_("Manual"), bind (
- mem_fun (_io->panner().get(), &Panner::set_automation_state),
+ mem_fun (_panner.get(), &Panner::set_automation_state),
(AutoState) Off)));
pan_astate_menu->items().push_back (MenuElem (_("Play"), bind (
- mem_fun (_io->panner().get(), &Panner::set_automation_state),
+ mem_fun (_panner.get(), &Panner::set_automation_state),
(AutoState) Play)));
pan_astate_menu->items().push_back (MenuElem (_("Write"), bind (
- mem_fun (_io->panner().get(), &Panner::set_automation_state),
+ mem_fun (_panner.get(), &Panner::set_automation_state),
(AutoState) Write)));
pan_astate_menu->items().push_back (MenuElem (_("Touch"), bind (
- mem_fun (_io->panner().get(), &Panner::set_automation_state),
+ mem_fun (_panner.get(), &Panner::set_automation_state),
(AutoState) Touch)));
}
@@ -242,7 +239,7 @@ bool
PannerUI::panning_link_button_release (GdkEventButton* ev)
{
if (!ignore_toggle) {
- _io->panner()->set_linked (!_io->panner()->linked());
+ _panner->set_linked (!_panner->linked());
}
return true;
}
@@ -250,12 +247,12 @@ PannerUI::panning_link_button_release (GdkEventButton* ev)
void
PannerUI::panning_link_direction_clicked()
{
- switch (_io->panner()->link_direction()) {
+ switch (_panner->link_direction()) {
case Panner::SameDirection:
- _io->panner()->set_link_direction (Panner::OppositeDirection);
+ _panner->set_link_direction (Panner::OppositeDirection);
break;
default:
- _io->panner()->set_link_direction (Panner::SameDirection);
+ _panner->set_link_direction (Panner::SameDirection);
break;
}
}
@@ -265,7 +262,7 @@ PannerUI::update_pan_linkage ()
{
ENSURE_GUI_THREAD(mem_fun(*this, &PannerUI::update_pan_linkage));
- bool x = _io->panner()->linked();
+ bool x = _panner->linked();
bool bx = panning_link_button.get_active();
if (x != bx) {
@@ -277,7 +274,7 @@ PannerUI::update_pan_linkage ()
panning_link_direction_button.set_sensitive (x);
- switch (_io->panner()->link_direction()) {
+ switch (_panner->link_direction()) {
case Panner::SameDirection:
panning_link_direction_button.set_image (*(manage (new Image (get_xpm ("forwardblarrow.xpm")))));
break;
@@ -339,11 +336,16 @@ PannerUI::update_pan_state ()
void
PannerUI::setup_pan ()
{
- if (!_io || !_io->panner()) {
+ cerr << "Setup pan for " << _panner->name() << endl;
+ // PBD::stacktrace (cerr, 5);
+
+ if (!_panner) {
return;
}
- uint32_t nouts = _io->n_outputs ().n_audio();
+ uint32_t nouts = _panner->nouts();
+
+ cerr << "\tnouts = " << nouts << endl;
if (nouts == 0 || nouts == 1) {
@@ -364,7 +366,7 @@ PannerUI::setup_pan ()
} else if (nouts == 2) {
vector<Adjustment*>::size_type asz;
- uint32_t npans = _io->panner()->npanners();
+ uint32_t npans = _panner->npanners();
while (!pan_adjustments.empty()) {
delete pan_bars.back();
@@ -381,7 +383,7 @@ PannerUI::setup_pan ()
/* initialize adjustment with 0.0 (L) or 1.0 (R) for the first and second panners,
which serves as a default, otherwise use current value */
- rx = _io->panner()->pan_control( asz)->get_value();
+ rx = _panner->pan_control( asz)->get_value();
if (npans == 1) {
x = 0.5;
@@ -395,20 +397,24 @@ PannerUI::setup_pan ()
pan_adjustments.push_back (new Adjustment (x, 0, 1.0, 0.005, 0.05));
bc = new PannerBar (*pan_adjustments[asz],
- boost::static_pointer_cast<PBD::Controllable>( _io->panner()->pan_control( asz )) );
+ boost::static_pointer_cast<PBD::Controllable>( _panner->pan_control( asz )) );
/* now set adjustment with current value of panner, then connect the signals */
pan_adjustments.back()->set_value(rx);
pan_adjustments.back()->signal_value_changed().connect (bind (mem_fun(*this, &PannerUI::pan_adjustment_changed), (uint32_t) asz));
- _io->panner()->pan_control( asz )->Changed.connect (bind (mem_fun(*this, &PannerUI::pan_value_changed), (uint32_t) asz));
+ _panner->pan_control( asz )->Changed.connect (bind (mem_fun(*this, &PannerUI::pan_value_changed), (uint32_t) asz));
bc->set_name ("PanSlider");
bc->set_shadow_type (Gtk::SHADOW_NONE);
-
- bc->StartGesture.connect (bind (mem_fun (*_io, &IO::start_pan_touch), (uint32_t) asz));
- bc->StopGesture.connect (bind (mem_fun (*_io, &IO::end_pan_touch), (uint32_t) asz));
+
+ boost::shared_ptr<AutomationControl> ac = _panner->pan_control (asz);
+
+ if (asz) {
+ bc->StartGesture.connect (mem_fun (*ac, &AutomationControl::start_touch));
+ bc->StopGesture.connect (mem_fun (*ac, &AutomationControl::stop_touch));
+ }
char buf[64];
snprintf (buf, sizeof (buf), _("panner for channel %zu"), asz + 1);
@@ -437,7 +443,7 @@ PannerUI::setup_pan ()
} else {
if (!panner) {
- panner = new Panner2d (_io->panner(), 61);
+ panner = new Panner2d (_panner, 61);
panner->set_name ("MixerPanZone");
panner->show ();
@@ -446,9 +452,9 @@ PannerUI::setup_pan ()
}
update_pan_sensitive ();
- panner->reset (_io->n_inputs().n_audio());
+ panner->reset (nouts);
if (big_window) {
- big_window->reset (_io->n_inputs().n_audio());
+ big_window->reset (_panner->npanners());
}
panner->set_size_request (-1, 61);
@@ -467,7 +473,7 @@ PannerUI::pan_button_event (GdkEventButton* ev, uint32_t which)
case 1:
if (panner && ev->type == GDK_2BUTTON_PRESS) {
if (!big_window) {
- big_window = new Panner2dWindow (panner->get_panner(), 400, _io->n_inputs().n_audio());
+ big_window = new Panner2dWindow (_panner, 400, _panner->npanners());
}
big_window->show ();
return true;
@@ -502,7 +508,7 @@ PannerUI::build_pan_menu (uint32_t which)
/* set state first, connect second */
- (dynamic_cast<CheckMenuItem*> (&items.back()))->set_active (_io->panner()->streampanner(which).muted());
+ (dynamic_cast<CheckMenuItem*> (&items.back()))->set_active (_panner->streampanner(which).muted());
(dynamic_cast<CheckMenuItem*> (&items.back()))->signal_toggled().connect
(bind (mem_fun(*this, &PannerUI::pan_mute), which));
@@ -511,7 +517,7 @@ PannerUI::build_pan_menu (uint32_t which)
/* set state first, connect second */
- bypass_menu_item->set_active (_io->panner()->bypassed());
+ bypass_menu_item->set_active (_panner->bypassed());
bypass_menu_item->signal_toggled().connect (mem_fun(*this, &PannerUI::pan_bypass_toggle));
items.push_back (MenuElem (_("Reset"), bind (mem_fun (*this, &PannerUI::pan_reset), which)));
@@ -522,38 +528,38 @@ PannerUI::build_pan_menu (uint32_t which)
void
PannerUI::pan_mute (uint32_t which)
{
- StreamPanner& sp = _io->panner()->streampanner(which);
+ StreamPanner& sp = _panner->streampanner(which);
sp.set_muted (!sp.muted());
}
void
PannerUI::pan_bypass_toggle ()
{
- if (bypass_menu_item && (_io->panner()->bypassed() != bypass_menu_item->get_active())) {
- _io->panner()->set_bypassed (!_io->panner()->bypassed());
+ if (bypass_menu_item && (_panner->bypassed() != bypass_menu_item->get_active())) {
+ _panner->set_bypassed (!_panner->bypassed());
}
}
void
PannerUI::pan_reset (uint32_t which)
{
- _io->panner()->reset_streampanner (which);
+ _panner->reset_streampanner (which);
}
void
PannerUI::pan_reset_all ()
{
- _io->panner()->reset_to_default ();
+ _panner->reset_to_default ();
}
void
PannerUI::effective_pan_display ()
{
- if (_io->panner()->empty()) {
+ if (_panner->empty()) {
return;
}
- switch (_io->n_outputs().n_audio()) {
+ switch (_panner->nouts()) {
case 0:
case 1:
/* relax */
@@ -576,7 +582,7 @@ PannerUI::pan_changed (void *src)
return;
}
- switch (_io->panner()->npanners()) {
+ switch (_panner->npanners()) {
case 0:
panning_link_direction_button.set_sensitive (false);
panning_link_button.set_sensitive (false);
@@ -590,7 +596,7 @@ PannerUI::pan_changed (void *src)
panning_link_button.set_sensitive (true);
}
- uint32_t nouts = _io->n_outputs().n_audio();
+ uint32_t nouts = _panner->nouts();
switch (nouts) {
case 0:
@@ -612,11 +618,11 @@ PannerUI::pan_changed (void *src)
void
PannerUI::pan_adjustment_changed (uint32_t which)
{
- if (!in_pan_update && which < _io->panner()->npanners()) {
+ if (!in_pan_update && which < _panner->npanners()) {
float xpos;
float val = pan_adjustments[which]->get_value ();
- xpos = _io->panner()->pan_control( which )->get_value();
+ xpos = _panner->pan_control( which )->get_value();
/* add a kinda-sorta detent for the middle */
@@ -633,7 +639,7 @@ PannerUI::pan_adjustment_changed (uint32_t which)
if (!Panner::equivalent (val, xpos)) {
- _io->panner()->streampanner(which).set_position (val);
+ _panner->streampanner(which).set_position (val);
/* XXX
the panner objects have no access to the session,
so do this here. ick.
@@ -648,11 +654,11 @@ PannerUI::pan_value_changed (uint32_t which)
{
ENSURE_GUI_THREAD (bind (mem_fun(*this, &PannerUI::pan_value_changed), which));
- if (_io->n_outputs().n_audio() > 1 && which < _io->panner()->npanners()) {
+ if (_panner->npanners() > 1 && which < _panner->npanners()) {
float xpos;
float val = pan_adjustments[which]->get_value ();
- _io->panner()->streampanner(which).get_position (xpos);
+ _panner->streampanner(which).get_position (xpos);
if (!Panner::equivalent (val, xpos)) {
in_pan_update = true;
@@ -678,14 +684,14 @@ PannerUI::update_pan_bars (bool only_if_aplay)
float xpos, val;
if (only_if_aplay) {
- boost::shared_ptr<AutomationList> alist (_io->panner()->streampanner(n).pan_control()->alist());
+ boost::shared_ptr<AutomationList> alist (_panner->streampanner(n).pan_control()->alist());
if (!alist->automation_playback()) {
continue;
}
}
- _io->panner()->streampanner(n).get_effective_position (xpos);
+ _panner->streampanner(n).get_effective_position (xpos);
val = (*i)->get_value ();
if (!Panner::equivalent (val, xpos)) {
@@ -699,9 +705,9 @@ PannerUI::update_pan_bars (bool only_if_aplay)
void
PannerUI::update_pan_sensitive ()
{
- bool sensitive = !(_io->panner()->automation_state() & Play);
+ bool sensitive = !(_panner->automation_state() & Play);
- switch (_io->n_outputs().n_audio()) {
+ switch (_panner->nouts()) {
case 0:
case 1:
break;
@@ -771,10 +777,10 @@ PannerUI::pan_automation_style_changed ()
switch (_width) {
case Wide:
- pan_automation_style_button.set_label (astyle_string(_io->panner()->automation_style()));
+ pan_automation_style_button.set_label (astyle_string(_panner->automation_style()));
break;
case Narrow:
- pan_automation_style_button.set_label (short_astyle_string(_io->panner()->automation_style()));
+ pan_automation_style_button.set_label (short_astyle_string(_panner->automation_style()));
break;
}
}
@@ -788,10 +794,10 @@ PannerUI::pan_automation_state_changed ()
switch (_width) {
case Wide:
- pan_automation_state_button.set_label (astate_string(_io->panner()->automation_state()));
+ pan_automation_state_button.set_label (astate_string(_panner->automation_state()));
break;
case Narrow:
- pan_automation_state_button.set_label (short_astate_string(_io->panner()->automation_state()));
+ pan_automation_state_button.set_label (short_astate_string(_panner->automation_state()));
break;
}
@@ -800,11 +806,11 @@ PannerUI::pan_automation_state_changed ()
here.
*/
- if (_io->panner()->empty()) {
+ if (_panner->empty()) {
return;
}
- x = (_io->panner()->streampanner(0).pan_control()->alist()->automation_state() != Off);
+ x = (_panner->streampanner(0).pan_control()->alist()->automation_state() != Off);
if (pan_automation_state_button.get_active() != x) {
ignore_toggle = true;
diff --git a/gtk2_ardour/panner_ui.h b/gtk2_ardour/panner_ui.h
index 602164d7a9..95e1e6c688 100644
--- a/gtk2_ardour/panner_ui.h
+++ b/gtk2_ardour/panner_ui.h
@@ -40,8 +40,9 @@ class PannerBar;
class Panner2dWindow;
namespace ARDOUR {
- class IO;
class Session;
+ class Panner;
+ class Delivery;
}
namespace Gtkmm2ext {
class FastMeter;
@@ -58,7 +59,7 @@ class PannerUI : public Gtk::HBox
PannerUI (ARDOUR::Session&);
~PannerUI ();
- virtual void set_io (boost::shared_ptr<ARDOUR::IO>);
+ virtual void set_panner (boost::shared_ptr<ARDOUR::Panner>);
void pan_changed (void *);
@@ -76,7 +77,7 @@ class PannerUI : public Gtk::HBox
private:
friend class MixerStrip;
- boost::shared_ptr<ARDOUR::IO> _io;
+ boost::shared_ptr<ARDOUR::Panner> _panner;
ARDOUR::Session& _session;
std::vector<sigc::connection> connections;
diff --git a/gtk2_ardour/port_group.cc b/gtk2_ardour/port_group.cc
index 3ff074f9d7..99c4861f79 100644
--- a/gtk2_ardour/port_group.cc
+++ b/gtk2_ardour/port_group.cc
@@ -36,6 +36,7 @@
using namespace std;
using namespace Gtk;
+using namespace ARDOUR;
/** PortGroup constructor.
* @param n Name.
@@ -50,7 +51,7 @@ PortGroup::PortGroup (std::string const & n)
* @param b Bundle.
*/
void
-PortGroup::add_bundle (boost::shared_ptr<ARDOUR::Bundle> b)
+PortGroup::add_bundle (boost::shared_ptr<Bundle> b)
{
assert (b.get());
_bundles.push_back (b);
@@ -62,11 +63,11 @@ PortGroup::add_bundle (boost::shared_ptr<ARDOUR::Bundle> b)
}
void
-PortGroup::remove_bundle (boost::shared_ptr<ARDOUR::Bundle> b)
+PortGroup::remove_bundle (boost::shared_ptr<Bundle> b)
{
assert (b.get());
- ARDOUR::BundleList::iterator i = std::find (_bundles.begin(), _bundles.end(), b);
+ BundleList::iterator i = std::find (_bundles.begin(), _bundles.end(), b);
if (i == _bundles.end()) {
return;
}
@@ -78,7 +79,7 @@ PortGroup::remove_bundle (boost::shared_ptr<ARDOUR::Bundle> b)
}
void
-PortGroup::bundle_changed (ARDOUR::Bundle::Change c)
+PortGroup::bundle_changed (Bundle::Change c)
{
BundleChanged (c);
}
@@ -103,7 +104,7 @@ PortGroup::clear ()
bool
PortGroup::has_port (std::string const& p) const
{
- for (ARDOUR::BundleList::const_iterator i = _bundles.begin(); i != _bundles.end(); ++i) {
+ for (BundleList::const_iterator i = _bundles.begin(); i != _bundles.end(); ++i) {
if ((*i)->offers_port_alone (p)) {
return true;
}
@@ -112,7 +113,7 @@ PortGroup::has_port (std::string const& p) const
return false;
}
-boost::shared_ptr<ARDOUR::Bundle>
+boost::shared_ptr<Bundle>
PortGroup::only_bundle ()
{
assert (_bundles.size() == 1);
@@ -124,7 +125,7 @@ uint32_t
PortGroup::total_channels () const
{
uint32_t n = 0;
- for (ARDOUR::BundleList::const_iterator i = _bundles.begin(); i != _bundles.end(); ++i) {
+ for (BundleList::const_iterator i = _bundles.begin(); i != _bundles.end(); ++i) {
n += (*i)->nchannels ();
}
@@ -135,21 +136,49 @@ PortGroup::total_channels () const
/** PortGroupList constructor.
*/
PortGroupList::PortGroupList ()
- : _type (ARDOUR::DataType::AUDIO), _signals_suspended (false), _pending_change (false)
+ : _type (DataType::AUDIO), _signals_suspended (false), _pending_change (false)
{
}
void
-PortGroupList::set_type (ARDOUR::DataType t)
+PortGroupList::set_type (DataType t)
{
_type = t;
clear ();
}
+void
+PortGroupList::maybe_add_processor_to_bundle (boost::weak_ptr<Processor> wp, boost::shared_ptr<RouteBundle> rb, bool inputs)
+{
+ boost::shared_ptr<Processor> p (wp.lock());
+
+ if (!p) {
+ return;
+ }
+
+ boost::shared_ptr<IOProcessor> iop = boost::dynamic_pointer_cast<IOProcessor> (p);
+
+ if (iop) {
+
+ if (inputs) {
+ if (!iop->output()) {
+ return;
+ }
+ } else {
+ if (!iop->input()) {
+ return;
+ }
+ }
+
+ rb->add_processor_bundle (inputs ? iop->output()->bundle() : iop->input()->bundle());
+ }
+}
+
+
/** Gather bundles from around the system and put them in this PortGroupList */
void
-PortGroupList::gather (ARDOUR::Session& session, bool inputs)
+PortGroupList::gather (Session& session, bool inputs)
{
clear ();
@@ -162,49 +191,28 @@ PortGroupList::gather (ARDOUR::Session& session, bool inputs)
the route's IO bundles and processor bundles together so that they
are presented as one bundle in the matrix. */
- boost::shared_ptr<ARDOUR::RouteList> routes = session.get_routes ();
-
- for (ARDOUR::RouteList::const_iterator i = routes->begin(); i != routes->end(); ++i) {
+ boost::shared_ptr<RouteList> routes = session.get_routes ();
- boost::shared_ptr<RouteBundle> rb (
- new RouteBundle (
- inputs ? (*i)->bundle_for_inputs() : (*i)->bundle_for_outputs()
- )
- );
+ for (RouteList::const_iterator i = routes->begin(); i != routes->end(); ++i) {
- uint32_t n = 0;
- while (1) {
- boost::shared_ptr<ARDOUR::Processor> p = (*i)->nth_processor (n);
- if (p == 0) {
- break;
- }
+ boost::shared_ptr<RouteBundle> rb (new RouteBundle (inputs ? (*i)->output()->bundle() : (*i)->input()->bundle()));
- boost::shared_ptr<ARDOUR::IOProcessor> iop = boost::dynamic_pointer_cast<ARDOUR::IOProcessor> (p);
+ (*i)->foreach_processor (bind (mem_fun (*this, &PortGroupList::maybe_add_processor_to_bundle), rb, inputs));
- if (iop) {
- rb->add_processor_bundle (
- inputs ? iop->io()->bundle_for_inputs() : iop->io()->bundle_for_outputs()
- );
-
- }
-
- ++n;
- }
-
/* Work out which group to put this bundle in */
boost::shared_ptr<PortGroup> g;
- if (_type == ARDOUR::DataType::AUDIO) {
+ if (_type == DataType::AUDIO) {
- if (boost::dynamic_pointer_cast<ARDOUR::AudioTrack> (*i)) {
+ if (boost::dynamic_pointer_cast<AudioTrack> (*i)) {
g = track;
- } else if (!boost::dynamic_pointer_cast<ARDOUR::MidiTrack>(*i)) {
+ } else if (!boost::dynamic_pointer_cast<MidiTrack>(*i)) {
g = bus;
}
- } else if (_type == ARDOUR::DataType::MIDI) {
+ } else if (_type == DataType::MIDI) {
- if (boost::dynamic_pointer_cast<ARDOUR::MidiTrack> (*i)) {
+ if (boost::dynamic_pointer_cast<MidiTrack> (*i)) {
g = track;
}
@@ -219,11 +227,11 @@ PortGroupList::gather (ARDOUR::Session& session, bool inputs)
/* Bundles owned by the session. We only add the mono ones and the User ones
otherwise there is duplication of the same ports within the matrix */
- boost::shared_ptr<ARDOUR::BundleList> b = session.bundles ();
- for (ARDOUR::BundleList::iterator i = b->begin(); i != b->end(); ++i) {
+ boost::shared_ptr<BundleList> b = session.bundles ();
+ for (BundleList::iterator i = b->begin(); i != b->end(); ++i) {
if ((*i)->ports_are_inputs() == inputs && (*i)->type() == _type) {
- if ((*i)->nchannels() == 1 || boost::dynamic_pointer_cast<ARDOUR::UserBundle> (*i)) {
+ if ((*i)->nchannels() == 1 || boost::dynamic_pointer_cast<UserBundle> (*i)) {
system->add_bundle (*i);
}
@@ -282,10 +290,10 @@ PortGroupList::gather (ARDOUR::Session& session, bool inputs)
emit_changed ();
}
-boost::shared_ptr<ARDOUR::Bundle>
+boost::shared_ptr<Bundle>
PortGroupList::make_bundle_from_ports (std::vector<std::string> const & p, bool inputs) const
{
- boost::shared_ptr<ARDOUR::Bundle> b (new ARDOUR::Bundle ("", _type, inputs));
+ boost::shared_ptr<Bundle> b (new Bundle ("", _type, inputs));
std::string const pre = common_prefix (p);
if (!pre.empty()) {
@@ -366,7 +374,7 @@ PortGroupList::clear ()
}
-ARDOUR::BundleList const &
+BundleList const &
PortGroupList::bundles () const
{
_bundles.clear ();
@@ -410,7 +418,7 @@ PortGroupList::add_group (boost::shared_ptr<PortGroup> g)
}
void
-PortGroupList::remove_bundle (boost::shared_ptr<ARDOUR::Bundle> b)
+PortGroupList::remove_bundle (boost::shared_ptr<Bundle> b)
{
for (List::iterator i = _groups.begin(); i != _groups.end(); ++i) {
(*i)->remove_bundle (b);
@@ -446,7 +454,7 @@ PortGroupList::resume_signals ()
_signals_suspended = false;
}
-RouteBundle::RouteBundle (boost::shared_ptr<ARDOUR::Bundle> r)
+RouteBundle::RouteBundle (boost::shared_ptr<Bundle> r)
: _route (r)
{
_route->Changed.connect (sigc::hide (sigc::mem_fun (*this, &RouteBundle::reread_component_bundles)));
@@ -470,7 +478,7 @@ RouteBundle::reread_component_bundles ()
}
}
- for (std::vector<boost::shared_ptr<ARDOUR::Bundle> >::iterator i = _processor.begin(); i != _processor.end(); ++i) {
+ for (std::vector<boost::shared_ptr<Bundle> >::iterator i = _processor.begin(); i != _processor.end(); ++i) {
add_channels_from_bundle (*i);
}
@@ -478,7 +486,7 @@ RouteBundle::reread_component_bundles ()
}
void
-RouteBundle::add_processor_bundle (boost::shared_ptr<ARDOUR::Bundle> p)
+RouteBundle::add_processor_bundle (boost::shared_ptr<Bundle> p)
{
p->Changed.connect (sigc::hide (sigc::mem_fun (*this, &RouteBundle::reread_component_bundles)));
_processor.push_back (p);
diff --git a/gtk2_ardour/port_group.h b/gtk2_ardour/port_group.h
index 02dd965e1d..707cc04966 100644
--- a/gtk2_ardour/port_group.h
+++ b/gtk2_ardour/port_group.h
@@ -31,9 +31,11 @@
namespace ARDOUR {
class Session;
class Bundle;
+ class Processor;
}
class PortMatrix;
+class RouteBundle;
/** A list of bundles and ports, grouped by some aspect of their
* type e.g. busses, tracks, system. Each group has 0 or more bundles
@@ -119,7 +121,8 @@ class PortGroupList : public sigc::trackable
std::string common_prefix_before (std::vector<std::string> const &, std::string const &) const;
void emit_changed ();
boost::shared_ptr<ARDOUR::Bundle> make_bundle_from_ports (std::vector<std::string> const &, bool) const;
-
+ void maybe_add_processor_to_bundle (boost::weak_ptr<ARDOUR::Processor>, boost::shared_ptr<RouteBundle>, bool);
+
ARDOUR::DataType _type;
mutable ARDOUR::BundleList _bundles;
List _groups;
diff --git a/gtk2_ardour/processor_box.cc b/gtk2_ardour/processor_box.cc
index f850582fec..f8ea758549 100644
--- a/gtk2_ardour/processor_box.cc
+++ b/gtk2_ardour/processor_box.cc
@@ -452,7 +452,7 @@ ProcessorBox::use_plugins (const SelectedPlugins& plugins)
}
if (_route->add_processor (processor, _placement, &err_streams)) {
- weird_plugin_dialog (**p, err_streams, _route);
+ weird_plugin_dialog (**p, err_streams);
// XXX SHAREDPTR delete plugin here .. do we even need to care?
} else {
@@ -467,7 +467,7 @@ ProcessorBox::use_plugins (const SelectedPlugins& plugins)
}
void
-ProcessorBox::weird_plugin_dialog (Plugin& p, Route::ProcessorStreams streams, boost::shared_ptr<IO> io)
+ProcessorBox::weird_plugin_dialog (Plugin& p, Route::ProcessorStreams streams)
{
ArdourDialog dialog (_("ardour: weird plugin dialog"));
Label label;
@@ -511,7 +511,7 @@ ProcessorBox::weird_plugin_dialog (Plugin& p, Route::ProcessorStreams streams, b
void
ProcessorBox::choose_insert ()
{
- boost::shared_ptr<Processor> processor (new PortInsert (_session));
+ boost::shared_ptr<Processor> processor (new PortInsert (_session, _route->mute_master()));
processor->ActiveChanged.connect (bind (
mem_fun(*this, &ProcessorBox::show_processor_active),
boost::weak_ptr<Processor>(processor)));
@@ -522,7 +522,7 @@ ProcessorBox::choose_insert ()
void
ProcessorBox::choose_send ()
{
- boost::shared_ptr<Send> send (new Send (_session));
+ boost::shared_ptr<Send> send (new Send (_session, _route->mute_master()));
/* make an educated guess at the initial number of outputs for the send */
ChanCount outs = (_session.master_out())
@@ -531,14 +531,14 @@ ProcessorBox::choose_send ()
/* XXX need processor lock on route */
try {
- send->io()->ensure_io (ChanCount::ZERO, outs, false, this);
+ send->output()->ensure_io (outs, false, this);
} catch (AudioEngine::PortRegistrationFailure& err) {
error << string_compose (_("Cannot set up new send: %1"), err.what()) << endmsg;
return;
}
/* let the user adjust the IO setup before creation */
- IOSelectorWindow *ios = new IOSelectorWindow (_session, send->io(), false, true);
+ IOSelectorWindow *ios = new IOSelectorWindow (_session, send->output(), true);
ios->show_all ();
/* keep a reference to the send so it doesn't get deleted while
@@ -588,14 +588,14 @@ ProcessorBox::choose_return ()
/* XXX need processor lock on route */
try {
- retrn->io()->ensure_io (ins, ChanCount::ZERO, false, this);
+ retrn->input()->ensure_io (ins, false, this);
} catch (AudioEngine::PortRegistrationFailure& err) {
error << string_compose (_("Cannot set up new return: %1"), err.what()) << endmsg;
return;
}
/* let the user adjust the IO setup before creation */
- IOSelectorWindow *ios = new IOSelectorWindow (_session, retrn->io(), true, true);
+ IOSelectorWindow *ios = new IOSelectorWindow (_session, retrn->output(), true);
ios->show_all ();
/* keep a reference to the send so it doesn't get deleted while
@@ -1050,7 +1050,7 @@ ProcessorBox::paste_processor_state (const XMLNodeList& nlist)
if (type->value() == "send") {
XMLNode n (**niter);
Send::make_unique (n, _session);
- p.reset (new Send (_session, n));
+ p.reset (new Send (_session, _route->mute_master(), n));
} else if (type->value() == "meter") {
p = _route->shared_peak_meter();
@@ -1064,7 +1064,7 @@ ProcessorBox::paste_processor_state (const XMLNodeList& nlist)
continue;
} else if (type->value() == "listen") {
- p.reset (new Delivery (_session, **niter));
+ p.reset (new Delivery (_session, _route->mute_master(), **niter));
} else {
p.reset (new PluginInsert (_session, **niter));
@@ -1214,8 +1214,8 @@ ProcessorBox::edit_processor (boost::shared_ptr<Processor> processor)
gidget = send_ui;
#else
if (_parent_strip) {
- _parent_strip->gain_meter().set_io (send->io());
- _parent_strip->panner_ui().set_io (send->io());
+ _parent_strip->gain_meter().set_controls (_route, send->meter(), send->amp()->gain_control(), send->amp());
+ _parent_strip->panner_ui().set_panner (send->panner());
}
#endif
diff --git a/gtk2_ardour/processor_box.h b/gtk2_ardour/processor_box.h
index d53d05fe23..985c8a1177 100644
--- a/gtk2_ardour/processor_box.h
+++ b/gtk2_ardour/processor_box.h
@@ -205,7 +205,7 @@ class ProcessorBox : public Gtk::HBox, public PluginInterestedObject
gint idle_delete_processor (boost::weak_ptr<ARDOUR::Processor>);
- void weird_plugin_dialog (ARDOUR::Plugin& p, ARDOUR::Route::ProcessorStreams streams, boost::shared_ptr<ARDOUR::IO> io);
+ void weird_plugin_dialog (ARDOUR::Plugin& p, ARDOUR::Route::ProcessorStreams streams);
static ProcessorBox* _current_processor_box;
static bool enter_box (GdkEventCrossing*, ProcessorBox*);
diff --git a/gtk2_ardour/return_ui.cc b/gtk2_ardour/return_ui.cc
index ac06529d38..155a1095c1 100644
--- a/gtk2_ardour/return_ui.cc
+++ b/gtk2_ardour/return_ui.cc
@@ -19,6 +19,7 @@
#include <gtkmm2ext/doi.h>
+#include "ardour/amp.h"
#include "ardour/io.h"
#include "ardour/return.h"
@@ -37,7 +38,7 @@ ReturnUI::ReturnUI (boost::shared_ptr<Return> r, Session& se)
, _session (se)
, _gpm (se)
{
- _gpm.set_io (r->io());
+ _gpm.set_controls (boost::shared_ptr<Route>(), r->meter(), r->amp()->gain_control(), r->amp());
_hbox.pack_start (_gpm, true, true);
set_name ("ReturnUIFrame");
@@ -47,7 +48,7 @@ ReturnUI::ReturnUI (boost::shared_ptr<Return> r, Session& se)
_vbox.pack_start (_hbox, false, false, false);
- io = manage (new IOSelector (se, r->io(), true));
+ io = manage (new IOSelector (se, r->output()));
pack_start (_vbox, false, false);
@@ -55,21 +56,19 @@ ReturnUI::ReturnUI (boost::shared_ptr<Return> r, Session& se)
show_all ();
- //_return->set_metering (true);
-
- _return->io()->input_changed.connect (mem_fun (*this, &ReturnUI::ins_changed));
- //_return->io()->output_changed.connect (mem_fun (*this, &ReturnUI::outs_changed));
+ _return->set_metering (true);
+ _return->input()->changed.connect (mem_fun (*this, &ReturnUI::ins_changed));
_gpm.setup_meters ();
_gpm.set_fader_name ("ReturnUIFrame");
-
+
// screen_update_connection = ARDOUR_UI::instance()->RapidScreenUpdate.connect (mem_fun (*this, &ReturnUI::update));
fast_screen_update_connection = ARDOUR_UI::instance()->SuperRapidScreenUpdate.connect (mem_fun (*this, &ReturnUI::fast_update));
}
ReturnUI::~ReturnUI ()
{
- //_return->set_metering (false);
+ _return->set_metering (false);
/* XXX not clear that we need to do this */
@@ -111,12 +110,8 @@ ReturnUIWindow::ReturnUIWindow (boost::shared_ptr<Return> s, Session& ss)
set_name ("ReturnUIWindow");
- going_away_connection = s->GoingAway.connect (
- mem_fun (*this, &ReturnUIWindow::return_going_away));
-
- signal_delete_event().connect (bind (
- sigc::ptr_fun (just_hide_it),
- reinterpret_cast<Window *> (this)));
+ going_away_connection = s->GoingAway.connect (mem_fun (*this, &ReturnUIWindow::return_going_away));
+ signal_delete_event().connect (bind (sigc::ptr_fun (just_hide_it), reinterpret_cast<Window *> (this)));
}
ReturnUIWindow::~ReturnUIWindow ()
diff --git a/gtk2_ardour/route_params_ui.cc b/gtk2_ardour/route_params_ui.cc
index 5c709d80bf..d2fc106c42 100644
--- a/gtk2_ardour/route_params_ui.cc
+++ b/gtk2_ardour/route_params_ui.cc
@@ -298,7 +298,7 @@ RouteParams_UI::cleanup_latency_frame ()
void
RouteParams_UI::setup_latency_frame ()
{
- latency_widget = new LatencyGUI (*(_route.get()), session->frame_rate(), session->engine().frames_per_cycle());
+ latency_widget = new LatencyGUI (*(_route->output()), session->frame_rate(), session->engine().frames_per_cycle());
char buf[128];
snprintf (buf, sizeof (buf), _("Playback delay: %u samples"), _route->initial_delay());
@@ -322,13 +322,13 @@ RouteParams_UI::setup_io_frames()
cleanup_io_frames();
// input
- _input_iosel = new IOSelector (*session, _route, false);
+ _input_iosel = new IOSelector (*session, _route->input());
_input_iosel->setup ();
input_frame.add (*_input_iosel);
input_frame.show_all();
// output
- _output_iosel = new IOSelector (*session, _route, true);
+ _output_iosel = new IOSelector (*session, _route->output());
_output_iosel->setup ();
output_frame.add (*_output_iosel);
output_frame.show_all();
diff --git a/gtk2_ardour/route_time_axis.cc b/gtk2_ardour/route_time_axis.cc
index df85cf69a4..715a70b1d3 100644
--- a/gtk2_ardour/route_time_axis.cc
+++ b/gtk2_ardour/route_time_axis.cc
@@ -40,6 +40,7 @@
#include <gtkmm2ext/bindable_button.h>
#include <gtkmm2ext/utils.h>
+#include "ardour/amp.h"
#include "ardour/audioplaylist.h"
#include "ardour/diskstream.h"
#include "ardour/event_type_map.h"
@@ -110,7 +111,7 @@ RouteTimeAxisView::RouteTimeAxisView (PublicEditor& ed, Session& sess, boost::sh
visual_button (_("v")),
gm (sess, slider, true)
{
- gm.set_io (rt);
+ gm.set_controls (_route, _route->shared_peak_meter(), _route->gain_control(), _route->amp());
gm.get_level_meter().set_no_show_all();
gm.get_level_meter().setup_meters(50);
@@ -187,8 +188,8 @@ RouteTimeAxisView::RouteTimeAxisView (PublicEditor& ed, Session& sess, boost::sh
controls_hbox.pack_start(gm.get_level_meter(), false, false);
_route->meter_change.connect (mem_fun(*this, &RouteTimeAxisView::meter_changed));
- _route->input_changed.connect (mem_fun(*this, &RouteTimeAxisView::io_changed));
- _route->output_changed.connect (mem_fun(*this, &RouteTimeAxisView::io_changed));
+ _route->input()->changed.connect (mem_fun(*this, &RouteTimeAxisView::io_changed));
+ _route->output()->changed.connect (mem_fun(*this, &RouteTimeAxisView::io_changed));
controls_table.attach (*mute_button, 6, 7, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND, 0, 0);
controls_table.attach (*solo_button, 7, 8, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND, 0, 0);
@@ -231,7 +232,7 @@ RouteTimeAxisView::RouteTimeAxisView (PublicEditor& ed, Session& sess, boost::sh
_route->solo_changed.connect (mem_fun(*this, &RouteUI::solo_changed));
_route->processors_changed.connect (mem_fun(*this, &RouteTimeAxisView::processors_changed));
_route->NameChanged.connect (mem_fun(*this, &RouteTimeAxisView::route_name_changed));
- _route->solo_safe_changed.connect (mem_fun(*this, &RouteUI::solo_changed));
+ _route->solo_isolated_changed.connect (mem_fun(*this, &RouteUI::solo_changed));
if (is_track()) {
diff --git a/gtk2_ardour/route_ui.cc b/gtk2_ardour/route_ui.cc
index 393ab011f3..b62229a70c 100644
--- a/gtk2_ardour/route_ui.cc
+++ b/gtk2_ardour/route_ui.cc
@@ -101,7 +101,6 @@ RouteUI::init ()
ignore_toggle = false;
wait_for_release = false;
route_active_menu_item = 0;
- was_solo_safe = false;
polarity_menu_item = 0;
denormal_menu_item = 0;
multiple_mute_change = false;
@@ -192,7 +191,7 @@ RouteUI::set_route (boost::shared_ptr<Route> rp)
connections.push_back (_route->active_changed.connect (mem_fun (*this, &RouteUI::route_active_changed)));
connections.push_back (_route->mute_changed.connect (mem_fun(*this, &RouteUI::mute_changed)));
connections.push_back (_route->solo_changed.connect (mem_fun(*this, &RouteUI::solo_changed)));
- connections.push_back (_route->solo_safe_changed.connect (mem_fun(*this, &RouteUI::solo_changed)));
+ connections.push_back (_route->solo_isolated_changed.connect (mem_fun(*this, &RouteUI::solo_changed)));
if (is_track()) {
boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
@@ -396,7 +395,7 @@ RouteUI::solo_press(GdkEventButton* ev)
Config->set_solo_latched (false);
}
} else {
- _route->set_solo_safe (!_route->solo_safe(), this);
+ _route->set_solo_isolated (!_route->solo_isolated(), this);
wait_for_release = false;
}
@@ -621,7 +620,7 @@ RouteUI::update_solo_display ()
ignore_toggle = false;
}
- if (_route->solo_safe()) {
+ if (_route->solo_isolated()) {
solo_button->set_visual_state (2);
} else if (_route->soloed()) {
solo_button->set_visual_state (1);
@@ -663,8 +662,7 @@ RouteUI::update_mute_display ()
if (Config->get_show_solo_mutes()) {
if (_route->muted()) {
mute_button->set_visual_state (2);
- } else if (!_route->soloed() && _route->solo_muted()) {
-
+ } else if (!_route->soloed() && _session.soloing()) {
mute_button->set_visual_state (1);
} else {
mute_button->set_visual_state (0);
@@ -804,10 +802,10 @@ RouteUI::build_solo_menu (void)
MenuList& items = solo_menu->items();
CheckMenuItem* check;
- check = new CheckMenuItem(_("Solo Lock"));
- check->set_active (_route->solo_safe());
- check->signal_toggled().connect (bind (mem_fun (*this, &RouteUI::toggle_solo_safe), check));
- _route->solo_safe_changed.connect(bind (mem_fun (*this, &RouteUI::solo_safe_toggle), check));
+ check = new CheckMenuItem(_("Solo Isolate"));
+ check->set_active (_route->solo_isolated());
+ check->signal_toggled().connect (bind (mem_fun (*this, &RouteUI::toggle_solo_isolated), check));
+ _route->solo_isolated_changed.connect(bind (mem_fun (*this, &RouteUI::solo_isolated_toggle), check));
items.push_back (CheckMenuElem(*check));
check->show_all();
@@ -823,9 +821,11 @@ RouteUI::build_mute_menu(void)
mute_menu = new Menu;
mute_menu->set_name ("ArdourContextMenu");
+
+#if FIX_ME_IN_3_0
MenuList& items = mute_menu->items();
CheckMenuItem* check;
-
+
check = new CheckMenuItem(_("Pre Fader"));
init_mute_menu(PRE_FADER, check);
check->signal_toggled().connect(bind (mem_fun (*this, &RouteUI::toggle_mute_menu), PRE_FADER, check));
@@ -853,29 +853,27 @@ RouteUI::build_mute_menu(void)
_route->main_outs_changed.connect(bind (mem_fun (*this, &RouteUI::main_outs_toggle), check));
items.push_back (CheckMenuElem(*check));
check->show_all();
-
+#endif
//items.push_back (SeparatorElem());
// items.push_back (MenuElem (_("MIDI Bind"), mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
}
void
-RouteUI::init_mute_menu(mute_type type, CheckMenuItem* check)
+RouteUI::init_mute_menu(MuteMaster::MutePoint mp, CheckMenuItem* check)
{
- if (_route->get_mute_config (type)) {
- check->set_active (true);
- }
+ check->set_active (_route->mute_master()->muted_at (mp));
}
void
-RouteUI::toggle_mute_menu(mute_type type, Gtk::CheckMenuItem* check)
+RouteUI::toggle_mute_menu(MuteMaster::MutePoint mp, Gtk::CheckMenuItem* check)
{
- _route->set_mute_config(type, check->get_active(), this);
+ // _route->set_mute_config(type, check->get_active(), this);
}
void
-RouteUI::toggle_solo_safe (Gtk::CheckMenuItem* check)
+RouteUI::toggle_solo_isolated (Gtk::CheckMenuItem* check)
{
- _route->set_solo_safe (check->get_active(), this);
+ _route->set_solo_isolated (check->get_active(), this);
}
void
@@ -1166,16 +1164,17 @@ RouteUI::denormal_protection_changed ()
/* no signal for this yet */
}
-
void
-RouteUI::solo_safe_toggle(void* src, Gtk::CheckMenuItem* check)
+RouteUI::solo_isolated_toggle(void* src, Gtk::CheckMenuItem* check)
{
- bool yn = _route->solo_safe ();
+ bool yn = _route->solo_isolated ();
if (check->get_active() != yn) {
check->set_active (yn);
}
}
+
+#ifdef FIX_THIS_FOR_3_0
void
RouteUI::pre_fader_toggle(void* src, Gtk::CheckMenuItem* check)
{
@@ -1219,17 +1218,18 @@ RouteUI::main_outs_toggle(void* src, Gtk::CheckMenuItem* check)
check->set_active (yn);
}
}
+#endif
void
RouteUI::disconnect_input ()
{
- _route->disconnect_inputs (this);
+ _route->input()->disconnect (this);
}
void
RouteUI::disconnect_output ()
{
- _route->disconnect_outputs (this);
+ _route->output()->disconnect (this);
}
bool
@@ -1308,7 +1308,7 @@ RouteUI::map_frozen ()
void
RouteUI::adjust_latency ()
{
- LatencyDialog dialog (_route->name() + _("latency"), *(_route.get()), _session.frame_rate(), _session.engine().frames_per_cycle());
+ LatencyDialog dialog (_route->name() + _("latency"), *(_route->output()), _session.frame_rate(), _session.engine().frames_per_cycle());
}
void
diff --git a/gtk2_ardour/route_ui.h b/gtk2_ardour/route_ui.h
index de8d7ea30c..fc6ef87f57 100644
--- a/gtk2_ardour/route_ui.h
+++ b/gtk2_ardour/route_ui.h
@@ -24,6 +24,7 @@
#include "pbd/xml++.h"
#include "ardour/ardour.h"
+#include "ardour/mute_master.h"
#include "ardour/route.h"
#include "ardour/track.h"
@@ -125,17 +126,17 @@ class RouteUI : public virtual AxisView
void build_remote_control_menu (void);
void refresh_remote_control_menu ();
- void solo_safe_toggle (void*, Gtk::CheckMenuItem*);
- void toggle_solo_safe (Gtk::CheckMenuItem*);
+ void solo_isolated_toggle (void*, Gtk::CheckMenuItem*);
+ void toggle_solo_isolated (Gtk::CheckMenuItem*);
- void toggle_mute_menu(ARDOUR::mute_type, Gtk::CheckMenuItem*);
+ void toggle_mute_menu(ARDOUR::MuteMaster::MutePoint, Gtk::CheckMenuItem*);
void pre_fader_toggle(void*, Gtk::CheckMenuItem*);
void post_fader_toggle(void*, Gtk::CheckMenuItem*);
void control_outs_toggle(void*, Gtk::CheckMenuItem*);
void main_outs_toggle(void*, Gtk::CheckMenuItem*);
void build_mute_menu(void);
- void init_mute_menu(ARDOUR::mute_type, Gtk::CheckMenuItem*);
+ void init_mute_menu(ARDOUR::MuteMaster::MutePoint, Gtk::CheckMenuItem*);
void set_mix_group_solo(boost::shared_ptr<ARDOUR::Route>, bool);
void set_mix_group_mute(boost::shared_ptr<ARDOUR::Route>, bool);
@@ -169,7 +170,6 @@ class RouteUI : public virtual AxisView
virtual void update_rec_display ();
void update_mute_display ();
- bool was_solo_safe;
void update_solo_display ();
virtual void map_frozen ();
diff --git a/gtk2_ardour/send_ui.cc b/gtk2_ardour/send_ui.cc
index 672d5f3d20..19baaa7f93 100644
--- a/gtk2_ardour/send_ui.cc
+++ b/gtk2_ardour/send_ui.cc
@@ -19,6 +19,7 @@
#include <gtkmm2ext/doi.h>
+#include "ardour/amp.h"
#include "ardour/io.h"
#include "ardour/send.h"
@@ -38,8 +39,8 @@ SendUI::SendUI (boost::shared_ptr<Send> s, Session& se)
, _gpm (se)
, _panners (se)
{
- _panners.set_io (s->io());
- _gpm.set_io (s->io());
+ _panners.set_panner (s->panner());
+ _gpm.set_controls (boost::shared_ptr<Route>(), s->meter(), s->amp()->gain_control(), s->amp());
_hbox.pack_start (_gpm, true, true);
set_name ("SendUIFrame");
@@ -50,7 +51,7 @@ SendUI::SendUI (boost::shared_ptr<Send> s, Session& se)
_vbox.pack_start (_hbox, false, false, false);
_vbox.pack_start (_panners, false,false);
- io = manage (new IOSelector (se, s->io(), true));
+ io = manage (new IOSelector (se, s->output()));
pack_start (_vbox, false, false);
@@ -60,8 +61,8 @@ SendUI::SendUI (boost::shared_ptr<Send> s, Session& se)
_send->set_metering (true);
- _send->io()->input_changed.connect (mem_fun (*this, &SendUI::ins_changed));
- _send->io()->output_changed.connect (mem_fun (*this, &SendUI::outs_changed));
+ _send->input()->changed.connect (mem_fun (*this, &SendUI::ins_changed));
+ _send->output()->changed.connect (mem_fun (*this, &SendUI::outs_changed));
_panners.set_width (Wide);
_panners.setup_pan ();
diff --git a/gtk2_ardour/session_option_editor.cc b/gtk2_ardour/session_option_editor.cc
index 76c8a85b88..09138f428e 100644
--- a/gtk2_ardour/session_option_editor.cc
+++ b/gtk2_ardour/session_option_editor.cc
@@ -25,12 +25,12 @@ public:
void setup_ports (int dim)
{
- cerr << _session.the_auditioner()->outputs().num_ports() << "\n";
+ cerr << _session.the_auditioner()->output()->n_ports() << "\n";
if (dim == OURS) {
_port_group->clear ();
- _port_group->add_bundle (_session.click_io()->bundle_for_outputs());
- _port_group->add_bundle (_session.the_auditioner()->bundle_for_outputs());
+ _port_group->add_bundle (_session.click_io()->bundle());
+ _port_group->add_bundle (_session.the_auditioner()->output()->bundle());
} else {
_ports[OTHER].gather (_session, true);
}
@@ -41,7 +41,7 @@ public:
Bundle::PortList const & our_ports = c[OURS].bundle->channel_ports (c[OURS].channel);
Bundle::PortList const & other_ports = c[OTHER].bundle->channel_ports (c[OTHER].channel);
- if (c[OURS].bundle == _session.click_io()->bundle_for_outputs()) {
+ if (c[OURS].bundle == _session.click_io()->bundle()) {
for (ARDOUR::Bundle::PortList::const_iterator i = our_ports.begin(); i != our_ports.end(); ++i) {
for (ARDOUR::Bundle::PortList::const_iterator j = other_ports.begin(); j != other_ports.end(); ++j) {
@@ -50,9 +50,9 @@ public:
assert (f);
if (s) {
- _session.click_io()->connect_output (f, *j, 0);
+ _session.click_io()->connect (f, *j, 0);
} else {
- _session.click_io()->disconnect_output (f, *j, 0);
+ _session.click_io()->disconnect (f, *j, 0);
}
}
}
@@ -64,7 +64,7 @@ public:
Bundle::PortList const & our_ports = c[OURS].bundle->channel_ports (c[OURS].channel);
Bundle::PortList const & other_ports = c[OTHER].bundle->channel_ports (c[OTHER].channel);
- if (c[OURS].bundle == _session.click_io()->bundle_for_outputs()) {
+ if (c[OURS].bundle == _session.click_io()->bundle()) {
for (ARDOUR::Bundle::PortList::const_iterator i = our_ports.begin(); i != our_ports.end(); ++i) {
for (ARDOUR::Bundle::PortList::const_iterator j = other_ports.begin(); j != other_ports.end(); ++j) {
diff --git a/gtk2_ardour/sfdb_ui.cc b/gtk2_ardour/sfdb_ui.cc
index 98dd328f55..cc9d09b654 100644
--- a/gtk2_ardour/sfdb_ui.cc
+++ b/gtk2_ardour/sfdb_ui.cc
@@ -39,6 +39,7 @@
#include "evoral/SMF.hpp"
+#include "ardour/amp.h"
#include "ardour/audio_library.h"
#include "ardour/auditioner.h"
#include "ardour/audioregion.h"
@@ -594,7 +595,10 @@ SoundFileBrowser::add_gain_meter ()
delete gm;
gm = new GainMeter (*session);
- gm->set_io (session->the_auditioner());
+
+ boost::shared_ptr<Route> r = session->the_auditioner ();
+
+ gm->set_controls (r, r->shared_peak_meter(), r->gain_control(), r->amp());
meter_packer.set_border_width (12);
meter_packer.pack_start (*gm, false, true);
diff --git a/libs/ardour/SConscript b/libs/ardour/SConscript
index edba74d117..eb45aad25d 100644
--- a/libs/ardour/SConscript
+++ b/libs/ardour/SConscript
@@ -118,6 +118,7 @@ midi_stretch.cc
midi_track.cc
mix.cc
mtc_slave.cc
+mute_master.cc
named_selection.cc
onset_detector.cc
panner.cc
diff --git a/libs/ardour/amp.cc b/libs/ardour/amp.cc
index 591fcd8569..755dc8b821 100644
--- a/libs/ardour/amp.cc
+++ b/libs/ardour/amp.cc
@@ -19,24 +19,31 @@
#include <cstring>
#include <cmath>
#include <algorithm>
+
+#include "evoral/Curve.hpp"
+
#include "ardour/amp.h"
#include "ardour/audio_buffer.h"
#include "ardour/buffer_set.h"
#include "ardour/configuration.h"
#include "ardour/io.h"
+#include "ardour/mute_master.h"
#include "ardour/session.h"
-namespace ARDOUR {
+#include "i18n.h"
+
+using namespace ARDOUR;
-Amp::Amp(Session& s, IO& io)
+Amp::Amp(Session& s, boost::shared_ptr<MuteMaster> mm)
: Processor(s, "Amp")
- , _io(io)
- , _mute(false)
, _apply_gain(true)
, _apply_gain_automation(false)
, _current_gain(1.0)
- , _desired_gain(1.0)
+ , _mute_master (mm)
{
+ boost::shared_ptr<AutomationList> gl(new AutomationList(Evoral::Parameter(GainAutomation)));
+ _gain_control = boost::shared_ptr<GainControl>( new GainControl(X_("gaincontrol"), s, this, Evoral::Parameter(GainAutomation), gl ));
+ add_control(_gain_control);
}
bool
@@ -59,64 +66,92 @@ Amp::configure_io (ChanCount in, ChanCount out)
void
Amp::run_in_place (BufferSet& bufs, sframes_t start_frame, sframes_t end_frame, nframes_t nframes)
{
- gain_t* gab = _session.gain_automation_buffer();
+ gain_t mute_gain;
- if (_mute && !bufs.is_silent()) {
- Amp::apply_gain (bufs, nframes, _current_mute_gain, _desired_mute_gain, false);
- if (_desired_mute_gain == 0.0f) {
- bufs.is_silent(true);
- }
+ if (_mute_master) {
+ mute_gain = _mute_master->mute_gain_at (MuteMaster::PreFader);
+ } else {
+ mute_gain = 1.0;
}
if (_apply_gain) {
if (_apply_gain_automation) {
- if (_io.phase_invert()) {
+ gain_t* gab = _session.gain_automation_buffer ();
+
+ if (mute_gain == 0.0) {
+
+ /* absolute mute */
+
+ if (_current_gain == 0.0) {
+
+ /* already silent */
+
+ for (BufferSet::audio_iterator i = bufs.audio_begin(); i != bufs.audio_end(); ++i) {
+ i->clear ();
+ }
+ } else {
+
+ /* cut to silence */
+
+ Amp::apply_gain (bufs, nframes, _current_gain, 0.0);
+ _current_gain = 0.0;
+ }
+
+
+ } else if (mute_gain != 1.0) {
+
+ /* mute dimming */
+
for (BufferSet::audio_iterator i = bufs.audio_begin(); i != bufs.audio_end(); ++i) {
Sample* const sp = i->data();
for (nframes_t nx = 0; nx < nframes; ++nx) {
- sp[nx] *= -gab[nx];
+ sp[nx] *= gab[nx] * mute_gain;
}
}
+
+ _current_gain = gab[nframes-1] * mute_gain;
+
} else {
+
+ /* no mute */
+
for (BufferSet::audio_iterator i = bufs.audio_begin(); i != bufs.audio_end(); ++i) {
Sample* const sp = i->data();
for (nframes_t nx = 0; nx < nframes; ++nx) {
sp[nx] *= gab[nx];
}
}
+
+ _current_gain = gab[nframes-1];
}
+
} else { /* manual (scalar) gain */
+
+ gain_t dg = _gain_control->user_float() * mute_gain;
- if (_current_gain != _desired_gain) {
+ if (_current_gain != dg) {
- Amp::apply_gain (bufs, nframes, _current_gain, _desired_gain, _io.phase_invert());
- _current_gain = _desired_gain;
+ Amp::apply_gain (bufs, nframes, _current_gain, dg);
+ _current_gain = dg;
- } else if (_current_gain != 0.0f && (_io.phase_invert() || _current_gain != 1.0f)) {
+ } else if ((_current_gain != 0.0f) && (_current_gain != 1.0f)) {
- /* no need to interpolate current gain value,
- but its non-unity, so apply it. if the gain
- is zero, do nothing because we'll ship silence
- below.
+ /* gain has not changed, but its non-unity, so apply it unless
+ its zero.
*/
- gain_t this_gain;
-
- if (_io.phase_invert()) {
- this_gain = -_current_gain;
- } else {
- this_gain = _current_gain;
- }
-
for (BufferSet::audio_iterator i = bufs.audio_begin(); i != bufs.audio_end(); ++i) {
Sample* const sp = i->data();
- apply_gain_to_buffer(sp, nframes, this_gain);
+ apply_gain_to_buffer(sp, nframes, _current_gain);
}
} else if (_current_gain == 0.0f) {
+
+ /* silence! */
+
for (BufferSet::audio_iterator i = bufs.audio_begin(); i != bufs.audio_end(); ++i) {
i->clear();
}
@@ -125,30 +160,19 @@ Amp::run_in_place (BufferSet& bufs, sframes_t start_frame, sframes_t end_frame,
}
}
-/** Apply a declicked gain to the audio buffers of @a bufs */
void
-Amp::apply_gain (BufferSet& bufs, nframes_t nframes,
- gain_t initial, gain_t target, bool invert_polarity)
+Amp::apply_gain (BufferSet& bufs, nframes_t nframes, gain_t initial, gain_t target)
{
- if (nframes == 0) {
- return;
- }
-
- if (bufs.count().n_audio() == 0) {
+ /** Apply a (potentially) declicked gain to the audio buffers of @a bufs
+ */
+
+ if (nframes == 0 || bufs.count().n_audio() == 0) {
return;
}
// if we don't need to declick, defer to apply_simple_gain
if (initial == target) {
- if (target == 0.0) {
- for (BufferSet::audio_iterator i = bufs.audio_begin(); i != bufs.audio_end(); ++i) {
- memset (i->data(), 0, sizeof (Sample) * nframes);
- }
- } else if (target != 1.0) {
- for (BufferSet::audio_iterator i = bufs.audio_begin(); i != bufs.audio_end(); ++i) {
- apply_gain_to_buffer (i->data(), nframes, target);
- }
- }
+ apply_simple_gain (bufs, nframes, target);
return;
}
@@ -156,7 +180,7 @@ Amp::apply_gain (BufferSet& bufs, nframes_t nframes,
gain_t delta;
double fractional_shift = -1.0/declick;
double fractional_pos;
- gain_t polscale = invert_polarity ? -1.0f : 1.0f;
+ gain_t polscale = 1.0f;
if (target < initial) {
/* fade out: remove more and more of delta from initial */
@@ -180,10 +204,6 @@ Amp::apply_gain (BufferSet& bufs, nframes_t nframes,
if (declick != nframes) {
- if (invert_polarity) {
- target = -target;
- }
-
if (target == 0.0) {
memset (&buffer[declick], 0, sizeof (Sample) * (nframes - declick));
} else if (target != 1.0) {
@@ -196,6 +216,62 @@ Amp::apply_gain (BufferSet& bufs, nframes_t nframes,
void
Amp::apply_simple_gain (BufferSet& bufs, nframes_t nframes, gain_t target)
{
+ if (target == 0.0) {
+ for (BufferSet::audio_iterator i = bufs.audio_begin(); i != bufs.audio_end(); ++i) {
+ memset (i->data(), 0, sizeof (Sample) * nframes);
+ }
+ } else if (target != 1.0) {
+ for (BufferSet::audio_iterator i = bufs.audio_begin(); i != bufs.audio_end(); ++i) {
+ apply_gain_to_buffer (i->data(), nframes, target);
+ }
+ }
+}
+
+void
+Amp::inc_gain (gain_t factor, void *src)
+{
+ float desired_gain = _gain_control->user_float();
+ if (desired_gain == 0.0f) {
+ set_gain (0.000001f + (0.000001f * factor), src);
+ } else {
+ set_gain (desired_gain + (desired_gain * factor), src);
+ }
+}
+
+void
+Amp::set_gain (gain_t val, void *src)
+{
+ // max gain at about +6dB (10.0 ^ ( 6 dB * 0.05))
+ if (val > 1.99526231f) {
+ val = 1.99526231f;
+ }
+
+ //cerr << "set desired gain to " << val << " when curgain = " << _gain_control->get_value () << endl;
+
+ if (src != _gain_control.get()) {
+ _gain_control->set_value(val);
+ // bit twisty, this will come back and call us again
+ // (this keeps control in sync with reality)
+ return;
+ }
+
+ {
+ // Glib::Mutex::Lock dm (declick_lock);
+ _gain_control->set_float(val, false);
+ }
+
+ if (_session.transport_stopped()) {
+ // _gain = val;
+ }
+
+ /*
+ if (_session.transport_stopped() && src != 0 && src != this && _gain_control->automation_write()) {
+ _gain_control->list()->add (_session.transport_frame(), val);
+
+ }
+ */
+
+ _session.set_dirty();
}
XMLNode&
@@ -206,4 +282,33 @@ Amp::state (bool full_state)
return node;
}
-} // namespace ARDOUR
+void
+Amp::GainControl::set_value (float val)
+{
+ // max gain at about +6dB (10.0 ^ ( 6 dB * 0.05))
+ if (val > 1.99526231f)
+ val = 1.99526231f;
+
+ _amp->set_gain (val, this);
+
+ AutomationControl::set_value(val);
+}
+
+float
+Amp::GainControl::get_value (void) const
+{
+ return AutomationControl::get_value();
+}
+
+void
+Amp::setup_gain_automation (sframes_t start_frame, sframes_t end_frame, nframes_t nframes)
+{
+ Glib::Mutex::Lock am (data().control_lock(), Glib::TRY_LOCK);
+
+ if (am.locked() && _session.transport_rolling() && _gain_control->automation_playback()) {
+ _apply_gain_automation = _gain_control->list()->curve().rt_safe_get_vector (
+ start_frame, end_frame, _session.gain_automation_buffer(), nframes);
+ } else {
+ _apply_gain_automation = false;
+ }
+}
diff --git a/libs/ardour/ardour/amp.h b/libs/ardour/ardour/amp.h
index 152b89a431..03cc3d02f7 100644
--- a/libs/ardour/ardour/amp.h
+++ b/libs/ardour/ardour/amp.h
@@ -22,19 +22,20 @@
#include "ardour/types.h"
#include "ardour/chan_count.h"
#include "ardour/processor.h"
+#include "ardour/automation_control.h"
namespace ARDOUR {
class BufferSet;
class IO;
-
+class MuteMaster;
/** Applies a declick operation to all audio inputs, passing the same number of
* audio outputs, and passing through any other types unchanged.
*/
class Amp : public Processor {
public:
- Amp(Session& s, IO& io);
+ Amp(Session& s, boost::shared_ptr<MuteMaster> m);
bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const;
bool configure_io (ChanCount in, ChanCount out);
@@ -44,38 +45,54 @@ public:
bool apply_gain() const { return _apply_gain; }
void apply_gain(bool yn) { _apply_gain = yn; }
+ void setup_gain_automation (sframes_t start_frame, sframes_t end_frame, nframes_t nframes);
+
bool apply_gain_automation() const { return _apply_gain_automation; }
void apply_gain_automation(bool yn) { _apply_gain_automation = yn; }
- void muute(bool yn) { _mute = yn; }
+ XMLNode& state (bool full);
- void set_gain(float current, float desired) {
- _current_gain = current;
- _desired_gain = desired;
- }
-
- void apply_mute(bool yn, float current=1.0, float desired=0.0) {
- _mute = yn;
- _current_mute_gain = current;
- _desired_mute_gain = desired;
- }
+ static void apply_gain (BufferSet& bufs, nframes_t nframes, gain_t initial, gain_t target);
+ static void apply_simple_gain(BufferSet& bufs, nframes_t nframes, gain_t target);
- XMLNode& state (bool full);
+ gain_t gain () const { return _gain_control->user_float(); }
- static void apply_gain (BufferSet& bufs, nframes_t nframes,
- gain_t initial, gain_t target, bool invert_polarity);
+ virtual void set_gain (gain_t g, void *src);
+ void inc_gain (gain_t delta, void *src);
- static void apply_simple_gain(BufferSet& bufs, nframes_t nframes, gain_t target);
+ static void update_meters();
+
+ /* automation */
+
+ struct GainControl : public AutomationControl {
+ GainControl (std::string name, Session& session, Amp* a, const Evoral::Parameter &param,
+ boost::shared_ptr<AutomationList> al = boost::shared_ptr<AutomationList>() )
+ : AutomationControl (session, param, al, name )
+ , _amp (a)
+ {}
+
+ void set_value (float val);
+ float get_value (void) const;
+
+ Amp* _amp;
+ };
+
+ boost::shared_ptr<GainControl> gain_control() {
+ return _gain_control;
+ }
+
+ boost::shared_ptr<const GainControl> gain_control() const {
+ return _gain_control;
+ }
private:
- IO& _io;
- bool _mute;
- bool _apply_gain;
- bool _apply_gain_automation;
- float _current_gain;
- float _desired_gain;
- float _current_mute_gain;
- float _desired_mute_gain;
+ bool _denormal_protection;
+ bool _apply_gain;
+ bool _apply_gain_automation;
+ float _current_gain;
+
+ boost::shared_ptr<GainControl> _gain_control;
+ boost::shared_ptr<MuteMaster> _mute_master;
};
diff --git a/libs/ardour/ardour/automatable.h b/libs/ardour/ardour/automatable.h
index 5eacfa14b2..ed98e8d8ba 100644
--- a/libs/ardour/ardour/automatable.h
+++ b/libs/ardour/ardour/automatable.h
@@ -58,7 +58,7 @@ public:
virtual void add_control(boost::shared_ptr<Evoral::Control>);
virtual void automation_snapshot(nframes_t now, bool force);
- virtual void transport_stopped(nframes_t now);
+ virtual void transport_stopped (sframes_t now);
virtual std::string describe_parameter(Evoral::Parameter param);
diff --git a/libs/ardour/ardour/click.h b/libs/ardour/ardour/click.h
index 8488df47a6..2f174ab472 100644
--- a/libs/ardour/ardour/click.h
+++ b/libs/ardour/ardour/click.h
@@ -27,7 +27,7 @@ namespace ARDOUR {
class ClickIO : public IO
{
public:
- ClickIO (Session& s, const std::string& name) : IO (s, name) {}
+ ClickIO (Session& s, const std::string& name) : IO (s, name, IO::Output) {}
~ClickIO() {}
protected:
diff --git a/libs/ardour/ardour/delivery.h b/libs/ardour/ardour/delivery.h
index 8d083695b1..645b601251 100644
--- a/libs/ardour/ardour/delivery.h
+++ b/libs/ardour/ardour/delivery.h
@@ -28,48 +28,91 @@ namespace ARDOUR {
class BufferSet;
class IO;
+class MuteMaster;
+class Panner;
class Delivery : public IOProcessor {
public:
enum Role {
- Send = 0x1,
- Solo = 0x2,
+ Insert = 0x1,
+ Send = 0x2,
Listen = 0x4,
Main = 0x8
};
- Delivery (Session& s, IO* io, const std::string& name, Role);
- Delivery (Session& s, const std::string& name, Role);
- Delivery (Session&, const XMLNode&);
+ Delivery (Session& s, boost::shared_ptr<IO> io, boost::shared_ptr<MuteMaster> mm, const std::string& name, Role);
+ Delivery (Session& s, boost::shared_ptr<MuteMaster> mm, const std::string& name, Role);
+ Delivery (Session&, boost::shared_ptr<MuteMaster> mm, const XMLNode&);
+ bool set_name (const std::string& name);
bool visible() const;
-
Role role() const { return _role; }
-
bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const;
bool configure_io (ChanCount in, ChanCount out);
void run_in_place (BufferSet& bufs, sframes_t start_frame, sframes_t end_frame, nframes_t nframes);
- void set_metering (bool yn);
-
- bool muted_by_self() const { return _muted_by_self; }
- bool muted_by_others() const { return _muted_by_others; }
+ /* supplemental method use with MIDI */
+
+ void flush (nframes_t nframes);
+
+ void no_outs_cuz_we_no_monitor(bool);
+
+ void mod_solo_level (int32_t);
+ uint32_t solo_level() const { return _solo_level; }
+ bool soloed () const { return (bool) _solo_level; }
+
+ bool solo_isolated() const { return _solo_isolated; }
+ void set_solo_isolated (bool);
+
+ void cycle_start (nframes_t);
+ void increment_output_offset (nframes_t);
+ void transport_stopped (sframes_t frame);
+
+ BufferSet& output_buffers() { return *_output_buffers; }
+
+ sigc::signal<void> MuteChange;
- void set_self_mute (bool);
- void set_nonself_mute (bool);
-
- sigc::signal<void> SelfMuteChange;
- sigc::signal<void> OtherMuteChange;
+ static sigc::signal<void,nframes_t> CycleStart;
XMLNode& state (bool full);
int set_state (const XMLNode&);
-private:
- Role _role;
- bool _metering;
- bool _muted_by_self;
- bool _muted_by_others;
+ /* Panning */
+
+ static int disable_panners (void);
+ static int reset_panners (void);
+
+ boost::shared_ptr<Panner> panner() const { return _panner; }
+
+ void reset_panner ();
+ void defer_pan_reset ();
+ void allow_pan_reset ();
+
+ uint32_t pans_required() const { return _configured_input.n_audio(); }
+ void start_pan_touch (uint32_t which);
+ void end_pan_touch (uint32_t which);
+
+ protected:
+ Role _role;
+ BufferSet* _output_buffers;
+ gain_t _current_gain;
+ nframes_t _output_offset;
+ bool _no_outs_cuz_we_no_monitor;
+ uint32_t _solo_level;
+ bool _solo_isolated;
+ boost::shared_ptr<MuteMaster> _mute_master;
+ bool no_panner_reset;
+ boost::shared_ptr<Panner> _panner;
+
+ static bool panners_legal;
+ static sigc::signal<int> PannersLegal;
+
+ int panners_became_legal ();
+ sigc::connection panner_legal_c;
+ void output_changed (IOChange, void*);
+
+ gain_t target_gain ();
};
diff --git a/libs/ardour/ardour/io.h b/libs/ardour/ardour/io.h
index 23e4f576df..3f222c6aa1 100644
--- a/libs/ardour/ardour/io.h
+++ b/libs/ardour/ardour/io.h
@@ -55,134 +55,83 @@ class AudioPort;
class BufferSet;
class Bundle;
class MidiPort;
-class Panner;
class PeakMeter;
class Port;
+class Processor;
class Session;
class UserBundle;
-/** A collection of input and output ports with connections.
+/** A collection of ports (all input or all output) with connections.
*
* An IO can contain ports of varying types, making routes/inserts/etc with
* varied combinations of types (eg MIDI and audio) possible.
*/
-class IO : public SessionObject, public AutomatableControls, public Latent
+class IO : public SessionObject, public Latent
{
public:
static const std::string state_node_name;
- IO (Session&, const std::string& name, DataType default_type = DataType::AUDIO);
+ enum Direction {
+ Input,
+ Output
+ };
+
+ IO (Session&, const std::string& name, Direction, DataType default_type = DataType::AUDIO);
IO (Session&, const XMLNode&, DataType default_type = DataType::AUDIO);
virtual ~IO();
- bool active() const { return _active; }
- void set_active (bool yn);
-
+ Direction direction() const { return _direction; }
+
DataType default_type() const { return _default_type; }
void set_default_type(DataType t) { _default_type = t; }
+
+ bool active() const { return _active; }
+ void set_active(bool yn) { _active = yn; }
bool set_name (const std::string& str);
virtual void silence (nframes_t);
- void collect_input (BufferSet& bufs, nframes_t nframes, ChanCount offset=ChanCount::ZERO);
- void deliver_output (BufferSet& bufs, sframes_t start_frame, sframes_t end_frame, nframes_t nframes);
- void just_meter_input (sframes_t start_frame, sframes_t end_frame, nframes_t nframes);
-
- BufferSet& output_buffers() { return *_output_buffers; }
-
- gain_t gain () const { return _gain_control->user_float(); }
- virtual gain_t effective_gain () const;
-
- void set_denormal_protection (bool yn, void *src);
- bool denormal_protection() const { return _denormal_protection; }
-
- void set_phase_invert (bool yn, void *src);
- bool phase_invert() const { return _phase_invert; }
-
- void reset_panner ();
-
- boost::shared_ptr<Amp> amp() const { return _amp; }
-
- PeakMeter& peak_meter() { return *_meter.get(); }
- const PeakMeter& peak_meter() const { return *_meter.get(); }
- boost::shared_ptr<PeakMeter> shared_peak_meter() const { return _meter; }
-
- boost::shared_ptr<Panner> panner() const { return _panner; }
-
- int ensure_io (ChanCount in, ChanCount out, bool clear, void *src);
+ int ensure_io (ChanCount cnt, bool clear, void *src);
- int connect_input_ports_to_bundle (boost::shared_ptr<Bundle>, void *);
- int disconnect_input_ports_from_bundle (boost::shared_ptr<Bundle>, void *);
- int connect_output_ports_to_bundle (boost::shared_ptr<Bundle>, void *);
- int disconnect_output_ports_from_bundle (boost::shared_ptr<Bundle>, void *);
+ int connect_ports_to_bundle (boost::shared_ptr<Bundle>, void *);
+ int disconnect_ports_from_bundle (boost::shared_ptr<Bundle>, void *);
- BundleList bundles_connected_to_inputs ();
- BundleList bundles_connected_to_outputs ();
+ BundleList bundles_connected ();
- boost::shared_ptr<Bundle> bundle_for_inputs () { return _bundle_for_inputs; }
- boost::shared_ptr<Bundle> bundle_for_outputs () { return _bundle_for_outputs; }
+ boost::shared_ptr<Bundle> bundle () { return _bundle; }
- int add_input_port (std::string source, void *src, DataType type = DataType::NIL);
- int add_output_port (std::string destination, void *src, DataType type = DataType::NIL);
-
- int remove_input_port (Port *, void *src);
- int remove_output_port (Port *, void *src);
-
- int set_input (Port *, void *src);
-
- int connect_input (Port *our_port, std::string other_port, void *src);
- int connect_output (Port *our_port, std::string other_port, void *src);
-
- int disconnect_input (Port *our_port, std::string other_port, void *src);
- int disconnect_output (Port *our_port, std::string other_port, void *src);
-
- int disconnect_inputs (void *src);
- int disconnect_outputs (void *src);
-
+ int add_port (std::string connection, void *src, DataType type = DataType::NIL);
+ int remove_port (Port *, void *src);
+ int connect (Port *our_port, std::string other_port, void *src);
+ int disconnect (Port *our_port, std::string other_port, void *src);
+ int disconnect (void *src);
bool connected_to (boost::shared_ptr<const IO>) const;
nframes_t signal_latency() const { return _own_latency; }
- nframes_t output_latency() const;
- nframes_t input_latency() const;
+ nframes_t latency() const;
void set_port_latency (nframes_t);
void update_port_total_latencies ();
- const PortSet& inputs() const { return _inputs; }
- const PortSet& outputs() const { return _outputs; }
+ PortSet& ports() { return _ports; }
+ const PortSet& ports() const { return _ports; }
- Port *output (uint32_t n) const {
- if (n < _outputs.num_ports()) {
- return _outputs.port(n);
+ Port *nth (uint32_t n) const {
+ if (n < _ports.num_ports()) {
+ return _ports.port(n);
} else {
return 0;
}
}
- Port *input (uint32_t n) const {
- if (n < _inputs.num_ports()) {
- return _inputs.port(n);
- } else {
- return 0;
- }
- }
+ AudioPort* audio(uint32_t n) const;
+ MidiPort* midi(uint32_t n) const;
- AudioPort* audio_input(uint32_t n) const;
- AudioPort* audio_output(uint32_t n) const;
- MidiPort* midi_input(uint32_t n) const;
- MidiPort* midi_output(uint32_t n) const;
+ const ChanCount& n_ports () const { return _ports.count(); }
- const ChanCount& n_inputs () const { return _inputs.count(); }
- const ChanCount& n_outputs () const { return _outputs.count(); }
-
- void attach_buffers(ChanCount ignored);
-
- sigc::signal<void> active_changed;
-
- sigc::signal<void,IOChange,void*> input_changed;
- sigc::signal<void,IOChange,void*> output_changed;
+ sigc::signal<void,IOChange,void*> changed;
virtual XMLNode& state (bool full);
XMLNode& get_state (void);
@@ -192,130 +141,45 @@ class IO : public SessionObject, public AutomatableControls, public Latent
static int enable_connecting (void);
static int disable_ports (void);
static int enable_ports (void);
- static int disable_panners (void);
- static int reset_panners (void);
- static sigc::signal<int> PortsLegal;
- static sigc::signal<int> PannersLegal;
- static sigc::signal<int> ConnectingLegal;
- /// raised when the number of input or output ports changes
- static sigc::signal<void,ChanCount> PortCountChanged;
- static sigc::signal<void,nframes_t> CycleStart;
-
- static void update_meters();
+ static sigc::signal<void,ChanCount> PortCountChanged; // emitted when the number of ports changes
+
static std::string name_from_state (const XMLNode&);
static void set_name_in_state (XMLNode&, const std::string&);
- private:
-
- static sigc::signal<void> Meter;
- static Glib::StaticMutex m_meter_signal_lock;
- sigc::connection m_meter_connection;
-
- public:
-
- /* automation */
-
- struct GainControl : public AutomationControl {
- GainControl (std::string name, IO* i, const Evoral::Parameter &param,
- boost::shared_ptr<AutomationList> al = boost::shared_ptr<AutomationList>() )
- : AutomationControl (i->_session, param, al, name )
- , _io (i)
- {}
-
- void set_value (float val);
- float get_value (void) const;
-
- IO* _io;
- };
+ /* we have to defer/order port connection. this is how we do it.
+ */
- boost::shared_ptr<GainControl> gain_control() {
- return _gain_control;
- }
- boost::shared_ptr<const GainControl> gain_control() const {
- return _gain_control;
- }
+ static sigc::signal<int> ConnectingLegal;
+ static bool connecting_legal;
- void clear_automation ();
+ XMLNode *pending_state_node;
- void set_parameter_automation_state (Evoral::Parameter, AutoState);
+ /* three utility functions - this just seems to be simplest place to put them */
- virtual void transport_stopped (nframes_t now);
- virtual void automation_snapshot (nframes_t now, bool force);
+ void collect_input (BufferSet& bufs, nframes_t nframes, ChanCount offset);
+ void process_input (boost::shared_ptr<Processor>, sframes_t start_frame, sframes_t end_frame, nframes_t nframes);
+ void copy_to_outputs (BufferSet& bufs, DataType type, nframes_t nframes, nframes_t offset);
- void start_pan_touch (uint32_t which);
- void end_pan_touch (uint32_t which);
-
- void defer_pan_reset ();
- void allow_pan_reset ();
+ /* AudioTrack::deprecated_use_diskstream_connections() needs these */
- /* the session calls this for master outs before
- anyone else. controls outs too, at some point.
- */
-
- XMLNode *pending_state_node;
- int ports_became_legal ();
+ int set_ports (const std::string& str);
private:
mutable Glib::Mutex io_lock;
protected:
- BufferSet* _output_buffers; //< Set directly to output port buffers
- bool _active;
- gain_t _gain;
- Glib::Mutex declick_lock;
- PortSet _outputs;
- PortSet _inputs;
- bool no_panner_reset;
- bool _phase_invert;
- bool _denormal_protection;
- XMLNode* deferred_state;
- DataType _default_type;
- nframes_t _output_offset;
-
- boost::shared_ptr<Amp> _amp;
- boost::shared_ptr<PeakMeter> _meter;
- boost::shared_ptr<Panner> _panner;
-
- virtual void prepare_inputs (nframes_t nframes);
- virtual void flush_outputs (nframes_t nframes);
-
- virtual void set_deferred_state() {}
-
- virtual uint32_t pans_required() const
- { return _inputs.count().n_audio(); }
-
- boost::shared_ptr<GainControl> _gain_control;
-
- virtual void set_gain (gain_t g, void *src);
- void inc_gain (gain_t delta, void *src);
-
- virtual int load_automation (std::string path);
-
- /* AudioTrack::deprecated_use_diskstream_connections() needs these */
-
- int set_inputs (const std::string& str);
- int set_outputs (const std::string& str);
-
- void increment_output_offset (nframes_t);
- void cycle_start (nframes_t);
-
- static bool connecting_legal;
- static bool ports_legal;
-
+ PortSet _ports;
+ Direction _direction;
+ DataType _default_type;
+ bool _active;
+
private:
- static bool panners_legal;
-
- void copy_to_outputs (BufferSet& bufs, DataType type, nframes_t nframes);
int connecting_became_legal ();
- int panners_became_legal ();
sigc::connection connection_legal_c;
- sigc::connection port_legal_c;
- sigc::connection panner_legal_c;
- boost::shared_ptr<Bundle> _bundle_for_inputs; ///< a bundle representing our inputs
- boost::shared_ptr<Bundle> _bundle_for_outputs; ///< a bundle representing our outputs
+ boost::shared_ptr<Bundle> _bundle; ///< a bundle representing our ports
struct UserBundleInfo {
UserBundleInfo (IO*, boost::shared_ptr<UserBundle> b);
@@ -324,45 +188,31 @@ class IO : public SessionObject, public AutomatableControls, public Latent
sigc::connection changed;
};
- std::vector<UserBundleInfo> _bundles_connected_to_outputs; ///< user bundles connected to our outputs
- std::vector<UserBundleInfo> _bundles_connected_to_inputs; ///< user bundles connected to our inputs
+ std::vector<UserBundleInfo> _bundles_connected; ///< user bundles connected to our ports
static int parse_io_string (const std::string&, std::vector<std::string>& chns);
-
static int parse_gain_string (const std::string&, std::vector<std::string>& chns);
- int set_sources (std::vector<std::string>&, void *src, bool add);
- int set_destinations (std::vector<std::string>&, void *src, bool add);
-
- int ensure_inputs (ChanCount, bool clear, bool lockit, void *src);
- int ensure_outputs (ChanCount, bool clear, bool lockit, void *src);
+ int ensure_ports (ChanCount, bool clear, bool lockit, void *src);
- void check_bundles_connected_to_inputs ();
- void check_bundles_connected_to_outputs ();
+ void check_bundles_connected ();
void check_bundles (std::vector<UserBundleInfo>&, const PortSet&);
void bundle_changed (Bundle::Change);
- int get_port_counts (const XMLNode& node, ChanCount& in, ChanCount& out,
- boost::shared_ptr<Bundle>& ic, boost::shared_ptr<Bundle>& oc);
+ int get_port_counts (const XMLNode& node, ChanCount& n, boost::shared_ptr<Bundle>& c);
int create_ports (const XMLNode&);
int make_connections (const XMLNode&);
- boost::shared_ptr<Bundle> find_possible_bundle (const std::string &desired_name, const std::string &default_name, const std::string &connection_type_name);
- virtual void setup_peak_meters ();
- void meter ();
+ boost::shared_ptr<Bundle> find_possible_bundle (const std::string &desired_name);
- bool ensure_inputs_locked (ChanCount, bool clear, void *src);
- bool ensure_outputs_locked (ChanCount, bool clear, void *src);
+ bool ensure_ports_locked (ChanCount, bool clear, void *src);
- std::string build_legal_port_name (DataType type, bool for_input);
- int32_t find_input_port_hole (const char* base);
- int32_t find_output_port_hole (const char* base);
+ std::string build_legal_port_name (DataType type);
+ int32_t find_port_hole (const char* base);
- void setup_bundles_for_inputs_and_outputs ();
- void setup_bundle_for_inputs ();
- void setup_bundle_for_outputs ();
+ void setup_bundles ();
std::string bundle_channel_name (uint32_t, uint32_t) const;
};
diff --git a/libs/ardour/ardour/io_processor.h b/libs/ardour/ardour/io_processor.h
index 896de52a3b..72be2c0743 100644
--- a/libs/ardour/ardour/io_processor.h
+++ b/libs/ardour/ardour/io_processor.h
@@ -38,15 +38,16 @@ namespace ARDOUR {
class Session;
class IO;
-/** A mixer strip element (Processor) with Jack ports (IO).
+/** A mixer strip element (Processor) with 1 or 2 IO elements.
*/
class IOProcessor : public Processor
{
public:
- IOProcessor (Session&, const std::string& proc_name, const std::string io_name="",
- ARDOUR::DataType default_type = DataType::AUDIO);
- IOProcessor (Session&, IO* io, const std::string& proc_name,
+ IOProcessor (Session&, bool with_input, bool with_output,
+ const std::string& proc_name, const std::string io_name="",
ARDOUR::DataType default_type = DataType::AUDIO);
+ IOProcessor (Session&, boost::shared_ptr<IO> input, boost::shared_ptr<IO> output,
+ const std::string& proc_name, ARDOUR::DataType default_type = DataType::AUDIO);
virtual ~IOProcessor ();
bool set_name (const std::string& str);
@@ -56,13 +57,14 @@ class IOProcessor : public Processor
virtual ChanCount natural_output_streams() const;
virtual ChanCount natural_input_streams () const;
- boost::shared_ptr<IO> io() { return _io; }
- boost::shared_ptr<const IO> io() const { return _io; }
- void set_io (boost::shared_ptr<IO>);
+ boost::shared_ptr<IO> input() { return _input; }
+ boost::shared_ptr<const IO> input() const { return _input; }
+ boost::shared_ptr<IO> output() { return _output; }
+ boost::shared_ptr<const IO> output() const { return _output; }
+ void set_input (boost::shared_ptr<IO>);
+ void set_output (boost::shared_ptr<IO>);
- virtual void automation_snapshot (nframes_t now, bool force);
-
- virtual void run_in_place (BufferSet& in, sframes_t start, sframes_t end, nframes_t nframes) = 0;
+ void run_in_place (BufferSet& in, sframes_t start, sframes_t end, nframes_t nframes) = 0;
void silence (nframes_t nframes);
sigc::signal<void,IOProcessor*,bool> AutomationPlaybackChanged;
@@ -72,12 +74,14 @@ class IOProcessor : public Processor
int set_state (const XMLNode&);
protected:
- boost::shared_ptr<IO> _io;
+ boost::shared_ptr<IO> _input;
+ boost::shared_ptr<IO> _output;
private:
/* disallow copy construction */
IOProcessor (const IOProcessor&);
- bool _own_io;
+ bool _own_input;
+ bool _own_output;
};
diff --git a/libs/ardour/ardour/meter.h b/libs/ardour/ardour/meter.h
index 250fb3111e..43df5e936c 100644
--- a/libs/ardour/ardour/meter.h
+++ b/libs/ardour/ardour/meter.h
@@ -20,6 +20,7 @@
#define __ardour_meter_h__
#include <vector>
+#include <sigc++/slot.h>
#include "ardour/types.h"
#include "ardour/processor.h"
#include "pbd/fastlog.h"
@@ -30,6 +31,20 @@ class BufferSet;
class ChanCount;
class Session;
+class Metering {
+ public:
+ static void update_meters ();
+ static sigc::signal<void> Meter;
+
+ static sigc::connection connect (sigc::slot<void> the_slot);
+ static void disconnect (sigc::connection& c);
+
+ private:
+ /* this object is not meant to be instantiated */
+ virtual void foo() = 0;
+
+ static Glib::StaticMutex m_meter_signal_lock;
+};
/** Meters peaks on the input and stores them for access.
*/
@@ -37,6 +52,8 @@ class PeakMeter : public Processor {
public:
PeakMeter(Session& s) : Processor(s, "Meter") {}
+ void meter();
+
void reset ();
void reset_max ();
@@ -66,7 +83,6 @@ public:
private:
friend class IO;
- void meter();
std::vector<float> _peak_power;
std::vector<float> _visible_peak_power;
diff --git a/libs/ardour/ardour/mute_master.h b/libs/ardour/ardour/mute_master.h
new file mode 100644
index 0000000000..d55de0c856
--- /dev/null
+++ b/libs/ardour/ardour/mute_master.h
@@ -0,0 +1,77 @@
+/*
+ Copyright (C) 2009 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#ifndef __ardour_mute_master_h__
+#define __ardour_mute_master_h__
+
+#include "evoral/Parameter.hpp"
+#include "ardour/automation_control.h"
+#include "ardour/automation_list.h"
+
+namespace ARDOUR {
+
+class Session;
+
+class MuteMaster : public AutomationControl
+{
+ public:
+ enum MutePoint {
+ PreFader = 0x1,
+ PostFader = 0x2,
+ Listen = 0x4,
+ Main = 0x8
+ };
+
+ MuteMaster (Session& s, const std::string& name);
+ ~MuteMaster() {}
+
+ bool muted_pre_fader() const { return _mute_point & PreFader; }
+ bool muted_post_fader() const { return _mute_point & PostFader; }
+ bool muted_listen() const { return _mute_point & Listen; }
+ bool muted_main () const { return _mute_point & Main; }
+
+ bool muted_at (MutePoint mp) const { return _mute_point & mp; }
+ bool muted() const { return _mute_point != MutePoint (0) && get_value() != 0.0; }
+
+ gain_t mute_gain_at (MutePoint) const;
+
+ void clear_mute ();
+ void mute_at (MutePoint);
+ void unmute_at (MutePoint);
+
+ void mute (bool yn);
+
+ /* Controllable interface */
+
+ void set_value (float); /* note: float is used as a bitfield of MutePoints */
+ float get_value () const;
+
+ sigc::signal<void> MutePointChanged;
+
+ XMLNode& get_state();
+ int set_state(const XMLNode& node);
+
+ private:
+ AutomationList* _automation;
+ MutePoint _mute_point;
+};
+
+} // namespace ARDOUR
+
+#endif /*__ardour_mute_master_h__ */
diff --git a/libs/ardour/ardour/panner.h b/libs/ardour/ardour/panner.h
index 9bc1817af0..3c66046ad1 100644
--- a/libs/ardour/ardour/panner.h
+++ b/libs/ardour/ardour/panner.h
@@ -183,7 +183,7 @@ class Multi2dPanner : public StreamPanner
};
-class Panner : public Processor
+class Panner : public SessionObject, public AutomatableControls
{
public:
struct Output {
@@ -204,18 +204,16 @@ class Panner : public Processor
void clear_panners ();
bool empty() const { return _streampanners.empty(); }
- /// The fundamental Panner function
void set_automation_state (AutoState);
AutoState automation_state() const;
void set_automation_style (AutoStyle);
AutoStyle automation_style() const;
bool touching() const;
- bool is_in_place () const { return false; }
- bool is_out_of_place () const { return true; }
bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const { return true; };
- void run_out_of_place(BufferSet& src, BufferSet& dest, sframes_t start_frame, sframes_t end_frames, nframes_t nframes);
+ /// The fundamental Panner function
+ void run (BufferSet& src, BufferSet& dest, sframes_t start_frame, sframes_t end_frames, nframes_t nframes);
//void* get_inline_gui() const = 0;
//void* get_full_gui() const = 0;
diff --git a/libs/ardour/ardour/port_insert.h b/libs/ardour/ardour/port_insert.h
index 56aa43c6c5..fa9c31efe6 100644
--- a/libs/ardour/ardour/port_insert.h
+++ b/libs/ardour/ardour/port_insert.h
@@ -34,25 +34,28 @@ class XMLNode;
namespace ARDOUR {
class Session;
+class IO;
+class Delivery;
+class MuteMaster;
/** Port inserts: send output to a Jack port, pick up input at a Jack port
*/
class PortInsert : public IOProcessor
{
public:
- PortInsert (Session&);
- PortInsert (Session&, const XMLNode&);
+ PortInsert (Session&, boost::shared_ptr<MuteMaster> mm);
+ PortInsert (Session&, boost::shared_ptr<MuteMaster> mm, const XMLNode&);
~PortInsert ();
XMLNode& state(bool full);
XMLNode& get_state(void);
int set_state(const XMLNode&);
- void init ();
-
void run_in_place (BufferSet& bufs, sframes_t start_frame, sframes_t end_frame, nframes_t nframes);
nframes_t signal_latency() const;
+
+ bool set_name (const std::string& name);
bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const;
bool configure_io (ChanCount in, ChanCount out);
@@ -62,6 +65,8 @@ class PortInsert : public IOProcessor
private:
/* disallow copy construction */
PortInsert (const PortInsert&);
+
+ boost::shared_ptr<Delivery> _out;
uint32_t bitslot;
};
diff --git a/libs/ardour/ardour/processor.h b/libs/ardour/ardour/processor.h
index 73a93b31d9..61a266e9c5 100644
--- a/libs/ardour/ardour/processor.h
+++ b/libs/ardour/ardour/processor.h
@@ -53,24 +53,26 @@ class Processor : public SessionObject, public AutomatableControls, public Laten
virtual ~Processor() { }
- /** Configuration of a processor on a bus
- * (i.e. how to apply to a BufferSet)
- */
- struct Mapping {
- ChanCount in;
- ChanCount out;
- };
-
virtual bool visible() const { return true; }
bool active () const { return _active; }
+
+ /* we keep loose tabs on the "placement" of a Processor. Ultimately,
+ they are all executed as a single list, but there are some
+ semantics that require knowing whether a Processor is before
+ or after the fader, or panner etc. See Route::reorder_processors()
+ to see where this gets set.
+ */
+
+ Placement placement() const { return _placement; }
+ void set_placement (Placement p) { _placement = p; }
bool get_next_ab_is_active () const { return _next_ab_is_active; }
void set_next_ab_is_active (bool yn) { _next_ab_is_active = yn; }
virtual nframes_t signal_latency() const { return 0; }
- virtual void transport_stopped (nframes_t frame) {}
+ virtual void transport_stopped (sframes_t frame) {}
virtual void set_block_size (nframes_t nframes) {}
@@ -127,7 +129,7 @@ protected:
ChanCount _configured_input;
ChanCount _configured_output;
void* _gui; /* generic, we don't know or care what this is */
- Mapping _mapping;
+ Placement _placement;
};
} // namespace ARDOUR
diff --git a/libs/ardour/ardour/rc_configuration_vars.h b/libs/ardour/ardour/rc_configuration_vars.h
index 99ac902629..1a4c49fe64 100644
--- a/libs/ardour/ardour/rc_configuration_vars.h
+++ b/libs/ardour/ardour/rc_configuration_vars.h
@@ -84,6 +84,7 @@ CONFIG_VARIABLE (bool, all_safe, "all-safe", false)
CONFIG_VARIABLE (bool, show_solo_mutes, "show-solo-mutes", false)
CONFIG_VARIABLE (bool, solo_mute_override, "solo-mute-override", false)
CONFIG_VARIABLE (bool, tape_machine_mode, "tape-machine-mode", false)
+CONFIG_VARIABLE (gain_t, solo_mute_gain, "solo_mute-gain", 0.0)
/* click */
diff --git a/libs/ardour/ardour/return.h b/libs/ardour/ardour/return.h
index 2b6cd0b69e..5c2a82e3aa 100644
--- a/libs/ardour/ardour/return.h
+++ b/libs/ardour/ardour/return.h
@@ -32,6 +32,9 @@
namespace ARDOUR {
+class Amp;
+class PeakMeter;
+
class Return : public IOProcessor
{
public:
@@ -43,9 +46,12 @@ public:
void run_in_place (BufferSet& bufs, sframes_t start_frame, sframes_t end_frame, nframes_t nframes);
- void activate() {}
- void deactivate () {}
+ boost::shared_ptr<Amp> amp() const { return _amp; }
+ boost::shared_ptr<PeakMeter> meter() const { return _meter; }
+ bool metering() const { return _metering; }
+ void set_metering (bool yn) { _metering = yn; }
+
XMLNode& state(bool full);
XMLNode& get_state(void);
int set_state(const XMLNode& node);
@@ -55,14 +61,22 @@ public:
bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const;
bool configure_io (ChanCount in, ChanCount out);
- static uint32_t how_many_sends();
+ static uint32_t how_many_returns();
static void make_unique (XMLNode &, Session &);
+ protected:
+ bool _metering;
+ boost::shared_ptr<Amp> _amp;
+ boost::shared_ptr<PeakMeter> _meter;
+
private:
/* disallow copy construction */
Return (const Return&);
uint32_t _bitslot;
+
+ void collect_input (BufferSet& bufs, nframes_t nframes, ChanCount offset=ChanCount::ZERO);
+ void just_meter_input (sframes_t start_frame, sframes_t end_frame, nframes_t nframes);
};
} // namespace ARDOUR
diff --git a/libs/ardour/ardour/route.h b/libs/ardour/ardour/route.h
index 8de82bb219..a2ad716592 100644
--- a/libs/ardour/ardour/route.h
+++ b/libs/ardour/ardour/route.h
@@ -41,24 +41,19 @@
#include "ardour/ardour.h"
#include "ardour/io.h"
#include "ardour/types.h"
+#include "ardour/mute_master.h"
namespace ARDOUR {
class Amp;
class Delivery;
class IOProcessor;
+class Panner;
class Processor;
class RouteGroup;
class Send;
-enum mute_type {
- PRE_FADER = 0x1,
- POST_FADER = 0x2,
- CONTROL_OUTS = 0x4,
- MAIN_OUTS = 0x8
-};
-
-class Route : public IO
+class Route : public SessionObject, public AutomatableControls
{
public:
@@ -75,6 +70,16 @@ class Route : public IO
Route (Session&, const XMLNode&, DataType default_type = DataType::AUDIO);
virtual ~Route();
+ boost::shared_ptr<IO> input() const { return _input; }
+ boost::shared_ptr<IO> output() const { return _output; }
+
+ ChanCount n_inputs() const { return _input->n_ports(); }
+ ChanCount n_outputs() const { return _output->n_ports(); }
+
+ bool active() const { return _active; }
+ void set_active (bool yn);
+
+
static std::string ensure_track_or_route_name(std::string, Session &);
std::string comment() { return _comment; }
@@ -102,6 +107,7 @@ class Route : public IO
virtual void toggle_monitor_input ();
virtual bool can_record() { return false; }
+
virtual void set_record_enable (bool yn, void *src) {}
virtual bool record_enabled() const { return false; }
virtual void handle_transport_stopped (bool abort, bool did_locate, bool flush_processors);
@@ -110,38 +116,44 @@ class Route : public IO
/* end of vfunc-based API */
void shift (nframes64_t, nframes64_t);
-
- /* override IO::set_gain() to provide group control */
-
+
void set_gain (gain_t val, void *src);
void inc_gain (gain_t delta, void *src);
-
+
+ void set_mute (bool yn, void* src);
+ bool muted () const;
+
void set_solo (bool yn, void *src);
- bool soloed() const { return _soloed; }
+ bool soloed() const;
- void set_solo_safe (bool yn, void *src);
- bool solo_safe() const { return _solo_safe; }
+ void set_solo_isolated (bool yn, void *src);
+ bool solo_isolated() const;
- void set_mute (bool yn, void *src);
- bool muted() const { return _muted; }
- bool solo_muted() const { return desired_solo_gain == 0.0; }
+ void set_phase_invert (bool yn, void* src);
+ bool phase_invert() const;
- void set_mute_config (mute_type, bool, void *src);
- bool get_mute_config (mute_type);
+ void set_denormal_protection (bool yn, void* src);
+ bool denormal_protection() const;
void set_edit_group (RouteGroup *, void *);
void drop_edit_group (void *);
- RouteGroup *edit_group () { return _edit_group; }
+ RouteGroup *edit_group () const { return _edit_group; }
void set_mix_group (RouteGroup *, void *);
void drop_mix_group (void *);
- RouteGroup *mix_group () { return _mix_group; }
+ RouteGroup *mix_group () const { return _mix_group; }
virtual void set_meter_point (MeterPoint, void *src);
MeterPoint meter_point() const { return _meter_point; }
+ void meter ();
/* Processors */
+ boost::shared_ptr<Amp> amp() const { return _amp; }
+ PeakMeter& peak_meter() { return *_meter.get(); }
+ const PeakMeter& peak_meter() const { return *_meter.get(); }
+ boost::shared_ptr<PeakMeter> shared_peak_meter() const { return _meter; }
+
void flush_processors ();
void foreach_processor (sigc::slot<void, boost::weak_ptr<Processor> > method) {
@@ -180,7 +192,7 @@ class Route : public IO
boost::shared_ptr<Delivery> control_outs() const { return _control_outs; }
boost::shared_ptr<Delivery> main_outs() const { return _main_outs; }
-
+
boost::shared_ptr<Send> send_for (boost::shared_ptr<const IO> target) const;
/** A record of the stream configuration at some point in the processor list.
@@ -213,8 +225,10 @@ class Route : public IO
void set_user_latency (nframes_t);
nframes_t initial_delay() const { return _initial_delay; }
+ sigc::signal<void> active_changed;
sigc::signal<void,void*> solo_changed;
sigc::signal<void,void*> solo_safe_changed;
+ sigc::signal<void,void*> solo_isolated_changed;
sigc::signal<void,void*> comment_changed;
sigc::signal<void,void*> mute_changed;
sigc::signal<void,void*> pre_fader_changed;
@@ -240,8 +254,8 @@ class Route : public IO
virtual XMLNode& get_template();
XMLNode& get_processor_state ();
- int set_processor_state (const XMLNode&);
-
+ virtual void set_processor_state (const XMLNode&);
+
int save_as_template (const std::string& path, const std::string& name);
sigc::signal<void,void*> SelectedChanged;
@@ -252,28 +266,38 @@ class Route : public IO
bool feeds (boost::shared_ptr<IO>);
std::set<boost::shared_ptr<Route> > fed_by;
- struct ToggleControllable : public PBD::Controllable {
- enum ToggleType {
- MuteControl = 0,
- SoloControl
- };
-
- ToggleControllable (std::string name, Route&, ToggleType);
- void set_value (float);
- float get_value (void) const;
-
- Route& route;
- ToggleType type;
+ /* Controls (not all directly owned by the Route */
+
+ boost::shared_ptr<AutomationControl> get_control (const Evoral::Parameter& param);
+
+ struct SoloControllable : public AutomationControl {
+ SoloControllable (std::string name, Route&);
+ void set_value (float);
+ float get_value (void) const;
+
+ Route& route;
};
- boost::shared_ptr<PBD::Controllable> solo_control() {
+ boost::shared_ptr<AutomationControl> solo_control() const {
return _solo_control;
}
- boost::shared_ptr<PBD::Controllable> mute_control() {
- return _mute_control;
+ boost::shared_ptr<AutomationControl> mute_control() const {
+ return _mute_master;
}
-
+
+ boost::shared_ptr<MuteMaster> mute_master() const {
+ return _mute_master;
+ }
+
+ /* Route doesn't own these items, but sub-objects that it does own have them
+ and to make UI code a bit simpler, we provide direct access to them
+ here.
+ */
+
+ boost::shared_ptr<Panner> panner() const;
+ boost::shared_ptr<AutomationControl> gain_control() const;
+
void automation_snapshot (nframes_t now, bool force=false);
void protect_automation ();
@@ -288,10 +312,11 @@ class Route : public IO
friend class Session;
void catch_up_on_solo_mute_override ();
- void set_solo_mute (bool yn);
+ void mod_solo_level (int32_t);
void set_block_size (nframes_t nframes);
bool has_external_redirects() const;
void curve_reallocate ();
+ void just_meter_input (sframes_t start_frame, sframes_t end_frame, nframes_t nframes);
protected:
nframes_t check_initial_delay (nframes_t, nframes_t&);
@@ -303,44 +328,38 @@ class Route : public IO
sframes_t start_frame, sframes_t end_frame,
nframes_t nframes, bool with_processors, int declick);
- Flag _flags;
- int _pending_declick;
- MeterPoint _meter_point;
+ boost::shared_ptr<IO> _input;
+ boost::shared_ptr<IO> _output;
- gain_t solo_gain;
- gain_t mute_gain;
- gain_t desired_solo_gain;
- gain_t desired_mute_gain;
-
+ bool _active;
nframes_t _initial_delay;
nframes_t _roll_delay;
+
ProcessorList _processors;
mutable Glib::RWLock _processor_lock;
boost::shared_ptr<Delivery> _main_outs;
boost::shared_ptr<Delivery> _control_outs; // XXX to be removed/generalized by listen points
- RouteGroup *_edit_group;
- RouteGroup *_mix_group;
- std::string _comment;
- bool _have_internal_generator;
-
- boost::shared_ptr<ToggleControllable> _solo_control;
- boost::shared_ptr<ToggleControllable> _mute_control;
-
- /* tight cache-line access here is more important than sheer speed of access.
- keep these after things that should be aligned
- */
- bool _muted : 1;
- bool _soloed : 1;
- bool _solo_safe : 1;
+ Flag _flags;
+ int _pending_declick;
+ MeterPoint _meter_point;
+ uint32_t _phase_invert;
+ bool _denormal_protection;
+
bool _recordable : 1;
- bool _mute_affects_pre_fader : 1;
- bool _mute_affects_post_fader : 1;
- bool _mute_affects_control_outs : 1;
- bool _mute_affects_main_outs : 1;
bool _silent : 1;
bool _declickable : 1;
+ boost::shared_ptr<SoloControllable> _solo_control;
+ boost::shared_ptr<MuteMaster> _mute_master;
+
+ RouteGroup* _edit_group;
+ RouteGroup* _mix_group;
+ std::string _comment;
+ bool _have_internal_generator;
+ bool _solo_safe;
+ DataType _default_type;
+
protected:
virtual XMLNode& state(bool);
@@ -358,13 +377,14 @@ class Route : public IO
uint32_t pans_required() const;
ChanCount n_process_buffers ();
- void setup_peak_meters ();
-
virtual int _set_state (const XMLNode&, bool call_base);
- virtual void _set_processor_states (const XMLNodeList&);
boost::shared_ptr<Delivery> add_listener (boost::shared_ptr<IO>, const std::string&);
+ boost::shared_ptr<Amp> _amp;
+ boost::shared_ptr<PeakMeter> _meter;
+ sigc::connection _meter_connection;
+
private:
void init ();
@@ -386,8 +406,7 @@ class Route : public IO
int configure_processors (ProcessorStreams*);
int configure_processors_unlocked (ProcessorStreams*);
-
- void set_deferred_state ();
+
bool add_processor_from_xml (const XMLNode&, Placement);
bool add_processor_from_xml (const XMLNode&, ProcessorList::iterator iter);
diff --git a/libs/ardour/ardour/send.h b/libs/ardour/ardour/send.h
index b47263b547..302f512c9c 100644
--- a/libs/ardour/ardour/send.h
+++ b/libs/ardour/ardour/send.h
@@ -23,40 +23,52 @@
#include <sigc++/signal.h>
#include <string>
-
#include "pbd/stateful.h"
+
#include "ardour/ardour.h"
#include "ardour/audioengine.h"
#include "ardour/delivery.h"
namespace ARDOUR {
+class PeakMeter;
+class Amp;
+
class Send : public Delivery
{
public:
- Send (Session&);
- Send (Session&, const XMLNode&);
+ Send (Session&, boost::shared_ptr<MuteMaster>);
+ Send (Session&, boost::shared_ptr<MuteMaster>, const XMLNode&);
virtual ~Send ();
uint32_t bit_slot() const { return _bitslot; }
-
- void activate() {}
- void deactivate () {}
+ boost::shared_ptr<Amp> amp() const { return _amp; }
+ boost::shared_ptr<PeakMeter> meter() const { return _meter; }
+
+ bool metering() const { return _metering; }
+ void set_metering (bool yn) { _metering = yn; }
+
XMLNode& state(bool full);
XMLNode& get_state(void);
int set_state(const XMLNode& node);
uint32_t pans_required() const { return _configured_input.n_audio(); }
+ void run_in_place (BufferSet& bufs, sframes_t start_frame, sframes_t end_frame, nframes_t nframes);
+
bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const;
- bool configure_io (ChanCount in, ChanCount out);
bool set_name (const std::string& str);
static uint32_t how_many_sends();
static void make_unique (XMLNode &, Session &);
+ protected:
+ bool _metering;
+ boost::shared_ptr<Amp> _amp;
+ boost::shared_ptr<PeakMeter> _meter;
+
private:
/* disallow copy construction */
Send (const Send&);
diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h
index 3d85c8d200..d476a958d8 100644
--- a/libs/ardour/ardour/session.h
+++ b/libs/ardour/ardour/session.h
@@ -730,8 +730,8 @@ class Session : public PBD::StatefulDestructible, public boost::noncopyable
/* session-wide solo/mute/rec-enable */
- bool soloing() const { return currently_soloing; }
-
+ bool soloing() const { return _non_soloed_outs_muted; }
+
void set_all_solo (bool);
void set_all_mute (bool);
@@ -743,8 +743,8 @@ class Session : public PBD::StatefulDestructible, public boost::noncopyable
/* control/master out */
- boost::shared_ptr<IO> control_out() const { return _control_out; }
- boost::shared_ptr<IO> master_out() const { return _master_out; }
+ boost::shared_ptr<Route> control_out() const { return _control_out; }
+ boost::shared_ptr<Route> master_out() const { return _master_out; }
/* insert/send management */
@@ -1040,6 +1040,7 @@ class Session : public PBD::StatefulDestructible, public boost::noncopyable
bool _have_captured;
float _meter_hold;
float _meter_falloff;
+ bool _non_soloed_outs_muted;
void set_worst_io_latencies ();
void set_worst_io_latencies_x (IOChange asifwecare, void *ignored) {
@@ -1688,8 +1689,8 @@ class Session : public PBD::StatefulDestructible, public boost::noncopyable
/* main outs */
uint32_t main_outs;
- boost::shared_ptr<IO> _master_out;
- boost::shared_ptr<IO> _control_out;
+ boost::shared_ptr<Route> _master_out;
+ boost::shared_ptr<Route> _control_out;
gain_t* _gain_automation_buffer;
pan_t** _pan_automation_buffer;
diff --git a/libs/ardour/audio_diskstream.cc b/libs/ardour/audio_diskstream.cc
index 910239f630..4e8e2bf12d 100644
--- a/libs/ardour/audio_diskstream.cc
+++ b/libs/ardour/audio_diskstream.cc
@@ -160,6 +160,8 @@ AudioDiskstream::free_working_buffers()
void
AudioDiskstream::non_realtime_input_change ()
{
+ cerr << "AD::NRIC ... " << name() << endl;
+
{
Glib::Mutex::Lock lm (state_lock);
@@ -173,10 +175,10 @@ AudioDiskstream::non_realtime_input_change ()
_n_channels.set(DataType::AUDIO, c->size());
- if (_io->n_inputs().n_audio() > _n_channels.n_audio()) {
- add_channel_to (c, _io->n_inputs().n_audio() - _n_channels.n_audio());
- } else if (_io->n_inputs().n_audio() < _n_channels.n_audio()) {
- remove_channel_from (c, _n_channels.n_audio() - _io->n_inputs().n_audio());
+ if (_io->n_ports().n_audio() > _n_channels.n_audio()) {
+ add_channel_to (c, _io->n_ports().n_audio() - _n_channels.n_audio());
+ } else if (_io->n_ports().n_audio() < _n_channels.n_audio()) {
+ remove_channel_from (c, _n_channels.n_audio() - _io->n_ports().n_audio());
}
}
@@ -227,14 +229,14 @@ AudioDiskstream::get_input_sources ()
uint32_t n;
ChannelList::iterator chan;
- uint32_t ni = _io->n_inputs().n_audio();
+ uint32_t ni = _io->n_ports().n_audio();
vector<string> connections;
for (n = 0, chan = c->begin(); chan != c->end() && n < ni; ++chan, ++n) {
connections.clear ();
- if (_io->input(n)->get_connections (connections) == 0) {
+ if (_io->nth (n)->get_connections (connections) == 0) {
if ((*chan)->source) {
// _source->disable_metering ();
@@ -633,7 +635,7 @@ AudioDiskstream::process (nframes_t transport_frame, nframes_t nframes, bool can
if (nominally_recording || rec_nframes) {
- uint32_t limit = _io->n_inputs ().n_audio();
+ uint32_t limit = _io->n_ports ().n_audio();
/* one or more ports could already have been removed from _io, but our
channel setup hasn't yet been updated. prevent us from trying to
@@ -656,7 +658,7 @@ AudioDiskstream::process (nframes_t transport_frame, nframes_t nframes, bool can
for recording, and use rec_offset
*/
- AudioPort* const ap = _io->audio_input(n);
+ AudioPort* const ap = _io->audio (n);
assert(ap);
assert(rec_nframes <= ap->get_audio_buffer(nframes).capacity());
memcpy (chaninfo->current_capture_buffer, ap->get_audio_buffer (rec_nframes).data(rec_offset), sizeof (Sample) * rec_nframes);
@@ -671,7 +673,7 @@ AudioDiskstream::process (nframes_t transport_frame, nframes_t nframes, bool can
goto out;
}
- AudioPort* const ap = _io->audio_input(n);
+ AudioPort* const ap = _io->audio (n);
assert(ap);
Sample* buf = ap->get_audio_buffer(nframes).data();
@@ -1822,7 +1824,7 @@ AudioDiskstream::finish_capture (bool rec_monitors_input, boost::shared_ptr<Chan
void
AudioDiskstream::set_record_enabled (bool yn)
{
- if (!recordable() || !_session.record_enabling_legal() || _io->n_inputs().n_audio() == 0) {
+ if (!recordable() || !_session.record_enabling_legal() || _io->n_ports().n_audio() == 0) {
return;
}
@@ -2110,6 +2112,8 @@ AudioDiskstream::reset_write_sources (bool mark_write_complete, bool force)
boost::shared_ptr<ChannelList> c = channels.reader();
uint32_t n;
+ cerr << _name << " RWS!!!\n";
+
if (!recordable()) {
return;
}
diff --git a/libs/ardour/audio_track.cc b/libs/ardour/audio_track.cc
index 70e317c880..a41fdbe6b6 100644
--- a/libs/ardour/audio_track.cc
+++ b/libs/ardour/audio_track.cc
@@ -36,6 +36,7 @@
#include "ardour/buffer_set.h"
#include "ardour/io_processor.h"
#include "ardour/panner.h"
+#include "ardour/meter.h"
#include "ardour/playlist_factory.h"
#include "ardour/plugin_insert.h"
#include "ardour/processor.h"
@@ -140,8 +141,7 @@ AudioTrack::deprecated_use_diskstream_connections ()
diskstream->deprecated_io_node = 0;
if ((prop = node.property ("gain")) != 0) {
- set_gain (atof (prop->value().c_str()), this);
- _gain = _gain_control->user_float();
+ _amp->set_gain (atof (prop->value().c_str()), this);
}
if ((prop = node.property ("input-connection")) != 0) {
@@ -160,10 +160,10 @@ AudioTrack::deprecated_use_diskstream_connections ()
}
}
- connect_input_ports_to_bundle (c, this);
+ _input->connect_ports_to_bundle (c, this);
} else if ((prop = node.property ("inputs")) != 0) {
- if (set_inputs (prop->value())) {
+ if (_input->set_ports (prop->value())) {
error << string_compose(_("improper input channel list in XML node (%1)"), prop->value()) << endmsg;
return -1;
}
@@ -176,14 +176,14 @@ int
AudioTrack::set_diskstream (boost::shared_ptr<AudioDiskstream> ds, void *src)
{
_diskstream = ds;
- _diskstream->set_io (*this);
+ _diskstream->set_io (*(_input.get()));
_diskstream->set_destructive (_mode == Destructive);
_diskstream->set_non_layered (_mode == NonLayered);
if (audio_diskstream()->deprecated_io_node) {
- if (!connecting_legal) {
- ConnectingLegal.connect (mem_fun (*this, &AudioTrack::deprecated_use_diskstream_connections));
+ if (!IO::connecting_legal) {
+ IO::ConnectingLegal.connect (mem_fun (*this, &AudioTrack::deprecated_use_diskstream_connections));
} else {
deprecated_use_diskstream_connections ();
}
@@ -193,7 +193,7 @@ AudioTrack::set_diskstream (boost::shared_ptr<AudioDiskstream> ds, void *src)
_diskstream->monitor_input (false);
ic_connection.disconnect();
- ic_connection = input_changed.connect (mem_fun (*_diskstream, &Diskstream::handle_input_change));
+ ic_connection = _input->changed.connect (mem_fun (*_diskstream, &Diskstream::handle_input_change));
DiskstreamChanged (); /* EMIT SIGNAL */
@@ -479,8 +479,6 @@ AudioTrack::roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame,
transport_frame = _session.transport_frame();
- prepare_inputs (nframes);
-
if ((nframes = check_initial_delay (nframes, transport_frame)) == 0) {
/* need to do this so that the diskstream sets its
@@ -501,7 +499,7 @@ AudioTrack::roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame,
/* special condition applies */
if (_meter_point == MeterInput) {
- just_meter_input (start_frame, end_frame, nframes);
+ _input->process_input (_meter, start_frame, end_frame, nframes);
}
if (diskstream->record_enabled() && !can_record && !_session.config.get_auto_input()) {
@@ -599,6 +597,7 @@ AudioTrack::roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame,
/* don't waste time with automation if we're recording or we've just stopped (yes it can happen) */
if (!diskstream->record_enabled() && _session.transport_rolling()) {
+#ifdef XXX_MOVE_THIS_TO_AMP
Glib::Mutex::Lock am (data().control_lock(), Glib::TRY_LOCK);
if (am.locked() && gain_control()->automation_playback()) {
@@ -606,6 +605,7 @@ AudioTrack::roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame,
gain_control()->list()->curve().rt_safe_get_vector (
start_frame, end_frame, _session.gain_automation_buffer(), nframes));
}
+#endif
}
process_output_buffers (bufs, start_frame, end_frame, nframes, (!_session.get_record_enabled() || !Config->get_do_not_record_plugins()), declick);
@@ -759,9 +759,9 @@ AudioTrack::freeze (InterThreadInfo& itt)
new_playlist = PlaylistFactory::create (DataType::AUDIO, _session, new_playlist_name, false);
- _freeze_record.gain = _gain;
- _freeze_record.gain_automation_state = _gain_control->automation_state();
- _freeze_record.pan_automation_state = _panner->automation_state();
+ _freeze_record.gain = _amp->gain();
+ _freeze_record.gain_automation_state = _amp->gain_control()->automation_state();
+ /* XXX need main outs automation state _freeze_record.pan_automation_state = _mainpanner->automation_state(); */
region_name = new_playlist_name;
@@ -784,8 +784,8 @@ AudioTrack::freeze (InterThreadInfo& itt)
/* reset stuff that has already been accounted for in the freeze process */
set_gain (1.0, this);
- _gain_control->set_automation_state (Off);
- _panner->set_automation_state (Off);
+ _amp->gain_control()->set_automation_state (Off);
+ /* XXX need to use _main_outs _panner->set_automation_state (Off); */
_freeze_record.state = Frozen;
FreezeChange(); /* EMIT SIGNAL */
@@ -811,8 +811,8 @@ AudioTrack::unfreeze ()
_freeze_record.playlist.reset ();
set_gain (_freeze_record.gain, this);
- _gain_control->set_automation_state (_freeze_record.gain_automation_state);
- _panner->set_automation_state (_freeze_record.pan_automation_state);
+ _amp->gain_control()->set_automation_state (_freeze_record.gain_automation_state);
+ /* XXX need to use _main_outs _panner->set_automation_state (_freeze_record.pan_automation_state); */
}
_freeze_record.state = UnFrozen;
diff --git a/libs/ardour/audioengine.cc b/libs/ardour/audioengine.cc
index fe9c064efa..b563537cb3 100644
--- a/libs/ardour/audioengine.cc
+++ b/libs/ardour/audioengine.cc
@@ -33,9 +33,11 @@
#include "ardour/audioengine.h"
#include "ardour/buffer.h"
+#include "ardour/delivery.h"
#include "ardour/port.h"
#include "ardour/audio_port.h"
#include "ardour/midi_port.h"
+#include "ardour/meter.h"
#include "ardour/session.h"
#include "ardour/cycle_timer.h"
#include "ardour/utils.h"
@@ -358,9 +360,9 @@ AudioEngine::process_callback (nframes_t nframes)
return 0;
}
- /* tell all IO objects that we're starting a new cycle */
+ /* tell all relevant objects that we're starting a new cycle */
- IO::CycleStart (nframes);
+ Delivery::CycleStart (nframes);
Port::set_port_offset (0);
/* tell all Ports that we're starting a new cycle */
@@ -519,7 +521,7 @@ AudioEngine::meter_thread ()
if (g_atomic_int_get(&m_meter_exit)) {
break;
}
- IO::update_meters ();
+ Metering::update_meters ();
}
}
diff --git a/libs/ardour/auditioner.cc b/libs/ardour/auditioner.cc
index b62d0f3406..35a1b70137 100644
--- a/libs/ardour/auditioner.cc
+++ b/libs/ardour/auditioner.cc
@@ -24,6 +24,7 @@
#include "ardour/audio_diskstream.h"
#include "ardour/audioregion.h"
#include "ardour/audioengine.h"
+#include "ardour/delivery.h"
#include "ardour/route.h"
#include "ardour/session.h"
#include "ardour/auditioner.h"
@@ -57,22 +58,21 @@ Auditioner::Auditioner (Session& s)
return;
}
- defer_pan_reset ();
+ _main_outs->defer_pan_reset ();
if (left.length()) {
- add_output_port (left, this, DataType::AUDIO);
+ _output->add_port (left, this, DataType::AUDIO);
}
if (right.length()) {
audio_diskstream()->add_channel (1);
- add_output_port (right, this, DataType::AUDIO);
+ _output->add_port (right, this, DataType::AUDIO);
}
-
- allow_pan_reset ();
- reset_panner ();
+ _main_outs->allow_pan_reset ();
+ _main_outs->reset_panner ();
- IO::output_changed.connect (mem_fun (*this, &Auditioner::output_changed));
+ _output->changed.connect (mem_fun (*this, &Auditioner::output_changed));
the_region.reset ((AudioRegion*) 0);
g_atomic_int_set (&_active, 0);
@@ -110,7 +110,7 @@ Auditioner::audition_current_playlist ()
/* force a panner reset now that we have all channels */
- _panner->reset (n_outputs().n_audio(), _diskstream->n_channels().n_audio());
+ _main_outs->panner()->reset (n_outputs().n_audio(), _diskstream->n_channels().n_audio());
g_atomic_int_set (&_active, 1);
}
@@ -148,7 +148,7 @@ Auditioner::audition_region (boost::shared_ptr<Region> region)
/* force a panner reset now that we have all channels */
- reset_panner();
+ _main_outs->reset_panner();
length = the_region->length();
@@ -206,7 +206,7 @@ Auditioner::output_changed (IOChange change, void* src)
if (change & ConnectionsChanged) {
vector<string> connections;
- if (output (0)->get_connections (connections)) {
+ if (_output->nth (0)->get_connections (connections)) {
phys = _session.engine().get_nth_physical_output (DataType::AUDIO, 0);
if (phys != connections[0]) {
_session.config.set_auditioner_output_left (connections[0]);
@@ -219,7 +219,7 @@ Auditioner::output_changed (IOChange change, void* src)
connections.clear ();
- if (output (1)->get_connections (connections)) {
+ if (_output->nth (1)->get_connections (connections)) {
phys = _session.engine().get_nth_physical_output (DataType::AUDIO, 1);
if (phys != connections[0]) {
_session.config.set_auditioner_output_right (connections[0]);
diff --git a/libs/ardour/automatable.cc b/libs/ardour/automatable.cc
index 0fa4e9c67a..bf08a4026c 100644
--- a/libs/ardour/automatable.cc
+++ b/libs/ardour/automatable.cc
@@ -24,8 +24,11 @@
#include <errno.h>
#include "pbd/error.h"
#include "pbd/enumwriter.h"
+
#include "midi++/names.h"
+
#include "ardour/automatable.h"
+#include "ardour/amp.h"
#include "ardour/event_type_map.h"
#include "ardour/midi_track.h"
#include "ardour/panner.h"
@@ -382,7 +385,7 @@ Automatable::automation_snapshot (nframes_t now, bool force)
}
void
-Automatable::transport_stopped (nframes_t now)
+Automatable::transport_stopped (sframes_t now)
{
for (Controls::iterator li = controls().begin(); li != controls().end(); ++li) {
@@ -409,7 +412,7 @@ Automatable::control_factory(const Evoral::Parameter& param)
} else if (param.type() == PluginAutomation) {
control = new PluginInsert::PluginControl((PluginInsert*)this, param);
} else if (param.type() == GainAutomation) {
- control = new IO::GainControl( X_("gaincontrol"), (IO*)this, param);
+ control = new Amp::GainControl( X_("gaincontrol"), _a_session, (Amp*)this, param);
} else if (param.type() == PanAutomation) {
Panner* me = dynamic_cast<Panner*>(this);
if (me) {
diff --git a/libs/ardour/delivery.cc b/libs/ardour/delivery.cc
index bf15242094..75b026618b 100644
--- a/libs/ardour/delivery.cc
+++ b/libs/ardour/delivery.cc
@@ -20,58 +20,102 @@
#include <algorithm>
#include "pbd/enumwriter.h"
+#include "pbd/convert.h"
+
#include "ardour/delivery.h"
#include "ardour/audio_buffer.h"
+#include "ardour/amp.h"
#include "ardour/buffer_set.h"
#include "ardour/configuration.h"
#include "ardour/io.h"
#include "ardour/meter.h"
+#include "ardour/mute_master.h"
+#include "ardour/panner.h"
+#include "ardour/port.h"
#include "ardour/session.h"
+#include "i18n.h"
+
using namespace std;
+using namespace PBD;
using namespace ARDOUR;
+sigc::signal<void,nframes_t> Delivery::CycleStart;
+sigc::signal<int> Delivery::PannersLegal;
+bool Delivery::panners_legal = false;
+
/* deliver to an existing IO object */
-Delivery::Delivery (Session& s, IO* io, const string& name, Role r)
- : IOProcessor(s, io, name)
+Delivery::Delivery (Session& s, boost::shared_ptr<IO> io, boost::shared_ptr<MuteMaster> mm, const string& name, Role r)
+ : IOProcessor(s, boost::shared_ptr<IO>(), io, name)
, _role (r)
- , _metering (false)
- , _muted_by_self (false)
- , _muted_by_others (false)
+ , _output_buffers (new BufferSet())
+ , _solo_level (0)
+ , _solo_isolated (false)
+ , _mute_master (mm)
{
+ _output_offset = 0;
+ _current_gain = 1.0;
+ _panner = boost::shared_ptr<Panner>(new Panner (_name, _session));
+
+ _output->changed.connect (mem_fun (*this, &Delivery::output_changed));
}
/* deliver to a new IO object */
-Delivery::Delivery (Session& s, const string& name, Role r)
- : IOProcessor(s, name)
+Delivery::Delivery (Session& s, boost::shared_ptr<MuteMaster> mm, const string& name, Role r)
+ : IOProcessor(s, false, true, name)
, _role (r)
- , _metering (false)
- , _muted_by_self (false)
- , _muted_by_others (false)
+ , _output_buffers (new BufferSet())
+ , _solo_level (0)
+ , _solo_isolated (false)
+ , _mute_master (mm)
{
+ _output_offset = 0;
+ _current_gain = 1.0;
+ _panner = boost::shared_ptr<Panner>(new Panner (_name, _session));
+
+ _output->changed.connect (mem_fun (*this, &Delivery::output_changed));
}
-/* reconstruct from XML */
+/* deliver to a new IO object, reconstruct from XML */
-Delivery::Delivery (Session& s, const XMLNode& node)
- : IOProcessor (s, "reset")
+Delivery::Delivery (Session& s, boost::shared_ptr<MuteMaster> mm, const XMLNode& node)
+ : IOProcessor (s, false, true, "reset")
, _role (Role (0))
- , _metering (false)
- , _muted_by_self (false)
- , _muted_by_others (false)
+ , _output_buffers (new BufferSet())
+ , _solo_level (0)
+ , _solo_isolated (false)
+ , _mute_master (mm)
{
+ _output_offset = 0;
+ _current_gain = 1.0;
+ _panner = boost::shared_ptr<Panner>(new Panner (_name, _session));
+
if (set_state (node)) {
throw failed_constructor ();
}
+
+ _output->changed.connect (mem_fun (*this, &Delivery::output_changed));
+}
+
+void
+Delivery::cycle_start (nframes_t nframes)
+{
+ _output_offset = 0;
+ _no_outs_cuz_we_no_monitor = false;
}
+void
+Delivery::increment_output_offset (nframes_t n)
+{
+ _output_offset += n;
+}
bool
Delivery::visible () const
{
- if (_role & (Main|Solo)) {
+ if (_role & Main) {
return false;
}
@@ -91,6 +135,8 @@ Delivery::configure_io (ChanCount in, ChanCount out)
if (out != in) { // always 1:1
return false;
}
+
+ reset_panner ();
return Processor::configure_io (in, out);
}
@@ -98,64 +144,46 @@ Delivery::configure_io (ChanCount in, ChanCount out)
void
Delivery::run_in_place (BufferSet& bufs, sframes_t start_frame, sframes_t end_frame, nframes_t nframes)
{
- if (_io->n_outputs().get (_io->default_type()) == 0) {
+ if (_output->n_ports ().get (_output->default_type()) == 0) {
return;
}
- if (!active() || _muted_by_self || _muted_by_others) {
- silence (nframes);
- if (_metering) {
- _io->peak_meter().reset();
- }
- } else {
+ // this Delivery processor is not a derived type, and thus we assume
+ // we really can modify the buffers passed in (it is almost certainly
+ // the main output stage of a Route). Contrast with Send::run_in_place()
+ // which cannot do this.
- // we have to copy the input, because IO::deliver_output may alter the buffers
- // in-place, which a send must never do.
+ gain_t tgain = target_gain ();
+
+ if (tgain != _current_gain) {
+ Amp::apply_gain (bufs, nframes, _current_gain, tgain);
+ _current_gain = tgain;
+ }
- BufferSet& sendbufs = _session.get_mix_buffers (bufs.count());
+ // Attach output buffers to port buffers
- sendbufs.read_from(bufs, nframes);
- assert(sendbufs.count() == bufs.count());
+ PortSet& ports (_output->ports());
+ output_buffers().attach_buffers (ports, nframes, _output_offset);
- _io->deliver_output (sendbufs, start_frame, end_frame, nframes);
-
- if (_metering) {
- if (_io->effective_gain() == 0) {
- _io->peak_meter().reset();
- } else {
- _io->peak_meter().run_in_place(_io->output_buffers(), start_frame, end_frame, nframes);
- }
+ if (_panner && _panner->npanners() && !_panner->bypassed()) {
+
+ // Use the panner to distribute audio to output port buffers
+
+ _panner->run (bufs, output_buffers(), start_frame, end_frame, nframes);
+
+ } else {
+ // Do a 1:1 copy of data to output ports
+
+ if (bufs.count().n_audio() > 0 && ports.count().n_audio () > 0) {
+ _output->copy_to_outputs (bufs, DataType::AUDIO, nframes, _output_offset);
}
- }
-}
-void
-Delivery::set_metering (bool yn)
-{
- _metering = yn;
-
- if (!_metering) {
- /* XXX possible thread hazard here */
- _io->peak_meter().reset();
- }
-}
-void
-Delivery::set_self_mute (bool yn)
-{
- if (yn != _muted_by_self) {
- _muted_by_self = yn;
- SelfMuteChange (); // emit signal
+ if (bufs.count().n_midi() > 0 && ports.count().n_midi () > 0) {
+ _output->copy_to_outputs (bufs, DataType::MIDI, nframes, _output_offset);
+ }
}
}
-void
-Delivery::set_nonself_mute (bool yn)
-{
- if (yn != _muted_by_others) {
- _muted_by_others = yn;
- OtherMuteChange (); // emit signal
- }
-}
XMLNode&
Delivery::state (bool full_state)
@@ -170,10 +198,8 @@ Delivery::state (bool full_state)
node.add_property("type", "delivery");
}
- node.add_property("metering", (_metering ? "yes" : "no"));
- node.add_property("self-muted", (_muted_by_self ? "yes" : "no"));
- node.add_property("other-muted", (_muted_by_others ? "yes" : "no"));
node.add_property("role", enum_2_string(_role));
+ node.add_child_nocopy (_panner->state (full_state));
return node;
}
@@ -182,22 +208,236 @@ int
Delivery::set_state (const XMLNode& node)
{
const XMLProperty* prop;
+
+ if (IOProcessor::set_state (node)) {
+ return -1;
+ }
if ((prop = node.property ("role")) != 0) {
_role = Role (string_2_enum (prop->value(), _role));
}
- if ((prop = node.property ("metering")) != 0) {
- set_metering (prop->value() == "yes");
+ if ((prop = node.property ("solo_level")) != 0) {
+ _solo_level = 0; // needed for the reset to work
+ mod_solo_level (atoi (prop->value()));
}
- if ((prop = node.property ("self-muted")) != 0) {
- set_self_mute (prop->value() == "yes");
+ if ((prop = node.property ("solo-isolated")) != 0) {
+ set_solo_isolated (prop->value() == "yes");
}
- if ((prop = node.property ("other-muted")) != 0) {
- set_nonself_mute (prop->value() == "yes");
+ XMLNode* pan_node = node.child (X_("Panner"));
+
+ if (pan_node) {
+ cerr << _name << " reset pan state from XML\n";
+ _panner->set_state (*pan_node);
+ }
+
+ reset_panner ();
+
+ return 0;
+}
+
+void
+Delivery::reset_panner ()
+{
+ cerr << _name << " reset panner - plegal ? " << panners_legal << endl;
+
+ if (panners_legal) {
+ if (!no_panner_reset) {
+ cerr << "\treset panner with " << _output->name() << " = " << _output->n_ports()
+ << " vs. " << pans_required () << endl;
+ _panner->reset (_output->n_ports().n_audio(), pans_required());
+ }
+ } else {
+ cerr << "\tdefer pan reset till later\n";
+ panner_legal_c.disconnect ();
+ panner_legal_c = PannersLegal.connect (mem_fun (*this, &Delivery::panners_became_legal));
}
+}
+int
+Delivery::panners_became_legal ()
+{
+ cerr << _name << " panners now legal, outputs @ " << _output << " on " << _output->name()
+ << " = " << _output->n_ports() << " vs. " << pans_required() << endl;
+ _panner->reset (_output->n_ports().n_audio(), pans_required());
+ _panner->load (); // automation
+ panner_legal_c.disconnect ();
return 0;
}
+
+void
+Delivery::defer_pan_reset ()
+{
+ no_panner_reset = true;
+}
+
+void
+Delivery::allow_pan_reset ()
+{
+ no_panner_reset = false;
+ reset_panner ();
+}
+
+
+int
+Delivery::disable_panners (void)
+{
+ panners_legal = false;
+ return 0;
+}
+
+int
+Delivery::reset_panners ()
+{
+ panners_legal = true;
+ return PannersLegal ();
+}
+
+
+void
+Delivery::start_pan_touch (uint32_t which)
+{
+ if (which < _panner->npanners()) {
+ _panner->pan_control(which)->start_touch();
+ }
+}
+
+void
+Delivery::end_pan_touch (uint32_t which)
+{
+ if (which < _panner->npanners()) {
+ _panner->pan_control(which)->stop_touch();
+ }
+
+}
+
+void
+Delivery::transport_stopped (sframes_t frame)
+{
+ _panner->transport_stopped (frame);
+}
+
+void
+Delivery::flush (nframes_t nframes)
+{
+ /* io_lock, not taken: function must be called from Session::process() calltree */
+
+ PortSet& ports (_output->ports());
+
+ for (PortSet::iterator i = ports.begin(); i != ports.end(); ++i) {
+ (*i).flush_buffers (nframes, _output_offset);
+ }
+}
+
+gain_t
+Delivery::target_gain ()
+{
+ /* if we've been told not to output because its a monitoring situation and
+ we're not monitoring, then be quiet.
+ */
+
+ if (_no_outs_cuz_we_no_monitor) {
+ return 0.0;
+ }
+
+ gain_t desired_gain;
+ MuteMaster::MutePoint mp;
+
+ if (_solo_level) {
+ desired_gain = 1.0;
+ } else {
+ if (_solo_isolated) {
+
+ switch (_role) {
+ case Main:
+ mp = MuteMaster::Main;
+ break;
+ case Listen:
+ mp = MuteMaster::Listen;
+ break;
+ case Send:
+ case Insert:
+ if (_placement == PreFader) {
+ mp = MuteMaster::PreFader;
+ } else {
+ mp = MuteMaster::PostFader;
+ }
+ break;
+ }
+
+ desired_gain = _mute_master->mute_gain_at (mp);
+ } else if (_session.soloing()) {
+
+ switch (_role) {
+ case Main:
+ mp = MuteMaster::Main;
+ break;
+ case Listen:
+ mp = MuteMaster::Listen;
+ break;
+ case Send:
+ case Insert:
+ if (_placement == PreFader) {
+ mp = MuteMaster::PreFader;
+ } else {
+ mp = MuteMaster::PostFader;
+ }
+ break;
+ }
+
+ desired_gain = min (Config->get_solo_mute_gain(), _mute_master->mute_gain_at (mp));
+ } else {
+ desired_gain = 1.0;
+ }
+ }
+
+ return desired_gain;
+}
+
+void
+Delivery::mod_solo_level (int32_t delta)
+{
+ if (delta < 0) {
+ if (_solo_level >= (uint32_t) delta) {
+ _solo_level += delta;
+ } else {
+ _solo_level = 0;
+ }
+ } else {
+ _solo_level += delta;
+ }
+}
+
+void
+Delivery::set_solo_isolated (bool yn)
+{
+ _solo_isolated = yn;
+}
+
+void
+Delivery::no_outs_cuz_we_no_monitor (bool yn)
+{
+ _no_outs_cuz_we_no_monitor = yn;
+}
+
+bool
+Delivery::set_name (const std::string& name)
+{
+ bool ret = IOProcessor::set_name (name);
+
+ if (ret) {
+ ret = _panner->set_name (name);
+ }
+
+ return ret;
+}
+
+void
+Delivery::output_changed (IOChange change, void* src)
+{
+ if (change & ARDOUR::ConfigurationChanged) {
+ reset_panner ();
+ }
+}
diff --git a/libs/ardour/diskstream.cc b/libs/ardour/diskstream.cc
index bca3c74241..27a1c18ff4 100644
--- a/libs/ardour/diskstream.cc
+++ b/libs/ardour/diskstream.cc
@@ -138,6 +138,8 @@ void
Diskstream::set_io (IO& io)
{
_io = &io;
+ input_change_pending = ConfigurationChanged;
+ non_realtime_input_change ();
set_align_style_from_io ();
}
@@ -233,7 +235,7 @@ Diskstream::set_capture_offset ()
return;
}
- _capture_offset = _io->input_latency();
+ _capture_offset = _io->latency();
}
void
@@ -420,6 +422,11 @@ Diskstream::remove_region_from_last_capture (boost::weak_ptr<Region> wregion)
void
Diskstream::playlist_ranges_moved (list< Evoral::RangeMove<nframes_t> > const & movements_frames)
{
+#if 0
+
+ XXX THIS HAS TO BE FIXED FOR 3.0
+
+
if (Config->get_automation_follows_regions () == false) {
return;
}
@@ -431,7 +438,7 @@ Diskstream::playlist_ranges_moved (list< Evoral::RangeMove<nframes_t> > const &
}
/* move gain automation */
- boost::shared_ptr<AutomationList> gain_alist = _io->gain_control()->alist();
+ boost::shared_ptr<AutomationList> gain_alist = _io->gain_control()->list();
XMLNode & before = gain_alist->get_state ();
gain_alist->move_ranges (movements);
_session.add_command (
@@ -458,11 +465,12 @@ Diskstream::playlist_ranges_moved (list< Evoral::RangeMove<nframes_t> > const &
if (route) {
route->foreach_processor (sigc::bind (sigc::mem_fun (*this, &Diskstream::move_processor_automation), movements_frames));
}
+#endif
}
void
Diskstream::move_processor_automation (boost::weak_ptr<Processor> p,
- list< Evoral::RangeMove<nframes_t> > const & movements_frames)
+ list< Evoral::RangeMove<nframes_t> > const & movements_frames)
{
boost::shared_ptr<Processor> processor (p.lock ());
if (!processor) {
diff --git a/libs/ardour/enums.cc b/libs/ardour/enums.cc
index 7767381499..60d2b5177e 100644
--- a/libs/ardour/enums.cc
+++ b/libs/ardour/enums.cc
@@ -19,20 +19,21 @@
#include "pbd/enumwriter.h"
-#include "ardour/types.h"
-#include "ardour/delivery.h"
-#include "ardour/session.h"
-#include "ardour/location.h"
#include "ardour/audiofilesource.h"
-#include "ardour/diskstream.h"
#include "ardour/audioregion.h"
-#include "ardour/route_group.h"
-#include "ardour/panner.h"
-#include "ardour/track.h"
-#include "ardour/midi_track.h"
+#include "ardour/delivery.h"
+#include "ardour/diskstream.h"
#include "ardour/export_filename.h"
#include "ardour/export_format_base.h"
#include "ardour/export_profile_manager.h"
+#include "ardour/io.h"
+#include "ardour/location.h"
+#include "ardour/midi_track.h"
+#include "ardour/panner.h"
+#include "ardour/route_group.h"
+#include "ardour/session.h"
+#include "ardour/track.h"
+#include "ardour/types.h"
using namespace std;
using namespace PBD;
@@ -70,7 +71,6 @@ setup_enum_writer ()
SlaveSource _SlaveSource;
ShuttleBehaviour _ShuttleBehaviour;
ShuttleUnits _ShuttleUnits;
- mute_type _mute_type;
Session::RecordState _Session_RecordState;
Session::Event::Type _Session_Event_Type;
SmpteFormat _Session_SmpteFormat;
@@ -105,6 +105,7 @@ setup_enum_writer ()
ExportFormatBase::SRCQuality _ExportFormatBase_SRCQuality;
ExportProfileManager::TimeFormat _ExportProfileManager_TimeFormat;
Delivery::Role _Delivery_Role;
+ IO::Direction _IO_Direction;
#define REGISTER(e) enum_writer->register_distinct (typeid(e).name(), i, s); i.clear(); s.clear()
#define REGISTER_BITS(e) enum_writer->register_bits (typeid(e).name(), i, s); i.clear(); s.clear()
@@ -328,12 +329,6 @@ setup_enum_writer ()
REGISTER_CLASS_ENUM (Session, pullup_Minus4Minus1);
REGISTER (_Session_PullupFormat);
- REGISTER_ENUM (PRE_FADER);
- REGISTER_ENUM (POST_FADER);
- REGISTER_ENUM (CONTROL_OUTS);
- REGISTER_ENUM (MAIN_OUTS);
- REGISTER (_mute_type);
-
REGISTER_CLASS_ENUM (Route, Hidden);
REGISTER_CLASS_ENUM (Route, MasterOut);
REGISTER_CLASS_ENUM (Route, ControlOut);
@@ -502,9 +497,13 @@ setup_enum_writer ()
REGISTER_CLASS_ENUM (ExportProfileManager, Off);
REGISTER (_ExportProfileManager_TimeFormat);
- REGISTER_CLASS_ENUM (Delivery, Solo);
+ REGISTER_CLASS_ENUM (Delivery, Insert);
REGISTER_CLASS_ENUM (Delivery, Send);
REGISTER_CLASS_ENUM (Delivery, Listen);
REGISTER_CLASS_ENUM (Delivery, Main);
REGISTER_BITS (_Delivery_Role);
+
+ REGISTER_CLASS_ENUM (IO, Input);
+ REGISTER_CLASS_ENUM (IO, Output);
+ REGISTER (_IO_Direction);
}
diff --git a/libs/ardour/io.cc b/libs/ardour/io.cc
index ba3d70c184..a5d4e639e3 100644
--- a/libs/ardour/io.cc
+++ b/libs/ardour/io.cc
@@ -30,8 +30,10 @@
#include "pbd/xml++.h"
#include "pbd/replace_all.h"
#include "pbd/unknown_type.h"
+#include "pbd/enumwriter.h"
#include "ardour/audioengine.h"
+#include "ardour/buffer.h"
#include "ardour/io.h"
#include "ardour/route.h"
#include "ardour/port.h"
@@ -67,131 +69,46 @@ using namespace PBD;
const string IO::state_node_name = "IO";
bool IO::connecting_legal = false;
-bool IO::ports_legal = false;
-bool IO::panners_legal = false;
-sigc::signal<void> IO::Meter;
sigc::signal<int> IO::ConnectingLegal;
-sigc::signal<int> IO::PortsLegal;
-sigc::signal<int> IO::PannersLegal;
sigc::signal<void,ChanCount> IO::PortCountChanged;
-sigc::signal<void,nframes_t> IO::CycleStart;
-
-Glib::StaticMutex IO::m_meter_signal_lock = GLIBMM_STATIC_MUTEX_INIT;
-
-/* this is a default mapper of [0 .. 1.0] control values to a gain coefficient.
- others can be imagined.
-*/
-
-#if 0
-static gain_t direct_control_to_gain (double fract) {
- /* XXX Marcus writes: this doesn't seem right to me. but i don't have a better answer ... */
- /* this maxes at +6dB */
- return pow (2.0,(sqrt(sqrt(sqrt(fract)))*198.0-192.0)/6.0);
-}
-
-static double direct_gain_to_control (gain_t gain) {
- /* XXX Marcus writes: this doesn't seem right to me. but i don't have a better answer ... */
- if (gain == 0) return 0.0;
-
- return pow((6.0*log(gain)/log(2.0)+192.0)/198.0, 8.0);
-}
-#endif
/** @param default_type The type of port that will be created by ensure_io
* and friends if no type is explicitly requested (to avoid breakage).
*/
-IO::IO (Session& s, const string& name, DataType default_type)
+IO::IO (Session& s, const string& name, Direction dir, DataType default_type)
: SessionObject (s, name)
- , AutomatableControls (s)
- , _output_buffers (new BufferSet())
- , _active (true)
+ , _direction (dir)
, _default_type (default_type)
- , _amp (new Amp(s, *this))
- , _meter (new PeakMeter(s))
- , _panner (new Panner(name, s))
{
- _gain = 1.0;
+ _active = true;
pending_state_node = 0;
- no_panner_reset = false;
- _phase_invert = false;
- deferred_state = 0;
-
- boost::shared_ptr<AutomationList> gl(
- new AutomationList(Evoral::Parameter(GainAutomation)));
-
- _gain_control = boost::shared_ptr<GainControl>( new GainControl( X_("gaincontrol"), this, Evoral::Parameter(GainAutomation), gl ));
-
- add_control(_gain_control);
-
- {
- // IO::Meter is emitted from another thread so the
- // Meter signal must be protected.
- Glib::Mutex::Lock guard (m_meter_signal_lock);
- m_meter_connection = Meter.connect (mem_fun (*this, &IO::meter));
- }
-
- _output_offset = 0;
- CycleStart.connect (mem_fun (*this, &IO::cycle_start));
-
- _session.add_controllable (_gain_control);
-
- setup_bundles_for_inputs_and_outputs ();
+ setup_bundles ();
+ cerr << "+++ IO created with name = " << _name << endl;
}
IO::IO (Session& s, const XMLNode& node, DataType dt)
: SessionObject(s, "unnamed io")
- , AutomatableControls (s)
- , _output_buffers (new BufferSet())
- , _active(true)
+ , _direction (Input)
, _default_type (dt)
- , _amp (new Amp(s, *this))
- , _meter(new PeakMeter (_session))
{
- deferred_state = 0;
- no_panner_reset = false;
- _gain = 1.0;
-
- boost::shared_ptr<AutomationList> gl(
- new AutomationList(Evoral::Parameter(GainAutomation)));
-
- _gain_control = boost::shared_ptr<GainControl>(
- new GainControl( X_("gaincontrol"), this, Evoral::Parameter(GainAutomation), gl));
-
- add_control(_gain_control);
+ _active = true;
+ pending_state_node = 0;
set_state (node);
- {
- // IO::Meter is emitted from another thread so the
- // Meter signal must be protected.
- Glib::Mutex::Lock guard (m_meter_signal_lock);
- m_meter_connection = Meter.connect (mem_fun (*this, &IO::meter));
- }
-
- _output_offset = 0;
- CycleStart.connect (mem_fun (*this, &IO::cycle_start));
-
- _session.add_controllable (_gain_control);
-
- setup_bundles_for_inputs_and_outputs ();
+ setup_bundles ();
+ cerr << "+++ IO created from XML with name = " << _name << endl;
}
IO::~IO ()
{
- Glib::Mutex::Lock guard (m_meter_signal_lock);
Glib::Mutex::Lock lm (io_lock);
BLOCK_PROCESS_CALLBACK ();
- for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
- _session.engine().unregister_port (*i);
- }
-
- for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
+ for (PortSet::iterator i = _ports.begin(); i != _ports.end(); ++i) {
_session.engine().unregister_port (*i);
}
-
- m_meter_connection.disconnect();
}
void
@@ -199,131 +116,15 @@ IO::silence (nframes_t nframes)
{
/* io_lock, not taken: function must be called from Session::process() calltree */
- for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
+ for (PortSet::iterator i = _ports.begin(); i != _ports.end(); ++i) {
i->get_buffer(nframes).silence (nframes);
}
}
-/** Deliver bufs to the IO's output ports
- *
- * This function should automatically do whatever it necessary to correctly deliver bufs
- * to the outputs, eg applying gain or pan or whatever else needs to be done.
- */
-void
-IO::deliver_output (BufferSet& bufs, sframes_t start_frame, sframes_t end_frame, nframes_t nframes)
-{
- // Attach output buffers to port buffers
- output_buffers().attach_buffers (_outputs, nframes, _output_offset);
-
- // Use the panner to distribute audio to output port buffers
- if (_panner && _panner->npanners() && !_panner->bypassed()) {
-
- _panner->run_out_of_place(bufs, output_buffers(), start_frame, end_frame, nframes);
-
- // Do a 1:1 copy of data to output ports
- } else {
- if (bufs.count().n_audio() > 0 && _outputs.count().n_audio () > 0) {
- copy_to_outputs (bufs, DataType::AUDIO, nframes);
- }
- if (bufs.count().n_midi() > 0 && _outputs.count().n_midi () > 0) {
- copy_to_outputs (bufs, DataType::MIDI, nframes);
- }
- }
-
- // Apply gain to output buffers if gain automation isn't playing
- if ( ! _amp->apply_gain_automation()) {
-
- gain_t dg = _gain; // desired gain
-
- {
- Glib::Mutex::Lock dm (declick_lock, Glib::TRY_LOCK);
-
- if (dm.locked()) {
- dg = _gain_control->user_float();
- }
-
- }
-
- if (dg != _gain || dg != 1.0) {
- Amp::apply_gain(output_buffers(), nframes, _gain, dg, _phase_invert);
- _gain = dg;
- }
- }
-
-}
-
-void
-IO::copy_to_outputs (BufferSet& bufs, DataType type, nframes_t nframes)
-{
- // Copy any buffers 1:1 to outputs
-
- PortSet::iterator o = _outputs.begin(type);
- BufferSet::iterator i = bufs.begin(type);
- BufferSet::iterator prev = i;
-
- while (i != bufs.end(type) && o != _outputs.end (type)) {
- Buffer& port_buffer (o->get_buffer (nframes));
- port_buffer.read_from (*i, nframes, _output_offset);
- prev = i;
- ++i;
- ++o;
- }
-
- // Copy last buffer to any extra outputs
- while (o != _outputs.end(type)) {
- Buffer& port_buffer (o->get_buffer (nframes));
- port_buffer.read_from (*prev, nframes, _output_offset);
- ++o;
- }
-}
-
void
-IO::collect_input (BufferSet& outs, nframes_t nframes, ChanCount offset)
+IO::check_bundles_connected ()
{
- assert(outs.available() >= n_inputs());
-
- if (n_inputs() == ChanCount::ZERO) {
- return;
- }
-
- outs.set_count(n_inputs());
-
- for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
- PortSet::iterator i = _inputs.begin(*t);
- BufferSet::iterator o = outs.begin(*t);
-
- for (uint32_t off = 0; off < offset.get(*t); ++off, ++o) {
- if (o == outs.end(*t)) {
- continue;
- }
- }
-
- for ( ; i != _inputs.end(*t); ++i, ++o) {
- Buffer& b (i->get_buffer (nframes));
- o->read_from (b, nframes);
- }
- }
-}
-
-void
-IO::just_meter_input (sframes_t start_frame, sframes_t end_frame, nframes_t nframes)
-{
- BufferSet& bufs = _session.get_scratch_buffers (n_inputs());
- collect_input (bufs, nframes);
- _meter->run_in_place (bufs, start_frame, end_frame, nframes);
-}
-
-
-void
-IO::check_bundles_connected_to_inputs ()
-{
- check_bundles (_bundles_connected_to_inputs, inputs());
-}
-
-void
-IO::check_bundles_connected_to_outputs ()
-{
- check_bundles (_bundles_connected_to_outputs, outputs());
+ check_bundles (_bundles_connected, ports());
}
void
@@ -335,7 +136,7 @@ IO::check_bundles (std::vector<UserBundleInfo>& list, const PortSet& ports)
uint32_t const N = i->bundle->nchannels ();
- if (ports.num_ports (default_type()) < N) {
+ if (_ports.num_ports (default_type()) < N) {
continue;
}
@@ -368,7 +169,7 @@ IO::check_bundles (std::vector<UserBundleInfo>& list, const PortSet& ports)
int
-IO::disconnect_input (Port* our_port, string other_port, void* src)
+IO::disconnect (Port* our_port, string other_port, void* src)
{
if (other_port.length() == 0 || our_port == 0) {
return 0;
@@ -382,29 +183,29 @@ IO::disconnect_input (Port* our_port, string other_port, void* src)
/* check that our_port is really one of ours */
- if ( ! _inputs.contains(our_port)) {
+ if ( ! _ports.contains(our_port)) {
return -1;
}
/* disconnect it from the source */
if (our_port->disconnect (other_port)) {
- error << string_compose(_("IO: cannot disconnect input port %1 from %2"), our_port->name(), other_port) << endmsg;
+ error << string_compose(_("IO: cannot disconnect port %1 from %2"), our_port->name(), other_port) << endmsg;
return -1;
}
- check_bundles_connected_to_inputs ();
+ check_bundles_connected ();
}
}
- input_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
+ changed (ConnectionsChanged, src); /* EMIT SIGNAL */
_session.set_dirty ();
return 0;
}
int
-IO::connect_input (Port* our_port, string other_port, void* src)
+IO::connect (Port* our_port, string other_port, void* src)
{
if (other_port.length() == 0 || our_port == 0) {
return 0;
@@ -418,7 +219,7 @@ IO::connect_input (Port* our_port, string other_port, void* src)
/* check that our_port is really one of ours */
- if ( ! _inputs.contains(our_port) ) {
+ if ( ! _ports.contains(our_port) ) {
return -1;
}
@@ -430,99 +231,13 @@ IO::connect_input (Port* our_port, string other_port, void* src)
}
}
- input_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
- _session.set_dirty ();
- return 0;
-}
-
-int
-IO::disconnect_output (Port* our_port, string other_port, void* src)
-{
- if (other_port.length() == 0 || our_port == 0) {
- return 0;
- }
-
- {
- BLOCK_PROCESS_CALLBACK ();
-
- {
- Glib::Mutex::Lock lm (io_lock);
-
- /* check that our_port is really one of ours */
-
- if ( ! _outputs.contains(our_port) ) {
- return -1;
- }
-
- /* disconnect it from the destination */
-
- if (our_port->disconnect (other_port)) {
- error << string_compose(_("IO: cannot disconnect output port %1 from %2"), our_port->name(), other_port) << endmsg;
- return -1;
- }
-
- check_bundles_connected_to_outputs ();
- }
- }
-
- output_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
+ changed (ConnectionsChanged, src); /* EMIT SIGNAL */
_session.set_dirty ();
return 0;
}
int
-IO::connect_output (Port* our_port, string other_port, void* src)
-{
- if (other_port.length() == 0 || our_port == 0) {
- return 0;
- }
-
- {
- BLOCK_PROCESS_CALLBACK ();
-
-
- {
- Glib::Mutex::Lock lm (io_lock);
-
- /* check that our_port is really one of ours */
-
- if ( ! _outputs.contains(our_port) ) {
- return -1;
- }
-
- /* connect it to the destination */
-
- if (our_port->connect (other_port)) {
- return -1;
- }
- }
- }
-
- output_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
- _session.set_dirty ();
- return 0;
-}
-
-int
-IO::set_input (Port* other_port, void* src)
-{
- /* this removes all but one ports, and connects that one port
- to the specified source.
- */
-
- if (!other_port) {
- return -1;
- }
-
- if (ensure_inputs (ChanCount(other_port->type(), 1), true, true, src)) {
- return -1;
- }
-
- return connect_input (_inputs.port(0), other_port->name(), src);
-}
-
-int
-IO::remove_output_port (Port* port, void* src)
+IO::remove_port (Port* port, void* src)
{
IOChange change (NoChange);
@@ -533,7 +248,7 @@ IO::remove_output_port (Port* port, void* src)
{
Glib::Mutex::Lock lm (io_lock);
- if (_outputs.remove(port)) {
+ if (_ports.remove(port)) {
change = IOChange (change|ConfigurationChanged);
if (port->connected()) {
@@ -541,22 +256,19 @@ IO::remove_output_port (Port* port, void* src)
}
_session.engine().unregister_port (*port);
- check_bundles_connected_to_outputs ();
-
- setup_peak_meters ();
- reset_panner ();
+ check_bundles_connected ();
}
}
- PortCountChanged (n_outputs()); /* EMIT SIGNAL */
+ PortCountChanged (n_ports()); /* EMIT SIGNAL */
}
if (change == ConfigurationChanged) {
- setup_bundle_for_outputs ();
+ setup_bundles ();
}
if (change != NoChange) {
- output_changed (change, src);
+ changed (change, src);
_session.set_dirty ();
return 0;
}
@@ -571,12 +283,13 @@ IO::remove_output_port (Port* port, void* src)
* @param type Data type of port. Default value (NIL) will use this IO's default type.
*/
int
-IO::add_output_port (string destination, void* src, DataType type)
+IO::add_port (string destination, void* src, DataType type)
{
Port* our_port;
- if (type == DataType::NIL)
+ if (type == DataType::NIL) {
type = _default_type;
+ }
{
BLOCK_PROCESS_CALLBACK ();
@@ -587,19 +300,24 @@ IO::add_output_port (string destination, void* src, DataType type)
/* Create a new output port */
- string portname = build_legal_port_name (type, false);
-
- if ((our_port = _session.engine().register_output_port (type, portname)) == 0) {
- error << string_compose(_("IO: cannot register output port %1"), portname) << endmsg;
- return -1;
+ string portname = build_legal_port_name (type);
+
+ if (_direction == Input) {
+ if ((our_port = _session.engine().register_input_port (type, portname)) == 0) {
+ error << string_compose(_("IO: cannot register input port %1"), portname) << endmsg;
+ return -1;
+ }
+ } else {
+ if ((our_port = _session.engine().register_output_port (type, portname)) == 0) {
+ error << string_compose(_("IO: cannot register output port %1"), portname) << endmsg;
+ return -1;
+ }
}
-
- _outputs.add (our_port);
- setup_peak_meters ();
- reset_panner ();
+
+ _ports.add (our_port);
}
- PortCountChanged (n_outputs()); /* EMIT SIGNAL */
+ PortCountChanged (n_ports()); /* EMIT SIGNAL */
}
if (destination.length()) {
@@ -609,111 +327,15 @@ IO::add_output_port (string destination, void* src, DataType type)
}
// pan_changed (src); /* EMIT SIGNAL */
- output_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
- setup_bundle_for_outputs ();
+ changed (ConfigurationChanged, src); /* EMIT SIGNAL */
+ setup_bundles ();
_session.set_dirty ();
return 0;
}
int
-IO::remove_input_port (Port* port, void* src)
-{
- IOChange change (NoChange);
-
- {
- BLOCK_PROCESS_CALLBACK ();
-
-
- {
- Glib::Mutex::Lock lm (io_lock);
-
- if (_inputs.remove(port)) {
- change = IOChange (change|ConfigurationChanged);
-
- if (port->connected()) {
- change = IOChange (change|ConnectionsChanged);
- }
-
- _session.engine().unregister_port (*port);
- check_bundles_connected_to_inputs ();
-
- setup_peak_meters ();
- reset_panner ();
- }
- }
-
- PortCountChanged (n_inputs ()); /* EMIT SIGNAL */
- }
-
- if (change == ConfigurationChanged) {
- setup_bundle_for_inputs ();
- }
-
- if (change != NoChange) {
- input_changed (change, src);
- _session.set_dirty ();
- return 0;
- }
-
- return -1;
-}
-
-
-/** Add an input port.
- *
- * @param type Data type of port. The appropriate port type, and @ref Port will be created.
- * @param destination Name of input port to connect new port to.
- * @param src Source for emitted ConfigurationChanged signal.
- */
-int
-IO::add_input_port (string source, void* src, DataType type)
-{
- Port* our_port;
-
- if (type == DataType::NIL)
- type = _default_type;
-
- {
- BLOCK_PROCESS_CALLBACK ();
-
- {
- Glib::Mutex::Lock lm (io_lock);
-
- /* Create a new input port */
-
- string portname = build_legal_port_name (type, true);
-
- if ((our_port = _session.engine().register_input_port (type, portname)) == 0) {
- error << string_compose(_("IO: cannot register input port %1"), portname) << endmsg;
- return -1;
- }
-
- _inputs.add (our_port);
- setup_peak_meters ();
- reset_panner ();
- }
-
- PortCountChanged (n_inputs()); /* EMIT SIGNAL */
- }
-
- if (source.length()) {
-
- if (our_port->connect (source)) {
- return -1;
- }
- }
-
- // pan_changed (src); /* EMIT SIGNAL */
- input_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
- setup_bundle_for_inputs ();
- _session.set_dirty ();
-
- return 0;
-}
-
-int
-IO::disconnect_inputs (void* src)
+IO::disconnect (void* src)
{
{
BLOCK_PROCESS_CALLBACK ();
@@ -721,46 +343,23 @@ IO::disconnect_inputs (void* src)
{
Glib::Mutex::Lock lm (io_lock);
- for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
+ for (PortSet::iterator i = _ports.begin(); i != _ports.end(); ++i) {
i->disconnect_all ();
}
- check_bundles_connected_to_inputs ();
+ check_bundles_connected ();
}
}
- input_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
-
- return 0;
-}
-
-int
-IO::disconnect_outputs (void* src)
-{
- {
- BLOCK_PROCESS_CALLBACK ();
-
- {
- Glib::Mutex::Lock lm (io_lock);
-
- for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
- i->disconnect_all ();
- }
-
- check_bundles_connected_to_outputs ();
- }
- }
-
- output_changed (ConnectionsChanged, src); /* EMIT SIGNAL */
- _session.set_dirty ();
+ changed (ConnectionsChanged, src); /* EMIT SIGNAL */
return 0;
}
bool
-IO::ensure_inputs_locked (ChanCount count, bool clear, void* src)
+IO::ensure_ports_locked (ChanCount count, bool clear, void* src)
{
- Port* input_port = 0;
+ Port* port = 0;
bool changed = false;
for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
@@ -768,274 +367,55 @@ IO::ensure_inputs_locked (ChanCount count, bool clear, void* src)
const size_t n = count.get(*t);
/* remove unused ports */
- for (size_t i = n_inputs().get(*t); i > n; --i) {
- input_port = _inputs.port(*t, i-1);
-
- assert(input_port);
- _inputs.remove(input_port);
- _session.engine().unregister_port (*input_port);
+ for (size_t i = n_ports().get(*t); i > n; --i) {
+ port = _ports.port(*t, i-1);
+
+ assert(port);
+ _ports.remove(port);
+ _session.engine().unregister_port (*port);
changed = true;
}
/* create any necessary new ports */
- while (n_inputs().get(*t) < n) {
+ while (n_ports().get(*t) < n) {
- string portname = build_legal_port_name (*t, true);
+ string portname = build_legal_port_name (*t);
try {
- if ((input_port = _session.engine().register_input_port (*t, portname)) == 0) {
- error << string_compose(_("IO: cannot register input port %1"), portname) << endmsg;
- return -1;
- }
- }
-
- catch (AudioEngine::PortRegistrationFailure& err) {
- setup_peak_meters ();
- reset_panner ();
- /* pass it on */
- throw AudioEngine::PortRegistrationFailure();
- }
-
- _inputs.add (input_port);
- changed = true;
- }
- }
-
- if (changed) {
- check_bundles_connected_to_inputs ();
- setup_peak_meters ();
- reset_panner ();
- PortCountChanged (n_inputs()); /* EMIT SIGNAL */
- _session.set_dirty ();
- }
-
- if (clear) {
- /* disconnect all existing ports so that we get a fresh start */
- for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
- i->disconnect_all ();
- }
- }
-
- return changed;
-}
-
-int
-IO::ensure_io (ChanCount in, ChanCount out, bool clear, void* src)
-{
- bool in_changed = false;
- bool out_changed = false;
-
- assert(in != ChanCount::INFINITE);
- assert(out != ChanCount::INFINITE);
-
- if (in == n_inputs() && out == n_outputs() && !clear) {
- return 0;
- }
-
- {
- BLOCK_PROCESS_CALLBACK ();
- Glib::Mutex::Lock lm (io_lock);
-
- Port* port;
-
- for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
-
- const size_t nin = in.get(*t);
- const size_t nout = out.get(*t);
-
- Port* output_port = 0;
- Port* input_port = 0;
-
- /* remove unused output ports */
- for (size_t i = n_outputs().get(*t); i > nout; --i) {
- output_port = _outputs.port(*t, i-1);
-
- assert(output_port);
- _outputs.remove(output_port);
- _session.engine().unregister_port (*output_port);
-
- out_changed = true;
- }
-
- /* remove unused input ports */
- for (size_t i = n_inputs().get(*t); i > nin; --i) {
- input_port = _inputs.port(*t, i-1);
-
- assert(input_port);
- _inputs.remove(input_port);
- _session.engine().unregister_port (*input_port);
-
- in_changed = true;
- }
-
- /* create any necessary new input ports */
- while (n_inputs().get(*t) < nin) {
- string portname = build_legal_port_name (*t, true);
-
- try {
+ if (_direction == Input) {
if ((port = _session.engine().register_input_port (*t, portname)) == 0) {
error << string_compose(_("IO: cannot register input port %1"), portname) << endmsg;
return -1;
}
- }
-
- catch (AudioEngine::PortRegistrationFailure& err) {
- setup_peak_meters ();
- reset_panner ();
- /* pass it on */
- throw err;
- }
-
- _inputs.add (port);
- in_changed = true;
- }
-
- /* create any necessary new output ports */
-
- while (n_outputs().get(*t) < nout) {
-
- string portname = build_legal_port_name (*t, false);
-
- try {
+ } else {
if ((port = _session.engine().register_output_port (*t, portname)) == 0) {
error << string_compose(_("IO: cannot register output port %1"), portname) << endmsg;
return -1;
}
}
-
- catch (AudioEngine::PortRegistrationFailure& err) {
- setup_peak_meters ();
- reset_panner ();
- /* pass it on */
- throw err;
- }
-
- _outputs.add (port);
- out_changed = true;
}
- }
-
- if (clear) {
-
- /* disconnect all existing ports so that we get a fresh start */
-
- for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
- i->disconnect_all ();
- }
-
- for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
- i->disconnect_all ();
- }
- }
-
- if (in_changed || out_changed) {
- setup_peak_meters ();
- reset_panner ();
- }
- }
-
- if (out_changed) {
- check_bundles_connected_to_outputs ();
- output_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
- setup_bundle_for_outputs ();
- }
-
- if (in_changed) {
- check_bundles_connected_to_inputs ();
- input_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
- setup_bundle_for_inputs ();
- }
- if (in_changed || out_changed) {
- PortCountChanged (max (n_outputs(), n_inputs())); /* EMIT SIGNAL */
- _session.set_dirty ();
- }
-
- return 0;
-}
-
-int
-IO::ensure_inputs (ChanCount count, bool clear, bool lockit, void* src)
-{
- bool changed = false;
-
- if (count == n_inputs() && !clear) {
- return 0;
- }
-
- if (lockit) {
- BLOCK_PROCESS_CALLBACK ();
- Glib::Mutex::Lock im (io_lock);
- changed = ensure_inputs_locked (count, clear, src);
- } else {
- changed = ensure_inputs_locked (count, clear, src);
- }
-
- if (changed) {
- input_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
- setup_bundle_for_inputs ();
- _session.set_dirty ();
- }
- return 0;
-}
-
-bool
-IO::ensure_outputs_locked (ChanCount count, bool clear, void* src)
-{
- Port* output_port = 0;
- bool changed = false;
- bool need_pan_reset = false;
-
- if (n_outputs() != count) {
- need_pan_reset = true;
- }
-
- for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
-
- const size_t n = count.get(*t);
-
- /* remove unused ports */
- for (size_t i = n_outputs().get(*t); i > n; --i) {
- output_port = _outputs.port(*t, i-1);
-
- assert(output_port);
- _outputs.remove(output_port);
- _session.engine().unregister_port (*output_port);
-
- changed = true;
- }
-
- /* create any necessary new ports */
- while (n_outputs().get(*t) < n) {
-
- string portname = build_legal_port_name (*t, false);
-
- if ((output_port = _session.engine().register_output_port (*t, portname)) == 0) {
- error << string_compose(_("IO: cannot register output port %1"), portname) << endmsg;
- return -1;
+ catch (AudioEngine::PortRegistrationFailure& err) {
+ /* pass it on */
+ throw AudioEngine::PortRegistrationFailure();
}
- _outputs.add (output_port);
+ _ports.add (port);
changed = true;
- setup_peak_meters ();
-
- if (need_pan_reset) {
- reset_panner ();
- }
}
}
if (changed) {
- check_bundles_connected_to_outputs ();
- PortCountChanged (n_outputs()); /* EMIT SIGNAL */
+ check_bundles_connected ();
+ PortCountChanged (n_ports()); /* EMIT SIGNAL */
_session.set_dirty ();
}
if (clear) {
/* disconnect all existing ports so that we get a fresh start */
- for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
+ for (PortSet::iterator i = _ports.begin(); i != _ports.end(); ++i) {
i->disconnect_all ();
}
}
@@ -1043,71 +423,45 @@ IO::ensure_outputs_locked (ChanCount count, bool clear, void* src)
return changed;
}
+
int
-IO::ensure_outputs (ChanCount count, bool clear, bool lockit, void* src)
+IO::ensure_ports (ChanCount count, bool clear, bool lockit, void* src)
{
bool changed = false;
- /* XXX caller should hold io_lock, but generally doesn't */
+ cerr << "Ensure that IO " << _name << '/' << (_direction == Input ? "input" : "output")
+ << " has " << count << endl;
+
+ if (count == n_ports() && !clear) {
+ cerr << "\talready has " << n_ports() << endl;
+ return 0;
+ }
if (lockit) {
BLOCK_PROCESS_CALLBACK ();
Glib::Mutex::Lock im (io_lock);
- changed = ensure_outputs_locked (count, clear, src);
+ changed = ensure_ports_locked (count, clear, src);
} else {
- changed = ensure_outputs_locked (count, clear, src);
+ changed = ensure_ports_locked (count, clear, src);
}
if (changed) {
- output_changed (ConfigurationChanged, src); /* EMIT SIGNAL */
- setup_bundle_for_outputs ();
+ this->changed (ConfigurationChanged, src); /* EMIT SIGNAL */
+ setup_bundles ();
+ _session.set_dirty ();
}
+ cerr << "\t@" << this << " established with " << n_ports() << endl;
+
return 0;
}
-gain_t
-IO::effective_gain () const
-{
- return _gain_control->get_value();
-}
-
-void
-IO::reset_panner ()
-{
- if (panners_legal) {
- if (!no_panner_reset) {
- _panner->reset (n_outputs().n_audio(), pans_required());
- }
- } else {
- panner_legal_c.disconnect ();
- panner_legal_c = PannersLegal.connect (mem_fun (*this, &IO::panners_became_legal));
- }
-}
-
int
-IO::panners_became_legal ()
+IO::ensure_io (ChanCount count, bool clear, void* src)
{
- _panner->reset (n_outputs().n_audio(), pans_required());
- _panner->load (); // automation
- panner_legal_c.disconnect ();
- return 0;
+ return ensure_ports (count, clear, true, src);
}
-void
-IO::defer_pan_reset ()
-{
- no_panner_reset = true;
-}
-
-void
-IO::allow_pan_reset ()
-{
- no_panner_reset = false;
- reset_panner ();
-}
-
-
XMLNode&
IO::get_state (void)
{
@@ -1128,44 +482,26 @@ IO::state (bool full_state)
node->add_property("name", _name);
id().print (buf, sizeof (buf));
node->add_property("id", buf);
+ node->add_property ("direction", enum_2_string (_direction));
+ node->add_property ("default-type", _default_type.to_string());
- for (
- std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_inputs.begin();
- i != _bundles_connected_to_inputs.end();
- ++i
- )
- {
- XMLNode* n = new XMLNode ("InputBundle");
- n->add_property ("name", i->bundle->name ());
- node->add_child_nocopy (*n);
- }
-
- for (
- std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_outputs.begin();
- i != _bundles_connected_to_outputs.end();
- ++i
- )
- {
- XMLNode* n = new XMLNode ("OutputBundle");
+ for (std::vector<UserBundleInfo>::iterator i = _bundles_connected.begin(); i != _bundles_connected.end(); ++i) {
+ XMLNode* n = new XMLNode ("Bundle");
n->add_property ("name", i->bundle->name ());
node->add_child_nocopy (*n);
}
-
- str = "";
- for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
-
+ for (PortSet::iterator i = _ports.begin(); i != _ports.end(); ++i) {
+
vector<string> connections;
+ XMLNode* pnode = new XMLNode (X_("port"));
+ pnode->add_property (X_("type"), i->type().to_string());
+
if (i->get_connections (connections)) {
- str += '{';
-
for (n = 0, ci = connections.begin(); ci != connections.end(); ++ci, ++n) {
- if (n) {
- str += ',';
- }
-
+
/* if its a connection to our own port,
return only the port name, not the
whole thing. this allows connections
@@ -1173,60 +509,12 @@ IO::state (bool full_state)
client name is different.
*/
- str += _session.engine().make_port_name_relative (*ci);
+ pnode->add_property (X_("connection"), _session.engine().make_port_name_relative (*ci));
}
-
- str += '}';
-
- } else {
- str += "{}";
}
- }
-
- node->add_property ("inputs", str);
-
- str = "";
-
- for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
- vector<string> connections;
-
- if (i->get_connections (connections)) {
-
- str += '{';
-
- for (n = 0, ci = connections.begin(); ci != connections.end(); ++ci, ++n) {
- if (n) {
- str += ',';
- }
-
- str += _session.engine().make_port_name_relative (*ci);
- }
-
- str += '}';
-
- } else {
- str += "{}";
- }
+ node->add_child_nocopy (*pnode);
}
-
- node->add_property ("outputs", str);
-
- node->add_child_nocopy (_panner->state (full_state));
- node->add_child_nocopy (_gain_control->get_state ());
-
- snprintf (buf, sizeof(buf), "%2.12f", gain());
- node->add_property ("gain", buf);
-
- /* port counts */
-
- node->add_child_nocopy(*n_inputs().state("Inputs"));
- node->add_child_nocopy(*n_outputs().state("Outputs"));
-
- /* automation */
-
- if (full_state)
- node->add_child_nocopy (get_automation_state());
return *node;
}
@@ -1246,79 +534,34 @@ IO::set_state (const XMLNode& node)
error << string_compose(_("incorrect XML node \"%1\" passed to IO object"), node.name()) << endmsg;
return -1;
}
-
+
if ((prop = node.property ("name")) != 0) {
- _name = prop->value();
- /* used to set panner name with this, but no more */
- }
-
- if ((prop = node.property ("id")) != 0) {
- _id = prop->value ();
+ set_name (prop->value());
}
- if ((prop = node.property ("gain")) != 0) {
- set_gain (atof (prop->value().c_str()), this);
- _gain = _gain_control->user_float();
+ if ((prop = node.property (X_("default-type"))) != 0) {
+ _default_type = DataType(prop->value());
+ assert(_default_type != DataType::NIL);
}
- if ((prop = node.property ("automation-state")) != 0 || (prop = node.property ("automation-style")) != 0) {
- /* old school automation handling */
- }
-
- for (iter = node.children().begin(); iter != node.children().end(); ++iter) {
-
- // Old school Panner.
- if ((*iter)->name() == "Panner") {
- if (!_panner) {
- _panner = boost::shared_ptr<Panner>(new Panner (_name, _session));
- }
- _panner->set_state (**iter);
- }
-
- if ((*iter)->name() == "Processor") {
- if ((*iter)->property ("type") && ((*iter)->property ("type")->value() == "panner" ) ) {
- if (!_panner) {
- _panner = boost::shared_ptr<Panner>(new Panner (_name, _session));
- }
- _panner->set_state (**iter);
- }
- }
-
- if ((*iter)->name() == X_("Automation")) {
-
- set_automation_state (*(*iter), Evoral::Parameter(GainAutomation));
- }
-
- if ((*iter)->name() == X_("Controllable")) {
- if ((prop = (*iter)->property("name")) != 0 && prop->value() == "gaincontrol") {
- _gain_control->set_state (**iter);
- }
- }
+ if ((prop = node.property ("id")) != 0) {
+ _id = prop->value ();
}
- if (ports_legal) {
-
- if (create_ports (node)) {
- return -1;
- }
-
- } else {
-
- port_legal_c = PortsLegal.connect (mem_fun (*this, &IO::ports_became_legal));
+ if ((prop = node.property ("direction")) != 0) {
+ _direction = (Direction) string_2_enum (prop->value(), _direction);
}
- if (!_panner) {
- _panner = boost::shared_ptr<Panner>(new Panner (_name, _session));
- }
+ if (!connecting_legal) {
+ pending_state_node = new XMLNode (node);
+ }
- if (panners_legal) {
- reset_panner ();
- } else {
- panner_legal_c = PannersLegal.connect (mem_fun (*this, &IO::panners_became_legal));
+ if (create_ports (node)) {
+ return -1;
}
if (connecting_legal) {
-
+
if (make_connections (node)) {
return -1;
}
@@ -1328,83 +571,6 @@ IO::set_state (const XMLNode& node)
connection_legal_c = ConnectingLegal.connect (mem_fun (*this, &IO::connecting_became_legal));
}
- if (!ports_legal || !connecting_legal) {
- pending_state_node = new XMLNode (node);
- }
-
- return 0;
-}
-
-int
-IO::load_automation (string path)
-{
- string fullpath;
- ifstream in;
- char line[128];
- uint32_t linecnt = 0;
- float version;
- LocaleGuard lg (X_("POSIX"));
-
- fullpath = Glib::build_filename(_session.automation_dir(), path);
-
- in.open (fullpath.c_str());
-
- if (!in) {
- fullpath = Glib::build_filename(_session.automation_dir(), _session.snap_name() + '-' + path);
-
- in.open (fullpath.c_str());
-
- if (!in) {
- error << string_compose(_("%1: cannot open automation event file \"%2\""), _name, fullpath) << endmsg;
- return -1;
- }
- }
-
- clear_automation ();
-
- while (in.getline (line, sizeof(line), '\n')) {
- char type;
- nframes_t when;
- double value;
-
- if (++linecnt == 1) {
- if (memcmp (line, "version", 7) == 0) {
- if (sscanf (line, "version %f", &version) != 1) {
- error << string_compose(_("badly formed version number in automation event file \"%1\""), path) << endmsg;
- return -1;
- }
- } else {
- error << string_compose(_("no version information in automation event file \"%1\""), path) << endmsg;
- return -1;
- }
-
- continue;
- }
-
- if (sscanf (line, "%c %" PRIu32 " %lf", &type, &when, &value) != 3) {
- warning << string_compose(_("badly formatted automation event record at line %1 of %2 (ignored)"), linecnt, path) << endmsg;
- continue;
- }
-
- switch (type) {
- case 'g':
- _gain_control->list()->fast_simple_add (when, value);
- break;
-
- case 's':
- break;
-
- case 'm':
- break;
-
- case 'p':
- /* older (pre-1.0) versions of ardour used this */
- break;
-
- default:
- warning << _("dubious automation event found (and ignored)") << endmsg;
- }
- }
return 0;
}
@@ -1414,51 +580,25 @@ IO::connecting_became_legal ()
{
int ret;
- if (pending_state_node == 0) {
- fatal << _("IO::connecting_became_legal() called without a pending state node") << endmsg;
- /*NOTREACHED*/
- return -1;
- }
+ assert (pending_state_node);
connection_legal_c.disconnect ();
ret = make_connections (*pending_state_node);
-
- if (ports_legal) {
- delete pending_state_node;
- pending_state_node = 0;
- }
-
- return ret;
-}
-int
-IO::ports_became_legal ()
-{
- int ret;
-
- if (pending_state_node == 0) {
- fatal << _("IO::ports_became_legal() called without a pending state node") << endmsg;
- /*NOTREACHED*/
- return -1;
- }
-
- port_legal_c.disconnect ();
-
- ret = create_ports (*pending_state_node);
-
- if (connecting_legal) {
- delete pending_state_node;
- pending_state_node = 0;
- }
+
+ delete pending_state_node;
+ pending_state_node = 0;
return ret;
}
boost::shared_ptr<Bundle>
-IO::find_possible_bundle (const string &desired_name, const string &default_name, const string &bundle_type_name)
+IO::find_possible_bundle (const string &desired_name)
{
static const string digits = "0123456789";
-
+ const string &default_name = (_direction == Input ? _("in") : _("out"));
+ const string &bundle_type_name = (_direction == Input ? _("input") : _("output"));
+
boost::shared_ptr<Bundle> c = _session.bundle_by_name (desired_name);
if (!c) {
@@ -1547,77 +687,71 @@ IO::find_possible_bundle (const string &desired_name, const string &default_name
}
int
-IO::get_port_counts (const XMLNode& node, ChanCount& in, ChanCount& out,
- boost::shared_ptr<Bundle>& ic, boost::shared_ptr<Bundle>& oc)
+IO::get_port_counts (const XMLNode& node, ChanCount& n, boost::shared_ptr<Bundle>& c)
{
XMLProperty const * prop;
XMLNodeConstIterator iter;
+ uint32_t n_audio = 0;
+ uint32_t n_midi = 0;
+ ChanCount cnt;
- in = n_inputs();
- out = n_outputs();
+ n = n_ports();
- for (iter = node.children().begin(); iter != node.children().end(); ++iter) {
- if ((*iter)->name() == X_("Inputs")) {
- in = ChanCount::max(in, ChanCount(**iter));
- } else if ((*iter)->name() == X_("Outputs")) {
- out = ChanCount::max(out, ChanCount(**iter));
+ if ((prop = node.property ("connection")) != 0) {
+
+ if ((c = find_possible_bundle (prop->value())) != 0) {
+ n = ChanCount::max (n, ChanCount(c->type(), c->nchannels()));
}
+ return 0;
}
+
+ for (iter = node.children().begin(); iter != node.children().end(); ++iter) {
- if ((prop = node.property ("input-connection")) != 0) {
-
- ic = find_possible_bundle (prop->value(), _("in"), _("input"));
- if (ic) {
- in = ChanCount::max(in, ChanCount(ic->type(), ic->nchannels()));
+ if ((*iter)->name() == X_("Bundle")) {
+ if ((c = find_possible_bundle (prop->value())) != 0) {
+ n = ChanCount::max (n, ChanCount(c->type(), c->nchannels()));
+ return 0;
+ } else {
+ return -1;
+ }
}
- } else if ((prop = node.property ("inputs")) != 0) {
+ if ((*iter)->name() == X_("port")) {
+ prop = (*iter)->property (X_("type"));
- in = ChanCount::max(in, ChanCount(_default_type,
- count (prop->value().begin(), prop->value().end(), '{')));
- }
-
- if ((prop = node.property ("output-connection")) != 0) {
-
- oc = find_possible_bundle (prop->value(), _("out"), _("output"));
- if (oc) {
- out = ChanCount::max(out, ChanCount(oc->type(), oc->nchannels()));
+ if (!prop) {
+ continue;
+ }
+
+ if (prop->value() == X_("audio")) {
+ cnt.set_audio (++n_audio);
+ } else if (prop->value() == X_("midi")) {
+ cnt.set_midi (++n_midi);
+ }
}
-
- } else if ((prop = node.property ("outputs")) != 0) {
-
- out = ChanCount::max(out, ChanCount(_default_type,
- count (prop->value().begin(), prop->value().end(), '{')));
}
+ n = ChanCount::max (n, cnt);
return 0;
}
int
IO::create_ports (const XMLNode& node)
{
- if (pending_state_node) {
+ ChanCount n;
+ boost::shared_ptr<Bundle> c;
+
+ get_port_counts (node, n, c);
+
+ cerr << _name << " got " << n << " from XML node" << endl;
- ChanCount in;
- ChanCount out;
- boost::shared_ptr<Bundle> ic;
- boost::shared_ptr<Bundle> oc;
-
- no_panner_reset = true;
-
- get_port_counts (*pending_state_node, in, out, ic, oc);
-
- if (ensure_io (in, out, true, this)) {
- error << string_compose(_("%1: cannot create I/O ports"), _name) << endmsg;
- return -1;
- }
-
- /* XXX use ic and oc if relevant */
-
- no_panner_reset = false;
+ if (ensure_ports (n, true, true, this)) {
+ error << string_compose(_("%1: cannot create I/O ports"), _name) << endmsg;
+ return -1;
}
- set_deferred_state ();
+ /* XXX use c */
+
return 0;
}
@@ -1626,60 +760,41 @@ IO::make_connections (const XMLNode& node)
{
const XMLProperty* prop;
- if ((prop = node.property ("input-connection")) != 0) {
- boost::shared_ptr<Bundle> c = find_possible_bundle (prop->value(), _("in"), _("input"));
+ if ((prop = node.property ("connection")) != 0) {
+ boost::shared_ptr<Bundle> c = find_possible_bundle (prop->value());
if (!c) {
return -1;
}
- if (n_inputs().get(c->type()) == c->nchannels() && c->ports_are_outputs()) {
- connect_input_ports_to_bundle (c, this);
+ if (n_ports().get(c->type()) == c->nchannels() && c->ports_are_outputs()) {
+ connect_ports_to_bundle (c, this);
}
- } else if ((prop = node.property ("inputs")) != 0) {
- if (set_inputs (prop->value())) {
- error << string_compose(_("improper input channel list in XML node (%1)"), prop->value()) << endmsg;
- return -1;
- }
- }
+ return 0;
+ }
- if ((prop = node.property ("output-connection")) != 0) {
- boost::shared_ptr<Bundle> c = find_possible_bundle (prop->value(), _("out"), _("output"));
-
- if (!c) {
- return -1;
- }
-
- if (n_outputs().get(c->type()) == c->nchannels() && c->ports_are_inputs()) {
- connect_output_ports_to_bundle (c, this);
- }
-
- } else if ((prop = node.property ("outputs")) != 0) {
- if (set_outputs (prop->value())) {
- error << string_compose(_("improper output channel list in XML node (%1)"), prop->value()) << endmsg;
- return -1;
- }
- }
+ uint32_t n = 0;
for (XMLNodeConstIterator i = node.children().begin(); i != node.children().end(); ++i) {
- if ((*i)->name() == "InputBundle") {
+ if ((*i)->name() == "Bundle") {
XMLProperty const * prop = (*i)->property ("name");
if (prop) {
- boost::shared_ptr<Bundle> b = find_possible_bundle (prop->value(), _("in"), _("input"));
+ boost::shared_ptr<Bundle> b = find_possible_bundle (prop->value());
if (b) {
- connect_input_ports_to_bundle (b, this);
+ connect_ports_to_bundle (b, this);
}
}
-
- } else if ((*i)->name() == "OutputBundle") {
- XMLProperty const * prop = (*i)->property ("name");
- if (prop) {
- boost::shared_ptr<Bundle> b = find_possible_bundle (prop->value(), _("out"), _("output"));
- if (b) {
- connect_output_ports_to_bundle (b, this);
- }
+
+ return 0;
+ }
+
+ if ((*i)->name() == "port") {
+ Port* p = nth (n++);
+ XMLProperty* prop = (*i)->property ("connection");
+ if (p && prop) {
+ p->connect (prop->value());
}
}
}
@@ -1688,7 +803,7 @@ IO::make_connections (const XMLNode& node)
}
int
-IO::set_inputs (const string& str)
+IO::set_ports (const string& str)
{
vector<string> ports;
int i;
@@ -1700,7 +815,7 @@ IO::set_inputs (const string& str)
}
// FIXME: audio-only
- if (ensure_inputs (ChanCount(DataType::AUDIO, nports), true, true, this)) {
+ if (ensure_ports (ChanCount(DataType::AUDIO, nports), true, true, this)) {
return -1;
}
@@ -1727,58 +842,7 @@ IO::set_inputs (const string& str)
} else if (n > 0) {
for (int x = 0; x < n; ++x) {
- connect_input (input (i), ports[x], this);
- }
- }
-
- ostart = end+1;
- i++;
- }
-
- return 0;
-}
-
-int
-IO::set_outputs (const string& str)
-{
- vector<string> ports;
- int i;
- int n;
- uint32_t nports;
-
- if ((nports = count (str.begin(), str.end(), '{')) == 0) {
- return 0;
- }
-
- // FIXME: audio-only - need a way to identify port types from XML/string
- if (ensure_outputs (ChanCount(DataType::AUDIO, nports), true, true, this)) {
- return -1;
- }
-
- string::size_type start, end, ostart;
-
- ostart = 0;
- start = 0;
- end = 0;
- i = 0;
-
- while ((start = str.find_first_of ('{', ostart)) != string::npos) {
- start += 1;
-
- if ((end = str.find_first_of ('}', start)) == string::npos) {
- error << string_compose(_("IO: badly formed string in XML node for outputs \"%1\""), str) << endmsg;
- return -1;
- }
-
- if ((n = parse_io_string (str.substr (start, end - start), ports)) < 0) {
- error << string_compose(_("IO: bad output string in XML node \"%1\""), str) << endmsg;
-
- return -1;
-
- } else if (n > 0) {
-
- for (int x = 0; x < n; ++x) {
- connect_output (output (i), ports[x], this);
+ connect (nth (i), ports[x], this);
}
}
@@ -1858,13 +922,7 @@ IO::set_name (const string& requested_name)
warning << _("you cannot use colons to name objects with I/O connections") << endmsg;
}
- for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
- string current_name = i->name();
- current_name.replace (current_name.find (_name), _name.length(), name);
- i->set_name (current_name);
- }
-
- for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
+ for (PortSet::iterator i = _ports.begin(); i != _ports.end(); ++i) {
string current_name = i->name();
current_name.replace (current_name.find (_name), _name.length(), name);
i->set_name (current_name);
@@ -1872,7 +930,7 @@ IO::set_name (const string& requested_name)
bool const r = SessionObject::set_name(name);
- setup_bundles_for_inputs_and_outputs ();
+ setup_bundles ();
return r;
}
@@ -1882,13 +940,13 @@ IO::set_port_latency (nframes_t nframes)
{
Glib::Mutex::Lock lm (io_lock);
- for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
+ for (PortSet::iterator i = _ports.begin(); i != _ports.end(); ++i) {
i->set_latency (nframes);
}
}
nframes_t
-IO::output_latency () const
+IO::latency () const
{
nframes_t max_latency;
nframes_t latency;
@@ -1897,26 +955,7 @@ IO::output_latency () const
/* io lock not taken - must be protected by other means */
- for (PortSet::const_iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
- if ((latency = i->total_latency ()) > max_latency) {
- max_latency = latency;
- }
- }
-
- return max_latency;
-}
-
-nframes_t
-IO::input_latency () const
-{
- nframes_t max_latency;
- nframes_t latency;
-
- max_latency = 0;
-
- /* io lock not taken - must be protected by other means */
-
- for (PortSet::const_iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
+ for (PortSet::const_iterator i = _ports.begin(); i != _ports.end(); ++i) {
if ((latency = i->total_latency ()) > max_latency) {
max_latency = latency;
}
@@ -1925,74 +964,24 @@ IO::input_latency () const
return max_latency;
}
-int
-IO::connect_input_ports_to_bundle (boost::shared_ptr<Bundle> c, void* src)
-{
- {
- BLOCK_PROCESS_CALLBACK ();
- Glib::Mutex::Lock lm2 (io_lock);
-
- c->connect (_bundle_for_inputs, _session.engine());
-
- /* If this is a UserBundle, make a note of what we've done */
-
- boost::shared_ptr<UserBundle> ub = boost::dynamic_pointer_cast<UserBundle> (c);
- if (ub) {
-
- /* See if we already know about this one */
- std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_inputs.begin();
- while (i != _bundles_connected_to_inputs.end() && i->bundle != ub) {
- ++i;
- }
-
- if (i == _bundles_connected_to_inputs.end()) {
- /* We don't, so make a note */
- _bundles_connected_to_inputs.push_back (UserBundleInfo (this, ub));
- }
- }
- }
-
- input_changed (IOChange (ConfigurationChanged|ConnectionsChanged), src); /* EMIT SIGNAL */
- return 0;
-}
-
-int
-IO::disconnect_input_ports_from_bundle (boost::shared_ptr<Bundle> c, void* src)
+void
+IO::update_port_total_latencies ()
{
- {
- BLOCK_PROCESS_CALLBACK ();
- Glib::Mutex::Lock lm2 (io_lock);
-
- c->disconnect (_bundle_for_inputs, _session.engine());
-
- /* If this is a UserBundle, make a note of what we've done */
-
- boost::shared_ptr<UserBundle> ub = boost::dynamic_pointer_cast<UserBundle> (c);
- if (ub) {
-
- std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_inputs.begin();
- while (i != _bundles_connected_to_inputs.end() && i->bundle != ub) {
- ++i;
- }
+ /* io_lock, not taken: function must be called from Session::process() calltree */
- if (i != _bundles_connected_to_inputs.end()) {
- _bundles_connected_to_inputs.erase (i);
- }
- }
+ for (PortSet::iterator i = _ports.begin(); i != _ports.end(); ++i) {
+ _session.engine().update_total_latency (*i);
}
-
- input_changed (IOChange (ConfigurationChanged|ConnectionsChanged), src); /* EMIT SIGNAL */
- return 0;
}
int
-IO::connect_output_ports_to_bundle (boost::shared_ptr<Bundle> c, void* src)
+IO::connect_ports_to_bundle (boost::shared_ptr<Bundle> c, void* src)
{
{
BLOCK_PROCESS_CALLBACK ();
Glib::Mutex::Lock lm2 (io_lock);
- c->connect (_bundle_for_outputs, _session.engine());
+ c->connect (_bundle, _session.engine());
/* If this is a UserBundle, make a note of what we've done */
@@ -2000,49 +989,48 @@ IO::connect_output_ports_to_bundle (boost::shared_ptr<Bundle> c, void* src)
if (ub) {
/* See if we already know about this one */
- std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_outputs.begin();
- while (i != _bundles_connected_to_outputs.end() && i->bundle != ub) {
+ std::vector<UserBundleInfo>::iterator i = _bundles_connected.begin();
+ while (i != _bundles_connected.end() && i->bundle != ub) {
++i;
}
- if (i == _bundles_connected_to_outputs.end()) {
+ if (i == _bundles_connected.end()) {
/* We don't, so make a note */
- _bundles_connected_to_outputs.push_back (UserBundleInfo (this, ub));
+ _bundles_connected.push_back (UserBundleInfo (this, ub));
}
}
}
- output_changed (IOChange (ConnectionsChanged|ConfigurationChanged), src); /* EMIT SIGNAL */
-
+ changed (IOChange (ConfigurationChanged|ConnectionsChanged), src); /* EMIT SIGNAL */
return 0;
}
int
-IO::disconnect_output_ports_from_bundle (boost::shared_ptr<Bundle> c, void* src)
+IO::disconnect_ports_from_bundle (boost::shared_ptr<Bundle> c, void* src)
{
{
BLOCK_PROCESS_CALLBACK ();
Glib::Mutex::Lock lm2 (io_lock);
- c->disconnect (_bundle_for_outputs, _session.engine());
+ c->disconnect (_bundle, _session.engine());
/* If this is a UserBundle, make a note of what we've done */
boost::shared_ptr<UserBundle> ub = boost::dynamic_pointer_cast<UserBundle> (c);
if (ub) {
- std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_outputs.begin();
- while (i != _bundles_connected_to_outputs.end() && i->bundle != ub) {
+ std::vector<UserBundleInfo>::iterator i = _bundles_connected.begin();
+ while (i != _bundles_connected.end() && i->bundle != ub) {
++i;
}
- if (i != _bundles_connected_to_outputs.end()) {
- _bundles_connected_to_outputs.erase (i);
+ if (i != _bundles_connected.end()) {
+ _bundles_connected.erase (i);
}
}
}
- output_changed (IOChange (ConfigurationChanged|ConnectionsChanged), src); /* EMIT SIGNAL */
+ changed (IOChange (ConfigurationChanged|ConnectionsChanged), src); /* EMIT SIGNAL */
return 0;
}
@@ -2061,34 +1049,6 @@ IO::enable_connecting ()
return ConnectingLegal ();
}
-int
-IO::disable_ports ()
-{
- ports_legal = false;
- return 0;
-}
-
-int
-IO::enable_ports ()
-{
- ports_legal = true;
- return PortsLegal ();
-}
-
-int
-IO::disable_panners (void)
-{
- panners_legal = false;
- return 0;
-}
-
-int
-IO::reset_panners ()
-{
- panners_legal = true;
- return PannersLegal ();
-}
-
void
IO::bundle_changed (Bundle::Change c)
{
@@ -2096,200 +1056,9 @@ IO::bundle_changed (Bundle::Change c)
// connect_input_ports_to_bundle (_input_bundle, this);
}
-void
-IO::GainControl::set_value (float val)
-{
- // max gain at about +6dB (10.0 ^ ( 6 dB * 0.05))
- if (val > 1.99526231f)
- val = 1.99526231f;
-
- _io->set_gain (val, this);
-
- AutomationControl::set_value(val);
-}
-
-float
-IO::GainControl::get_value (void) const
-{
- return AutomationControl::get_value();
-}
-
-void
-IO::setup_peak_meters()
-{
- ChanCount max_streams = std::max (_inputs.count(), _outputs.count());
- _meter->configure_io (max_streams, max_streams);
-}
-
-/**
- Update the peak meters.
-
- The meter signal lock is taken to prevent modification of the
- Meter signal while updating the meters, taking the meter signal
- lock prior to taking the io_lock ensures that all IO will remain
- valid while metering.
-*/
-void
-IO::update_meters()
-{
- Glib::Mutex::Lock guard (m_meter_signal_lock);
- Meter(); /* EMIT SIGNAL */
-}
-
-void
-IO::meter ()
-{
- // FIXME: Ugly. Meter should manage the lock, if it's necessary
-
- Glib::Mutex::Lock lm (io_lock); // READER: meter thread.
- _meter->meter();
-}
-
-void
-IO::clear_automation ()
-{
- data().clear_controls (); // clears gain automation
- _panner->data().clear_controls ();
-}
-
-void
-IO::set_parameter_automation_state (Evoral::Parameter param, AutoState state)
-{
- // XXX: would be nice to get rid of this special hack
-
- if (param.type() == GainAutomation) {
-
- bool changed = false;
-
- {
- Glib::Mutex::Lock lm (control_lock());
-
- boost::shared_ptr<AutomationList> gain_auto
- = boost::dynamic_pointer_cast<AutomationList>(_gain_control->list());
-
- if (state != gain_auto->automation_state()) {
- changed = true;
- _last_automation_snapshot = 0;
- gain_auto->set_automation_state (state);
-
- if (state != Off) {
- // FIXME: shouldn't this use Curve?
- set_gain (gain_auto->eval (_session.transport_frame()), this);
- }
- }
- }
-
- if (changed) {
- _session.set_dirty ();
- }
-
- } else {
- AutomatableControls::set_parameter_automation_state(param, state);
- }
-}
-
-void
-IO::inc_gain (gain_t factor, void *src)
-{
- float desired_gain = _gain_control->user_float();
- if (desired_gain == 0.0f) {
- set_gain (0.000001f + (0.000001f * factor), src);
- } else {
- set_gain (desired_gain + (desired_gain * factor), src);
- }
-}
-
-void
-IO::set_gain (gain_t val, void *src)
-{
- // max gain at about +6dB (10.0 ^ ( 6 dB * 0.05))
- if (val > 1.99526231f) {
- val = 1.99526231f;
- }
-
- //cerr << "set desired gain to " << val << " when curgain = " << _gain_control->get_value () << endl;
-
- if (src != _gain_control.get()) {
- _gain_control->set_value(val);
- // bit twisty, this will come back and call us again
- // (this keeps control in sync with reality)
- return;
- }
-
- {
- Glib::Mutex::Lock dm (declick_lock);
- _gain_control->set_float(val, false);
- }
-
- if (_session.transport_stopped()) {
- // _gain = val;
- }
-
- /*
- if (_session.transport_stopped() && src != 0 && src != this && _gain_control->automation_write()) {
- _gain_control->list()->add (_session.transport_frame(), val);
-
- }
- */
-
- _session.set_dirty();
-}
-
-void
-IO::start_pan_touch (uint32_t which)
-{
- if (which < _panner->npanners()) {
- (*_panner).pan_control(which)->start_touch();
- }
-}
-
-void
-IO::end_pan_touch (uint32_t which)
-{
- if (which < _panner->npanners()) {
- (*_panner).pan_control(which)->stop_touch();
- }
-
-}
-
-void
-IO::automation_snapshot (nframes_t now, bool force)
-{
- AutomatableControls::automation_snapshot (now, force);
- // XXX: This seems to be wrong.
- // drobilla: shouldnt automation_snapshot for panner be called
- // "automagically" because its an Automatable now ?
- //
- // we could dump this whole method then. <3
-
- if (_last_automation_snapshot > now || (now - _last_automation_snapshot) > _automation_interval) {
- _panner->automation_snapshot (now, force);
- }
-
- _panner->automation_snapshot (now, force);
- _last_automation_snapshot = now;
-}
-
-void
-IO::transport_stopped (nframes_t frame)
-{
- _gain_control->list()->reposition_for_rt_add (frame);
-
- if (_gain_control->automation_state() != Off) {
-
- /* the src=0 condition is a special signal to not propagate
- automation gain changes into the mix group when locating.
- */
-
- // FIXME: shouldn't this use Curve?
- set_gain (_gain_control->list()->eval (frame), 0);
- }
-
- _panner->transport_stopped (frame);
-}
string
-IO::build_legal_port_name (DataType type, bool in)
+IO::build_legal_port_name (DataType type)
{
const int name_size = jack_port_name_size();
int limit;
@@ -2303,7 +1072,7 @@ IO::build_legal_port_name (DataType type, bool in)
throw unknown_type();
}
- if (in) {
+ if (_direction == Input) {
suffix += _("_in");
} else {
suffix += _("_out");
@@ -2318,60 +1087,20 @@ IO::build_legal_port_name (DataType type, bool in)
snprintf (buf1, name_size+1, ("%.*s/%s"), limit, _name.c_str(), suffix.c_str());
- int port_number;
-
- if (in) {
- port_number = find_input_port_hole (buf1);
- } else {
- port_number = find_output_port_hole (buf1);
- }
-
+ int port_number = find_port_hole (buf1);
snprintf (buf2, name_size+1, "%s %d", buf1, port_number);
return string (buf2);
}
int32_t
-IO::find_input_port_hole (const char* base)
-{
- /* CALLER MUST HOLD IO LOCK */
-
- uint32_t n;
-
- if (_inputs.empty()) {
- return 1;
- }
-
- /* we only allow up to 4 characters for the port number
- */
-
- for (n = 1; n < 9999; ++n) {
- char buf[jack_port_name_size()];
- PortSet::iterator i = _inputs.begin();
-
- snprintf (buf, jack_port_name_size(), _("%s %u"), base, n);
-
- for ( ; i != _inputs.end(); ++i) {
- if (i->name() == buf) {
- break;
- }
- }
-
- if (i == _inputs.end()) {
- break;
- }
- }
- return n;
-}
-
-int32_t
-IO::find_output_port_hole (const char* base)
+IO::find_port_hole (const char* base)
{
/* CALLER MUST HOLD IO LOCK */
uint32_t n;
- if (_outputs.empty()) {
+ if (_ports.empty()) {
return 1;
}
@@ -2380,213 +1109,109 @@ IO::find_output_port_hole (const char* base)
for (n = 1; n < 9999; ++n) {
char buf[jack_port_name_size()];
- PortSet::iterator i = _outputs.begin();
+ PortSet::iterator i = _ports.begin();
snprintf (buf, jack_port_name_size(), _("%s %u"), base, n);
- for ( ; i != _outputs.end(); ++i) {
+ for ( ; i != _ports.end(); ++i) {
if (i->name() == buf) {
break;
}
}
- if (i == _outputs.end()) {
+ if (i == _ports.end()) {
break;
}
}
-
return n;
}
-void
-IO::set_active (bool yn)
-{
- _active = yn;
- active_changed(); /* EMIT SIGNAL */
-}
-
-AudioPort*
-IO::audio_input(uint32_t n) const
-{
- return dynamic_cast<AudioPort*>(input(n));
-}
AudioPort*
-IO::audio_output(uint32_t n) const
+IO::audio(uint32_t n) const
{
- return dynamic_cast<AudioPort*>(output(n));
-}
+ return _ports.nth_audio_port (n);
-MidiPort*
-IO::midi_input(uint32_t n) const
-{
- return dynamic_cast<MidiPort*>(input(n));
}
MidiPort*
-IO::midi_output(uint32_t n) const
-{
- return dynamic_cast<MidiPort*>(output(n));
-}
-
-void
-IO::set_phase_invert (bool yn, void *src)
-{
- if (_phase_invert != yn) {
- _phase_invert = yn;
- // phase_invert_changed (src); /* EMIT SIGNAL */
- }
-}
-
-void
-IO::set_denormal_protection (bool yn, void *src)
+IO::midi(uint32_t n) const
{
- if (_denormal_protection != yn) {
- _denormal_protection = yn;
- // denormal_protection_changed (src); /* EMIT SIGNAL */
- }
+ return _ports.nth_midi_port (n);
}
-void
-IO::update_port_total_latencies ()
-{
- /* io_lock, not taken: function must be called from Session::process() calltree */
-
- for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
- _session.engine().update_total_latency (*i);
- }
-
- for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
- _session.engine().update_total_latency (*i);
- }
-}
-
-
/**
* Setup bundles that describe our inputs and outputs. Also creates bundles if necessary.
*/
void
-IO::setup_bundles_for_inputs_and_outputs ()
-{
- setup_bundle_for_inputs ();
- setup_bundle_for_outputs ();
-}
-
-
-void
-IO::setup_bundle_for_inputs ()
+IO::setup_bundles ()
{
char buf[32];
- if (!_bundle_for_inputs) {
- _bundle_for_inputs.reset (new Bundle (true));
- }
-
- _bundle_for_inputs->suspend_signals ();
-
- _bundle_for_inputs->set_type (default_type ());
-
- _bundle_for_inputs->remove_channels ();
-
- snprintf(buf, sizeof (buf), _("%s in"), _name.c_str());
- _bundle_for_inputs->set_name (buf);
- uint32_t const ni = inputs().num_ports();
- for (uint32_t i = 0; i < ni; ++i) {
- _bundle_for_inputs->add_channel (bundle_channel_name (i, ni));
- _bundle_for_inputs->set_port (i, _session.engine().make_port_name_non_relative (inputs().port(i)->name()));
+ if (!_bundle) {
+ _bundle.reset (new Bundle (true));
}
- _bundle_for_inputs->resume_signals ();
-}
+ _bundle->suspend_signals ();
+ _bundle->set_type (default_type ());
-void
-IO::setup_bundle_for_outputs ()
-{
- char buf[32];
+ _bundle->remove_channels ();
- if (!_bundle_for_outputs) {
- _bundle_for_outputs.reset (new Bundle (false));
+ if (_direction == Input) {
+ snprintf(buf, sizeof (buf), _("%s in"), _name.c_str());
+ } else {
+ snprintf(buf, sizeof (buf), _("%s out"), _name.c_str());
}
-
- _bundle_for_outputs->suspend_signals ();
-
- _bundle_for_outputs->set_type (default_type ());
-
- _bundle_for_outputs->remove_channels ();
-
- snprintf(buf, sizeof (buf), _("%s out"), _name.c_str());
- _bundle_for_outputs->set_name (buf);
- uint32_t const no = outputs().num_ports();
- for (uint32_t i = 0; i < no; ++i) {
- _bundle_for_outputs->add_channel (bundle_channel_name (i, no));
- _bundle_for_outputs->set_port (i, _session.engine().make_port_name_non_relative (outputs().port(i)->name()));
+ _bundle->set_name (buf);
+ uint32_t const ni = _ports.num_ports();
+ for (uint32_t i = 0; i < ni; ++i) {
+ _bundle->add_channel (bundle_channel_name (i, ni));
+ _bundle->set_port (i, _session.engine().make_port_name_non_relative (_ports.port(i)->name()));
}
- _bundle_for_outputs->resume_signals ();
+ _bundle->resume_signals ();
}
-
-/** @return Bundles connected to our inputs */
+/** @return Bundles connected to our ports */
BundleList
-IO::bundles_connected_to_inputs ()
+IO::bundles_connected ()
{
BundleList bundles;
/* User bundles */
- for (std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_inputs.begin(); i != _bundles_connected_to_inputs.end(); ++i) {
+ for (std::vector<UserBundleInfo>::iterator i = _bundles_connected.begin(); i != _bundles_connected.end(); ++i) {
bundles.push_back (i->bundle);
}
/* Session bundles */
boost::shared_ptr<ARDOUR::BundleList> b = _session.bundles ();
for (ARDOUR::BundleList::iterator i = b->begin(); i != b->end(); ++i) {
- if ((*i)->connected_to (_bundle_for_inputs, _session.engine())) {
+ if ((*i)->connected_to (_bundle, _session.engine())) {
bundles.push_back (*i);
}
}
/* Route bundles */
- boost::shared_ptr<ARDOUR::RouteList> r = _session.get_routes ();
- for (ARDOUR::RouteList::iterator i = r->begin(); i != r->end(); ++i) {
- if ((*i)->bundle_for_outputs()->connected_to (_bundle_for_inputs, _session.engine())) {
- bundles.push_back ((*i)->bundle_for_outputs());
- }
- }
-
- return bundles;
-}
-
-
-/* @return Bundles connected to our outputs */
-BundleList
-IO::bundles_connected_to_outputs ()
-{
- BundleList bundles;
- /* User bundles */
- for (std::vector<UserBundleInfo>::iterator i = _bundles_connected_to_outputs.begin(); i != _bundles_connected_to_outputs.end(); ++i) {
- bundles.push_back (i->bundle);
- }
+ boost::shared_ptr<ARDOUR::RouteList> r = _session.get_routes ();
- /* Session bundles */
- boost::shared_ptr<ARDOUR::BundleList> b = _session.bundles ();
- for (ARDOUR::BundleList::iterator i = b->begin(); i != b->end(); ++i) {
- if ((*i)->connected_to (_bundle_for_outputs, _session.engine())) {
- bundles.push_back (*i);
+ if (_direction == Input) {
+ for (ARDOUR::RouteList::iterator i = r->begin(); i != r->end(); ++i) {
+ if ((*i)->output()->bundle()->connected_to (_bundle, _session.engine())) {
+ bundles.push_back ((*i)->output()->bundle());
+ }
}
- }
-
- /* Route bundles */
- boost::shared_ptr<ARDOUR::RouteList> r = _session.get_routes ();
- for (ARDOUR::RouteList::iterator i = r->begin(); i != r->end(); ++i) {
- if ((*i)->bundle_for_inputs()->connected_to (_bundle_for_outputs, _session.engine())) {
- bundles.push_back ((*i)->bundle_for_inputs());
+ } else {
+ for (ARDOUR::RouteList::iterator i = r->begin(); i != r->end(); ++i) {
+ if ((*i)->input()->bundle()->connected_to (_bundle, _session.engine())) {
+ bundles.push_back ((*i)->input()->bundle());
+ }
}
}
-
- return bundles;
+
+ return bundles;
}
@@ -2598,22 +1223,6 @@ IO::UserBundleInfo::UserBundleInfo (IO* io, boost::shared_ptr<UserBundle> b)
);
}
-void
-IO::prepare_inputs (nframes_t nframes)
-{
- /* io_lock, not taken: function must be called from Session::process() calltree */
-}
-
-void
-IO::flush_outputs (nframes_t nframes)
-{
- /* io_lock, not taken: function must be called from Session::process() calltree */
-
- for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
- (*i).flush_buffers (nframes, _output_offset);
- }
-}
-
std::string
IO::bundle_channel_name (uint32_t c, uint32_t n) const
{
@@ -2654,29 +1263,18 @@ IO::set_name_in_state (XMLNode& node, const string& new_name)
}
}
-void
-IO::cycle_start (nframes_t nframes)
-{
- _output_offset = 0;
-}
-
-void
-IO::increment_output_offset (nframes_t n)
-{
- _output_offset += n;
-}
-
bool
IO::connected_to (boost::shared_ptr<const IO> other) const
{
+ assert (_direction != other->direction());
+
uint32_t i, j;
-
- uint32_t no = n_outputs().n_total();
- uint32_t ni = other->n_inputs ().n_total();
+ uint32_t no = n_ports().n_total();
+ uint32_t ni = other->n_ports ().n_total();
for (i = 0; i < no; ++i) {
for (j = 0; j < ni; ++j) {
- if (output(i)->connected_to (other->input(j)->name())) {
+ if (nth(i)->connected_to (other->nth(j)->name())) {
return true;
}
}
@@ -2685,3 +1283,67 @@ IO::connected_to (boost::shared_ptr<const IO> other) const
return false;
}
+void
+IO::process_input (boost::shared_ptr<Processor> proc, sframes_t start_frame, sframes_t end_frame, nframes_t nframes)
+{
+ BufferSet bufs;
+
+ /* don't read the data into new buffers - just use the port buffers directly */
+
+ bufs.attach_buffers (_ports, nframes, 0);
+ proc->run_in_place (bufs, start_frame, end_frame, nframes);
+}
+
+void
+IO::collect_input (BufferSet& bufs, nframes_t nframes, ChanCount offset)
+{
+ assert(bufs.available() >= _ports.count());
+
+ if (_ports.count() == ChanCount::ZERO) {
+ return;
+ }
+
+ bufs.set_count (_ports.count());
+
+ for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
+ PortSet::iterator i = _ports.begin(*t);
+ BufferSet::iterator b = bufs.begin(*t);
+
+ for (uint32_t off = 0; off < offset.get(*t); ++off, ++b) {
+ if (b == bufs.end(*t)) {
+ continue;
+ }
+ }
+
+ for ( ; i != _ports.end(*t); ++i, ++b) {
+ Buffer& bb (i->get_buffer (nframes));
+ b->read_from (bb, nframes);
+ }
+ }
+}
+
+void
+IO::copy_to_outputs (BufferSet& bufs, DataType type, nframes_t nframes, nframes_t offset)
+{
+ // Copy any buffers 1:1 to outputs
+
+ PortSet::iterator o = _ports.begin(type);
+ BufferSet::iterator i = bufs.begin(type);
+ BufferSet::iterator prev = i;
+
+ while (i != bufs.end(type) && o != _ports.end (type)) {
+ Buffer& port_buffer (o->get_buffer (nframes));
+ port_buffer.read_from (*i, nframes, offset);
+ prev = i;
+ ++i;
+ ++o;
+ }
+
+ // Copy last buffer to any extra outputs
+
+ while (o != _ports.end(type)) {
+ Buffer& port_buffer (o->get_buffer (nframes));
+ port_buffer.read_from (*prev, nframes, offset);
+ ++o;
+ }
+}
diff --git a/libs/ardour/io_processor.cc b/libs/ardour/io_processor.cc
index 2eac9dc88b..7e0d4a771c 100644
--- a/libs/ardour/io_processor.cc
+++ b/libs/ardour/io_processor.cc
@@ -46,20 +46,36 @@ using namespace PBD;
/* create an IOProcessor that proxies to a new IO object */
-IOProcessor::IOProcessor (Session& s, const string& proc_name, const string io_name, DataType dtype)
+IOProcessor::IOProcessor (Session& s, bool with_input, bool with_output,
+ const string& proc_name, const string io_name, DataType dtype)
: Processor(s, proc_name)
- , _io (new IO(s, io_name.empty() ? proc_name : io_name, dtype))
{
- _own_io = true;
+ /* these are true in this constructor whether we actually create the associated
+ IO objects or not.
+ */
+
+ _own_input = true;
+ _own_output = true;
+
+ if (with_input) {
+ _input.reset (new IO(s, io_name.empty() ? proc_name : io_name, IO::Input, dtype));
+ }
+
+ if (with_output) {
+ _output.reset (new IO(s, io_name.empty() ? proc_name : io_name, IO::Output, dtype));
+ }
}
/* create an IOProcessor that proxies to an existing IO object */
-IOProcessor::IOProcessor (Session& s, IO* io, const string& proc_name, DataType dtype)
+IOProcessor::IOProcessor (Session& s, boost::shared_ptr<IO> in, boost::shared_ptr<IO> out,
+ const string& proc_name, DataType dtype)
: Processor(s, proc_name)
- , _io (io)
+ , _input (in)
+ , _output (out)
{
- _own_io = false;
+ _own_input = false;
+ _own_output = false;
}
IOProcessor::~IOProcessor ()
@@ -68,12 +84,21 @@ IOProcessor::~IOProcessor ()
}
void
-IOProcessor::set_io (boost::shared_ptr<IO> io)
+IOProcessor::set_input (boost::shared_ptr<IO> io)
+{
+ /* CALLER MUST HOLD PROCESS LOCK */
+
+ _input = io;
+ _own_input = false;
+}
+
+void
+IOProcessor::set_output (boost::shared_ptr<IO> io)
{
/* CALLER MUST HOLD PROCESS LOCK */
- _io = io;
- _own_io = false;
+ _output = io;
+ _own_output = false;
}
XMLNode&
@@ -81,12 +106,28 @@ IOProcessor::state (bool full_state)
{
XMLNode& node (Processor::state (full_state));
- if (_own_io) {
- node.add_child_nocopy (_io->state (full_state));
- node.add_property ("own-io", "yes");
+ if (_own_input) {
+ XMLNode& i (_input->state (full_state));
+ // i.name() = X_("output");
+ node.add_child_nocopy (i);
+ node.add_property ("own-input", "yes");
+ } else {
+ node.add_property ("own-input", "no");
+ if (_input) {
+ node.add_property ("input", _input->name());
+ }
+ }
+
+ if (_own_output) {
+ XMLNode& o (_output->state (full_state));
+ // o.name() = X_("output");
+ node.add_child_nocopy (o);
+ node.add_property ("own-output", "yes");
} else {
- node.add_property ("own-io", "no");
- node.add_property ("io", _io->name());
+ node.add_property ("own-output", "no");
+ if (_output) {
+ node.add_property ("output", _output->name());
+ }
}
return node;
@@ -100,67 +141,59 @@ IOProcessor::set_state (const XMLNode& node)
Processor::set_state(node);
- if ((prop = node.property ("own-io")) != 0) {
- _own_io = prop->value() == "yes";
+ if ((prop = node.property ("own-input")) != 0) {
+ _own_input = (prop->value() == "yes");
}
- /* don't attempt to set state for a proxied IO that we don't own */
-
- if (!_own_io) {
-
- /* look up the IO object we're supposed to proxy to */
-
- if ((prop = node.property ("io")) == 0) {
- fatal << "IOProcessor has no named IO object" << endmsg;
- /*NOTREACHED*/
- }
-
- boost::shared_ptr<Route> r = _session.route_by_name (prop->value());
-
- if (!r) {
- fatal << string_compose ("IOProcessor uses an unknown IO object called %1", prop->value()) << endmsg;
- /*NOTREACHED*/
- }
-
- /* gotcha */
-
- _io = boost::static_pointer_cast<IO> (r);
-
- return 0;
+ if ((prop = node.property ("own-output")) != 0) {
+ _own_output = (prop->value() == "yes");
}
+ cerr << _name << " own input = " << _own_input << " output = " << _own_output << endl;
+
+ /* don't attempt to set state for a proxied IO that we don't own */
+
XMLNodeList nlist = node.children();
XMLNodeIterator niter;
-
- for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
- if ((*niter)->name() == IO::state_node_name) {
- io_node = (*niter);
- break;
- } else if ((*niter)->name() == "Redirect") {
- XMLNodeList rlist = (*niter)->children();
- XMLNodeIterator riter;
-
- for (riter = rlist.begin(); riter != rlist.end(); ++riter) {
- if ( (*riter)->name() == IO::state_node_name) {
- warning << _("Found legacy IO in a redirect") << endmsg;
- io_node = (*riter);
- break;
- }
+
+ if (_own_input) {
+ for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
+ if ((*niter)->name() == "input") {
+ io_node = (*niter);
+ break;
+ }
+ }
+
+ if (io_node) {
+ _input->set_state(*io_node);
+
+ // legacy sessions: use IO name
+ if ((prop = node.property ("name")) == 0) {
+ set_name (_input->name());
}
+
+ } else {
+ error << _("XML node describing an IOProcessor is missing an IO node") << endmsg;
+ return -1;
}
}
-
- if (io_node) {
- _io->set_state(*io_node);
-
- // legacy sessions: use IO name
- if ((prop = node.property ("name")) == 0) {
- set_name (_io->name());
+
+ if (_own_output) {
+ for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
+ if ((*niter)->name() == "output") {
+ io_node = (*niter);
+ break;
+ }
}
-
- } else {
- error << _("XML node describing a redirect is missing an IO node") << endmsg;
- return -1;
+
+ if (io_node) {
+ _output->set_state(*io_node);
+
+ // legacy sessions: use IO name
+ if ((prop = node.property ("name")) == 0) {
+ set_name (_output->name());
+ }
+ }
}
return 0;
@@ -169,41 +202,33 @@ IOProcessor::set_state (const XMLNode& node)
void
IOProcessor::silence (nframes_t nframes)
{
- if (_own_io) {
- _io->silence (nframes);
+ if (_own_output && _output) {
+ _output->silence (nframes);
}
}
ChanCount
IOProcessor::output_streams() const
{
- return _io->n_outputs();
+ return _output ? _output->n_ports() : ChanCount::ZERO;
}
ChanCount
IOProcessor::input_streams () const
{
- return _io->n_inputs();
+ return _input ? _input->n_ports() : ChanCount::ZERO;
}
ChanCount
IOProcessor::natural_output_streams() const
{
- return _io->n_outputs();
+ return _output ? _output->n_ports() : ChanCount::ZERO;
}
ChanCount
IOProcessor::natural_input_streams () const
{
- return _io->n_inputs();
-}
-
-void
-IOProcessor::automation_snapshot (nframes_t now, bool force)
-{
- if (_own_io) {
- _io->automation_snapshot(now, force);
- }
+ return _input ? _input->n_ports() : ChanCount::ZERO;
}
bool
@@ -211,8 +236,12 @@ IOProcessor::set_name (const std::string& name)
{
bool ret = SessionObject::set_name (name);
- if (ret && _own_io) {
- ret = _io->set_name (name);
+ if (ret && _own_input && _input) {
+ ret = _input->set_name (name);
+ }
+
+ if (ret && _own_output && _output) {
+ ret = _output->set_name (name);
}
return ret;
diff --git a/libs/ardour/meter.cc b/libs/ardour/meter.cc
index 371e0c5a90..ed50479c74 100644
--- a/libs/ardour/meter.cc
+++ b/libs/ardour/meter.cc
@@ -29,8 +29,41 @@
using namespace std;
-namespace ARDOUR {
+using namespace ARDOUR;
+sigc::signal<void> Metering::Meter;
+Glib::StaticMutex Metering::m_meter_signal_lock;
+
+sigc::connection
+Metering::connect (sigc::slot<void> the_slot)
+{
+ // SignalProcessor::Meter is emitted from another thread so the
+ // Meter signal must be protected.
+ Glib::Mutex::Lock guard (m_meter_signal_lock);
+ return Meter.connect (the_slot);
+}
+
+void
+Metering::disconnect (sigc::connection& c)
+{
+ Glib::Mutex::Lock guard (m_meter_signal_lock);
+ c.disconnect ();
+}
+
+/**
+ Update the meters.
+
+ The meter signal lock is taken to prevent modification of the
+ Meter signal while updating the meters, taking the meter signal
+ lock prior to taking the io_lock ensures that all IO will remain
+ valid while metering.
+*/
+void
+Metering::update_meters()
+{
+ Glib::Mutex::Lock guard (m_meter_signal_lock);
+ Meter(); /* EMIT SIGNAL */
+}
/** Get peaks from @a bufs
* Input acceptance is lenient - the first n buffers from @a bufs will
@@ -128,8 +161,10 @@ PeakMeter::configure_io (ChanCount in, ChanCount out)
}
/** To be driven by the Meter signal from IO.
- * Caller MUST hold io_lock!
+ * Caller MUST hold its own processor_lock to prevent reconfiguration
+ * of meter size during this call.
*/
+
void
PeakMeter::meter ()
{
@@ -139,12 +174,10 @@ PeakMeter::meter ()
for (size_t n = 0; n < limit; ++n) {
- /* XXX we should use atomic exchange here */
-
/* grab peak since last read */
- float new_peak = _peak_power[n];
- _peak_power[n] = 0;
+ float new_peak = _peak_power[n]; /* XXX we should use atomic exchange from here ... */
+ _peak_power[n] = 0; /* ... to here */
/* compute new visible value using falloff */
@@ -176,4 +209,3 @@ PeakMeter::state (bool full_state)
return node;
}
-} // namespace ARDOUR
diff --git a/libs/ardour/midi_diskstream.cc b/libs/ardour/midi_diskstream.cc
index 30b1542974..e0921d8916 100644
--- a/libs/ardour/midi_diskstream.cc
+++ b/libs/ardour/midi_diskstream.cc
@@ -159,8 +159,8 @@ MidiDiskstream::non_realtime_input_change ()
}
if (input_change_pending & ConfigurationChanged) {
- if (_io->n_inputs().n_midi() != _n_channels.n_midi()) {
- error << "Can not feed IO " << _io->n_inputs()
+ if (_io->n_ports().n_midi() != _n_channels.n_midi()) {
+ error << "Can not feed IO " << _io->n_ports()
<< " with diskstream " << _n_channels << endl;
}
}
@@ -199,7 +199,7 @@ MidiDiskstream::non_realtime_input_change ()
void
MidiDiskstream::get_input_sources ()
{
- uint32_t ni = _io->n_inputs().n_midi();
+ uint32_t ni = _io->n_ports().n_midi();
if (ni == 0) {
return;
@@ -208,7 +208,7 @@ MidiDiskstream::get_input_sources ()
// This is all we do for now at least
assert(ni == 1);
- _source_port = _io->midi_input(0);
+ _source_port = _io->midi(0);
// do... stuff?
}
@@ -421,6 +421,7 @@ MidiDiskstream::check_record_status (nframes_t transport_frame, nframes_t nframe
last_possibly_recording = possibly_recording;
}
+#if 0
static void
trace_midi (ostream& o, MIDI::byte *msg, size_t len)
{
@@ -587,6 +588,7 @@ trace_midi (ostream& o, MIDI::byte *msg, size_t len)
break;
}
}
+#endif
int
MidiDiskstream::process (nframes_t transport_frame, nframes_t nframes, bool can_record, bool rec_monitors_input)
diff --git a/libs/ardour/midi_track.cc b/libs/ardour/midi_track.cc
index c993b17ced..a6ff1b93f4 100644
--- a/libs/ardour/midi_track.cc
+++ b/libs/ardour/midi_track.cc
@@ -27,6 +27,7 @@
#include "ardour/amp.h"
#include "ardour/buffer_set.h"
+#include "ardour/delivery.h"
#include "ardour/io_processor.h"
#include "ardour/meter.h"
#include "ardour/midi_diskstream.h"
@@ -94,14 +95,14 @@ int
MidiTrack::set_diskstream (boost::shared_ptr<MidiDiskstream> ds)
{
_diskstream = ds;
- _diskstream->set_io (*this);
+ _diskstream->set_io (*(_input.get()));
_diskstream->set_destructive (_mode == Destructive);
_diskstream->set_record_enabled (false);
//_diskstream->monitor_input (false);
ic_connection.disconnect();
- ic_connection = input_changed.connect (mem_fun (*_diskstream, &MidiDiskstream::handle_input_change));
+ ic_connection = _input->changed.connect (mem_fun (*_diskstream, &MidiDiskstream::handle_input_change));
DiskstreamChanged (); /* EMIT SIGNAL */
@@ -113,11 +114,14 @@ MidiTrack::use_diskstream (string name)
{
boost::shared_ptr<MidiDiskstream> dstream;
+ cerr << "\n\n\nMIDI use diskstream\n";
+
if ((dstream = boost::dynamic_pointer_cast<MidiDiskstream>(_session.diskstream_by_name (name))) == 0) {
error << string_compose(_("MidiTrack: midi diskstream \"%1\" not known by session"), name) << endmsg;
return -1;
}
+ cerr << "\n\n\nMIDI found DS\n";
return set_diskstream (dstream);
}
@@ -191,6 +195,8 @@ MidiTrack::_set_state (const XMLNode& node, bool call_base)
that means "you should create a new diskstream here, not look for
an old one.
*/
+
+ cerr << "\n\n\n\n MIDI track " << name() << " found DS id " << id << endl;
if (id == zero) {
use_new_diskstream ();
@@ -363,8 +369,6 @@ MidiTrack::roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame,
int dret;
boost::shared_ptr<MidiDiskstream> diskstream = midi_diskstream();
- prepare_inputs (nframes);
-
{
Glib::RWLock::ReaderLock lm (_processor_lock, Glib::TRY_LOCK);
if (lm.locked()) {
@@ -405,7 +409,7 @@ MidiTrack::roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame,
/* special condition applies */
if (_meter_point == MeterInput) {
- just_meter_input (start_frame, end_frame, nframes);
+ _input->process_input (_meter, start_frame, end_frame, nframes);
}
if (diskstream->record_enabled() && !can_record && !_session.config.get_auto_input()) {
@@ -438,7 +442,7 @@ MidiTrack::roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame,
}
- flush_outputs (nframes);
+ _main_outs->flush (nframes);
return 0;
}
diff --git a/libs/ardour/mute_master.cc b/libs/ardour/mute_master.cc
new file mode 100644
index 0000000000..ca64fb01a5
--- /dev/null
+++ b/libs/ardour/mute_master.cc
@@ -0,0 +1,109 @@
+/*
+
+ Copyright (C) 2009 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include "ardour/mute_master.h"
+#include "ardour/rc_configuration.h"
+
+#include "i18n.h"
+
+using namespace ARDOUR;
+
+MuteMaster::MuteMaster (Session& s, const std::string& name)
+ : AutomationControl (s, Evoral::Parameter (MuteAutomation), boost::shared_ptr<AutomationList>(), name)
+ , _mute_point (MutePoint (0))
+{
+ // default range for parameter is fine
+
+ _automation = new AutomationList (MuteAutomation);
+ set_list (boost::shared_ptr<AutomationList>(_automation));
+}
+
+void
+MuteMaster::clear_mute ()
+{
+ if (_mute_point != MutePoint (0)) {
+ _mute_point = MutePoint (0);
+ MutePointChanged (); // EMIT SIGNAL
+ }
+}
+
+void
+MuteMaster::mute_at (MutePoint mp)
+{
+ if ((_mute_point & mp) != mp) {
+ _mute_point = MutePoint (_mute_point | mp);
+ MutePointChanged (); // EMIT SIGNAL
+ }
+}
+
+void
+MuteMaster::unmute_at (MutePoint mp)
+{
+ if ((_mute_point & mp) == mp) {
+ _mute_point = MutePoint (_mute_point & ~mp);
+ MutePointChanged (); // EMIT SIGNAL
+ }
+}
+
+void
+MuteMaster::mute (bool yn)
+{
+ /* convenience wrapper around AutomationControl method */
+
+ if (yn) {
+ set_value (1.0f);
+ } else {
+ set_value (0.0f);
+ }
+}
+
+gain_t
+MuteMaster::mute_gain_at (MutePoint mp) const
+{
+ if (_mute_point & mp) {
+ return Config->get_solo_mute_gain ();
+ } else {
+ return 1.0;
+ }
+}
+
+void
+MuteMaster::set_value (float f)
+{
+ mute_at ((MutePoint) ((int) rint (f)));
+}
+
+float
+MuteMaster::get_value () const
+{
+ return (float) _mute_point;
+}
+
+int
+MuteMaster::set_state (const XMLNode& node)
+{
+ return 0;
+}
+
+XMLNode&
+MuteMaster::get_state()
+{
+ return *(new XMLNode (X_("MuteMaster")));
+}
diff --git a/libs/ardour/panner.cc b/libs/ardour/panner.cc
index 73326e12a4..3b700631cb 100644
--- a/libs/ardour/panner.cc
+++ b/libs/ardour/panner.cc
@@ -703,7 +703,8 @@ Multi2dPanner::set_state (const XMLNode& node)
/*---------------------------------------------------------------------- */
Panner::Panner (string name, Session& s)
- : Processor(s, name)
+ : SessionObject (s, name)
+ , AutomatableControls (s)
{
//set_name_old_auto (name);
set_name (name);
@@ -829,6 +830,8 @@ Panner::reset (uint32_t nouts, uint32_t npans)
bool changed = false;
bool do_not_and_did_not_need_panning = ((nouts < 2) && (outputs.size() < 2));
+ cerr << "panner " << _name << " reset to " << nouts << " / " << npans << endl;
+
/* if new and old config don't need panning, or if
the config hasn't changed, we're done.
*/
@@ -1058,15 +1061,13 @@ Panner::get_state (void)
XMLNode&
Panner::state (bool full)
{
- XMLNode& node = Processor::state(full);
-
- node.add_property ("type", "panner");
+ XMLNode* node = new XMLNode ("Panner");
char buf[32];
- node.add_property (X_("linked"), (_linked ? "yes" : "no"));
- node.add_property (X_("link_direction"), enum_2_string (_link_direction));
- node.add_property (X_("bypassed"), (bypassed() ? "yes" : "no"));
+ node->add_property (X_("linked"), (_linked ? "yes" : "no"));
+ node->add_property (X_("link_direction"), enum_2_string (_link_direction));
+ node->add_property (X_("bypassed"), (bypassed() ? "yes" : "no"));
for (vector<Panner::Output>::iterator o = outputs.begin(); o != outputs.end(); ++o) {
XMLNode* onode = new XMLNode (X_("Output"));
@@ -1074,15 +1075,15 @@ Panner::state (bool full)
onode->add_property (X_("x"), buf);
snprintf (buf, sizeof (buf), "%.12g", (*o).y);
onode->add_property (X_("y"), buf);
- node.add_child_nocopy (*onode);
+ node->add_child_nocopy (*onode);
}
-
+
for (vector<StreamPanner*>::const_iterator i = _streampanners.begin(); i != _streampanners.end(); ++i) {
- node.add_child_nocopy ((*i)->state (full));
+ node->add_child_nocopy ((*i)->state (full));
}
- return node;
+ return *node;
}
int
@@ -1098,8 +1099,6 @@ Panner::set_state (const XMLNode& node)
clear_panners ();
- Processor::set_state(node);
-
ChanCount ins = ChanCount::ZERO;
ChanCount outs = ChanCount::ZERO;
@@ -1419,7 +1418,7 @@ Panner::distribute_no_automation (BufferSet& inbufs, BufferSet& outbufs, nframes
}
void
-Panner::run_out_of_place (BufferSet& inbufs, BufferSet& outbufs, sframes_t start_frame, sframes_t end_frame, nframes_t nframes)
+Panner::run (BufferSet& inbufs, BufferSet& outbufs, sframes_t start_frame, sframes_t end_frame, nframes_t nframes)
{
if (outbufs.count().n_audio() == 0) {
// Failing to deliver audio we were asked to deliver is a bug
@@ -1432,16 +1431,16 @@ Panner::run_out_of_place (BufferSet& inbufs, BufferSet& outbufs, sframes_t start
assert(!empty());
// If we shouldn't play automation defer to distribute_no_automation
- if ( !( automation_state() & Play ||
- ((automation_state() & Touch) && !touching()) ) ) {
+ if (!(automation_state() & Play || ((automation_state() & Touch) && !touching()))) {
// Speed quietning
gain_t gain_coeff = 1.0;
+
if (fabsf(_session.transport_speed()) > 1.5f) {
gain_coeff = speed_quietning;
}
- distribute_no_automation(inbufs, outbufs, nframes, gain_coeff);
+ distribute_no_automation (inbufs, outbufs, nframes, gain_coeff);
return;
}
diff --git a/libs/ardour/port_insert.cc b/libs/ardour/port_insert.cc
index 9d0d65ccd5..8ff2633771 100644
--- a/libs/ardour/port_insert.cc
+++ b/libs/ardour/port_insert.cc
@@ -24,6 +24,7 @@
#include "pbd/failed_constructor.h"
#include "pbd/xml++.h"
+#include "ardour/delivery.h"
#include "ardour/port_insert.h"
#include "ardour/plugin.h"
#include "ardour/port.h"
@@ -40,15 +41,17 @@ using namespace std;
using namespace ARDOUR;
using namespace PBD;
-PortInsert::PortInsert (Session& s)
- : IOProcessor (s, string_compose (_("insert %1"), (bitslot = s.next_insert_id()) + 1), "")
+PortInsert::PortInsert (Session& s, boost::shared_ptr<MuteMaster> mm)
+ : IOProcessor (s, true, true, string_compose (_("insert %1"), (bitslot = s.next_insert_id()) + 1), "")
+ , _out (new Delivery (s, _output, mm, _name, Delivery::Insert))
{
- init ();
ProcessorCreated (this); /* EMIT SIGNAL */
}
-PortInsert::PortInsert (Session& s, const XMLNode& node)
- : IOProcessor (s, "unnamed port insert")
+PortInsert::PortInsert (Session& s, boost::shared_ptr<MuteMaster> mm, const XMLNode& node)
+ : IOProcessor (s, true, true, "unnamed port insert")
+ , _out (new Delivery (s, _output, mm, _name, Delivery::Insert))
+
{
if (set_state (node)) {
throw failed_constructor();
@@ -63,29 +66,20 @@ PortInsert::~PortInsert ()
}
void
-PortInsert::init ()
-{
- if (_io->ensure_io(output_streams(), input_streams(), false, this)) { // sic
- error << _("PortInsert: cannot create ports") << endmsg;
- throw failed_constructor();
- }
-}
-
-void
PortInsert::run_in_place (BufferSet& bufs, sframes_t start_frame, sframes_t end_frame, nframes_t nframes)
{
- if (_io->n_outputs().n_total() == 0) {
+ if (_output->n_ports().n_total() == 0) {
return;
}
if (!active()) {
/* deliver silence */
- _io->silence (nframes);
+ silence (nframes);
return;
}
- _io->deliver_output (bufs, start_frame, end_frame, nframes);
- _io->collect_input (bufs, nframes);
+ _out->run_in_place (bufs, start_frame, end_frame, nframes);
+ _input->collect_input (bufs, nframes, ChanCount::ZERO);
}
XMLNode&
@@ -97,7 +91,7 @@ PortInsert::get_state(void)
XMLNode&
PortInsert::state (bool full)
{
- XMLNode& node = IOProcessor::state(full);
+ XMLNode& node = Processor::state(full);
char buf[32];
node.add_property ("type", "port");
snprintf (buf, sizeof (buf), "%" PRIu32, bitslot);
@@ -141,7 +135,7 @@ PortInsert::set_state(const XMLNode& node)
}
}
- IOProcessor::set_state (*insert_node);
+ Processor::set_state (*insert_node);
return 0;
}
@@ -156,7 +150,7 @@ PortInsert::signal_latency() const
need to take that into account too.
*/
- return _session.engine().frames_per_cycle() + _io->input_latency();
+ return _session.engine().frames_per_cycle() + _input->signal_latency();
}
bool
@@ -164,7 +158,11 @@ PortInsert::configure_io (ChanCount in, ChanCount out)
{
/* for an insert, processor input corresponds to IO output, and vice versa */
- if (_io->ensure_io (out, in, false, this) != 0) {
+ if (_input->ensure_io (in, false, this) != 0) {
+ return false;
+ }
+
+ if (_output->ensure_io (out, false, this) != 0) {
return false;
}
@@ -178,3 +176,12 @@ PortInsert::can_support_io_configuration (const ChanCount& in, ChanCount& out) c
return true;
}
+bool
+PortInsert::set_name (const std::string& name)
+{
+ bool ret = Processor::set_name (name);
+
+ ret = (_input->set_name (name) || _output->set_name (name));
+
+ return ret;
+}
diff --git a/libs/ardour/processor.cc b/libs/ardour/processor.cc
index 3fc9fcaee2..2e39c52d67 100644
--- a/libs/ardour/processor.cc
+++ b/libs/ardour/processor.cc
@@ -211,7 +211,8 @@ Processor::configure_io (ChanCount in, ChanCount out)
{
/* This class assumes 1:1 input:output.static output stream count.
Derived classes must override and set _configured_output appropriately
- if this is not the case */
+ if this is not the case
+ */
_configured_input = in;
_configured_output = out;
diff --git a/libs/ardour/return.cc b/libs/ardour/return.cc
index 1f228d01ca..4942f9023b 100644
--- a/libs/ardour/return.cc
+++ b/libs/ardour/return.cc
@@ -21,14 +21,15 @@
#include "pbd/xml++.h"
-#include "ardour/return.h"
-#include "ardour/session.h"
-#include "ardour/port.h"
+#include "ardour/amp.h"
#include "ardour/audio_port.h"
#include "ardour/buffer_set.h"
+#include "ardour/io.h"
#include "ardour/meter.h"
#include "ardour/panner.h"
-#include "ardour/io.h"
+#include "ardour/port.h"
+#include "ardour/return.h"
+#include "ardour/session.h"
#include "i18n.h"
@@ -36,14 +37,26 @@ using namespace ARDOUR;
using namespace PBD;
Return::Return (Session& s)
- : IOProcessor (s, string_compose (_("return %1"), (_bitslot = s.next_return_id()) + 1))
+ : IOProcessor (s, true, false, string_compose (_("return %1"), (_bitslot = s.next_return_id()) + 1))
+ , _metering (false)
{
+ /* never muted */
+
+ _amp.reset (new Amp (_session, boost::shared_ptr<MuteMaster>()));
+ _meter.reset (new PeakMeter (_session));
+
ProcessorCreated (this); /* EMIT SIGNAL */
}
Return::Return (Session& s, const XMLNode& node)
- : IOProcessor (s, "return")
+ : IOProcessor (s, true, false, "return")
+ , _metering (false)
{
+ /* never muted */
+
+ _amp.reset (new Amp (_session, boost::shared_ptr<MuteMaster>()));
+ _meter.reset (new PeakMeter (_session));
+
if (set_state (node)) {
throw failed_constructor();
}
@@ -108,23 +121,38 @@ Return::set_state(const XMLNode& node)
void
Return::run_in_place (BufferSet& bufs, sframes_t start_frame, sframes_t end_frame, nframes_t nframes)
{
- if (active()) {
- _io->collect_input (bufs, nframes, _configured_input);
- bufs.set_count(_configured_output);
+ if (!active() || _input->n_ports() == ChanCount::ZERO) {
+ return;
+ }
+
+ _input->collect_input (bufs, nframes, _configured_input);
+ bufs.set_count(_configured_output);
+
+ // Can't automate gain for sends or returns yet because we need different buffers
+ // so that we don't overwrite the main automation data for the route amp
+ // _amp->setup_gain_automation (start_frame, end_frame, nframes);
+ _amp->run_in_place (bufs, start_frame, end_frame, nframes);
+
+ if (_metering) {
+ if (_amp->gain_control()->get_value() == 0) {
+ _meter->reset();
+ } else {
+ _meter->run_in_place (bufs, start_frame, end_frame, nframes);
+ }
}
}
bool
Return::can_support_io_configuration (const ChanCount& in, ChanCount& out) const
{
- out = in + _io->n_inputs();
+ out = in + _input->n_ports();
return true;
}
bool
Return::configure_io (ChanCount in, ChanCount out)
{
- if (out != in + _io->n_inputs()) {
+ if (out != in + _input->n_ports()) {
return false;
}
@@ -162,3 +190,4 @@ Return::make_unique (XMLNode &state, Session &session)
}
}
+
diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc
index ccdd523654..edd38eb80c 100644
--- a/libs/ardour/route.cc
+++ b/libs/ardour/route.cc
@@ -64,19 +64,23 @@ uint32_t Route::order_key_cnt = 0;
sigc::signal<void,const char*> Route::SyncOrderKeys;
Route::Route (Session& sess, string name, Flag flg, DataType default_type)
- : IO (sess, name, default_type)
+ : SessionObject (sess, name)
+ , AutomatableControls (sess)
, _flags (flg)
- , _solo_control (new ToggleControllable (X_("solo"), *this, ToggleControllable::SoloControl))
- , _mute_control (new ToggleControllable (X_("mute"), *this, ToggleControllable::MuteControl))
+ , _solo_control (new SoloControllable (X_("solo"), *this))
+ , _mute_master (new MuteMaster (sess, name))
+ , _default_type (default_type)
+
{
init ();
-
}
Route::Route (Session& sess, const XMLNode& node, DataType default_type)
- : IO (sess, *node.child ("IO"), default_type)
- , _solo_control (new ToggleControllable (X_("solo"), *this, ToggleControllable::SoloControl))
- , _mute_control (new ToggleControllable (X_("mute"), *this, ToggleControllable::MuteControl))
+ : SessionObject (sess, "toBeReset")
+ , AutomatableControls (sess)
+ , _solo_control (new SoloControllable (X_("solo"), *this))
+ , _mute_master (new MuteMaster (sess, "toBeReset"))
+ , _default_type (default_type)
{
init ();
_set_state (node, false);
@@ -85,21 +89,15 @@ Route::Route (Session& sess, const XMLNode& node, DataType default_type)
void
Route::init ()
{
+ _active = true;
processor_max_streams.reset();
- _muted = false;
- _soloed = false;
_solo_safe = false;
_recordable = true;
- _active = true;
- _phase_invert = false;
- _denormal_protection = false;
order_keys[strdup (N_("signal"))] = order_key_cnt++;
_silent = false;
_meter_point = MeterPostFader;
_initial_delay = 0;
_roll_delay = 0;
- _own_latency = 0;
- _user_latency = 0;
_have_internal_generator = false;
_declickable = false;
_pending_declick = true;
@@ -109,32 +107,42 @@ Route::init ()
_edit_group = 0;
_mix_group = 0;
- _mute_affects_pre_fader = Config->get_mute_affects_pre_fader();
- _mute_affects_post_fader = Config->get_mute_affects_post_fader();
- _mute_affects_control_outs = Config->get_mute_affects_control_outs();
- _mute_affects_main_outs = Config->get_mute_affects_main_outs();
-
- solo_gain = 1.0;
- desired_solo_gain = 1.0;
- mute_gain = 1.0;
- desired_mute_gain = 1.0;
+ _phase_invert = 0;
+ _denormal_protection = false;
+
+ /* add standard controls */
- input_changed.connect (mem_fun (this, &Route::input_change_handler));
- output_changed.connect (mem_fun (this, &Route::output_change_handler));
+ add_control (_solo_control);
+ add_control (_mute_master);
- /* add standard processors: amp, meter, main outs */
+ /* input and output objects */
- /* amp & meter belong to IO but need to be added to our processor list */
+ _input.reset (new IO (_session, _name, IO::Input, _default_type));
+ _output.reset (new IO (_session, _name, IO::Output, _default_type));
+ _input->changed.connect (mem_fun (this, &Route::input_change_handler));
+ _output->changed.connect (mem_fun (this, &Route::output_change_handler));
+
+ /* add standard processors */
+
+ _amp.reset (new Amp (_session, _mute_master));
add_processor (_amp, PostFader);
+
+ _meter.reset (new PeakMeter (_session));
add_processor (_meter, PreFader);
- _main_outs.reset (new Delivery (_session, this, _name, Delivery::Main));
+ _main_outs.reset (new Delivery (_session, _output, _mute_master, _name, Delivery::Main));
add_processor (_main_outs, PostFader);
+
+ /* now we can meter */
+
+ _meter_connection = Metering::connect (mem_fun (*this, &Route::meter));
}
Route::~Route ()
{
+ Metering::disconnect (_meter_connection);
+
clear_processors (PreFader);
clear_processors (PostFader);
@@ -224,10 +232,11 @@ Route::ensure_track_or_route_name(string name, Session &session)
return newname;
}
+
void
Route::inc_gain (gain_t fraction, void *src)
{
- IO::inc_gain (fraction, src);
+ _amp->inc_gain (fraction, src);
}
void
@@ -237,7 +246,7 @@ Route::set_gain (gain_t val, void *src)
if (_mix_group->is_relative()) {
- gain_t usable_gain = gain();
+ gain_t usable_gain = _amp->gain();
if (usable_gain < 0.000001f) {
usable_gain = 0.000001f;
}
@@ -257,13 +266,13 @@ Route::set_gain (gain_t val, void *src)
if (factor > 0.0f) {
factor = _mix_group->get_max_factor(factor);
if (factor == 0.0f) {
- _gain_control->Changed(); /* EMIT SIGNAL */
+ _amp->gain_control()->Changed(); /* EMIT SIGNAL */
return;
}
} else {
factor = _mix_group->get_min_factor(factor);
if (factor == 0.0f) {
- _gain_control->Changed(); /* EMIT SIGNAL */
+ _amp->gain_control()->Changed(); /* EMIT SIGNAL */
return;
}
}
@@ -278,11 +287,11 @@ Route::set_gain (gain_t val, void *src)
return;
}
- if (val == gain()) {
+ if (val == _amp->gain()) {
return;
}
- IO::set_gain (val, src);
+ _amp->set_gain (val, src);
}
/** Process this route for one (sub) cycle (process thread)
@@ -300,132 +309,78 @@ Route::process_output_buffers (BufferSet& bufs,
sframes_t start_frame, sframes_t end_frame, nframes_t nframes,
bool with_processors, int declick)
{
- ProcessorList::iterator i;
- bool mute_declick_applied = false;
- gain_t dmg, dsg, dg;
- bool no_monitor;
+ bool monitor;
- bufs.is_silent(false);
+ bufs.is_silent (false);
switch (Config->get_monitoring_model()) {
case HardwareMonitoring:
case ExternalMonitoring:
- no_monitor = true;
+ monitor = record_enabled() && (_session.config.get_auto_input() || _session.actively_recording());
break;
default:
- no_monitor = false;
- }
-
- declick = _pending_declick;
-
- const bool recording_without_monitoring = no_monitor && record_enabled()
- && (!_session.config.get_auto_input() || _session.actively_recording());
-
-
- /* -------------------------------------------------------------------------------------------
- SET UP GAIN (FADER)
- ----------------------------------------------------------------------------------------- */
-
- {
- Glib::Mutex::Lock dm (declick_lock, Glib::TRY_LOCK);
-
- if (dm.locked()) {
- dmg = desired_mute_gain;
- dsg = desired_solo_gain;
- dg = _gain_control->user_float();
- } else {
- dmg = mute_gain;
- dsg = solo_gain;
- dg = _gain;
- }
+ monitor = true;
}
-
- // apply gain at the amp if...
- _amp->apply_gain(
- // we're not recording
- !(record_enabled() && _session.actively_recording())
- // or (we are recording, and) software monitoring is required
- || Config->get_monitoring_model() == SoftwareMonitoring);
-
- // mute at the amp if...
- _amp->apply_mute (!_soloed && (mute_gain != dmg) && !mute_declick_applied && _mute_affects_post_fader,
- mute_gain, dmg);
- _amp->set_gain (_gain, dg);
-
-
- /* -------------------------------------------------------------------------------------------
- SET UP CONTROL OUTPUTS
- ----------------------------------------------------------------------------------------- */
-
- boost::shared_ptr<Delivery> co = _control_outs;
- if (co) {
- // deliver control outputs unless we're ...
- bool self_mute = ((dmg == 0 && _mute_affects_control_outs) || // or muted by mute of this track
- !recording_without_monitoring); // or rec-enabled w/o s/w monitoring
- bool other_mute = (dsg == 0); // muted by solo of another track
-
- co->set_self_mute (self_mute);
- co->set_nonself_mute (other_mute);
+ if (!declick) {
+ declick = _pending_declick;
}
- /* -------------------------------------------------------------------------------------------
- SET UP MAIN OUTPUT STAGE
- ----------------------------------------------------------------------------------------- */
+ /* figure out if we're going to use gain automation */
- bool solo_audible = dsg > 0;
- bool mute_audible = dmg > 0 || !_mute_affects_main_outs;
+ _amp->setup_gain_automation (start_frame, end_frame, nframes);
+
+ /* tell main outs what to do about monitoring */
- bool silent_anyway = (_gain == 0 && !_amp->apply_gain_automation());
- bool muted_by_other_solo = (!solo_audible && (Config->get_solo_model() != SoloBus));
- bool muted_by_self = !mute_audible;
+ _main_outs->no_outs_cuz_we_no_monitor (!monitor);
- _main_outs->set_nonself_mute (recording_without_monitoring || muted_by_other_solo || silent_anyway);
- _main_outs->set_self_mute (muted_by_self);
-
/* -------------------------------------------------------------------------------------------
GLOBAL DECLICK (for transport changes etc.)
----------------------------------------------------------------------------------------- */
if (declick > 0) {
- Amp::apply_gain (bufs, nframes, 0.0, 1.0, false);
- _pending_declick = 0;
+ Amp::apply_gain (bufs, nframes, 0.0, 1.0);
} else if (declick < 0) {
- Amp::apply_gain (bufs, nframes, 1.0, 0.0, false);
- _pending_declick = 0;
- } else { // no global declick
- if (solo_gain != dsg) {
- Amp::apply_gain (bufs, nframes, solo_gain, dsg, false);
- solo_gain = dsg;
- }
- }
-
+ Amp::apply_gain (bufs, nframes, 1.0, 0.0);
+ }
+ _pending_declick = 0;
+
/* -------------------------------------------------------------------------------------------
- PRE-FADER MUTING
+ DENORMAL CONTROL/PHASE INVERT
----------------------------------------------------------------------------------------- */
- if (!_soloed && _mute_affects_pre_fader && (mute_gain != dmg)) {
- Amp::apply_gain (bufs, nframes, mute_gain, dmg, false);
- mute_gain = dmg;
- mute_declick_applied = true;
- }
- if (mute_gain == 0.0f && dmg == 0.0f) {
- bufs.is_silent(true);
- }
+ if (_phase_invert) {
+
+ int chn = 0;
+ if (_denormal_protection || Config->get_denormal_protection()) {
+
+ for (BufferSet::audio_iterator i = bufs.audio_begin(); i != bufs.audio_end(); ++i, ++chn) {
+ Sample* const sp = i->data();
- /* -------------------------------------------------------------------------------------------
- DENORMAL CONTROL
- ----------------------------------------------------------------------------------------- */
+ if (_phase_invert & chn) {
+ for (nframes_t nx = 0; nx < nframes; ++nx) {
+ sp[nx] = -sp[nx];
+ sp[nx] += 1.0e-27f;
+ }
+ } else {
+ for (nframes_t nx = 0; nx < nframes; ++nx) {
+ sp[nx] += 1.0e-27f;
+ }
+ }
+ }
- if (_denormal_protection || Config->get_denormal_protection()) {
+ } else {
- for (BufferSet::audio_iterator i = bufs.audio_begin(); i != bufs.audio_end(); ++i) {
- Sample* const sp = i->data();
-
- for (nframes_t nx = 0; nx < nframes; ++nx) {
- sp[nx] += 1.0e-27f;
+ for (BufferSet::audio_iterator i = bufs.audio_begin(); i != bufs.audio_end(); ++i, ++chn) {
+ Sample* const sp = i->data();
+
+ if (_phase_invert & chn) {
+ for (nframes_t nx = 0; nx < nframes; ++nx) {
+ sp[nx] = -sp[nx];
+ }
+ }
}
}
}
@@ -437,57 +392,48 @@ Route::process_output_buffers (BufferSet& bufs,
Glib::RWLock::ReaderLock rm (_processor_lock, Glib::TRY_LOCK);
if (rm.locked()) {
- for (i = _processors.begin(); i != _processors.end(); ++i) {
- bufs.set_count(ChanCount::max(bufs.count(), (*i)->input_streams()));
+ for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
+ bufs.set_count (ChanCount::max(bufs.count(), (*i)->input_streams()));
(*i)->run_in_place (bufs, start_frame, end_frame, nframes);
- bufs.set_count(ChanCount::max(bufs.count(), (*i)->output_streams()));
+ 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 (ChanCount::max (bufs.count(), _processors.back()->output_streams()));
}
}
-
- /* -------------------------------------------------------------------------------------------
- POST-FADER MUTING
- ----------------------------------------------------------------------------------------- */
-
- if (!_soloed && (mute_gain != dmg) && !mute_declick_applied && _mute_affects_main_outs) {
- Amp::apply_gain (bufs, nframes, mute_gain, dmg, false);
- mute_gain = dmg;
- mute_declick_applied = true;
- }
-
- if (mute_gain == 0.0f && dmg == 0.0f) {
- bufs.is_silent(true);
- }
-
- // at this point we've reached the desired mute gain regardless
- mute_gain = dmg;
}
ChanCount
Route::n_process_buffers ()
{
- return max (n_inputs(), processor_max_streams);
-}
-
-void
-Route::setup_peak_meters()
-{
- ChanCount max_streams = std::max (_inputs.count(), _outputs.count());
- max_streams = std::max (max_streams, processor_max_streams);
- _meter->configure_io (max_streams, max_streams);
+ return max (_input->n_ports(), processor_max_streams);
}
void
Route::passthru (sframes_t start_frame, sframes_t end_frame, nframes_t nframes, int declick)
{
- BufferSet& bufs = _session.get_scratch_buffers(n_process_buffers());
+ BufferSet& bufs = _session.get_scratch_buffers (n_process_buffers());
_silent = false;
- collect_input (bufs, nframes);
+ assert (bufs.available() >= _input->n_ports());
+
+ if (_input->n_ports() == ChanCount::ZERO) {
+ silence (nframes);
+ }
+
+ bufs.set_count (_input->n_ports());
+
+ for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
+
+ BufferSet::iterator o = bufs.begin(*t);
+ PortSet& ports (_input->ports());
+
+ for (PortSet::iterator i = ports.begin(*t); i != ports.end(*t); ++i, ++o) {
+ o->read_from (i->get_buffer(nframes), nframes);
+ }
+ }
process_output_buffers (bufs, start_frame, end_frame, nframes, true, declick);
}
@@ -510,82 +456,58 @@ Route::set_solo (bool yn, void *src)
return;
}
- if (_soloed != yn) {
- _soloed = yn;
+ if (_main_outs->soloed() != yn) {
+ _main_outs->mod_solo_level (yn ? 1 : -1);
solo_changed (src); /* EMIT SIGNAL */
_solo_control->Changed (); /* EMIT SIGNAL */
}
-
- catch_up_on_solo_mute_override ();
}
-void
-Route::catch_up_on_solo_mute_override ()
+bool
+Route::soloed() const
{
- if (Config->get_solo_model() != InverseMute) {
- return;
- }
-
- {
- Glib::Mutex::Lock lm (declick_lock);
-
- if (_muted) {
- if (Config->get_solo_mute_override()) {
- desired_mute_gain = (_soloed?1.0:0.0);
- } else {
- desired_mute_gain = 0.0;
- }
- } else {
- desired_mute_gain = 1.0;
- }
- }
+ return _main_outs->soloed ();
}
void
-Route::set_solo_mute (bool yn)
+Route::set_solo_isolated (bool yn, void *src)
{
- Glib::Mutex::Lock lm (declick_lock);
+ if (_mix_group && src != _mix_group && _mix_group->is_active()) {
+ _mix_group->apply (&Route::set_solo_isolated, yn, _mix_group);
+ return;
+ }
- /* Called by Session in response to another Route being soloed.
- */
-
- desired_solo_gain = (yn?0.0:1.0);
+ _main_outs->set_solo_isolated (yn);
+ solo_isolated_changed (src);
}
-void
-Route::set_solo_safe (bool yn, void *src)
+bool
+Route::solo_isolated () const
{
- if (_solo_safe != yn) {
- _solo_safe = yn;
- solo_safe_changed (src); /* EMIT SIGNAL */
- }
+ return _main_outs->solo_isolated();
}
void
Route::set_mute (bool yn, void *src)
-
{
if (_mix_group && src != _mix_group && _mix_group->is_active()) {
_mix_group->apply (&Route::set_mute, yn, _mix_group);
return;
}
- if (_muted != yn) {
- _muted = yn;
- mute_changed (src); /* EMIT SIGNAL */
-
- _mute_control->Changed (); /* EMIT SIGNAL */
-
- Glib::Mutex::Lock lm (declick_lock);
-
- if (_soloed && Config->get_solo_mute_override()) {
- desired_mute_gain = 1.0f;
- } else {
- desired_mute_gain = (yn?0.0f:1.0f);
- }
+ if (muted() != yn) {
+ _mute_master->mute (yn);
+ mute_changed (src);
}
+}
+
+bool
+Route::muted() const
+{
+ return _mute_master->muted ();
}
+#if DEFINE_IF_YOU_NEED_THIS
static void
dump_processors(const string& name, const list<boost::shared_ptr<Processor> >& procs)
{
@@ -596,6 +518,7 @@ dump_processors(const string& name, const list<boost::shared_ptr<Processor> >& p
}
cerr << "}" << endl;
}
+#endif
Route::ProcessorList::iterator
Route::prefader_iterator()
@@ -702,22 +625,19 @@ Route::add_processor (boost::shared_ptr<Processor> processor, ProcessorList::ite
}
- // Ensure peak vector sizes before the plugin is activated
- ChanCount potential_max_streams = ChanCount::max (processor->input_streams(), processor->output_streams());
-
- _meter->configure_io (potential_max_streams, potential_max_streams);
+ if (_meter) {
+ // Ensure peak vector sizes before the plugin is activated
+ ChanCount potential_max_streams = ChanCount::max (processor->input_streams(), processor->output_streams());
+ _meter->configure_io (potential_max_streams, potential_max_streams);
+ }
// XXX: do we want to emit the signal here ? change call order.
processor->activate ();
processor->ActiveChanged.connect (bind (mem_fun (_session, &Session::update_latency_compensation), false, false));
- _user_latency = 0;
+ _output->set_user_latency (0);
}
- if (processor_max_streams != old_pms || old_pms == ChanCount::ZERO) {
- reset_panner ();
- }
-
processors_changed (); /* EMIT SIGNAL */
return 0;
@@ -747,7 +667,7 @@ Route::add_processor_from_xml (const XMLNode& node, ProcessorList::iterator iter
if (node.name() == "Send") {
try {
- boost::shared_ptr<Send> send (new Send (_session, node));
+ boost::shared_ptr<Send> send (new Send (_session, _mute_master, node));
add_processor (send, iter);
return true;
}
@@ -762,6 +682,9 @@ Route::add_processor_from_xml (const XMLNode& node, ProcessorList::iterator iter
try {
if ((prop = node.property ("type")) != 0) {
+
+ cerr << _name << " : got processor type " << prop->value() << endl;
+
boost::shared_ptr<Processor> processor;
bool have_insert = false;
@@ -775,31 +698,35 @@ Route::add_processor_from_xml (const XMLNode& node, ProcessorList::iterator iter
} else if (prop->value() == "port") {
- processor.reset (new PortInsert (_session, node));
+ processor.reset (new PortInsert (_session, _mute_master, node));
} else if (prop->value() == "send") {
- processor.reset (new Send (_session, node));
+ processor.reset (new Send (_session, _mute_master, node));
have_insert = true;
} else if (prop->value() == "meter") {
processor = _meter;
+ processor->set_state (node);
} else if (prop->value() == "amp") {
processor = _amp;
+ processor->set_state (node);
} else if (prop->value() == "listen" || prop->value() == "deliver") {
/* XXX need to generalize */
processor = _control_outs;
+ processor->set_state (node);
} else if (prop->value() == "main-outs") {
processor = _main_outs;
-
+ processor->set_state (node);
+
} else {
error << string_compose(_("unknown Processor type \"%1\"; ignored"), prop->value()) << endmsg;
@@ -884,7 +811,7 @@ Route::add_processors (const ProcessorList& others, ProcessorList::iterator iter
ProcessorList::iterator existing_end = _processors.end();
--existing_end;
- ChanCount potential_max_streams = ChanCount::max (n_inputs(), n_outputs());
+ ChanCount potential_max_streams = ChanCount::max (_input->n_ports(), _output->n_ports());
for (ProcessorList::const_iterator i = others.begin(); i != others.end(); ++i) {
@@ -921,11 +848,7 @@ Route::add_processors (const ProcessorList& others, ProcessorList::iterator iter
(*i)->ActiveChanged.connect (bind (mem_fun (_session, &Session::update_latency_compensation), false, false));
}
- _user_latency = 0;
- }
-
- if (processor_max_streams != old_pms || old_pms == ChanCount::ZERO) {
- reset_panner ();
+ _output->set_user_latency (0);
}
processors_changed (); /* EMIT SIGNAL */
@@ -1081,7 +1004,7 @@ Route::pre_fader_streams() const
if (processor) {
return processor->output_streams();
} else {
- return n_inputs ();
+ return _input->n_ports ();
}
}
@@ -1134,10 +1057,6 @@ Route::clear_processors (Placement p)
configure_processors_unlocked (&err); // this can't fail
}
- if (processor_max_streams != old_pms) {
- reset_panner ();
- }
-
processor_max_streams.reset();
_have_internal_generator = false;
processors_changed (); /* EMIT SIGNAL */
@@ -1173,7 +1092,7 @@ Route::remove_processor (boost::shared_ptr<Processor> processor, ProcessorStream
if (*i == processor) {
/* move along, see failure case for configure_processors()
- where we may need to reprocessor the processor.
+ where we may need to reconfigure the processor.
*/
/* stop redirects that send signals to JACK ports
@@ -1181,13 +1100,17 @@ Route::remove_processor (boost::shared_ptr<Processor> processor, ProcessorStream
run.
*/
- boost::shared_ptr<IOProcessor> redirect;
-
- if ((redirect = boost::dynamic_pointer_cast<IOProcessor> (*i)) != 0) {
- redirect->io()->disconnect_inputs (this);
- redirect->io()->disconnect_outputs (this);
+ boost::shared_ptr<IOProcessor> iop;
+
+ if ((iop = boost::dynamic_pointer_cast<IOProcessor> (*i)) != 0) {
+ if (iop->input()) {
+ iop->input()->disconnect (this);
+ }
+ if (iop->output()) {
+ iop->output()->disconnect (this);
+ }
}
-
+
i = _processors.erase (i);
removed = true;
break;
@@ -1196,7 +1119,7 @@ Route::remove_processor (boost::shared_ptr<Processor> processor, ProcessorStream
++i;
}
- _user_latency = 0;
+ _output->set_user_latency (0);
}
if (!removed) {
@@ -1226,10 +1149,6 @@ Route::remove_processor (boost::shared_ptr<Processor> processor, ProcessorStream
}
}
- if (old_pms != processor_max_streams) {
- reset_panner ();
- }
-
processor->drop_references ();
processors_changed (); /* EMIT SIGNAL */
@@ -1259,7 +1178,7 @@ Route::configure_processors_unlocked (ProcessorStreams* err)
_in_configure_processors = true;
// Check each processor in order to see if we can configure as requested
- ChanCount in = n_inputs();
+ ChanCount in = _input->n_ports ();
ChanCount out;
list< pair<ChanCount,ChanCount> > configuration;
uint32_t index = 0;
@@ -1288,8 +1207,8 @@ Route::configure_processors_unlocked (ProcessorStreams* err)
}
// Ensure route outputs match last processor's outputs
- if (out != n_outputs()) {
- ensure_io (n_inputs(), out, false, this);
+ if (out != _output->n_ports ()) {
+ _output->ensure_io (out, false, this);
}
_in_configure_processors = false;
@@ -1354,6 +1273,12 @@ Route::all_processors_active (Placement p, bool state)
int
Route::reorder_processors (const ProcessorList& new_order, Placement placement, ProcessorStreams* err)
{
+ /* "new_order" is an ordered list of processors to be positioned according to "placement".
+ NOTE: all processors in "new_order" MUST be marked as visible. There maybe additional
+ processors in the current actual processor list that are hidden. Any visible processors
+ in the current list but not in "new_order" will be assumed to be deleted.
+ */
+
{
Glib::RWLock::WriterLock lm (_processor_lock);
ChanCount old_pms = processor_max_streams;
@@ -1384,6 +1309,10 @@ Route::reorder_processors (const ProcessorList& new_order, Placement placement,
*/
as_it_will_be.insert (as_it_will_be.end(), niter, new_order.end());
+ while (niter != new_order.end()) {
+ (*niter)->set_placement (placement);
+ ++niter;
+ }
break;
} else {
@@ -1391,16 +1320,18 @@ Route::reorder_processors (const ProcessorList& new_order, Placement placement,
if (!(*oiter)->visible()) {
as_it_will_be.push_back (*oiter);
+ (*oiter)->set_placement (placement);
} else {
/* visible processor: check that its in the new order */
if (find (new_order.begin(), new_order.end(), (*oiter)) == new_order.end()) {
- /* deleted: do nothing */
+ /* deleted: do nothing, shared_ptr<> will clean up */
} else {
/* ignore this one, and add the next item from the new order instead */
as_it_will_be.push_back (*niter);
+ (*niter)->set_placement (placement);
++niter;
}
}
@@ -1420,8 +1351,6 @@ Route::reorder_processors (const ProcessorList& new_order, Placement placement,
}
}
- /* do we really need to do this every time? */
- reset_panner ();
processors_changed (); /* EMIT SIGNAL */
return 0;
@@ -1446,21 +1375,16 @@ Route::state(bool full_state)
ProcessorList::iterator i;
char buf[32];
+ node->add_property ("name", _name);
+ node->add_property("default-type", _default_type.to_string());
+
if (_flags) {
node->add_property("flags", enum_2_string (_flags));
}
-
- node->add_property("default-type", _default_type.to_string());
node->add_property("active", _active?"yes":"no");
- node->add_property("muted", _muted?"yes":"no");
- node->add_property("soloed", _soloed?"yes":"no");
node->add_property("phase-invert", _phase_invert?"yes":"no");
node->add_property("denormal-protection", _denormal_protection?"yes":"no");
- node->add_property("mute-affects-pre-fader", _mute_affects_pre_fader?"yes":"no");
- node->add_property("mute-affects-post-fader", _mute_affects_post_fader?"yes":"no");
- node->add_property("mute-affects-control-outs", _mute_affects_control_outs?"yes":"no");
- node->add_property("mute-affects-main-outs", _mute_affects_main_outs?"yes":"no");
node->add_property("meter-point", enum_2_string (_meter_point));
if (_edit_group) {
@@ -1489,9 +1413,10 @@ Route::state(bool full_state)
}
node->add_property ("order-keys", order_string);
- node->add_child_nocopy (IO::state (full_state));
+ node->add_child_nocopy (_input->state (full_state));
+ node->add_child_nocopy (_output->state (full_state));
node->add_child_nocopy (_solo_control->get_state ());
- node->add_child_nocopy (_mute_control->get_state ());
+ node->add_child_nocopy (_mute_master->get_state ());
XMLNode* remote_control_node = new XMLNode (X_("RemoteControl"));
snprintf (buf, sizeof (buf), "%d", _remote_control_id);
@@ -1514,92 +1439,6 @@ Route::state(bool full_state)
return *node;
}
-XMLNode&
-Route::get_processor_state ()
-{
- XMLNode* root = new XMLNode (X_("redirects"));
- for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
- root->add_child_nocopy ((*i)->state (true));
- }
-
- return *root;
-}
-
-int
-Route::set_processor_state (const XMLNode& root)
-{
- if (root.name() != X_("redirects")) {
- return -1;
- }
-
- XMLNodeList nlist;
- XMLNodeList nnlist;
- XMLNodeConstIterator iter;
- XMLNodeConstIterator niter;
- Glib::RWLock::ReaderLock lm (_processor_lock);
-
- nlist = root.children();
-
- for (iter = nlist.begin(); iter != nlist.end(); ++iter){
-
- /* iter now points to a IOProcessor state node */
-
- nnlist = (*iter)->children ();
-
- for (niter = nnlist.begin(); niter != nnlist.end(); ++niter) {
-
- /* find the IO child node, since it contains the ID we need */
-
- /* XXX OOP encapsulation violation, ugh */
-
- if ((*niter)->name() == IO::state_node_name) {
-
- XMLProperty* prop = (*niter)->property (X_("id"));
-
- if (!prop) {
- warning << _("IOProcessor node has no ID, ignored") << endmsg;
- break;
- }
-
- ID id = prop->value ();
-
- /* now look for a processor with that ID */
-
- for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
- if ((*i)->id() == id) {
- (*i)->set_state (**iter);
- break;
- }
- }
-
- break;
-
- }
- }
-
- }
-
- return 0;
-}
-
-void
-Route::set_deferred_state ()
-{
- XMLNodeList nlist;
- XMLNodeConstIterator niter;
-
- if (!deferred_state) {
- return;
- }
-
- nlist = deferred_state->children();
-
- _set_processor_states (nlist);
-
- delete deferred_state;
- deferred_state = 0;
-}
-
int
Route::set_state (const XMLNode& node)
{
@@ -1609,6 +1448,7 @@ Route::set_state (const XMLNode& node)
int
Route::_set_state (const XMLNode& node, bool call_base)
{
+
XMLNodeList nlist;
XMLNodeConstIterator niter;
XMLNode *child;
@@ -1620,17 +1460,16 @@ Route::_set_state (const XMLNode& node, bool call_base)
return -1;
}
+ if ((prop = node.property (X_("name"))) != 0) {
+ Route::set_name (prop->value());
+ }
+
if ((prop = node.property (X_("flags"))) != 0) {
_flags = Flag (string_2_enum (prop->value(), _flags));
} else {
_flags = Flag (0);
}
- if ((prop = node.property (X_("default-type"))) != 0) {
- _default_type = DataType(prop->value());
- assert(_default_type != DataType::NIL);
- }
-
if ((prop = node.property (X_("phase-invert"))) != 0) {
set_phase_invert (prop->value()=="yes"?true:false, this);
}
@@ -1639,45 +1478,18 @@ Route::_set_state (const XMLNode& node, bool call_base)
set_denormal_protection (prop->value()=="yes"?true:false, this);
}
- _active = true;
if ((prop = node.property (X_("active"))) != 0) {
- set_active (prop->value() == "yes");
- }
-
- if ((prop = node.property (X_("muted"))) != 0) {
- bool yn = prop->value()=="yes"?true:false;
-
- /* force reset of mute status */
-
- _muted = !yn;
- set_mute(yn, this);
- mute_gain = desired_mute_gain;
+ bool yn = (prop->value() == "yes");
+ _active = !yn; // force switch
+ set_active (yn);
}
if ((prop = node.property (X_("soloed"))) != 0) {
- bool yn = prop->value()=="yes"?true:false;
+ bool yn = (prop->value()=="yes");
- /* force reset of solo status */
+ /* XXX force reset of solo status */
- _soloed = !yn;
set_solo (yn, this);
- solo_gain = desired_solo_gain;
- }
-
- if ((prop = node.property (X_("mute-affects-pre-fader"))) != 0) {
- _mute_affects_pre_fader = (prop->value()=="yes")?true:false;
- }
-
- if ((prop = node.property (X_("mute-affects-post-fader"))) != 0) {
- _mute_affects_post_fader = (prop->value()=="yes")?true:false;
- }
-
- if ((prop = node.property (X_("mute-affects-control-outs"))) != 0) {
- _mute_affects_control_outs = (prop->value()=="yes")?true:false;
- }
-
- if ((prop = node.property (X_("mute-affects-main-outs"))) != 0) {
- _mute_affects_main_outs = (prop->value()=="yes")?true:false;
}
if ((prop = node.property (X_("meter-point"))) != 0) {
@@ -1725,51 +1537,35 @@ Route::_set_state (const XMLNode& node, bool call_base)
}
nlist = node.children();
-
- delete deferred_state;
- deferred_state = new XMLNode(X_("deferred state"));
-
- /* set parent class properties before anything else */
+ XMLNode processor_state (X_("processor_state"));
for (niter = nlist.begin(); niter != nlist.end(); ++niter){
-
+
child = *niter;
- if (child->name() == IO::state_node_name && call_base) {
- IO::set_state (*child);
- break;
+ if (child->name() == IO::state_node_name) {
+ if ((prop = child->property (X_("direction"))) == 0) {
+ continue;
+ }
+
+ if (prop->value() == "Input") {
+ _input->set_state (*child);
+ } else if (prop->value() == "Output") {
+ _output->set_state (*child);
+ }
}
- }
-
- for (niter = nlist.begin(); niter != nlist.end(); ++niter){
-
- child = *niter;
- if (child->name() == X_("Send") || child->name() == X_("Processor")) {
- deferred_state->add_child_copy (*child);
+ if (child->name() == X_("Processor")) {
+ processor_state.add_child_copy (*child);
}
}
- if (ports_legal) {
- _set_processor_states (deferred_state->children());
- delete deferred_state;
- deferred_state = 0;
- }
-
+ set_processor_state (processor_state);
+
for (niter = nlist.begin(); niter != nlist.end(); ++niter){
child = *niter;
- if (child->name() == X_("Automation")) {
-
- if ((prop = child->property (X_("path"))) != 0) {
- load_automation (prop->value());
- }
-
- } else if (child->name() == X_("ControlOuts")) {
-
- /* ignore this - deprecated */
-
- } else if (child->name() == X_("Comment")) {
+ if (child->name() == X_("Comment")) {
/* XXX this is a terrible API design in libxml++ */
@@ -1785,17 +1581,15 @@ Route::_set_state (const XMLNode& node, bool call_base)
if (prop->value() == "solo") {
_solo_control->set_state (*child);
_session.add_controllable (_solo_control);
- } else if (prop->value() == "mute") {
- _mute_control->set_state (*child);
- _session.add_controllable (_mute_control);
- }
+ }
+
} else if (child->name() == X_("RemoteControl")) {
if ((prop = child->property (X_("id"))) != 0) {
int32_t x;
sscanf (prop->value().c_str(), "%d", &x);
set_remote_control_id (x);
}
- }
+ }
}
if ((prop = node.property (X_("mix-group"))) != 0) {
@@ -1810,13 +1604,27 @@ Route::_set_state (const XMLNode& node, bool call_base)
return 0;
}
+XMLNode&
+Route::get_processor_state ()
+{
+ XMLNode* root = new XMLNode (X_("redirects"));
+ for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
+ root->add_child_nocopy ((*i)->state (true));
+ }
+
+ return *root;
+}
+
void
-Route::_set_processor_states(const XMLNodeList &nlist)
+Route::set_processor_state (const XMLNode& node)
{
+ const XMLNodeList &nlist = node.children();
XMLNodeConstIterator niter;
bool has_meter_processor = false; // legacy sessions don't
ProcessorList::iterator i, o;
+ cerr << _name << " _set_processor_states\n";
+
// Iterate through existing processors, remove those which are not in the state list
for (i = _processors.begin(); i != _processors.end(); ) {
ProcessorList::iterator tmp = i;
@@ -1852,6 +1660,8 @@ Route::_set_processor_states(const XMLNodeList &nlist)
has_meter_processor = true;
}
+ cerr << _name << " setting up proc state for " << prop->value() << endl;
+
o = i;
if (prop->value() != "meter" && prop->value() != "amp" && prop->value() != "main-outs") {
@@ -1872,6 +1682,8 @@ Route::_set_processor_states(const XMLNodeList &nlist)
// create it and move it to the correct location
if (o == _processors.end()) {
+ cerr << "\tproc not in list\n";
+
if (add_processor_from_xml (**niter, i)) {
--i; // move iterator to the newly inserted processor
} else {
@@ -1882,6 +1694,8 @@ Route::_set_processor_states(const XMLNodeList &nlist)
// ensure it is at the location provided in the XML state
} else {
+ cerr << "\tproc in wrong place in list\n";
+
if (i != o) {
boost::shared_ptr<Processor> tmp = (*o);
_processors.erase (o); // remove the old copy
@@ -1889,6 +1703,7 @@ Route::_set_processor_states(const XMLNodeList &nlist)
--i; // move iterator to the correct processor
}
+ cerr << "\tnow reset proc " << (*i)->name() << endl;
(*i)->set_state (**niter);
}
}
@@ -1902,9 +1717,6 @@ Route::_set_processor_states(const XMLNodeList &nlist)
}
processors_changed ();
-
-
-
}
void
@@ -1919,7 +1731,7 @@ Route::silence (nframes_t nframes)
{
if (!_silent) {
- IO::silence (nframes);
+ _output->silence (nframes);
{
Glib::RWLock::ReaderLock lm (_processor_lock, Glib::TRY_LOCK);
@@ -1953,7 +1765,7 @@ Route::add_listener (boost::shared_ptr<IO> io, const string& listen_name)
name += listen_name;
name += ']';
- boost::shared_ptr<Delivery> listener (new Delivery (_session, name, Delivery::Listen));
+ boost::shared_ptr<Delivery> listener (new Delivery (_session, _mute_master, name, Delivery::Listen));
/* As an IO, our control outs need as many IO outputs as we have outputs
* (we track the changes in ::output_change_handler()).
@@ -1961,7 +1773,7 @@ Route::add_listener (boost::shared_ptr<IO> io, const string& listen_name)
* (i.e. it does not modify its input buffers whatsoever)
*/
- if (listener->io()->ensure_io (ChanCount::ZERO, n_outputs(), true, this)) {
+ if (listener->output()->ensure_io (n_outputs(), true, this)) {
return boost::shared_ptr<Delivery>();
}
@@ -1982,17 +1794,17 @@ Route::listen_via (boost::shared_ptr<IO> io, const string& listen_name)
for (ProcessorList::const_iterator x = _processors.begin(); x != _processors.end(); ++x) {
boost::shared_ptr<const Delivery> d = boost::dynamic_pointer_cast<const Delivery>(*x);
- if (d && d->io() == io) {
+ if (d && d->output() == io) {
/* already listening via the specified IO: do nothing */
return 0;
}
}
}
- uint32_t ni = io->n_inputs().n_total();
+ uint32_t ni = io->n_ports().n_total();
for (uint32_t n = 0; n < ni; ++n) {
- ports.push_back (io->input(n)->name());
+ ports.push_back (io->nth (n)->name());
}
if (ports.empty()) {
@@ -2007,13 +1819,13 @@ Route::listen_via (boost::shared_ptr<IO> io, const string& listen_name)
/* now connect to the named ports */
- ni = listen_point->io()->n_outputs().n_total();
+ ni = listen_point->output()->n_ports().n_total();
size_t psize = ports.size();
for (size_t n = 0; n < ni; ++n) {
- if (listen_point->io()->connect_output (listen_point->io()->output (n), ports[n % psize], this)) {
+ if (listen_point->output()->connect (listen_point->output()->nth (n), ports[n % psize], this)) {
error << string_compose (_("could not connect %1 to %2"),
- listen_point->io()->output(n)->name(), ports[n % psize]) << endmsg;
+ listen_point->output()->nth (n)->name(), ports[n % psize]) << endmsg;
return -1;
}
}
@@ -2037,7 +1849,7 @@ Route::drop_listen (boost::shared_ptr<IO> io)
boost::shared_ptr<Delivery> d = boost::dynamic_pointer_cast<Delivery>(*x);
- if (d && d->io() == io) {
+ if (d && d->output() == io) {
/* already listening via the specified IO: do nothing */
remove_processor (*x, &err);
@@ -2114,7 +1926,7 @@ Route::set_comment (string cmt, void *src)
bool
Route::feeds (boost::shared_ptr<IO> other)
{
- if (connected_to (other)) {
+ if (_output->connected_to (other)) {
return true;
}
@@ -2122,10 +1934,10 @@ Route::feeds (boost::shared_ptr<IO> other)
for (ProcessorList::iterator r = _processors.begin(); r != _processors.end(); r++) {
- boost::shared_ptr<IOProcessor> proc;
-
- if ((proc = boost::dynamic_pointer_cast<IOProcessor>(*r)) != 0) {
- if (proc->io()->connected_to (other)) {
+ boost::shared_ptr<IOProcessor> iop;
+
+ if ((iop = boost::dynamic_pointer_cast<IOProcessor>(*r)) != 0) {
+ if (iop->output() && iop->output()->connected_to (other)) {
return true;
}
}
@@ -2135,55 +1947,6 @@ Route::feeds (boost::shared_ptr<IO> other)
}
void
-Route::set_mute_config (mute_type t, bool onoff, void *src)
-{
- switch (t) {
- case PRE_FADER:
- _mute_affects_pre_fader = onoff;
- pre_fader_changed(src); /* EMIT SIGNAL */
- break;
-
- case POST_FADER:
- _mute_affects_post_fader = onoff;
- post_fader_changed(src); /* EMIT SIGNAL */
- break;
-
- case CONTROL_OUTS:
- _mute_affects_control_outs = onoff;
- control_outs_changed(src); /* EMIT SIGNAL */
- break;
-
- case MAIN_OUTS:
- _mute_affects_main_outs = onoff;
- main_outs_changed(src); /* EMIT SIGNAL */
- break;
- }
-}
-
-bool
-Route::get_mute_config (mute_type t)
-{
- bool onoff = false;
-
- switch (t){
- case PRE_FADER:
- onoff = _mute_affects_pre_fader;
- break;
- case POST_FADER:
- onoff = _mute_affects_post_fader;
- break;
- case CONTROL_OUTS:
- onoff = _mute_affects_control_outs;
- break;
- case MAIN_OUTS:
- onoff = _mute_affects_main_outs;
- break;
- }
-
- return onoff;
-}
-
-void
Route::handle_transport_stopped (bool abort_ignored, bool did_locate, bool can_flush_processors)
{
nframes_t now = _session.transport_frame();
@@ -2206,8 +1969,6 @@ Route::handle_transport_stopped (bool abort_ignored, bool did_locate, bool can_f
}
}
- IO::transport_stopped (now);
-
_roll_delay = _initial_delay;
}
@@ -2223,11 +1984,10 @@ void
Route::output_change_handler (IOChange change, void *src)
{
if ((change & ConfigurationChanged)) {
- if (_control_outs) {
- _control_outs->io()->ensure_io (ChanCount::ZERO, n_outputs(), true, this);
- }
- configure_processors (0);
+ /* XXX resize all listeners to match _main_outs? */
+
+ // configure_processors (0);
}
}
@@ -2249,18 +2009,13 @@ Route::no_roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame,
return 0;
}
- if (session_state_changing || !_active) {
+ if (session_state_changing || !_active || n_inputs() == ChanCount::ZERO) {
silence (nframes);
return 0;
}
- _amp->apply_gain_automation(false);
-
- if (n_inputs() != ChanCount::ZERO) {
- passthru (start_frame, end_frame, nframes, 0);
- } else {
- silence (nframes);
- }
+ _amp->apply_gain_automation (false);
+ passthru (start_frame, end_frame, nframes, 0);
return 0;
}
@@ -2283,7 +2038,7 @@ Route::check_initial_delay (nframes_t nframes, nframes_t& transport_frame)
output ports, so make a note of that for
future reference.
*/
- increment_output_offset (_roll_delay);
+ _main_outs->increment_output_offset (_roll_delay);
transport_frame += _roll_delay;
_roll_delay = 0;
@@ -2297,15 +2052,20 @@ Route::roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame, int
bool can_record, bool rec_monitors_input)
{
{
+ // automation snapshot can also be called from the non-rt context
+ // and it uses the processor list, so we try to acquire the lock here
Glib::RWLock::ReaderLock lm (_processor_lock, Glib::TRY_LOCK);
+
if (lm.locked()) {
- // automation snapshot can also be called from the non-rt context
- // and it uses the processor list, so we take the lock out here
automation_snapshot (_session.transport_frame(), false);
}
}
- if ((n_outputs().n_total() == 0 && _processors.empty()) || n_inputs().n_total() == 0 || !_active) {
+ if (n_outputs().n_total() == 0) {
+ return 0;
+ }
+
+ if (!_active || n_inputs().n_total() == 0) {
silence (nframes);
return 0;
}
@@ -2318,21 +2078,6 @@ Route::roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame, int
_silent = false;
- _amp->apply_gain_automation(false);
-
- {
- Glib::Mutex::Lock am (data().control_lock(), Glib::TRY_LOCK);
-
- if (am.locked() && _session.transport_rolling()) {
-
- if (_gain_control->automation_playback()) {
- _amp->apply_gain_automation(
- _gain_control->list()->curve().rt_safe_get_vector (
- start_frame, end_frame, _session.gain_automation_buffer(), nframes));
- }
- }
- }
-
passthru (start_frame, end_frame, nframes, declick);
return 0;
@@ -2349,7 +2094,7 @@ Route::silent_roll (nframes_t nframes, sframes_t start_frame, sframes_t end_fram
void
Route::toggle_monitor_input ()
{
- for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
+ for (PortSet::iterator i = _input->ports().begin(); i != _input->ports().end(); ++i) {
i->ensure_monitor_input( ! i->monitoring_input());
}
}
@@ -2357,15 +2102,15 @@ Route::toggle_monitor_input ()
bool
Route::has_external_redirects () const
{
- // FIXME: what about sends?
+ // FIXME: what about sends? - they don't return a signal back to ardour?
boost::shared_ptr<const PortInsert> pi;
for (ProcessorList::const_iterator i = _processors.begin(); i != _processors.end(); ++i) {
+
if ((pi = boost::dynamic_pointer_cast<const PortInsert>(*i)) != 0) {
- for (PortSet::const_iterator port = pi->io()->outputs().begin();
- port != pi->io()->outputs().end(); ++port) {
+ for (PortSet::const_iterator port = pi->output()->ports().begin(); port != pi->output()->ports().end(); ++port) {
string port_name = port->name();
string client_name = port_name.substr (0, port_name.find(':'));
@@ -2428,55 +2173,51 @@ Route::set_meter_point (MeterPoint p, void *src)
nframes_t
Route::update_total_latency ()
{
- nframes_t old = _own_latency;
-
- if (_user_latency) {
- _own_latency = _user_latency;
- } else {
- _own_latency = 0;
+ nframes_t old = _output->effective_latency();
+ nframes_t own_latency = _output->user_latency();
- for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
- if ((*i)->active ()) {
- _own_latency += (*i)->signal_latency ();
- }
+ for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
+ if ((*i)->active ()) {
+ own_latency += (*i)->signal_latency ();
}
}
#undef DEBUG_LATENCY
#ifdef DEBUG_LATENCY
- cerr << _name << ": internal redirect latency = " << _own_latency << endl;
+ cerr << _name << ": internal redirect latency = " << own_latency << endl;
#endif
- set_port_latency (_own_latency);
+ _output->set_port_latency (own_latency);
- if (!_user_latency) {
+ if (_output->user_latency() == 0) {
+
/* this (virtual) function is used for pure Routes,
not derived classes like AudioTrack. this means
that the data processed here comes from an input
port, not prerecorded material, and therefore we
have to take into account any input latency.
*/
-
-
- _own_latency += input_latency ();
+
+ own_latency += _input->signal_latency ();
}
- if (old != _own_latency) {
+ if (old != own_latency) {
+ _output->set_latency_delay (own_latency);
signal_latency_changed (); /* EMIT SIGNAL */
}
#ifdef DEBUG_LATENCY
- cerr << _name << ": input latency = " << input_latency() << " total = "
- << _own_latency << endl;
+ cerr << _name << ": input latency = " << _input->signal_latency() << " total = "
+ << own_latency << endl;
#endif
- return _own_latency;
+ return _output->effective_latency ();
}
void
Route::set_user_latency (nframes_t nframes)
{
- Latent::set_user_latency (nframes);
+ _output->set_user_latency (nframes);
_session.update_latency_compensation (false, false);
}
@@ -2485,8 +2226,8 @@ Route::set_latency_delay (nframes_t longest_session_latency)
{
nframes_t old = _initial_delay;
- if (_own_latency < longest_session_latency) {
- _initial_delay = longest_session_latency - _own_latency;
+ if (_output->effective_latency() < longest_session_latency) {
+ _initial_delay = longest_session_latency - _output->effective_latency();
} else {
_initial_delay = 0;
}
@@ -2503,57 +2244,32 @@ Route::set_latency_delay (nframes_t longest_session_latency)
void
Route::automation_snapshot (nframes_t now, bool force)
{
- if (!force && !should_snapshot(now)) {
- return;
- }
-
- IO::automation_snapshot (now, force);
-
for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
(*i)->automation_snapshot (now, force);
}
}
-Route::ToggleControllable::ToggleControllable (std::string name, Route& s, ToggleType tp)
- : Controllable (name), route (s), type(tp)
+Route::SoloControllable::SoloControllable (std::string name, Route& r)
+ : AutomationControl (r.session(), Evoral::Parameter (SoloAutomation),
+ boost::shared_ptr<AutomationList>(), name)
+ , route (r)
{
-
+ boost::shared_ptr<AutomationList> gl(new AutomationList(Evoral::Parameter(SoloAutomation)));
+ set_list (gl);
}
void
-Route::ToggleControllable::set_value (float val)
+Route::SoloControllable::set_value (float val)
{
bool bval = ((val >= 0.5f) ? true: false);
- switch (type) {
- case MuteControl:
- route.set_mute (bval, this);
- break;
- case SoloControl:
- route.set_solo (bval, this);
- break;
- default:
- break;
- }
+ route.set_solo (bval, this);
}
float
-Route::ToggleControllable::get_value (void) const
+Route::SoloControllable::get_value (void) const
{
- float val = 0.0f;
-
- switch (type) {
- case MuteControl:
- val = route.muted() ? 1.0f : 0.0f;
- break;
- case SoloControl:
- val = route.soloed() ? 1.0f : 0.0f;
- break;
- default:
- break;
- }
-
- return val;
+ return route.soloed() ? 1.0f : 0.0f;
}
void
@@ -2568,8 +2284,6 @@ Route::set_block_size (nframes_t nframes)
void
Route::protect_automation ()
{
- Automatable::protect_automation();
-
for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i)
(*i)->protect_automation();
}
@@ -2656,23 +2370,28 @@ Route::set_name (const string& str)
{
bool ret;
string ioproc_name;
+
+ SessionObject::set_name (str);
+
+ ret = (_input->set_name(str) && _output->set_name(str));
- if ((ret = IO::set_name (str)) == true) {
+ if (ret) {
+
Glib::RWLock::ReaderLock lm (_processor_lock);
for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
- /* rename all delivery objects to reflect our new name */
+ /* rename all processors with outputs to reflect our new name */
- boost::shared_ptr<Delivery> dp = boost::dynamic_pointer_cast<Delivery> (*i);
+ boost::shared_ptr<IOProcessor> iop = boost::dynamic_pointer_cast<IOProcessor> (*i);
- if (dp) {
- string dp_name = str;
- dp_name += '[';
- dp_name += "XXX FIX ME XXX";
- dp_name += ']';
+ if (iop) {
+ string iop_name = str;
+ iop_name += '[';
+ iop_name += "XXX FIX ME XXX";
+ iop_name += ']';
- if (!dp->set_name (dp_name)) {
+ if (!iop->set_name (iop_name)) {
ret = false;
}
}
@@ -2692,7 +2411,7 @@ Route::send_for (boost::shared_ptr<const IO> target) const
boost::shared_ptr<Send> send;
if ((send = boost::dynamic_pointer_cast<Send>(*i)) != 0) {
- if (send->io()->connected_to (target)) {
+ if (send->output()->connected_to (target)) {
return send;
}
}
@@ -2700,3 +2419,95 @@ Route::send_for (boost::shared_ptr<const IO> target) const
return boost::shared_ptr<Send>();
}
+
+void
+Route::set_phase_invert (bool yn, void *src)
+{
+ if (_phase_invert != yn) {
+ _phase_invert = yn;
+ // phase_invert_changed (src); /* EMIT SIGNAL */
+ }
+}
+
+bool
+Route::phase_invert () const
+{
+ return _phase_invert != 0;
+}
+
+void
+Route::set_denormal_protection (bool yn, void *src)
+{
+ if (_denormal_protection != yn) {
+ _denormal_protection = yn;
+ // denormal_protection_changed (src); /* EMIT SIGNAL */
+ }
+}
+
+bool
+Route::denormal_protection () const
+{
+ return _denormal_protection;
+}
+
+void
+Route::set_active (bool yn)
+{
+ if (_active != yn) {
+ _active = yn;
+ _input->set_active (yn);
+ _output->set_active (yn);
+ active_changed (); // EMIT SIGNAL
+ }
+}
+
+void
+Route::meter ()
+{
+ Glib::RWLock::ReaderLock rm (_processor_lock, Glib::TRY_LOCK);
+ _meter->meter ();
+}
+
+boost::shared_ptr<Panner>
+Route::panner() const
+{
+
+ return _main_outs->panner();
+}
+
+boost::shared_ptr<AutomationControl>
+Route::gain_control() const
+{
+
+ return _amp->gain_control();
+}
+
+boost::shared_ptr<AutomationControl>
+Route::get_control (const Evoral::Parameter& param)
+{
+ /* either we own the control or .... */
+
+ boost::shared_ptr<AutomationControl> c = boost::dynamic_pointer_cast<AutomationControl>(data().control (param));
+
+ if (!c) {
+
+ /* maybe one of our processors does or ... */
+
+ Glib::RWLock::ReaderLock rm (_processor_lock, Glib::TRY_LOCK);
+ for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
+ if ((c = boost::dynamic_pointer_cast<AutomationControl>((*i)->data().control (param))) != 0) {
+ break;
+ }
+ }
+ }
+
+ if (!c) {
+
+ /* nobody does so we'll make a new one */
+
+ c = boost::dynamic_pointer_cast<AutomationControl>(control_factory(param));
+ add_control(c);
+ }
+
+ return c;
+}
diff --git a/libs/ardour/route_group.cc b/libs/ardour/route_group.cc
index 527597548d..438d0395d0 100644
--- a/libs/ardour/route_group.cc
+++ b/libs/ardour/route_group.cc
@@ -27,6 +27,7 @@
#include "pbd/error.h"
#include "pbd/enumwriter.h"
+#include "ardour/amp.h"
#include "ardour/route_group.h"
#include "ardour/audio_track.h"
#include "ardour/audio_diskstream.h"
@@ -87,7 +88,7 @@ RouteGroup::get_min_factor(gain_t factor)
gain_t g;
for (list<Route *>::iterator i = routes.begin(); i != routes.end(); i++) {
- g = (*i)->gain();
+ g = (*i)->amp()->gain();
if ( (g+g*factor) >= 0.0f)
continue;
@@ -106,7 +107,7 @@ RouteGroup::get_max_factor(gain_t factor)
gain_t g;
for (list<Route *>::iterator i = routes.begin(); i != routes.end(); i++) {
- g = (*i)->gain();
+ g = (*i)->amp()->gain();
// if the current factor woulnd't raise this route above maximum
if ( (g+g*factor) <= 1.99526231f)
diff --git a/libs/ardour/send.cc b/libs/ardour/send.cc
index 5874b91cf6..61c235e60a 100644
--- a/libs/ardour/send.cc
+++ b/libs/ardour/send.cc
@@ -21,6 +21,7 @@
#include "pbd/xml++.h"
+#include "ardour/amp.h"
#include "ardour/send.h"
#include "ardour/session.h"
#include "ardour/port.h"
@@ -35,15 +36,23 @@
using namespace ARDOUR;
using namespace PBD;
-Send::Send (Session& s)
- : Delivery (s, string_compose (_("send %1"), (_bitslot = s.next_send_id()) + 1), Delivery::Send)
+Send::Send (Session& s, boost::shared_ptr<MuteMaster> mm)
+ : Delivery (s, mm, string_compose (_("send %1"), (_bitslot = s.next_send_id()) + 1), Delivery::Send)
+ , _metering (false)
{
+ _amp.reset (new Amp (_session, _mute_master));
+ _meter.reset (new PeakMeter (_session));
+
ProcessorCreated (this); /* EMIT SIGNAL */
}
-Send::Send (Session& s, const XMLNode& node)
- : Delivery (s, "send", Delivery::Send)
+Send::Send (Session& s, boost::shared_ptr<MuteMaster> mm, const XMLNode& node)
+ : Delivery (s, mm, "send", Delivery::Send)
+ , _metering (false)
{
+ _amp.reset (new Amp (_session, _mute_master));
+ _meter.reset (new PeakMeter (_session));
+
if (set_state (node)) {
throw failed_constructor();
}
@@ -56,6 +65,43 @@ Send::~Send ()
GoingAway ();
}
+void
+Send::run_in_place (BufferSet& bufs, sframes_t start_frame, sframes_t end_frame, nframes_t nframes)
+{
+ if (!_active || _output->n_ports() == ChanCount::ZERO) {
+ _meter->reset ();
+ return;
+ }
+
+ // we have to copy the input, because deliver_output() may alter the buffers
+ // in-place, which a send must never do.
+
+ BufferSet& sendbufs = _session.get_mix_buffers (bufs.count());
+ sendbufs.read_from (bufs, nframes);
+ assert(sendbufs.count() == bufs.count());
+
+ /* gain control */
+
+ // Can't automate gain for sends or returns yet because we need different buffers
+ // so that we don't overwrite the main automation data for the route amp
+ // _amp->setup_gain_automation (start_frame, end_frame, nframes);
+ _amp->run_in_place (sendbufs, start_frame, end_frame, nframes);
+
+ /* deliver to outputs */
+
+ Delivery::run_in_place (sendbufs, start_frame, end_frame, nframes);
+
+ /* consider metering */
+
+ if (_metering) {
+ if (_amp->gain_control()->get_value() == 0) {
+ _meter->reset();
+ } else {
+ _meter->run_in_place (*_output_buffers, start_frame, end_frame, nframes);
+ }
+ }
+}
+
XMLNode&
Send::get_state(void)
{
@@ -90,17 +136,9 @@ Send::set_state(const XMLNode& node)
const XMLNode* insert_node = &node;
- /* Send has regular IO automation (gain, pan) */
-
- for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
- if ((*niter)->name() == IOProcessor::state_node_name) {
- insert_node = *niter;
- } else if ((*niter)->name() == X_("Automation")) {
- // _io->set_automation_state (*(*niter), Evoral::Parameter(GainAutomation));
- }
- }
+ /* XXX need to load automation state & data for amp */
- IOProcessor::set_state (*insert_node);
+ Delivery::set_state (*insert_node);
return 0;
}
@@ -108,7 +146,7 @@ Send::set_state(const XMLNode& node)
bool
Send::can_support_io_configuration (const ChanCount& in, ChanCount& out) const
{
- if (_io->n_inputs() == ChanCount::ZERO && _io->n_outputs() == ChanCount::ZERO) {
+ if (_output->n_ports() == ChanCount::ZERO) {
/* not configured yet, we can support anything */
@@ -126,25 +164,6 @@ Send::can_support_io_configuration (const ChanCount& in, ChanCount& out) const
return false;
}
-bool
-Send::configure_io (ChanCount in, ChanCount out)
-{
- /* we're transparent no matter what. fight the power. */
-
- if (out != in) {
- return false;
- }
-
- if (_io->ensure_io (ChanCount::ZERO, in, false, this) != 0) {
- return false;
- }
-
- Processor::configure_io(in, out);
- _io->reset_panner();
-
- return true;
-}
-
/** Set up the XML description of a send so that its name is unique.
* @param state XML send state.
* @param session Session.
diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc
index db6063e7f4..25f3f6a368 100644
--- a/libs/ardour/session.cc
+++ b/libs/ardour/session.cc
@@ -272,7 +272,8 @@ Session::Session (AudioEngine &eng,
if (control_out_channels) {
ChanCount count(DataType::AUDIO, control_out_channels);
shared_ptr<Route> r (new Route (*this, _("monitor"), Route::ControlOut, DataType::AUDIO));
- r->ensure_io (count, count, false, this);
+ r->input()->ensure_io (count, false, this);
+ r->output()->ensure_io (count, false, this);
r->set_remote_control_id (control_id++);
rl.push_back (r);
@@ -280,9 +281,9 @@ Session::Session (AudioEngine &eng,
if (master_out_channels) {
ChanCount count(DataType::AUDIO, master_out_channels);
- cerr << "new MO with " << count << endl;
shared_ptr<Route> r (new Route (*this, _("master"), Route::MasterOut, DataType::AUDIO));
- r->ensure_io (count, count, false, this);
+ r->input()->ensure_io (count, false, this);
+ r->output()->ensure_io (count, false, this);
r->set_remote_control_id (control_id);
rl.push_back (r);
@@ -516,8 +517,8 @@ Session::set_worst_io_latencies ()
boost::shared_ptr<RouteList> r = routes.reader ();
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
- _worst_output_latency = max (_worst_output_latency, (*i)->output_latency());
- _worst_input_latency = max (_worst_input_latency, (*i)->input_latency());
+ _worst_output_latency = max (_worst_output_latency, (*i)->output()->latency());
+ _worst_input_latency = max (_worst_input_latency, (*i)->input()->latency());
}
}
@@ -574,15 +575,15 @@ Session::when_engine_running ()
for (int physport = 0; physport < 2; ++physport) {
string physical_output = _engine.get_nth_physical_output (DataType::AUDIO, physport);
-
+
if (physical_output.length()) {
- if (_click_io->add_output_port (physical_output, this)) {
+ if (_click_io->add_port (physical_output, this)) {
// relax, even though its an error
}
}
}
- if (_click_io->n_outputs () > ChanCount::ZERO) {
+ if (_click_io->n_ports () > ChanCount::ZERO) {
_clicking = Config->get_clicking ();
}
}
@@ -665,12 +666,6 @@ Session::when_engine_running ()
if (_master_out) {
- /* force the master to ignore any later call to this
- */
- if (_master_out->pending_state_node) {
- _master_out->ports_became_legal();
- }
-
/* if requested auto-connect the outputs to the first N physical ports.
*/
@@ -678,11 +673,11 @@ Session::when_engine_running ()
uint32_t limit = _master_out->n_outputs().n_total();
for (uint32_t n = 0; n < limit; ++n) {
- Port* p = _master_out->output (n);
+ Port* p = _master_out->output()->nth (n);
string connect_to = _engine.get_nth_physical_output (DataType (p->type()), n);
if (!connect_to.empty()) {
- if (_master_out->connect_output (p, connect_to, this)) {
+ if (_master_out->output()->connect (p, connect_to, this)) {
error << string_compose (_("cannot connect master output %1 to %2"), n, connect_to)
<< endmsg;
break;
@@ -760,10 +755,6 @@ Session::hookup_io ()
}
}
- /* Tell all IO objects to create their ports */
-
- IO::enable_ports ();
-
/* Connect track to listen/solo etc. busses XXX generalize this beyond control_out */
if (_control_out) {
@@ -777,7 +768,7 @@ Session::hookup_io ()
boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track> (*x);
if (t) {
- t->listen_via (_control_out, X_("listen"));
+ t->listen_via (_control_out->input(), X_("listen"));
}
}
}
@@ -794,7 +785,7 @@ Session::hookup_io ()
/* Now reset all panners */
- IO::reset_panners ();
+ Delivery::reset_panners ();
/* Anyone who cares about input state, wake up and do something */
@@ -1468,7 +1459,7 @@ Session::resort_routes_using (shared_ptr<RouteList> r)
continue;
}
- if ((*j)->feeds (*i)) {
+ if ((*j)->feeds ((*i)->input())) {
(*i)->fed_by.insert (*j);
}
}
@@ -1553,7 +1544,13 @@ Session::new_midi_track (TrackMode mode, uint32_t how_many)
try {
track = boost::shared_ptr<MidiTrack>((new MidiTrack (*this, track_name, Route::Flag (0), mode)));
- if (track->ensure_io (ChanCount(DataType::MIDI, 1), ChanCount(DataType::AUDIO, 1), false, this)) {
+ if (track->input()->ensure_io (ChanCount(DataType::MIDI, 1), false, this)) {
+ error << "cannot configure 1 in/1 out configuration for new midi track" << endmsg;
+ goto failed;
+ }
+
+
+ if (track->output()->ensure_io (ChanCount(DataType::AUDIO, 1), false, this)) {
error << "cannot configure 1 in/1 out configuration for new midi track" << endmsg;
goto failed;
}
@@ -1711,7 +1708,14 @@ Session::new_audio_track (int input_channels, int output_channels, TrackMode mod
try {
track = boost::shared_ptr<AudioTrack>((new AudioTrack (*this, track_name, Route::Flag (0), mode)));
- if (track->ensure_io (ChanCount(DataType::AUDIO, input_channels), ChanCount(DataType::AUDIO, output_channels), false, this)) {
+ if (track->input()->ensure_io (ChanCount(DataType::AUDIO, input_channels), false, this)) {
+ error << string_compose (_("cannot configure %1 in/%2 out configuration for new audio track"),
+ input_channels, output_channels)
+ << endmsg;
+ goto failed;
+ }
+
+ if (track->output()->ensure_io (ChanCount(DataType::AUDIO, output_channels), false, this)) {
error << string_compose (_("cannot configure %1 in/%2 out configuration for new audio track"),
input_channels, output_channels)
<< endmsg;
@@ -1729,7 +1733,7 @@ Session::new_audio_track (int input_channels, int output_channels, TrackMode mod
port = physinputs[(channels_used+x)%nphysical_in];
}
- if (port.length() && track->connect_input (track->input (x), port, this)) {
+ if (port.length() && track->input()->connect (track->input()->nth(x), port, this)) {
break;
}
}
@@ -1745,11 +1749,11 @@ Session::new_audio_track (int input_channels, int output_channels, TrackMode mod
port = physoutputs[(channels_used+x)%nphysical_out];
} else if (Config->get_output_auto_connect() & AutoConnectMaster) {
if (_master_out && _master_out->n_inputs().n_audio() > 0) {
- port = _master_out->input (x % _master_out->n_inputs().n_audio())->name();
+ port = _master_out->input()->nth (x % _master_out->input()->n_ports().n_audio())->name();
}
}
- if (port.length() && track->connect_output (track->output (x), port, this)) {
+ if (port.length() && track->output()->connect (track->output()->nth(x), port, this)) {
break;
}
}
@@ -1889,7 +1893,15 @@ Session::new_audio_route (int input_channels, int output_channels, uint32_t how_
try {
shared_ptr<Route> bus (new Route (*this, bus_name, Route::Flag(0), DataType::AUDIO));
- if (bus->ensure_io (ChanCount(DataType::AUDIO, input_channels), ChanCount(DataType::AUDIO, output_channels), false, this)) {
+ if (bus->output()->ensure_io (ChanCount(DataType::AUDIO, input_channels), false, this)) {
+ error << string_compose (_("cannot configure %1 in/%2 out configuration for new audio track"),
+ input_channels, output_channels)
+ << endmsg;
+ goto failure;
+ }
+
+
+ if (bus->output()->ensure_io (ChanCount(DataType::AUDIO, output_channels), false, this)) {
error << string_compose (_("cannot configure %1 in/%2 out configuration for new audio track"),
input_channels, output_channels)
<< endmsg;
@@ -1920,11 +1932,11 @@ Session::new_audio_route (int input_channels, int output_channels, uint32_t how_
port = physoutputs[((n+x)%n_physical_outputs)];
} else if (Config->get_output_auto_connect() & AutoConnectMaster) {
if (_master_out) {
- port = _master_out->input (x%_master_out->n_inputs().n_audio())->name();
+ port = _master_out->input()->nth (x%_master_out->input()->n_ports().n_audio())->name();
}
}
- if (port.length() && bus->connect_output (bus->output (x), port, this)) {
+ if (port.length() && bus->output()->connect (bus->output()->nth(x), port, this)) {
break;
}
}
@@ -2023,8 +2035,8 @@ Session::new_route_from_template (uint32_t how_many, const std::string& template
picks up the configuration of the route. During session
loading this normally happens in a different way.
*/
- route->input_changed (IOChange (ConfigurationChanged|ConnectionsChanged), this);
- route->output_changed (IOChange (ConfigurationChanged|ConnectionsChanged), this);
+ route->input()->changed (IOChange (ConfigurationChanged|ConnectionsChanged), this);
+ route->output()->changed (IOChange (ConfigurationChanged|ConnectionsChanged), this);
}
route->set_remote_control_id (control_id);
@@ -2070,7 +2082,7 @@ Session::add_routes (RouteList& new_routes, bool save)
(*x)->solo_changed.connect (sigc::bind (mem_fun (*this, &Session::route_solo_changed), wpr));
(*x)->mute_changed.connect (mem_fun (*this, &Session::route_mute_changed));
- (*x)->output_changed.connect (mem_fun (*this, &Session::set_worst_io_latencies_x));
+ (*x)->output()->changed.connect (mem_fun (*this, &Session::set_worst_io_latencies_x));
(*x)->processors_changed.connect (bind (mem_fun (*this, &Session::update_latency_compensation), false, false));
if ((*x)->is_master()) {
@@ -2085,7 +2097,7 @@ Session::add_routes (RouteList& new_routes, bool save)
if (_control_out && IO::connecting_legal) {
for (RouteList::iterator x = new_routes.begin(); x != new_routes.end(); ++x) {
- (*x)->listen_via (_control_out, "control");
+ (*x)->listen_via (_control_out->input(), "control");
}
}
@@ -2145,7 +2157,7 @@ Session::remove_route (shared_ptr<Route> route)
/* cancel control outs for all routes */
for (RouteList::iterator r = rs->begin(); r != rs->end(); ++r) {
- (*r)->drop_listen (_control_out);
+ (*r)->drop_listen (_control_out->input());
}
_control_out = shared_ptr<Route> ();
@@ -2176,8 +2188,8 @@ Session::remove_route (shared_ptr<Route> route)
// We need to disconnect the routes inputs and outputs
- route->disconnect_inputs (0);
- route->disconnect_outputs (0);
+ route->input()->disconnect (0);
+ route->output()->disconnect (0);
update_latency_compensation (false, false);
set_dirty();
@@ -2215,7 +2227,6 @@ Session::route_solo_changed (void* src, boost::weak_ptr<Route> wpr)
return;
}
- bool is_track;
boost::shared_ptr<Route> route = wpr.lock ();
if (!route) {
@@ -2224,86 +2235,39 @@ Session::route_solo_changed (void* src, boost::weak_ptr<Route> wpr)
return;
}
- is_track = (boost::dynamic_pointer_cast<AudioTrack>(route) != 0);
-
shared_ptr<RouteList> r = routes.reader ();
+ int32_t delta;
- for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
-
- /* soloing a track mutes all other tracks, soloing a bus mutes all other busses */
-
- if (is_track) {
-
- /* don't mess with busses */
-
- if (boost::dynamic_pointer_cast<Track>(*i) == 0) {
- continue;
- }
-
- } else {
-
- /* don't mess with tracks */
-
- if (boost::dynamic_pointer_cast<Track>(*i) != 0) {
- continue;
- }
- }
-
- if ((*i) != route &&
- ((*i)->mix_group () == 0 ||
- (*i)->mix_group () != route->mix_group () ||
- !route->mix_group ()->is_active())) {
-
- if ((*i)->soloed()) {
-
- /* if its already soloed, and solo latching is enabled,
- then leave it as it is.
- */
-
- if (Config->get_solo_latched()) {
- continue;
- }
- }
+ if (route->soloed()) {
+ delta = 1;
+ } else {
+ delta = -1;
+ }
+ for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
+ if ((*i)->feeds (route->input())) {
/* do it */
-
+
solo_update_disabled = true;
- (*i)->set_solo (false, src);
+ (*i)->main_outs()->mod_solo_level (delta);
solo_update_disabled = false;
}
}
+ /* now figure out if anything is soloed */
+
bool something_soloed = false;
- bool same_thing_soloed = false;
- bool signal = false;
- for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
+ for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
if ((*i)->soloed()) {
something_soloed = true;
- if (boost::dynamic_pointer_cast<Track>(*i)) {
- if (is_track) {
- same_thing_soloed = true;
- break;
- }
- } else {
- if (!is_track) {
- same_thing_soloed = true;
- break;
- }
- }
break;
}
}
- if (something_soloed != currently_soloing) {
- signal = true;
- currently_soloing = something_soloed;
- }
-
- modify_solo_mute (is_track, same_thing_soloed);
-
- if (signal) {
- SoloActive (currently_soloing); /* EMIT SIGNAL */
+ if (something_soloed != _non_soloed_outs_muted) {
+ _non_soloed_outs_muted = something_soloed;
+ SoloActive (_non_soloed_outs_muted); /* EMIT SIGNAL */
}
SoloChanged (); /* EMIT SIGNAL */
@@ -2343,70 +2307,18 @@ Session::update_route_solo_state ()
/* nothing is soloed */
- for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
- (*i)->set_solo_mute (false);
- }
-
if (signal) {
SoloActive (false);
}
return;
}
-
- modify_solo_mute (is_track, mute);
-
+
if (signal) {
SoloActive (currently_soloing);
}
}
-void
-Session::modify_solo_mute (bool is_track, bool mute)
-{
- shared_ptr<RouteList> r = routes.reader ();
-
- for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
-
- if (is_track) {
-
- /* only alter track solo mute */
-
- if (boost::dynamic_pointer_cast<Track>(*i)) {
- if ((*i)->soloed()) {
- (*i)->set_solo_mute (!mute);
- } else {
- (*i)->set_solo_mute (mute);
- }
- }
-
- } else {
-
- /* only alter bus solo mute */
-
- if (!boost::dynamic_pointer_cast<Track>(*i)) {
-
- if ((*i)->soloed()) {
-
- (*i)->set_solo_mute (false);
-
- } else {
-
- /* don't mute master or control outs
- in response to another bus solo
- */
-
- if ((*i) != _master_out &&
- (*i) != _control_out) {
- (*i)->set_solo_mute (mute);
- }
- }
- }
-
- }
- }
-}
-
void
Session::catch_up_on_solo ()
@@ -2432,7 +2344,7 @@ Session::catch_up_on_solo_mute_override ()
shared_ptr<RouteList> r = routes.reader ();
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
- (*i)->catch_up_on_solo_mute_override ();
+ // (*i)->catch_up_on_solo_mute_override ();
}
}
diff --git a/libs/ardour/session_click.cc b/libs/ardour/session_click.cc
index cbe085b82d..dfbd599c4c 100644
--- a/libs/ardour/session_click.cc
+++ b/libs/ardour/session_click.cc
@@ -127,7 +127,7 @@ Session::click (nframes_t start, nframes_t nframes)
i = next;
}
- _click_io->deliver_output (bufs, start, end, nframes);
+ _click_io->copy_to_outputs (bufs, DataType::AUDIO, nframes, 0);
}
void
diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc
index 4d07a6c6e2..0391e1f962 100644
--- a/libs/ardour/session_state.cc
+++ b/libs/ardour/session_state.cc
@@ -151,7 +151,7 @@ Session::first_stage_init (string fullpath, string snapshot_name)
_tempo_map->StateChanged.connect (mem_fun (*this, &Session::tempo_map_changed));
-
+ _non_soloed_outs_muted = false;
g_atomic_int_set (&processing_prohibited, 0);
insert_cnt = 0;
_transport_speed = 0;
@@ -272,8 +272,7 @@ Session::first_stage_init (string fullpath, string snapshot_name)
/* stop IO objects from doing stuff until we're ready for them */
- IO::disable_panners ();
- IO::disable_ports ();
+ Delivery::disable_panners ();
IO::disable_connecting ();
}
@@ -1155,7 +1154,6 @@ Session::set_state (const XMLNode& node)
}
- IO::disable_ports ();
IO::disable_connecting ();
/* Object loading order:
@@ -3215,7 +3213,7 @@ Session::config_changed (std::string p, bool ours)
// deliver_midi (_mmc_port, buf, 2);
}
} else if (p == "solo-mute-override") {
- catch_up_on_solo_mute_override ();
+ // catch_up_on_solo_mute_override ();
}
set_dirty ();
diff --git a/libs/ardour/session_transport.cc b/libs/ardour/session_transport.cc
index b3fa34419a..31dc52a11b 100644
--- a/libs/ardour/session_transport.cc
+++ b/libs/ardour/session_transport.cc
@@ -1335,11 +1335,12 @@ Session::update_latency_compensation (bool with_stop, bool abort)
(!(post_transport_work & PostTransportLocate) || pending_locate_flush));
}
- nframes_t old_latency = (*i)->signal_latency ();
+ nframes_t old_latency = (*i)->output()->signal_latency ();
nframes_t track_latency = (*i)->update_total_latency ();
if (old_latency != track_latency) {
- (*i)->update_port_total_latencies ();
+ (*i)->input()->update_port_total_latencies ();
+ (*i)->output()->update_port_total_latencies ();
update_jack = true;
}
diff --git a/libs/ardour/track.cc b/libs/ardour/track.cc
index fa3193cba3..96d44de555 100644
--- a/libs/ardour/track.cc
+++ b/libs/ardour/track.cc
@@ -26,7 +26,7 @@
#include "ardour/audiosource.h"
#include "ardour/diskstream.h"
#include "ardour/io_processor.h"
-#include "ardour/panner.h"
+#include "ardour/meter.h"
#include "ardour/port.h"
#include "ardour/processor.h"
#include "ardour/route_group_specialized.h"
@@ -84,7 +84,7 @@ Track::get_template ()
void
Track::toggle_monitor_input ()
{
- for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
+ for (PortSet::iterator i = _input->ports().begin(); i != _input->ports().end(); ++i) {
i->ensure_monitor_input(!i->monitoring_input());
}
}
@@ -92,32 +92,28 @@ Track::toggle_monitor_input ()
ARDOUR::nframes_t
Track::update_total_latency ()
{
- nframes_t old = _own_latency;
-
- if (_user_latency) {
- _own_latency = _user_latency;
- } else {
- _own_latency = 0;
-
- for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
- if ((*i)->active ()) {
- _own_latency += (*i)->signal_latency ();
- }
+ nframes_t old = _output->effective_latency();
+ nframes_t own_latency = _output->user_latency();
+
+ for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
+ if ((*i)->active ()) {
+ own_latency += (*i)->signal_latency ();
}
}
#undef DEBUG_LATENCY
#ifdef DEBUG_LATENCY
- cerr << _name << ": internal redirect (final) latency = " << _own_latency << endl;
+ cerr << _name << ": internal redirect (final) latency = " << own_latency << endl;
#endif
- set_port_latency (_own_latency);
-
- if (old != _own_latency) {
+ _output->set_port_latency (own_latency);
+
+ if (old != own_latency) {
+ _output->set_latency_delay (own_latency);
signal_latency_changed (); /* EMIT SIGNAL */
}
- return _own_latency;
+ return _output->effective_latency();
}
Track::FreezeRecord::~FreezeRecord ()
@@ -155,14 +151,14 @@ Track::RecEnableControllable::get_value (void) const
bool
Track::record_enabled () const
{
- return _diskstream->record_enabled ();
+ return _diskstream && _diskstream->record_enabled ();
}
bool
Track::can_record()
{
bool will_record = true;
- for (PortSet::iterator i = _inputs.begin(); i != _inputs.end() && will_record; ++i) {
+ for (PortSet::iterator i = _input->ports().begin(); i != _input->ports().end() && will_record; ++i) {
if (!i->connected())
will_record = false;
}
@@ -307,7 +303,7 @@ Track::no_roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame,
passthru_silence (start_frame, end_frame, nframes, 0);
} else {
if (_meter_point == MeterInput) {
- just_meter_input (start_frame, end_frame, nframes);
+ _input->process_input (_meter, start_frame, end_frame, nframes);
}
passthru_silence (start_frame, end_frame, nframes, 0);
}
diff --git a/libs/ardour/wscript b/libs/ardour/wscript
index 7079a64a08..98bc7106f3 100644
--- a/libs/ardour/wscript
+++ b/libs/ardour/wscript
@@ -135,7 +135,7 @@ def build(bld):
gdither.cc
globals.cc
import.cc
- io.cc
+ io.cc
io_processor.cc
jack_slave.cc
ladspa_plugin.cc
@@ -157,6 +157,7 @@ def build(bld):
midi_track.cc
mix.cc
mtc_slave.cc
+ mute_master.cc
named_selection.cc
onset_detector.cc
panner.cc
@@ -178,7 +179,7 @@ def build(bld):
resampled_source.cc
return.cc
reverse.cc
- route.cc
+ route.cc
route_group.cc
send.cc
session.cc
diff --git a/libs/gtkmm2ext/gtkmm2ext/barcontroller.h b/libs/gtkmm2ext/gtkmm2ext/barcontroller.h
index 0b074a0f90..5970fe2d5f 100644
--- a/libs/gtkmm2ext/gtkmm2ext/barcontroller.h
+++ b/libs/gtkmm2ext/gtkmm2ext/barcontroller.h
@@ -23,9 +23,6 @@
#include <gtkmm/drawingarea.h>
#include <gtkmm2ext/binding_proxy.h>
-namespace ARDOUR {
- class Controllable;
-}
namespace Gtkmm2ext {
diff --git a/libs/midi++2/midi.cc b/libs/midi++2/midi.cc
index eacd85bf28..6b5bca8a98 100644
--- a/libs/midi++2/midi.cc
+++ b/libs/midi++2/midi.cc
@@ -158,7 +158,7 @@ MIDI::byte
MIDI::decode_controller_name (const char *name)
{
- char *lparen;
+ const char *lparen;
size_t len;
if ((lparen = strrchr (name, '(')) != 0) {
diff --git a/libs/surfaces/control_protocol/control_protocol.cc b/libs/surfaces/control_protocol/control_protocol.cc
index f95aadb2b8..2d59912dc8 100644
--- a/libs/surfaces/control_protocol/control_protocol.cc
+++ b/libs/surfaces/control_protocol/control_protocol.cc
@@ -18,11 +18,12 @@
*/
-#include <ardour/session.h>
-#include <ardour/route.h>
-#include <ardour/audio_track.h>
-#include <ardour/meter.h>
-#include <control_protocol/control_protocol.h>
+#include "ardour/session.h"
+#include "ardour/route.h"
+#include "ardour/audio_track.h"
+#include "ardour/meter.h"
+#include "ardour/amp.h"
+#include "control_protocol/control_protocol.h"
using namespace ARDOUR;
using namespace std;
@@ -212,7 +213,7 @@ ControlProtocol::route_get_gain (uint32_t table_index)
return 0.0f;
}
- return r->gain ();
+ return r->amp()->gain ();
}
void
@@ -242,7 +243,7 @@ ControlProtocol::route_get_effective_gain (uint32_t table_index)
return 0.0f;
}
- return r->effective_gain ();
+ return r->amp()->gain_control()->get_value();
}
diff --git a/wscript b/wscript
index 471ed1f0bf..051d97d07c 100644
--- a/wscript
+++ b/wscript
@@ -95,7 +95,7 @@ def set_options(opt):
help='Compile with support for LV2 (if slv2 is available)')
opt.add_option('--nls', action='store_true', default=True, dest='nls',
help='Enable i18n (native language support)')
- opt.add_option('--surfaces', action='store_true', default=True, dest='surfaces',
+ opt.add_option('--surfaces', action='store_true', default=False, dest='surfaces',
help='Build support for control surfaces')
opt.add_option('--syslibs', action='store_true', default=True, dest='syslibs',
help='Use existing system versions of various libraries instead of internal ones')