75% (?) of the way towards making mixer strips control bus sends. lots more to do
authorPaul Davis <paul@linuxaudiosystems.com>
Sun, 17 May 2009 02:08:13 +0000 (02:08 +0000)
committerPaul Davis <paul@linuxaudiosystems.com>
Sun, 17 May 2009 02:08:13 +0000 (02:08 +0000)
git-svn-id: svn://localhost/ardour2/branches/3.0@5090 d708f5d6-7413-0410-9779-e7cbd77b26cf

15 files changed:
gtk2_ardour/gain_meter.cc
gtk2_ardour/level_meter.cc
gtk2_ardour/level_meter.h
gtk2_ardour/mixer_strip.cc
gtk2_ardour/mixer_strip.h
gtk2_ardour/panner_ui.cc
gtk2_ardour/processor_box.cc
gtk2_ardour/processor_box.h
gtk2_ardour/route_params_ui.cc
gtk2_ardour/route_ui.cc
gtk2_ardour/route_ui.h
libs/ardour/ardour/io.h
libs/ardour/ardour/route.h
libs/ardour/io.cc
libs/ardour/route.cc

index f06597253c33e67207205341cbc903f381923477..597e2a2fbeac5d8bfd3570d7b6f8b132c25ac1e4 100644 (file)
@@ -165,7 +165,13 @@ GainMeterBase::set_io (boost::shared_ptr<IO> io)
        
        _io = io;
        
-       level_meter->set_meter (_io->peak_meter());
+       if (!_io) {
+               level_meter->set_meter (0);
+               gain_slider->set_controllable (boost::shared_ptr<PBD::Controllable>());
+               return;
+       } 
+
+       level_meter->set_meter (&_io->peak_meter());
        gain_slider->set_controllable (_io->gain_control());
 
        boost::shared_ptr<Route> r;
@@ -836,6 +842,14 @@ GainMeter::set_io (boost::shared_ptr<IO> io)
                if (!r->is_hidden()) {
                        fader_vbox->pack_start (gain_automation_state_button, false, false, 0);
                }
+
+       } else {
+
+               /* we're managing a non-Route IO (e.g. Send) */
+
+               gain_display_box.pack_end (peak_display, true, true);
+               hbox.pack_end (*level_meter, true, true);
+               fader_vbox->pack_start (gain_automation_state_button, false, false, 0);
        }
 }
 
index 1f6cecb74d972b05381e6b0f8434fc2e3f46f37f..f6d41c3312e7fa7e5c5c30d4b51f4b615a755f6f 100644 (file)
@@ -80,12 +80,14 @@ LevelMeter::~LevelMeter ()
 }
 
 void
-LevelMeter::set_meter (PeakMeter& meter)
+LevelMeter::set_meter (PeakMeter* meter)
 {
        _configuration_connection.disconnect();
-       _meter = &meter;
-       _configuration_connection = _meter->ConfigurationChanged.connect(
+       _meter = meter;
+       if (_meter) {
+               _configuration_connection = _meter->ConfigurationChanged.connect(
                        mem_fun(*this, &LevelMeter::configuration_changed));
+       }
 }
 
 float
@@ -94,6 +96,10 @@ LevelMeter::update_meters ()
        vector<MeterInfo>::iterator i;
        uint32_t n;
        float peak, mpeak;
+
+       if (!_meter) {
+               return 0.0f;
+       }
        
        for (n = 0, i = meters.begin(); i != meters.end(); ++i, ++n) {
                if ((*i).packed) {
@@ -149,8 +155,10 @@ LevelMeter::hide_all_meters ()
 void
 LevelMeter::setup_meters (int len, int initial_width)
 {
+       hide_all_meters ();
+
        if (!_meter) {
-               return; /* do it later */
+               return; /* do it later or never */
        }
  
        int32_t nmidi = _meter->input_streams().n_midi();
@@ -160,8 +168,6 @@ LevelMeter::setup_meters (int len, int initial_width)
 
        guint16 width;
 
-       hide_all_meters ();
-
        if (nmeters == 0) {
                return;
        }
index 100ce213537e71ace4c9b859f5f538addbc139bf..a2bbd5f4a1089873d7ecbb625216e593c504889d 100644 (file)
@@ -55,7 +55,7 @@ class LevelMeter : public Gtk::HBox
        LevelMeter (ARDOUR::Session&);
        ~LevelMeter ();
 
-       virtual void set_meter (ARDOUR::PeakMeter& meter);
+       virtual void set_meter (ARDOUR::PeakMeter* meter);
 
        void update_gain_sensitive ();
 
index 8a00eb88a28a2f8675bb934b27d0f3a653ff2204..5a8442dc44d577f9f37d5e53c5eb75f4658ceac3 100644 (file)
@@ -67,6 +67,8 @@ using namespace Gtk;
 using namespace Gtkmm2ext;
 using namespace std;
 
+sigc::signal<void,boost::shared_ptr<Route> > MixerStrip::SwitchIO;
+
 int MixerStrip::scrollbar_height = 0;
 
 #ifdef VARISPEED_IN_MIXER_STRIP
@@ -88,8 +90,8 @@ MixerStrip::MixerStrip (Mixer_UI& mx, Session& sess, bool in_mixer)
        , RouteUI (sess, _("Mute"), _("Solo"), _("Record"))
        ,_mixer(mx)
        , _mixer_owned (in_mixer)
-       , pre_processor_box (PreFader, sess, mx.plugin_selector(), mx.selection(), in_mixer)
-       , post_processor_box (PostFader, sess, mx.plugin_selector(), mx.selection(), in_mixer)
+       , pre_processor_box (PreFader, sess, mx.plugin_selector(), mx.selection(), this, in_mixer)
+       , post_processor_box (PostFader, sess, mx.plugin_selector(), mx.selection(), this, in_mixer)
        , gpm (sess)
        , panners (sess)
        , button_table (3, 2)
@@ -117,8 +119,8 @@ MixerStrip::MixerStrip (Mixer_UI& mx, Session& sess, boost::shared_ptr<Route> rt
        , RouteUI (sess, _("Mute"), _("Solo"), _("Record"))
        ,_mixer(mx)
        , _mixer_owned (in_mixer)
-       , pre_processor_box (PreFader, sess, mx.plugin_selector(), mx.selection(), in_mixer)
-       , post_processor_box (PostFader, sess, mx.plugin_selector(), mx.selection(), in_mixer)
+       , pre_processor_box (PreFader, sess, mx.plugin_selector(), mx.selection(), this, in_mixer)
+       , post_processor_box (PostFader, sess, mx.plugin_selector(), mx.selection(), this, in_mixer)
        , gpm (sess)
        , panners (sess)
        , button_table (3, 2)
@@ -290,6 +292,12 @@ MixerStrip::init ()
        rec_enable_button->signal_button_press_event().connect (mem_fun(*this, &RouteUI::rec_enable_press), false);
        rec_enable_button->signal_button_release_event().connect (mem_fun(*this, &RouteUI::rec_enable_release));
 
+       /* ditto for this button and busses */
+
+       show_sends_button->set_name ("MixerRecordEnableButton");
+       show_sends_button->signal_button_press_event().connect (mem_fun(*this, &RouteUI::show_sends_press), false);
+       show_sends_button->signal_button_release_event().connect (mem_fun(*this, &RouteUI::show_sends_release));
+
        name_button.signal_button_press_event().connect (mem_fun(*this, &MixerStrip::name_button_button_press), false);
        group_button.signal_button_press_event().connect (mem_fun(*this, &MixerStrip::select_mix_group), false);
 
@@ -309,6 +317,9 @@ MixerStrip::init ()
                set_name ("AudioTrackStripBase");
 
        add_events (Gdk::BUTTON_RELEASE_MASK);
+
+       SwitchIO.connect (mem_fun (*this, &MixerStrip::switch_io));
+       
 }
 
 MixerStrip::~MixerStrip ()
@@ -326,6 +337,10 @@ MixerStrip::set_route (boost::shared_ptr<Route> rt)
                button_table.remove (*rec_enable_button);
        }
 
+       if (show_sends_button->get_parent()) {
+               button_table.remove (*show_sends_button);
+       }
+
 #ifdef VARISPEED_IN_MIXER_STRIP
        if (speed_frame->get_parent()) {
                button_table.remove (*speed_frame);
@@ -384,6 +399,12 @@ MixerStrip::set_route (boost::shared_ptr<Route> rt)
 
                button_table.attach (*rec_enable_button, 0, 2, 2, 3);
                rec_enable_button->show();
+
+       } else if (!is_track()) {
+               /* bus */
+
+               button_table.attach (*show_sends_button, 0, 2, 2, 3);
+               show_sends_button->show();
        }
 
        if (_route->phase_invert()) {
@@ -562,6 +583,9 @@ MixerStrip::set_width (Width w, void* owner)
                if (rec_enable_button)  {
                        ((Gtk::Label*)rec_enable_button->get_child())->set_text (_("Record"));
                }
+               if (show_sends_button)  {
+                       ((Gtk::Label*)show_sends_button->get_child())->set_text (_("Sends"));
+               }
                ((Gtk::Label*)mute_button->get_child())->set_text  (_("Mute"));
                ((Gtk::Label*)solo_button->get_child())->set_text (_("Solo"));
 
@@ -593,6 +617,9 @@ MixerStrip::set_width (Width w, void* owner)
                if (rec_enable_button) {
                        ((Gtk::Label*)rec_enable_button->get_child())->set_text (_("Rec"));
                }
+               if (show_sends_button) {
+                       ((Gtk::Label*)show_sends_button->get_child())->set_text (_("Snd"));
+               }
                ((Gtk::Label*)mute_button->get_child())->set_text (_("M"));
                ((Gtk::Label*)solo_button->get_child())->set_text (_("S"));
 
@@ -1462,3 +1489,24 @@ MixerStrip::meter_changed (void *src)
        set_width(_width, this);
 }
 
+void
+MixerStrip::switch_io (boost::shared_ptr<Route> target)
+{
+       boost::shared_ptr<IO> to_display;
+
+       if (_route == target) {
+               /* don't change the display for the target */
+               return;
+       }
+
+       if (!target) {
+               to_display = _route;
+       } else {
+               to_display = _route->send_io_for (target);
+       }
+       
+       gain_meter().set_io (to_display);
+       gain_meter().setup_meters ();
+       panner_ui().set_io (to_display);
+       panner_ui().setup_pan ();
+}
index e2fa2e52d56b2539272ace55eb2bbb5db4847f1e..958bfc942290484e970f63af66e4030cb435eff7 100644 (file)
@@ -88,6 +88,9 @@ class MixerStrip : public RouteUI, public Gtk::EventBox
        Width get_width() const { return _width; }
        void* width_owner() const { return _width_owner; }
 
+       GainMeter& gain_meter() { return gpm; }
+       PannerUI&  panner_ui()  { return panners; }
+
        void fast_update ();
        void set_embedded (bool);
        
@@ -98,6 +101,8 @@ class MixerStrip : public RouteUI, public Gtk::EventBox
        sigc::signal<void>      WidthChanged;
 #endif
 
+       static sigc::signal<void,boost::shared_ptr<ARDOUR::Route> > SwitchIO;
+
   protected:
        friend class Mixer_UI;
        void set_packed (bool yn);
@@ -257,6 +262,8 @@ class MixerStrip : public RouteUI, public Gtk::EventBox
        void engine_running();
        void engine_stopped();
 
+       void switch_io (boost::shared_ptr<ARDOUR::Route>);
+
        static int scrollbar_height;
 };
 
index c8c933348bc988934a2141df46b8347d48829f76..3ffec0ab05bfbebcef55bc8e5d138e03f48517a4 100644 (file)
@@ -133,7 +133,7 @@ PannerUI::PannerUI (Session& s)
 void
 PannerUI::set_io (boost::shared_ptr<IO> io)
 {
-       if (!io->panner()) {
+       if (io && !io->panner()) {
                cerr << "PannerUI::set_io IO has no panners" << endl;
                return;
        }
@@ -148,15 +148,16 @@ PannerUI::set_io (boost::shared_ptr<IO> io)
                        
        _io = io;
  
-       connections.push_back (_io->panner()->Changed.connect (
-                       mem_fun(*this, &PannerUI::panner_changed)));
-       connections.push_back (_io->panner()->LinkStateChanged.connect (
-                       mem_fun(*this, &PannerUI::update_pan_linkage)));
-       connections.push_back (_io->panner()->StateChanged.connect (
-                       mem_fun(*this, &PannerUI::update_pan_state)));
        delete panner;
        panner = 0;
+
+       if (!_io) {
+               return;
+       }
+       connections.push_back (_io->panner()->Changed.connect (mem_fun(*this, &PannerUI::panner_changed)));
+       connections.push_back (_io->panner()->LinkStateChanged.connect (mem_fun(*this, &PannerUI::update_pan_linkage)));
+       connections.push_back (_io->panner()->StateChanged.connect (mem_fun(*this, &PannerUI::update_pan_state)));
  
        setup_pan ();
 
@@ -338,7 +339,7 @@ PannerUI::update_pan_state ()
 void
 PannerUI::setup_pan ()
 {
-       if (!_io->panner()) {
+       if (!_io || !_io->panner()) {
                return;
        }
 
index 027d9df51e15d49a2f19c7448e280b7e295da982..f850582fec62ec9df1e4b2f34a3546d325dba93a 100644 (file)
@@ -59,6 +59,7 @@
 #include "io_selector.h"
 #include "keyboard.h"
 #include "mixer_ui.h"
+#include "mixer_strip.h"
 #include "plugin_selector.h"
 #include "plugin_ui.h"
 #include "processor_box.h"
@@ -89,8 +90,9 @@ Gdk::Color* ProcessorBox::active_processor_color;
 Gdk::Color* ProcessorBox::inactive_processor_color;
 
 ProcessorBox::ProcessorBox (Placement pcmnt, Session& sess, PluginSelector &plugsel,
-                           RouteRedirectSelection & rsel, bool owner_is_mixer)
+                           RouteRedirectSelection & rsel, MixerStrip* parent, bool owner_is_mixer)
        : _session(sess)
+       , _parent_strip (parent)
        , _owner_is_mixer (owner_is_mixer)
        , _placement(pcmnt)
        , _plugin_selector(plugsel)
@@ -1193,12 +1195,10 @@ ProcessorBox::edit_processor (boost::shared_ptr<Processor> processor)
                        return;
                }
 
-               boost::shared_ptr<Send> send = boost::dynamic_pointer_cast<Send> (processor);
-
+#ifdef OLD_SEND_EDITING
                SendUIWindow *send_ui;
 
                if (send->get_gui() == 0) {
-
                        send_ui = new SendUIWindow (send, _session);
 
                        WindowTitle title(Glib::get_application_name());
@@ -1212,6 +1212,12 @@ ProcessorBox::edit_processor (boost::shared_ptr<Processor> processor)
                }
 
                gidget = send_ui;
+#else
+               if (_parent_strip) {
+                       _parent_strip->gain_meter().set_io (send->io());
+                       _parent_strip->panner_ui().set_io (send->io());
+               }
+#endif
        
        } else if ((retrn = boost::dynamic_pointer_cast<Return> (processor)) != 0) {
 
index a003ed8c5d2509c7a33af2fd0f2975f248b2de48..d53d05fe2328695c2f371f4e267951efcfa16603 100644 (file)
@@ -52,6 +52,7 @@ class MotionController;
 class PluginSelector;
 class PluginUIWindow;
 class RouteRedirectSelection;
+class MixerStrip;
 
 namespace ARDOUR {
        class Connection;
@@ -68,7 +69,7 @@ namespace ARDOUR {
 class ProcessorBox : public Gtk::HBox, public PluginInterestedObject
 {
   public:
-       ProcessorBox (ARDOUR::Placement, ARDOUR::Session&, PluginSelector &, RouteRedirectSelection &, bool owner_is_mixer = false);
+       ProcessorBox (ARDOUR::Placement, ARDOUR::Session&, PluginSelector &, RouteRedirectSelection &, MixerStrip* parent, bool owner_is_mixer = false);
        ~ProcessorBox ();
 
        void set_route (boost::shared_ptr<ARDOUR::Route>);
@@ -90,6 +91,7 @@ class ProcessorBox : public Gtk::HBox, public PluginInterestedObject
   private:
        boost::shared_ptr<ARDOUR::Route>  _route;
        ARDOUR::Session &   _session;
+       MixerStrip*         _parent_strip; // null if in RouteParamsUI
        bool                _owner_is_mixer;
        bool                 ab_direction;
        std::vector<sigc::connection> connections;
index 33a99f695587e6b24f121968f87ea4c1919ee324..5c709d80bfebeb9ab944042d8cfb89be1bf1b816 100644 (file)
@@ -231,8 +231,8 @@ RouteParams_UI::setup_processor_boxes()
                cleanup_processor_boxes();
                
                // construct new redirect boxes
-               pre_insert_box = new ProcessorBox(PreFader, *session, *_plugin_selector, _rr_selection);
-               post_insert_box = new ProcessorBox(PostFader, *session, *_plugin_selector, _rr_selection);
+               pre_insert_box = new ProcessorBox(PreFader, *session, *_plugin_selector, _rr_selection, 0);
+               post_insert_box = new ProcessorBox(PostFader, *session, *_plugin_selector, _rr_selection, 0);
   
                pre_insert_box->set_route (_route);
                post_insert_box->set_route (_route);
index 40d0ae8da5adc4be0c9fee207f2862c7d17ffdff..d050bc97fe6b14e18f83547eb445af3a0f15a5fe 100644 (file)
@@ -38,6 +38,7 @@
 #include "gui_thread.h"
 #include "ardour_dialog.h"
 #include "latency_gui.h"
+#include "mixer_strip.h"
 #include "automation_time_axis.h"
 
 #include "ardour/route.h"
@@ -84,6 +85,7 @@ RouteUI::~RouteUI()
        delete solo_menu;
        delete mute_menu;
        delete remote_control_menu;
+       delete sends_menu;
 }
 
 void
@@ -94,6 +96,7 @@ RouteUI::init ()
        mute_menu = 0;
        solo_menu = 0;
        remote_control_menu = 0;
+       sends_menu = 0;
        ignore_toggle = false;
        wait_for_release = false;
        route_active_menu_item = 0;
@@ -118,6 +121,11 @@ RouteUI::init ()
        rec_enable_button->set_self_managed (true);
        UI::instance()->set_tip (rec_enable_button, _("Enable recording on this track"), "");
 
+       show_sends_button = manage (new BindableToggleButton (""));
+       show_sends_button->set_name ("ShowSendsButton");
+       show_sends_button->set_self_managed (true);
+       UI::instance()->set_tip (show_sends_button, _("make mixer strips show sends to this bus"), "");
+
        _session.SoloChanged.connect (mem_fun(*this, &RouteUI::solo_changed_so_update_mute));
 }
 
@@ -497,6 +505,83 @@ RouteUI::rec_enable_release (GdkEventButton* ev)
        return true;
 }
 
+void
+RouteUI::build_sends_menu ()
+{
+       using namespace Menu_Helpers;
+       
+       sends_menu = new Menu;
+       sends_menu->set_name ("ArdourContextMenu");
+       MenuList& items = sends_menu->items();
+       
+       items.push_back (MenuElem(_("Copy track gains to sends"), mem_fun (*this, &RouteUI::set_sends_gain_from_track)));
+       items.push_back (MenuElem(_("Set sends gain to -inf"), mem_fun (*this, &RouteUI::set_sends_gain_to_zero)));
+       items.push_back (MenuElem(_("Set sends gain to 0dB"), mem_fun (*this, &RouteUI::set_sends_gain_to_unity)));
+}
+
+void
+RouteUI::set_sends_gain_from_track ()
+{
+}
+
+void
+RouteUI::set_sends_gain_to_zero ()
+{
+}
+
+void
+RouteUI::set_sends_gain_to_unity ()
+{
+}
+
+bool
+RouteUI::show_sends_press(GdkEventButton* ev)
+{
+       if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
+               return true;
+       }
+
+       if (!ignore_toggle && !is_track() && show_sends_button) {
+
+               if (Keyboard::is_button2_event (ev) && Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
+
+                       // do nothing on midi bind event
+                       return false;
+
+               } else if (Keyboard::is_context_menu_event (ev)) {
+
+                       if (sends_menu == 0) {
+                               build_sends_menu ();
+                       }
+
+                       sends_menu->popup (0, ev->time);
+
+               } else {
+
+                       /* change button state */
+
+                       show_sends_button->set_active (!show_sends_button->get_active());
+
+                       if (show_sends_button->get_active()) {
+                               /* show sends to this bus */
+                               MixerStrip::SwitchIO (_route);
+                       } else {
+                               /* everybody back to normal */
+                               MixerStrip::SwitchIO (boost::shared_ptr<Route>());
+                       }
+
+               }
+       }
+
+       return true;
+}
+
+bool
+RouteUI::show_sends_release (GdkEventButton* ev)
+{
+       return true;
+}
+
 void
 RouteUI::solo_changed(void* src)
 {
index 4ec6fd3ce81f9cb0c4ca3ff1e106eafcd67bf178..5a1933997dde9bc60d53194c2283e436edaabc1f 100644 (file)
@@ -81,7 +81,8 @@ class RouteUI : public virtual AxisView
 
        BindableToggleButton* mute_button;
        BindableToggleButton* solo_button;
-       BindableToggleButton* rec_enable_button;
+       BindableToggleButton* rec_enable_button; /* audio tracks */
+       BindableToggleButton* show_sends_button; /* busses */
        
        virtual std::string solo_button_name () const { return "SoloButton"; }
        virtual std::string safe_solo_button_name () const { return "SafeSoloButton"; }
@@ -89,6 +90,7 @@ class RouteUI : public virtual AxisView
        Gtk::Menu* mute_menu;
        Gtk::Menu* solo_menu;
        Gtk::Menu* remote_control_menu;
+       Gtk::Menu* sends_menu;
 
        XMLNode *xml_node;
        void ensure_xml_node ();
@@ -101,6 +103,13 @@ class RouteUI : public virtual AxisView
        bool solo_release(GdkEventButton*);
        bool rec_enable_press(GdkEventButton*);
        bool rec_enable_release(GdkEventButton*);
+       bool show_sends_press(GdkEventButton*);
+       bool show_sends_release(GdkEventButton*);
+
+       void build_sends_menu ();
+       void set_sends_gain_from_track ();
+       void set_sends_gain_to_zero ();
+       void set_sends_gain_to_unity ();
 
        void solo_changed(void*);
        void solo_changed_so_update_mute ();
index 5c7d8d0f0f62945ab06967a9c5adacf17e3ffa76..23e4f576df14554d8cc8229cafec1c1c0b9829f8 100644 (file)
@@ -141,6 +141,8 @@ class IO : public SessionObject, public AutomatableControls, public Latent
        int disconnect_inputs (void *src);
        int disconnect_outputs (void *src);
 
+       bool connected_to (boost::shared_ptr<const IO>) const;
+
        nframes_t signal_latency() const { return _own_latency; }
        nframes_t output_latency() const;
        nframes_t input_latency() const;
index c498b1f04eab7d827fb748b61ac3d8e3d622bbed..10aec0446e8ff6a3b7fce9123f996a88fd6e3af3 100644 (file)
@@ -91,7 +91,6 @@ class Route : public IO
 
        /* these are the core of the API of a Route. see the protected sections as well */
 
-
        virtual int roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame, 
                          int declick, bool can_record, bool rec_monitors_input);
 
@@ -181,6 +180,8 @@ class Route : public IO
 
        boost::shared_ptr<Delivery> control_outs() const { return _control_outs; }
        boost::shared_ptr<Delivery> main_outs() const { return _main_outs; }
+
+       boost::shared_ptr<IO> send_io_for (boost::shared_ptr<const IO> target) const;
        
        /** A record of the stream configuration at some point in the processor list.
         * Used to return where and why an processor list configuration request failed.
@@ -248,7 +249,7 @@ class Route : public IO
        int listen_via (boost::shared_ptr<IO>, const std::string& name);
        void drop_listen (boost::shared_ptr<IO>);
 
-       bool feeds (boost::shared_ptr<Route>);
+       bool feeds (boost::shared_ptr<IO>);
        std::set<boost::shared_ptr<Route> > fed_by;
 
        struct ToggleControllable : public PBD::Controllable {
@@ -314,7 +315,7 @@ class Route : public IO
        nframes_t      _initial_delay;
        nframes_t      _roll_delay;
        ProcessorList  _processors;
-       Glib::RWLock   _processor_lock;
+       mutable Glib::RWLock   _processor_lock;
        boost::shared_ptr<Delivery> _main_outs;
        boost::shared_ptr<Delivery> _control_outs; // XXX to be removed/generalized by listen points
        RouteGroup    *_edit_group;
index 52c2aa48ccda7f5ff361ce8a09392febb0a7d29b..ba3d70c18461a5a2afbad1587c0aa5d9fe3019ea 100644 (file)
@@ -1596,25 +1596,28 @@ IO::get_port_counts (const XMLNode& node, ChanCount& in, ChanCount& out,
 int
 IO::create_ports (const XMLNode& node)
 {
-       ChanCount in;
-       ChanCount out;
-       boost::shared_ptr<Bundle> ic;
-       boost::shared_ptr<Bundle> oc;
+       if (pending_state_node) {
 
-       no_panner_reset = true;
-
-       get_port_counts (*pending_state_node, in, out, ic, oc);
-
-       if (ensure_io (in, out, true, this)) {
-               error << string_compose(_("%1: cannot create I/O ports"), _name) << endmsg;
-               return -1;
+               ChanCount in;
+               ChanCount out;
+               boost::shared_ptr<Bundle> ic;
+               boost::shared_ptr<Bundle> oc;
+               
+               no_panner_reset = true;
+               
+               get_port_counts (*pending_state_node, in, out, ic, oc);
+               
+               if (ensure_io (in, out, true, this)) {
+                       error << string_compose(_("%1: cannot create I/O ports"), _name) << endmsg;
+                       return -1;
+               }
+               
+               /* XXX use ic and oc if relevant */
+               
+               no_panner_reset = false;
        }
 
-       /* XXX use ic and oc if relevant */
-
-       no_panner_reset = false;
        set_deferred_state ();
-
        return 0;
 }
 
@@ -2663,3 +2666,22 @@ IO::increment_output_offset (nframes_t n)
        _output_offset += n;
 }
 
+bool
+IO::connected_to (boost::shared_ptr<const IO> other) const
+{
+       uint32_t i, j;
+       
+       uint32_t no = n_outputs().n_total();
+       uint32_t ni = other->n_inputs ().n_total();
+       
+       for (i = 0; i < no; ++i) {
+               for (j = 0; j < ni; ++j) {
+                       if (output(i)->connected_to (other->input(j)->name())) {
+                               return true;
+                       }
+               }
+       }
+
+       return false;
+}
+
index 228a140d056d539f0ad40f42bc26a726aab7e298..7fb063eae012f558fe84090cdc47d53259b5a471 100644 (file)
@@ -2112,39 +2112,21 @@ Route::set_comment (string cmt, void *src)
 }
 
 bool
-Route::feeds (boost::shared_ptr<Route> other)
+Route::feeds (boost::shared_ptr<IO> other)
 {
-       uint32_t i, j;
-
-       IO& self = *this;
-       uint32_t no = self.n_outputs().n_total();
-       uint32_t ni = other->n_inputs ().n_total();
-
-       for (i = 0; i < no; ++i) {
-               for (j = 0; j < ni; ++j) {
-                       if (self.output(i)->connected_to (other->input(j)->name())) {
-                               return true;
-                       }
-               }
+       if (connected_to (other)) {
+               return true;
        }
 
        /* check IOProcessors which may also interconnect Routes */
 
        for (ProcessorList::iterator r = _processors.begin(); r != _processors.end(); r++) {
 
-               boost::shared_ptr<IOProcessor> proc = boost::dynamic_pointer_cast<IOProcessor>(*r);
-               
-               if (!proc) {
-                       continue;
-               }
-               
-               no = proc->io()->n_outputs().n_total();
-               
-               for (i = 0; i < no; ++i) {
-                       for (j = 0; j < ni; ++j) {
-                               if (proc->io()->output(i)->connected_to (other->input (j)->name())) {
-                                       return true;
-                               }
+               boost::shared_ptr<IOProcessor> proc;
+
+               if ((proc = boost::dynamic_pointer_cast<IOProcessor>(*r)) != 0) {
+                       if (proc->io()->connected_to (other)) {
+                               return true;
                        }
                }
        }
@@ -2700,3 +2682,21 @@ Route::set_name (const string& str)
 
        return ret;
 }
+
+boost::shared_ptr<IO>
+Route::send_io_for (boost::shared_ptr<const IO> target) const
+{
+       Glib::RWLock::ReaderLock lm (_processor_lock);
+
+       for (ProcessorList::const_iterator i = _processors.begin(); i != _processors.end(); ++i) {
+               boost::shared_ptr<Send> send;
+               
+               if ((send = boost::dynamic_pointer_cast<Send>(*i)) != 0) {
+                       if (send->io()->connected_to (target)) {
+                               return send->io();
+                       }
+               }
+       }
+       
+       return boost::shared_ptr<IO>();
+}