summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gtk2_ardour/audio_time_axis.cc14
-rw-r--r--gtk2_ardour/keyboard.cc2
-rw-r--r--gtk2_ardour/main.cc2
-rw-r--r--gtk2_ardour/mixer_strip.cc84
-rw-r--r--gtk2_ardour/panner2d.cc35
-rw-r--r--gtk2_ardour/panner2d.h8
-rw-r--r--gtk2_ardour/panner_ui.cc107
-rw-r--r--gtk2_ardour/po/de_DE.po9
-rw-r--r--gtk2_ardour/po/el_GR.po3
-rw-r--r--gtk2_ardour/po/es_ES.po3
-rw-r--r--gtk2_ardour/po/fr_FR.po9
-rw-r--r--gtk2_ardour/po/it_IT.po3
-rw-r--r--gtk2_ardour/po/pl_PL.po7
-rw-r--r--gtk2_ardour/po/pt_BR.po3
-rw-r--r--gtk2_ardour/po/pt_PT.po3
-rw-r--r--gtk2_ardour/po/ru_RU.po3
-rw-r--r--gtk2_ardour/po/sv_SE.po3
-rw-r--r--gtk2_ardour/processor_box.cc303
-rw-r--r--gtk2_ardour/processor_box.h4
-rw-r--r--gtk2_ardour/time_axis_view.cc2
-rw-r--r--gtk2_ardour/ui_config.cc6
-rw-r--r--libs/ardour/amp.cc125
-rw-r--r--libs/ardour/ardour/amp.h49
-rw-r--r--libs/ardour/ardour/audio_track.h6
-rw-r--r--libs/ardour/ardour/buffer_set.h8
-rw-r--r--libs/ardour/ardour/chan_count.h12
-rw-r--r--libs/ardour/ardour/chan_mapping.h46
-rw-r--r--libs/ardour/ardour/click.h12
-rw-r--r--libs/ardour/ardour/control_outputs.h55
-rw-r--r--libs/ardour/ardour/io.h49
-rw-r--r--libs/ardour/ardour/io_processor.h5
-rw-r--r--libs/ardour/ardour/meter.h10
-rw-r--r--libs/ardour/ardour/midi_track.h11
-rw-r--r--libs/ardour/ardour/panner.h2
-rw-r--r--libs/ardour/ardour/plugin_insert.h2
-rw-r--r--libs/ardour/ardour/port_insert.h2
-rw-r--r--libs/ardour/ardour/processor.h16
-rw-r--r--libs/ardour/ardour/route.h64
-rw-r--r--libs/ardour/ardour/send.h2
-rw-r--r--libs/ardour/ardour/session.h1
-rw-r--r--libs/ardour/ardour/track.h12
-rw-r--r--libs/ardour/audio_diskstream.cc11
-rw-r--r--libs/ardour/audio_track.cc193
-rw-r--r--libs/ardour/audioengine.cc20
-rw-r--r--libs/ardour/automatable.cc12
-rw-r--r--libs/ardour/buffer_set.cc9
-rw-r--r--libs/ardour/chan_count.cc32
-rw-r--r--libs/ardour/configuration.cc4
-rw-r--r--libs/ardour/control_outputs.cc79
-rw-r--r--libs/ardour/diskstream.cc20
-rw-r--r--libs/ardour/globals.cc2
-rw-r--r--libs/ardour/import.cc2
-rw-r--r--libs/ardour/io.cc261
-rw-r--r--libs/ardour/io_processor.cc19
-rw-r--r--libs/ardour/lv2_event_buffer.cc8
-rw-r--r--libs/ardour/lv2_plugin.cc43
-rw-r--r--libs/ardour/meter.cc71
-rw-r--r--libs/ardour/midi_diskstream.cc12
-rw-r--r--libs/ardour/midi_patch_manager.cc25
-rw-r--r--libs/ardour/midi_source.cc2
-rw-r--r--libs/ardour/midi_track.cc173
-rw-r--r--libs/ardour/panner.cc23
-rw-r--r--libs/ardour/plugin_insert.cc92
-rw-r--r--libs/ardour/plugin_manager.cc2
-rw-r--r--libs/ardour/po/el_GR.po4
-rw-r--r--libs/ardour/po/it_IT.po4
-rw-r--r--libs/ardour/po/pl_PL.po4
-rw-r--r--libs/ardour/po/ru_RU.po4
-rw-r--r--libs/ardour/po/sv_SE.po4
-rw-r--r--libs/ardour/port.cc1
-rw-r--r--libs/ardour/port_insert.cc33
-rw-r--r--libs/ardour/processor.cc65
-rw-r--r--libs/ardour/route.cc1428
-rw-r--r--libs/ardour/send.cc10
-rw-r--r--libs/ardour/session.cc75
-rw-r--r--libs/ardour/session_state.cc8
-rw-r--r--libs/ardour/smf_source.cc8
-rw-r--r--libs/ardour/template_utils.cc2
-rw-r--r--libs/ardour/track.cc132
-rw-r--r--libs/ardour/wscript2
-rw-r--r--libs/evoral/evoral/Control.hpp10
-rw-r--r--libs/evoral/evoral/ControlSet.hpp4
-rw-r--r--libs/evoral/evoral/Sequence.hpp2
-rw-r--r--libs/evoral/src/Control.cpp13
-rw-r--r--libs/evoral/src/ControlSet.cpp2
85 files changed, 1840 insertions, 2192 deletions
diff --git a/gtk2_ardour/audio_time_axis.cc b/gtk2_ardour/audio_time_axis.cc
index b774182a88..6f8acc9651 100644
--- a/gtk2_ardour/audio_time_axis.cc
+++ b/gtk2_ardour/audio_time_axis.cc
@@ -106,7 +106,11 @@ AudioTimeAxisView::AudioTimeAxisView (PublicEditor& ed, Session& sess, boost::sh
create_automation_child (GainAutomation, false);
}
- _route->panner().Changed.connect (bind (mem_fun(*this, &AudioTimeAxisView::ensure_pan_views), false));
+ if (_route->panner()) {
+ _route->panner()->Changed.connect (bind (
+ mem_fun(*this, &AudioTimeAxisView::ensure_pan_views),
+ false));
+ }
/* map current state of the route */
@@ -370,13 +374,17 @@ AudioTimeAxisView::create_automation_child (const Evoral::Parameter& param, bool
void
AudioTimeAxisView::ensure_pan_views (bool show)
{
- const set<Evoral::Parameter>& params = _route->panner().what_can_be_automated();
+ if (!_route->panner()) {
+ return;
+ }
+
+ const set<Evoral::Parameter>& params = _route->panner()->what_can_be_automated();
set<Evoral::Parameter>::iterator p;
for (p = params.begin(); p != params.end(); ++p) {
boost::shared_ptr<ARDOUR::AutomationControl> pan_control
= boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
- _route->panner().data().control(*p));
+ _route->panner()->data().control(*p));
if (pan_control->parameter().type() == NullAutomation) {
error << "Pan control has NULL automation type!" << endmsg;
diff --git a/gtk2_ardour/keyboard.cc b/gtk2_ardour/keyboard.cc
index ad8b02ab53..2e29c9c1c5 100644
--- a/gtk2_ardour/keyboard.cc
+++ b/gtk2_ardour/keyboard.cc
@@ -617,7 +617,7 @@ bool
Keyboard::load_keybindings (string path)
{
try {
- cerr << "loading bindings from " << path << endl;
+ cerr << "Loading bindings from " << path << endl;
Gtk::AccelMap::load (path);
diff --git a/gtk2_ardour/main.cc b/gtk2_ardour/main.cc
index 32454d69d5..0a95b9a94b 100644
--- a/gtk2_ardour/main.cc
+++ b/gtk2_ardour/main.cc
@@ -344,7 +344,7 @@ int main (int argc, char *argv[])
cout << _("Ardour/GTK ")
<< VERSIONSTRING
- << _("\n (built using ")
+ << _(" (built using ")
<< svn_revision
#ifdef __GNUC__
<< _(" and GCC version ") << __VERSION__
diff --git a/gtk2_ardour/mixer_strip.cc b/gtk2_ardour/mixer_strip.cc
index fc358b8f7b..8a00eb88a2 100644
--- a/gtk2_ardour/mixer_strip.cc
+++ b/gtk2_ardour/mixer_strip.cc
@@ -413,20 +413,33 @@ MixerStrip::set_route (boost::shared_ptr<Route> rt)
_("Click to Add/Edit Comments"):
_route->comment());
- connections.push_back (_route->meter_change.connect (mem_fun(*this, &MixerStrip::meter_changed)));
- connections.push_back (_route->input_changed.connect (mem_fun(*this, &MixerStrip::input_changed)));
- 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)));
- connections.push_back (_route->panner().Changed.connect (mem_fun(*this, &MixerStrip::connect_to_pan)));
+ connections.push_back (_route->meter_change.connect (
+ mem_fun(*this, &MixerStrip::meter_changed)));
+ connections.push_back (_route->input_changed.connect (
+ mem_fun(*this, &MixerStrip::input_changed)));
+ 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)));
+
+ if (_route->panner()) {
+ connections.push_back (_route->panner()->Changed.connect (
+ mem_fun(*this, &MixerStrip::connect_to_pan)));
+ }
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 (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 (mem_fun(*this, &RouteUI::name_changed)));
- connections.push_back (_route->comment_changed.connect (mem_fun(*this, &MixerStrip::comment_changed)));
- connections.push_back (_route->gui_changed.connect (mem_fun(*this, &MixerStrip::route_gui_changed)));
+ connections.push_back (_route->NameChanged.connect (
+ mem_fun(*this, &RouteUI::name_changed)));
+ connections.push_back (_route->comment_changed.connect (
+ mem_fun(*this, &MixerStrip::comment_changed)));
+ connections.push_back (_route->gui_changed.connect (
+ mem_fun(*this, &MixerStrip::route_gui_changed)));
set_stuff_from_route ();
@@ -553,17 +566,25 @@ MixerStrip::set_width (Width w, void* owner)
((Gtk::Label*)solo_button->get_child())->set_text (_("Solo"));
if (_route->comment() == "") {
- comment_button.unset_bg (STATE_NORMAL);
- ((Gtk::Label*)comment_button.get_child())->set_text (_("Comments"));
+ comment_button.unset_bg (STATE_NORMAL);
+ ((Gtk::Label*)comment_button.get_child())->set_text (_("Comments"));
} else {
- comment_button.modify_bg (STATE_NORMAL, color());
- ((Gtk::Label*)comment_button.get_child())->set_text (_("*Comments*"));
+ comment_button.modify_bg (STATE_NORMAL, color());
+ ((Gtk::Label*)comment_button.get_child())->set_text (_("*Comments*"));
+ }
+
+ ((Gtk::Label*)gpm.gain_automation_style_button.get_child())->set_text (
+ gpm.astyle_string(gain_automation->automation_style()));
+ ((Gtk::Label*)gpm.gain_automation_state_button.get_child())->set_text (
+ gpm.astate_string(gain_automation->automation_state()));
+
+ if (_route->panner()) {
+ ((Gtk::Label*)panners.pan_automation_style_button.get_child())->set_text (
+ panners.astyle_string(_route->panner()->automation_style()));
+ ((Gtk::Label*)panners.pan_automation_state_button.get_child())->set_text (
+ panners.astate_string(_route->panner()->automation_state()));
}
- ((Gtk::Label*)gpm.gain_automation_style_button.get_child())->set_text (gpm.astyle_string(gain_automation->automation_style()));
- ((Gtk::Label*)gpm.gain_automation_state_button.get_child())->set_text (gpm.astate_string(gain_automation->automation_state()));
- ((Gtk::Label*)panners.pan_automation_style_button.get_child())->set_text (panners.astyle_string(_route->panner().automation_style()));
- ((Gtk::Label*)panners.pan_automation_state_button.get_child())->set_text (panners.astate_string(_route->panner().automation_state()));
Gtkmm2ext::set_size_request_to_display_given_text (name_button, "long", 2, 2);
set_size_request (-1, -1);
break;
@@ -583,10 +604,18 @@ MixerStrip::set_width (Width w, void* owner)
((Gtk::Label*)comment_button.get_child())->set_text (_("*Cmt*"));
}
- ((Gtk::Label*)gpm.gain_automation_style_button.get_child())->set_text (gpm.short_astyle_string(gain_automation->automation_style()));
- ((Gtk::Label*)gpm.gain_automation_state_button.get_child())->set_text (gpm.short_astate_string(gain_automation->automation_state()));
- ((Gtk::Label*)panners.pan_automation_style_button.get_child())->set_text (panners.short_astyle_string(_route->panner().automation_style()));
- ((Gtk::Label*)panners.pan_automation_state_button.get_child())->set_text (panners.short_astate_string(_route->panner().automation_state()));
+ ((Gtk::Label*)gpm.gain_automation_style_button.get_child())->set_text (
+ gpm.short_astyle_string(gain_automation->automation_style()));
+ ((Gtk::Label*)gpm.gain_automation_state_button.get_child())->set_text (
+ gpm.short_astate_string(gain_automation->automation_state()));
+
+ if (_route->panner()) {
+ ((Gtk::Label*)panners.pan_automation_style_button.get_child())->set_text (
+ panners.short_astyle_string(_route->panner()->automation_style()));
+ ((Gtk::Label*)panners.pan_automation_state_button.get_child())->set_text (
+ panners.short_astate_string(_route->panner()->automation_state()));
+ }
+
Gtkmm2ext::set_size_request_to_display_given_text (name_button, "longest label", 2, 2);
set_size_request (max (50, gpm.get_gm_width()), -1);
break;
@@ -856,9 +885,13 @@ MixerStrip::connect_to_pan ()
panstate_connection.disconnect ();
panstyle_connection.disconnect ();
- boost::shared_ptr<ARDOUR::AutomationControl> pan_control
- = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
- _route->panner().data().control(Evoral::Parameter( PanAutomation ) ));
+ if (!_route->panner()) {
+ return;
+ }
+
+ boost::shared_ptr<ARDOUR::AutomationControl> pan_control
+ = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
+ _route->panner()->data().control(Evoral::Parameter(PanAutomation)));
if (pan_control) {
panstate_connection = pan_control->alist()->automation_state_changed.connect (mem_fun(panners, &PannerUI::pan_automation_state_changed));
@@ -1407,7 +1440,6 @@ MixerStrip::engine_running ()
void
MixerStrip::meter_changed (void *src)
{
-
ENSURE_GUI_THREAD (bind (mem_fun(*this, &MixerStrip::meter_changed), src));
switch (_route->meter_point()) {
diff --git a/gtk2_ardour/panner2d.cc b/gtk2_ardour/panner2d.cc
index 0216e76c27..b6c601cdef 100644
--- a/gtk2_ardour/panner2d.cc
+++ b/gtk2_ardour/panner2d.cc
@@ -65,15 +65,15 @@ Panner2d::Target::set_text (const char* txt)
text = strdup (txt);
}
-Panner2d::Panner2d (Panner& p, int32_t h)
+Panner2d::Panner2d (boost::shared_ptr<Panner> p, int32_t h)
: panner (p), width (0), height (h)
{
allow_x = false;
allow_y = false;
allow_target = false;
- panner.StateChanged.connect (mem_fun(*this, &Panner2d::handle_state_change));
- panner.Changed.connect (mem_fun(*this, &Panner2d::handle_position_change));
+ panner->StateChanged.connect (mem_fun(*this, &Panner2d::handle_state_change));
+ panner->Changed.connect (mem_fun(*this, &Panner2d::handle_position_change));
drag_target = 0;
set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::POINTER_MOTION_MASK);
@@ -135,7 +135,7 @@ Panner2d::reset (uint32_t n_inputs)
if (existing_pucks < i) {
float x, y;
- panner.streampanner (i).get_position (x, y);
+ panner->streampanner (i).get_position (x, y);
pucks[i]->x.set_value (x);
pucks[i]->y.set_value (y);
}
@@ -147,11 +147,11 @@ Panner2d::reset (uint32_t n_inputs)
/* add all outputs */
- while (targets.size() < panner.nouts()) {
+ while (targets.size() < panner->nouts()) {
add_target (0.0, 0.0);
}
- while (targets.size() > panner.nouts()) {
+ while (targets.size() > panner->nouts()) {
targets.erase (targets.begin());
}
@@ -159,13 +159,13 @@ Panner2d::reset (uint32_t n_inputs)
(*x).second->visible = false;
}
- for (uint32_t n = 0; n < panner.nouts(); ++n) {
+ for (uint32_t n = 0; n < panner->nouts(); ++n) {
char buf[16];
snprintf (buf, sizeof (buf), "%d", n+1);
targets[n]->set_text (buf);
- targets[n]->x.set_value (panner.output(n).x);
- targets[n]->y.set_value (panner.output(n).y);
+ targets[n]->x.set_value (panner->output(n).x);
+ targets[n]->y.set_value (panner->output(n).y);
targets[n]->visible = true;
}
@@ -275,14 +275,14 @@ Panner2d::handle_position_change ()
for (n = 0; n < pucks.size(); ++n) {
float x, y;
- panner.streampanner(n).get_position (x, y);
+ panner->streampanner(n).get_position (x, y);
pucks[n]->x.set_value (x);
pucks[n]->y.set_value (y);
}
for (n = 0; n < targets.size(); ++n) {
- targets[n]->x.set_value (panner.output(n).x);
- targets[n]->y.set_value (panner.output(n).y);
+ targets[n]->x.set_value (panner->output(n).x);
+ targets[n]->y.set_value (panner->output(n).y);
}
queue_draw ();
@@ -454,7 +454,7 @@ Panner2d::on_expose_event (GdkEventExpose *event)
cairo_set_line_width (cr, 1.0);
cairo_rectangle (cr, event->area.x, event->area.y, event->area.width, event->area.height);
- if (!panner.bypassed()) {
+ if (!panner->bypassed()) {
cairo_set_source_rgba (cr, 0.1, 0.1, 0.1, 1.0);
} else {
cairo_set_source_rgba (cr, 0.1, 0.1, 0.1, 0.2);
@@ -478,7 +478,7 @@ Panner2d::on_expose_event (GdkEventExpose *event)
cairo_arc (cr, height/2, height/2, height/2, 0, 2.0 * M_PI);
cairo_stroke (cr);
- if (!panner.bypassed()) {
+ if (!panner->bypassed()) {
float arc_radius;
cairo_select_font_face (cr, "sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
@@ -715,7 +715,8 @@ Panner2d::handle_motion (gint evx, gint evy, GdkModifierType state)
if (drag_is_puck) {
- panner.streampanner(drag_index).set_position (drag_target->x.get_value(), drag_target->y.get_value(), false);
+ panner->streampanner(drag_index).set_position (
+ drag_target->x.get_value(), drag_target->y.get_value(), false);
} else {
@@ -745,7 +746,7 @@ Panner2d::handle_motion (gint evx, gint evy, GdkModifierType state)
void
Panner2d::toggle_bypass ()
{
- panner.set_bypassed (!panner.bypassed());
+ panner->set_bypassed (!panner->bypassed());
}
void
@@ -766,7 +767,7 @@ Panner2d::allow_y_motion (bool yn)
allow_y = yn;
}
-Panner2dWindow::Panner2dWindow (Panner&p, int32_t h, uint32_t inputs)
+Panner2dWindow::Panner2dWindow (boost::shared_ptr<Panner> p, int32_t h, uint32_t inputs)
: widget (p, h)
, reset_button (_("Reset"))
, bypass_button (_("Bypass"))
diff --git a/gtk2_ardour/panner2d.h b/gtk2_ardour/panner2d.h
index 2bf57f2627..1abac7fe5a 100644
--- a/gtk2_ardour/panner2d.h
+++ b/gtk2_ardour/panner2d.h
@@ -54,7 +54,7 @@ class Panner2dWindow;
class Panner2d : public Gtk::DrawingArea
{
public:
- Panner2d (ARDOUR::Panner&, int32_t height);
+ Panner2d (boost::shared_ptr<ARDOUR::Panner>, int32_t height);
~Panner2d ();
void allow_x_motion(bool);
@@ -76,7 +76,7 @@ class Panner2d : public Gtk::DrawingArea
Gtk::Adjustment& azimuth (uint32_t which);
- ARDOUR::Panner& get_panner() const { return panner; }
+ boost::shared_ptr<ARDOUR::Panner> get_panner() const { return panner; }
sigc::signal<void,int> PuckMoved;
sigc::signal<void,int> TargetMoved;
@@ -102,7 +102,7 @@ class Panner2d : public Gtk::DrawingArea
void set_text (const char*);
};
- ARDOUR::Panner& panner;
+ boost::shared_ptr<ARDOUR::Panner> panner;
Glib::RefPtr<Pango::Layout> layout;
typedef std::map<int,Target *> Targets;
@@ -137,7 +137,7 @@ class Panner2d : public Gtk::DrawingArea
class Panner2dWindow : public Gtk::Window
{
public:
- Panner2dWindow (ARDOUR::Panner&, int32_t height, uint32_t inputs);
+ Panner2dWindow (boost::shared_ptr<ARDOUR::Panner>, int32_t height, uint32_t inputs);
void reset (uint32_t n_inputs);
diff --git a/gtk2_ardour/panner_ui.cc b/gtk2_ardour/panner_ui.cc
index 2df79d2c39..4777c82479 100644
--- a/gtk2_ardour/panner_ui.cc
+++ b/gtk2_ardour/panner_ui.cc
@@ -132,6 +132,11 @@ PannerUI::PannerUI (Session& s)
void
PannerUI::set_io (boost::shared_ptr<IO> io)
{
+ if (!io->panner()) {
+ cerr << "PannerUI::set_io IO has no panners" << endl;
+ return;
+ }
+
connections.clear ();
delete pan_astyle_menu;
@@ -142,9 +147,12 @@ PannerUI::set_io (boost::shared_ptr<IO> io)
_io = io;
- 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 (_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)));
delete panner;
panner = 0;
@@ -185,14 +193,18 @@ PannerUI::build_astate_menu ()
pan_astate_menu->items().clear ();
}
- pan_astate_menu->items().push_back (MenuElem (_("Manual"),
- bind (mem_fun (_io->panner(), &Panner::set_automation_state), (AutoState) Off)));
- pan_astate_menu->items().push_back (MenuElem (_("Play"),
- bind (mem_fun (_io->panner(), &Panner::set_automation_state), (AutoState) Play)));
- pan_astate_menu->items().push_back (MenuElem (_("Write"),
- bind (mem_fun (_io->panner(), &Panner::set_automation_state), (AutoState) Write)));
- pan_astate_menu->items().push_back (MenuElem (_("Touch"),
- bind (mem_fun (_io->panner(), &Panner::set_automation_state), (AutoState) Touch)));
+ pan_astate_menu->items().push_back (MenuElem (_("Manual"), bind (
+ mem_fun (_io->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),
+ (AutoState) Play)));
+ pan_astate_menu->items().push_back (MenuElem (_("Write"), bind (
+ mem_fun (_io->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),
+ (AutoState) Touch)));
}
@@ -228,7 +240,7 @@ bool
PannerUI::panning_link_button_release (GdkEventButton* ev)
{
if (!ignore_toggle) {
- _io->panner().set_linked (!_io->panner().linked());
+ _io->panner()->set_linked (!_io->panner()->linked());
}
return true;
}
@@ -236,12 +248,12 @@ PannerUI::panning_link_button_release (GdkEventButton* ev)
void
PannerUI::panning_link_direction_clicked()
{
- switch (_io->panner().link_direction()) {
+ switch (_io->panner()->link_direction()) {
case Panner::SameDirection:
- _io->panner().set_link_direction (Panner::OppositeDirection);
+ _io->panner()->set_link_direction (Panner::OppositeDirection);
break;
default:
- _io->panner().set_link_direction (Panner::SameDirection);
+ _io->panner()->set_link_direction (Panner::SameDirection);
break;
}
}
@@ -251,7 +263,7 @@ PannerUI::update_pan_linkage ()
{
ENSURE_GUI_THREAD(mem_fun(*this, &PannerUI::update_pan_linkage));
- bool x = _io->panner().linked();
+ bool x = _io->panner()->linked();
bool bx = panning_link_button.get_active();
if (x != bx) {
@@ -263,7 +275,7 @@ PannerUI::update_pan_linkage ()
panning_link_direction_button.set_sensitive (x);
- switch (_io->panner().link_direction()) {
+ switch (_io->panner()->link_direction()) {
case Panner::SameDirection:
panning_link_direction_button.set_image (*(manage (new Image (get_xpm ("forwardblarrow.xpm")))));
break;
@@ -325,6 +337,10 @@ PannerUI::update_pan_state ()
void
PannerUI::setup_pan ()
{
+ if (!_io->panner()) {
+ return;
+ }
+
uint32_t nouts = _io->n_outputs ().n_audio();
if (nouts == 0 || nouts == 1) {
@@ -346,7 +362,7 @@ PannerUI::setup_pan ()
} else if (nouts == 2) {
vector<Adjustment*>::size_type asz;
- uint32_t npans = _io->panner().npanners();
+ uint32_t npans = _io->panner()->npanners();
while (!pan_adjustments.empty()) {
delete pan_bars.back();
@@ -363,7 +379,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 = _io->panner()->pan_control( asz)->get_value();
if (npans == 1) {
x = 0.5;
@@ -377,13 +393,13 @@ PannerUI::setup_pan ()
pan_adjustments.push_back (new Adjustment (x, 0, 1.0, 0.05, 0.1));
bc = new PannerBar (*pan_adjustments[asz],
- boost::static_pointer_cast<PBD::Controllable>( _io->panner().pan_control( asz )) );
+ boost::static_pointer_cast<PBD::Controllable>( _io->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));
+ _io->panner()->pan_control( asz )->Changed.connect (bind (mem_fun(*this, &PannerUI::pan_value_changed), (uint32_t) asz));
bc->set_name ("PanSlider");
@@ -418,11 +434,10 @@ PannerUI::setup_pan ()
} else {
- if (panner == 0) {
+ if (!panner) {
panner = new Panner2d (_io->panner(), 61);
panner->set_name ("MixerPanZone");
panner->show ();
-
panner->signal_button_press_event().connect
(bind (mem_fun(*this, &PannerUI::pan_button_event), (uint32_t) 0), false);
@@ -485,7 +500,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 (_io->panner()->streampanner(which).muted());
(dynamic_cast<CheckMenuItem*> (&items.back()))->signal_toggled().connect
(bind (mem_fun(*this, &PannerUI::pan_mute), which));
@@ -494,7 +509,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 (_io->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)));
@@ -505,34 +520,34 @@ PannerUI::build_pan_menu (uint32_t which)
void
PannerUI::pan_mute (uint32_t which)
{
- StreamPanner& sp = _io->panner().streampanner(which);
+ StreamPanner& sp = _io->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 && (_io->panner()->bypassed() != bypass_menu_item->get_active())) {
+ _io->panner()->set_bypassed (!_io->panner()->bypassed());
}
}
void
PannerUI::pan_reset (uint32_t which)
{
- _io->panner().reset_streampanner (which);
+ _io->panner()->reset_streampanner (which);
}
void
PannerUI::pan_reset_all ()
{
- _io->panner().reset_to_default ();
+ _io->panner()->reset_to_default ();
}
void
PannerUI::effective_pan_display ()
{
- if (_io->panner().empty()) {
+ if (_io->panner()->empty()) {
return;
}
@@ -559,7 +574,7 @@ PannerUI::pan_changed (void *src)
return;
}
- switch (_io->panner().npanners()) {
+ switch (_io->panner()->npanners()) {
case 0:
panning_link_direction_button.set_sensitive (false);
panning_link_button.set_sensitive (false);
@@ -595,11 +610,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 < _io->panner()->npanners()) {
float xpos;
float val = pan_adjustments[which]->get_value ();
- xpos = _io->panner().pan_control( which )->get_value();
+ xpos = _io->panner()->pan_control( which )->get_value();
/* add a kinda-sorta detent for the middle */
@@ -616,7 +631,7 @@ PannerUI::pan_adjustment_changed (uint32_t which)
if (!Panner::equivalent (val, xpos)) {
- _io->panner().streampanner(which).set_position (val);
+ _io->panner()->streampanner(which).set_position (val);
/* XXX
the panner objects have no access to the session,
so do this here. ick.
@@ -631,11 +646,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 (_io->n_outputs().n_audio() > 1 && which < _io->panner()->npanners()) {
float xpos;
float val = pan_adjustments[which]->get_value ();
- _io->panner().streampanner(which).get_position (xpos);
+ _io->panner()->streampanner(which).get_position (xpos);
if (!Panner::equivalent (val, xpos)) {
in_pan_update = true;
@@ -661,14 +676,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 (_io->panner()->streampanner(n).pan_control()->alist());
if (!alist->automation_playback()) {
continue;
}
}
- _io->panner().streampanner(n).get_effective_position (xpos);
+ _io->panner()->streampanner(n).get_effective_position (xpos);
val = (*i)->get_value ();
if (!Panner::equivalent (val, xpos)) {
@@ -699,7 +714,7 @@ PannerUI::pan_printer (char *buf, uint32_t len, Adjustment* adj)
void
PannerUI::update_pan_sensitive ()
{
- bool sensitive = !(_io->panner().automation_state() & Play);
+ bool sensitive = !(_io->panner()->automation_state() & Play);
switch (_io->n_outputs().n_audio()) {
case 0:
@@ -771,10 +786,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(_io->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(_io->panner()->automation_style()));
break;
}
}
@@ -788,10 +803,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(_io->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(_io->panner()->automation_state()));
break;
}
@@ -800,11 +815,11 @@ PannerUI::pan_automation_state_changed ()
here.
*/
- if (_io->panner().empty()) {
+ if (_io->panner()->empty()) {
return;
}
- x = (_io->panner().streampanner(0).pan_control()->alist()->automation_state() != Off);
+ x = (_io->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/po/de_DE.po b/gtk2_ardour/po/de_DE.po
index 7087f0c278..4fc76bc7da 100644
--- a/gtk2_ardour/po/de_DE.po
+++ b/gtk2_ardour/po/de_DE.po
@@ -7312,8 +7312,7 @@ msgstr "Ardour/GTK "
#: gtk2_ardour/main.cc:294
msgid ""
-"\n"
-" (built using "
+" (built using "
msgstr ""
"\n"
" (kompiliert mit Version "
@@ -7355,7 +7354,7 @@ msgid "could not create ARDOUR GUI"
msgstr "konnte das grafische Ardour User Interface nicht erstellen"
#: gtk2_ardour/ui_config.cc:78
-msgid "loading default ui configuration file %1"
+msgid "Loading default ui configuration file %1"
msgstr "lade voreingestellte UI-Konfigurationsdatei %1"
#: gtk2_ardour/ui_config.cc:81
@@ -7367,8 +7366,8 @@ msgid "Ardour: default ui configuration file \"%1\" not loaded successfully."
msgstr "Ardour: Die voreingestellte UI-Konfigurationsdatei \"%1\" konnte nicht geladen werden."
#: gtk2_ardour/ui_config.cc:104
-msgid "loading user ui configuration file %1"
-msgstr "lade benutzerdefinierte UI-Konfigurationsdatei %1"
+msgid "Loading user ui configuration file %1"
+msgstr "Lade benutzerdefinierte UI-Konfigurationsdatei %1"
#: gtk2_ardour/ui_config.cc:107
msgid "Ardour: cannot read ui configuration file \"%1\""
diff --git a/gtk2_ardour/po/el_GR.po b/gtk2_ardour/po/el_GR.po
index fdbe8f0673..c34906e607 100644
--- a/gtk2_ardour/po/el_GR.po
+++ b/gtk2_ardour/po/el_GR.po
@@ -4931,8 +4931,7 @@ msgstr "Ardour/GTK "
#: main.cc:401
msgid ""
-"\n"
-" (built using "
+" (built using "
msgstr ""
#: main.cc:405
diff --git a/gtk2_ardour/po/es_ES.po b/gtk2_ardour/po/es_ES.po
index c6c0c7415e..682e85199b 100644
--- a/gtk2_ardour/po/es_ES.po
+++ b/gtk2_ardour/po/es_ES.po
@@ -4900,8 +4900,7 @@ msgstr ""
#: main.cc:401
msgid ""
-"\n"
-" (built using "
+" (built using "
msgstr ""
#: main.cc:405
diff --git a/gtk2_ardour/po/fr_FR.po b/gtk2_ardour/po/fr_FR.po
index 100e2dbedf..7ae67b2df7 100644
--- a/gtk2_ardour/po/fr_FR.po
+++ b/gtk2_ardour/po/fr_FR.po
@@ -5528,8 +5528,7 @@ msgstr "Ardour/GTK"
#: gtk2_ardour/main.cc:314
msgid ""
-"\n"
-" (built using "
+" (built using "
msgstr ""
"\n"
" (construit avec "
@@ -7004,7 +7003,7 @@ msgid "programming error: request for non-existent audio range (%1)!"
msgstr "programming error: request for non-existent audio range (%1)!"
#: gtk2_ardour/ui_config.cc:67
-msgid "loading default ui configuration file %1"
+msgid "Loading default ui configuration file %1"
msgstr ""
"Chargement du fichier de style par défaut (%1) pour l'interface graphique"
@@ -7021,9 +7020,9 @@ msgstr ""
"graphique n'a pas pu être chargé correctement."
#: gtk2_ardour/ui_config.cc:93
-msgid "loading user ui configuration file %1"
+msgid "Loading user ui configuration file %1"
msgstr ""
-"chargement du fichier utilisateur (%1) pour la configuration de l'interface "
+"Chargement du fichier utilisateur (%1) pour la configuration de l'interface "
"graphique"
#: gtk2_ardour/ui_config.cc:96
diff --git a/gtk2_ardour/po/it_IT.po b/gtk2_ardour/po/it_IT.po
index 018bce6576..c550eb5132 100644
--- a/gtk2_ardour/po/it_IT.po
+++ b/gtk2_ardour/po/it_IT.po
@@ -4790,8 +4790,7 @@ msgstr ""
#: main.cc:401
msgid ""
-"\n"
-" (built using "
+" (built using "
msgstr ""
#: main.cc:405
diff --git a/gtk2_ardour/po/pl_PL.po b/gtk2_ardour/po/pl_PL.po
index b01253b6e5..2e19de45d2 100644
--- a/gtk2_ardour/po/pl_PL.po
+++ b/gtk2_ardour/po/pl_PL.po
@@ -6147,8 +6147,7 @@ msgstr "Ardour/GTK "
#: gtk2_ardour/main.cc:272
msgid ""
-"\n"
-" (built using "
+" (built using "
msgstr ""
"\n"
" (skompilowany przy użyciu "
@@ -7636,7 +7635,7 @@ msgid "programming error: request for non-existent audio range (%1)!"
msgstr ""
#: gtk2_ardour/ui_config.cc:76
-msgid "loading default ui configuration file %1"
+msgid "Loading default ui configuration file %1"
msgstr ""
#: gtk2_ardour/ui_config.cc:79
@@ -7648,7 +7647,7 @@ msgid "Ardour: default ui configuration file \"%1\" not loaded successfully."
msgstr ""
#: gtk2_ardour/ui_config.cc:102
-msgid "loading user ui configuration file %1"
+msgid "Loading user ui configuration file %1"
msgstr ""
#: gtk2_ardour/ui_config.cc:105
diff --git a/gtk2_ardour/po/pt_BR.po b/gtk2_ardour/po/pt_BR.po
index e327dd1549..4de77b1748 100644
--- a/gtk2_ardour/po/pt_BR.po
+++ b/gtk2_ardour/po/pt_BR.po
@@ -4852,8 +4852,7 @@ msgstr ""
#: main.cc:401
msgid ""
-"\n"
-" (built using "
+" (built using "
msgstr ""
#: main.cc:405
diff --git a/gtk2_ardour/po/pt_PT.po b/gtk2_ardour/po/pt_PT.po
index 7af0a59254..253628e405 100644
--- a/gtk2_ardour/po/pt_PT.po
+++ b/gtk2_ardour/po/pt_PT.po
@@ -4529,8 +4529,7 @@ msgstr ""
#: main.cc:401
msgid ""
-"\n"
-" (built using "
+" (built using "
msgstr ""
"\n"
" (compilado "
diff --git a/gtk2_ardour/po/ru_RU.po b/gtk2_ardour/po/ru_RU.po
index 6ef4bf5878..dc97ef025e 100644
--- a/gtk2_ardour/po/ru_RU.po
+++ b/gtk2_ardour/po/ru_RU.po
@@ -4761,8 +4761,7 @@ msgstr "Ardour/GTK "
#: gtk2_ardour/main.cc:388
msgid ""
-"\n"
-" (built using "
+" (built using "
msgstr ""
"\n"
" (Ñобран Ñ Ð¸Ñпользованием "
diff --git a/gtk2_ardour/po/sv_SE.po b/gtk2_ardour/po/sv_SE.po
index 66edd56dcc..dba2d07134 100644
--- a/gtk2_ardour/po/sv_SE.po
+++ b/gtk2_ardour/po/sv_SE.po
@@ -4797,8 +4797,7 @@ msgstr ""
#: ../main.cc:397
msgid ""
-"\n"
-" (built using "
+" (built using "
msgstr ""
"\n"
" (kompilerat med "
diff --git a/gtk2_ardour/processor_box.cc b/gtk2_ardour/processor_box.cc
index 75d9281a94..2bf988aad9 100644
--- a/gtk2_ardour/processor_box.cc
+++ b/gtk2_ardour/processor_box.cc
@@ -37,17 +37,19 @@
#include <gtkmm2ext/doi.h>
#include <gtkmm2ext/window_title.h>
+#include "ardour/amp.h"
#include "ardour/ardour.h"
-#include "ardour/session.h"
-#include "ardour/audioengine.h"
-#include "ardour/route.h"
-#include "ardour/audio_track.h"
#include "ardour/audio_diskstream.h"
-#include "ardour/send.h"
+#include "ardour/audio_track.h"
+#include "ardour/audioengine.h"
+#include "ardour/ladspa_plugin.h"
+#include "ardour/meter.h"
#include "ardour/plugin_insert.h"
#include "ardour/port_insert.h"
-#include "ardour/ladspa_plugin.h"
#include "ardour/profile.h"
+#include "ardour/route.h"
+#include "ardour/send.h"
+#include "ardour/session.h"
#include "ardour_ui.h"
#include "ardour_dialog.h"
@@ -82,19 +84,21 @@ bool ProcessorBox::get_colors = true;
Gdk::Color* ProcessorBox::active_processor_color;
Gdk::Color* ProcessorBox::inactive_processor_color;
-ProcessorBox::ProcessorBox (Placement pcmnt, Session& sess, PluginSelector &plugsel,
+ProcessorBox::ProcessorBox (Placement pcmnt, Session& sess, PluginSelector &plugsel,
RouteRedirectSelection & rsel, bool owner_is_mixer)
- : _session(sess),
- _owner_is_mixer (owner_is_mixer),
- _placement(pcmnt),
- _plugin_selector(plugsel),
- _rr_selection(rsel)
+ : _session(sess)
+ , _owner_is_mixer (owner_is_mixer)
+ , _placement(pcmnt)
+ , _plugin_selector(plugsel)
+ , _rr_selection(rsel)
{
if (get_colors) {
active_processor_color = new Gdk::Color;
inactive_processor_color = new Gdk::Color;
- set_color (*active_processor_color, rgba_from_style ("ProcessorSelector", 0xff, 0, 0, 0, "fg", Gtk::STATE_ACTIVE, false ));
- set_color (*inactive_processor_color, rgba_from_style ("ProcessorSelector", 0xff, 0, 0, 0, "fg", Gtk::STATE_NORMAL, false ));
+ set_color (*active_processor_color, rgba_from_style (
+ "ProcessorSelector", 0xff, 0, 0, 0, "fg", Gtk::STATE_ACTIVE, false ));
+ set_color (*inactive_processor_color, rgba_from_style (
+ "ProcessorSelector", 0xff, 0, 0, 0, "fg", Gtk::STATE_NORMAL, false ));
get_colors = false;
}
@@ -123,24 +127,29 @@ ProcessorBox::ProcessorBox (Placement pcmnt, Session& sess, PluginSelector &plug
processor_display.signal_drop.connect (mem_fun (*this, &ProcessorBox::object_drop));
TreeViewColumn* name_col = processor_display.get_column(0);
- CellRendererText* renderer = dynamic_cast<CellRendererText*>(processor_display.get_column_cell_renderer (0));
+ CellRendererText* renderer = dynamic_cast<CellRendererText*>(
+ processor_display.get_column_cell_renderer (0));
name_col->add_attribute(renderer->property_foreground_gdk(), columns.color);
processor_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
-
+
model->signal_row_deleted().connect (mem_fun (*this, &ProcessorBox::row_deleted));
processor_scroller.add (processor_display);
processor_eventbox.add (processor_scroller);
-
+
processor_scroller.set_size_request (-1, 40);
pack_start (processor_eventbox, true, true);
- processor_eventbox.signal_enter_notify_event().connect (bind (sigc::ptr_fun (ProcessorBox::enter_box), this));
+ processor_eventbox.signal_enter_notify_event().connect (bind (
+ sigc::ptr_fun (ProcessorBox::enter_box),
+ this));
- processor_display.signal_button_press_event().connect (mem_fun(*this, &ProcessorBox::processor_button_press_event), false);
- processor_display.signal_button_release_event().connect (mem_fun(*this, &ProcessorBox::processor_button_release_event));
+ processor_display.signal_button_press_event().connect (
+ mem_fun(*this, &ProcessorBox::processor_button_press_event), false);
+ processor_display.signal_button_release_event().connect (
+ mem_fun(*this, &ProcessorBox::processor_button_release_event));
}
ProcessorBox::~ProcessorBox ()
@@ -154,9 +163,12 @@ ProcessorBox::set_route (boost::shared_ptr<Route> r)
_route = r;
- connections.push_back (_route->processors_changed.connect (mem_fun(*this, &ProcessorBox::redisplay_processors)));
- connections.push_back (_route->GoingAway.connect (mem_fun (*this, &ProcessorBox::route_going_away)));
- connections.push_back (_route->NameChanged.connect (mem_fun(*this, &ProcessorBox::route_name_changed)));
+ connections.push_back (_route->processors_changed.connect (
+ mem_fun(*this, &ProcessorBox::redisplay_processors)));
+ connections.push_back (_route->GoingAway.connect (
+ mem_fun (*this, &ProcessorBox::route_going_away)));
+ connections.push_back (_route->NameChanged.connect (
+ mem_fun(*this, &ProcessorBox::route_name_changed)));
redisplay_processors ();
}
@@ -172,8 +184,8 @@ ProcessorBox::route_going_away ()
void
ProcessorBox::object_drop (const list<boost::shared_ptr<Processor> >& procs)
{
- for (std::list<boost::shared_ptr<Processor> >::const_iterator i = procs.begin(); i != procs.end(); ++i) {
-
+ for (std::list<boost::shared_ptr<Processor> >::const_iterator i = procs.begin();
+ i != procs.end(); ++i) {
XMLNode& state = (*i)->get_state ();
XMLNodeList nlist;
nlist.push_back (&state);
@@ -207,11 +219,9 @@ ProcessorBox::remove_processor_gui (boost::shared_ptr<Processor> processor)
boost::shared_ptr<PortInsert> port_insert;
if ((port_insert = boost::dynamic_pointer_cast<PortInsert> (processor)) != 0) {
-
PortInsertUI *io_selector = reinterpret_cast<PortInsertUI *> (port_insert->get_gui());
port_insert->set_gui (0);
delete io_selector;
-
} else if ((send = boost::dynamic_pointer_cast<Send> (processor)) != 0) {
SendUIWindow *sui = reinterpret_cast<SendUIWindow*> (send->get_gui());
send->set_gui (0);
@@ -219,9 +229,8 @@ ProcessorBox::remove_processor_gui (boost::shared_ptr<Processor> processor)
}
}
-void
+void
ProcessorBox::build_send_action_menu ()
-
{
using namespace Menu_Helpers;
@@ -235,13 +244,11 @@ ProcessorBox::build_send_action_menu ()
void
ProcessorBox::show_send_controls ()
-
{
}
void
ProcessorBox::new_send ()
-
{
}
@@ -292,17 +299,17 @@ ProcessorBox::processor_button_press_event (GdkEventButton *ev)
processor = (*iter)[columns.processor];
selected = processor_display.get_selection()->is_selected (iter);
}
-
+
}
if (processor && (Keyboard::is_edit_event (ev) || (ev->button == 1 && ev->type == GDK_2BUTTON_PRESS))) {
-
+
if (_session.engine().connected()) {
/* XXX giving an error message here is hard, because we may be in the midst of a button press */
edit_processor (processor);
}
ret = true;
-
+
} else if (processor && ev->button == 1 && selected) {
// this is purely informational but necessary
@@ -314,7 +321,7 @@ ProcessorBox::processor_button_press_event (GdkEventButton *ev)
_plugin_selector.show_manager ();
}
-
+
return ret;
}
@@ -337,10 +344,12 @@ ProcessorBox::processor_button_release_event (GdkEventButton *ev)
}
if (processor && Keyboard::is_delete_event (ev)) {
-
- Glib::signal_idle().connect (bind (mem_fun(*this, &ProcessorBox::idle_delete_processor), boost::weak_ptr<Processor>(processor)));
+
+ Glib::signal_idle().connect (bind (
+ mem_fun(*this, &ProcessorBox::idle_delete_processor),
+ boost::weak_ptr<Processor>(processor)));
ret = true;
-
+
} else if (Keyboard::is_context_menu_event (ev)) {
show_processor_menu(ev->time);
@@ -350,7 +359,7 @@ ProcessorBox::processor_button_release_event (GdkEventButton *ev)
#ifndef GTKOSX
&& (Keyboard::no_modifier_keys_pressed (ev) && ((ev->state & Gdk::BUTTON2_MASK) == Gdk::BUTTON2_MASK))
#endif
- ) {
+ ) {
/* button2-click with no/appropriate modifiers */
@@ -361,7 +370,7 @@ ProcessorBox::processor_button_release_event (GdkEventButton *ev)
}
ret = true;
- }
+ }
return ret;
}
@@ -407,23 +416,25 @@ ProcessorBox::use_plugins (const SelectedPlugins& plugins)
{
for (SelectedPlugins::const_iterator p = plugins.begin(); p != plugins.end(); ++p) {
- boost::shared_ptr<Processor> processor (new PluginInsert (_session, *p, _placement));
+ boost::shared_ptr<Processor> processor (new PluginInsert (_session, *p));
Route::ProcessorStreams err_streams;
if (Config->get_new_plugins_active()) {
processor->activate ();
}
-
- if (_route->add_processor (processor, &err_streams)) {
+
+ if (_route->add_processor (processor, &err_streams, 0, _placement)) {
weird_plugin_dialog (**p, err_streams, _route);
- // XXX SHAREDPTR delete plugin here .. do we even need to care?
+ // XXX SHAREDPTR delete plugin here .. do we even need to care?
} else {
-
+
if (Profile->get_sae()) {
processor->activate ();
}
- processor->ActiveChanged.connect (bind (mem_fun (*this, &ProcessorBox::show_processor_active), boost::weak_ptr<Processor>(processor)));
+ processor->ActiveChanged.connect (bind (
+ mem_fun (*this, &ProcessorBox::show_processor_active),
+ boost::weak_ptr<Processor>(processor)));
}
}
}
@@ -448,7 +459,7 @@ ProcessorBox::weird_plugin_dialog (Plugin& p, Route::ProcessorStreams streams, b
text += string_compose("\t%1 ", p.get_info()->n_inputs.n_audio()) + _("audio input(s)\n");
}
- text += "\nBut at the insertion point, there are:\n";
+ text += _("\nBut at the insertion point, there are:\n");
if (has_midi) {
text += string_compose("\t%1 ", streams.count.n_midi()) + _("MIDI channel(s)\n");
}
@@ -456,7 +467,7 @@ ProcessorBox::weird_plugin_dialog (Plugin& p, Route::ProcessorStreams streams, b
text += string_compose("\t%1 ", streams.count.n_audio()) + _("audio channel(s)\n");
}
- text += "\nArdour is unable to insert this plugin here.\n";
+ text += _("\nArdour is unable to insert this plugin here.\n");
label.set_text(text);
dialog.get_vbox()->pack_start (label);
@@ -473,15 +484,17 @@ ProcessorBox::weird_plugin_dialog (Plugin& p, Route::ProcessorStreams streams, b
void
ProcessorBox::choose_insert ()
{
- boost::shared_ptr<Processor> processor (new PortInsert (_session, _placement));
- processor->ActiveChanged.connect (bind (mem_fun(*this, &ProcessorBox::show_processor_active), boost::weak_ptr<Processor>(processor)));
- _route->add_processor (processor);
+ boost::shared_ptr<Processor> processor (new PortInsert (_session));
+ processor->ActiveChanged.connect (bind (
+ mem_fun(*this, &ProcessorBox::show_processor_active),
+ boost::weak_ptr<Processor>(processor)));
+ _route->add_processor (processor, 0, 0, _placement);
}
void
ProcessorBox::choose_send ()
{
- boost::shared_ptr<Send> send (new Send (_session, _placement));
+ boost::shared_ptr<Send> send (new Send (_session));
//send->set_default_type(_route->default_type());
ChanCount outs;
@@ -502,11 +515,11 @@ ProcessorBox::choose_send ()
error << string_compose (_("Cannot set up new send: %1"), err.what()) << endmsg;
return;
}
-
+
/* let the user adjust the output setup (number and connections) before passing
it along to the Route
*/
-
+
IOSelectorWindow *ios = new IOSelectorWindow (_session, send->io(), false, true);
ios->show_all ();
@@ -516,8 +529,10 @@ ProcessorBox::choose_send ()
_send_being_created = send;
boost::shared_ptr<Processor> r = boost::static_pointer_cast<Processor>(send);
-
- ios->selector().Finished.connect (bind (mem_fun(*this, &ProcessorBox::send_io_finished), boost::weak_ptr<Processor>(r), ios));
+
+ ios->selector().Finished.connect (bind (
+ mem_fun(*this, &ProcessorBox::send_io_finished),
+ boost::weak_ptr<Processor>(r), ios));
}
void
@@ -538,7 +553,7 @@ ProcessorBox::send_io_finished (IOSelector::Result r, boost::weak_ptr<Processor>
break;
case IOSelector::Accepted:
- _route->add_processor (processor);
+ _route->add_processor (processor, 0, 0, _placement);
if (Profile->get_sae()) {
processor->activate ();
}
@@ -556,7 +571,7 @@ ProcessorBox::redisplay_processors ()
if (no_processor_redisplay) {
return;
}
-
+
ignore_delete = true;
model->clear ();
ignore_delete = false;
@@ -564,7 +579,7 @@ ProcessorBox::redisplay_processors ()
processor_active_connections.clear ();
processor_name_connections.clear ();
- _route->foreach_processor (mem_fun (*this, &ProcessorBox::add_processor_to_display));
+ _route->foreach_processor (_placement, mem_fun (*this, &ProcessorBox::add_processor_to_display));
switch (_placement) {
case PreFader:
@@ -583,19 +598,23 @@ ProcessorBox::add_processor_to_display (boost::weak_ptr<Processor> p)
if (!processor) {
return;
}
-
- if (processor->placement() != _placement) {
+
+ if (processor == _route->amp()) {
return;
}
-
+
Gtk::TreeModel::Row row = *(model->append());
row[columns.text] = processor_name (processor);
row[columns.processor] = processor;
show_processor_active (processor);
- processor_active_connections.push_back (processor->ActiveChanged.connect (bind (mem_fun(*this, &ProcessorBox::show_processor_active), boost::weak_ptr<Processor>(processor))));
- processor_name_connections.push_back (processor->NameChanged.connect (bind (mem_fun(*this, &ProcessorBox::show_processor_name), boost::weak_ptr<Processor>(processor))));
+ processor_active_connections.push_back (processor->ActiveChanged.connect (bind (
+ mem_fun(*this, &ProcessorBox::show_processor_active),
+ boost::weak_ptr<Processor>(processor))));
+ processor_name_connections.push_back (processor->NameChanged.connect (bind (
+ mem_fun(*this, &ProcessorBox::show_processor_name),
+ boost::weak_ptr<Processor>(processor))));
}
string
@@ -678,13 +697,13 @@ void
ProcessorBox::show_processor_active (boost::weak_ptr<Processor> weak_processor)
{
boost::shared_ptr<Processor> processor (weak_processor.lock());
-
+
if (!processor) {
return;
}
ENSURE_GUI_THREAD(bind (mem_fun(*this, &ProcessorBox::show_processor_active), weak_processor));
-
+
Gtk::TreeModel::Children children = model->children();
Gtk::TreeModel::Children::iterator iter = children.begin();
@@ -694,7 +713,7 @@ ProcessorBox::show_processor_active (boost::weak_ptr<Processor> weak_processor)
if (r == processor) {
(*iter)[columns.text] = processor_name (r);
-
+
if (processor->active()) {
(*iter)[columns.color] = *active_processor_color;
} else {
@@ -756,15 +775,15 @@ outputs do not work correctly."));
void
ProcessorBox::rename_processors ()
{
- vector<boost::shared_ptr<Processor> > to_be_renamed;
-
+ ProcSelection to_be_renamed;
+
get_selected_processors (to_be_renamed);
if (to_be_renamed.empty()) {
return;
}
- for (vector<boost::shared_ptr<Processor> >::iterator i = to_be_renamed.begin(); i != to_be_renamed.end(); ++i) {
+ for (ProcSelection::iterator i = to_be_renamed.begin(); i != to_be_renamed.end(); ++i) {
rename_processor (*i);
}
}
@@ -772,7 +791,7 @@ ProcessorBox::rename_processors ()
void
ProcessorBox::cut_processors ()
{
- vector<boost::shared_ptr<Processor> > to_be_removed;
+ ProcSelection to_be_removed;
XMLNode* node = new XMLNode (X_("cut"));
get_selected_processors (to_be_removed);
@@ -782,17 +801,17 @@ ProcessorBox::cut_processors ()
}
no_processor_redisplay = true;
- for (vector<boost::shared_ptr<Processor> >::iterator i = to_be_removed.begin(); i != to_be_removed.end(); ++i) {
+ for (ProcSelection::iterator i = to_be_removed.begin(); i != to_be_removed.end(); ++i) {
// Do not cut inserts
if (boost::dynamic_pointer_cast<PluginInsert>((*i)) != 0 ||
(boost::dynamic_pointer_cast<Send>((*i)) != 0)) {
void* gui = (*i)->get_gui ();
-
+
if (gui) {
static_cast<Gtk::Widget*>(gui)->hide ();
}
-
+
XMLNode& child ((*i)->get_state());
if (_route->remove_processor (*i) == 0) {
@@ -801,7 +820,7 @@ ProcessorBox::cut_processors ()
} else {
delete &child;
}
- }
+ }
}
_rr_selection.set (node);
@@ -813,7 +832,7 @@ ProcessorBox::cut_processors ()
void
ProcessorBox::copy_processors ()
{
- vector<boost::shared_ptr<Processor> > to_be_copied;
+ ProcSelection to_be_copied;
XMLNode* node = new XMLNode (X_("copy"));
get_selected_processors (to_be_copied);
@@ -822,7 +841,7 @@ ProcessorBox::copy_processors ()
return;
}
- for (vector<boost::shared_ptr<Processor> >::iterator i = to_be_copied.begin(); i != to_be_copied.end(); ++i) {
+ for (ProcSelection::iterator i = to_be_copied.begin(); i != to_be_copied.end(); ++i) {
// Do not copy inserts
if (boost::dynamic_pointer_cast<PluginInsert>((*i)) != 0 ||
(boost::dynamic_pointer_cast<Send>((*i)) != 0)) {
@@ -836,18 +855,18 @@ ProcessorBox::copy_processors ()
void
ProcessorBox::delete_processors ()
{
- vector<boost::shared_ptr<Processor> > to_be_deleted;
-
+ ProcSelection to_be_deleted;
+
get_selected_processors (to_be_deleted);
if (to_be_deleted.empty()) {
return;
}
- for (vector<boost::shared_ptr<Processor> >::iterator i = to_be_deleted.begin(); i != to_be_deleted.end(); ++i) {
-
+ for (ProcSelection::iterator i = to_be_deleted.begin(); i != to_be_deleted.end(); ++i) {
+
void* gui = (*i)->get_gui ();
-
+
if (gui) {
static_cast<Gtk::Widget*>(gui)->hide ();
}
@@ -895,7 +914,7 @@ ProcessorBox::rename_processor (boost::shared_ptr<Processor> processor)
name_prompter.get_result (result);
if (result.length()) {
processor->set_name (result);
- }
+ }
break;
}
@@ -937,12 +956,14 @@ ProcessorBox::paste_processor_state (const XMLNodeList& nlist)
XMLNode n (**niter);
Send::make_unique (n, _session);
p.reset (new Send (_session, n));
-
+
+ } else if (type->value() == "meter") {
+ p = _route->shared_peak_meter();
+
} else {
p.reset (new PluginInsert (_session, **niter));
}
- p->set_placement (_placement);
copies.push_back (p);
}
catch (...) {
@@ -950,7 +971,7 @@ ProcessorBox::paste_processor_state (const XMLNodeList& nlist)
}
}
- if (_route->add_processors (copies)) {
+ if (_route->add_processors (copies, 0, _placement)) {
string msg = _(
"Copying the set of processors on the clipboard failed,\n\
@@ -974,10 +995,10 @@ ProcessorBox::deactivate_processor (boost::shared_ptr<Processor> r)
}
void
-ProcessorBox::get_selected_processors (vector<boost::shared_ptr<Processor> >& processors)
+ProcessorBox::get_selected_processors (ProcSelection& processors)
{
vector<Gtk::TreeModel::Path> pathlist = processor_display.get_selection()->get_selected_rows();
-
+
for (vector<Gtk::TreeModel::Path>::iterator iter = pathlist.begin(); iter != pathlist.end(); ++iter) {
processors.push_back ((*(model->get_iter(*iter)))[columns.processor]);
}
@@ -1056,19 +1077,19 @@ ProcessorBox::edit_processor (boost::shared_ptr<Processor> processor)
return;
}
}
-
+
if ((send = boost::dynamic_pointer_cast<Send> (processor)) != 0) {
-
+
if (!_session.engine().connected()) {
return;
}
boost::shared_ptr<Send> send = boost::dynamic_pointer_cast<Send> (processor);
-
+
SendUIWindow *send_ui;
-
+
if (send->get_gui() == 0) {
-
+
send_ui = new SendUIWindow (send, _session);
WindowTitle title(Glib::get_application_name());
@@ -1076,57 +1097,57 @@ ProcessorBox::edit_processor (boost::shared_ptr<Processor> processor)
send_ui->set_title (title.get_string());
send->set_gui (send_ui);
-
+
} else {
send_ui = reinterpret_cast<SendUIWindow *> (send->get_gui());
}
-
+
gidget = send_ui;
-
+
} else if ((plugin_insert = boost::dynamic_pointer_cast<PluginInsert> (processor)) != 0) {
-
+
PluginUIWindow *plugin_ui;
-
+
/* these are both allowed to be null */
-
+
Container* toplevel = get_toplevel();
Window* win = dynamic_cast<Gtk::Window*>(toplevel);
-
+
if (plugin_insert->get_gui() == 0) {
-
+
plugin_ui = new PluginUIWindow (win, plugin_insert);
-
+
WindowTitle title(Glib::get_application_name());
title += generate_processor_title (plugin_insert);
plugin_ui->set_title (title.get_string());
-
+
plugin_insert->set_gui (plugin_ui);
-
+
} else {
plugin_ui = reinterpret_cast<PluginUIWindow *> (plugin_insert->get_gui());
plugin_ui->set_parent (win);
}
-
+
gidget = plugin_ui;
-
+
} else if ((port_insert = boost::dynamic_pointer_cast<PortInsert> (processor)) != 0) {
-
+
if (!_session.engine().connected()) {
MessageDialog msg ( _("Not connected to JACK - no I/O changes are possible"));
msg.run ();
return;
}
-
+
PortInsertWindow *io_selector;
-
+
if (port_insert->get_gui() == 0) {
io_selector = new PortInsertWindow (_session, port_insert);
port_insert->set_gui (io_selector);
-
+
} else {
io_selector = reinterpret_cast<PortInsertWindow *> (port_insert->get_gui());
}
-
+
gidget = io_selector;
}
@@ -1164,45 +1185,59 @@ ProcessorBox::register_actions ()
Glib::RefPtr<Action> act;
/* new stuff */
- ActionManager::register_action (popup_act_grp, X_("newplugin"), _("New Plugin"), sigc::ptr_fun (ProcessorBox::rb_choose_plugin));
+ ActionManager::register_action (popup_act_grp, X_("newplugin"), _("New Plugin"),
+ sigc::ptr_fun (ProcessorBox::rb_choose_plugin));
- act = ActionManager::register_action (popup_act_grp, X_("newinsert"), _("New Insert"), sigc::ptr_fun (ProcessorBox::rb_choose_insert));
+ act = ActionManager::register_action (popup_act_grp, X_("newinsert"), _("New Insert"),
+ sigc::ptr_fun (ProcessorBox::rb_choose_insert));
ActionManager::jack_sensitive_actions.push_back (act);
- act = ActionManager::register_action (popup_act_grp, X_("newsend"), _("New Send ..."), sigc::ptr_fun (ProcessorBox::rb_choose_send));
+ act = ActionManager::register_action (popup_act_grp, X_("newsend"), _("New Send ..."),
+ sigc::ptr_fun (ProcessorBox::rb_choose_send));
ActionManager::jack_sensitive_actions.push_back (act);
- ActionManager::register_action (popup_act_grp, X_("clear"), _("Clear"), sigc::ptr_fun (ProcessorBox::rb_clear));
+ ActionManager::register_action (popup_act_grp, X_("clear"), _("Clear"),
+ sigc::ptr_fun (ProcessorBox::rb_clear));
/* standard editing stuff */
- act = ActionManager::register_action (popup_act_grp, X_("cut"), _("Cut"), sigc::ptr_fun (ProcessorBox::rb_cut));
+ act = ActionManager::register_action (popup_act_grp, X_("cut"), _("Cut"),
+ sigc::ptr_fun (ProcessorBox::rb_cut));
ActionManager::plugin_selection_sensitive_actions.push_back(act);
- act = ActionManager::register_action (popup_act_grp, X_("copy"), _("Copy"), sigc::ptr_fun (ProcessorBox::rb_copy));
+ act = ActionManager::register_action (popup_act_grp, X_("copy"), _("Copy"),
+ sigc::ptr_fun (ProcessorBox::rb_copy));
ActionManager::plugin_selection_sensitive_actions.push_back(act);
- act = ActionManager::register_action (popup_act_grp, X_("delete"), _("Delete"), sigc::ptr_fun (ProcessorBox::rb_delete));
+ act = ActionManager::register_action (popup_act_grp, X_("delete"), _("Delete"),
+ sigc::ptr_fun (ProcessorBox::rb_delete));
ActionManager::plugin_selection_sensitive_actions.push_back(act); // ??
- paste_action = ActionManager::register_action (popup_act_grp, X_("paste"), _("Paste"), sigc::ptr_fun (ProcessorBox::rb_paste));
- act = ActionManager::register_action (popup_act_grp, X_("rename"), _("Rename"), sigc::ptr_fun (ProcessorBox::rb_rename));
+ paste_action = ActionManager::register_action (popup_act_grp, X_("paste"), _("Paste"),
+ sigc::ptr_fun (ProcessorBox::rb_paste));
+ act = ActionManager::register_action (popup_act_grp, X_("rename"), _("Rename"),
+ sigc::ptr_fun (ProcessorBox::rb_rename));
ActionManager::plugin_selection_sensitive_actions.push_back(act);
- ActionManager::register_action (popup_act_grp, X_("selectall"), _("Select All"), sigc::ptr_fun (ProcessorBox::rb_select_all));
- ActionManager::register_action (popup_act_grp, X_("deselectall"), _("Deselect All"), sigc::ptr_fun (ProcessorBox::rb_deselect_all));
-
+ ActionManager::register_action (popup_act_grp, X_("selectall"), _("Select All"),
+ sigc::ptr_fun (ProcessorBox::rb_select_all));
+ ActionManager::register_action (popup_act_grp, X_("deselectall"), _("Deselect All"),
+ sigc::ptr_fun (ProcessorBox::rb_deselect_all));
+
/* activation */
- act = ActionManager::register_action (popup_act_grp, X_("activate"), _("Activate"), sigc::ptr_fun (ProcessorBox::rb_activate));
+ act = ActionManager::register_action (popup_act_grp, X_("activate"), _("Activate"),
+ sigc::ptr_fun (ProcessorBox::rb_activate));
ActionManager::plugin_selection_sensitive_actions.push_back(act);
- act = ActionManager::register_action (popup_act_grp, X_("deactivate"), _("Deactivate"), sigc::ptr_fun (ProcessorBox::rb_deactivate));
+ act = ActionManager::register_action (popup_act_grp, X_("deactivate"), _("Deactivate"),
+ sigc::ptr_fun (ProcessorBox::rb_deactivate));
ActionManager::plugin_selection_sensitive_actions.push_back(act);
- ActionManager::register_action (popup_act_grp, X_("activate_all"), _("Activate all"), sigc::ptr_fun (ProcessorBox::rb_activate_all));
- ActionManager::register_action (popup_act_grp, X_("deactivate_all"), _("Deactivate all"), sigc::ptr_fun (ProcessorBox::rb_deactivate_all));
+ ActionManager::register_action (popup_act_grp, X_("activate_all"), _("Activate all"),
+ sigc::ptr_fun (ProcessorBox::rb_activate_all));
+ ActionManager::register_action (popup_act_grp, X_("deactivate_all"), _("Deactivate all"),
+ sigc::ptr_fun (ProcessorBox::rb_deactivate_all));
/* show editors */
- act = ActionManager::register_action (popup_act_grp, X_("edit"), _("Edit"), sigc::ptr_fun (ProcessorBox::rb_edit));
+ act = ActionManager::register_action (popup_act_grp, X_("edit"), _("Edit"),
+ sigc::ptr_fun (ProcessorBox::rb_edit));
ActionManager::plugin_selection_sensitive_actions.push_back(act);
ActionManager::add_action_group (popup_act_grp);
-
-
}
void
@@ -1373,7 +1408,7 @@ ProcessorBox::route_name_changed ()
Gtk::TreeModel::Row row = *iter;
processor= row[columns.processor];
-
+
void* gui = processor->get_gui();
if (!gui) {
@@ -1383,7 +1418,7 @@ ProcessorBox::route_name_changed ()
/* rename editor windows for sends and plugins */
WindowTitle title (Glib::get_application_name());
-
+
if ((send = boost::dynamic_pointer_cast<Send> (processor)) != 0) {
title += send->name();
static_cast<Window*>(gui)->set_title (title.get_string());
@@ -1394,7 +1429,7 @@ ProcessorBox::route_name_changed ()
}
}
-string
+string
ProcessorBox::generate_processor_title (boost::shared_ptr<PluginInsert> pi)
{
string maker = pi->plugin()->maker() ? pi->plugin()->maker() : "";
@@ -1409,6 +1444,6 @@ ProcessorBox::generate_processor_title (boost::shared_ptr<PluginInsert> pi)
maker += " ...";
}
- return string_compose(_("%1: %2 (by %3)"), _route->name(), pi->name(), maker);
+ return string_compose(_("%1: %2 (by %3)"), _route->name(), pi->name(), maker);
}
diff --git a/gtk2_ardour/processor_box.h b/gtk2_ardour/processor_box.h
index 60836ac1f6..ea908133e3 100644
--- a/gtk2_ardour/processor_box.h
+++ b/gtk2_ardour/processor_box.h
@@ -184,8 +184,10 @@ class ProcessorBox : public Gtk::HBox, public PluginInterestedObject
void clear_processors ();
void rename_processors ();
+ typedef vector<boost::shared_ptr<ARDOUR::Processor> > ProcSelection;
+
void for_selected_processors (void (ProcessorBox::*pmf)(boost::shared_ptr<ARDOUR::Processor>));
- void get_selected_processors (vector<boost::shared_ptr<ARDOUR::Processor> >&);
+ void get_selected_processors (ProcSelection&);
static Glib::RefPtr<Gtk::Action> paste_action;
void paste_processor_state (const XMLNodeList&);
diff --git a/gtk2_ardour/time_axis_view.cc b/gtk2_ardour/time_axis_view.cc
index 056135e70c..f62895c6f7 100644
--- a/gtk2_ardour/time_axis_view.cc
+++ b/gtk2_ardour/time_axis_view.cc
@@ -1104,8 +1104,6 @@ TimeAxisView::compute_controls_size_info ()
two_row_table.show_all ();
req = two_row_table.size_request ();
- cerr << "Normal height is " << req.height << " + " << extra_height << endl;
-
// height required to show all normal buttons
hNormal = /*req.height*/ 48 + extra_height;
diff --git a/gtk2_ardour/ui_config.cc b/gtk2_ardour/ui_config.cc
index c6dd70c992..f52ad14277 100644
--- a/gtk2_ardour/ui_config.cc
+++ b/gtk2_ardour/ui_config.cc
@@ -79,7 +79,7 @@ UIConfiguration::load_defaults ()
string rcfile = default_ui_rc_file.to_string();
- cerr << string_compose (_("loading default ui configuration file %1"), rcfile) << endl;
+ cerr << string_compose (_("Loading default ui configuration file %1"), rcfile) << endl;
if (!tree.read (rcfile.c_str())) {
error << string_compose(_("Ardour: cannot read default ui configuration file \"%1\""), rcfile) << endmsg;
@@ -109,7 +109,7 @@ UIConfiguration::load_state ()
string rcfile = default_ui_rc_file.to_string();
- cerr << string_compose (_("loading default ui configuration file %1"), rcfile) << endl;
+ cerr << string_compose (_("Loading default ui configuration file %1"), rcfile) << endl;
if (!tree.read (rcfile.c_str())) {
error << string_compose(_("Ardour: cannot read default ui configuration file \"%1\""), rcfile) << endmsg;
@@ -132,7 +132,7 @@ UIConfiguration::load_state ()
string rcfile = user_ui_rc_file.to_string();
- cerr << string_compose (_("loading user ui configuration file %1"), rcfile) << endl;
+ cerr << string_compose (_("Loading user ui configuration file %1"), rcfile) << endl;
if (!tree.read (rcfile)) {
error << string_compose(_("Ardour: cannot read ui configuration file \"%1\""), rcfile) << endmsg;
diff --git a/libs/ardour/amp.cc b/libs/ardour/amp.cc
index 263ce82086..aa20f3e389 100644
--- a/libs/ardour/amp.cc
+++ b/libs/ardour/amp.cc
@@ -20,23 +20,123 @@
#include <cmath>
#include <algorithm>
#include "ardour/amp.h"
-#include "ardour/buffer_set.h"
#include "ardour/audio_buffer.h"
+#include "ardour/buffer_set.h"
+#include "ardour/configuration.h"
+#include "ardour/io.h"
+#include "ardour/session.h"
namespace ARDOUR {
+Amp::Amp(Session& s, IO& io)
+ : Processor(s, "Amp")
+ , _io(io)
+ , _mute(false)
+ , _apply_gain(true)
+ , _apply_gain_automation(false)
+ , _current_gain(1.0)
+ , _desired_gain(1.0)
+{
+}
+
+bool
+Amp::can_support_io_configuration (const ChanCount& in, ChanCount& out) const
+{
+ out = in;
+ return true;
+}
+
+bool
+Amp::configure_io (ChanCount in, ChanCount out)
+{
+ if (out != in) { // always 1:1
+ return false;
+ }
+
+ return Processor::configure_io (in, out);
+}
+
+void
+Amp::run_in_place (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame, nframes_t nframes)
+{
+ gain_t* gab = _session.gain_automation_buffer();
+
+ 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 (_apply_gain) {
+
+ if (_apply_gain_automation) {
+
+ if (_io.phase_invert()) {
+ 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];
+ }
+ }
+ } 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] *= gab[nx];
+ }
+ }
+ }
+
+ } else { /* manual (scalar) gain */
+
+ if (_current_gain != _desired_gain) {
+
+ Amp::apply_gain (bufs, nframes, _current_gain, _desired_gain, _io.phase_invert());
+ _current_gain = _desired_gain;
+
+ } else if (_current_gain != 0.0f && (_io.phase_invert() || _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_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);
+ }
+
+ } else if (_current_gain == 0.0f) {
+ for (BufferSet::audio_iterator i = bufs.audio_begin(); i != bufs.audio_end(); ++i) {
+ i->clear();
+ }
+ }
+ }
+ }
+}
/** Apply a declicked gain to the audio buffers of @a bufs */
void
-Amp::run_in_place (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, bool invert_polarity)
{
- if (nframes == 0)
+ if (nframes == 0) {
return;
+ }
- if (bufs.count().n_audio() == 0)
+ if (bufs.count().n_audio() == 0) {
return;
-
- // assert(bufs.buffer_capacity(DataType::AUDIO) >= nframes);
+ }
// if we don't need to declick, defer to apply_simple_gain
if (initial == target) {
@@ -98,5 +198,18 @@ Amp::apply_simple_gain (BufferSet& bufs, nframes_t nframes, gain_t target)
{
}
+XMLNode&
+Amp::state (bool full_state)
+{
+ return get_state();
+}
+
+XMLNode&
+Amp::get_state()
+{
+ XMLNode* node = new XMLNode(state_node_name);
+ node->add_property("type", "amp");
+ return *node;
+}
} // namespace ARDOUR
diff --git a/libs/ardour/ardour/amp.h b/libs/ardour/ardour/amp.h
index 402a29542d..fa9de724ad 100644
--- a/libs/ardour/ardour/amp.h
+++ b/libs/ardour/ardour/amp.h
@@ -20,22 +20,63 @@
#define __ardour_amp_h__
#include "ardour/types.h"
+#include "ardour/chan_count.h"
+#include "ardour/processor.h"
namespace ARDOUR {
class BufferSet;
+class IO;
/** Applies a declick operation to all audio inputs, passing the same number of
* audio outputs, and passing through any other types unchanged.
- *
- * FIXME: make this a Processor.
*/
-class Amp {
+class Amp : public Processor {
public:
- static void run_in_place (BufferSet& bufs, nframes_t nframes, gain_t initial, gain_t target, bool invert_polarity);
+ Amp(Session& s, IO& io);
+
+ bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const;
+ bool configure_io (ChanCount in, ChanCount out);
+
+ void run_in_place (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame, nframes_t nframes);
+
+ bool apply_gain() const { return _apply_gain; }
+ void apply_gain(bool yn) { _apply_gain = yn; }
+
+ 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; }
+
+ 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;
+ }
+
+ XMLNode& state (bool full);
+ XMLNode& get_state();
+
+ static void apply_gain (BufferSet& bufs, nframes_t nframes,
+ gain_t initial, gain_t target, bool invert_polarity);
static void apply_simple_gain(BufferSet& bufs, nframes_t nframes, gain_t target);
+
+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;
};
diff --git a/libs/ardour/ardour/audio_track.h b/libs/ardour/ardour/audio_track.h
index 22092b5e1b..484887e0b7 100644
--- a/libs/ardour/ardour/audio_track.h
+++ b/libs/ardour/ardour/audio_track.h
@@ -41,12 +41,6 @@ class AudioTrack : public Track
int roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame,
int declick, bool can_record, bool rec_monitors_input);
-
- int no_roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame,
- bool state_changing, bool can_record, bool rec_monitors_input);
-
- int silent_roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame,
- bool can_record, bool rec_monitors_input);
boost::shared_ptr<AudioDiskstream> audio_diskstream() const;
diff --git a/libs/ardour/ardour/buffer_set.h b/libs/ardour/ardour/buffer_set.h
index 9d7ba6d6ae..3f10929fe8 100644
--- a/libs/ardour/ardour/buffer_set.h
+++ b/libs/ardour/ardour/buffer_set.h
@@ -66,7 +66,10 @@ public:
const ChanCount& count() const { return _count; }
ChanCount& count() { return _count; }
- void set_count(const ChanCount& count) { _count = count; }
+ void is_silent(bool yn) { _is_silent = yn; }
+ bool is_silent() const { return _is_silent; }
+
+ void set_count(const ChanCount& count) { assert(count <= _available); _count = count; }
size_t buffer_capacity(DataType type) const;
@@ -161,6 +164,9 @@ private:
/// Whether we (don't) 'own' the contained buffers (otherwise we mirror a PortSet)
bool _is_mirror;
+
+ /// Whether the buffer set should be considered silent
+ bool _is_silent;
};
diff --git a/libs/ardour/ardour/chan_count.h b/libs/ardour/ardour/chan_count.h
index fb4b1999ca..c9b543c4ba 100644
--- a/libs/ardour/ardour/chan_count.h
+++ b/libs/ardour/ardour/chan_count.h
@@ -23,6 +23,7 @@
#include <cassert>
#include <ostream>
+#include "pbd/xml++.h"
#include "ardour/data_type.h"
namespace ARDOUR {
@@ -35,6 +36,7 @@ namespace ARDOUR {
*/
class ChanCount {
public:
+ ChanCount(const XMLNode& node);
ChanCount() { reset(); }
// Convenience constructor for making single-typed streams (stereo, mono, etc)
@@ -104,6 +106,14 @@ public:
return ( (*this > other) || (*this == other) );
}
+ static ChanCount min(const ChanCount& a, const ChanCount& b) {
+ ChanCount ret;
+ for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
+ ret.set(*t, std::min(a.get(*t), b.get(*t)));
+ }
+ return ret;
+ }
+
static ChanCount max(const ChanCount& a, const ChanCount& b) {
ChanCount ret;
for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
@@ -111,6 +121,8 @@ public:
}
return ret;
}
+
+ XMLNode* state(const std::string& name) const;
static const ChanCount INFINITE;
static const ChanCount ZERO;
diff --git a/libs/ardour/ardour/chan_mapping.h b/libs/ardour/ardour/chan_mapping.h
index 1dae20e34a..5f948a77b0 100644
--- a/libs/ardour/ardour/chan_mapping.h
+++ b/libs/ardour/ardour/chan_mapping.h
@@ -26,6 +26,7 @@
#include <utility>
#include "ardour/data_type.h"
+#include "ardour/chan_count.h"
namespace ARDOUR {
@@ -36,47 +37,26 @@ namespace ARDOUR {
class ChanMapping {
public:
ChanMapping() {}
- ChanMapping(ChanCount identity) {
- for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
- for (size_t i = 0; i <= identity.get(*t); ++i)
- set(*t, i, i);
- }
- }
-
- uint32_t get(DataType t, uint32_t from) {
- Mappings::iterator tm = _mappings.find(t);
- assert(tm != _mappings.end());
- TypeMapping::iterator m = tm->second.find(from);
- assert(m != tm->second.end());
- return m->second;
- }
+ ChanMapping(ARDOUR::ChanCount identity);
+
+ uint32_t get(DataType t, uint32_t from);
+ void set(DataType t, uint32_t from, uint32_t to);
+ void offset_from(DataType t, int32_t delta);
+ void offset_to(DataType t, int32_t delta);
- void set(DataType t, uint32_t from, uint32_t to) {
- Mappings::iterator tm = _mappings.find(t);
- if (tm == _mappings.end()) {
- tm = _mappings.insert(std::make_pair(t, TypeMapping())).first;
- }
- tm->second.insert(std::make_pair(from, to));
- }
-
- /** Increase the 'to' field of every mapping for type @a t by @a delta */
- void offset(DataType t, uint32_t delta) {
- Mappings::iterator tm = _mappings.find(t);
- if (tm != _mappings.end()) {
- for (TypeMapping::iterator m = tm->second.begin(); m != tm->second.end(); ++m) {
- m->second += delta;
- }
- }
- }
-
-private:
typedef std::map<uint32_t, uint32_t> TypeMapping;
typedef std::map<DataType, TypeMapping> Mappings;
+ Mappings mappings() { return _mappings; }
+ const Mappings mappings() const { return _mappings; }
+
+private:
Mappings _mappings;
};
} // namespace ARDOUR
+std::ostream& operator<<(std::ostream& o, const ARDOUR::ChanMapping& m);
+
#endif // __ardour_chan_mapping_h__
diff --git a/libs/ardour/ardour/click.h b/libs/ardour/ardour/click.h
index e50e0a29cb..ae744478f1 100644
--- a/libs/ardour/ardour/click.h
+++ b/libs/ardour/ardour/click.h
@@ -26,17 +26,11 @@ namespace ARDOUR {
class ClickIO : public IO
{
- public:
- ClickIO (Session& s, const string& name,
-
- int input_min = -1, int input_max = -1,
-
- int output_min = -1, int output_max = -1)
- : IO (s, name, input_min, input_max, output_min, output_max) {}
-
+public:
+ ClickIO (Session& s, const string& name) : IO (s, name) {}
~ClickIO() {}
- protected:
+protected:
uint32_t pans_required () const { return 1; }
};
diff --git a/libs/ardour/ardour/control_outputs.h b/libs/ardour/ardour/control_outputs.h
new file mode 100644
index 0000000000..72d9534ddf
--- /dev/null
+++ b/libs/ardour/ardour/control_outputs.h
@@ -0,0 +1,55 @@
+/*
+ Copyright (C) 2006 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_control_outputs_h__
+#define __ardour_control_outputs_h__
+
+#include <string>
+#include "ardour/types.h"
+#include "ardour/chan_count.h"
+#include "ardour/io_processor.h"
+
+namespace ARDOUR {
+
+class BufferSet;
+class IO;
+
+class ControlOutputs : public IOProcessor {
+public:
+ ControlOutputs(Session& s, IO* io);
+
+ bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const;
+ bool configure_io (ChanCount in, ChanCount out);
+
+ void run_in_place (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame, nframes_t nframes);
+
+ bool deliver() const { return _deliver; }
+ void deliver(bool yn) { _deliver = yn; }
+
+ XMLNode& state (bool full);
+ XMLNode& get_state();
+
+private:
+ bool _deliver;
+};
+
+
+} // namespace ARDOUR
+
+#endif // __ardour_control_outputs_h__
+
diff --git a/libs/ardour/ardour/io.h b/libs/ardour/ardour/io.h
index 8457668756..3e36d10be3 100644
--- a/libs/ardour/ardour/io.h
+++ b/libs/ardour/ardour/io.h
@@ -52,32 +52,31 @@ class XMLNode;
namespace ARDOUR {
-class Session;
+class Amp;
class AudioEngine;
-class UserBundle;
+class AudioPort;
+class BufferSet;
class Bundle;
+class MidiPort;
class Panner;
class PeakMeter;
class Port;
-class AudioPort;
-class MidiPort;
-class BufferSet;
+class Session;
+class UserBundle;
/** A collection of input and output ports 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
{
public:
static const string state_node_name;
- IO (Session&, const string& name,
- int input_min = -1, int input_max = -1,
- int output_min = -1, int output_max = -1,
- DataType default_type = DataType::AUDIO);
+ IO (Session&, const string& name, DataType default_type = DataType::AUDIO,
+ ChanCount in_min=ChanCount::ZERO, ChanCount in_max=ChanCount::INFINITE,
+ ChanCount out_min=ChanCount::ZERO, ChanCount out_max=ChanCount::INFINITE);
IO (Session&, const XMLNode&, DataType default_type = DataType::AUDIO);
@@ -109,7 +108,7 @@ class IO : public SessionObject, public AutomatableControls, public Latent
BufferSet& output_buffers() { return *_output_buffers; }
- gain_t gain () const { return _desired_gain; }
+ gain_t gain () const { return _gain_control->user_float(); }
virtual gain_t effective_gain () const;
void set_denormal_protection (bool yn, void *src);
@@ -118,11 +117,16 @@ class IO : public SessionObject, public AutomatableControls, public Latent
void set_phase_invert (bool yn, void *src);
bool phase_invert() const { return _phase_invert; }
- Panner& panner() { return *_panner; }
- PeakMeter& peak_meter() { return *_meter; }
- const Panner& panner() const { return *_panner; }
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 connect_input_ports_to_bundle (boost::shared_ptr<Bundle>, void *);
@@ -133,8 +137,8 @@ class IO : public SessionObject, public AutomatableControls, public Latent
BundleList bundles_connected_to_inputs ();
BundleList bundles_connected_to_outputs ();
- 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_for_inputs () { return _bundle_for_inputs; }
+ boost::shared_ptr<Bundle> bundle_for_outputs () { return _bundle_for_outputs; }
int add_input_port (string source, void *src, DataType type = DataType::NIL);
int add_output_port (string destination, void *src, DataType type = DataType::NIL);
@@ -271,22 +275,24 @@ class IO : public SessionObject, public AutomatableControls, public Latent
mutable Glib::Mutex io_lock;
protected:
- Panner* _panner;
BufferSet* _output_buffers; //< Set directly to output port buffers
bool _active;
gain_t _gain;
- gain_t _effective_gain;
- gain_t _desired_gain;
Glib::Mutex declick_lock;
PortSet _outputs;
PortSet _inputs;
- PeakMeter* _meter;
bool no_panner_reset;
bool _phase_invert;
bool _denormal_protection;
XMLNode* deferred_state;
DataType _default_type;
nframes_t _output_offset;
+ ChanCount _configured_inputs;
+ ChanCount _configured_outputs;
+
+ 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);
@@ -301,8 +307,6 @@ class IO : public SessionObject, public AutomatableControls, public Latent
virtual void set_gain (gain_t g, void *src);
void inc_gain (gain_t delta, void *src);
- bool apply_gain_automation;
-
virtual int load_automation (std::string path);
/* AudioTrack::deprecated_use_diskstream_connections() needs these */
@@ -361,6 +365,7 @@ class IO : public SessionObject, public AutomatableControls, public Latent
void bundle_changed (Bundle::Change);
+ int get_port_counts (const XMLNode& node);
int create_ports (const XMLNode&);
int make_connections (const XMLNode&);
boost::shared_ptr<Bundle> find_possible_bundle (const string &desired_name, const string &default_name, const string &connection_type_name);
diff --git a/libs/ardour/ardour/io_processor.h b/libs/ardour/ardour/io_processor.h
index 1a12a3271e..e7dffb3138 100644
--- a/libs/ardour/ardour/io_processor.h
+++ b/libs/ardour/ardour/io_processor.h
@@ -45,8 +45,9 @@ class IO;
class IOProcessor : public Processor
{
public:
- IOProcessor (Session&, const string& name, Placement,
- int input_min = -1, int input_max = -1, int output_min = -1, int output_max = -1,
+ IOProcessor (Session&, const string& proc_name, const string io_name="",
+ ARDOUR::DataType default_type = DataType::AUDIO);
+ IOProcessor (Session&, IO* io, const string& proc_name,
ARDOUR::DataType default_type = DataType::AUDIO);
virtual ~IOProcessor ();
diff --git a/libs/ardour/ardour/meter.h b/libs/ardour/ardour/meter.h
index 972e1b6760..0a49ddf99f 100644
--- a/libs/ardour/ardour/meter.h
+++ b/libs/ardour/ardour/meter.h
@@ -35,12 +35,12 @@ class Session;
*/
class PeakMeter : public Processor {
public:
- PeakMeter(Session& s) : Processor(s, "meter", PreFader) {}
+ PeakMeter(Session& s) : Processor(s, "Meter") {}
void reset ();
void reset_max ();
- bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const { return true; }
+ bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const;
bool configure_io (ChanCount in, ChanCount out);
/** Compute peaks */
@@ -61,11 +61,11 @@ public:
return minus_infinity();
}
}
+
+ XMLNode& state (bool full);
+ XMLNode& get_state();
private:
- /* disallow copy construction */
- PeakMeter (PeakMeter const &);
-
friend class IO;
void meter();
diff --git a/libs/ardour/ardour/midi_track.h b/libs/ardour/ardour/midi_track.h
index 424b9d2c92..fe8290d5d9 100644
--- a/libs/ardour/ardour/midi_track.h
+++ b/libs/ardour/ardour/midi_track.h
@@ -41,17 +41,6 @@ public:
int roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame,
int declick, bool can_record, bool rec_monitors_input);
- int no_roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame,
- bool state_changing, bool can_record, bool rec_monitors_input);
-
- int silent_roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame,
- bool can_record, bool rec_monitors_input);
-
- void process_output_buffers (BufferSet& bufs,
- nframes_t start_frame, nframes_t end_frame,
- nframes_t nframes, bool with_redirects, int declick,
- bool meter);
-
boost::shared_ptr<MidiDiskstream> midi_diskstream() const;
int use_diskstream (string name);
diff --git a/libs/ardour/ardour/panner.h b/libs/ardour/ardour/panner.h
index 9e54696048..dcb34c8a04 100644
--- a/libs/ardour/ardour/panner.h
+++ b/libs/ardour/ardour/panner.h
@@ -205,7 +205,7 @@ class Panner : public Processor
virtual ~Panner ();
void clear_panners ();
-
+ bool empty() const { return _streampanners.empty(); }
/// The fundamental Panner function
void set_automation_state (AutoState);
diff --git a/libs/ardour/ardour/plugin_insert.h b/libs/ardour/ardour/plugin_insert.h
index 99bd492ab5..89512df40c 100644
--- a/libs/ardour/ardour/plugin_insert.h
+++ b/libs/ardour/ardour/plugin_insert.h
@@ -44,7 +44,7 @@ class Plugin;
class PluginInsert : public Processor
{
public:
- PluginInsert (Session&, boost::shared_ptr<Plugin>, Placement);
+ PluginInsert (Session&, boost::shared_ptr<Plugin>);
PluginInsert (Session&, const XMLNode&);
~PluginInsert ();
diff --git a/libs/ardour/ardour/port_insert.h b/libs/ardour/ardour/port_insert.h
index 27d251cc45..076e4af9d1 100644
--- a/libs/ardour/ardour/port_insert.h
+++ b/libs/ardour/ardour/port_insert.h
@@ -40,7 +40,7 @@ class Session;
class PortInsert : public IOProcessor
{
public:
- PortInsert (Session&, Placement);
+ PortInsert (Session&);
PortInsert (Session&, const XMLNode&);
~PortInsert ();
diff --git a/libs/ardour/ardour/processor.h b/libs/ardour/ardour/processor.h
index 1167930d61..547cc87f88 100644
--- a/libs/ardour/ardour/processor.h
+++ b/libs/ardour/ardour/processor.h
@@ -49,16 +49,21 @@ class Processor : public SessionObject, public AutomatableControls, public Laten
public:
static const string state_node_name;
- Processor(Session&, const string& name, Placement p); // TODO: remove placement (use sort key)
+ Processor(Session&, const string& name);
virtual ~Processor() { }
+ /** Configuration of a processor on a bus
+ * (i.e. how to apply to a BufferSet)
+ */
+ struct Mapping {
+ ChanCount in;
+ ChanCount out;
+ };
+
uint32_t sort_key() const { return _sort_key; }
void set_sort_key (uint32_t key);
- Placement placement() const { return _placement; }
- void set_placement (Placement);
-
bool active () const { return _active; }
bool get_next_ab_is_active () const { return _next_ab_is_active; }
@@ -108,7 +113,6 @@ class Processor : public SessionObject, public AutomatableControls, public Laten
static sigc::signal<void,Processor*> ProcessorCreated;
sigc::signal<void> ActiveChanged;
- sigc::signal<void> PlacementChanged;
sigc::signal<void,ChanCount,ChanCount> ConfigurationChanged;
protected:
@@ -118,9 +122,9 @@ protected:
bool _configured;
ChanCount _configured_input;
ChanCount _configured_output;
- Placement _placement;
uint32_t _sort_key;
void* _gui; /* generic, we don't know or care what this is */
+ Mapping _mapping;
};
} // namespace ARDOUR
diff --git a/libs/ardour/ardour/route.h b/libs/ardour/ardour/route.h
index 6926dbd036..2b54810577 100644
--- a/libs/ardour/ardour/route.h
+++ b/libs/ardour/ardour/route.h
@@ -44,10 +44,12 @@
namespace ARDOUR {
-class Processor;
+class Amp;
+class ControlOutputs;
class IOProcessor;
-class Send;
+class Processor;
class RouteGroup;
+class Send;
enum mute_type {
PRE_FADER = 0x1,
@@ -70,8 +72,10 @@ class Route : public IO
ControlOut = 0x4
};
- Route (Session&, std::string name, int input_min, int input_max, int output_min, int output_max,
- Flag flags = Flag(0), DataType default_type = DataType::AUDIO);
+ Route (Session&, std::string name, Flag flags = Flag(0),
+ DataType default_type = DataType::AUDIO,
+ ChanCount in=ChanCount::ZERO, ChanCount out=ChanCount::ZERO);
+
Route (Session&, const XMLNode&, DataType default_type = DataType::AUDIO);
virtual ~Route();
@@ -149,6 +153,15 @@ class Route : public IO
method (boost::weak_ptr<Processor> (*i));
}
}
+
+ void foreach_processor (Placement p, sigc::slot<void, boost::weak_ptr<Processor> > method) {
+ Glib::RWLock::ReaderLock lm (_processor_lock);
+ ProcessorList::iterator start, end;
+ placement_range(p, start, end);
+ for (ProcessorList::iterator i = start; i != end; ++i) {
+ method (boost::weak_ptr<Processor> (*i));
+ }
+ }
boost::shared_ptr<Processor> nth_processor (uint32_t n) {
Glib::RWLock::ReaderLock lm (_processor_lock);
@@ -170,12 +183,12 @@ class Route : public IO
struct ProcessorStreams {
ProcessorStreams(size_t i=0, ChanCount c=ChanCount()) : index(i), count(c) {}
- size_t index; ///< Index of processor where configuration failed
+ uint32_t index; ///< Index of processor where configuration failed
ChanCount count; ///< Input requested of processor
};
- int add_processor (boost::shared_ptr<Processor>, ProcessorStreams* err = 0);
- int add_processors (const ProcessorList&, ProcessorStreams* err = 0);
+ int add_processor (boost::shared_ptr<Processor>, ProcessorStreams* err = 0, ProcessorList::iterator* iter=0, Placement=PreFader);
+ int add_processors (const ProcessorList&, ProcessorStreams* err = 0, Placement placement=PreFader);
int remove_processor (boost::shared_ptr<Processor>, ProcessorStreams* err = 0);
int sort_processors (ProcessorStreams* err = 0);
void disable_processors (Placement);
@@ -226,7 +239,7 @@ class Route : public IO
sigc::signal<void,void*> SelectedChanged;
int set_control_outs (const vector<std::string>& ports);
- IO* control_outs() { return _control_outs; }
+ boost::shared_ptr<ControlOutputs> control_outs() { return _control_outs; }
bool feeds (boost::shared_ptr<Route>);
std::set<boost::shared_ptr<Route> > fed_by;
@@ -276,12 +289,11 @@ class Route : public IO
nframes_t check_initial_delay (nframes_t, nframes_t&);
void passthru (nframes_t start_frame, nframes_t end_frame,
- nframes_t nframes, int declick, bool meter_inputs);
+ nframes_t nframes, int declick);
virtual void process_output_buffers (BufferSet& bufs,
nframes_t start_frame, nframes_t end_frame,
- nframes_t nframes, bool with_processors, int declick,
- bool meter);
+ nframes_t nframes, bool with_processors, int declick);
Flag _flags;
int _pending_declick;
@@ -296,8 +308,7 @@ class Route : public IO
nframes_t _roll_delay;
ProcessorList _processors;
Glib::RWLock _processor_lock;
- IO *_control_outs;
- Glib::Mutex _control_outs_lock;
+ boost::shared_ptr<ControlOutputs> _control_outs;
RouteGroup *_edit_group;
RouteGroup *_mix_group;
std::string _comment;
@@ -326,8 +337,7 @@ class Route : public IO
virtual XMLNode& state(bool);
void passthru_silence (nframes_t start_frame, nframes_t end_frame,
- nframes_t nframes, int declick,
- bool meter);
+ nframes_t nframes, int declick);
void silence (nframes_t nframes);
@@ -361,24 +371,18 @@ class Route : public IO
void input_change_handler (IOChange, void *src);
void output_change_handler (IOChange, void *src);
- int reset_processor_counts (ProcessorStreams*); /* locked */
- int _reset_processor_counts (ProcessorStreams*); /* unlocked */
-
- /** processor I/O channels and plugin count handling */
- struct ProcessorCount {
- boost::shared_ptr<ARDOUR::Processor> processor;
- ChanCount in;
- ChanCount out;
+ bool _in_configure_processors;
- ProcessorCount (boost::shared_ptr<ARDOUR::Processor> ins) : processor(ins) {}
- };
+ int configure_processors (ProcessorStreams*);
+ int configure_processors_unlocked (ProcessorStreams*);
- int32_t apply_some_processor_counts (std::list<ProcessorCount>& iclist);
- bool check_some_processor_counts (std::list<ProcessorCount>& iclist,
- ChanCount required_inputs, ProcessorStreams* err_streams);
-
void set_deferred_state ();
- void add_processor_from_xml (const XMLNode&);
+ bool add_processor_from_xml (const XMLNode&, ProcessorList::iterator* iter=0);
+
+ void placement_range(
+ Placement p,
+ ProcessorList::iterator& start,
+ ProcessorList::iterator& end);
};
} // namespace ARDOUR
diff --git a/libs/ardour/ardour/send.h b/libs/ardour/ardour/send.h
index 2e7d2c239c..77bb6d9017 100644
--- a/libs/ardour/ardour/send.h
+++ b/libs/ardour/ardour/send.h
@@ -34,7 +34,7 @@ namespace ARDOUR {
class Send : public IOProcessor
{
public:
- Send (Session&, Placement);
+ Send (Session&);
Send (Session&, const XMLNode&);
virtual ~Send ();
diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h
index 8bef24a7e2..1e3855c308 100644
--- a/libs/ardour/ardour/session.h
+++ b/libs/ardour/ardour/session.h
@@ -255,6 +255,7 @@ class Session : public PBD::StatefulDestructible, public boost::noncopyable
void set_clean ();
bool dirty() const { return _state_of_the_state & Dirty; }
void set_deletion_in_progress ();
+ void clear_deletion_in_progress ();
bool deletion_in_progress() const { return _state_of_the_state & Deletion; }
sigc::signal<void> DirtyChanged;
diff --git a/libs/ardour/ardour/track.h b/libs/ardour/ardour/track.h
index 29a4aa8e25..96826e3eaa 100644
--- a/libs/ardour/ardour/track.h
+++ b/libs/ardour/ardour/track.h
@@ -44,16 +44,16 @@ class Track : public Route
virtual int set_mode (TrackMode m) { return false; }
virtual bool can_use_mode (TrackMode m, bool& bounce_required) { return false; }
sigc::signal<void> TrackModeChanged;
+
+ int no_roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame,
+ bool state_changing, bool can_record, bool rec_monitors_input);
+
+ int silent_roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame,
+ bool can_record, bool rec_monitors_input);
virtual int roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame,
int declick, bool can_record, bool rec_monitors_input) = 0;
- virtual int no_roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame,
- bool state_changing, bool can_record, bool rec_monitors_input) = 0;
-
- virtual int silent_roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame,
- bool can_record, bool rec_monitors_input) = 0;
-
void toggle_monitor_input ();
bool can_record();
diff --git a/libs/ardour/audio_diskstream.cc b/libs/ardour/audio_diskstream.cc
index 5c73d826bf..bb74d5fc16 100644
--- a/libs/ardour/audio_diskstream.cc
+++ b/libs/ardour/audio_diskstream.cc
@@ -2172,7 +2172,8 @@ AudioDiskstream::set_block_size (nframes_t nframes)
boost::shared_ptr<ChannelList> c = channels.reader();
for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan) {
- if ((*chan)->speed_buffer) delete [] (*chan)->speed_buffer;
+ if ((*chan)->speed_buffer)
+ delete [] (*chan)->speed_buffer;
(*chan)->speed_buffer = new Sample[speed_buffer_size];
}
}
@@ -2195,9 +2196,11 @@ AudioDiskstream::allocate_temporary_buffers ()
boost::shared_ptr<ChannelList> c = channels.reader();
for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan) {
- if ((*chan)->playback_wrap_buffer) delete [] (*chan)->playback_wrap_buffer;
+ if ((*chan)->playback_wrap_buffer)
+ delete [] (*chan)->playback_wrap_buffer;
(*chan)->playback_wrap_buffer = new Sample[required_wrap_size];
- if ((*chan)->capture_wrap_buffer) delete [] (*chan)->capture_wrap_buffer;
+ if ((*chan)->capture_wrap_buffer)
+ delete [] (*chan)->capture_wrap_buffer;
(*chan)->capture_wrap_buffer = new Sample[required_wrap_size];
}
@@ -2270,7 +2273,7 @@ int
AudioDiskstream::remove_channel_from (boost::shared_ptr<ChannelList> c, uint32_t how_many)
{
while (how_many-- && !c->empty()) {
- delete c->back();
+ //delete c->back(); // FIXME: crash (thread safe with RCU?)
c->pop_back();
}
diff --git a/libs/ardour/audio_track.cc b/libs/ardour/audio_track.cc
index d814709798..79b1240ab0 100644
--- a/libs/ardour/audio_track.cc
+++ b/libs/ardour/audio_track.cc
@@ -26,22 +26,23 @@
#include "evoral/Curve.hpp"
-#include "ardour/audio_track.h"
+#include "ardour/amp.h"
+#include "ardour/audio_buffer.h"
#include "ardour/audio_diskstream.h"
-#include "ardour/session.h"
-#include "ardour/io_processor.h"
+#include "ardour/audio_track.h"
+#include "ardour/audioplaylist.h"
#include "ardour/audioregion.h"
#include "ardour/audiosource.h"
+#include "ardour/buffer_set.h"
+#include "ardour/io_processor.h"
+#include "ardour/panner.h"
+#include "ardour/playlist_factory.h"
+#include "ardour/plugin_insert.h"
+#include "ardour/processor.h"
#include "ardour/region_factory.h"
#include "ardour/route_group_specialized.h"
-#include "ardour/processor.h"
-#include "ardour/plugin_insert.h"
-#include "ardour/audioplaylist.h"
-#include "ardour/playlist_factory.h"
-#include "ardour/panner.h"
+#include "ardour/session.h"
#include "ardour/utils.h"
-#include "ardour/buffer_set.h"
-#include "ardour/audio_buffer.h"
#include "i18n.h"
using namespace std;
@@ -145,7 +146,7 @@ AudioTrack::deprecated_use_diskstream_connections ()
if ((prop = node.property ("gain")) != 0) {
set_gain (atof (prop->value().c_str()), this);
- _gain = _desired_gain;
+ _gain = _gain_control->user_float();
}
if ((prop = node.property ("input-connection")) != 0) {
@@ -452,91 +453,6 @@ AudioTrack::set_state_part_two ()
return;
}
-int
-AudioTrack::no_roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame,
- bool session_state_changing, bool can_record, bool rec_monitors_input)
-{
- if (n_outputs().n_total() == 0) {
- return 0;
- }
-
- if (!_active) {
- silence (nframes);
- return 0;
- }
-
- if (session_state_changing) {
-
- /* XXX is this safe to do against transport state changes? */
-
- passthru_silence (start_frame, end_frame, nframes, 0, false);
- return 0;
- }
-
- audio_diskstream()->check_record_status (start_frame, nframes, can_record);
-
- bool send_silence;
-
- if (_have_internal_generator) {
- /* since the instrument has no input streams,
- there is no reason to send any signal
- into the route.
- */
- send_silence = true;
- } else {
-
- if (!Config->get_tape_machine_mode()) {
- /*
- ADATs work in a strange way..
- they monitor input always when stopped.and auto-input is engaged.
- */
- if ((Config->get_monitoring_model() == SoftwareMonitoring) && (Config->get_auto_input () || _diskstream->record_enabled())) {
- send_silence = false;
- } else {
- send_silence = true;
- }
- } else {
- /*
- Other machines switch to input on stop if the track is record enabled,
- regardless of the auto input setting (auto input only changes the
- monitoring state when the transport is rolling)
- */
- if ((Config->get_monitoring_model() == SoftwareMonitoring) && _diskstream->record_enabled()) {
- send_silence = false;
- } else {
- send_silence = true;
- }
- }
- }
-
- apply_gain_automation = false;
-
- if (send_silence) {
-
- /* if we're sending silence, but we want the meters to show levels for the signal,
- meter right here.
- */
-
- if (_have_internal_generator) {
- passthru_silence (start_frame, end_frame, nframes, 0, true);
- } else {
- if (_meter_point == MeterInput) {
- just_meter_input (start_frame, end_frame, nframes);
- }
- passthru_silence (start_frame, end_frame, nframes, 0, false);
- }
-
- } else {
-
- /* we're sending signal, but we may still want to meter the input.
- */
-
- passthru (start_frame, end_frame, nframes, 0, (_meter_point == MeterInput));
- }
-
- return 0;
-}
-
int
AudioTrack::roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame, int declick,
bool can_record, bool rec_monitors_input)
@@ -580,7 +496,7 @@ AudioTrack::roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame,
}
_silent = false;
- apply_gain_automation = false;
+ _amp->apply_gain_automation(false);
if ((dret = diskstream->process (transport_frame, nframes, can_record, rec_monitors_input)) != 0) {
silence (nframes);
@@ -599,7 +515,7 @@ AudioTrack::roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame,
at least potentially (depending on monitoring options)
*/
- passthru (start_frame, end_frame, nframes, 0, true);
+ passthru (start_frame, end_frame, nframes, false);
} else if ((b = diskstream->playback_buffer(0)) != 0) {
@@ -691,11 +607,13 @@ AudioTrack::roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame,
Glib::Mutex::Lock am (data().control_lock(), Glib::TRY_LOCK);
if (am.locked() && gain_control()->automation_playback()) {
- apply_gain_automation = gain_control()->list()->curve().rt_safe_get_vector (start_frame, end_frame, _session.gain_automation_buffer(), nframes);
+ _amp->apply_gain_automation(
+ gain_control()->list()->curve().rt_safe_get_vector (
+ start_frame, end_frame, _session.gain_automation_buffer(), nframes));
}
}
- process_output_buffers (bufs, start_frame, end_frame, nframes, (!_session.get_record_enabled() || !Config->get_do_not_record_plugins()), declick, (_meter_point != MeterInput));
+ process_output_buffers (bufs, start_frame, end_frame, nframes, (!_session.get_record_enabled() || !Config->get_do_not_record_plugins()), declick);
} else {
/* problem with the diskstream; just be quiet for a bit */
@@ -706,35 +624,11 @@ AudioTrack::roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame,
}
int
-AudioTrack::silent_roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame,
- bool can_record, bool rec_monitors_input)
-{
- if (n_outputs().n_total() == 0 && _processors.empty()) {
- return 0;
- }
-
- if (!_active) {
- silence (nframes);
- return 0;
- }
-
- _silent = true;
- apply_gain_automation = false;
-
- silence (nframes);
-
- return audio_diskstream()->process (_session.transport_frame(), nframes, can_record, rec_monitors_input);
-}
-
-int
AudioTrack::export_stuff (BufferSet& buffers, nframes_t start, nframes_t nframes, bool enable_processing)
{
- gain_t gain_automation[nframes];
gain_t gain_buffer[nframes];
float mix_buffer[nframes];
ProcessorList::iterator i;
- bool post_fader_work = false;
- gain_t this_gain = _gain;
boost::shared_ptr<AudioDiskstream> diskstream = audio_diskstream();
Glib::RWLock::ReaderLock rlock (_processor_lock);
@@ -767,8 +661,9 @@ AudioTrack::export_stuff (BufferSet& buffers, nframes_t start, nframes_t nframes
}
// If no processing is required, there's no need to go any further.
- if (!enable_processing)
+ if (!enable_processing) {
return 0;
+ }
/* note: only run processors during export. other layers in the machinery
will already have checked that there are no external port processors.
@@ -776,57 +671,11 @@ AudioTrack::export_stuff (BufferSet& buffers, nframes_t start, nframes_t nframes
for (i = _processors.begin(); i != _processors.end(); ++i) {
boost::shared_ptr<Processor> processor;
-
if ((processor = boost::dynamic_pointer_cast<Processor>(*i)) != 0) {
- switch (processor->placement()) {
- case PreFader:
- processor->run_in_place (buffers, start, start+nframes, nframes);
- break;
- case PostFader:
- post_fader_work = true;
- break;
- }
+ processor->run_in_place (buffers, start, start+nframes, nframes);
}
}
- if (gain_control()->automation_state() == Play) {
-
- gain_control()->list()->curve().get_vector (start, start + nframes, gain_automation, nframes);
-
- for (BufferSet::audio_iterator bi = buffers.audio_begin(); bi != buffers.audio_end(); ++bi) {
- Sample *b = bi->data();
- for (nframes_t n = 0; n < nframes; ++n) {
- b[n] *= gain_automation[n];
- }
- }
-
- } else {
-
- for (BufferSet::audio_iterator bi = buffers.audio_begin(); bi != buffers.audio_end(); ++bi) {
- Sample *b = bi->data();
- for (nframes_t n = 0; n < nframes; ++n) {
- b[n] *= this_gain;
- }
- }
- }
-
- if (post_fader_work) {
-
- for (i = _processors.begin(); i != _processors.end(); ++i) {
- boost::shared_ptr<PluginInsert> processor;
-
- if ((processor = boost::dynamic_pointer_cast<PluginInsert>(*i)) != 0) {
- switch ((*i)->placement()) {
- case PreFader:
- break;
- case PostFader:
- processor->run_in_place (buffers, start, start+nframes, nframes);
- break;
- }
- }
- }
- }
-
return 0;
}
diff --git a/libs/ardour/audioengine.cc b/libs/ardour/audioengine.cc
index 51a6ae71fb..91cea6ba71 100644
--- a/libs/ardour/audioengine.cc
+++ b/libs/ardour/audioengine.cc
@@ -469,6 +469,8 @@ AudioEngine::jack_bufsize_callback (nframes_t nframes)
{
_buffer_size = nframes;
_raw_buffer_sizes[DataType::AUDIO] = nframes * sizeof(float);
+ cout << "FIXME: Assuming maximum MIDI buffer size " << nframes * 4 << "bytes" << endl;
+ _raw_buffer_sizes[DataType::MIDI] = nframes * 4;
_usecs_per_cycle = (int) floor ((((double) nframes / frame_rate())) * 1000000.0);
last_monitor_check = 0;
@@ -604,13 +606,14 @@ AudioEngine::register_port (DataType dtype, const string& portname, bool input)
} else if (dtype == DataType::MIDI) {
newport = new MidiPort (portname, (input ? Port::IsInput : Port::IsOutput));
} else {
- throw unknown_type();
+ throw PortRegistrationFailure("unable to create port (unknown type)");
}
size_t& old_buffer_size = _raw_buffer_sizes[newport->type()];
size_t port_buffer_size = newport->raw_buffer_size(0);
- if (port_buffer_size > old_buffer_size)
+ if (port_buffer_size > old_buffer_size) {
old_buffer_size = port_buffer_size;
+ }
RCUWriter<Ports> writer (ports);
boost::shared_ptr<Ports> ps = writer.get_copy ();
@@ -621,8 +624,13 @@ AudioEngine::register_port (DataType dtype, const string& portname, bool input)
return newport;
}
- catch (...) {
- throw PortRegistrationFailure("unable to create port (unknown type?)");
+ catch (PortRegistrationFailure& err) {
+ throw err;
+ } catch (std::exception& e) {
+ throw PortRegistrationFailure(string_compose(
+ _("unable to create port: %1"), e.what()).c_str());
+ } catch (...) {
+ throw PortRegistrationFailure("unable to create port (unknown error)");
}
}
@@ -1256,6 +1264,10 @@ AudioEngine::reconnect_to_jack ()
nframes_t blocksize = jack_get_buffer_size (_jack);
session->set_block_size (blocksize);
session->set_frame_rate (jack_get_sample_rate (_jack));
+
+ _raw_buffer_sizes[DataType::AUDIO] = blocksize * sizeof(float);
+ cout << "FIXME: Assuming maximum MIDI buffer size " << blocksize * 4 << "bytes" << endl;
+ _raw_buffer_sizes[DataType::MIDI] = blocksize * 4;
}
last_monitor_check = 0;
diff --git a/libs/ardour/automatable.cc b/libs/ardour/automatable.cc
index c43623b358..0fa4e9c67a 100644
--- a/libs/ardour/automatable.cc
+++ b/libs/ardour/automatable.cc
@@ -242,7 +242,6 @@ Automatable::set_automation_state (const XMLNode& node, Evoral::Parameter legacy
boost::shared_ptr<Evoral::Control> newcontrol = control_factory(param);
add_control(newcontrol);
newcontrol->set_list(al);
- warning << "Control did not exist";
}
} else {
@@ -268,7 +267,9 @@ Automatable::get_automation_state ()
for (Controls::iterator li = controls().begin(); li != controls().end(); ++li) {
boost::shared_ptr<AutomationList> l
= boost::dynamic_pointer_cast<AutomationList>(li->second->list());
- node->add_child_nocopy (l->get_state ());
+ if (!l->empty()) {
+ node->add_child_nocopy (l->get_state ());
+ }
}
return *node;
@@ -410,7 +411,12 @@ Automatable::control_factory(const Evoral::Parameter& param)
} else if (param.type() == GainAutomation) {
control = new IO::GainControl( X_("gaincontrol"), (IO*)this, param);
} else if (param.type() == PanAutomation) {
- control = new Panner::PanControllable( ((Panner *)this)->session(), X_("panner"), *(Panner *)this, param);
+ Panner* me = dynamic_cast<Panner*>(this);
+ if (me) {
+ control = new Panner::PanControllable(me->session(), X_("panner"), *me, param);
+ } else {
+ cerr << "ERROR: PanAutomation for non-Panner" << endl;
+ }
} else {
control = new AutomationControl(_a_session, param);
}
diff --git a/libs/ardour/buffer_set.cc b/libs/ardour/buffer_set.cc
index 545d980178..005a4dae65 100644
--- a/libs/ardour/buffer_set.cc
+++ b/libs/ardour/buffer_set.cc
@@ -34,6 +34,7 @@ namespace ARDOUR {
/** Create a new, empty BufferSet */
BufferSet::BufferSet()
: _is_mirror(false)
+ , _is_silent(false)
{
for (size_t i=0; i < DataType::num_types; ++i) {
_buffers.push_back(BufferVec());
@@ -84,6 +85,7 @@ BufferSet::attach_buffers(PortSet& ports, nframes_t nframes, nframes_t offset)
}
_count = ports.count();
+ _available = ports.count();
_is_mirror = true;
}
@@ -97,8 +99,9 @@ BufferSet::ensure_buffers(DataType type, size_t num_buffers, size_t buffer_capac
assert(type != DataType::NIL);
assert(type < _buffers.size());
- if (num_buffers == 0)
+ if (num_buffers == 0) {
return;
+ }
// The vector of buffers of the type we care about
BufferVec& bufs = _buffers[type];
@@ -132,7 +135,7 @@ BufferSet::ensure_buffers(DataType type, size_t num_buffers, size_t buffer_capac
#ifdef HAVE_SLV2
// Ensure enough low level MIDI format buffers are available for conversion
// in both directions (input & output, out-of-place)
- if (type == DataType::MIDI && _lv2_buffers.size() < _buffers[type].size() * 2) {
+ if (type == DataType::MIDI && _lv2_buffers.size() < _buffers[type].size() * 2 + 1) {
while (_lv2_buffers.size() < _buffers[type].size() * 2) {
_lv2_buffers.push_back(std::make_pair(false, new LV2EventBuffer(buffer_capacity)));
}
@@ -160,7 +163,7 @@ BufferSet::buffer_capacity(DataType type) const
Buffer&
BufferSet::get(DataType type, size_t i)
{
- assert(i <= _count.get(type));
+ assert(i < _available.get(type));
return *_buffers[type][i];
}
diff --git a/libs/ardour/chan_count.cc b/libs/ardour/chan_count.cc
index 1c892c1a87..e60104dad8 100644
--- a/libs/ardour/chan_count.cc
+++ b/libs/ardour/chan_count.cc
@@ -22,11 +22,28 @@
#include <stdint.h>
#include "ardour/chan_count.h"
+#include "i18n.h"
+
+static const char* state_node_name = "Channels";
+
namespace ARDOUR {
// infinite/zero chan count stuff, for setting minimums and maximums, etc.
// FIXME: implement this in a less fugly way
+ChanCount::ChanCount(const XMLNode& node)
+{
+ reset();
+ XMLNodeConstIterator iter = node.children().begin();
+ for ( ; iter != node.children().end(); ++iter) {
+ if ((*iter)->name() == X_(state_node_name)) {
+ const string& type_str = (*iter)->property("type")->value();
+ const string& count_str = (*iter)->property("count")->value();
+ set(DataType(type_str), atol(count_str.c_str()));
+ }
+ }
+}
+
ChanCount
infinity_factory()
{
@@ -39,6 +56,21 @@ infinity_factory()
return ret;
}
+XMLNode*
+ChanCount::state(const std::string& name) const
+{
+ XMLNode* node = new XMLNode (name);
+ for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
+ uint32_t count = get(*t);
+ if (count > 0) {
+ XMLNode* n = new XMLNode(X_(state_node_name));
+ n->add_property("type", (*t).to_string());
+ n->add_property("count", count);
+ node->add_child_nocopy(*n);
+ }
+ }
+ return node;
+}
// Statics
const ChanCount ChanCount::INFINITE = infinity_factory();
diff --git a/libs/ardour/configuration.cc b/libs/ardour/configuration.cc
index 611ebddb59..bff9fb16d6 100644
--- a/libs/ardour/configuration.cc
+++ b/libs/ardour/configuration.cc
@@ -103,7 +103,7 @@ Configuration::load_state ()
}
if (statbuf.st_size != 0) {
- cerr << string_compose (_("loading system configuration file %1"), rcfile) << endl;
+ cerr << string_compose (_("Loading system configuration file %1"), rcfile) << endl;
if (!tree.read (rcfile.c_str())) {
error << string_compose(_("Ardour: cannot read system configuration file \"%1\""), rcfile) << endmsg;
@@ -140,7 +140,7 @@ Configuration::load_state ()
}
if (statbuf.st_size != 0) {
- cerr << string_compose (_("loading user configuration file %1"), rcfile) << endl;
+ cerr << string_compose (_("Loading user configuration file %1"), rcfile) << endl;
if (!tree.read (rcfile)) {
error << string_compose(_("Ardour: cannot read configuration file \"%1\""), rcfile) << endmsg;
diff --git a/libs/ardour/control_outputs.cc b/libs/ardour/control_outputs.cc
new file mode 100644
index 0000000000..2acd3c6d9e
--- /dev/null
+++ b/libs/ardour/control_outputs.cc
@@ -0,0 +1,79 @@
+/*
+ Copyright (C) 2006 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 <cmath>
+#include <algorithm>
+#include "ardour/control_outputs.h"
+#include "ardour/audio_buffer.h"
+#include "ardour/buffer_set.h"
+#include "ardour/configuration.h"
+#include "ardour/io.h"
+#include "ardour/session.h"
+
+using namespace std;
+
+namespace ARDOUR {
+
+ControlOutputs::ControlOutputs(Session& s, IO* io)
+ : IOProcessor(s, io, "Control Outs")
+ , _deliver(true)
+{
+}
+
+bool
+ControlOutputs::can_support_io_configuration (const ChanCount& in, ChanCount& out) const
+{
+ out = in;
+ return true;
+}
+
+bool
+ControlOutputs::configure_io (ChanCount in, ChanCount out)
+{
+ if (out != in) { // always 1:1
+ return false;
+ }
+
+ return Processor::configure_io (in, out);
+}
+
+void
+ControlOutputs::run_in_place (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame, nframes_t nframes)
+{
+ if (_deliver) {
+ _io->deliver_output (bufs, start_frame, end_frame, nframes);
+ } else {
+ _io->silence (nframes);
+ }
+}
+
+XMLNode&
+ControlOutputs::state (bool full_state)
+{
+ return get_state();
+}
+
+XMLNode&
+ControlOutputs::get_state()
+{
+ XMLNode* node = new XMLNode(state_node_name);
+ node->add_property("type", "control-outputs");
+ return *node;
+}
+
+} // namespace ARDOUR
diff --git a/libs/ardour/diskstream.cc b/libs/ardour/diskstream.cc
index 4cce7d4dc3..bca3c74241 100644
--- a/libs/ardour/diskstream.cc
+++ b/libs/ardour/diskstream.cc
@@ -441,17 +441,15 @@ Diskstream::playlist_ranges_moved (list< Evoral::RangeMove<nframes_t> > const &
);
/* move panner automation */
- Panner & p = _io->panner ();
- for (uint32_t i = 0; i < p.npanners (); ++i) {
-
- boost::shared_ptr<AutomationList> pan_alist = p.streampanner(i).pan_control()->alist();
- XMLNode & before = pan_alist->get_state ();
- pan_alist->move_ranges (movements);
- _session.add_command (
- new MementoCommand<AutomationList> (
- *pan_alist.get(), &before, &pan_alist->get_state ()
- )
- );
+ boost::shared_ptr<Panner> p = _io->panner ();
+ if (p) {
+ for (uint32_t i = 0; i < p->npanners (); ++i) {
+ boost::shared_ptr<AutomationList> pan_alist = p->streampanner(i).pan_control()->alist();
+ XMLNode & before = pan_alist->get_state ();
+ pan_alist->move_ranges (movements);
+ _session.add_command (new MementoCommand<AutomationList> (
+ *pan_alist.get(), &before, &pan_alist->get_state ()));
+ }
}
/* move processor automation */
diff --git a/libs/ardour/globals.cc b/libs/ardour/globals.cc
index 1c354a5db0..722c0fad49 100644
--- a/libs/ardour/globals.cc
+++ b/libs/ardour/globals.cc
@@ -107,7 +107,7 @@ int
ARDOUR::setup_midi ()
{
if (Config->midi_ports.size() == 0) {
- warning << _("no MIDI ports specified: no MMC or MTC control possible") << endmsg;
+ //warning << _("no MIDI ports specified: no MMC or MTC control possible") << endmsg;
return 0;
}
diff --git a/libs/ardour/import.cc b/libs/ardour/import.cc
index 410d085142..ef9605f467 100644
--- a/libs/ardour/import.cc
+++ b/libs/ardour/import.cc
@@ -449,7 +449,7 @@ Session::import_audiofiles (ImportStatus& status)
frame_rate(), cnt, status.total);
write_audio_data_to_new_files (source.get(), status, newfiles);
} else if (smf_reader.get()) { // midi
- status.doing_what = string_compose(_("loading MIDI file %1"), *p);
+ status.doing_what = string_compose(_("Loading MIDI file %1"), *p);
write_midi_data_to_new_files (smf_reader.get(), status, newfiles);
}
}
diff --git a/libs/ardour/io.cc b/libs/ardour/io.cc
index 7e77996d39..3e5b138fb7 100644
--- a/libs/ardour/io.cc
+++ b/libs/ardour/io.cc
@@ -102,36 +102,27 @@ static double direct_gain_to_control (gain_t gain) {
* and friends if no type is explicitly requested (to avoid breakage).
*/
IO::IO (Session& s, const string& name,
- int input_min, int input_max, int output_min, int output_max,
- DataType default_type)
- : SessionObject(s, name),
- AutomatableControls (s),
- _output_buffers (new BufferSet()),
- _active(true),
- _default_type (default_type),
- _input_minimum (ChanCount::ZERO),
- _input_maximum (ChanCount::INFINITE),
- _output_minimum (ChanCount::ZERO),
- _output_maximum (ChanCount::INFINITE)
-{
- _panner = new Panner (name, _session);
- _meter = new PeakMeter (_session);
-
- if (input_min > 0) {
- _input_minimum = ChanCount(_default_type, input_min);
- }
- if (input_max >= 0) {
- _input_maximum = ChanCount(_default_type, input_max);
- }
- if (output_min > 0) {
- _output_minimum = ChanCount(_default_type, output_min);
- }
- if (output_max >= 0) {
- _output_maximum = ChanCount(_default_type, output_max);
- }
+ DataType default_type,
+ ChanCount in_min, ChanCount in_max, ChanCount out_min, ChanCount out_max)
+ : SessionObject (s, name)
+ , AutomatableControls (s)
+ , _output_buffers (new BufferSet())
+ , _active (true)
+ , _default_type (default_type)
+ , _amp (new Amp(s, *this))
+ , _meter (new PeakMeter(s))
+ , _panner (new Panner(name, s))
+ , _input_minimum (ChanCount::ZERO)
+ , _input_maximum (ChanCount::INFINITE)
+ , _output_minimum (ChanCount::ZERO)
+ , _output_maximum (ChanCount::INFINITE)
+{
+ _input_minimum = in_min;
+ _output_minimum = out_min;
+ _input_maximum = in_max;
+ _output_maximum = out_max;
_gain = 1.0;
- _desired_gain = 1.0;
pending_state_node = 0;
no_panner_reset = false;
_phase_invert = false;
@@ -143,8 +134,6 @@ IO::IO (Session& s, const string& name,
_gain_control = boost::shared_ptr<GainControl>( new GainControl( X_("gaincontrol"), this, Evoral::Parameter(GainAutomation), gl ));
add_control(_gain_control);
-
- apply_gain_automation = false;
{
// IO::Meter is emitted from another thread so the
@@ -162,21 +151,18 @@ IO::IO (Session& s, const string& name,
}
IO::IO (Session& s, const XMLNode& node, DataType dt)
- : SessionObject(s, "unnamed io"),
- AutomatableControls (s),
- _output_buffers (new BufferSet()),
- _active(true),
- _default_type (dt)
-{
- _meter = new PeakMeter (_session);
- _panner = 0;
+ : SessionObject(s, "unnamed io")
+ , AutomatableControls (s)
+ , _output_buffers (new BufferSet())
+ , _active(true)
+ , _default_type (dt)
+ , _amp (new Amp(s, *this))
+ , _meter(new PeakMeter (_session))
+{
deferred_state = 0;
no_panner_reset = false;
- _desired_gain = 1.0;
_gain = 1.0;
- apply_gain_automation = false;
-
boost::shared_ptr<AutomationList> gl(
new AutomationList(Evoral::Parameter(GainAutomation)));
@@ -218,9 +204,6 @@ IO::~IO ()
}
m_meter_connection.disconnect();
-
- delete _meter;
- delete _panner;
}
void
@@ -241,12 +224,26 @@ IO::silence (nframes_t nframes)
void
IO::deliver_output (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame, nframes_t nframes)
{
- // FIXME: type specific code doesn't actually need to be here, it will go away in time
+ // Attach output buffers to port buffers
+ output_buffers().attach_buffers (_outputs, nframes, _output_offset);
- /* ********** AUDIO ********** */
+ // 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);
- // Apply gain if gain automation isn't playing
- if ( ! apply_gain_automation) {
+ // 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
@@ -254,44 +251,17 @@ IO::deliver_output (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame,
Glib::Mutex::Lock dm (declick_lock, Glib::TRY_LOCK);
if (dm.locked()) {
- dg = _desired_gain;
+ dg = _gain_control->user_float();
}
}
if (dg != _gain || dg != 1.0) {
- Amp::run_in_place(bufs, nframes, _gain, dg, _phase_invert);
+ Amp::apply_gain(output_buffers(), nframes, _gain, dg, _phase_invert);
_gain = dg;
}
}
- /* do this so that any processing that comes after deliver_outputs()
- can use the output buffers.
- */
-
- output_buffers().attach_buffers (_outputs, nframes, _output_offset);
-
- // Use the panner to distribute audio to output port buffers
-
- if (0 && _panner && _panner->npanners() && !_panner->bypassed()) {
-
- /* blech .. we shouldn't be creating and tearing this down every process()
- cycle. XXX fix me to not waste cycles and do memory allocation etc.
- */
-
- _panner->run_out_of_place(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 && _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);
- }
- }
}
void
@@ -302,9 +272,8 @@ IO::copy_to_outputs (BufferSet& bufs, DataType type, nframes_t nframes)
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;
@@ -312,8 +281,7 @@ IO::copy_to_outputs (BufferSet& bufs, DataType type, nframes_t nframes)
++o;
}
- /* extra outputs get a copy of the last buffer */
-
+ // 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);
@@ -894,14 +862,19 @@ IO::ensure_io (ChanCount in, ChanCount out, bool clear, void* src)
bool out_changed = false;
bool need_pan_reset = false;
- in = min (_input_maximum, in);
+ assert(in != ChanCount::INFINITE);
+ assert(out != ChanCount::INFINITE);
- out = min (_output_maximum, out);
+ in = ChanCount::min (_input_maximum, in);
+ out = ChanCount::min (_output_maximum, out);
if (in == n_inputs() && out == n_outputs() && !clear) {
return 0;
}
+ _configured_inputs = in;
+ _configured_outputs = out;
+
{
BLOCK_PROCESS_CALLBACK ();
Glib::Mutex::Lock lm (io_lock);
@@ -943,9 +916,7 @@ IO::ensure_io (ChanCount in, ChanCount out, bool clear, void* src)
}
/* create any necessary new input ports */
-
while (n_inputs().get(*t) < nin) {
-
string portname = build_legal_port_name (*t, true);
try {
@@ -959,7 +930,7 @@ IO::ensure_io (ChanCount in, ChanCount out, bool clear, void* src)
setup_peak_meters ();
reset_panner ();
/* pass it on */
- throw AudioEngine::PortRegistrationFailure();
+ throw err;
}
_inputs.add (port);
@@ -983,7 +954,7 @@ IO::ensure_io (ChanCount in, ChanCount out, bool clear, void* src)
setup_peak_meters ();
reset_panner ();
/* pass it on */
- throw AudioEngine::PortRegistrationFailure ();
+ throw err;
}
_outputs.add (port);
@@ -1124,7 +1095,7 @@ IO::ensure_outputs (ChanCount count, bool clear, bool lockit, void* src)
{
bool changed = false;
- if (_output_maximum < ChanCount::INFINITE) {
+ if (_output_maximum != ChanCount::INFINITE) {
count = min (_output_maximum, count);
if (count == n_outputs() && !clear) {
return 0;
@@ -1152,11 +1123,7 @@ IO::ensure_outputs (ChanCount count, bool clear, bool lockit, void* src)
gain_t
IO::effective_gain () const
{
- if (_gain_control->automation_playback()) {
- return _gain_control->get_value();
- } else {
- return _desired_gain;
- }
+ return _gain_control->get_value();
}
void
@@ -1305,16 +1272,10 @@ IO::state (bool full_state)
snprintf (buf, sizeof(buf), "%2.12f", gain());
node->add_property ("gain", buf);
- /* To make backwards compatibility a bit easier, write ChanCount::INFINITE to the session file
- as -1.
- */
-
- int const in_max = _input_maximum == ChanCount::INFINITE ? -1 : _input_maximum.get(_default_type);
- int const out_max = _output_maximum == ChanCount::INFINITE ? -1 : _output_maximum.get(_default_type);
-
- snprintf (buf, sizeof(buf)-1, "%d,%d,%d,%d", _input_minimum.get(_default_type), in_max, _output_minimum.get(_default_type), out_max);
-
- node->add_property ("iolimits", buf);
+ /* port counts */
+
+ node->add_child_nocopy(*n_inputs().state("Inputs"));
+ node->add_child_nocopy(*n_outputs().state("Outputs"));
/* automation */
@@ -1358,9 +1319,9 @@ IO::set_state (const XMLNode& node)
sscanf (prop->value().c_str(), "%d,%d,%d,%d",
&in_min, &in_max, &out_min, &out_max);
- /* Correct for the difference between the way we write things to session files and the
- way things are described by ChanCount; see comments in io.h about what the different
- ChanCount values mean. */
+ // Legacy numbers:
+ // minimum == -1 => minimum == 0
+ // maximum == -1 => maximum == infinity
if (in_min < 0) {
_input_minimum = ChanCount::ZERO;
@@ -1389,7 +1350,7 @@ IO::set_state (const XMLNode& node)
if ((prop = node.property ("gain")) != 0) {
set_gain (atof (prop->value().c_str()), this);
- _gain = _desired_gain;
+ _gain = _gain_control->user_float();
}
if ((prop = node.property ("automation-state")) != 0 || (prop = node.property ("automation-style")) != 0) {
@@ -1400,16 +1361,16 @@ IO::set_state (const XMLNode& node)
// Old school Panner.
if ((*iter)->name() == "Panner") {
- if (_panner == 0) {
- _panner = new Panner (_name, _session);
+ 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 == 0) {
- _panner = new Panner (_name, _session);
+ if (!_panner) {
+ _panner = boost::shared_ptr<Panner>(new Panner (_name, _session));
}
_panner->set_state (**iter);
}
@@ -1427,6 +1388,8 @@ IO::set_state (const XMLNode& node)
}
}
+ get_port_counts (node);
+
if (ports_legal) {
if (create_ports (node)) {
@@ -1438,8 +1401,10 @@ IO::set_state (const XMLNode& node)
port_legal_c = PortsLegal.connect (mem_fun (*this, &IO::ports_became_legal));
}
- if( !_panner )
- _panner = new Panner( _name, _session );
+ if (!_panner) {
+ _panner = boost::shared_ptr<Panner>(new Panner (_name, _session));
+ }
+
if (panners_legal) {
reset_panner ();
} else {
@@ -1573,6 +1538,7 @@ IO::ports_became_legal ()
port_legal_c.disconnect ();
+ get_port_counts (*pending_state_node);
ret = create_ports (*pending_state_node);
if (connecting_legal) {
@@ -1676,48 +1642,64 @@ IO::find_possible_bundle (const string &desired_name, const string &default_name
}
int
-IO::create_ports (const XMLNode& node)
+IO::get_port_counts (const XMLNode& node)
{
XMLProperty const * prop;
- uint32_t num_inputs = 0;
- uint32_t num_outputs = 0;
+ XMLNodeConstIterator iter;
+ ChanCount num_inputs = n_inputs();
+ ChanCount num_outputs = n_outputs();
+
+ for (iter = node.children().begin(); iter != node.children().end(); ++iter) {
+ if ((*iter)->name() == X_("Inputs")) {
+ num_inputs = ChanCount::max(num_inputs, ChanCount(**iter));
+ } else if ((*iter)->name() == X_("Outputs")) {
+ num_outputs = ChanCount::max(num_inputs, ChanCount(**iter));
+ }
+ }
if ((prop = node.property ("input-connection")) != 0) {
boost::shared_ptr<Bundle> c = find_possible_bundle (prop->value(), _("in"), _("input"));
-
if (c) {
- num_inputs = c->nchannels ();
- } else {
- num_inputs = 0;
+ num_inputs = ChanCount::max(num_inputs, ChanCount(c->type(), c->nchannels()));
}
} else if ((prop = node.property ("inputs")) != 0) {
- num_inputs = count (prop->value().begin(), prop->value().end(), '{');
+ num_inputs = ChanCount::max(num_inputs, ChanCount(_default_type,
+ count (prop->value().begin(), prop->value().end(), '{')));
}
if ((prop = node.property ("output-connection")) != 0) {
- boost::shared_ptr<Bundle> c = find_possible_bundle(prop->value(), _("out"), _("output"));
-
+ boost::shared_ptr<Bundle> c = find_possible_bundle (prop->value(), _("out"), _("output"));
if (c) {
- num_outputs = c->nchannels ();
- } else {
- num_outputs = 0;
+ num_outputs = ChanCount::max(num_outputs, ChanCount(c->type(), c->nchannels()));
}
} else if ((prop = node.property ("outputs")) != 0) {
- num_outputs = count (prop->value().begin(), prop->value().end(), '{');
+ num_outputs = ChanCount::max(num_outputs, ChanCount(_default_type,
+ count (prop->value().begin(), prop->value().end(), '{')));
}
+
+ _configured_inputs = num_inputs;
+ _configured_outputs = num_outputs;
+ _input_minimum = ChanCount::min(_input_minimum, num_inputs);
+ _input_maximum = ChanCount::max(_input_maximum, num_inputs);
+ _output_minimum = ChanCount::min(_output_minimum, num_outputs);
+ _output_maximum = ChanCount::max(_output_maximum, num_outputs);
+
+ return 0;
+}
+
+int
+IO::create_ports (const XMLNode& node)
+{
no_panner_reset = true;
- if (ensure_io (ChanCount (_default_type, num_inputs),
- ChanCount (_default_type, num_outputs),
- true, this)) {
-
+ if (ensure_io (_input_minimum, _output_minimum, true, this)) {
error << string_compose(_("%1: cannot create I/O ports"), _name) << endmsg;
return -1;
}
@@ -1730,7 +1712,6 @@ IO::create_ports (const XMLNode& node)
return 0;
}
-
int
IO::make_connections (const XMLNode& node)
{
@@ -2282,8 +2263,8 @@ IO::meter ()
void
IO::clear_automation ()
{
- data().clear (); // clears gain automation
- _panner->data().clear();
+ data().clear_controls (); // clears gain automation
+ _panner->data().clear_controls ();
}
void
@@ -2325,10 +2306,12 @@ IO::set_parameter_automation_state (Evoral::Parameter param, AutoState state)
void
IO::inc_gain (gain_t factor, void *src)
{
- if (_desired_gain == 0.0f)
+ 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);
+ } else {
+ set_gain (desired_gain + (desired_gain * factor), src);
+ }
}
void
@@ -2350,7 +2333,7 @@ IO::set_gain (gain_t val, void *src)
{
Glib::Mutex::Lock dm (declick_lock);
- _desired_gain = val;
+ _gain_control->set_float(val, false);
}
if (_session.transport_stopped()) {
@@ -2470,7 +2453,7 @@ IO::build_legal_port_name (DataType type, bool in)
}
snprintf (buf2, name_size+1, "%s %d", buf1, port_number);
-
+
return string (buf2);
}
diff --git a/libs/ardour/io_processor.cc b/libs/ardour/io_processor.cc
index 53ad91b9bf..53fbda24c7 100644
--- a/libs/ardour/io_processor.cc
+++ b/libs/ardour/io_processor.cc
@@ -43,12 +43,19 @@ using namespace std;
using namespace ARDOUR;
using namespace PBD;
-IOProcessor::IOProcessor (Session& s, const string& name, Placement p,
- int input_min, int input_max,
- int output_min, int output_max,
- DataType dtype)
- : Processor(s, name, p)
- , _io (new IO(s, name, input_min, input_max, output_min, output_max, dtype))
+IOProcessor::IOProcessor (Session& s, const string& proc_name, const string io_name, DataType dtype)
+ : Processor(s, proc_name)
+ , _io (new IO(s, io_name != "" ? io_name : proc_name, dtype))
+{
+ _active = false;
+ _sort_key = 0;
+ _gui = 0;
+ _extra_xml = 0;
+}
+
+IOProcessor::IOProcessor (Session& s, IO* io, const string& proc_name, DataType dtype)
+ : Processor(s, proc_name)
+ , _io (io)
{
_active = false;
_sort_key = 0;
diff --git a/libs/ardour/lv2_event_buffer.cc b/libs/ardour/lv2_event_buffer.cc
index dd4a925877..6afd395a56 100644
--- a/libs/ardour/lv2_event_buffer.cc
+++ b/libs/ardour/lv2_event_buffer.cc
@@ -41,6 +41,11 @@ LV2EventBuffer::LV2EventBuffer(size_t capacity)
throw std::bad_alloc();
}
+ if (capacity == 0) {
+ cerr << "ERROR: LV2 event buffer of size 0 created." << endl;
+ capacity = 1024;
+ }
+
#ifdef NO_POSIX_MEMALIGN
_data = (LV2_Event_Buffer*)malloc(sizeof(LV2_Event_Buffer) + capacity);
int ret = (_data != NULL) ? 0 : -1;
@@ -139,7 +144,8 @@ LV2EventBuffer::append(uint32_t frames,
#endif
/*cout << "Appending event type " << type << ", size " << size
- << " @ " << frames << "." << subframes << endl;*/
+ << " @ " << frames << "." << subframes << endl;
+ cout << "Buffer capacity " << _data->capacity << ", size " << _data->size << endl;*/
if (!lv2_event_write(&_iter, frames, subframes, type, size, data)) {
cerr << "ERROR: Failed to write event." << endl;
diff --git a/libs/ardour/lv2_plugin.cc b/libs/ardour/lv2_plugin.cc
index 5b4696b48c..8000bd8e44 100644
--- a/libs/ardour/lv2_plugin.cc
+++ b/libs/ardour/lv2_plugin.cc
@@ -268,8 +268,8 @@ LV2Plugin::get_state()
if (parameter_is_input(i) && parameter_is_control(i)) {
child = new XMLNode("Port");
- snprintf(buf, sizeof(buf), "%u", i);
- child->add_property("number", string(buf));
+ /*snprintf(buf, sizeof(buf), "%u", i);
+ child->add_property("number", string(buf));*/
child->add_property("symbol", port_symbol(i));
snprintf(buf, sizeof(buf), "%+f", _shadow_data[i]);
child->add_property("value", string(buf));
@@ -343,8 +343,8 @@ LV2Plugin::set_state(const XMLNode& node)
XMLProperty *prop;
XMLNodeConstIterator iter;
XMLNode *child;
- const char *port;
- const char *data;
+ const char *sym;
+ const char *value;
uint32_t port_id;
LocaleGuard lg (X_("POSIX"));
@@ -359,22 +359,29 @@ LV2Plugin::set_state(const XMLNode& node)
child = *iter;
- if ((prop = child->property("number")) != 0) {
- port = prop->value().c_str();
+ if ((prop = child->property("symbol")) != 0) {
+ sym = prop->value().c_str();
} else {
- warning << _("LV2: no lv2 port number") << endmsg;
+ warning << _("LV2: port has no symbol, ignored") << endmsg;
+ continue;
+ }
+
+ map<string,uint32_t>::iterator i = _port_indices.find(sym);
+ if (i != _port_indices.end()) {
+ port_id = i->second;
+ } else {
+ warning << _("LV2: port has unknown index, ignored") << endmsg;
continue;
}
if ((prop = child->property("value")) != 0) {
- data = prop->value().c_str();
+ value = prop->value().c_str();
} else {
- warning << _("LV2: no lv2 port data") << endmsg;
+ warning << _("LV2: port has no value, ignored") << endmsg;
continue;
}
- sscanf (port, "%" PRIu32, &port_id);
- set_parameter (port_id, atof(data));
+ set_parameter (port_id, atof(value));
}
latency_compute_run ();
@@ -462,9 +469,7 @@ LV2Plugin::connect_and_run (BufferSet& bufs,
ChanMapping in_map, ChanMapping out_map,
nframes_t nframes, nframes_t offset)
{
- cycles_t then, now;
-
- then = get_cycles ();
+ cycles_t then = get_cycles ();
uint32_t audio_in_index = 0;
uint32_t audio_out_index = 0;
@@ -474,25 +479,29 @@ LV2Plugin::connect_and_run (BufferSet& bufs,
if (parameter_is_audio(port_index)) {
if (parameter_is_input(port_index)) {
const uint32_t buf_index = in_map.get(DataType::AUDIO, audio_in_index++);
+ //cerr << port_index << " : " << " AUDIO IN " << buf_index << endl;
slv2_instance_connect_port(_instance, port_index,
bufs.get_audio(buf_index).data(offset));
} else if (parameter_is_output(port_index)) {
const uint32_t buf_index = out_map.get(DataType::AUDIO, audio_out_index++);
+ //cerr << port_index << " : " << " AUDIO OUT " << buf_index << endl;
slv2_instance_connect_port(_instance, port_index,
bufs.get_audio(buf_index).data(offset));
}
} else if (parameter_is_midi(port_index)) {
if (parameter_is_input(port_index)) {
const uint32_t buf_index = in_map.get(DataType::MIDI, midi_in_index++);
+ //cerr << port_index << " : " << " MIDI IN " << buf_index << endl;
slv2_instance_connect_port(_instance, port_index,
bufs.get_lv2_midi(true, buf_index).data());
} else if (parameter_is_output(port_index)) {
const uint32_t buf_index = out_map.get(DataType::MIDI, midi_out_index++);
+ //cerr << port_index << " : " << " MIDI OUT " << buf_index << endl;
slv2_instance_connect_port(_instance, port_index,
bufs.get_lv2_midi(false, buf_index).data());
}
} else if (!parameter_is_control(port_index)) {
- std::cerr << "WARNING: Unknown LV2 port type, ignored" << endl;
+ // Optional port (it'd better be if we've made it this far...)
slv2_instance_connect_port(_instance, port_index, NULL);
}
}
@@ -507,7 +516,7 @@ LV2Plugin::connect_and_run (BufferSet& bufs,
}
}
- now = get_cycles ();
+ cycles_t now = get_cycles ();
set_cycles ((uint32_t) (now - then));
return 0;
@@ -683,7 +692,7 @@ LV2PluginInfo::discover (void* lv2_world)
LV2World* world = (LV2World*)lv2_world;
SLV2Plugins plugins = slv2_world_get_all_plugins(world->world);
- cerr << "Discovered " << slv2_plugins_size (plugins) << " Lv2 plugins\n";
+ cerr << "LV2: Discovered " << slv2_plugins_size (plugins) << " plugins\n";
for (unsigned i=0; i < slv2_plugins_size(plugins); ++i) {
SLV2Plugin p = slv2_plugins_get_at(plugins, i);
diff --git a/libs/ardour/meter.cc b/libs/ardour/meter.cc
index 30d4d1a1d8..d8fee1ac47 100644
--- a/libs/ardour/meter.cc
+++ b/libs/ardour/meter.cc
@@ -27,6 +27,8 @@
#include "ardour/audio_buffer.h"
#include "ardour/runtime_functions.h"
+using namespace std;
+
namespace ARDOUR {
@@ -38,44 +40,39 @@ namespace ARDOUR {
void
PeakMeter::run_in_place (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame, nframes_t nframes)
{
+ const uint32_t n_audio = min(_configured_input.n_audio(), bufs.count().n_audio());
+ const uint32_t n_midi = min(_configured_input.n_midi(), bufs.count().n_midi());
+
uint32_t n = 0;
- uint32_t meterable = std::min(bufs.count().n_total(), (uint32_t)_peak_power.size());
- uint32_t limit = std::min (meterable, (uint32_t)bufs.count().n_midi());
-
- // Meter what we have (midi)
- for ( ; n < limit; ++n) {
- float val = 0;
-
- // GUI needs a better MIDI meter, not much information can be
- // expressed through peaks alone
- for (MidiBuffer::iterator i = bufs.get_midi(n).begin(); i != bufs.get_midi(n).end(); ++i) {
- const Evoral::MIDIEvent<nframes_t> ev(*i, false);
+
+ // Meter MIDI in to the first n_midi peaks
+ for (uint32_t i = 0; i < n_midi; ++i, ++n) {
+ float val = 0.0f;
+ for (MidiBuffer::iterator e = bufs.get_midi(i).begin(); e != bufs.get_midi(i).end(); ++e) {
+ const Evoral::MIDIEvent<nframes_t> ev(*e, false);
if (ev.is_note_on()) {
const float this_vel = log(ev.buffer()[2] / 127.0 * (M_E*M_E-M_E) + M_E) - 1.0;
- //printf("V %d -> %f\n", (int)((Byte)ev.buffer[2]), this_vel);
- if (this_vel > val)
+ if (this_vel > val) {
val = this_vel;
+ }
} else {
val += 1.0 / bufs.get_midi(n).capacity();
- if (val > 1.0)
+ if (val > 1.0) {
val = 1.0;
+ }
}
}
-
_peak_power[n] = val;
-
}
-
- limit = std::min (meterable, bufs.count().n_audio());
- // Meter what we have (audio)
- for ( ; n < limit; ++n) {
- _peak_power[n] = compute_peak (bufs.get_audio(n).data(), nframes, _peak_power[n]);
+ // Meter audio in to the rest of the peaks
+ for (uint32_t i = 0; i < n_audio; ++i, ++n) {
+ _peak_power[n] = compute_peak (bufs.get_audio(i).data(), nframes, _peak_power[n]);
}
// Zero any excess peaks
- for (size_t n = meterable; n < _peak_power.size(); ++n) {
- _peak_power[n] = 0;
+ for (uint32_t i = n; i < _peak_power.size(); ++i) {
+ _peak_power[i] = 0.0f;
}
}
@@ -83,7 +80,7 @@ void
PeakMeter::reset ()
{
for (size_t i = 0; i < _peak_power.size(); ++i) {
- _peak_power[i] = 0;
+ _peak_power[i] = 0.0f;
}
}
@@ -96,13 +93,19 @@ PeakMeter::reset_max ()
}
bool
+PeakMeter::can_support_io_configuration (const ChanCount& in, ChanCount& out) const
+{
+ out = in;
+ return true;
+}
+
+bool
PeakMeter::configure_io (ChanCount in, ChanCount out)
{
- /* we're transparent no matter what. fight the power. */
- if (out != in) {
+ if (out != in) { // always 1:1
return false;
}
-
+
uint32_t limit = in.n_total();
while (_peak_power.size() > limit) {
@@ -165,4 +168,18 @@ PeakMeter::meter ()
}
}
+XMLNode&
+PeakMeter::state (bool full_state)
+{
+ return get_state();
+}
+
+XMLNode&
+PeakMeter::get_state()
+{
+ XMLNode* node = new XMLNode(state_node_name);
+ node->add_property("type", "meter");
+ return *node;
+}
+
} // namespace ARDOUR
diff --git a/libs/ardour/midi_diskstream.cc b/libs/ardour/midi_diskstream.cc
index a0ef073c3a..f8d9f1eb58 100644
--- a/libs/ardour/midi_diskstream.cc
+++ b/libs/ardour/midi_diskstream.cc
@@ -139,8 +139,9 @@ MidiDiskstream::~MidiDiskstream ()
void
MidiDiskstream::non_realtime_locate (nframes_t position)
{
- assert(_write_source);
- _write_source->set_timeline_position (position);
+ if (_write_source) {
+ _write_source->set_timeline_position (position);
+ }
seek(position, false);
}
@@ -156,7 +157,10 @@ MidiDiskstream::non_realtime_input_change ()
}
if (input_change_pending & ConfigurationChanged) {
- assert(_io->n_inputs() == _n_channels);
+ if (_io->n_inputs().n_midi() != _n_channels.n_midi()) {
+ error << "Can not feed IO " << _io->n_inputs()
+ << " with diskstream " << _n_channels << endl;
+ }
}
get_input_sources ();
@@ -547,8 +551,6 @@ MidiDiskstream::process (nframes_t transport_frame, nframes_t nframes, bool can_
} else if (nominally_recording) {
- cerr << "B" << endl;
-
/* can't do actual capture yet - waiting for latency effects to finish before we start*/
playback_distance = nframes;
diff --git a/libs/ardour/midi_patch_manager.cc b/libs/ardour/midi_patch_manager.cc
index 39a5be9b5a..b555c12934 100644
--- a/libs/ardour/midi_patch_manager.cc
+++ b/libs/ardour/midi_patch_manager.cc
@@ -21,12 +21,16 @@
#include <sigc++/sigc++.h>
#include <boost/shared_ptr.hpp>
+#include "pbd/compose.h"
#include "pbd/file_utils.h"
+#include "pbd/error.h"
#include "ardour/session.h"
#include "ardour/session_directory.h"
#include "ardour/midi_patch_manager.h"
+#include "i18n.h"
+
using namespace std;
using namespace sigc;
using namespace ARDOUR;
@@ -55,12 +59,11 @@ MidiPatchManager::refresh()
path path_to_patches = _session->session_directory().midi_patch_path();
- cerr << "Path to patches: " << path_to_patches.to_string() << endl;
+ info << string_compose(_("looking for MIDI patches in %1"), path_to_patches.to_string()) << endmsg;
- if(!exists(path_to_patches)) {
+ if (!exists(path_to_patches)) {
return;
}
- cerr << "Path to patches: " << path_to_patches.to_string() << " exists" << endl;
assert(is_directory(path_to_patches));
@@ -69,17 +72,15 @@ MidiPatchManager::refresh()
find_matching_files_in_directory(path_to_patches, pattern, result);
- cerr << "patchfiles result contains " << result.size() << " elements" << endl;
+ cerr << "Loading " << result.size() << " MIDI patches from " << path_to_patches.to_string() << endl;
- for(vector<path>::iterator i = result.begin(); i != result.end(); ++i) {
- cerr << "processing patchfile " << i->to_string() << endl;
-
+ for (vector<path>::iterator i = result.begin(); i != result.end(); ++i) {
boost::shared_ptr<MIDINameDocument> document(new MIDINameDocument(i->to_string()));
- for(MIDINameDocument::MasterDeviceNamesList::const_iterator device =
- document->master_device_names_by_model().begin();
- device != document->master_device_names_by_model().end();
- ++device) {
- cerr << "got model " << device->first << endl;
+ for (MIDINameDocument::MasterDeviceNamesList::const_iterator device =
+ document->master_device_names_by_model().begin();
+ device != document->master_device_names_by_model().end();
+ ++device) {
+ //cerr << "got model " << device->first << endl;
// have access to the documents by model name
_documents[device->first] = document;
// build a list of all master devices from all documents
diff --git a/libs/ardour/midi_source.cc b/libs/ardour/midi_source.cc
index b66d6c6b13..59c19981a5 100644
--- a/libs/ardour/midi_source.cc
+++ b/libs/ardour/midi_source.cc
@@ -139,7 +139,7 @@ MidiSource::midi_read (MidiRingBuffer<nframes_t>& dst, sframes_t source_start,
Evoral::Sequence<double>::const_iterator& i = _model_iter;
if (_last_read_end == 0 || start != _last_read_end) { // || !i.valid()) {
- cerr << "MidiSource seeking to " << start << " from " << _last_read_end << endl;
+ //cerr << "MidiSource seeking to " << start << " from " << _last_read_end << endl;
for (i = _model->begin(); i != _model->end(); ++i) {
if (BEATS_TO_FRAMES(i->time()) >= start) {
break;
diff --git a/libs/ardour/midi_track.cc b/libs/ardour/midi_track.cc
index 1fe15a16bf..030e8ff905 100644
--- a/libs/ardour/midi_track.cc
+++ b/libs/ardour/midi_track.cc
@@ -25,20 +25,20 @@
#include "midi++/events.h"
#include "evoral/midi_util.h"
-#include "ardour/midi_track.h"
-#include "ardour/midi_diskstream.h"
-#include "ardour/session.h"
+#include "ardour/amp.h"
+#include "ardour/buffer_set.h"
#include "ardour/io_processor.h"
+#include "ardour/meter.h"
+#include "ardour/midi_diskstream.h"
+#include "ardour/midi_playlist.h"
#include "ardour/midi_region.h"
#include "ardour/midi_source.h"
-#include "ardour/route_group_specialized.h"
-#include "ardour/processor.h"
-#include "ardour/midi_playlist.h"
+#include "ardour/midi_track.h"
#include "ardour/panner.h"
+#include "ardour/processor.h"
+#include "ardour/route_group_specialized.h"
+#include "ardour/session.h"
#include "ardour/utils.h"
-#include "ardour/buffer_set.h"
-#include "ardour/meter.h"
-
#include "i18n.h"
@@ -60,10 +60,6 @@ MidiTrack::MidiTrack (Session& sess, string name, Route::Flag flag, TrackMode mo
set_input_minimum(ChanCount(DataType::MIDI, 1));
set_input_maximum(ChanCount(DataType::MIDI, 1));
- set_output_minimum(ChanCount(DataType::MIDI, 1));
- set_output_maximum(ChanCount(DataType::MIDI, 1));
-
- PortCountChanged(ChanCount(DataType::MIDI, 2)); /* EMIT SIGNAL */
}
MidiTrack::MidiTrack (Session& sess, const XMLNode& node)
@@ -75,10 +71,6 @@ MidiTrack::MidiTrack (Session& sess, const XMLNode& node)
set_input_minimum(ChanCount(DataType::MIDI, 1));
set_input_maximum(ChanCount(DataType::MIDI, 1));
- set_output_minimum(ChanCount(DataType::MIDI, 1));
- set_output_maximum(ChanCount(DataType::MIDI, 1));
-
- PortCountChanged(ChanCount(DataType::MIDI, 2)); /* EMIT SIGNAL */
}
MidiTrack::~MidiTrack ()
@@ -370,87 +362,6 @@ MidiTrack::set_state_part_two ()
return;
}
-int
-MidiTrack::no_roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame,
- bool session_state_changing, bool can_record, bool rec_monitors_input)
-{
- if (n_outputs().n_midi() == 0) {
- return 0;
- }
-
- if (!_active) {
- silence (nframes);
- }
-
- if (session_state_changing) {
-
- /* XXX is this safe to do against transport state changes? */
-
- passthru_silence (start_frame, end_frame, nframes, 0, false);
- return 0;
- }
-
- midi_diskstream()->check_record_status (start_frame, nframes, can_record);
-
- bool send_silence;
-
- if (_have_internal_generator) {
- /* since the instrument has no input streams,
- there is no reason to send any signal
- into the route.
- */
- send_silence = true;
- } else {
-
- if (Config->get_auto_input()) {
- if (Config->get_monitoring_model() == SoftwareMonitoring) {
- send_silence = false;
- } else {
- send_silence = true;
- }
- } else {
- if (_diskstream->record_enabled()) {
- if (Config->get_monitoring_model() == SoftwareMonitoring) {
- send_silence = false;
- } else {
- send_silence = true;
- }
- } else {
- send_silence = true;
- }
- }
- }
-
- apply_gain_automation = false;
-
- if (send_silence) {
-
- /* if we're sending silence, but we want the meters to show levels for the signal,
- meter right here.
- */
-
- if (_have_internal_generator) {
- passthru_silence (start_frame, end_frame, nframes, 0, true);
- } else {
- if (_meter_point == MeterInput) {
- just_meter_input (start_frame, end_frame, nframes);
- }
- passthru_silence (start_frame, end_frame, nframes, 0, false);
- }
-
- } else {
-
- /* we're sending signal, but we may still want to meter the input.
- */
-
- passthru (start_frame, end_frame, nframes, 0, (_meter_point == MeterInput));
- }
-
- flush_outputs (nframes);
-
- return 0;
-}
-
int
MidiTrack::roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame, int declick,
bool can_record, bool rec_monitors_input)
@@ -509,7 +420,7 @@ MidiTrack::roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame,
at least potentially (depending on monitoring options)
*/
- passthru (start_frame, end_frame, nframes, 0, true);
+ passthru (start_frame, end_frame, nframes, 0);
} else {
/*
@@ -529,7 +440,7 @@ MidiTrack::roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame,
diskstream->get_playback(bufs.get_midi(0), start_frame, end_frame);
process_output_buffers (bufs, start_frame, end_frame, nframes,
- (!_session.get_record_enabled() || !Config->get_do_not_record_plugins()), declick, (_meter_point != MeterInput));
+ (!_session.get_record_enabled() || !Config->get_do_not_record_plugins()), declick);
}
@@ -538,68 +449,6 @@ MidiTrack::roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame,
return 0;
}
-int
-MidiTrack::silent_roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame,
- bool can_record, bool rec_monitors_input)
-{
- if (n_outputs().n_midi() == 0 && _processors.empty()) {
- return 0;
- }
-
- if (!_active) {
- silence (nframes);
- return 0;
- }
-
- _silent = true;
- apply_gain_automation = false;
-
- silence (nframes);
-
- return midi_diskstream()->process (_session.transport_frame(), nframes, can_record, rec_monitors_input);
-}
-
-void
-MidiTrack::process_output_buffers (BufferSet& bufs,
- nframes_t start_frame, nframes_t end_frame,
- nframes_t nframes, bool with_processors, int declick,
- bool meter)
-{
- /* There's no such thing as a MIDI bus for the time being.
- * We'll do all the MIDI route work here for now, but the long-term goal is to have
- * Route::process_output_buffers handle everything */
-
- if (meter && (_meter_point == MeterInput || _meter_point == MeterPreFader)) {
- _meter->run_in_place(bufs, start_frame, end_frame, nframes);
- }
-
- // Run all processors
- if (with_processors) {
- Glib::RWLock::ReaderLock rm (_processor_lock, Glib::TRY_LOCK);
- if (rm.locked()) {
- for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
- bufs.set_count(ChanCount::max(bufs.count(), (*i)->output_streams()));
- (*i)->run_in_place (bufs, start_frame, end_frame, nframes);
- }
- }
- }
-
- if (meter && (_meter_point == MeterPostFader)) {
- _meter->run_in_place(bufs, start_frame, end_frame, nframes);
- }
-
- // Main output stage
- if (muted()) {
- IO::silence (nframes);
- } else {
-
- // Write 'automation' controllers (e.g. CC events from a UI slider)
- write_controller_messages(bufs.get_midi(0), start_frame, end_frame, nframes);
-
- deliver_output(bufs, start_frame, end_frame, nframes);
- }
-}
-
void
MidiTrack::write_controller_messages(MidiBuffer& output_buf, nframes_t start, nframes_t end, nframes_t nframes)
{
diff --git a/libs/ardour/panner.cc b/libs/ardour/panner.cc
index 23c87f0a2e..83923a44d6 100644
--- a/libs/ardour/panner.cc
+++ b/libs/ardour/panner.cc
@@ -703,7 +703,7 @@ Multi2dPanner::set_state (const XMLNode& node)
/*---------------------------------------------------------------------- */
Panner::Panner (string name, Session& s)
- : Processor(s, name, PostFader)
+ : Processor(s, name)
{
//set_name_old_auto (name);
set_name (name);
@@ -1012,23 +1012,30 @@ Panner::set_automation_state (AutoState state)
AutoState
Panner::automation_state () const
{
+ boost::shared_ptr<AutomationList> l;
if (!empty()) {
- return ((AutomationList*)_streampanners.front()->pan_control()->list().get())->automation_state ();
- } else {
- return Off;
+ boost::shared_ptr<AutomationControl> control = _streampanners.front()->pan_control();
+ if (control) {
+ l = boost::dynamic_pointer_cast<AutomationList>(control->list());
+ }
}
+
+ return l ? l->automation_state() : Off;
}
AutoStyle
Panner::automation_style () const
{
+ boost::shared_ptr<AutomationList> l;
if (!empty()) {
- return ((AutomationList*)_streampanners.front()->pan_control()->list().get())->automation_style ();
- } else {
- return Absolute;
+ boost::shared_ptr<AutomationControl> control = _streampanners.front()->pan_control();
+ if (control) {
+ l = boost::dynamic_pointer_cast<AutomationList>(control->list());
+ }
}
-}
+ return l ? l->automation_style() : Absolute;
+}
struct PanPlugins {
string name;
diff --git a/libs/ardour/plugin_insert.cc b/libs/ardour/plugin_insert.cc
index bf67e33493..41c65ba4fe 100644
--- a/libs/ardour/plugin_insert.cc
+++ b/libs/ardour/plugin_insert.cc
@@ -58,10 +58,10 @@ using namespace PBD;
const string PluginInsert::port_automation_node_name = "PortAutomation";
-PluginInsert::PluginInsert (Session& s, boost::shared_ptr<Plugin> plug, Placement placement)
- : Processor (s, plug->name(), placement),
- _signal_analysis_collected_nframes(0),
- _signal_analysis_collect_nframes_max(0)
+PluginInsert::PluginInsert (Session& s, boost::shared_ptr<Plugin> plug)
+ : Processor (s, plug->name())
+ , _signal_analysis_collected_nframes(0)
+ , _signal_analysis_collect_nframes_max(0)
{
/* the first is the master */
@@ -78,7 +78,7 @@ PluginInsert::PluginInsert (Session& s, boost::shared_ptr<Plugin> plug, Placemen
}
PluginInsert::PluginInsert (Session& s, const XMLNode& node)
- : Processor (s, "unnamed plugin insert", PreFader),
+ : Processor (s, "unnamed plugin insert"),
_signal_analysis_collected_nframes(0),
_signal_analysis_collect_nframes_max(0)
{
@@ -160,14 +160,10 @@ PluginInsert::output_streams() const
ChanCount out = _plugins.front()->get_info()->n_outputs;
if (out == ChanCount::INFINITE) {
-
return _plugins.front()->output_streams ();
-
} else {
-
out.set_audio (out.n_audio() * _plugins.size());
out.set_midi (out.n_midi() * _plugins.size());
-
return out;
}
}
@@ -182,7 +178,6 @@ PluginInsert::input_streams() const
} else {
in.set_audio (in.n_audio() * _plugins.size());
in.set_midi (in.n_midi() * _plugins.size());
-
return in;
}
}
@@ -323,10 +318,10 @@ PluginInsert::connect_and_run (BufferSet& bufs, nframes_t nframes, nframes_t off
}
for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
- (*i)->connect_and_run (bufs, in_map, out_map, nframes, offset);
+ (*i)->connect_and_run(bufs, in_map, out_map, nframes, offset);
for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
- in_map.offset(*t, input_streams().get(*t));
- out_map.offset(*t, output_streams().get(*t));
+ in_map.offset_to(*t, natural_input_streams().get(*t));
+ out_map.offset_to(*t, natural_output_streams().get(*t));
}
}
@@ -562,61 +557,60 @@ PluginInsert::configure_io (ChanCount in, ChanCount out)
bool
PluginInsert::can_support_io_configuration (const ChanCount& in, ChanCount& out) const
{
+ // Plugin has flexible I/O, so delegate to it
if (_plugins.front()->reconfigurable_io()) {
- /* plugin has flexible I/O, so delegate to it */
return _plugins.front()->can_support_io_configuration (in, out);
}
+ ChanCount inputs = _plugins[0]->get_info()->n_inputs;
ChanCount outputs = _plugins[0]->get_info()->n_outputs;
- ChanCount inputs = _plugins[0]->get_info()->n_inputs;
- if ((inputs.n_total() == 0)
- || (inputs.n_total() == 1 && outputs == inputs)
- || (inputs.n_total() == 1 && outputs == inputs
- && ((inputs.n_audio() == 0 && in.n_audio() == 0)
- || (inputs.n_midi() == 0 && in.n_midi() == 0)))
- || (inputs == in)) {
+ // Plugin inputs match requested inputs exactly
+ if (inputs == in) {
out = outputs;
return true;
}
- bool can_replicate = true;
-
- /* if number of inputs is a factor of the requested input
- configuration for every type, we can replicate.
- */
+ // See if replication is possible
+ // We can replicate if there exists a single factor f such that, for every type,
+ // the number of plugin inputs * f = the requested number of inputs
+ uint32_t f = 0;
+ bool can_replicate = true;
for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
- if (inputs.get(*t) >= in.get(*t) || (inputs.get(*t) % in.get(*t) != 0)) {
+ // No inputs of this type
+ if (inputs.get(*t) == 0 && in.get(*t) == 0) {
+ continue;
+
+ // Plugin has more inputs than requested, can not replicate
+ } else if (inputs.get(*t) >= in.get(*t)) {
can_replicate = false;
break;
+
+ // Plugin inputs is not a factor of requested inputs, can not replicate
+ } else if (inputs.get(*t) == 0 || in.get(*t) % inputs.get(*t) != 0) {
+ can_replicate = false;
+ break;
+
+ // Potential factor not set yet
+ } else if (f == 0) {
+ f = in.get(*t) / inputs.get(*t);;
}
- }
- if (!can_replicate || (in.n_total() % inputs.n_total() != 0)) {
- return false;
+ // Factor for this type does not match another type, can not replicate
+ if (f != (in.get(*t) / inputs.get(*t))) {
+ can_replicate = false;
+ break;
+ }
}
- if (inputs.n_total() == 0) {
- /* instrument plugin, always legal, but throws away any existing streams */
- out = outputs;
- } else if (inputs.n_total() == 1 && outputs == inputs
- && ((inputs.n_audio() == 0 && in.n_audio() == 0)
- || (inputs.n_midi() == 0 && in.n_midi() == 0))) {
- /* mono, single-typed plugin, replicate as needed to match in */
- out = in;
- } else if (inputs == in) {
- /* exact match */
- out = outputs;
- } else {
- /* replicate - note that we've already verified that
- the replication count is constant across all data types.
- */
+ if (can_replicate) {
for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
- out.set (*t, outputs.get(*t) * (in.get(*t) / inputs.get(*t)));
+ out.set (*t, outputs.get(*t) * f);
}
+ return true;
+ } else {
+ return false;
}
-
- return true;
}
/* Number of plugin instances required to support a given channel configuration.
@@ -798,7 +792,7 @@ PluginInsert::set_state(const XMLNode& node)
cnodes = (*niter)->children ("Port");
- for(iter = cnodes.begin(); iter != cnodes.end(); ++iter){
+ for (iter = cnodes.begin(); iter != cnodes.end(); ++iter) {
child = *iter;
diff --git a/libs/ardour/plugin_manager.cc b/libs/ardour/plugin_manager.cc
index ce7a94a517..0b5b9276f1 100644
--- a/libs/ardour/plugin_manager.cc
+++ b/libs/ardour/plugin_manager.cc
@@ -127,7 +127,7 @@ PluginManager::PluginManager ()
}
#ifdef HAVE_SLV2
- cerr << "Creating a new lv2 world\n";
+ cerr << "LV2: Creating world" << endl;
_lv2_world = new LV2World();
#endif
diff --git a/libs/ardour/po/el_GR.po b/libs/ardour/po/el_GR.po
index 9ddd3e7188..fb1856dbdd 100644
--- a/libs/ardour/po/el_GR.po
+++ b/libs/ardour/po/el_GR.po
@@ -446,7 +446,7 @@ msgid "automation list: no y-coordinate stored for control point (point ignored)
msgstr "λίστα αυτοματισμοÏ: καμία y-συντεταγμένη αποθηκευμένη για σημείο ελέγχου (το σημείο αγνοήθηκε)"
#: libs/ardour/configuration.cc:80
-msgid "loading system configuration file %1"
+msgid "Loading system configuration file %1"
msgstr "Ανάκληση αÏχείου Ïυθμίσεων συστήματος %1"
#: libs/ardour/configuration.cc:83
@@ -458,7 +458,7 @@ msgid "Ardour: system configuration file \"%1\" not loaded successfully."
msgstr "Ardour: το αÏχείο διαÏÏυθμίσεως του συστήματος \"%1\" δεν φοÏτώθηκε επιτυχώς."
#: libs/ardour/configuration.cc:105
-msgid "loading user configuration file %1"
+msgid "Loading user configuration file %1"
msgstr "Ανάκληση αÏχείου Ïυθμίσεων χÏήστη %1"
#: libs/ardour/configuration.cc:108
diff --git a/libs/ardour/po/it_IT.po b/libs/ardour/po/it_IT.po
index 2ce02827bd..61ec7853ed 100644
--- a/libs/ardour/po/it_IT.po
+++ b/libs/ardour/po/it_IT.po
@@ -467,7 +467,7 @@ msgstr ""
#: libs/ardour/configuration.cc:80
#, fuzzy
-msgid "loading system configuration file %1"
+msgid "Loading system configuration file %1"
msgstr ""
"Ardour: impossibile leggere il file di configurazione di sistema \"%1\""
@@ -484,7 +484,7 @@ msgstr ""
#: libs/ardour/configuration.cc:105
#, fuzzy
-msgid "loading user configuration file %1"
+msgid "Loading user configuration file %1"
msgstr "Ardour: impossibile la lettura del file di configurazione \"%1\""
#: libs/ardour/configuration.cc:108
diff --git a/libs/ardour/po/pl_PL.po b/libs/ardour/po/pl_PL.po
index f2bdc8d91a..c189796689 100644
--- a/libs/ardour/po/pl_PL.po
+++ b/libs/ardour/po/pl_PL.po
@@ -365,7 +365,7 @@ msgid "AutomationList: passed XML node called %1, not \"AutomationList\" - ignor
msgstr ""
#: libs/ardour/configuration.cc:97
-msgid "loading system configuration file %1"
+msgid "Loading system configuration file %1"
msgstr ""
#: libs/ardour/configuration.cc:100
@@ -381,7 +381,7 @@ msgid "your system Ardour configuration file is empty. This probably means that
msgstr ""
#: libs/ardour/configuration.cc:131
-msgid "loading user configuration file %1"
+msgid "Loading user configuration file %1"
msgstr ""
#: libs/ardour/configuration.cc:134
diff --git a/libs/ardour/po/ru_RU.po b/libs/ardour/po/ru_RU.po
index aeeb1bf547..c1c4850ce2 100644
--- a/libs/ardour/po/ru_RU.po
+++ b/libs/ardour/po/ru_RU.po
@@ -430,7 +430,7 @@ msgstr ""
#: libs/ardour/configuration.cc:80
#, fuzzy
-msgid "loading system configuration file %1"
+msgid "Loading system configuration file %1"
msgstr "Ardour: ÎÅ ÕÄÁÌÏÓØ ÐÒÏÞÉÔÁÔØ ÆÁÊÌ ËÏÎÆÉÇÕÒÁÃÉÉ ÐÒÏÇÒÁÍÍÙ \"%1\""
#: libs/ardour/configuration.cc:83
@@ -443,7 +443,7 @@ msgstr "Ardour: ÎÅ ÕÄÁÌÏÓØ ÚÁÇÒÕÚÉÔØ ÆÁÊÌ ËÏÎÆÉÇÕÒÁÃÉÉ ÐÒÏÇÒÁÍÍÙ \"%1\"."
#: libs/ardour/configuration.cc:105
#, fuzzy
-msgid "loading user configuration file %1"
+msgid "Loading user configuration file %1"
msgstr "Ardour: ÎÅ ÕÄÁÌÏÓØ ÐÒÏÞÉÔÁÔØ ÆÁÊÌ ËÏÎÆÉÇÕÒÁÃÉÉ ÐÏÌØÚÏ×ÁÔÅÌÑ \"%1\""
#: libs/ardour/configuration.cc:108
diff --git a/libs/ardour/po/sv_SE.po b/libs/ardour/po/sv_SE.po
index 58be548f8e..19fe623de9 100644
--- a/libs/ardour/po/sv_SE.po
+++ b/libs/ardour/po/sv_SE.po
@@ -423,7 +423,7 @@ msgid ""
msgstr ""
#: libs/ardour/configuration.cc:87
-msgid "loading system configuration file %1"
+msgid "Loading system configuration file %1"
msgstr ""
#: libs/ardour/configuration.cc:90
@@ -435,7 +435,7 @@ msgid "Ardour: system configuration file \"%1\" not loaded successfully."
msgstr ""
#: libs/ardour/configuration.cc:111
-msgid "loading user configuration file %1"
+msgid "Loading user configuration file %1"
msgstr ""
#: libs/ardour/configuration.cc:114
diff --git a/libs/ardour/port.cc b/libs/ardour/port.cc
index d5021026de..ebe31a1fde 100644
--- a/libs/ardour/port.cc
+++ b/libs/ardour/port.cc
@@ -210,6 +210,7 @@ Port::total_latency () const
int
Port::reestablish ()
{
+ cerr << "RE-REGISTER: " << _name.c_str() << endl;
_jack_port = jack_port_register (_engine->jack(), _name.c_str(), type().to_jack_type(), _flags, 0);
if (_jack_port == 0) {
diff --git a/libs/ardour/port_insert.cc b/libs/ardour/port_insert.cc
index 8f53be8534..606b055dab 100644
--- a/libs/ardour/port_insert.cc
+++ b/libs/ardour/port_insert.cc
@@ -40,29 +40,15 @@ using namespace std;
using namespace ARDOUR;
using namespace PBD;
-PortInsert::PortInsert (Session& s, Placement p)
- : IOProcessor (s, string_compose (_("insert %1"), (bitslot = s.next_insert_id()) + 1), p, 1, -1, 1, -1)
+PortInsert::PortInsert (Session& s)
+ : IOProcessor (s, string_compose (_("insert %1"), (bitslot = s.next_insert_id()) + 1), "")
{
init ();
ProcessorCreated (this); /* EMIT SIGNAL */
}
-void
-PortInsert::init ()
-{
- if (_io->add_input_port ("", this)) {
- error << _("PortInsert: cannot add input port") << endmsg;
- throw failed_constructor();
- }
-
- if (_io->add_output_port ("", this)) {
- error << _("PortInsert: cannot add output port") << endmsg;
- throw failed_constructor();
- }
-}
-
PortInsert::PortInsert (Session& s, const XMLNode& node)
- : IOProcessor (s, "unnamed port insert", PreFader)
+ : IOProcessor (s, "unnamed port insert")
{
if (set_state (node)) {
throw failed_constructor();
@@ -77,6 +63,15 @@ 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, nframes_t start_frame, nframes_t end_frame, nframes_t nframes)
{
if (_io->n_outputs().n_total() == 0) {
@@ -180,10 +175,10 @@ PortInsert::configure_io (ChanCount in, ChanCount out)
to the number of input ports we need.
*/
- _io->set_output_maximum (in);
+ /*_io->set_output_maximum (in);
_io->set_output_minimum (in);
_io->set_input_maximum (out);
- _io->set_input_minimum (out);
+ _io->set_input_minimum (out);*/
if (_io->ensure_io (out, in, false, this) != 0) {
return false;
diff --git a/libs/ardour/processor.cc b/libs/ardour/processor.cc
index 63848e8c40..b48b0aebb0 100644
--- a/libs/ardour/processor.cc
+++ b/libs/ardour/processor.cc
@@ -58,13 +58,12 @@ sigc::signal<void,Processor*> Processor::ProcessorCreated;
// Always saved as Processor, but may be IOProcessor or Send in legacy sessions
const string Processor::state_node_name = "Processor";
-Processor::Processor(Session& session, const string& name, Placement p)
+Processor::Processor(Session& session, const string& name)
: SessionObject(session, name)
, AutomatableControls(session)
, _active(false)
, _next_ab_is_active(false)
, _configured(false)
- , _placement(p)
, _gui(0)
{
}
@@ -75,15 +74,6 @@ Processor::set_sort_key (uint32_t key)
_sort_key = key;
}
-void
-Processor::set_placement (Placement p)
-{
- if (_placement != p) {
- _placement = p;
- PlacementChanged (); /* EMIT SIGNAL */
- }
-}
-
XMLNode&
Processor::get_state (void)
{
@@ -120,26 +110,28 @@ Processor::state (bool full_state)
node->add_property("name", _name);
node->add_property("active", active() ? "yes" : "no");
- node->add_property("placement", enum_2_string (_placement));
if (_extra_xml){
node->add_child_copy (*_extra_xml);
}
if (full_state) {
-
XMLNode& automation = Automatable::get_automation_state();
-
- for (set<Evoral::Parameter>::iterator x = _visible_controls.begin(); x != _visible_controls.end(); ++x) {
- if (x != _visible_controls.begin()) {
- sstr << ' ';
+ if (!automation.children().empty()
+ || !automation.properties().empty()
+ || !_visible_controls.empty()) {
+
+ for (set<Evoral::Parameter>::iterator x = _visible_controls.begin();
+ x != _visible_controls.end(); ++x) {
+ if (x != _visible_controls.begin()) {
+ sstr << ' ';
+ }
+ sstr << *x;
}
- sstr << *x;
- }
-
- automation.add_property ("visible", sstr.str());
- node->add_child_nocopy (automation);
+ automation.add_property ("visible", sstr.str());
+ node->add_child_nocopy (automation);
+ }
}
return *node;
@@ -164,7 +156,6 @@ Processor::set_state (const XMLNode& node)
if ((*niter)->name() == X_("Automation")) {
-
XMLProperty *prop;
if ((prop = (*niter)->property ("path")) != 0) {
@@ -203,7 +194,8 @@ Processor::set_state (const XMLNode& node)
}
if ((prop = node.property ("active")) == 0) {
- warning << _("XML node describing a processor is missing the `active' field, trying legacy active flag from child node") << endmsg;
+ warning << _("XML node describing a processor is missing the `active' field,"
+ "trying legacy active flag from child node") << endmsg;
if (legacy_active) {
prop = legacy_active;
} else {
@@ -217,31 +209,6 @@ Processor::set_state (const XMLNode& node)
ActiveChanged (); /* EMIT_SIGNAL */
}
- if ((prop = node.property ("placement")) == 0) {
- warning << _("XML node describing a processor is missing the `placement' field, trying legacy placement flag from child node") << endmsg;
- if (legacy_placement) {
- prop = legacy_placement;
- } else {
- error << _("No child node with placement property") << endmsg;
- return -1;
- }
- }
-
- /* hack to handle older sessions before we only used EnumWriter */
-
- string pstr;
-
- if (prop->value() == "pre") {
- pstr = "PreFader";
- } else if (prop->value() == "post") {
- pstr = "PostFader";
- } else {
- pstr = prop->value();
- }
-
- Placement p = Placement (string_2_enum (pstr, p));
- set_placement (p);
-
return 0;
}
diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc
index 6179af5028..931ae9a996 100644
--- a/libs/ardour/route.cc
+++ b/libs/ardour/route.cc
@@ -29,29 +29,30 @@
#include "evoral/Curve.hpp"
-#include "ardour/timestamps.h"
+#include "ardour/amp.h"
+#include "ardour/audio_port.h"
#include "ardour/audioengine.h"
-#include "ardour/route.h"
#include "ardour/buffer.h"
-#include "ardour/processor.h"
-#include "ardour/plugin_insert.h"
-#include "ardour/port_insert.h"
-#include "ardour/send.h"
-#include "ardour/session.h"
-#include "ardour/utils.h"
+#include "ardour/buffer_set.h"
#include "ardour/configuration.h"
+#include "ardour/control_outputs.h"
#include "ardour/cycle_timer.h"
-#include "ardour/route_group.h"
-#include "ardour/port.h"
-#include "ardour/audio_port.h"
-#include "ardour/ladspa_plugin.h"
-#include "ardour/panner.h"
#include "ardour/dB.h"
-#include "ardour/amp.h"
+#include "ardour/ladspa_plugin.h"
#include "ardour/meter.h"
-#include "ardour/buffer_set.h"
#include "ardour/mix.h"
+#include "ardour/panner.h"
+#include "ardour/plugin_insert.h"
+#include "ardour/port.h"
+#include "ardour/port_insert.h"
+#include "ardour/processor.h"
#include "ardour/profile.h"
+#include "ardour/route.h"
+#include "ardour/route_group.h"
+#include "ardour/send.h"
+#include "ardour/session.h"
+#include "ardour/timestamps.h"
+#include "ardour/utils.h"
#include "i18n.h"
@@ -62,21 +63,22 @@ using namespace PBD;
uint32_t Route::order_key_cnt = 0;
sigc::signal<void,const char*> Route::SyncOrderKeys;
-Route::Route (Session& sess, string name,
- int in_min, int in_max, int out_min, int out_max,
- Flag flg, DataType default_type)
- : IO (sess, name, in_min, in_max, out_min, out_max, default_type)
+Route::Route (Session& sess, string name, Flag flg,
+ DataType default_type, ChanCount in, ChanCount out)
+ : IO (sess, name, default_type, in, ChanCount::INFINITE, out, ChanCount::INFINITE)
, _flags (flg)
, _solo_control (new ToggleControllable (X_("solo"), *this, ToggleControllable::SoloControl))
, _mute_control (new ToggleControllable (X_("mute"), *this, ToggleControllable::MuteControl))
{
+ _configured_inputs = in;
+ _configured_outputs = out;
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))
+ , _solo_control (new ToggleControllable (X_("solo"), *this, ToggleControllable::SoloControl))
+ , _mute_control (new ToggleControllable (X_("mute"), *this, ToggleControllable::MuteControl))
{
init ();
_set_state (node, false);
@@ -104,6 +106,7 @@ Route::init ()
_declickable = false;
_pending_declick = true;
_remote_control_id = 0;
+ _in_configure_processors = false;
_edit_group = 0;
_mix_group = 0;
@@ -118,10 +121,13 @@ Route::init ()
mute_gain = 1.0;
desired_mute_gain = 1.0;
- _control_outs = 0;
-
input_changed.connect (mem_fun (this, &Route::input_change_handler));
output_changed.connect (mem_fun (this, &Route::output_change_handler));
+
+ _amp->set_sort_key (0);
+ _meter->set_sort_key (1);
+ add_processor (_amp, NULL);
+ add_processor (_meter, NULL);
}
Route::~Route ()
@@ -132,8 +138,6 @@ Route::~Route ()
for (OrderKeys::iterator i = order_keys.begin(); i != order_keys.end(); ++i) {
free ((void*)(i->first));
}
-
- delete _control_outs;
}
void
@@ -217,7 +221,6 @@ Route::ensure_track_or_route_name(string name, Session &session)
return newname;
}
-
void
Route::inc_gain (gain_t fraction, void *src)
{
@@ -291,21 +294,15 @@ Route::set_gain (gain_t val, void *src)
*/
void
Route::process_output_buffers (BufferSet& bufs,
- nframes_t start_frame, nframes_t end_frame, nframes_t nframes,
- bool with_processors, int declick, bool meter)
+ nframes_t start_frame, nframes_t end_frame, nframes_t nframes,
+ bool with_processors, int declick)
{
- // This is definitely very audio-only for now
- assert(_default_type == DataType::AUDIO);
-
ProcessorList::iterator i;
- bool post_fader_work = false;
bool mute_declick_applied = false;
gain_t dmg, dsg, dg;
- IO *co;
- bool mute_audible;
- bool solo_audible;
bool no_monitor;
- gain_t* gab = _session.gain_automation_buffer();
+
+ bufs.is_silent(false);
switch (Config->get_monitoring_model()) {
case HardwareMonitoring:
@@ -317,96 +314,89 @@ Route::process_output_buffers (BufferSet& bufs,
}
declick = _pending_declick;
-
- {
- Glib::Mutex::Lock cm (_control_outs_lock, Glib::TRY_LOCK);
-
- if (cm.locked()) {
- co = _control_outs;
- } else {
- co = 0;
- }
- }
+ const bool recording_without_monitoring = no_monitor && record_enabled()
+ && (!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 = _desired_gain;
+ dg = _gain_control->user_float();
} else {
dmg = mute_gain;
dsg = solo_gain;
dg = _gain;
}
}
+
+ // 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<ControlOutputs> co = _control_outs;
+ if (co) {
+ // deliver control outputs unless we're ...
+ co->deliver (!(
+ dsg == 0 || // muted by solo of another track
+ (dmg == 0 && _mute_affects_control_outs) || // or muted by mute of this track
+ !recording_without_monitoring )); // or rec-enabled w/o s/w monitoring
+ }
+
/* -------------------------------------------------------------------------------------------
GLOBAL DECLICK (for transport changes etc.)
----------------------------------------------------------------------------------------- */
if (declick > 0) {
- Amp::run_in_place (bufs, nframes, 0.0, 1.0, false);
+ Amp::apply_gain (bufs, nframes, 0.0, 1.0, false);
_pending_declick = 0;
} else if (declick < 0) {
- Amp::run_in_place (bufs, nframes, 1.0, 0.0, false);
+ Amp::apply_gain (bufs, nframes, 1.0, 0.0, false);
_pending_declick = 0;
- } else {
-
- /* no global declick */
-
+ } else { // no global declick
if (solo_gain != dsg) {
- Amp::run_in_place (bufs, nframes, solo_gain, dsg, false);
+ Amp::apply_gain (bufs, nframes, solo_gain, dsg, false);
solo_gain = dsg;
}
}
/* -------------------------------------------------------------------------------------------
- INPUT METERING & MONITORING
+ PRE-FADER MUTING
----------------------------------------------------------------------------------------- */
- if (meter && (_meter_point == MeterInput)) {
- _meter->run_in_place(bufs, start_frame, end_frame, nframes);
- }
-
if (!_soloed && _mute_affects_pre_fader && (mute_gain != dmg)) {
- Amp::run_in_place (bufs, nframes, mute_gain, dmg, false);
+ 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 ((_meter_point == MeterInput) && co) {
-
- solo_audible = dsg > 0;
- mute_audible = dmg > 0;// || !_mute_affects_pre_fader;
-
- if ( // muted by solo of another track
-
- !solo_audible ||
-
- // muted by mute of this track
-
- !mute_audible ||
-
- // rec-enabled but not s/w monitoring
-
- // TODO: this is probably wrong
-
- ( no_monitor && record_enabled()
- && (!Config->get_auto_input() || _session.actively_recording()) )
-
- ) {
-
- co->silence (nframes);
-
- } else {
-
- co->deliver_output (bufs, start_frame, end_frame, nframes);
-
- }
- }
/* -------------------------------------------------------------------------------------------
DENORMAL CONTROL
@@ -423,300 +413,78 @@ Route::process_output_buffers (BufferSet& bufs,
}
}
+
/* -------------------------------------------------------------------------------------------
- PRE-FADER REDIRECTS
+ PROCESSORS (including Amp (fader) and Meter)
----------------------------------------------------------------------------------------- */
if (with_processors) {
Glib::RWLock::ReaderLock rm (_processor_lock, Glib::TRY_LOCK);
if (rm.locked()) {
- if (mute_gain > 0 || !_mute_affects_pre_fader) {
+ //if (!bufs.is_silent()) {
for (i = _processors.begin(); i != _processors.end(); ++i) {
- switch ((*i)->placement()) {
- case PreFader:
- (*i)->run_in_place (bufs, start_frame, end_frame, nframes);
- break;
- case PostFader:
- post_fader_work = true;
- break;
- }
+ 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()));
}
- } else {
+ /*} else {
for (i = _processors.begin(); i != _processors.end(); ++i) {
- switch ((*i)->placement()) {
- case PreFader:
- (*i)->silence (nframes);
- break;
- case PostFader:
- post_fader_work = true;
- break;
- }
+ (*i)->silence (nframes);
+ bufs.set_count(ChanCount::max(bufs.count(), (*i)->output_streams()));
}
- }
- }
- }
-
- /* When we entered this method, the number of bufs was set by n_process_buffers(), so
- * it may be larger than required. Consider e.g a mono track with two redirects A and B.
- * If A has one input and three outputs, and B three inputs and one output, n_process_buffers()
- * will be 3. In this case, now we've done pre-fader redirects, we can reset the number of bufs.
- */
- bufs.set_count (pre_fader_streams());
-
- if (!_soloed && (mute_gain != dmg) && !mute_declick_applied && _mute_affects_post_fader) {
- Amp::run_in_place (bufs, nframes, mute_gain, dmg, false);
- mute_gain = dmg;
- mute_declick_applied = true;
- }
-
- /* -------------------------------------------------------------------------------------------
- PRE-FADER METERING & MONITORING
- ----------------------------------------------------------------------------------------- */
-
- if (meter && (_meter_point == MeterPreFader)) {
- _meter->run_in_place(bufs, start_frame, end_frame, nframes);
- }
-
-
- if ((_meter_point == MeterPreFader) && co) {
-
- solo_audible = dsg > 0;
- mute_audible = dmg > 0 || !_mute_affects_pre_fader;
-
- if ( // muted by solo of another track
-
- !solo_audible ||
-
- // muted by mute of this track
-
- !mute_audible ||
-
- // rec-enabled but not s/w monitoring
-
- ( no_monitor && record_enabled()
- && (!Config->get_auto_input() || _session.actively_recording()) )
-
- ) {
-
- co->silence (nframes);
-
- } else {
-
- co->deliver_output (bufs, start_frame, end_frame, nframes);
+ }*/
}
- }
-
- /* -------------------------------------------------------------------------------------------
- GAIN STAGE
- ----------------------------------------------------------------------------------------- */
-
- /* if not recording or recording and requiring any monitor signal, then apply gain */
-
- if ( // not recording
-
- !(record_enabled() && _session.actively_recording()) ||
-
- // OR recording
-
- // AND software monitoring required
- Config->get_monitoring_model() == SoftwareMonitoring) {
-
- if (apply_gain_automation) {
-
- if (_phase_invert) {
- 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];
- }
- }
- } 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] *= gab[nx];
- }
- }
- }
-
- if (apply_gain_automation && _session.transport_rolling() && nframes > 0) {
- _effective_gain = gab[nframes-1];
- }
-
- } else {
-
- /* manual (scalar) gain */
-
- if (_gain != dg) {
-
- Amp::run_in_place (bufs, nframes, _gain, dg, _phase_invert);
- _gain = dg;
-
- } else if (_gain != 0 && (_phase_invert || _gain != 1.0)) {
-
- /* 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_t this_gain;
-
- if (_phase_invert) {
- this_gain = -_gain;
- } else {
- this_gain = _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);
- }
-
- } else if (_gain == 0) {
- for (BufferSet::audio_iterator i = bufs.audio_begin(); i != bufs.audio_end(); ++i) {
- i->clear();
- }
- }
+ if (!_processors.empty()) {
+ bufs.set_count(ChanCount::max(bufs.count(), _processors.back()->output_streams()));
}
-
- } else {
-
- /* actively recording, no monitoring required; leave buffers as-is to save CPU cycles */
-
}
+
/* -------------------------------------------------------------------------------------------
- POST-FADER REDIRECTS
- ----------------------------------------------------------------------------------------- */
-
- /* note that post_fader_work cannot be true unless with_processors was also true,
- so don't test both
- */
-
- if (post_fader_work) {
-
- Glib::RWLock::ReaderLock rm (_processor_lock, Glib::TRY_LOCK);
- if (rm.locked()) {
- if (mute_gain > 0 || !_mute_affects_post_fader) {
- for (i = _processors.begin(); i != _processors.end(); ++i) {
- switch ((*i)->placement()) {
- case PreFader:
- break;
- case PostFader:
- (*i)->run_in_place (bufs, start_frame, end_frame, nframes);
- break;
- }
- }
- } else {
- for (i = _processors.begin(); i != _processors.end(); ++i) {
- switch ((*i)->placement()) {
- case PreFader:
- break;
- case PostFader:
- (*i)->silence (nframes);
- break;
- }
- }
- }
- }
- }
-
- if (!_soloed && (mute_gain != dmg) && !mute_declick_applied && _mute_affects_control_outs) {
- Amp::run_in_place (bufs, nframes, mute_gain, dmg, false);
- mute_gain = dmg;
- mute_declick_applied = true;
- }
-
- /* -------------------------------------------------------------------------------------------
- CONTROL OUTPUT STAGE
- ----------------------------------------------------------------------------------------- */
-
- if ((_meter_point == MeterPostFader) && co) {
-
- solo_audible = solo_gain > 0;
- mute_audible = dmg > 0 || !_mute_affects_control_outs;
-
- if ( // silent anyway
-
- (_gain == 0 && !apply_gain_automation) ||
-
- // muted by solo of another track
-
- !solo_audible ||
-
- // muted by mute of this track
-
- !mute_audible ||
-
- // recording but not s/w monitoring
-
- ( no_monitor && record_enabled()
- && (!Config->get_auto_input() || _session.actively_recording()) )
-
- ) {
-
- co->silence (nframes);
-
- } else {
-
- co->deliver_output (bufs, start_frame, end_frame, nframes);
- }
- }
-
- /* -------------------------------------------------------------------------------------------
- GLOBAL MUTE
+ POST-FADER MUTING
----------------------------------------------------------------------------------------- */
if (!_soloed && (mute_gain != dmg) && !mute_declick_applied && _mute_affects_main_outs) {
- Amp::run_in_place (bufs, nframes, mute_gain, dmg, false);
+ 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);
+ }
+
/* -------------------------------------------------------------------------------------------
MAIN OUTPUT STAGE
----------------------------------------------------------------------------------------- */
- solo_audible = dsg > 0;
- mute_audible = dmg > 0 || !_mute_affects_main_outs;
+ bool solo_audible = dsg > 0;
+ bool mute_audible = dmg > 0 || !_mute_affects_main_outs;
if (n_outputs().get(_default_type) == 0) {
/* relax */
- } else if (no_monitor && record_enabled()
- && (!Config->get_auto_input() || _session.actively_recording())) {
-
+ } else if (recording_without_monitoring) {
+
IO::silence (nframes);
-
- } else {
- if ( // silent anyway
+ } else {
- (_gain == 0 && !apply_gain_automation) ||
+ if ( // we're silent anyway
+ (_gain == 0 && !_amp->apply_gain_automation()) ||
- // muted by solo of another track, but not using control outs for solo
-
+ // or muted by solo of another track, but not using control outs for solo
(!solo_audible && (Config->get_solo_model() != SoloBus)) ||
- // muted by mute of this track
-
+ // or muted by mute of this track
!mute_audible
-
) {
/* don't use Route::silence() here, because that causes
all outputs (sends, port processors, etc. to be silent).
*/
-
- if (_meter_point == MeterPostFader) {
- peak_meter().reset();
- }
-
IO::silence (nframes);
} else {
@@ -731,321 +499,19 @@ Route::process_output_buffers (BufferSet& bufs,
POST-FADER METERING
----------------------------------------------------------------------------------------- */
+ /* TODO: Processor-list-ification needs to go further for this to be cleanly possible...
if (meter && (_meter_point == MeterPostFader)) {
if ((_gain == 0 && !apply_gain_automation) || dmg == 0) {
_meter->reset();
} else {
_meter->run_in_place(output_buffers(), start_frame, end_frame, nframes);
}
- }
-}
-
-#ifdef NEW_POB
-/** Process this route for one (sub) cycle (process thread)
- *
- * @param bufs Scratch buffers to use for the signal path
- * @param start_frame Initial transport frame
- * @param end_frame Final transport frame
- * @param nframes Number of frames to output (to ports)
- *
- * Note that (end_frame - start_frame) may not be equal to nframes when the
- * transport speed isn't 1.0 (eg varispeed).
- */
-void
-Route::process_output_buffers (BufferSet& bufs,
- nframes_t start_frame, nframes_t end_frame, nframes_t nframes,
- bool with_processors, int declick, bool meter)
-{
- // This is definitely very audio-only for now
- assert(_default_type == DataType::AUDIO);
-
- ProcessorList::iterator i;
- bool post_fader_work = false;
- bool mute_declick_applied = false;
- gain_t dmg, dsg, dg;
- IO *co;
- bool mute_audible;
- bool solo_audible;
- bool no_monitor;
- gain_t* gab = _session.gain_automation_buffer();
-
- switch (Config->get_monitoring_model()) {
- case HardwareMonitoring:
- case ExternalMonitoring:
- no_monitor = true;
- break;
- default:
- no_monitor = false;
- }
-
- declick = _pending_declick;
-
- {
- Glib::Mutex::Lock cm (_control_outs_lock, Glib::TRY_LOCK);
-
- if (cm.locked()) {
- co = _control_outs;
- } else {
- co = 0;
- }
- }
-
- {
- Glib::Mutex::Lock dm (declick_lock, Glib::TRY_LOCK);
-
- if (dm.locked()) {
- dmg = desired_mute_gain;
- dsg = desired_solo_gain;
- dg = _desired_gain;
- } else {
- dmg = mute_gain;
- dsg = solo_gain;
- dg = _gain;
- }
- }
-
- /* -------------------------------------------------------------------------------------------
- GLOBAL DECLICK (for transport changes etc.)
- input metering & monitoring (control outs)
- denormal control
- pre-fader redirects
- pre-fader metering & monitoring (control outs)
- gain stage
- post-fader redirects
- global mute
- main output
- post-fader metering & monitoring (control outs)
- ----------------------------------------------------------------------------------------- */
-
- {
- Glib::RWLock::ReaderLock rm (_processor_lock, Glib::TRY_LOCK);
- for (i = processors.begin(); i != processors.end(); ++i) {
- (*i)->run_in_place (bufs, start_frame, end_frame, nframes);
- }
- }
-
-
- /* -------------------------------------------------------------------------------------------
- INPUT METERING & MONITORING
- ----------------------------------------------------------------------------------------- */
-
- if (meter && (_meter_point == MeterInput)) {
- _meter->run_in_place(bufs, start_frame, end_frame, nframes);
- }
-
- if (!_soloed && _mute_affects_pre_fader && (mute_gain != dmg)) {
- Amp::run_in_place (bufs, nframes, mute_gain, dmg, false);
- mute_gain = dmg;
- mute_declick_applied = true;
- }
-
- /* -------------------------------------------------------------------------------------------
- PRE-FADER REDIRECTS
- ----------------------------------------------------------------------------------------- */
-
- // This really should already be true...
- bufs.set_count(pre_fader_streams());
-
-
- if ((_meter_point == MeterPreFader) && co) {
-
- solo_audible = dsg > 0;
- mute_audible = dmg > 0 || !_mute_affects_pre_fader;
-
- if ( // muted by solo of another track
-
- !solo_audible ||
-
- // muted by mute of this track
-
- !mute_audible ||
-
- // rec-enabled but not s/w monitoring
-
- ( no_monitor && record_enabled()
- && (!Config->get_auto_input() || _session.actively_recording()) )
-
- ) {
-
- co->silence (nframes);
-
- } else {
-
- co->deliver_output (bufs, start_frame, end_frame, nframes);
- }
- }
-
- /* -------------------------------------------------------------------------------------------
- GAIN STAGE
- ----------------------------------------------------------------------------------------- */
-
- /* if not recording or recording and requiring any monitor signal, then apply gain */
-
- if ( // not recording
-
- !(record_enabled() && _session.actively_recording()) ||
-
- // OR recording
-
- // AND software monitoring required
-
- Config->get_monitoring_model() == SoftwareMonitoring) {
-
- if (apply_gain_automation) {
-
- if (_phase_invert) {
- 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];
- }
- }
- } 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] *= gab[nx];
- }
- }
- }
-
- if (apply_gain_automation && _session.transport_rolling() && nframes > 0) {
- _effective_gain = gab[nframes-1];
- }
-
- } else {
-
- /* manual (scalar) gain */
-
- if (_gain != dg) {
-
- Amp::run_in_place (bufs, nframes, _gain, dg, _phase_invert);
- _gain = dg;
-
- } else if (_gain != 0 && (_phase_invert || _gain != 1.0)) {
-
- /* 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_t this_gain;
-
- if (_phase_invert) {
- this_gain = -_gain;
- } else {
- this_gain = _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);
- }
-
- } else if (_gain == 0) {
- for (BufferSet::audio_iterator i = bufs.audio_begin(); i != bufs.audio_end(); ++i) {
- i->clear();
- }
- }
- }
-
- } else {
-
- /* actively recording, no monitoring required; leave buffers as-is to save CPU cycles */
-
- }
-
- /* -------------------------------------------------------------------------------------------
- CONTROL OUTPUT STAGE
- ----------------------------------------------------------------------------------------- */
-
- if ((_meter_point == MeterPostFader) && co) {
-
- solo_audible = solo_gain > 0;
- mute_audible = dmg > 0 || !_mute_affects_control_outs;
-
- if ( // silent anyway
-
- (_gain == 0 && !apply_gain_automation) ||
-
- // muted by solo of another track
-
- !solo_audible ||
-
- // muted by mute of this track
-
- !mute_audible ||
-
- // recording but not s/w monitoring
-
- (no_monitor && record_enabled() && (!Config->get_auto_input() || _session.actively_recording()))
+ }*/
- ) {
-
- co->silence (nframes);
-
- } else {
-
- co->deliver_output (bufs, start_frame, end_frame, nframes);
- }
- }
-
- /* -------------------------------------------------------------------------------------------
- MAIN OUTPUT STAGE
- ----------------------------------------------------------------------------------------- */
-
- solo_audible = dsg > 0;
- mute_audible = dmg > 0 || !_mute_affects_main_outs;
-
- if (n_outputs().get(_default_type) == 0) {
-
- /* relax */
-
- } else if (no_monitor && record_enabled()
- && (!Config->get_auto_input() || _session.actively_recording())) {
-
- IO::silence (nframes);
-
- } else {
-
- if ( // silent anyway
-
- (_gain == 0 && !apply_gain_automation) ||
-
- // muted by solo of another track, but not using control outs for solo
-
- (!solo_audible && (Config->get_solo_model() != SoloBus)) ||
-
- // muted by mute of this track
-
- !mute_audible
-
- ) {
-
- /* don't use Route::silence() here, because that causes
- all outputs (sends, port processors, etc. to be silent).
- */
-
- if (_meter_point == MeterPostFader) {
- peak_meter().reset();
- }
-
- IO::silence (nframes);
-
- } else {
-
- deliver_output(bufs, start_frame, end_frame, nframes);
-
- }
-
- }
+ // at this point we've reached the desired mute gain regardless
+ mute_gain = dmg;
}
-#endif /* NEW_POB */
-
ChanCount
Route::n_process_buffers ()
{
@@ -1061,7 +527,7 @@ Route::setup_peak_meters()
}
void
-Route::passthru (nframes_t start_frame, nframes_t end_frame, nframes_t nframes, int declick, bool meter_first)
+Route::passthru (nframes_t start_frame, nframes_t end_frame, nframes_t nframes, int declick)
{
BufferSet& bufs = _session.get_scratch_buffers(n_process_buffers());
@@ -1069,20 +535,13 @@ Route::passthru (nframes_t start_frame, nframes_t end_frame, nframes_t nframes,
collect_input (bufs, nframes);
- if (meter_first) {
- _meter->run_in_place(bufs, start_frame, end_frame, nframes);
- meter_first = false;
- } else {
- meter_first = true;
- }
-
- process_output_buffers (bufs, start_frame, end_frame, nframes, true, declick, meter_first);
+ process_output_buffers (bufs, start_frame, end_frame, nframes, true, declick);
}
void
-Route::passthru_silence (nframes_t start_frame, nframes_t end_frame, nframes_t nframes, int declick, bool meter)
+Route::passthru_silence (nframes_t start_frame, nframes_t end_frame, nframes_t nframes, int declick)
{
- process_output_buffers (_session.get_silent_buffers (n_process_buffers()), start_frame, end_frame, nframes, true, declick, meter);
+ process_output_buffers (_session.get_silent_buffers (n_process_buffers()), start_frame, end_frame, nframes, true, declick);
}
void
@@ -1114,7 +573,6 @@ Route::catch_up_on_solo_mute_override ()
}
{
-
Glib::Mutex::Lock lm (declick_lock);
if (_muted) {
@@ -1166,7 +624,7 @@ Route::set_mute (bool yn, void *src)
Glib::Mutex::Lock lm (declick_lock);
- if (_soloed && Config->get_solo_mute_override()){
+ if (_soloed && Config->get_solo_mute_override()) {
desired_mute_gain = 1.0f;
} else {
desired_mute_gain = (yn?0.0f:1.0f);
@@ -1174,8 +632,24 @@ Route::set_mute (bool yn, void *src)
}
}
+static void
+dump_processors(const string& name, const list<boost::shared_ptr<Processor> >& procs)
+{
+ cerr << name << " {" << endl;
+ for (list<boost::shared_ptr<Processor> >::const_iterator p = procs.begin();
+ p != procs.end(); ++p) {
+ cerr << "\t" << (*p)->sort_key() << ": " << (*p)->name() << endl;
+ }
+ cerr << "}" << endl;
+}
+
+/** Add a processor to the route.
+ * If @a iter is not NULL, it must point to an iterator in _processors and the new
+ * processor will be inserted immediately before this location. Otherwise,
+ * @a position is used.
+ */
int
-Route::add_processor (boost::shared_ptr<Processor> processor, ProcessorStreams* err)
+Route::add_processor (boost::shared_ptr<Processor> processor, ProcessorStreams* err, ProcessorList::iterator* iter, Placement placement)
{
ChanCount old_pms = processor_max_streams;
@@ -1189,18 +663,66 @@ Route::add_processor (boost::shared_ptr<Processor> processor, ProcessorStreams*
boost::shared_ptr<PluginInsert> pi;
boost::shared_ptr<PortInsert> porti;
- //processor->set_default_type(_default_type);
+ ProcessorList::iterator loc = find(_processors.begin(), _processors.end(), processor);
+
+ if (processor == _amp || processor == _meter) {
+ // Ensure only one amp and one meter are in the list at any time
+ if (loc != _processors.end()) {
+ if (iter) {
+ if (*iter == loc) { // Already in place, do nothing
+ return 0;
+ } else { // New position given, relocate
+ _processors.erase(loc);
+ }
+ } else { // Insert at end
+ _processors.erase(loc);
+ loc = _processors.end();
+ }
+ }
+
+ } else {
+ if (loc != _processors.end()) {
+ cerr << "ERROR: Processor added to route twice!" << endl;
+ return 1;
+ }
+ }
+
+ // Use position given by user
+ if (iter) {
+ loc = *iter;
+
+ // Insert immediately before the amp
+ } else if (placement == PreFader) {
+ loc = find(_processors.begin(), _processors.end(), _amp);
+
+ // Insert at end
+ } else {
+ loc = _processors.end();
+ }
+
+ // Update sort keys
+ if (loc == _processors.end()) {
+ processor->set_sort_key(_processors.size());
+ } else {
+ processor->set_sort_key((*loc)->sort_key());
+ for (ProcessorList::iterator p = loc; p != _processors.end(); ++p) {
+ (*p)->set_sort_key((*p)->sort_key() + 1);
+ }
+ }
- _processors.push_back (processor);
+ _processors.insert(loc, processor);
// Set up processor list channels. This will set processor->[input|output]_streams(),
// configure redirect ports properly, etc.
- if (_reset_processor_counts (err)) {
- _processors.pop_back ();
- _reset_processor_counts (0); // it worked before we tried to add it ...
+ if (configure_processors_unlocked (err)) {
+ dump_processors(_name, _processors);
+ ProcessorList::iterator ploc = loc;
+ --ploc;
+ _processors.erase(ploc);
+ configure_processors_unlocked (0); // it worked before we tried to add it ...
return -1;
}
-
+
if ((pi = boost::dynamic_pointer_cast<PluginInsert>(processor)) != 0) {
if (pi->natural_input_streams() == ChanCount::ZERO) {
@@ -1211,13 +733,8 @@ Route::add_processor (boost::shared_ptr<Processor> processor, ProcessorStreams*
}
// Ensure peak vector sizes before the plugin is activated
-
- ChanCount potential_max_streams;
-
- potential_max_streams.set (DataType::AUDIO, max (processor->input_streams().n_audio(),
- processor->output_streams().n_audio()));
- potential_max_streams.set (DataType::MIDI, max (processor->input_streams().n_midi(),
- processor->output_streams().n_midi()));
+ ChanCount potential_max_streams = ChanCount::max(
+ processor->input_streams(), processor->output_streams());
_meter->configure_io (potential_max_streams, potential_max_streams);
@@ -1232,13 +749,15 @@ Route::add_processor (boost::shared_ptr<Processor> processor, ProcessorStreams*
reset_panner ();
}
+ dump_processors (_name, _processors);
processors_changed (); /* EMIT SIGNAL */
+
return 0;
}
int
-Route::add_processors (const ProcessorList& others, ProcessorStreams* err)
+Route::add_processors (const ProcessorList& others, ProcessorStreams* err, Placement placement)
{
/* NOTE: this is intended to be used ONLY when copying
processors from another Route. Hence the subtle
@@ -1257,10 +776,18 @@ Route::add_processors (const ProcessorList& others, ProcessorStreams* err)
ProcessorList::iterator existing_end = _processors.end();
--existing_end;
- ChanCount potential_max_streams;
+ ChanCount potential_max_streams = ChanCount::max(input_minimum(), output_minimum());
for (ProcessorList::const_iterator i = others.begin(); i != others.end(); ++i) {
+ // Ensure meter only appears in the list once
+ if (*i == _meter) {
+ ProcessorList::iterator m = find(_processors.begin(), _processors.end(), *i);
+ if (m != _processors.end()) {
+ _processors.erase(m);
+ }
+ }
+
boost::shared_ptr<PluginInsert> pi;
if ((pi = boost::dynamic_pointer_cast<PluginInsert>(*i)) != 0) {
@@ -1274,12 +801,16 @@ Route::add_processors (const ProcessorList& others, ProcessorStreams* err)
// Ensure peak vector sizes before the plugin is activated
_meter->configure_io (potential_max_streams, potential_max_streams);
- _processors.push_back (*i);
+ ProcessorList::iterator loc = (placement == PreFader)
+ ? find(_processors.begin(), _processors.end(), _amp)
+ : _processors.end();
+
+ _processors.insert (loc, *i);
- if (_reset_processor_counts (err)) {
+ if (configure_processors_unlocked (err)) {
++existing_end;
_processors.erase (existing_end, _processors.end());
- _reset_processor_counts (0); // it worked before we tried to add it ...
+ configure_processors_unlocked (0); // it worked before we tried to add it ...
return -1;
}
@@ -1292,11 +823,26 @@ Route::add_processors (const ProcessorList& others, ProcessorStreams* err)
if (processor_max_streams != old_pms || old_pms == ChanCount::ZERO) {
reset_panner ();
}
-
+
+ dump_processors (_name, _processors);
processors_changed (); /* EMIT SIGNAL */
+
return 0;
}
+void
+Route::placement_range(Placement p, ProcessorList::iterator& start, ProcessorList::iterator& end)
+{
+ if (p == PreFader) {
+ start = _processors.begin();
+ end = find(_processors.begin(), _processors.end(), _amp);
+ } else {
+ start = find(_processors.begin(), _processors.end(), _amp);
+ ++start;
+ end = _processors.end();
+ }
+}
+
/** Turn off all processors with a given placement
* @param p Placement of processors to disable
*/
@@ -1305,10 +851,11 @@ Route::disable_processors (Placement p)
{
Glib::RWLock::ReaderLock lm (_processor_lock);
- for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
- if ((*i)->placement() == p) {
- (*i)->deactivate ();
- }
+ ProcessorList::iterator start, end;
+ placement_range(p, start, end);
+
+ for (ProcessorList::iterator i = start; i != end; ++i) {
+ (*i)->deactivate ();
}
_session.set_dirty ();
@@ -1336,8 +883,11 @@ Route::disable_plugins (Placement p)
{
Glib::RWLock::ReaderLock lm (_processor_lock);
- for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
- if (boost::dynamic_pointer_cast<PluginInsert> (*i) && (*i)->placement() == p) {
+ ProcessorList::iterator start, end;
+ placement_range(p, start, end);
+
+ for (ProcessorList::iterator i = start; i != end; ++i) {
+ if (boost::dynamic_pointer_cast<PluginInsert> (*i)) {
(*i)->deactivate ();
}
}
@@ -1417,7 +967,10 @@ Route::pre_fader_streams() const
/* Find the last pre-fader redirect that isn't a send; sends don't affect the number
* of streams. */
for (ProcessorList::const_iterator i = _processors.begin(); i != _processors.end(); ++i) {
- if ((*i)->placement() == PreFader && boost::dynamic_pointer_cast<Send> (*i) == 0) {
+ if ((*i) == _amp) {
+ break;
+ }
+ if (boost::dynamic_pointer_cast<Send> (*i) == 0) {
processor = *i;
}
}
@@ -1441,21 +994,38 @@ Route::clear_processors (Placement p)
if (!_session.engine().connected()) {
return;
}
+
+ bool already_deleting = _session.deletion_in_progress();
+ if (!already_deleting) {
+ _session.set_deletion_in_progress();
+ }
{
Glib::RWLock::WriterLock lm (_processor_lock);
ProcessorList new_list;
- for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
- if ((*i)->placement() == p) {
- /* it's the placement we want to get rid of */
+ ProcessorList::iterator amp_loc = find(_processors.begin(), _processors.end(), _amp);
+ if (p == PreFader) {
+ // Get rid of PreFader processors
+ for (ProcessorList::iterator i = _processors.begin(); i != amp_loc; ++i) {
(*i)->drop_references ();
- } else {
- /* it's a different placement, so keep it */
+ }
+ // Keep the rest
+ for (ProcessorList::iterator i = amp_loc; i != _processors.end(); ++i) {
+ new_list.push_back (*i);
+ }
+ } else {
+ // Keep PreFader processors
+ for (ProcessorList::iterator i = _processors.begin(); i != amp_loc; ++i) {
new_list.push_back (*i);
}
+ new_list.push_back (_amp);
+ // Get rid of PostFader processors
+ for (ProcessorList::iterator i = amp_loc; i != _processors.end(); ++i) {
+ (*i)->drop_references ();
+ }
}
-
+
_processors = new_list;
}
@@ -1467,11 +1037,19 @@ Route::clear_processors (Placement p)
processor_max_streams.reset();
_have_internal_generator = false;
processors_changed (); /* EMIT SIGNAL */
+
+ if (!already_deleting) {
+ _session.clear_deletion_in_progress();
+ }
}
int
Route::remove_processor (boost::shared_ptr<Processor> processor, ProcessorStreams* err)
{
+ if (processor == _amp || processor == _meter) {
+ return 0;
+ }
+
ChanCount old_pms = processor_max_streams;
if (!_session.engine().connected()) {
@@ -1490,7 +1068,7 @@ Route::remove_processor (boost::shared_ptr<Processor> processor, ProcessorStream
ProcessorList::iterator tmp;
- /* move along, see failure case for reset_processor_counts()
+ /* move along, see failure case for configure_processors()
where we may need to reprocessor the processor.
*/
@@ -1524,11 +1102,11 @@ Route::remove_processor (boost::shared_ptr<Processor> processor, ProcessorStream
return 1;
}
- if (_reset_processor_counts (err)) {
+ if (configure_processors_unlocked (err)) {
/* get back to where we where */
_processors.insert (i, processor);
/* we know this will work, because it worked before :) */
- _reset_processor_counts (0);
+ configure_processors_unlocked (0);
return -1;
}
@@ -1551,224 +1129,72 @@ Route::remove_processor (boost::shared_ptr<Processor> processor, ProcessorStream
}
processor->drop_references ();
-
+
+ dump_processors (_name, _processors);
processors_changed (); /* EMIT SIGNAL */
- return 0;
-}
-int
-Route::reset_processor_counts (ProcessorStreams* err)
-{
- Glib::RWLock::WriterLock lm (_processor_lock);
- return _reset_processor_counts (err);
+ return 0;
}
-
int
-Route::_reset_processor_counts (ProcessorStreams* err)
-{
- ProcessorList::iterator r;
- uint32_t insert_cnt = 0;
- uint32_t send_cnt = 0;
- map<Placement,list<ProcessorCount> > proc_map;
- ProcessorList::iterator prev;
- ChanCount initial_streams = n_inputs ();
- ChanCount previous_initial_streams = n_inputs ();
- int ret = -1;
- uint32_t max_audio = 0;
- uint32_t max_midi = 0;
-
- processor_max_streams.reset ();
-
- /* Step 1: build a map that links each insert to an in/out channel count
-
- Divide inserts up by placement so we get the signal flow
- properly modelled. we need to do this because the _processors
- list is not sorted by placement, and because other reasons may
- exist now or in the future for this separate treatment.
- */
-
- /* ... but it should/will be... */
-
- for (r = _processors.begin(); r != _processors.end(); ++r) {
-
- boost::shared_ptr<PluginInsert> plugin_insert;
- boost::shared_ptr<PortInsert> port_insert;
-
- if ((plugin_insert = boost::dynamic_pointer_cast<PluginInsert>(*r)) != 0) {
-
- ++insert_cnt;
- proc_map[(*r)->placement()].push_back (ProcessorCount (*r));
-
- /* reset plugin counts back to one for now so
- that we have a predictable, controlled
- state to try to configure.
- */
-
- plugin_insert->set_count (1);
-
- } else if ((port_insert = boost::dynamic_pointer_cast<PortInsert>(*r)) != 0) {
-
- ++insert_cnt;
- proc_map[(*r)->placement()].push_back (ProcessorCount (*r));
-
- } else if (boost::dynamic_pointer_cast<Send> (*r) != 0) {
- ++send_cnt;
- }
- }
-
- if (insert_cnt == 0) {
- if (send_cnt) {
- goto recompute;
- } else {
- ret = 0;
- goto streamcount;
- }
- }
-
- /* Now process each placement in order, checking to see if we
- can really do what has been requested.
- */
-
- /* A: PreFader */
-
- if (check_some_processor_counts (proc_map[PreFader], n_inputs (), err)) {
- goto streamcount;
- }
-
- if (!proc_map[PreFader].empty()) {
- previous_initial_streams = n_inputs ();
- for (list<ProcessorCount>::iterator i = proc_map[PreFader].begin(); i != proc_map[PreFader].end(); i++) {
- if (i->processor->can_support_io_configuration (previous_initial_streams, initial_streams) == false) {
- goto streamcount;
- }
- previous_initial_streams = initial_streams;
- }
- }
-
- /* B: PostFader */
-
- if (check_some_processor_counts (proc_map[PostFader], initial_streams, err)) {
- goto streamcount;
- }
-
- if (!proc_map[PostFader].empty()) {
- for (list<ProcessorCount>::iterator i = proc_map[PostFader].begin(); i != proc_map[PostFader].end(); i++) {
- if (i->processor->can_support_io_configuration (previous_initial_streams, initial_streams) == false) {
- goto streamcount;
- }
- previous_initial_streams = initial_streams;
- }
- }
-
- /* OK, everything can be set up correctly, so lets do it */
-
- apply_some_processor_counts (proc_map[PreFader]);
- apply_some_processor_counts (proc_map[PostFader]);
-
- /* recompute max outs of any processor */
-
- ret = 0;
-
- recompute:
-
- processor_max_streams.reset ();
- prev = _processors.end();
-
- for (r = _processors.begin(); r != _processors.end(); prev = r, ++r) {
- boost::shared_ptr<Send> s;
-
- if ((s = boost::dynamic_pointer_cast<Send> (*r)) != 0) {
-
- /* don't pay any attention to send output configuration, since it doesn't
- affect the route.
- */
-
- if (r == _processors.begin()) {
- s->expect_inputs (n_inputs());
- } else {
- s->expect_inputs ((*prev)->output_streams());
- }
-
- } else {
-
- max_audio = max ((*r)->input_streams ().n_audio(), max_audio);
- max_midi = max ((*r)->input_streams ().n_midi(), max_midi);
- max_audio = max ((*r)->output_streams ().n_audio(), max_audio);
- max_midi = max ((*r)->output_streams ().n_midi(), max_midi);
- }
- }
-
- processor_max_streams.set (DataType::AUDIO, max_audio);
- processor_max_streams.set (DataType::MIDI, max_midi);
-
- /* we're done */
- return 0;
-
- streamcount:
- for (r = _processors.begin(); r != _processors.end(); ++r) {
- max_audio = max ((*r)->output_streams ().n_audio(), max_audio);
- max_midi = max ((*r)->output_streams ().n_midi(), max_midi);
- }
-
- processor_max_streams.set (DataType::AUDIO, max_audio);
- processor_max_streams.set (DataType::MIDI, max_midi);
-
- return ret;
-}
-
-int32_t
-Route::apply_some_processor_counts (list<ProcessorCount>& iclist)
+Route::configure_processors (ProcessorStreams* err)
{
- list<ProcessorCount>::iterator i;
-
- for (i = iclist.begin(); i != iclist.end(); ++i) {
-
- ProcessorCount& pc (*i);
-
- if (pc.processor->configure_io (pc.in, pc.out)) {
- return -1;
- }
-
- /* make sure that however many we have, they are all active */
-
- pc.processor->activate ();
+ if (!_in_configure_processors) {
+ Glib::RWLock::WriterLock lm (_processor_lock);
+ return configure_processors_unlocked (err);
}
-
return 0;
}
-/** Returns whether \a iclist can be configured and run starting with
- * \a required_inputs at the first processor's inputs.
- * If false is returned, \a iclist can not be run with \a required_inputs, and \a err is set.
- * Otherwise, \a err is set to the output of the list.
+/** Configure the input/output configuration of each processor in the processors list.
+ * Return 0 on success, otherwise configuration is impossible.
*/
-bool
-Route::check_some_processor_counts (list<ProcessorCount>& iclist, ChanCount required_inputs, ProcessorStreams* err)
+int
+Route::configure_processors_unlocked (ProcessorStreams* err)
{
- list<ProcessorCount>::iterator i;
- size_t index = 0;
-
- if (err) {
- err->index = 0;
- err->count = required_inputs;
+ if (_in_configure_processors) {
+ return 0;
}
- for (i = iclist.begin(); i != iclist.end(); ++i, ++index) {
+ _in_configure_processors = true;
- if (!(*i).processor->can_support_io_configuration (required_inputs, (*i).out)) {
+ // Check each processor in order to see if we can configure as requested
+ ChanCount in = _configured_inputs;
+ ChanCount out;
+ list< pair<ChanCount,ChanCount> > configuration;
+ uint32_t index = 0;
+ for (ProcessorList::iterator p = _processors.begin(); p != _processors.end(); ++p, ++index) {
+ (*p)->set_sort_key(index);
+ if ((*p)->can_support_io_configuration(in, out)) {
+ configuration.push_back(make_pair(in, out));
+ in = out;
+ } else {
if (err) {
err->index = index;
- err->count = required_inputs;
+ err->count = in;
}
- return true;
+ _in_configure_processors = false;
+ return -1;
}
-
- (*i).in = required_inputs;
- required_inputs = (*i).out;
+ }
+
+ // We can, so configure everything
+ list< pair<ChanCount,ChanCount> >::iterator c = configuration.begin();
+ for (ProcessorList::iterator p = _processors.begin(); p != _processors.end(); ++p, ++c) {
+ (*p)->configure_io(c->first, c->second);
+ (*p)->activate();
+ processor_max_streams = ChanCount::max(processor_max_streams, c->first);
+ processor_max_streams = ChanCount::max(processor_max_streams, c->second);
+ out = c->second;
}
- return false;
+ // Ensure route outputs match last processor's outputs
+ if (out != n_outputs()) {
+ ensure_io(_configured_inputs, out, false, this);
+ }
+
+ _in_configure_processors = false;
+ return 0;
}
void
@@ -1805,9 +1231,16 @@ Route::all_processors_active (Placement p, bool state)
if (_processors.empty()) {
return;
}
+ ProcessorList::iterator start, end;
+ placement_range(p, start, end);
+ bool before_amp = true;
for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
- if ((*i)->placement() == p) {
+ if ((*i) == _amp) {
+ before_amp = false;
+ continue;
+ }
+ if (p == PreFader && before_amp) {
if (state) {
(*i)->activate ();
} else {
@@ -1839,7 +1272,7 @@ Route::sort_processors (ProcessorStreams* err)
_processors.sort (comparator);
- if (_reset_processor_counts (err)) {
+ if (configure_processors_unlocked (err)) {
_processors = as_it_was_before;
processor_max_streams = old_pms;
return -1;
@@ -1925,7 +1358,7 @@ Route::state(bool full_state)
if (_control_outs) {
XMLNode* cnode = new XMLNode (X_("ControlOuts"));
- cnode->add_child_nocopy (_control_outs->state (full_state));
+ cnode->add_child_nocopy (_control_outs->io()->state (full_state));
node->add_child_nocopy (*cnode);
}
@@ -2033,8 +1466,8 @@ Route::set_deferred_state ()
deferred_state = 0;
}
-void
-Route::add_processor_from_xml (const XMLNode& node)
+bool
+Route::add_processor_from_xml (const XMLNode& node, ProcessorList::iterator* iter)
{
const XMLProperty *prop;
@@ -2043,15 +1476,15 @@ Route::add_processor_from_xml (const XMLNode& node)
try {
boost::shared_ptr<Send> send (new Send (_session, node));
- add_processor (send);
+ add_processor (send, 0, iter);
+ return true;
}
catch (failed_constructor &err) {
error << _("Send construction failed") << endmsg;
- return;
+ return false;
}
- // use "Processor" in XML?
} else if (node.name() == "Processor") {
try {
@@ -2076,13 +1509,21 @@ Route::add_processor_from_xml (const XMLNode& node)
processor.reset (new Send (_session, node));
have_insert = true;
+
+ } else if (prop->value() == "meter") {
+
+ processor = _meter;
+
+ } else if (prop->value() == "amp") {
+
+ processor = _amp;
} else {
error << string_compose(_("unknown Processor type \"%1\"; ignored"), prop->value()) << endmsg;
}
- add_processor (processor);
+ return (add_processor (processor, 0, iter) == 0);
} else {
error << _("Processor XML node has no type property") << endmsg;
@@ -2091,9 +1532,10 @@ Route::add_processor_from_xml (const XMLNode& node)
catch (failed_constructor &err) {
warning << _("processor could not be created. Ignored.") << endmsg;
- return;
+ return false;
}
}
+ return false;
}
int
@@ -2238,6 +1680,7 @@ Route::_set_state (const XMLNode& node, bool call_base)
}
XMLNodeList processor_nodes;
+ bool has_meter_processor = false; // legacy sessions don't
for (niter = nlist.begin(); niter != nlist.end(); ++niter){
@@ -2245,12 +1688,18 @@ Route::_set_state (const XMLNode& node, bool call_base)
if (child->name() == X_("Send") || child->name() == X_("Processor")) {
processor_nodes.push_back(child);
+ if ((prop = child->property (X_("type"))) != 0 && prop->value() == "meter") {
+ has_meter_processor = true;
+ }
}
}
_set_processor_states(processor_nodes);
-
+ if (!has_meter_processor) {
+ set_meter_point(_meter_point, NULL);
+ }
+ processors_changed ();
for (niter = nlist.begin(); niter != nlist.end(); ++niter){
child = *niter;
@@ -2267,8 +1716,8 @@ Route::_set_state (const XMLNode& node, bool call_base)
string coutname = _name;
coutname += _("[control]");
- delete _control_outs;
- _control_outs = new IO (_session, coutname);
+ _control_outs = boost::shared_ptr<ControlOutputs> (
+ new ControlOutputs (_session, new IO (_session, coutname)));
/* fix up the control out name in the XML before setting it.
Otherwise track templates don't work because the control
@@ -2281,7 +1730,9 @@ Route::_set_state (const XMLNode& node, bool call_base)
prop->set_value (coutname);
}
- _control_outs->set_state (**(child->children().begin()));
+ _control_outs->io()->set_state (**(child->children().begin()));
+ _control_outs->set_sort_key (_meter->sort_key() + 1);
+ add_processor (_control_outs, 0);
} else if (child->name() == X_("Comment")) {
@@ -2303,8 +1754,7 @@ Route::_set_state (const XMLNode& node, bool call_base)
_mute_control->set_state (*child);
_session.add_controllable (_mute_control);
}
- }
- else if (child->name() == X_("RemoteControl")) {
+ } else if (child->name() == X_("RemoteControl")) {
if ((prop = child->property (X_("id"))) != 0) {
int32_t x;
sscanf (prop->value().c_str(), "%d", &x);
@@ -2365,6 +1815,7 @@ Route::_set_processor_states(const XMLNodeList &nlist)
i = tmp;
}
+ Placement placement = PreFader;
// Iterate through state list and make sure all processors are on the track and in the correct order,
// set the state of existing processors according to the new state on the same go
@@ -2389,50 +1840,33 @@ Route::_set_processor_states(const XMLNodeList &nlist)
++o;
}
+ // If the processor (*niter) is not on the route,
+ // create it and move it to the correct location
if (o == _processors.end()) {
- // If the processor (*niter) is not on the route, we need to create it
- // and move it to the correct location
-
- ProcessorList::iterator prev_last = _processors.end();
- --prev_last; // We need this to check whether adding succeeded
-
- add_processor_from_xml (**niter);
-
- ProcessorList::iterator last = _processors.end();
- --last;
+ if (add_processor_from_xml (**niter, &i)) {
+ --i; // move iterator to the newly inserted processor
+ } else {
+ cerr << "Error restoring route: unable to restore processor" << endl;
+ }
- if (prev_last == last) {
- cerr << "Could not fully restore state as some processors were not possible to create" << endl;
- continue;
+ // Otherwise, we found the processor (*niter) on the route,
+ // ensure it is at the location provided in the XML state
+ } else {
+ if (i != o) {
+ boost::shared_ptr<Processor> tmp = (*o);
+ _processors.erase(o); // remove the old copy
+ _processors.insert(i, tmp); // insert the processor at the correct location
+ --i; // move iterator to the correct processor
}
- boost::shared_ptr<Processor> tmp = (*last);
- // remove the processor from the wrong location
- _processors.erase(last);
- // processor the new processor at the current location
- _processors.insert(i, tmp);
-
- --i; // move pointer to the newly processored processor
- continue;
+ (*i)->set_state((**niter));
}
- // We found the processor (*niter) on the route, first we must make sure the processor
- // is at the location provided in the XML state
- if (i != o) {
- boost::shared_ptr<Processor> tmp = (*o);
- // remove the old copy
- _processors.erase(o);
- // processor the processor at the correct location
- _processors.insert(i, tmp);
-
- --i; // move pointer so it points to the right processor
+ if (*i == _amp) {
+ placement = PostFader;
}
-
- (*i)->set_state( (**niter) );
}
-
- processors_changed ();
}
void
@@ -2450,7 +1884,7 @@ Route::silence (nframes_t nframes)
IO::silence (nframes);
if (_control_outs) {
- _control_outs->silence (nframes);
+ _control_outs->io()->silence (nframes);
}
{
@@ -2479,13 +1913,8 @@ Route::silence (nframes_t nframes)
int
Route::set_control_outs (const vector<string>& ports)
{
- Glib::Mutex::Lock lm (_control_outs_lock);
vector<string>::const_iterator i;
- size_t limit;
- delete _control_outs;
- _control_outs = 0;
-
if (is_control() || is_master()) {
/* no control outs for these two special busses */
return 0;
@@ -2498,28 +1927,31 @@ Route::set_control_outs (const vector<string>& ports)
string coutname = _name;
coutname += _("[control]");
- _control_outs = new IO (_session, coutname);
+ IO* out_io = new IO (_session, coutname);
+ boost::shared_ptr<ControlOutputs> out_proc(new ControlOutputs (_session, out_io));
- /* our control outs need as many outputs as we
- have audio outputs. we track the changes in ::output_change_handler().
- */
-
- // XXX its stupid that we have to get this value twice
-
- limit = n_outputs().n_audio();
-
- if (_control_outs->ensure_io (ChanCount::ZERO, ChanCount (DataType::AUDIO, n_outputs().get (DataType::AUDIO)), true, this)) {
+ /* As an IO, our control outs need as many IO outputs as we have outputs
+ * (we track the changes in ::output_change_handler()).
+ * As a processor, the control outs is an identity processor
+ * (i.e. it does not modify its input buffers whatsoever)
+ */
+ if (out_io->ensure_io (ChanCount::ZERO, n_outputs(), true, this)) {
return -1;
}
-
+
/* now connect to the named ports */
- for (size_t n = 0; n < limit; ++n) {
- if (_control_outs->connect_output (_control_outs->output (n), ports[n % ports.size()], this)) {
- error << string_compose (_("could not connect %1 to %2"), _control_outs->output(n)->name(), ports[n]) << endmsg;
+ for (size_t n = 0; n < n_outputs().n_total(); ++n) {
+ if (out_io->connect_output (out_io->output (n), ports[n % ports.size()], this)) {
+ error << string_compose (_("could not connect %1 to %2"),
+ out_io->output(n)->name(), ports[n]) << endmsg;
return -1;
}
}
+
+ _control_outs = out_proc;
+ _control_outs->set_sort_key (_meter->sort_key() + 1);
+ add_processor (_control_outs, NULL);
return 0;
}
@@ -2631,11 +2063,11 @@ Route::feeds (boost::shared_ptr<Route> other)
if (_control_outs) {
- no = _control_outs->n_outputs().n_total();
+ no = _control_outs->io()->n_outputs().n_total();
for (i = 0; i < no; ++i) {
for (j = 0; j < ni; ++j) {
- if (_control_outs->output(i)->connected_to (other->input (j)->name())) {
+ if (_control_outs->io()->output(i)->connected_to (other->input (j)->name())) {
return true;
}
}
@@ -2651,22 +2083,22 @@ 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 */
+ pre_fader_changed(src); /* EMIT SIGNAL */
break;
case POST_FADER:
_mute_affects_post_fader = onoff;
- post_fader_changed(src); /* EMIT SIGNAL */
+ post_fader_changed(src); /* EMIT SIGNAL */
break;
case CONTROL_OUTS:
_mute_affects_control_outs = onoff;
- control_outs_changed(src); /* EMIT SIGNAL */
+ control_outs_changed(src); /* EMIT SIGNAL */
break;
case MAIN_OUTS:
_mute_affects_main_outs = onoff;
- main_outs_changed(src); /* EMIT SIGNAL */
+ main_outs_changed(src); /* EMIT SIGNAL */
break;
}
}
@@ -2723,22 +2155,22 @@ Route::handle_transport_stopped (bool abort_ignored, bool did_locate, bool can_f
}
void
-Route::input_change_handler (IOChange change, void *ignored)
+Route::input_change_handler (IOChange change, void *src)
{
- if (change & ConfigurationChanged) {
- reset_processor_counts (0);
+ if ((change & ConfigurationChanged)) {
+ configure_processors (0);
}
}
void
-Route::output_change_handler (IOChange change, void *ignored)
+Route::output_change_handler (IOChange change, void *src)
{
- if (change & ConfigurationChanged) {
+ if ((change & ConfigurationChanged)) {
if (_control_outs) {
- _control_outs->ensure_io (ChanCount::ZERO, ChanCount(DataType::AUDIO, n_outputs().n_audio()), true, this);
+ _control_outs->io()->ensure_io (ChanCount::ZERO, n_outputs(), true, this);
}
- reset_processor_counts (0);
+ configure_processors (0);
}
}
@@ -2765,10 +2197,10 @@ Route::no_roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame,
return 0;
}
- apply_gain_automation = false;
+ _amp->apply_gain_automation(false);
- if (n_inputs().n_total()) {
- passthru (start_frame, end_frame, nframes, 0, false);
+ if (n_inputs() != ChanCount::ZERO) {
+ passthru (start_frame, end_frame, nframes, 0);
} else {
silence (nframes);
}
@@ -2829,7 +2261,7 @@ Route::roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame, int
_silent = false;
- apply_gain_automation = false;
+ _amp->apply_gain_automation(false);
{
Glib::Mutex::Lock am (data().control_lock(), Glib::TRY_LOCK);
@@ -2837,13 +2269,14 @@ Route::roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame, int
if (am.locked() && _session.transport_rolling()) {
if (_gain_control->automation_playback()) {
- apply_gain_automation = _gain_control->list()->curve().rt_safe_get_vector (
- start_frame, end_frame, _session.gain_automation_buffer(), nframes);
+ _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, false);
+ passthru (start_frame, end_frame, nframes, declick);
return 0;
}
@@ -2912,7 +2345,35 @@ Route::set_meter_point (MeterPoint p, void *src)
{
if (_meter_point != p) {
_meter_point = p;
+
+ // Move meter in the processors list
+ ProcessorList::iterator loc = find(_processors.begin(), _processors.end(), _meter);
+ _processors.erase(loc);
+ switch (p) {
+ case MeterInput:
+ loc = _processors.begin();
+ break;
+ case MeterPreFader:
+ loc = find(_processors.begin(), _processors.end(), _amp);
+ break;
+ case MeterPostFader:
+ loc = _processors.end();
+ break;
+ }
+ _processors.insert(loc, _meter);
+
+ // Update sort key
+ if (loc == _processors.end()) {
+ _meter->set_sort_key(_processors.size());
+ } else {
+ _meter->set_sort_key((*loc)->sort_key());
+ for (ProcessorList::iterator p = loc; p != _processors.end(); ++p) {
+ (*p)->set_sort_key((*p)->sort_key() + 1);
+ }
+ }
+
meter_change (src); /* EMIT SIGNAL */
+ processors_changed (); /* EMIT SIGNAL */
_session.set_dirty ();
}
}
@@ -3054,6 +2515,7 @@ Route::set_block_size (nframes_t nframes)
for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
(*i)->set_block_size (nframes);
}
+ _session.ensure_buffers(processor_max_streams);
}
void
diff --git a/libs/ardour/send.cc b/libs/ardour/send.cc
index ef6f954dd2..9246db9458 100644
--- a/libs/ardour/send.cc
+++ b/libs/ardour/send.cc
@@ -35,15 +35,15 @@
using namespace ARDOUR;
using namespace PBD;
-Send::Send (Session& s, Placement p)
- : IOProcessor (s, string_compose (_("send %1"), (bitslot = s.next_send_id()) + 1), p)
+Send::Send (Session& s)
+ : IOProcessor (s, string_compose (_("send %1"), (bitslot = s.next_send_id()) + 1))
{
_metering = false;
ProcessorCreated (this); /* EMIT SIGNAL */
}
Send::Send (Session& s, const XMLNode& node)
- : IOProcessor (s, "send", PreFader)
+ : IOProcessor (s, "send")
{
_metering = false;
@@ -183,10 +183,10 @@ Send::configure_io (ChanCount in, ChanCount out)
return false;
}
- _io->set_output_maximum (in);
+ /*_io->set_output_maximum (in);
_io->set_output_minimum (in);
_io->set_input_maximum (ChanCount::ZERO);
- _io->set_input_minimum (ChanCount::ZERO);
+ _io->set_input_minimum (ChanCount::ZERO);*/
if (_io->ensure_io (ChanCount::ZERO, in, false, this) != 0) {
return false;
diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc
index 0297aa76bb..db66c2dc30 100644
--- a/libs/ardour/session.cc
+++ b/libs/ardour/session.cc
@@ -112,6 +112,9 @@ Session::Session (AudioEngine &eng,
string mix_template)
: _engine (eng),
+ phi (0),
+ target_phi (0),
+ phase (0),
_requested_return_frame (-1),
_scratch_buffers(new BufferSet()),
_silent_buffers(new BufferSet()),
@@ -196,6 +199,9 @@ Session::Session (AudioEngine &eng,
nframes_t initial_length)
: _engine (eng),
+ phi (0),
+ target_phi (0),
+ phase (0),
_requested_return_frame (-1),
_scratch_buffers(new BufferSet()),
_silent_buffers(new BufferSet()),
@@ -264,14 +270,18 @@ Session::Session (AudioEngine &eng,
int control_id = 1;
if (control_out_channels) {
- shared_ptr<Route> r (new Route (*this, _("monitor"), -1, control_out_channels, -1, control_out_channels, Route::ControlOut));
+ ChanCount count(DataType::AUDIO, control_out_channels);
+ shared_ptr<Route> r (new Route (*this, _("monitor"), Route::ControlOut,
+ DataType::AUDIO, count, count));
r->set_remote_control_id (control_id++);
rl.push_back (r);
}
if (master_out_channels) {
- shared_ptr<Route> r (new Route (*this, _("master"), -1, master_out_channels, -1, master_out_channels, Route::MasterOut));
+ ChanCount count(DataType::AUDIO, master_out_channels);
+ shared_ptr<Route> r (new Route (*this, _("master"), Route::MasterOut,
+ DataType::AUDIO, count, count));
r->set_remote_control_id (control_id);
rl.push_back (r);
@@ -543,7 +553,7 @@ Session::when_engine_running ()
try {
XMLNode* child = 0;
- _click_io.reset (new ClickIO (*this, "click", 0, 0, -1, -1));
+ _click_io.reset (new ClickIO (*this, "click"));
if (state_tree && (child = find_named_node (*state_tree->root(), "Click")) != 0) {
@@ -656,36 +666,20 @@ Session::when_engine_running ()
/* create master/control ports */
if (_master_out) {
- uint32_t n;
-
/* force the master to ignore any later call to this */
-
if (_master_out->pending_state_node) {
_master_out->ports_became_legal();
}
/* no panner resets till we are through */
-
_master_out->defer_pan_reset ();
- while (_master_out->n_inputs().n_audio()
- < _master_out->input_maximum().n_audio()) {
- if (_master_out->add_input_port ("", this, DataType::AUDIO)) {
- error << _("cannot setup master inputs")
- << endmsg;
- break;
- }
- }
- n = 0;
- while (_master_out->n_outputs().n_audio()
- < _master_out->output_maximum().n_audio()) {
- if (_master_out->add_output_port (_engine.get_nth_physical_output (DataType::AUDIO, n), this, DataType::AUDIO)) {
- error << _("cannot setup master outputs")
- << endmsg;
- break;
- }
- n++;
- }
+ /* create ports */
+ _master_out->set_input_minimum(ChanCount(DataType::AUDIO, n_physical_inputs));
+ _master_out->set_output_minimum(ChanCount(DataType::AUDIO, n_physical_outputs));
+ _master_out->ensure_io (
+ _master_out->input_minimum (), _master_out->output_minimum (),
+ true, this);
_master_out->allow_pan_reset ();
@@ -765,30 +759,15 @@ Session::hookup_io ()
IO::enable_ports ();
if (_control_out) {
- uint32_t n;
vector<string> cports;
- while (_control_out->n_inputs().n_audio() < _control_out->input_maximum().n_audio()) {
- if (_control_out->add_input_port ("", this)) {
- error << _("cannot setup control inputs")
- << endmsg;
- break;
- }
- }
- n = 0;
- while (_control_out->n_outputs().n_audio() < _control_out->output_maximum().n_audio()) {
- if (_control_out->add_output_port (_engine.get_nth_physical_output (DataType::AUDIO, n), this)) {
- error << _("cannot set up master outputs")
- << endmsg;
- break;
- }
- n++;
- }
-
+ _control_out->ensure_io(
+ _control_out->input_minimum(), _control_out->output_minimum(),
+ false, this);
uint32_t ni = _control_out->n_inputs().get (DataType::AUDIO);
- for (n = 0; n < ni; ++n) {
+ for (uint32_t n = 0; n < ni; ++n) {
cports.push_back (_control_out->input(n)->name());
}
@@ -1313,7 +1292,6 @@ Session::set_block_size (nframes_t nframes)
*/
{
-
current_block_size = nframes;
ensure_buffers(_scratch_buffers->available());
@@ -1757,14 +1735,13 @@ Session::new_audio_track (int input_channels, int output_channels, TrackMode mod
uint32_t nphysical_out = physoutputs.size();
for (uint32_t x = 0; x < track->n_outputs().n_audio(); ++x) {
-
port = "";
if (Config->get_output_auto_connect() & AutoConnectPhysical) {
port = physoutputs[(channels_used+x)%nphysical_out];
} else if (Config->get_output_auto_connect() & AutoConnectMaster) {
- if (_master_out) {
- port = _master_out->input (x%_master_out->n_inputs().n_audio())->name();
+ if (_master_out && _master_out->n_inputs().n_audio() > 0) {
+ port = _master_out->input (x % _master_out->n_inputs().n_audio())->name();
}
}
@@ -1906,7 +1883,7 @@ Session::new_audio_route (int input_channels, int output_channels, uint32_t how_
} while (bus_id < (UINT_MAX-1));
try {
- shared_ptr<Route> bus (new Route (*this, bus_name, -1, -1, -1, -1, Route::Flag(0), DataType::AUDIO));
+ 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)) {
error << string_compose (_("cannot configure %1 in/%2 out configuration for new audio track"),
diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc
index 44e8bb0392..7d14035c93 100644
--- a/libs/ardour/session_state.cc
+++ b/libs/ardour/session_state.cc
@@ -339,8 +339,7 @@ Session::second_stage_init (bool new_session)
/* handle this one in a different way than all others, so that its clear what happened */
catch (AudioEngine::PortRegistrationFailure& err) {
- error << _("Unable to create all required ports")
- << endmsg;
+ error << err.what() << endmsg;
return -1;
}
@@ -2831,7 +2830,12 @@ void
Session::set_deletion_in_progress ()
{
_state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
+}
+void
+Session::clear_deletion_in_progress ()
+{
+ _state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
}
void
diff --git a/libs/ardour/smf_source.cc b/libs/ardour/smf_source.cc
index ea9f30322b..40848dc9ed 100644
--- a/libs/ardour/smf_source.cc
+++ b/libs/ardour/smf_source.cc
@@ -117,7 +117,7 @@ SMFSource::read_unlocked (MidiRingBuffer<nframes_t>& destination, sframes_t sour
const uint64_t start_ticks = (uint64_t)(converter.from(start) * ppqn());
if (_last_read_end == 0 || start != _last_read_end) {
- cerr << "SMFSource::read_unlocked seeking to " << start << endl;
+ //cerr << "SMFSource::read_unlocked seeking to " << start << endl;
Evoral::SMF::seek_to_start();
while (time < start_ticks) {
ret = read_event(&ev_delta_t, &ev_size, &ev_buffer);
@@ -374,10 +374,10 @@ SMFSource::load_model (bool lock, bool force_reload)
if (! _model) {
_model = boost::shared_ptr<MidiModel>(new MidiModel(this));
- cerr << _name << " loaded new model " << _model.get() << endl;
+ //cerr << _name << " loaded new model " << _model.get() << endl;
} else {
- cerr << _name << " reloading model " << _model.get()
- << " (" << _model->n_notes() << " notes)" <<endl;
+ /*cerr << _name << " reloading model " << _model.get()
+ << " (" << _model->n_notes() << " notes)" << endl;*/
_model->clear();
}
diff --git a/libs/ardour/template_utils.cc b/libs/ardour/template_utils.cc
index 22fc6f38df..3f380c0fd6 100644
--- a/libs/ardour/template_utils.cc
+++ b/libs/ardour/template_utils.cc
@@ -102,7 +102,7 @@ find_session_templates (vector<TemplateInfo>& template_names)
template_names.push_back (rti);
}
- free (templates);
+ delete templates;
}
void
diff --git a/libs/ardour/track.cc b/libs/ardour/track.cc
index 2ce73ce727..1e344403b1 100644
--- a/libs/ardour/track.cc
+++ b/libs/ardour/track.cc
@@ -20,18 +20,19 @@
#include <sigc++/retype_return.h>
#include <sigc++/bind.h>
-#include "ardour/track.h"
-#include "ardour/diskstream.h"
-#include "ardour/session.h"
-#include "ardour/io_processor.h"
+#include "ardour/amp.h"
+#include "ardour/audioplaylist.h"
#include "ardour/audioregion.h"
#include "ardour/audiosource.h"
-#include "ardour/route_group_specialized.h"
-#include "ardour/processor.h"
-#include "ardour/audioplaylist.h"
+#include "ardour/diskstream.h"
+#include "ardour/io_processor.h"
#include "ardour/panner.h"
-#include "ardour/utils.h"
#include "ardour/port.h"
+#include "ardour/processor.h"
+#include "ardour/route_group_specialized.h"
+#include "ardour/session.h"
+#include "ardour/track.h"
+#include "ardour/utils.h"
#include "i18n.h"
@@ -40,7 +41,7 @@ using namespace ARDOUR;
using namespace PBD;
Track::Track (Session& sess, string name, Route::Flag flag, TrackMode mode, DataType default_type)
- : Route (sess, name, 1, -1, -1, -1, flag, default_type)
+ : Route (sess, name, flag, default_type)
, _rec_enable_control (new RecEnableControllable(*this))
{
_declickable = true;
@@ -231,7 +232,114 @@ Track::set_latency_delay (nframes_t longest_session_latency)
void
Track::zero_diskstream_id_in_xml (XMLNode& node)
{
- if (node.property ("diskstream-id")) {
- node.add_property ("diskstream-id", "0");
- }
+ if (node.property ("diskstream-id")) {
+ node.add_property ("diskstream-id", "0");
+ }
+}
+
+int
+Track::no_roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame,
+ bool session_state_changing, bool can_record, bool rec_monitors_input)
+{
+ if (n_outputs().n_total() == 0) {
+ return 0;
+ }
+
+ if (!_active) {
+ silence (nframes);
+ return 0;
+ }
+
+ if (session_state_changing) {
+
+ /* XXX is this safe to do against transport state changes? */
+
+ passthru_silence (start_frame, end_frame, nframes, 0);
+ return 0;
+ }
+
+ diskstream()->check_record_status (start_frame, nframes, can_record);
+
+ bool send_silence;
+
+ if (_have_internal_generator) {
+ /* since the instrument has no input streams,
+ there is no reason to send any signal
+ into the route.
+ */
+ send_silence = true;
+ } else {
+ if (!Config->get_tape_machine_mode()) {
+ /*
+ ADATs work in a strange way..
+ they monitor input always when stopped.and auto-input is engaged.
+ */
+ if ((Config->get_monitoring_model() == SoftwareMonitoring)
+ && (Config->get_auto_input () || _diskstream->record_enabled())) {
+ send_silence = false;
+ } else {
+ send_silence = true;
+ }
+ } else {
+ /*
+ Other machines switch to input on stop if the track is record enabled,
+ regardless of the auto input setting (auto input only changes the
+ monitoring state when the transport is rolling)
+ */
+ if ((Config->get_monitoring_model() == SoftwareMonitoring)
+ && _diskstream->record_enabled()) {
+ send_silence = false;
+ } else {
+ send_silence = true;
+ }
+ }
+ }
+
+ _amp->apply_gain_automation(false);
+
+ if (send_silence) {
+
+ /* if we're sending silence, but we want the meters to show levels for the signal,
+ meter right here.
+ */
+
+ if (_have_internal_generator) {
+ passthru_silence (start_frame, end_frame, nframes, 0);
+ } else {
+ if (_meter_point == MeterInput) {
+ just_meter_input (start_frame, end_frame, nframes);
+ }
+ passthru_silence (start_frame, end_frame, nframes, 0);
+ }
+
+ } else {
+
+ /* we're sending signal, but we may still want to meter the input.
+ */
+
+ passthru (start_frame, end_frame, nframes, false);
+ }
+
+ return 0;
+}
+
+int
+Track::silent_roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame,
+ bool can_record, bool rec_monitors_input)
+{
+ if (n_outputs().n_total() == 0 && _processors.empty()) {
+ return 0;
+ }
+
+ if (!_active) {
+ silence (nframes);
+ return 0;
+ }
+
+ _silent = true;
+ _amp->apply_gain_automation(false);
+
+ silence (nframes);
+
+ return diskstream()->process (_session.transport_frame(), nframes, can_record, rec_monitors_input);
}
diff --git a/libs/ardour/wscript b/libs/ardour/wscript
index dfc9cc0156..adcf3a5f0b 100644
--- a/libs/ardour/wscript
+++ b/libs/ardour/wscript
@@ -97,7 +97,9 @@ def build(bld):
buffer_set.cc
bundle.cc
chan_count.cc
+ chan_mapping.cc
configuration.cc
+ control_outputs.cc
control_protocol_manager.cc
control_protocol_search_path.cc
crossfade.cc
diff --git a/libs/evoral/evoral/Control.hpp b/libs/evoral/evoral/Control.hpp
index 2f6e72be1e..806125d973 100644
--- a/libs/evoral/evoral/Control.hpp
+++ b/libs/evoral/evoral/Control.hpp
@@ -38,7 +38,15 @@ public:
virtual void set_float(float val, bool to_list=false, FrameTime frame=0);
virtual float get_float(bool from_list=false, FrameTime frame=0) const;
- virtual float user_float() const;
+
+
+ /** Get the latest user-set value
+ * (which may not equal get_value() when automation is playing back).
+ *
+ * Automation write/touch works by periodically sampling this value
+ * and adding it to the ControlList.
+ */
+ float user_float() const { return _user_value; }
void set_list(boost::shared_ptr<ControlList>);
diff --git a/libs/evoral/evoral/ControlSet.hpp b/libs/evoral/evoral/ControlSet.hpp
index 0172d0e025..e039332920 100644
--- a/libs/evoral/evoral/ControlSet.hpp
+++ b/libs/evoral/evoral/ControlSet.hpp
@@ -58,8 +58,8 @@ public:
bool find_next_event(FrameTime start, FrameTime end, ControlEvent& ev) const;
- virtual bool empty() const { return _controls.size() == 0; }
- virtual void clear();
+ virtual bool controls_empty() const { return _controls.size() == 0; }
+ virtual void clear_controls();
void what_has_data(std::set<Parameter>&) const;
diff --git a/libs/evoral/evoral/Sequence.hpp b/libs/evoral/evoral/Sequence.hpp
index ee18af50dc..6a1fe5ab87 100644
--- a/libs/evoral/evoral/Sequence.hpp
+++ b/libs/evoral/evoral/Sequence.hpp
@@ -85,7 +85,7 @@ public:
inline const boost::shared_ptr< Note<Time> > note_at(size_t i) { return _notes[i]; }
inline size_t n_notes() const { return _notes.size(); }
- inline bool empty() const { return _notes.size() == 0 && ControlSet::empty(); }
+ inline bool empty() const { return _notes.size() == 0 && ControlSet::controls_empty(); }
inline static bool note_time_comparator(const boost::shared_ptr< const Note<Time> >& a,
const boost::shared_ptr< const Note<Time> >& b) {
diff --git a/libs/evoral/src/Control.cpp b/libs/evoral/src/Control.cpp
index b1b492548b..079bd2929e 100644
--- a/libs/evoral/src/Control.cpp
+++ b/libs/evoral/src/Control.cpp
@@ -54,19 +54,6 @@ Control::set_float(float value, bool to_list, FrameTime frame)
}
-/** Get the latest user-set value, which may not equal get_value() when automation
- * is playing back, etc.
- *
- * Automation write/touch works by periodically sampling this value and adding it
- * to the AutomationList.
- */
-float
-Control::user_float() const
-{
- return _user_value;
-}
-
-
void
Control::set_list(boost::shared_ptr<ControlList> list)
{
diff --git a/libs/evoral/src/ControlSet.cpp b/libs/evoral/src/ControlSet.cpp
index 860419a187..4a583b5a55 100644
--- a/libs/evoral/src/ControlSet.cpp
+++ b/libs/evoral/src/ControlSet.cpp
@@ -99,7 +99,7 @@ ControlSet::find_next_event (FrameTime now, FrameTime end, ControlEvent& next_ev
}
void
-ControlSet::clear ()
+ControlSet::clear_controls ()
{
Glib::Mutex::Lock lm (_control_lock);