diff options
-rw-r--r-- | gtk2_ardour/SAE-us-keypad.bindings.in | 1 | ||||
-rw-r--r-- | gtk2_ardour/ardour-sae.menus | 1 | ||||
-rw-r--r-- | gtk2_ardour/ardour.menus.in | 2 | ||||
-rw-r--r-- | gtk2_ardour/ergonomic-us.bindings.in | 1 | ||||
-rw-r--r-- | gtk2_ardour/mnemonic-us.bindings.in | 1 | ||||
-rw-r--r-- | gtk2_ardour/processor_box.cc | 151 | ||||
-rw-r--r-- | gtk2_ardour/processor_box.h | 6 | ||||
-rw-r--r-- | gtk2_ardour/return_ui.cc | 133 | ||||
-rw-r--r-- | gtk2_ardour/return_ui.h | 77 | ||||
-rw-r--r-- | gtk2_ardour/route_params_ui.cc | 83 | ||||
-rw-r--r-- | gtk2_ardour/send_ui.cc | 49 | ||||
-rw-r--r-- | gtk2_ardour/send_ui.h | 12 | ||||
-rw-r--r-- | gtk2_ardour/wscript | 1 | ||||
-rw-r--r-- | libs/ardour/ardour/chan_count.h | 8 | ||||
-rw-r--r-- | libs/ardour/ardour/io.h | 3 | ||||
-rw-r--r-- | libs/ardour/ardour/port_insert.h | 3 | ||||
-rw-r--r-- | libs/ardour/ardour/return.h | 71 | ||||
-rw-r--r-- | libs/ardour/ardour/send.h | 9 | ||||
-rw-r--r-- | libs/ardour/ardour/session.h | 5 | ||||
-rw-r--r-- | libs/ardour/io.cc | 34 | ||||
-rw-r--r-- | libs/ardour/port_insert.cc | 31 | ||||
-rw-r--r-- | libs/ardour/return.cc | 164 | ||||
-rw-r--r-- | libs/ardour/send.cc | 65 | ||||
-rw-r--r-- | libs/ardour/session.cc | 43 | ||||
-rw-r--r-- | libs/ardour/wscript | 1 |
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 |