diff options
author | Robin Gareus <robin@gareus.org> | 2014-01-13 23:21:30 +0100 |
---|---|---|
committer | Robin Gareus <robin@gareus.org> | 2014-01-13 23:21:30 +0100 |
commit | e45151b89c64912077c03fc979f1581780ac9e27 (patch) | |
tree | 0fa6c5fbcb350dd40fadb36f97b472ae25bd0e73 | |
parent | 5b0c90299785d46357a70cc7625c9b3ee87486f1 (diff) |
first stab at send+route panner link
-rw-r--r-- | gtk2_ardour/ardour.menus.in | 1 | ||||
-rw-r--r-- | gtk2_ardour/processor_box.cc | 54 | ||||
-rw-r--r-- | gtk2_ardour/processor_box.h | 2 | ||||
-rw-r--r-- | libs/ardour/ardour/panner_shell.h | 18 | ||||
-rw-r--r-- | libs/ardour/ardour/rc_configuration_vars.h | 2 | ||||
-rw-r--r-- | libs/ardour/delivery.cc | 8 | ||||
-rw-r--r-- | libs/ardour/panner_shell.cc | 52 | ||||
-rw-r--r-- | libs/ardour/route.cc | 11 |
8 files changed, 121 insertions, 27 deletions
diff --git a/gtk2_ardour/ardour.menus.in b/gtk2_ardour/ardour.menus.in index a354df603d..b6328963bb 100644 --- a/gtk2_ardour/ardour.menus.in +++ b/gtk2_ardour/ardour.menus.in @@ -551,6 +551,7 @@ <menuitem action='newaux'/> <separator/> <menuitem action='controls'/> + <menuitem action='send_options'/> <separator/> <menuitem action='clear'/> <menuitem action='clear_pre'/> diff --git a/gtk2_ardour/processor_box.cc b/gtk2_ardour/processor_box.cc index 98bb3f13cd..c2421dcabf 100644 --- a/gtk2_ardour/processor_box.cc +++ b/gtk2_ardour/processor_box.cc @@ -45,8 +45,8 @@ #include "ardour/audioengine.h" #include "ardour/internal_return.h" #include "ardour/internal_send.h" +#include "ardour/panner_shell.h" #include "ardour/plugin_insert.h" -#include "ardour/pannable.h" #include "ardour/port_insert.h" #include "ardour/profile.h" #include "ardour/return.h" @@ -456,6 +456,34 @@ ProcessorEntry::toggle_control_visibility (Control* c) _parent->update_gui_object_state (this); } +Menu * +ProcessorEntry::build_send_options_menu () +{ + using namespace Menu_Helpers; + Menu* menu = manage (new Menu); + MenuList& items = menu->items (); + + boost::shared_ptr<Send> send = boost::dynamic_pointer_cast<Send> (_processor); + if (send) { + + items.push_back (CheckMenuElem (_("Link panner controls"))); + CheckMenuItem* c = dynamic_cast<CheckMenuItem*> (&items.back ()); + c->set_active (send->panner_shell()->is_linked_to_route()); + c->signal_toggled().connect (sigc::mem_fun (*this, &ProcessorEntry::toggle_panner_link)); + + } + return menu; +} + +void +ProcessorEntry::toggle_panner_link () +{ + boost::shared_ptr<Send> send = boost::dynamic_pointer_cast<Send> (_processor); + if (send) { + send->panner_shell()->set_linked_to_route(!send->panner_shell()->is_linked_to_route()); + } +} + ProcessorEntry::Control::Control (boost::shared_ptr<AutomationControl> c, string const & n) : _control (c) , _adjustment (gain_to_slider_position_with_max (1.0, Config->get_max_gain()), 0, 1, 0.01, 0.1) @@ -1092,6 +1120,20 @@ ProcessorBox::show_processor_menu (int arg) } } + Gtk::MenuItem* send_menu_item = dynamic_cast<Gtk::MenuItem*>(ActionManager::get_widget("/ProcessorMenu/send_options")); + if (send_menu_item) { + if (single_selection) { + Menu* m = single_selection->build_send_options_menu (); + if (m && !m->items().empty()) { + send_menu_item->set_submenu (*m); + send_menu_item->set_sensitive (true); + } else { + gtk_menu_item_set_submenu (send_menu_item->gobj(), 0); + send_menu_item->set_sensitive (false); + } + } + } + /* Sensitise actions as approprioate */ cut_action->set_sensitive (can_cut()); @@ -1403,8 +1445,7 @@ ProcessorBox::choose_insert () void ProcessorBox::choose_send () { - boost::shared_ptr<Pannable> sendpan(new Pannable (*_session)); - boost::shared_ptr<Send> send (new Send (*_session, sendpan, _route->mute_master())); + boost::shared_ptr<Send> send (new Send (*_session, _route->pannable(), _route->mute_master())); /* make an educated guess at the initial number of outputs for the send */ ChanCount outs = (_session->master_out()) @@ -2053,9 +2094,8 @@ ProcessorBox::paste_processor_state (const XMLNodeList& nlist, boost::shared_ptr continue; } - boost::shared_ptr<Pannable> sendpan(new Pannable (*_session)); XMLNode n (**niter); - InternalSend* s = new InternalSend (*_session, sendpan, _route->mute_master(), + InternalSend* s = new InternalSend (*_session, _route->pannable(), _route->mute_master(), boost::shared_ptr<Route>(), Delivery::Aux); IOProcessor::prepare_for_reset (n, s->name()); @@ -2069,9 +2109,8 @@ ProcessorBox::paste_processor_state (const XMLNodeList& nlist, boost::shared_ptr } else if (type->value() == "send") { - boost::shared_ptr<Pannable> sendpan(new Pannable (*_session)); XMLNode n (**niter); - Send* s = new Send (*_session, sendpan, _route->mute_master()); + Send* s = new Send (*_session, _route->pannable(), _route->mute_master()); IOProcessor::prepare_for_reset (n, s->name()); @@ -2404,6 +2443,7 @@ ProcessorBox::register_actions () ActionManager::register_action (popup_act_grp, X_("newaux"), _("New Aux Send ...")); ActionManager::register_action (popup_act_grp, X_("controls"), _("Controls")); + ActionManager::register_action (popup_act_grp, X_("send_options"), _("Send Options")); ActionManager::register_action (popup_act_grp, X_("clear"), _("Clear (all)"), sigc::ptr_fun (ProcessorBox::rb_clear)); diff --git a/gtk2_ardour/processor_box.h b/gtk2_ardour/processor_box.h index a66a6c4a56..021e557d36 100644 --- a/gtk2_ardour/processor_box.h +++ b/gtk2_ardour/processor_box.h @@ -138,6 +138,7 @@ public: void set_control_state (XMLNode const *); std::string state_id () const; Gtk::Menu* build_controls_menu (); + Gtk::Menu* build_send_options_menu (); protected: ArdourButton _button; @@ -205,6 +206,7 @@ private: std::list<Control*> _controls; void toggle_control_visibility (Control *); + void toggle_panner_link (); class PortIcon : public Gtk::DrawingArea { public: diff --git a/libs/ardour/ardour/panner_shell.h b/libs/ardour/ardour/panner_shell.h index 765acad16a..60db264b4d 100644 --- a/libs/ardour/ardour/panner_shell.h +++ b/libs/ardour/ardour/panner_shell.h @@ -49,7 +49,7 @@ class Pannable; class PannerShell : public SessionObject { public: - PannerShell (std::string name, Session&, boost::shared_ptr<Pannable>); + PannerShell (std::string name, Session&, boost::shared_ptr<Pannable>, bool is_send = false); virtual ~PannerShell (); std::string describe_parameter (Evoral::Parameter param); @@ -63,19 +63,25 @@ public: XMLNode& get_state (); int set_state (const XMLNode&, int version); + PBD::Signal0<void> PannableChanged; /* Pannable changed -- l*/ PBD::Signal0<void> Changed; /* panner and/or outputs count and/or bypass state changed */ boost::shared_ptr<Panner> panner() const { return _panner; } - boost::shared_ptr<Pannable> pannable() const { return _pannable; } + boost::shared_ptr<Pannable> pannable() const { return _panlinked ? _pannable_route : _pannable_internal; } bool bypassed () const; void set_bypassed (bool); + bool is_send () const { return (_is_send); } + bool is_linked_to_route () const { return (_is_send && _panlinked); } + /* this function takes the process lock: */ + void set_linked_to_route (bool); + std::string current_panner_uri() const { return _current_panner_uri; } std::string user_selected_panner_uri() const { return _user_selected_panner_uri; } std::string panner_gui_uri() const { return _panner_gui_uri; } - /* this function takes the process lock */ + /* this function takes the process lock: */ bool select_panner_by_uri (std::string const uri); private: @@ -84,7 +90,11 @@ public: bool set_user_selected_panner_uri (std::string const uri); boost::shared_ptr<Panner> _panner; - boost::shared_ptr<Pannable> _pannable; + + boost::shared_ptr<Pannable> _pannable_internal; + boost::shared_ptr<Pannable> _pannable_route; + bool _is_send; + bool _panlinked; bool _bypassed; std::string _current_panner_uri; diff --git a/libs/ardour/ardour/rc_configuration_vars.h b/libs/ardour/ardour/rc_configuration_vars.h index e1f8b42914..b92d0e152a 100644 --- a/libs/ardour/ardour/rc_configuration_vars.h +++ b/libs/ardour/ardour/rc_configuration_vars.h @@ -113,6 +113,8 @@ CONFIG_VARIABLE (gain_t, solo_mute_gain, "solo-mute-gain", 0.0) CONFIG_VARIABLE (std::string, monitor_bus_preferred_bundle, "monitor-bus-preferred-bundle", "") CONFIG_VARIABLE (bool, quieten_at_speed, "quieten-at-speed", true) +CONFIG_VARIABLE (bool, link_send_and_route_panner, "link-send-and-route-panner", true) + /* click */ CONFIG_VARIABLE (bool, clicking, "clicking", false) diff --git a/libs/ardour/delivery.cc b/libs/ardour/delivery.cc index 8e636ed861..b4b9831d97 100644 --- a/libs/ardour/delivery.cc +++ b/libs/ardour/delivery.cc @@ -58,7 +58,9 @@ Delivery::Delivery (Session& s, boost::shared_ptr<IO> io, boost::shared_ptr<Pann , _no_panner_reset (false) { if (pannable) { - _panshell = boost::shared_ptr<PannerShell>(new PannerShell (_name, _session, pannable)); + bool is_send = false; + if (r & (Delivery::Send|Delivery::Aux)) is_send = true; + _panshell = boost::shared_ptr<PannerShell>(new PannerShell (_name, _session, pannable, is_send)); } _display_to_user = false; @@ -80,7 +82,9 @@ Delivery::Delivery (Session& s, boost::shared_ptr<Pannable> pannable, boost::sha , _no_panner_reset (false) { if (pannable) { - _panshell = boost::shared_ptr<PannerShell>(new PannerShell (_name, _session, pannable)); + bool is_send = false; + if (r & (Delivery::Send|Delivery::Aux)) is_send = true; + _panshell = boost::shared_ptr<PannerShell>(new PannerShell (_name, _session, pannable, is_send)); } _display_to_user = false; diff --git a/libs/ardour/panner_shell.cc b/libs/ardour/panner_shell.cc index ccb8aa8e87..b489354e21 100644 --- a/libs/ardour/panner_shell.cc +++ b/libs/ardour/panner_shell.cc @@ -61,21 +61,31 @@ using namespace std; using namespace ARDOUR; using namespace PBD; -PannerShell::PannerShell (string name, Session& s, boost::shared_ptr<Pannable> p) +PannerShell::PannerShell (string name, Session& s, boost::shared_ptr<Pannable> p, bool is_send) : SessionObject (s, name) - , _pannable (p) + , _pannable_route (p) + , _is_send (is_send) + , _panlinked (true) , _bypassed (false) , _current_panner_uri("") , _user_selected_panner_uri("") , _panner_gui_uri("") , _force_reselect (false) { + if (is_send) { + _pannable_internal.reset(new Pannable (s)); + if (Config->get_link_send_and_route_panner()) { + _panlinked = true; + } else { + _panlinked = false; + } + } set_name (name); } PannerShell::~PannerShell () { - DEBUG_TRACE(DEBUG::Destruction, string_compose ("panner shell %3 for %1 destructor, panner is %4, pannable is %2\n", _name, _pannable, this, _panner)); + DEBUG_TRACE(DEBUG::Destruction, string_compose ("panner shell %3 for %1 destructor, panner is %4, pannable is %2\n", _name, _pannable_route, this, _panner)); } void @@ -122,7 +132,8 @@ PannerShell::configure_io (ChanCount in, ChanCount out) speakers.reset (s); } - Panner* p = pi->descriptor.factory (_pannable, speakers); + /* TODO don't allow to link _is_send if internal & route panners are different types */ + Panner* p = pi->descriptor.factory (pannable(), speakers); // boost_debug_shared_ptr_mark_interesting (p, "Panner"); _panner.reset (p); _panner->configure_io (in, out); @@ -139,8 +150,9 @@ PannerShell::get_state () node->add_property (X_("bypassed"), _bypassed ? X_("yes") : X_("no")); node->add_property (X_("user-panner"), _user_selected_panner_uri); + node->add_property (X_("linked-to-route"), _panlinked ? X_("yes") : X_("no")); - if (_panner) { + if (_panner && _is_send) { node->add_child_nocopy (_panner->get_state ()); } @@ -159,6 +171,10 @@ PannerShell::set_state (const XMLNode& node, int version) set_bypassed (string_is_affirmative (prop->value ())); } + if ((prop = node.property (X_("linked-to-route"))) != 0) { + _panlinked = string_is_affirmative (prop->value ()); + } + if ((prop = node.property (X_("user-panner"))) != 0) { _user_selected_panner_uri = prop->value (); } @@ -172,7 +188,8 @@ PannerShell::set_state (const XMLNode& node, int version) if ((prop = (*niter)->property (X_("uri")))) { PannerInfo* p = PannerManager::instance().get_by_uri(prop->value()); if (p) { - _panner.reset (p->descriptor.factory (_pannable, _session.get_speakers ())); + _panner.reset (p->descriptor.factory ( + _is_send ? _pannable_internal : _pannable_route, _session.get_speakers ())); _current_panner_uri = p->descriptor.panner_uri; _panner_gui_uri = p->descriptor.gui_uri; if (_panner->set_state (**niter, version) == 0) { @@ -195,7 +212,8 @@ PannerShell::set_state (const XMLNode& node, int version) assumption, but it's still an assumption. */ - _panner.reset ((*p)->descriptor.factory (_pannable, _session.get_speakers ())); + _panner.reset ((*p)->descriptor.factory ( + _is_send ? _pannable_internal : _pannable_route, _session.get_speakers ())); _current_panner_uri = (*p)->descriptor.panner_uri; _panner_gui_uri = (*p)->descriptor.gui_uri; @@ -413,3 +431,23 @@ PannerShell::select_panner_by_uri (std::string const uri) } return true; } + +void +PannerShell::set_linked_to_route (bool onoff) +{ + if (!_is_send || onoff == _panlinked) { + return; + } + _panlinked = onoff; + + _force_reselect = true; + if (_panner) { + Glib::Threads::Mutex::Lock lx (AudioEngine::instance()->process_lock ()); + ChanCount in = _panner->in(); + ChanCount out = _panner->out(); + configure_io(in, out); + pannable()->set_panner(_panner); + _session.set_dirty (); + } + PannableChanged(); +} diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc index ccfe38e9e1..a2176e8d45 100644 --- a/libs/ardour/route.cc +++ b/libs/ardour/route.cc @@ -1069,8 +1069,7 @@ Route::add_processor_from_xml_2X (const XMLNode& node, int version) } else if (node.name() == "Send") { - boost::shared_ptr<Pannable> sendpan (new Pannable (_session)); - processor.reset (new Send (_session, sendpan, _mute_master)); + processor.reset (new Send (_session, _pannable, _mute_master)); } else { @@ -2553,8 +2552,7 @@ Route::set_processor_state (const XMLNode& node) if (prop->value() == "intsend") { - boost::shared_ptr<Pannable> sendpan (new Pannable (_session)); - processor.reset (new InternalSend (_session, sendpan, _mute_master, boost::shared_ptr<Route>(), Delivery::Role (0))); + processor.reset (new InternalSend (_session, _pannable, _mute_master, boost::shared_ptr<Route>(), Delivery::Aux)); } else if (prop->value() == "ladspa" || prop->value() == "Ladspa" || prop->value() == "lv2" || @@ -2571,7 +2569,7 @@ Route::set_processor_state (const XMLNode& node) } else if (prop->value() == "send") { boost::shared_ptr<Pannable> sendpan (new Pannable (_session)); - processor.reset (new Send (_session, sendpan, _mute_master)); + processor.reset (new Send (_session, _pannable, _mute_master)); } else { error << string_compose(_("unknown Processor type \"%1\"; ignored"), prop->value()) << endmsg; @@ -2761,8 +2759,7 @@ Route::add_aux_send (boost::shared_ptr<Route> route, boost::shared_ptr<Processor { Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ()); - boost::shared_ptr<Pannable> sendpan (new Pannable (_session)); - listener.reset (new InternalSend (_session, sendpan, _mute_master, route, Delivery::Aux)); + listener.reset (new InternalSend (_session, _pannable, _mute_master, route, Delivery::Aux)); } add_processor (listener, before); |