solo models work again (amazing how hard this was); remove crufty debug output; remov...
authorPaul Davis <paul@linuxaudiosystems.com>
Wed, 17 Jun 2009 15:50:29 +0000 (15:50 +0000)
committerPaul Davis <paul@linuxaudiosystems.com>
Wed, 17 Jun 2009 15:50:29 +0000 (15:50 +0000)
git-svn-id: svn://localhost/ardour2/branches/3.0@5207 d708f5d6-7413-0410-9779-e7cbd77b26cf

15 files changed:
gtk2_ardour/editor.cc
gtk2_ardour/editor.h
gtk2_ardour/rc_option_editor.cc
libs/ardour/ardour/delivery.h
libs/ardour/ardour/rc_configuration_vars.h
libs/ardour/ardour/route.h
libs/ardour/ardour/types.h
libs/ardour/delivery.cc
libs/ardour/enums.cc
libs/ardour/internal_send.cc
libs/ardour/io_processor.cc
libs/ardour/processor.cc
libs/ardour/route.cc
libs/ardour/send.cc
libs/ardour/session.cc

index 5a5ef1341e09f12960e843c00baa58f6a84bf9f8..87490a67b287d1f5b8a4b2291977f7d91b85b9f4 100644 (file)
@@ -407,7 +407,7 @@ Editor::Editor ()
        tempo_label.set_no_show_all();
        meter_label.set_name ("EditorTimeButton");
        meter_label.set_size_request (-1, (int)timebar_height);
-       meter_label.set_alignment (1.0, 0.5);
+       meter_label.set_alignment (0.0, 0.5);
        meter_label.set_padding (5,0);
        meter_label.hide();
        meter_label.set_no_show_all();
@@ -487,11 +487,9 @@ Editor::Editor ()
 
        ruler_label_event_box.add (ruler_label_vbox);   
        ruler_label_event_box.set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
-       ruler_label_event_box.set_name ("TimebarLabelBase");
        ruler_label_event_box.signal_button_release_event().connect (mem_fun(*this, &Editor::ruler_label_button_release));
 
        time_button_event_box.add (time_button_vbox);
-       time_button_event_box.set_name ("TimebarLabelBase");
        time_button_event_box.set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
        time_button_event_box.signal_button_release_event().connect (mem_fun(*this, &Editor::ruler_label_button_release));
 
@@ -510,32 +508,15 @@ Editor::Editor ()
        edit_packer.set_border_width (0);
        edit_packer.set_name ("EditorWindow");
 
-       /* summary */
-       edit_packer.attach (*_summary,               0, 2, 0, 1,    FILL|EXPAND, SHRINK, 0, 0);
+       edit_packer.attach (ruler_label_event_box,   1, 2, 0, 1,    FILL,        SHRINK, 0, 0);
+       edit_packer.attach (time_button_event_box,   1, 2, 1, 2,    FILL,        SHRINK, 0, 0);
 
-       /* labels for rulers (mins:secs, timecode, samples, bars:beats) */
-       edit_packer.attach (ruler_label_event_box,   0, 1, 1, 2,    FILL,        SHRINK, 0, 0);
+       edit_packer.attach (time_canvas_event_box,   2, 3, 0, 1,    FILL|EXPAND, FILL, 0, 0);
 
-       /* labels for time lines (meter, tempo, markers) */
-       edit_packer.attach (time_button_event_box,   0, 1, 2, 3,    FILL,        SHRINK, 0, 0);
+       edit_packer.attach (controls_layout,         1, 2, 2, 3,    FILL,        FILL|EXPAND, 0, 0);
+       edit_packer.attach (track_canvas_event_box,  2, 3, 1, 3,    FILL|EXPAND, FILL|EXPAND, 0, 0);
 
-       /* rulers */
-       edit_packer.attach (time_canvas_event_box,   1, 2, 1, 2,    FILL|EXPAND, FILL, 0, 0);
-
-       /* LHS controls for tracks */
-       edit_packer.attach (controls_layout,         0, 1, 3, 4,    FILL,        FILL|EXPAND, 0, 0);
-
-       /* main canvas (which has the time line canvas items at the top of it) */
-       edit_packer.attach (track_canvas_event_box,  1, 2, 2, 4,    FILL|EXPAND, FILL|EXPAND, 0, 0);
-
-       /* zoom controls */
-       edit_packer.attach (zoom_box,                0, 1, 4, 5,    FILL,         FILL, 0, 0);
-
-       /* h scroller */
-       edit_packer.attach (edit_hscrollbar,         1, 2, 4, 5,    FILL|EXPAND,  FILL, 0, 0);
-
-       /* v scroller */
-       edit_packer.attach (edit_vscrollbar,         3, 4, 3, 4,    FILL,        FILL|EXPAND, 0, 0);
+       edit_packer.attach (*_summary,               0, 3, 3, 4,    FILL|EXPAND, SHRINK, 0, 0);
 
        bottom_hbox.set_border_width (2);
        bottom_hbox.set_spacing (3);
@@ -3143,11 +3124,15 @@ Editor::setup_toolbar ()
        zoom_focus_selector.signal_changed().connect (mem_fun(*this, &Editor::zoom_focus_selection_done));
        ARDOUR_UI::instance()->tooltips().set_tip (zoom_focus_selector, _("Zoom focus"));
 
-       zoom_box.pack_start (zoom_focus_selector, true, true);
        zoom_box.pack_start (zoom_out_button, false, false);
        zoom_box.pack_start (zoom_in_button, false, false);
        zoom_box.pack_start (zoom_out_full_button, false, false);
 
+       HBox* zbc = manage (new HBox);
+       zbc->pack_start (zoom_focus_selector, false, false);
+       zoom_vbox.pack_start (*zbc, false, false);
+       zoom_vbox.pack_start (zoom_box, false, false);
+
        snap_box.set_spacing (1);
        snap_box.set_border_width (2);
 
index 37f66e71ab5e112f475ba416627a4dab99ba4981..6e30ef29549635dc6b093e09b3702b2d406cfca3 100644 (file)
@@ -1677,6 +1677,7 @@ public:
        Glib::RefPtr<Gtk::RadioAction> zoom_focus_action (Editing::ZoomFocus);
 
        Gtk::HBox           zoom_box;
+       Gtk::VBox           zoom_vbox;
 
        void                zoom_adjustment_changed();
 
index 33af7787440ee80b533f56a61a88c561f3c2715d..390ebe92de0a4faa7badd4d7538ffa60789d899b 100644 (file)
@@ -1089,7 +1089,7 @@ RCOptionEditor::RCOptionEditor ()
                mem_fun (*_rc_config, &RCConfiguration::set_solo_model)
                );
 
-       sm->add (InverseMute, _("in place"));
+       sm->add (SoloInPlace, _("in place"));
        sm->add (SoloBus, _("via bus"));
 
        add_option (_("Audio"), sm);
index 32ecc98215ea484c1d61a89b651505634ed2b8f6..7f1d964264e46a054e75be660018d8611b4248ec 100644 (file)
@@ -64,12 +64,8 @@ public:
 
        void no_outs_cuz_we_no_monitor(bool);
 
-       void mod_solo_level (int32_t);
-       uint32_t solo_level() const { return _solo_level; }
-       bool soloed () const { return (bool) _solo_level; }
-
-       bool solo_isolated() const { return _solo_isolated; }
-       void set_solo_isolated (bool);
+       void set_solo_level (int32_t sl) { _solo_level = sl; }
+       void set_solo_isolated (bool yn) { _solo_isolated = yn; }
 
        void cycle_start (nframes_t);
        void increment_output_offset (nframes_t);
index 3f063f4692c32dc911873c55d1b2c98264225f53..b156513a2d4ad225ab5aa348bb261c4eb3ef9997 100644 (file)
@@ -77,7 +77,7 @@ CONFIG_VARIABLE (bool, mute_affects_post_fader, "mute-affects-post-fader", true)
 CONFIG_VARIABLE (bool, mute_affects_control_outs, "mute-affects-control-outs", true)
 CONFIG_VARIABLE (bool, mute_affects_main_outs, "mute-affects-main-outs", true)
 CONFIG_VARIABLE (MonitorModel, monitoring_model, "monitoring-model", ExternalMonitoring)
-CONFIG_VARIABLE (SoloModel, solo_model, "solo-model", InverseMute)
+CONFIG_VARIABLE (SoloModel, solo_model, "solo-model", SoloInPlace)
 CONFIG_VARIABLE (bool, solo_latched, "solo-latched", true)
 CONFIG_VARIABLE (bool, latched_record_enable, "latched-record-enable", false)
 CONFIG_VARIABLE (bool, all_safe, "all-safe", false)
index 339f18ef3f47d34a32e757bc57296dea56718d8c..122927ff7d9ae4d32acdfa18515e0054d732bec9 100644 (file)
@@ -124,8 +124,11 @@ class Route : public SessionObject, public AutomatableControls
        void set_mute (bool yn, void* src);
        bool muted () const;
 
+       /* controls use set_solo() to modify this route's solo state
+        */
+
        void set_solo (bool yn, void *src);
-       bool soloed() const;
+       bool soloed () const { return (bool) _solo_level; }
 
        void set_solo_isolated (bool yn, void *src);
        bool solo_isolated() const;
@@ -315,6 +318,7 @@ class Route : public SessionObject, public AutomatableControls
 
        void catch_up_on_solo_mute_override ();
        void mod_solo_level (int32_t);
+       uint32_t solo_level () const { return _solo_level; }
        void set_block_size (nframes_t nframes);
        bool has_external_redirects() const;
        void curve_reallocate ();
@@ -340,13 +344,16 @@ class Route : public SessionObject, public AutomatableControls
        ProcessorList  _processors;
        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
+       boost::shared_ptr<Delivery> _control_outs;
        boost::shared_ptr<InternalReturn> _intreturn;
 
        Flag           _flags;
        int            _pending_declick;
        MeterPoint     _meter_point;
        uint32_t       _phase_invert;
+       uint32_t       _solo_level;
+       bool           _solo_isolated;
+
        bool           _denormal_protection;
        
        bool _recordable : 1;
index b5e53d494ea8478a9a236bc46b06aa678238e431..874a3f7ca0ef6f4a800571fbf24678eeaf4e9d5a 100644 (file)
@@ -331,7 +331,7 @@ namespace ARDOUR {
        };
 
        enum SoloModel {
-               InverseMute,
+               SoloInPlace,
                SoloBus
        };
 
index a4a76c37ae7fcb64b0958e34def12195a8be3560..1b1f62c4b207c17d43d980a96befc7063fe6c862 100644 (file)
@@ -53,6 +53,7 @@ Delivery::Delivery (Session& s, boost::shared_ptr<IO> io, boost::shared_ptr<Mute
        , _solo_level (0)
        , _solo_isolated (false)
        , _mute_master (mm)
+
 {
        _output_offset = 0;
        _current_gain = 1.0;
@@ -267,15 +268,9 @@ Delivery::set_state (const XMLNode& node)
        
        if ((prop = node.property ("role")) != 0) {
                _role = Role (string_2_enum (prop->value(), _role));
-       }
-
-       if ((prop = node.property ("solo_level")) != 0) {
-               _solo_level = 0; // needed for the reset to work
-               mod_solo_level (atoi (prop->value()));
-       }
-
-       if ((prop = node.property ("solo-isolated")) != 0) {
-               set_solo_isolated (prop->value() == "yes");
+               // std::cerr << this << ' ' << _name << " set role to " << enum_2_string (_role) << std::endl;
+       } else {
+               // std::cerr << this << ' ' << _name << " NO ROLE INFO\n";
        }
 
        XMLNode* pan_node = node.child (X_("Panner"));
@@ -423,11 +418,15 @@ Delivery::target_gain ()
                break;
        }
 
+
        if (_solo_level) {
                desired_gain = 1.0;
        } else {
-               if (_solo_isolated) {
 
+               if (_solo_isolated) {
+               
+                       /* ... but we are isolated from all that nonsense */
+                       
                        desired_gain = _mute_master->mute_gain_at (mp);
 
                } else if (_session.soloing()) {
@@ -442,26 +441,6 @@ Delivery::target_gain ()
        return desired_gain;
 }
 
-void
-Delivery::mod_solo_level (int32_t delta)
-{
-       if (delta < 0) {
-               if (_solo_level >= (uint32_t) delta) {
-                       _solo_level += delta;
-               } else {
-                       _solo_level = 0;
-               }
-       } else {
-               _solo_level += delta;
-       }
-}
-
-void
-Delivery::set_solo_isolated (bool yn)
-{
-       _solo_isolated = yn;
-}
-
 void
 Delivery::no_outs_cuz_we_no_monitor (bool yn)
 {
index 43fb4e4014e8540fe89e5a5ef7281cfc577c4a87..94878bc97e5465549443e5bd09d6c2debb99d5bf 100644 (file)
@@ -228,7 +228,7 @@ setup_enum_writer ()
        REGISTER_ENUM (AddHigher);
        REGISTER (_LayerModel);
 
-       REGISTER_ENUM (InverseMute);
+       REGISTER_ENUM (SoloInPlace);
        REGISTER_ENUM (SoloBus);
        REGISTER (_SoloModel);
 
index 398dbca08d130f9e2beb9cc26b8dd83685ee9548..db0390e813f8290a96fe891a505c7a1bf2c5acc1 100644 (file)
@@ -81,12 +81,38 @@ InternalSend::run (BufferSet& bufs, sframes_t start_frame, sframes_t end_frame,
        BufferSet& sendbufs = _session.get_mix_buffers (bufs.count());
        sendbufs.read_from (bufs, nframes);
        assert(sendbufs.count() == bufs.count());
-
+       
        /* gain control */
 
+       gain_t tgain = target_gain ();
+       
+       if (tgain != _current_gain) {
+               
+               /* target gain has changed */
+
+               Amp::apply_gain (sendbufs, nframes, _current_gain, tgain);
+               _current_gain = tgain;
+
+       } else if (tgain == 0.0) {
+
+               /* we were quiet last time, and we're still supposed to be quiet.
+               */
+
+               _meter->reset ();
+               Amp::apply_simple_gain (sendbufs, nframes, 0.0);
+               
+               return;
+
+       } else if (tgain != 1.0) {
+
+               /* target gain has not changed, but is not unity */
+               Amp::apply_simple_gain (sendbufs, nframes, tgain);
+       }
+       
        // Can't automate gain for sends or returns yet because we need different buffers
        // so that we don't overwrite the main automation data for the route amp
        // _amp->setup_gain_automation (start_frame, end_frame, nframes);
+
        _amp->run (sendbufs, start_frame, end_frame, nframes);
 
        /* consider metering */
@@ -137,6 +163,8 @@ InternalSend::set_state (const XMLNode& node)
 {
        const XMLProperty* prop;
 
+       Send::set_state (node);
+
        if ((prop = node.property ("target")) != 0) {
 
                _send_to_id = prop->value();
@@ -148,9 +176,7 @@ InternalSend::set_state (const XMLNode& node)
 
                if (!IO::connecting_legal) {
                        connect_c = IO::ConnectingLegal.connect (mem_fun (*this, &InternalSend::connect_when_legal));
-                       std::cerr << "connect later!\n";
                } else {
-                       std::cerr << "connect NOW!\n";
                        connect_when_legal ();
                }
        }
@@ -161,8 +187,6 @@ InternalSend::set_state (const XMLNode& node)
 int
 InternalSend::connect_when_legal ()
 {
-       std::cerr << "IOP/send connecting now that its legal\n";
-       
        connect_c.disconnect ();
 
        if (_send_to_id == "0") {
@@ -172,13 +196,12 @@ InternalSend::connect_when_legal ()
 
        if ((_send_to = _session.route_by_id (_send_to_id)) == 0) {
                error << X_("cannot find route to connect to") << endmsg;
-               std::cerr << "cannot find route with ID " << _send_to_id << std::endl;
-       } else {
-               std::cerr << "got target send as " << _send_to << std::endl;
-       }
+               return -1;
+       } 
        
        if ((target = _send_to->get_return_buffer ()) == 0) {
                error << X_("target for internal send has no return buffer") << endmsg;
+               return -1;
        }
 
        return 0;
index cfa2b4c689ef177c1100785407d5814d7dd544e7..87d679bbacd231f9e8a2daa9a3379fe8a4ea543e 100644 (file)
@@ -64,8 +64,6 @@ IOProcessor::IOProcessor (Session& s, bool with_input, bool with_output,
        if (with_output) {
                _output.reset (new IO(s, io_name.empty() ? proc_name : io_name, IO::Output, dtype));
        }
-
-       cerr << "fresh create IOP name = " << proc_name << " in = " << _input << " out = " << _output << endl;
 }
 
 /* create an IOProcessor that proxies to an existing IO object */
@@ -76,7 +74,6 @@ IOProcessor::IOProcessor (Session& s, boost::shared_ptr<IO> in, boost::shared_pt
        , _input (in)
        , _output (out)
 {
-       cerr << "XML create IOP name = " << proc_name << " in = " << in << " out = " << out << endl;
        if (in) {
                _own_input = false;
        } else {
@@ -165,8 +162,6 @@ IOProcessor::set_state (const XMLNode& node)
                _own_output = (prop->value() == "yes");
        }
 
-       cerr << _name << " own input = " << _own_input << " output = " << _own_output << endl;
-       
        /* don't attempt to set state for a proxied IO that we don't own */
 
        XMLNodeList nlist = node.children();
index ab5902efa5e907ad1f83e946cd714d1a99bb1620..ece9d6becc50b13c92b192d2f37350bddfc97ce8 100644 (file)
@@ -152,10 +152,7 @@ Processor::set_state (const XMLNode& node)
        // may not exist for legacy 3.0 sessions
        if ((prop = node.property ("id")) != 0) {
                _id = prop->value();
-               cerr << "---------------- ID for processor " << name() << " = " << _id << endl;
-       } else {
-               cerr << "---------------- NO ID for processor " << name() << endl;
-       }
+       } 
 
        XMLNodeList nlist = node.children();
        XMLNodeIterator niter;
index 0b6c3c48ca4dde37a92a4e02ba249e5050313b73..c3e586227074da558acbbeadd66309b632f08522 100644 (file)
@@ -37,6 +37,7 @@
 #include "ardour/buffer_set.h"
 #include "ardour/configuration.h"
 #include "ardour/cycle_timer.h"
+#include "ardour/delivery.h"
 #include "ardour/dB.h"
 #include "ardour/internal_send.h"
 #include "ardour/internal_return.h"
@@ -114,6 +115,8 @@ Route::Route (Session& sess, const XMLNode& node, DataType default_type)
 void
 Route::init ()
 {
+       _solo_level = 0;
+       _solo_isolated = false;
        _active = true;
        processor_max_streams.reset();
        _solo_safe = false;
@@ -475,7 +478,7 @@ Route::passthru_silence (sframes_t start_frame, sframes_t end_frame, nframes_t n
 void
 Route::set_solo (bool yn, void *src)
 {
-       if (_solo_safe) {
+       if (_solo_safe || _solo_isolated) {
                return;
        }
 
@@ -484,17 +487,52 @@ Route::set_solo (bool yn, void *src)
                return;
        }
 
-       if (_main_outs->soloed() != yn) {
-               _main_outs->mod_solo_level (yn ? 1 : -1);
+       if (soloed() != yn) {
+               mod_solo_level (yn ? 1 : -1);
                solo_changed (src); /* EMIT SIGNAL */
                _solo_control->Changed (); /* EMIT SIGNAL */
        }       
 }
 
-bool
-Route::soloed() const
+void
+Route::mod_solo_level (int32_t delta)
 {
-       return _main_outs->soloed ();
+       if (delta < 0) {
+               if (_solo_level >= (uint32_t) delta) {
+                       _solo_level += delta;
+               } else {
+                       _solo_level = 0;
+               }
+       } else {
+               _solo_level += delta;
+       }
+
+       /* tell "special" delivery units what the solo situation is
+        */
+
+       switch (Config->get_solo_model()) {
+       case SoloInPlace:
+               /* main outs are used for soloing */
+               _main_outs->set_solo_level (_solo_level);
+               _main_outs->set_solo_isolated (_solo_isolated);
+               if (_control_outs) {
+                       /* control outs just keep on playing */
+                       _control_outs->set_solo_level (0);
+                       _control_outs->set_solo_isolated (true);
+               }
+               break;
+
+       case SoloBus:
+               /* control outs are used for soloing */
+               if (_control_outs) {
+                       _control_outs->set_solo_level (_solo_level);
+                       _control_outs->set_solo_isolated (_solo_isolated);
+               }
+               /* main outs just keep on playing */
+               _main_outs->set_solo_level (0);
+               _main_outs->set_solo_isolated (true);
+               break;
+       }
 }
 
 void
@@ -505,14 +543,39 @@ Route::set_solo_isolated (bool yn, void *src)
                return;
        }
 
-       _main_outs->set_solo_isolated (yn);
-       solo_isolated_changed (src);
+       if (yn != _solo_isolated) {
+               _solo_isolated = yn;
+
+               /* tell "special" delivery units what the solo situation is
+                */
+               
+               switch (Config->get_solo_model()) {
+               case SoloInPlace:
+                       _main_outs->set_solo_level (_solo_level);
+                       _main_outs->set_solo_isolated (_solo_isolated);
+                       if (_control_outs) {
+                               _main_outs->set_solo_level (1);
+                               _main_outs->set_solo_isolated (false);
+                       }
+                       break;
+               case SoloBus:
+                       if (_control_outs) {
+                               _control_outs->set_solo_level (_solo_level);
+                               _control_outs->set_solo_isolated (_solo_isolated);
+                       }
+                       _main_outs->set_solo_level (1);
+                       _main_outs->set_solo_isolated (false);
+                       break;
+               }
+
+               solo_isolated_changed (src);
+       }
 }
 
 bool
 Route::solo_isolated () const 
 {
-       return _main_outs->solo_isolated();
+       return _solo_isolated;
 }
 
 void
@@ -535,6 +598,7 @@ Route::muted() const
        return _mute_master->muted ();
 }
 
+#if 0
 static void
 dump_processors(const string& name, const list<boost::shared_ptr<Processor> >& procs)
 {
@@ -545,6 +609,7 @@ dump_processors(const string& name, const list<boost::shared_ptr<Processor> >& p
        }
        cerr << "}" << endl;
 }
+#endif
 
 int
 Route::add_processor (boost::shared_ptr<Processor> processor, Placement placement, ProcessorStreams* err)
@@ -567,7 +632,6 @@ Route::add_processor (boost::shared_ptr<Processor> processor, Placement placemen
                        ProcessorList::iterator p;
                        p = _processors.end();
                        --p;
-                       cerr << "Let's check " << (*p)->name() << " vis ? " << (*p)->visible() << endl;
                        while (!(*p)->visible() && p != _processors.begin()) {
                                --p;
                        }
@@ -621,8 +685,6 @@ Route::add_processor (boost::shared_ptr<Processor> processor, ProcessorList::ite
                        loc = iter;
                }
 
-               cerr << "Adding " << processor->name() << " @ " << processor << endl;
-
                _processors.insert (loc, processor);
 
                // Set up processor list channels.  This will set processor->[input|output]_streams(),
@@ -705,9 +767,6 @@ Route::add_processor_from_xml (const XMLNode& node, ProcessorList::iterator iter
                try {
                        if ((prop = node.property ("type")) != 0) {
 
-
-                               cerr << _name << " : got processor type " << prop->value() << endl;
-
                                boost::shared_ptr<Processor> processor;
 
                                if (prop->value() == "ladspa" || prop->value() == "Ladspa" || 
@@ -757,7 +816,7 @@ Route::add_processor_from_xml (const XMLNode& node, ProcessorList::iterator iter
                                } else if (prop->value() == "intsend") {
 
                                        processor.reset (new InternalSend (_session, _mute_master, node));
-                               
+
                                } else if (prop->value() == "intreturn") {
                                        
                                        if (_intreturn) {
@@ -792,7 +851,6 @@ Route::add_processor_from_xml (const XMLNode& node, ProcessorList::iterator iter
                                        ProcessorList::iterator p;
                                        p = _processors.end();
                                        --p;
-                                       cerr << "Let's check " << (*p)->name() << " vis ? " << (*p)->visible() << endl;
                                        while (!(*p)->visible() && p != _processors.begin()) {
                                                --p;
                                        }
@@ -1213,10 +1271,7 @@ Route::configure_processors_unlocked (ProcessorStreams* err)
        list< pair<ChanCount,ChanCount> > configuration;
        uint32_t index = 0;
        
-       cerr << "Processor check with " << _processors.size() << endl;
-
        for (ProcessorList::iterator p = _processors.begin(); p != _processors.end(); ++p, ++index) {
-               cerr << "Checking out " << (*p)->name() << " type = " << endl;
                if ((*p)->can_support_io_configuration(in, out)) {
                        configuration.push_back(make_pair(in, out));
                        in = out;
@@ -1538,6 +1593,15 @@ Route::_set_state (const XMLNode& node, bool call_base)
 
        set_processor_state (processor_state);
        
+       if ((prop = node.property ("solo_level")) != 0) {
+               _solo_level = 0; // needed for mod_solo_level() to work
+               mod_solo_level (atoi (prop->value()));
+       }
+
+       if ((prop = node.property ("solo-isolated")) != 0) {
+               set_solo_isolated (prop->value() == "yes", this);
+       }
+
        if ((prop = node.property (X_("phase-invert"))) != 0) {
                set_phase_invert (prop->value()=="yes"?true:false);
        }
@@ -1667,8 +1731,6 @@ Route::set_processor_state (const XMLNode& node)
        XMLNodeConstIterator niter;
        ProcessorList::iterator i, o;
 
-       dump_processors ("set processor states", _processors);
-
        // Iterate through existing processors, remove those which are not in the state list
 
        for (i = _processors.begin(); i != _processors.end(); ) {
@@ -1841,11 +1903,21 @@ Route::listen_via (boost::shared_ptr<Route> route, const string& listen_name)
        {
                Glib::RWLock::ReaderLock rm (_processor_lock);
                
-               for (ProcessorList::const_iterator x = _processors.begin(); x != _processors.end(); ++x) {
-                       boost::shared_ptr<const InternalSend> d = boost::dynamic_pointer_cast<const InternalSend>(*x);
+               for (ProcessorList::iterator x = _processors.begin(); x != _processors.end(); ++x) {
+                       boost::shared_ptr<InternalSend> d = boost::dynamic_pointer_cast<InternalSend>(*x);
 
                        if (d && d->target_route() == route) {
+                               
+                               /* if the target is the control outs, then make sure
+                                  we take note of which i-send is doing that.
+                               */
+
+                               if (route == _session.control_out()) {
+                                       _control_outs = boost::dynamic_pointer_cast<Delivery>(d);
+                               }
+
                                /* already listening via the specified IO: do nothing */
+
                                return 0;
                        }
                }
@@ -1894,6 +1966,10 @@ Route::drop_listen (boost::shared_ptr<Route> route)
        }
 
        rl.release ();
+
+       if (route == _session.control_out()) {
+               _control_outs.reset ();
+       }
 }
 
 void
index 71685e1b88d02bc91de81d272359e6f35165817d..307f83fa62ec0a51317b03e6512422a72f2f2d00 100644 (file)
@@ -112,7 +112,7 @@ Send::get_state(void)
 XMLNode&
 Send::state(bool full)
 {
-       XMLNode& node = IOProcessor::state(full);
+       XMLNode& node = Delivery::state(full);
        char buf[32];
 
        node.add_property ("type", "send");
index db30fea0217b282df1405e37a5084c216396b635..e87f315a24ed06341483be1de929e4f5d4bcf879 100644 (file)
@@ -790,7 +790,6 @@ Session::hookup_io ()
 
        _state_of_the_state = StateOfTheState (_state_of_the_state & ~InitialConnecting);
 
-
        /* now handle the whole enchilada as if it was one
           graph reorder event.
        */
@@ -2247,15 +2246,20 @@ Session::route_solo_changed (void* src, boost::weak_ptr<Route> wpr)
 
                if ((*i)->feeds (route)) {
                        /* do it */
-                       
-                       (*i)->main_outs()->mod_solo_level (delta);
+                       (*i)->mod_solo_level (delta);
                }
        }
 
        /* make sure master is never muted by solo */
 
-       if (_master_out->main_outs()->solo_level() == 0) {
-               _master_out->main_outs()->mod_solo_level (1);
+       if (_master_out->solo_level() == 0) {
+               _master_out->mod_solo_level (1);
+       }
+
+       /* ditto for control outs make sure master is never muted by solo */
+
+       if (_control_out && _control_out->solo_level() == 0) {
+               _control_out->mod_solo_level (1);
        }
 
        solo_update_disabled = false;
@@ -2276,7 +2280,7 @@ Session::update_route_solo_state (boost::shared_ptr<RouteList> r)
        }
 
        for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
-               if (!(*i)->is_master() && !(*i)->is_hidden() && (*i)->soloed()) {
+               if (!(*i)->is_master() && !(*i)->is_control() && !(*i)->is_hidden() && (*i)->soloed()) {
                        something_soloed = true;
                        break;
                }
@@ -2302,7 +2306,7 @@ Session::catch_up_on_solo ()
 void
 Session::catch_up_on_solo_mute_override ()
 {
-       if (Config->get_solo_model() != InverseMute) {
+       if (Config->get_solo_model() != SoloInPlace) {
                return;
        }