summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gtk2_ardour/SAE-us-keypad.bindings.in1
-rw-r--r--gtk2_ardour/ardour-sae.menus1
-rw-r--r--gtk2_ardour/ardour.menus.in2
-rw-r--r--gtk2_ardour/ergonomic-us.bindings.in1
-rw-r--r--gtk2_ardour/mnemonic-us.bindings.in1
-rw-r--r--gtk2_ardour/processor_box.cc151
-rw-r--r--gtk2_ardour/processor_box.h6
-rw-r--r--gtk2_ardour/return_ui.cc133
-rw-r--r--gtk2_ardour/return_ui.h77
-rw-r--r--gtk2_ardour/route_params_ui.cc83
-rw-r--r--gtk2_ardour/send_ui.cc49
-rw-r--r--gtk2_ardour/send_ui.h12
-rw-r--r--gtk2_ardour/wscript1
-rw-r--r--libs/ardour/ardour/chan_count.h8
-rw-r--r--libs/ardour/ardour/io.h3
-rw-r--r--libs/ardour/ardour/port_insert.h3
-rw-r--r--libs/ardour/ardour/return.h71
-rw-r--r--libs/ardour/ardour/send.h9
-rw-r--r--libs/ardour/ardour/session.h5
-rw-r--r--libs/ardour/io.cc34
-rw-r--r--libs/ardour/port_insert.cc31
-rw-r--r--libs/ardour/return.cc164
-rw-r--r--libs/ardour/send.cc65
-rw-r--r--libs/ardour/session.cc43
-rw-r--r--libs/ardour/wscript1
25 files changed, 769 insertions, 186 deletions
diff --git a/gtk2_ardour/SAE-us-keypad.bindings.in b/gtk2_ardour/SAE-us-keypad.bindings.in
index 88085b0968..a3b40c284a 100644
--- a/gtk2_ardour/SAE-us-keypad.bindings.in
+++ b/gtk2_ardour/SAE-us-keypad.bindings.in
@@ -424,6 +424,7 @@
; (gtk_accel_path "<Actions>/redirectmenu/newinsert" "")
; (gtk_accel_path "<Actions>/redirectmenu/newplugin" "")
; (gtk_accel_path "<Actions>/redirectmenu/newsend" "")
+; (gtk_accel_path "<Actions>/redirectmenu/newreturn" "")
; (gtk_accel_path "<Actions>/redirectmenu/paste" "")
; (gtk_accel_path "<Actions>/redirectmenu/rename" "")
; (gtk_accel_path "<Actions>/redirectmenu/selectall" "")
diff --git a/gtk2_ardour/ardour-sae.menus b/gtk2_ardour/ardour-sae.menus
index 2a73c4c16a..9d61bf7ebb 100644
--- a/gtk2_ardour/ardour-sae.menus
+++ b/gtk2_ardour/ardour-sae.menus
@@ -354,6 +354,7 @@
<menuitem action='newplugin'/>
<menuitem action='newinsert'/>
<menuitem action='newsend'/>
+ <menuitem action='newreturn'/>
<separator/>
<menuitem action='clear'/>
<separator/>
diff --git a/gtk2_ardour/ardour.menus.in b/gtk2_ardour/ardour.menus.in
index c754590102..f17f8e2bd0 100644
--- a/gtk2_ardour/ardour.menus.in
+++ b/gtk2_ardour/ardour.menus.in
@@ -607,6 +607,7 @@
<menuitem action='newplugin'/>
<menuitem action='newinsert'/>
<menuitem action='newsend'/>
+ <menuitem action='newreturn'/>
<separator/>
<menuitem action='clear'/>
<separator/>
@@ -663,6 +664,7 @@
<menuitem action='newplugin'/>
<menuitem action='newinsert'/>
<menuitem action='newsend'/>
+ <menuitem action='newreturn'/>
<separator/>
<menuitem action='clear'/>
<separator/>
diff --git a/gtk2_ardour/ergonomic-us.bindings.in b/gtk2_ardour/ergonomic-us.bindings.in
index 523878bd3f..e657dcc1b8 100644
--- a/gtk2_ardour/ergonomic-us.bindings.in
+++ b/gtk2_ardour/ergonomic-us.bindings.in
@@ -129,6 +129,7 @@
; (gtk_accel_path "<Actions>/Editor/EditSelectRegionOptions" "")
(gtk_accel_path "<Actions>/Editor/crop" "c")
; (gtk_accel_path "<Actions>/redirectmenu/newsend" "")
+; (gtk_accel_path "<Actions>/redirectmenu/newreturn" "")
; (gtk_accel_path "<Actions>/Editor/ToggleGeneric MIDISurfaceSubMenu" "")
; (gtk_accel_path "<Actions>/Editor/MeterFalloff" "")
; (gtk_accel_path "<Actions>/RegionList/rlRemove" "")
diff --git a/gtk2_ardour/mnemonic-us.bindings.in b/gtk2_ardour/mnemonic-us.bindings.in
index d6df9078cc..ed26ec2212 100644
--- a/gtk2_ardour/mnemonic-us.bindings.in
+++ b/gtk2_ardour/mnemonic-us.bindings.in
@@ -439,6 +439,7 @@
; (gtk_accel_path "<Actions>/Editor/playhead-to-range-end" "")
; (gtk_accel_path "<Actions>/Editor/EditSelectRegionOptions" "")
; (gtk_accel_path "<Actions>/redirectmenu/newsend" "")
+; (gtk_accel_path "<Actions>/redirectmenu/newreturn" "")
; (gtk_accel_path "<Actions>/Editor/ToggleGeneric MIDISurfaceSubMenu" "")
; (gtk_accel_path "<Actions>/Editor/MeterFalloff" "")
; (gtk_accel_path "<Actions>/RegionList/rlRemove" "")
diff --git a/gtk2_ardour/processor_box.cc b/gtk2_ardour/processor_box.cc
index 2bf988aad9..3c2de7edd7 100644
--- a/gtk2_ardour/processor_box.cc
+++ b/gtk2_ardour/processor_box.cc
@@ -47,23 +47,26 @@
#include "ardour/plugin_insert.h"
#include "ardour/port_insert.h"
#include "ardour/profile.h"
+#include "ardour/return.h"
#include "ardour/route.h"
#include "ardour/send.h"
#include "ardour/session.h"
-#include "ardour_ui.h"
+#include "actions.h"
#include "ardour_dialog.h"
-#include "public_editor.h"
-#include "processor_box.h"
+#include "ardour_ui.h"
+#include "gui_thread.h"
+#include "io_selector.h"
#include "keyboard.h"
-#include "plugin_selector.h"
-#include "route_processor_selection.h"
#include "mixer_ui.h"
-#include "actions.h"
+#include "plugin_selector.h"
#include "plugin_ui.h"
-#include "io_selector.h"
+#include "processor_box.h"
+#include "public_editor.h"
+#include "return_ui.h"
+#include "route_processor_selection.h"
+#include "send_ui.h"
#include "utils.h"
-#include "gui_thread.h"
#include "i18n.h"
@@ -216,6 +219,7 @@ void
ProcessorBox::remove_processor_gui (boost::shared_ptr<Processor> processor)
{
boost::shared_ptr<Send> send;
+ boost::shared_ptr<Return> retrn;
boost::shared_ptr<PortInsert> port_insert;
if ((port_insert = boost::dynamic_pointer_cast<PortInsert> (processor)) != 0) {
@@ -226,6 +230,10 @@ ProcessorBox::remove_processor_gui (boost::shared_ptr<Processor> processor)
SendUIWindow *sui = reinterpret_cast<SendUIWindow*> (send->get_gui());
send->set_gui (0);
delete sui;
+ } else if ((retrn = boost::dynamic_pointer_cast<Return> (processor)) != 0) {
+ ReturnUIWindow *rui = reinterpret_cast<ReturnUIWindow*> (retrn->get_gui());
+ retrn->set_gui (0);
+ delete rui;
}
}
@@ -495,20 +503,13 @@ void
ProcessorBox::choose_send ()
{
boost::shared_ptr<Send> send (new Send (_session));
- //send->set_default_type(_route->default_type());
-
- ChanCount outs;
/* make an educated guess at the initial number of outputs for the send */
-
- if (_session.master_out()) {
- outs = _session.master_out()->n_outputs();
- } else {
- outs = _route->n_outputs();
- }
+ ChanCount outs = (_session.master_out())
+ ? _session.master_out()->n_outputs()
+ : _route->n_outputs();
/* XXX need processor lock on route */
-
try {
send->io()->ensure_io (ChanCount::ZERO, outs, false, this);
} catch (AudioEngine::PortRegistrationFailure& err) {
@@ -516,23 +517,17 @@ ProcessorBox::choose_send ()
return;
}
- /* let the user adjust the output setup (number and connections) before passing
- it along to the Route
- */
-
+ /* let the user adjust the IO setup before creation */
IOSelectorWindow *ios = new IOSelectorWindow (_session, send->io(), false, true);
-
ios->show_all ();
- /* bit of a hack; keep a shared_ptr to send around so that it doesn't get deleted while
+ /* keep a reference to the send so it doesn't get deleted while
the IOSelectorWindow is doing its stuff */
- _send_being_created = send;
-
- boost::shared_ptr<Processor> r = boost::static_pointer_cast<Processor>(send);
+ _processor_being_created = send;
ios->selector().Finished.connect (bind (
mem_fun(*this, &ProcessorBox::send_io_finished),
- boost::weak_ptr<Processor>(r), ios));
+ boost::weak_ptr<Processor>(send), ios));
}
void
@@ -540,8 +535,65 @@ ProcessorBox::send_io_finished (IOSelector::Result r, boost::weak_ptr<Processor>
{
boost::shared_ptr<Processor> processor (weak_processor.lock());
- /* now we can lose the dummy shared_ptr */
- _send_being_created.reset ();
+ /* drop our temporary reference to the new send */
+ _processor_being_created.reset ();
+
+ if (!processor) {
+ return;
+ }
+
+ switch (r) {
+ case IOSelector::Cancelled:
+ // processor will go away when all shared_ptrs to it vanish
+ break;
+
+ case IOSelector::Accepted:
+ _route->add_processor (processor, 0, 0, _placement);
+ if (Profile->get_sae()) {
+ processor->activate ();
+ }
+ break;
+ }
+
+ delete_when_idle (ios);
+}
+
+void
+ProcessorBox::choose_return ()
+{
+ boost::shared_ptr<Return> retrn (new Return (_session));
+
+ /* assume user just wants a single audio input (sidechain) by default */
+ ChanCount ins(DataType::AUDIO, 1);
+
+ /* XXX need processor lock on route */
+ try {
+ retrn->io()->ensure_io (ins, ChanCount::ZERO, false, this);
+ } catch (AudioEngine::PortRegistrationFailure& err) {
+ error << string_compose (_("Cannot set up new return: %1"), err.what()) << endmsg;
+ return;
+ }
+
+ /* let the user adjust the IO setup before creation */
+ IOSelectorWindow *ios = new IOSelectorWindow (_session, retrn->io(), true, true);
+ ios->show_all ();
+
+ /* keep a reference to the send so it doesn't get deleted while
+ the IOSelectorWindow is doing its stuff */
+ _processor_being_created = retrn;
+
+ ios->selector().Finished.connect (bind (
+ mem_fun(*this, &ProcessorBox::return_io_finished),
+ boost::weak_ptr<Processor>(retrn), ios));
+}
+
+void
+ProcessorBox::return_io_finished (IOSelector::Result r, boost::weak_ptr<Processor> weak_processor, IOSelectorWindow* ios)
+{
+ boost::shared_ptr<Processor> processor (weak_processor.lock());
+
+ /* drop our temporary reference to the new return */
+ _processor_being_created.reset ();
if (!processor) {
return;
@@ -1067,6 +1119,7 @@ void
ProcessorBox::edit_processor (boost::shared_ptr<Processor> processor)
{
boost::shared_ptr<Send> send;
+ boost::shared_ptr<Return> retrn;
boost::shared_ptr<PluginInsert> plugin_insert;
boost::shared_ptr<PortInsert> port_insert;
Window* gidget = 0;
@@ -1103,6 +1156,32 @@ ProcessorBox::edit_processor (boost::shared_ptr<Processor> processor)
}
gidget = send_ui;
+
+ } else if ((retrn = boost::dynamic_pointer_cast<Return> (processor)) != 0) {
+
+ if (!_session.engine().connected()) {
+ return;
+ }
+
+ boost::shared_ptr<Return> retrn = boost::dynamic_pointer_cast<Return> (processor);
+
+ ReturnUIWindow *return_ui;
+
+ if (retrn->get_gui() == 0) {
+
+ return_ui = new ReturnUIWindow (retrn, _session);
+
+ WindowTitle title(Glib::get_application_name());
+ title += retrn->name();
+ return_ui->set_title (title.get_string());
+
+ send->set_gui (return_ui);
+
+ } else {
+ return_ui = reinterpret_cast<ReturnUIWindow *> (retrn->get_gui());
+ }
+
+ gidget = return_ui;
} else if ((plugin_insert = boost::dynamic_pointer_cast<PluginInsert> (processor)) != 0) {
@@ -1194,6 +1273,9 @@ ProcessorBox::register_actions ()
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);
+ act = ActionManager::register_action (popup_act_grp, X_("newreturn"), _("New Return ..."),
+ sigc::ptr_fun (ProcessorBox::rb_choose_return));
+ ActionManager::jack_sensitive_actions.push_back (act);
ActionManager::register_action (popup_act_grp, X_("clear"), _("Clear"),
sigc::ptr_fun (ProcessorBox::rb_clear));
@@ -1268,6 +1350,15 @@ ProcessorBox::rb_choose_send ()
}
void
+ProcessorBox::rb_choose_return ()
+{
+ if (_current_processor_box == 0) {
+ return;
+ }
+ _current_processor_box->choose_return ();
+}
+
+void
ProcessorBox::rb_clear ()
{
if (_current_processor_box == 0) {
diff --git a/gtk2_ardour/processor_box.h b/gtk2_ardour/processor_box.h
index ea908133e3..37c442d283 100644
--- a/gtk2_ardour/processor_box.h
+++ b/gtk2_ardour/processor_box.h
@@ -94,8 +94,7 @@ class ProcessorBox : public Gtk::HBox, public PluginInterestedObject
bool ab_direction;
std::vector<sigc::connection> connections;
- /// a send that is in the process of creation
- boost::shared_ptr<ARDOUR::Send> _send_being_created;
+ boost::shared_ptr<ARDOUR::Processor> _processor_being_created;
ARDOUR::Placement _placement;
@@ -147,6 +146,8 @@ class ProcessorBox : public Gtk::HBox, public PluginInterestedObject
void choose_send ();
void send_io_finished (IOSelector::Result, boost::weak_ptr<ARDOUR::Processor>, IOSelectorWindow*);
+ void choose_return ();
+ void return_io_finished (IOSelector::Result, boost::weak_ptr<ARDOUR::Processor>, IOSelectorWindow*);
void choose_insert ();
void choose_plugin ();
void use_plugins (const SelectedPlugins&);
@@ -209,6 +210,7 @@ class ProcessorBox : public Gtk::HBox, public PluginInterestedObject
static void rb_choose_plugin ();
static void rb_choose_insert ();
static void rb_choose_send ();
+ static void rb_choose_return ();
static void rb_clear ();
static void rb_cut ();
static void rb_copy ();
diff --git a/gtk2_ardour/return_ui.cc b/gtk2_ardour/return_ui.cc
new file mode 100644
index 0000000000..5423415bd2
--- /dev/null
+++ b/gtk2_ardour/return_ui.cc
@@ -0,0 +1,133 @@
+/*
+ Copyright (C) 2002 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 <gtkmm2ext/doi.h>
+
+#include "ardour/io.h"
+#include "ardour/return.h"
+
+#include "utils.h"
+#include "return_ui.h"
+#include "io_selector.h"
+#include "ardour_ui.h"
+#include "gui_thread.h"
+
+using namespace ARDOUR;
+using namespace PBD;
+
+ReturnUI::ReturnUI (boost::shared_ptr<Return> r, Session& se)
+ : _return (r)
+ , _session (se)
+ , _gpm (se)
+{
+ _gpm.set_io (r->io());
+
+ _hbox.pack_start (_gpm, true, true);
+ set_name ("ReturnUIFrame");
+
+ _vbox.set_spacing (5);
+ _vbox.set_border_width (5);
+
+ _vbox.pack_start (_hbox, false, false, false);
+
+ io = manage (new IOSelector (se, r->io(), true));
+
+ pack_start (_vbox, false, false);
+
+ pack_start (*io, true, true);
+
+ show_all ();
+
+ //_return->set_metering (true);
+
+ _return->io()->input_changed.connect (mem_fun (*this, &ReturnUI::ins_changed));
+ //_return->io()->output_changed.connect (mem_fun (*this, &ReturnUI::outs_changed));
+
+ _gpm.setup_meters ();
+ _gpm.set_fader_name ("ReturnUIFrame");
+
+ // screen_update_connection = ARDOUR_UI::instance()->RapidScreenUpdate.connect (mem_fun (*this, &ReturnUI::update));
+ fast_screen_update_connection = ARDOUR_UI::instance()->SuperRapidScreenUpdate.connect (mem_fun (*this, &ReturnUI::fast_update));
+}
+
+ReturnUI::~ReturnUI ()
+{
+ //_return->set_metering (false);
+
+ /* XXX not clear that we need to do this */
+
+ screen_update_connection.disconnect();
+ fast_screen_update_connection.disconnect();
+}
+
+void
+ReturnUI::ins_changed (IOChange change, void* ignored)
+{
+ ENSURE_GUI_THREAD(bind (mem_fun (*this, &ReturnUI::ins_changed), change, ignored));
+ if (change & ConfigurationChanged) {
+ _gpm.setup_meters ();
+ }
+}
+
+void
+ReturnUI::update ()
+{
+}
+
+void
+ReturnUI::fast_update ()
+{
+ if (Config->get_meter_falloff() > 0.0f) {
+ _gpm.update_meters ();
+ }
+}
+
+ReturnUIWindow::ReturnUIWindow (boost::shared_ptr<Return> s, Session& ss)
+ : ArdourDialog (string("Ardour: return ") + s->name())
+{
+ ui = new ReturnUI (s, ss);
+
+ hpacker.pack_start (*ui, true, true);
+
+ get_vbox()->set_border_width (5);
+ get_vbox()->pack_start (hpacker);
+
+ set_name ("ReturnUIWindow");
+
+ going_away_connection = s->GoingAway.connect (
+ mem_fun (*this, &ReturnUIWindow::return_going_away));
+
+ signal_delete_event().connect (bind (
+ ptr_fun (just_hide_it),
+ reinterpret_cast<Window *> (this)));
+}
+
+ReturnUIWindow::~ReturnUIWindow ()
+{
+ delete ui;
+}
+
+void
+ReturnUIWindow::return_going_away ()
+{
+ ENSURE_GUI_THREAD (mem_fun (*this, &ReturnUIWindow::return_going_away));
+ delete_when_idle (this);
+ going_away_connection.disconnect ();
+}
+
diff --git a/gtk2_ardour/return_ui.h b/gtk2_ardour/return_ui.h
new file mode 100644
index 0000000000..08c6bba5ba
--- /dev/null
+++ b/gtk2_ardour/return_ui.h
@@ -0,0 +1,77 @@
+/*
+ Copyright (C) 2002 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_gtk_return_ui_h__
+#define __ardour_gtk_return_ui_h__
+
+#include "gain_meter.h"
+#include "panner_ui.h"
+#include "ardour_dialog.h"
+
+namespace ARDOUR {
+ class Return;
+ class Session;
+ class IOProcessor;
+}
+
+class IOSelector;
+
+class ReturnUI : public Gtk::HBox
+{
+ public:
+ ReturnUI (boost::shared_ptr<ARDOUR::Return>, ARDOUR::Session&);
+ ~ReturnUI();
+
+ void update ();
+ void fast_update ();
+
+ IOSelector* io;
+
+ boost::shared_ptr<ARDOUR::Return>& retrn() { return _return; }
+
+ private:
+ boost::shared_ptr<ARDOUR::Return> _return;
+ ARDOUR::Session& _session;
+ GainMeter _gpm;
+ Gtk::VBox _vbox;
+ Gtk::VBox _hbox;
+
+ sigc::connection screen_update_connection;
+ sigc::connection fast_screen_update_connection;
+
+ void ins_changed (ARDOUR::IOChange, void*);
+};
+
+class ReturnUIWindow : public ArdourDialog
+{
+ public:
+ ReturnUIWindow(boost::shared_ptr<ARDOUR::Return>, ARDOUR::Session&);
+ ~ReturnUIWindow();
+
+ ReturnUI* ui;
+
+ private:
+ Gtk::HBox hpacker;
+
+ void return_going_away ();
+ sigc::connection going_away_connection;
+};
+
+#endif /* __ardour_gtk_return_ui_h__ */
+
diff --git a/gtk2_ardour/route_params_ui.cc b/gtk2_ardour/route_params_ui.cc
index 37639a9985..33a99f6955 100644
--- a/gtk2_ardour/route_params_ui.cc
+++ b/gtk2_ardour/route_params_ui.cc
@@ -26,29 +26,31 @@
#include <gtkmm2ext/stop_signal.h>
#include <gtkmm2ext/window_title.h>
-#include "ardour/session.h"
-#include "ardour/session_route.h"
+#include "ardour/ardour.h"
#include "ardour/audio_diskstream.h"
+#include "ardour/audio_track.h"
#include "ardour/plugin.h"
+#include "ardour/plugin_insert.h"
#include "ardour/plugin_manager.h"
-#include "ardour/ardour.h"
-#include "ardour/session.h"
+#include "ardour/port_insert.h"
+#include "ardour/return.h"
#include "ardour/route.h"
-#include "ardour/audio_track.h"
#include "ardour/send.h"
-#include "ardour/plugin_insert.h"
-#include "ardour/port_insert.h"
+#include "ardour/session.h"
+#include "ardour/session.h"
+#include "ardour/session_route.h"
-#include "route_params_ui.h"
+#include "ardour_ui.h"
+#include "gui_thread.h"
+#include "io_selector.h"
#include "keyboard.h"
#include "mixer_strip.h"
#include "plugin_selector.h"
-#include "ardour_ui.h"
#include "plugin_ui.h"
-#include "io_selector.h"
+#include "return_ui.h"
+#include "route_params_ui.h"
#include "send_ui.h"
#include "utils.h"
-#include "gui_thread.h"
#include "i18n.h"
@@ -559,6 +561,7 @@ RouteParams_UI::redirect_selected (boost::shared_ptr<ARDOUR::Processor> insert,
}
boost::shared_ptr<Send> send;
+ boost::shared_ptr<Return> retrn;
boost::shared_ptr<PluginInsert> plugin_insert;
boost::shared_ptr<PortInsert> port_insert;
@@ -568,35 +571,66 @@ RouteParams_UI::redirect_selected (boost::shared_ptr<ARDOUR::Processor> insert,
if (place == PreFader) {
cleanup_pre_view();
- _pre_plugin_conn = send->GoingAway.connect (bind (mem_fun(*this, &RouteParams_UI::redirect_going_away), insert));
+ _pre_plugin_conn = send->GoingAway.connect (bind (
+ mem_fun(*this, &RouteParams_UI::redirect_going_away),
+ insert));
_active_pre_view = send_ui;
pre_redir_hpane.add2 (*_active_pre_view);
pre_redir_hpane.show_all();
- }
- else {
+ } else {
cleanup_post_view();
- _post_plugin_conn = send->GoingAway.connect (bind (mem_fun(*this, &RouteParams_UI::redirect_going_away), insert));
+ _post_plugin_conn = send->GoingAway.connect (bind (
+ mem_fun(*this, &RouteParams_UI::redirect_going_away),
+ insert));
_active_post_view = send_ui;
post_redir_hpane.add2 (*_active_post_view);
post_redir_hpane.show_all();
}
+
+ } else if ((retrn = boost::dynamic_pointer_cast<Return> (insert)) != 0) {
+
+ ReturnUI *return_ui = new ReturnUI (retrn, *session);
+
+ if (place == PreFader) {
+ cleanup_pre_view();
+ _pre_plugin_conn = retrn->GoingAway.connect (bind (
+ mem_fun(*this, &RouteParams_UI::redirect_going_away),
+ insert));
+ _active_pre_view = return_ui;
+
+ pre_redir_hpane.add2 (*_active_pre_view);
+ pre_redir_hpane.show_all();
+ } else {
+ cleanup_post_view();
+ _post_plugin_conn = retrn->GoingAway.connect (bind (
+ mem_fun(*this, &RouteParams_UI::redirect_going_away),
+ insert));
+ _active_post_view = return_ui;
+
+ post_redir_hpane.add2 (*_active_post_view);
+ post_redir_hpane.show_all();
+ }
+
} else if ((plugin_insert = boost::dynamic_pointer_cast<PluginInsert> (insert)) != 0) {
GenericPluginUI *plugin_ui = new GenericPluginUI (plugin_insert, true);
if (place == PreFader) {
cleanup_pre_view();
- _pre_plugin_conn = plugin_insert->plugin()->GoingAway.connect (bind (mem_fun(*this, &RouteParams_UI::plugin_going_away), PreFader));
+ _pre_plugin_conn = plugin_insert->plugin()->GoingAway.connect (bind (
+ mem_fun(*this, &RouteParams_UI::plugin_going_away),
+ PreFader));
plugin_ui->start_updating (0);
_active_pre_view = plugin_ui;
pre_redir_hpane.pack2 (*_active_pre_view);
pre_redir_hpane.show_all();
- }
- else {
+ } else {
cleanup_post_view();
- _post_plugin_conn = plugin_insert->plugin()->GoingAway.connect (bind (mem_fun(*this, &RouteParams_UI::plugin_going_away), PostFader));
+ _post_plugin_conn = plugin_insert->plugin()->GoingAway.connect (bind (
+ mem_fun(*this, &RouteParams_UI::plugin_going_away),
+ PostFader));
plugin_ui->start_updating (0);
_active_post_view = plugin_ui;
post_redir_hpane.pack2 (*_active_post_view);
@@ -609,15 +643,18 @@ RouteParams_UI::redirect_selected (boost::shared_ptr<ARDOUR::Processor> insert,
if (place == PreFader) {
cleanup_pre_view();
- _pre_plugin_conn = port_insert->GoingAway.connect (bind (mem_fun(*this, &RouteParams_UI::redirect_going_away), insert));
+ _pre_plugin_conn = port_insert->GoingAway.connect (bind (
+ mem_fun(*this, &RouteParams_UI::redirect_going_away),
+ insert));
_active_pre_view = portinsert_ui;
pre_redir_hpane.pack2 (*_active_pre_view);
portinsert_ui->redisplay();
pre_redir_hpane.show_all();
- }
- else {
+ } else {
cleanup_post_view();
- _post_plugin_conn = port_insert->GoingAway.connect (bind (mem_fun(*this, &RouteParams_UI::redirect_going_away), insert));
+ _post_plugin_conn = port_insert->GoingAway.connect (bind (
+ mem_fun(*this, &RouteParams_UI::redirect_going_away),
+ insert));
_active_post_view = portinsert_ui;
post_redir_hpane.pack2 (*_active_post_view);
portinsert_ui->redisplay();
diff --git a/gtk2_ardour/send_ui.cc b/gtk2_ardour/send_ui.cc
index 1014f5a07a..664092d39f 100644
--- a/gtk2_ardour/send_ui.cc
+++ b/gtk2_ardour/send_ui.cc
@@ -34,24 +34,24 @@ using namespace PBD;
SendUI::SendUI (boost::shared_ptr<Send> s, Session& se)
: _send (s)
, _session (se)
- , gpm (se)
- , panners (se)
+ , _gpm (se)
+ , _panners (se)
{
- panners.set_io (s->io());
- gpm.set_io (s->io());
+ _panners.set_io (s->io());
+ _gpm.set_io (s->io());
- hbox.pack_start (gpm, true, true);
+ _hbox.pack_start (_gpm, true, true);
set_name ("SendUIFrame");
- vbox.set_spacing (5);
- vbox.set_border_width (5);
+ _vbox.set_spacing (5);
+ _vbox.set_border_width (5);
- vbox.pack_start (hbox, false, false, false);
- vbox.pack_start (panners, false,false);
+ _vbox.pack_start (_hbox, false, false, false);
+ _vbox.pack_start (_panners, false,false);
io = manage (new IOSelector (se, s->io(), true));
- pack_start (vbox, false, false);
+ pack_start (_vbox, false, false);
pack_start (*io, true, true);
@@ -62,14 +62,16 @@ SendUI::SendUI (boost::shared_ptr<Send> s, Session& se)
_send->io()->input_changed.connect (mem_fun (*this, &SendUI::ins_changed));
_send->io()->output_changed.connect (mem_fun (*this, &SendUI::outs_changed));
- panners.set_width (Wide);
- panners.setup_pan ();
+ _panners.set_width (Wide);
+ _panners.setup_pan ();
- gpm.setup_meters ();
- gpm.set_fader_name ("SendUIFrame");
+ _gpm.setup_meters ();
+ _gpm.set_fader_name ("SendUIFrame");
- // screen_update_connection = ARDOUR_UI::instance()->RapidScreenUpdate.connect (mem_fun (*this, &SendUI::update));
- fast_screen_update_connection = ARDOUR_UI::instance()->SuperRapidScreenUpdate.connect (mem_fun (*this, &SendUI::fast_update));
+ // screen_update_connection = ARDOUR_UI::instance()->RapidScreenUpdate.connect (
+ // mem_fun (*this, &SendUI::update));
+ fast_screen_update_connection = ARDOUR_UI::instance()->SuperRapidScreenUpdate.connect (
+ mem_fun (*this, &SendUI::fast_update));
}
SendUI::~SendUI ()
@@ -87,7 +89,7 @@ SendUI::ins_changed (IOChange change, void* ignored)
{
ENSURE_GUI_THREAD(bind (mem_fun (*this, &SendUI::ins_changed), change, ignored));
if (change & ConfigurationChanged) {
- panners.setup_pan ();
+ _panners.setup_pan ();
}
}
@@ -96,8 +98,8 @@ SendUI::outs_changed (IOChange change, void* ignored)
{
ENSURE_GUI_THREAD(bind (mem_fun (*this, &SendUI::outs_changed), change, ignored));
if (change & ConfigurationChanged) {
- panners.setup_pan ();
- gpm.setup_meters ();
+ _panners.setup_pan ();
+ _gpm.setup_meters ();
}
}
@@ -110,7 +112,7 @@ void
SendUI::fast_update ()
{
if (Config->get_meter_falloff() > 0.0f) {
- gpm.update_meters ();
+ _gpm.update_meters ();
}
}
@@ -126,9 +128,12 @@ SendUIWindow::SendUIWindow (boost::shared_ptr<Send> s, Session& ss)
set_name ("SendUIWindow");
- going_away_connection = s->GoingAway.connect (mem_fun (*this, &SendUIWindow::send_going_away));
+ going_away_connection = s->GoingAway.connect (
+ mem_fun (*this, &SendUIWindow::send_going_away));
- signal_delete_event().connect (bind (ptr_fun (just_hide_it), reinterpret_cast<Window *> (this)));
+ signal_delete_event().connect (bind (
+ ptr_fun (just_hide_it),
+ reinterpret_cast<Window *> (this)));
}
SendUIWindow::~SendUIWindow ()
diff --git a/gtk2_ardour/send_ui.h b/gtk2_ardour/send_ui.h
index 0d6356970e..284f078234 100644
--- a/gtk2_ardour/send_ui.h
+++ b/gtk2_ardour/send_ui.h
@@ -47,11 +47,11 @@ class SendUI : public Gtk::HBox
private:
boost::shared_ptr<ARDOUR::Send> _send;
- ARDOUR::Session& _session;
- GainMeter gpm;
- PannerUI panners;
- Gtk::VBox vbox;
- Gtk::VBox hbox;
+ ARDOUR::Session& _session;
+ GainMeter _gpm;
+ PannerUI _panners;
+ Gtk::VBox _vbox;
+ Gtk::VBox _hbox;
sigc::connection screen_update_connection;
sigc::connection fast_screen_update_connection;
@@ -66,7 +66,7 @@ class SendUIWindow : public ArdourDialog
SendUIWindow(boost::shared_ptr<ARDOUR::Send>, ARDOUR::Session&);
~SendUIWindow();
- SendUI* ui;
+ SendUI* ui;
private:
Gtk::HBox hpacker;
diff --git a/gtk2_ardour/wscript b/gtk2_ardour/wscript
index 8bb973c4e6..56df15b846 100644
--- a/gtk2_ardour/wscript
+++ b/gtk2_ardour/wscript
@@ -182,6 +182,7 @@ def build(bld):
region_gain_line.cc
region_selection.cc
region_view.cc
+ return_ui.cc
rhythm_ferret.cc
route_params_ui.cc
route_processor_selection.cc
diff --git a/libs/ardour/ardour/chan_count.h b/libs/ardour/ardour/chan_count.h
index c9b543c4ba..ccae3920f6 100644
--- a/libs/ardour/ardour/chan_count.h
+++ b/libs/ardour/ardour/chan_count.h
@@ -106,6 +106,14 @@ public:
return ( (*this > other) || (*this == other) );
}
+ ChanCount operator+(const ChanCount& other) const {
+ ChanCount ret;
+ for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
+ ret.set(*t, get(*t) + other.get(*t));
+ }
+ return ret;
+ }
+
static ChanCount min(const ChanCount& a, const ChanCount& b) {
ChanCount ret;
for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
diff --git a/libs/ardour/ardour/io.h b/libs/ardour/ardour/io.h
index 3e36d10be3..fbaf379a30 100644
--- a/libs/ardour/ardour/io.h
+++ b/libs/ardour/ardour/io.h
@@ -102,7 +102,7 @@ class IO : public SessionObject, public AutomatableControls, public Latent
virtual void silence (nframes_t);
- void collect_input (BufferSet& bufs, nframes_t nframes);
+ void collect_input (BufferSet& bufs, nframes_t nframes, ChanCount offset=ChanCount::ZERO);
void deliver_output (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame, nframes_t nframes);
void just_meter_input (nframes_t start_frame, nframes_t end_frame, nframes_t nframes);
@@ -214,7 +214,6 @@ class IO : public SessionObject, public AutomatableControls, public Latent
static sigc::signal<int> ConnectingLegal;
/// raised when the number of input or output ports changes
static sigc::signal<void,ChanCount> PortCountChanged;
- static sigc::signal<int> PortsCreated;
static sigc::signal<void,nframes_t> CycleStart;
static void update_meters();
diff --git a/libs/ardour/ardour/port_insert.h b/libs/ardour/ardour/port_insert.h
index 076e4af9d1..ce21d9f223 100644
--- a/libs/ardour/ardour/port_insert.h
+++ b/libs/ardour/ardour/port_insert.h
@@ -54,9 +54,6 @@ class PortInsert : public IOProcessor
nframes_t signal_latency() const;
- ChanCount output_streams() const;
- ChanCount input_streams() const;
-
bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const;
bool configure_io (ChanCount in, ChanCount out);
diff --git a/libs/ardour/ardour/return.h b/libs/ardour/ardour/return.h
new file mode 100644
index 0000000000..af55df59ed
--- /dev/null
+++ b/libs/ardour/ardour/return.h
@@ -0,0 +1,71 @@
+/*
+ Copyright (C) 2009 Paul Davis
+ Author: Dave Robillard
+
+ 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_return_h__
+#define __ardour_return_h__
+
+#include <sigc++/signal.h>
+#include <string>
+
+
+#include "pbd/stateful.h"
+#include "ardour/ardour.h"
+#include "ardour/audioengine.h"
+#include "ardour/io_processor.h"
+
+namespace ARDOUR {
+
+class Return : public IOProcessor
+{
+public:
+ Return (Session&);
+ Return (Session&, const XMLNode&);
+ virtual ~Return ();
+
+ uint32_t bit_slot() const { return _bitslot; }
+
+ void run_in_place (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame, nframes_t nframes);
+
+ void activate() {}
+ void deactivate () {}
+
+ XMLNode& state(bool full);
+ XMLNode& get_state(void);
+ int set_state(const XMLNode& node);
+
+ uint32_t pans_required() const { return _configured_input.n_audio(); }
+
+ bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const;
+ bool configure_io (ChanCount in, ChanCount out);
+
+ static uint32_t how_many_sends();
+ static void make_unique (XMLNode &, Session &);
+
+private:
+ /* disallow copy construction */
+ Return (const Return&);
+
+ uint32_t _bitslot;
+};
+
+} // namespace ARDOUR
+
+#endif /* __ardour_return_h__ */
+
diff --git a/libs/ardour/ardour/send.h b/libs/ardour/ardour/send.h
index 77bb6d9017..825506f0e2 100644
--- a/libs/ardour/ardour/send.h
+++ b/libs/ardour/ardour/send.h
@@ -38,10 +38,7 @@ class Send : public IOProcessor
Send (Session&, const XMLNode&);
virtual ~Send ();
- uint32_t bit_slot() const { return bitslot; }
-
- ChanCount output_streams() const;
- ChanCount input_streams () const;
+ uint32_t bit_slot() const { return _bitslot; }
void run_in_place (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame, nframes_t nframes);
@@ -55,7 +52,6 @@ class Send : public IOProcessor
int set_state(const XMLNode& node);
uint32_t pans_required() const { return _configured_input.n_audio(); }
- void expect_inputs (const ChanCount&);
bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const;
bool configure_io (ChanCount in, ChanCount out);
@@ -68,8 +64,7 @@ class Send : public IOProcessor
Send (const Send&);
bool _metering;
- ChanCount expected_inputs;
- uint32_t bitslot;
+ uint32_t _bitslot;
};
} // namespace ARDOUR
diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h
index 1e3855c308..86a2f778dc 100644
--- a/libs/ardour/ardour/session.h
+++ b/libs/ardour/ardour/session.h
@@ -101,6 +101,7 @@ class Port;
class PortInsert;
class Processor;
class Region;
+class Return;
class Route;
class RouteGroup;
class SMFSource;
@@ -764,8 +765,10 @@ class Session : public PBD::StatefulDestructible, public boost::noncopyable
}
uint32_t next_send_id();
+ uint32_t next_return_id();
uint32_t next_insert_id();
void mark_send_id (uint32_t);
+ void mark_return_id (uint32_t);
void mark_insert_id (uint32_t);
/* s/w "RAID" management */
@@ -1566,7 +1569,9 @@ class Session : public PBD::StatefulDestructible, public boost::noncopyable
list<PortInsert *> _port_inserts;
list<PluginInsert *> _plugin_inserts;
list<Send *> _sends;
+ list<Return *> _returns;
boost::dynamic_bitset<uint32_t> send_bitset;
+ boost::dynamic_bitset<uint32_t> return_bitset;
boost::dynamic_bitset<uint32_t> insert_bitset;
uint32_t send_cnt;
uint32_t insert_cnt;
diff --git a/libs/ardour/io.cc b/libs/ardour/io.cc
index 3e5b138fb7..c8e2c78cd2 100644
--- a/libs/ardour/io.cc
+++ b/libs/ardour/io.cc
@@ -74,7 +74,6 @@ sigc::signal<int> IO::ConnectingLegal;
sigc::signal<int> IO::PortsLegal;
sigc::signal<int> IO::PannersLegal;
sigc::signal<void,ChanCount> IO::PortCountChanged;
-sigc::signal<int> IO::PortsCreated;
sigc::signal<void,nframes_t> IO::CycleStart;
Glib::StaticMutex IO::m_meter_signal_lock = GLIBMM_STATIC_MUTEX_INIT;
@@ -290,24 +289,31 @@ IO::copy_to_outputs (BufferSet& bufs, DataType type, nframes_t nframes)
}
void
-IO::collect_input (BufferSet& outs, nframes_t nframes)
+IO::collect_input (BufferSet& outs, nframes_t nframes, ChanCount offset)
{
assert(outs.available() >= n_inputs());
- if (n_inputs() == ChanCount::ZERO)
+ if (n_inputs() == ChanCount::ZERO) {
return;
+ }
outs.set_count(n_inputs());
-
+
for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
-
+ PortSet::iterator i = _inputs.begin(*t);
BufferSet::iterator o = outs.begin(*t);
- PortSet::iterator e = _inputs.end (*t);
- for (PortSet::iterator i = _inputs.begin(*t); i != e; ++i, ++o) {
+
+ cerr << (*t).to_string() << endl;
+ for (uint32_t off = 0; off < offset.get(*t); ++off, ++o) {
+ if (o == outs.end(*t)) {
+ continue;
+ }
+ }
+
+ for ( ; i != _inputs.end(*t); ++i, ++o) {
Buffer& b (i->get_buffer (nframes));
o->read_from (b, nframes);
}
-
}
}
@@ -795,7 +801,8 @@ IO::ensure_inputs_locked (ChanCount count, bool clear, void* src)
{
Port* input_port = 0;
bool changed = false;
-
+
+ _configured_inputs = count;
for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
@@ -867,14 +874,14 @@ IO::ensure_io (ChanCount in, ChanCount out, bool clear, void* src)
in = ChanCount::min (_input_maximum, in);
out = ChanCount::min (_output_maximum, out);
+
+ _configured_inputs = in;
+ _configured_outputs = 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);
@@ -1034,6 +1041,8 @@ IO::ensure_outputs_locked (ChanCount count, bool clear, void* src)
Port* output_port = 0;
bool changed = false;
bool need_pan_reset = false;
+
+ _configured_outputs = count;
if (n_outputs() != count) {
need_pan_reset = true;
@@ -1708,7 +1717,6 @@ IO::create_ports (const XMLNode& node)
set_deferred_state ();
- PortsCreated();
return 0;
}
diff --git a/libs/ardour/port_insert.cc b/libs/ardour/port_insert.cc
index 606b055dab..73a70861ea 100644
--- a/libs/ardour/port_insert.cc
+++ b/libs/ardour/port_insert.cc
@@ -162,23 +162,7 @@ PortInsert::signal_latency() const
bool
PortInsert::configure_io (ChanCount in, ChanCount out)
{
- /* do not allow configuration to be changed outside the range of
- the last request config. or something like that.
- */
-
- /* this is a bit odd:
-
- the number of inputs we are required to handle corresponds
- to the number of output ports we need.
-
- the number of outputs we are required to have corresponds
- to the number of input ports we need.
- */
-
- /*_io->set_output_maximum (in);
- _io->set_output_minimum (in);
- _io->set_input_maximum (out);
- _io->set_input_minimum (out);*/
+ /* for an insert, processor input corresponds to IO output, and vice versa */
if (_io->ensure_io (out, in, false, this) != 0) {
return false;
@@ -187,21 +171,10 @@ PortInsert::configure_io (ChanCount in, ChanCount out)
return Processor::configure_io (in, out);
}
-ChanCount
-PortInsert::output_streams() const
-{
- return _io->n_inputs ();
-}
-
-ChanCount
-PortInsert::input_streams() const
-{
- return _io->n_outputs ();
-}
-
bool
PortInsert::can_support_io_configuration (const ChanCount& in, ChanCount& out) const
{
out = in;
return true;
}
+
diff --git a/libs/ardour/return.cc b/libs/ardour/return.cc
new file mode 100644
index 0000000000..fdc2b259e1
--- /dev/null
+++ b/libs/ardour/return.cc
@@ -0,0 +1,164 @@
+/*
+ Copyright (C) 2000 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 <algorithm>
+
+#include "pbd/xml++.h"
+
+#include "ardour/return.h"
+#include "ardour/session.h"
+#include "ardour/port.h"
+#include "ardour/audio_port.h"
+#include "ardour/buffer_set.h"
+#include "ardour/meter.h"
+#include "ardour/panner.h"
+#include "ardour/io.h"
+
+#include "i18n.h"
+
+using namespace ARDOUR;
+using namespace PBD;
+
+Return::Return (Session& s)
+ : IOProcessor (s, string_compose (_("return %1"), (_bitslot = s.next_return_id()) + 1))
+{
+ ProcessorCreated (this); /* EMIT SIGNAL */
+}
+
+Return::Return (Session& s, const XMLNode& node)
+ : IOProcessor (s, "return")
+{
+ if (set_state (node)) {
+ throw failed_constructor();
+ }
+
+ ProcessorCreated (this); /* EMIT SIGNAL */
+}
+
+Return::~Return ()
+{
+ GoingAway ();
+}
+
+XMLNode&
+Return::get_state(void)
+{
+ return state (true);
+}
+
+XMLNode&
+Return::state(bool full)
+{
+ XMLNode& node = IOProcessor::state(full);
+ char buf[32];
+ node.add_property ("type", "return");
+ snprintf (buf, sizeof (buf), "%" PRIu32, _bitslot);
+ node.add_property ("bitslot", buf);
+
+ return node;
+}
+
+int
+Return::set_state(const XMLNode& node)
+{
+ XMLNodeList nlist = node.children();
+ XMLNodeIterator niter;
+ const XMLProperty* prop;
+
+ if ((prop = node.property ("bitslot")) == 0) {
+ _bitslot = _session.next_return_id();
+ } else {
+ sscanf (prop->value().c_str(), "%" PRIu32, &_bitslot);
+ _session.mark_return_id (_bitslot);
+ }
+
+ const XMLNode* insert_node = &node;
+
+ /* Return has regular IO automation (gain, pan) */
+
+ for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
+ if ((*niter)->name() == "IOProcessor") {
+ insert_node = *niter;
+ } else if ((*niter)->name() == X_("Automation")) {
+ // _io->set_automation_state (*(*niter), Evoral::Parameter(GainAutomation));
+ }
+ }
+
+ IOProcessor::set_state (*insert_node);
+
+ return 0;
+}
+
+void
+Return::run_in_place (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame, nframes_t nframes)
+{
+ if (active()) {
+ _io->collect_input (bufs, nframes, _configured_input);
+ bufs.set_count(_configured_output);
+ }
+}
+
+bool
+Return::can_support_io_configuration (const ChanCount& in, ChanCount& out) const
+{
+ out = in + _io->n_inputs();
+ return true;
+}
+
+bool
+Return::configure_io (ChanCount in, ChanCount out)
+{
+ if (out != in + _io->n_inputs()) {
+ return false;
+ }
+
+ // Ensure there are enough buffers (since we add some)
+ if (_session.get_scratch_buffers(in).count() < out) {
+ Glib::Mutex::Lock em (_session.engine().process_lock());
+ IO::PortCountChanged(out);
+ }
+
+ Processor::configure_io(in, out);
+
+ return true;
+}
+
+/** Set up the XML description of a return so that its name is unique.
+ * @param state XML return state.
+ * @param session Session.
+ */
+void
+Return::make_unique (XMLNode &state, Session &session)
+{
+ uint32_t const bitslot = session.next_return_id() + 1;
+
+ char buf[32];
+ snprintf (buf, sizeof (buf), "%" PRIu32, bitslot);
+ state.property("bitslot")->set_value (buf);
+
+ std::string const name = string_compose (_("return %1"), bitslot);
+
+ state.property("name")->set_value (name);
+
+ XMLNode* io = state.child ("IO");
+ if (io) {
+ io->property("name")->set_value (name);
+ }
+}
+
diff --git a/libs/ardour/send.cc b/libs/ardour/send.cc
index 9246db9458..2c28fb5dcd 100644
--- a/libs/ardour/send.cc
+++ b/libs/ardour/send.cc
@@ -36,7 +36,7 @@ using namespace ARDOUR;
using namespace PBD;
Send::Send (Session& s)
- : IOProcessor (s, string_compose (_("send %1"), (bitslot = s.next_send_id()) + 1))
+ : IOProcessor (s, string_compose (_("send %1"), (_bitslot = s.next_send_id()) + 1))
{
_metering = false;
ProcessorCreated (this); /* EMIT SIGNAL */
@@ -71,7 +71,7 @@ Send::state(bool full)
XMLNode& node = IOProcessor::state(full);
char buf[32];
node.add_property ("type", "send");
- snprintf (buf, sizeof (buf), "%" PRIu32, bitslot);
+ snprintf (buf, sizeof (buf), "%" PRIu32, _bitslot);
node.add_property ("bitslot", buf);
return node;
@@ -85,10 +85,10 @@ Send::set_state(const XMLNode& node)
const XMLProperty* prop;
if ((prop = node.property ("bitslot")) == 0) {
- bitslot = _session.next_send_id();
+ _bitslot = _session.next_send_id();
} else {
- sscanf (prop->value().c_str(), "%" PRIu32, &bitslot);
- _session.mark_send_id (bitslot);
+ sscanf (prop->value().c_str(), "%" PRIu32, &_bitslot);
+ _session.mark_send_id (_bitslot);
}
const XMLNode* insert_node = &node;
@@ -113,15 +113,7 @@ Send::run_in_place (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame,
{
if (active()) {
- // we have to copy the input, because IO::deliver_output may alter the buffers
- // in-place, which a send must never do.
-
- BufferSet& sendbufs = _session.get_mix_buffers(bufs.count());
-
- sendbufs.read_from(bufs, nframes);
- assert(sendbufs.count() == bufs.count());
-
- _io->deliver_output (sendbufs, start_frame, end_frame, nframes);
+ _io->deliver_output (bufs, start_frame, end_frame, nframes);
if (_metering) {
if (_io->effective_gain() == 0) {
@@ -152,26 +144,27 @@ Send::set_metering (bool yn)
}
bool
-Send::can_support_io_configuration (const ChanCount& in, ChanCount& out_is_ignored) const
+Send::can_support_io_configuration (const ChanCount& in, ChanCount& out) const
{
- if (_io->input_maximum() == ChanCount::INFINITE && _io->output_maximum() == ChanCount::INFINITE) {
+ if (_io->input_maximum() == ChanCount::INFINITE
+ && _io->output_maximum() == ChanCount::INFINITE) {
- /* not configured yet */
+ /* not configured yet, we can support anything */
- return 1; /* we can support anything the first time we're asked */
+ out = in;
+ return true; /* we can support anything the first time we're asked */
} else {
- /* the "input" config for a port insert corresponds to how
- many output ports it will have.
- */
+ /* for a send, processor input corresponds to IO output */
if (_io->output_maximum() == in) {
- return 1;
+ out = in;
+ return true;
}
}
- return -1;
+ return false;
}
bool
@@ -198,32 +191,6 @@ Send::configure_io (ChanCount in, ChanCount out)
return true;
}
-ChanCount
-Send::output_streams() const
-{
- // this method reflects the idea that from the perspective of the Route's ProcessorList,
- // a send is just a passthrough. that doesn't match what the Send actually does with its
- // data, but since what it does is invisible to the Route, it appears to be a passthrough.
-
- return _configured_input;
-}
-
-ChanCount
-Send::input_streams() const
-{
- return _configured_input;
-}
-
-
-void
-Send::expect_inputs (const ChanCount& expected)
-{
- if (expected != expected_inputs) {
- expected_inputs = expected;
- _io->reset_panner ();
- }
-}
-
/** Set up the XML description of a send so that its name is unique.
* @param state XML send state.
* @param session Session.
diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc
index db66c2dc30..302bf87f64 100644
--- a/libs/ardour/session.cc
+++ b/libs/ardour/session.cc
@@ -72,6 +72,7 @@
#include "ardour/processor.h"
#include "ardour/recent_sessions.h"
#include "ardour/region_factory.h"
+#include "ardour/return.h"
#include "ardour/route_group.h"
#include "ardour/send.h"
#include "ardour/session.h"
@@ -3666,6 +3667,7 @@ void
Session::add_processor (Processor* processor)
{
Send* send;
+ Return* retrn;
PortInsert* port_insert;
PluginInsert* plugin_insert;
@@ -3675,6 +3677,8 @@ Session::add_processor (Processor* processor)
_plugin_inserts.insert (_plugin_inserts.begin(), plugin_insert);
} else if ((send = dynamic_cast<Send *> (processor)) != 0) {
_sends.insert (_sends.begin(), send);
+ } else if ((retrn = dynamic_cast<Return *> (processor)) != 0) {
+ _returns.insert (_returns.begin(), retrn);
} else {
fatal << _("programming error: unknown type of Insert created!") << endmsg;
/*NOTREACHED*/
@@ -3689,6 +3693,7 @@ void
Session::remove_processor (Processor* processor)
{
Send* send;
+ Return* retrn;
PortInsert* port_insert;
PluginInsert* plugin_insert;
@@ -3706,6 +3711,12 @@ Session::remove_processor (Processor* processor)
send_bitset[send->bit_slot()] = false;
_sends.erase (x);
}
+ } else if ((retrn = dynamic_cast<Return *> (processor)) != 0) {
+ list<Return*>::iterator x = find (_returns.begin(), _returns.end(), retrn);
+ if (x != _returns.end()) {
+ return_bitset[send->bit_slot()] = false;
+ _returns.erase (x);
+ }
} else {
fatal << _("programming error: unknown type of Insert deleted!") << endmsg;
/*NOTREACHED*/
@@ -3884,6 +3895,26 @@ Session::next_send_id ()
}
}
+uint32_t
+Session::next_return_id ()
+{
+ /* this doesn't really loop forever. just think about it */
+
+ while (true) {
+ for (boost::dynamic_bitset<uint32_t>::size_type n = 0; n < return_bitset.size(); ++n) {
+ if (!return_bitset[n]) {
+ return_bitset[n] = true;
+ return n;
+
+ }
+ }
+
+ /* none available, so resize and try again */
+
+ return_bitset.resize (return_bitset.size() + 16, false);
+ }
+}
+
void
Session::mark_send_id (uint32_t id)
{
@@ -3897,6 +3928,18 @@ Session::mark_send_id (uint32_t id)
}
void
+Session::mark_return_id (uint32_t id)
+{
+ if (id >= return_bitset.size()) {
+ return_bitset.resize (id+16, false);
+ }
+ if (return_bitset[id]) {
+ warning << string_compose (_("return ID %1 appears to be in use already"), id) << endmsg;
+ }
+ return_bitset[id] = true;
+}
+
+void
Session::mark_insert_id (uint32_t id)
{
if (id >= insert_bitset.size()) {
diff --git a/libs/ardour/wscript b/libs/ardour/wscript
index adcf3a5f0b..fc0e8107f9 100644
--- a/libs/ardour/wscript
+++ b/libs/ardour/wscript
@@ -175,6 +175,7 @@ def build(bld):
region.cc
region_factory.cc
resampled_source.cc
+ return.cc
reverse.cc
route.cc
route_group.cc