major, substantive reworking of how we store GUI information (visibility, height...
authorPaul Davis <paul@linuxaudiosystems.com>
Sat, 11 Jun 2011 15:35:34 +0000 (15:35 +0000)
committerPaul Davis <paul@linuxaudiosystems.com>
Sat, 11 Jun 2011 15:35:34 +0000 (15:35 +0000)
git-svn-id: svn://localhost/ardour2/branches/3.0@9703 d708f5d6-7413-0410-9779-e7cbd77b26cf

30 files changed:
gtk2_ardour/audio_time_axis.cc
gtk2_ardour/audio_time_axis.h
gtk2_ardour/automation_time_axis.cc
gtk2_ardour/automation_time_axis.h
gtk2_ardour/editor_routes.cc
gtk2_ardour/midi_time_axis.cc
gtk2_ardour/midi_time_axis.h
gtk2_ardour/route_time_axis.cc
gtk2_ardour/route_time_axis.h
gtk2_ardour/route_ui.cc
gtk2_ardour/route_ui.h
gtk2_ardour/time_axis_view.cc
gtk2_ardour/time_axis_view.h
gtk2_ardour/ui_config.cc
libs/ardour/ardour/automatable.h
libs/ardour/automatable.cc
libs/ardour/event_type_map.cc
libs/ardour/pannable.cc
libs/ardour/processor.cc
libs/ardour/rc_configuration.cc
libs/ardour/region.cc
libs/ardour/route.cc
libs/ardour/session_state.cc
libs/evoral/evoral/Control.hpp
libs/evoral/src/ControlSet.cpp
libs/gtkmm2ext/cairocell.cc
libs/gtkmm2ext/gtkmm2ext/cairocell.h
libs/pbd/controllable.cc
libs/pbd/pbd/stateful.h
libs/pbd/stateful.cc

index 763c9a5575b28b2fef9e92d2c86f6b9c3fae5e35..4cf127042d70eb24891a751d1e167b453f5b450a 100644 (file)
@@ -190,6 +190,29 @@ AudioTimeAxisView::append_extra_display_menu_items ()
 void
 AudioTimeAxisView::create_automation_child (const Evoral::Parameter& param, bool show)
 {
+       if (param.type() == NullAutomation) {
+               cerr << "WARNING: Attempt to create NullAutomation child, ignoring" << endl;
+               return;
+       }
+
+       AutomationTracks::iterator existing = _automation_tracks.find (param);
+
+       if (existing != _automation_tracks.end()) {
+               
+               /* automation track created because we had existing data for
+                * the processor, but visibility may need to be controlled
+                * since it will have been set visible by default.
+                */
+
+               existing->second->set_visibility (show);
+               
+               if (!no_redraw) {
+                       _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
+               }
+
+               return;
+       }
+
        if (param.type() == GainAutomation) {
 
                create_gain_automation_child (param, show);
@@ -264,16 +287,7 @@ AudioTimeAxisView::update_gain_track_visibility ()
        bool const showit = gain_automation_item->get_active();
 
        if (showit != gain_track->marked_for_display()) {
-               if (showit) {
-                       gain_track->set_marked_for_display (true);
-                       gain_track->canvas_display()->show();
-                       gain_track->canvas_background()->show();
-                       gain_track->get_state_node()->add_property ("shown", X_("yes"));
-               } else {
-                       gain_track->set_marked_for_display (false);
-                       gain_track->hide ();
-                       gain_track->get_state_node()->add_property ("shown", X_("no"));
-               }
+               gain_track->set_visibility (showit);
 
                /* now trigger a redisplay */
 
@@ -291,17 +305,7 @@ AudioTimeAxisView::update_pan_track_visibility ()
        for (list<boost::shared_ptr<AutomationTimeAxisView> >::iterator i = pan_tracks.begin(); i != pan_tracks.end(); ++i) {
 
                if (showit != (*i)->marked_for_display()) {
-                       if (showit) {
-                               (*i)->set_marked_for_display (true);
-                               (*i)->canvas_display()->show();
-                               (*i)->canvas_background()->show();
-                               (*i)->get_state_node()->add_property ("shown", X_("yes"));
-                       } else {
-                               (*i)->set_marked_for_display (false);
-                               (*i)->hide ();
-                               (*i)->get_state_node()->add_property ("shown", X_("no"));
-                       }
-
+                       (*i)->set_visibility (showit);
                        /* now trigger a redisplay */
                        if (!no_redraw) {
                                _route->gui_changed (X_("visible_tracks"), (void *) 0); /* EMIT_SIGNAL */
@@ -472,24 +476,6 @@ AudioTimeAxisView::build_automation_action_menu (bool for_selection)
        }
 }
 
-void
-AudioTimeAxisView::add_processor_to_subplugin_menu (boost::weak_ptr<Processor> wp)
-{
-       /* we use this override to veto the Amp processor from the plugin menu,
-          as its automation lane can be accessed using the special "Fader" menu
-          option
-       */
-
-       boost::shared_ptr<Processor> p = wp.lock ();
-       if (!p) {
-               return;
-       }
-
-       if (boost::dynamic_pointer_cast<Amp> (p) == 0) {
-               RouteTimeAxisView::add_processor_to_subplugin_menu (wp);
-       }
-}
-
 void
 AudioTimeAxisView::enter_internal_edit_mode ()
 {
index a13ac32f2a5cfe35131b98d6c33aa58e975285e2..8f9bf92a70e93239ecc2af54f14b16b3ba47f76c 100644 (file)
@@ -78,7 +78,6 @@ class AudioTimeAxisView : public RouteTimeAxisView
 
        /* Overridden from parent to store display state */
        guint32 show_at (double y, int& nth, Gtk::VBox *parent);
-       void hide ();
 
         void enter_internal_edit_mode ();
         void leave_internal_edit_mode ();
@@ -101,6 +100,8 @@ class AudioTimeAxisView : public RouteTimeAxisView
        void show_existing_automation (bool apply_to_selection = false);
        void hide_all_automation (bool apply_to_selection = false);
 
+       void hide ();
+
        void gain_hidden ();
        void pan_hidden ();
 
@@ -110,8 +111,6 @@ class AudioTimeAxisView : public RouteTimeAxisView
        void update_gain_track_visibility ();
        void update_pan_track_visibility ();
 
-       void add_processor_to_subplugin_menu (boost::weak_ptr<ARDOUR::Processor>);
-
        Gtk::CheckMenuItem* gain_automation_item;
        std::list<boost::shared_ptr<AutomationTimeAxisView> > pan_tracks;
        Gtk::CheckMenuItem* pan_automation_item;
index bd882719be271f4a3a6613f2eb789572d3cb6e93..d12dfa97bd6d9eee80a5318d02abfac568cf9eff 100644 (file)
 
 #include <utility>
 #include <gtkmm2ext/barcontroller.h>
+
 #include "pbd/memento_command.h"
+#include "pbd/stacktrace.h"
+
 #include "ardour/automation_control.h"
 #include "ardour/event_type_map.h"
 #include "ardour/route.h"
@@ -147,51 +150,22 @@ AutomationTimeAxisView::AutomationTimeAxisView (
 
        hide_name_entry();
 
-       /* move the name label over a bit */
+       /* keep the parameter name short */
 
        string shortpname = _name;
-       bool shortened = false;
-
        int ignore_width;
        shortpname = fit_to_pixels (_name, 60, name_font, ignore_width, true);
 
-       if (shortpname != _name ){
-               shortened = true;
-       }
-
        name_label.set_text (shortpname);
        name_label.set_alignment (Gtk::ALIGN_CENTER, Gtk::ALIGN_CENTER);
         name_label.set_name (X_("TrackParameterName"));
 
-       if (nomparent.length()) {
-
-               /* limit the plug name string */
-
-               string pname = fit_to_pixels (nomparent, 60, name_font, ignore_width, true);
-               if (pname != nomparent) {
-                       shortened = true;
-               }
-
-               plugname = new Label (pname);
-               plugname->set_name (X_("TrackPlugName"));
-               plugname->show();
-               controls_table.remove (name_hbox);
-               controls_table.attach (*plugname, 1, 5, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
-               plugname_packed = true;
-               controls_table.attach (name_hbox, 1, 5, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
-       } else {
-               plugname = 0;
-               plugname_packed = false;
-       }
-
-       if (shortened) {
-               string tipname = nomparent;
-               if (!tipname.empty()) {
-                       tipname += ": ";
-               }
-               tipname += _name;
-               ARDOUR_UI::instance()->set_tip(controls_ebox, tipname);
+       string tipname = nomparent;
+       if (!tipname.empty()) {
+               tipname += ": ";
        }
+       tipname += _name;
+       ARDOUR_UI::instance()->set_tip(controls_ebox, tipname);
 
        /* add the buttons */
        controls_table.attach (hide_button, 0, 1, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
@@ -212,7 +186,7 @@ AutomationTimeAxisView::AutomationTimeAxisView (
        controls_base_unselected_name = X_("AutomationTrackControlsBase");
        controls_ebox.set_name (controls_base_unselected_name);
 
-       XMLNode* xml_node = get_parent_with_state()->get_automation_child_xml_node (_parameter);
+       XMLNode* xml_node = get_state_node ();
 
        if (xml_node) {
                set_state (*xml_node, Stateful::loading_state_version);
@@ -435,7 +409,7 @@ AutomationTimeAxisView::set_height (uint32_t h)
 
        TimeAxisView* state_parent = get_parent_with_state ();
        assert(state_parent);
-       XMLNode* xml_node = state_parent->get_automation_child_xml_node (_parameter);
+       XMLNode* xml_node = _control->extra_xml ("GUI");
 
        TimeAxisView::set_height (h);
        _base_rect->property_y2() = h;
@@ -460,19 +434,6 @@ AutomationTimeAxisView::set_height (uint32_t h)
                first_call_to_set_height = false;
 
                if (h >= preset_height (HeightNormal)) {
-                       controls_table.remove (name_hbox);
-
-                       if (plugname) {
-                               if (plugname_packed) {
-                                       controls_table.remove (*plugname);
-                                       plugname_packed = false;
-                               }
-                               controls_table.attach (*plugname, 1, 5, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
-                               plugname_packed = true;
-                               controls_table.attach (name_hbox, 1, 5, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
-                       } else {
-                               controls_table.attach (name_hbox, 1, 5, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
-                       }
                        hide_name_entry ();
                        show_name_label ();
                        name_hbox.show_all ();
@@ -481,14 +442,6 @@ AutomationTimeAxisView::set_height (uint32_t h)
                        hide_button.show_all();
 
                } else if (h >= preset_height (HeightSmall)) {
-                       controls_table.remove (name_hbox);
-                       if (plugname) {
-                               if (plugname_packed) {
-                                       controls_table.remove (*plugname);
-                                       plugname_packed = false;
-                               }
-                       }
-                       controls_table.attach (name_hbox, 1, 5, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
                        controls_table.hide_all ();
                        hide_name_entry ();
                        show_name_label ();
@@ -989,24 +942,18 @@ AutomationTimeAxisView::set_state (const XMLNode& node, int version)
                return set_state_2X (node, version);
        }
 
-       XMLProperty const * type = node.property ("automation-id");
-       if (type && type->value () == ARDOUR::EventTypeMap::instance().to_symbol (_parameter)) {
-               XMLProperty const * shown = node.property ("shown");
-               if (shown && shown->value () == "yes") {
-                       set_marked_for_display (true);
-                       _canvas_display->show (); /* FIXME: necessary? show_at? */
-               }
-       }
+       XMLProperty const * prop = node.property ("shown");
 
-       if (!_marked_for_display) {
-               hide();
+       if (prop) {
+               set_visibility (string_is_affirmative (prop->value()));
+       } else {
+               set_visibility (false);
        }
 
        return 0;
 }
 
 int
-
 AutomationTimeAxisView::set_state_2X (const XMLNode& node, int /*version*/)
 {
        if (node.name() == X_("gain") && _parameter == Evoral::Parameter (GainAutomation)) {
@@ -1027,50 +974,77 @@ AutomationTimeAxisView::set_state_2X (const XMLNode& node, int /*version*/)
 XMLNode*
 AutomationTimeAxisView::get_state_node ()
 {
-       TimeAxisView* state_parent = get_parent_with_state ();
-
-       if (state_parent) {
-               return state_parent->get_automation_child_xml_node (_parameter);
-       } else {
-               return 0;
-       }
+       return _control->extra_xml ("GUI", true);
 }
 
 void
-AutomationTimeAxisView::update_extra_xml_shown (bool editor_shown)
+AutomationTimeAxisView::update_extra_xml_shown (bool shown)
 {
        XMLNode* xml_node = get_state_node();
        if (xml_node) {
-               xml_node->add_property ("shown", editor_shown ? "yes" : "no");
+               xml_node->add_property ("shown", shown ? "yes" : "no");
+       }
+}
+
+void
+AutomationTimeAxisView::what_has_visible_automation (const boost::shared_ptr<Automatable>& automatable, set<Evoral::Parameter>& visible)
+{
+       /* this keeps "knowledge" of how we store visibility information
+          in XML private to this class.
+       */
+
+       assert (automatable);
+
+       Automatable::Controls& controls (automatable->controls());
+       
+       for (Automatable::Controls::iterator i = controls.begin(); i != controls.end(); ++i) {
+               
+               boost::shared_ptr<AutomationControl> ac = boost::dynamic_pointer_cast<AutomationControl> (i->second);
+
+               if (ac) {
+                       
+                       const XMLNode* gui_node = ac->extra_xml ("GUI");
+                       
+                       if (gui_node) {
+                               const XMLProperty* prop = gui_node->property ("shown");
+                               if (prop) {
+                                       if (string_is_affirmative (prop->value())) {
+                                               visible.insert (i->first);
+                                       }
+                               }
+                       }
+               }
        }
 }
 
 guint32
 AutomationTimeAxisView::show_at (double y, int& nth, Gtk::VBox *parent)
 {
-       update_extra_xml_shown (true);
+       if (!canvas_item_visible (_canvas_display)) {
+               update_extra_xml_shown (true);
+       }
 
        return TimeAxisView::show_at (y, nth, parent);
 }
 
 void
-AutomationTimeAxisView::hide ()
+AutomationTimeAxisView::show ()
 {
-       update_extra_xml_shown (false);
+       if (!canvas_item_visible (_canvas_display)) {
+               update_extra_xml_shown (true);
+       }
 
-       TimeAxisView::hide ();
+       return TimeAxisView::show ();
 }
 
-bool
-AutomationTimeAxisView::set_visibility (bool yn)
+void
+AutomationTimeAxisView::hide ()
 {
-       bool changed = TimeAxisView::set_visibility (yn);
-
-       if (changed) {
-               get_state_node()->add_property ("shown", yn ? X_("yes") : X_("no"));
+       if (canvas_item_visible (_canvas_display)) {
+               update_extra_xml_shown (false);
        }
 
-       return changed;
+       TimeAxisView::hide ();
 }
 
 /** @return true if this view has any automation data to display */
index 47d1d70d73ae2a80e93ef7d62a59b4685d3cc81c..3e3fbde35c54b9ffe246acdf8602c911483acb8d 100644 (file)
@@ -70,7 +70,6 @@ class AutomationTimeAxisView : public TimeAxisView {
 
        virtual void set_height (uint32_t);
        void set_samples_per_unit (double);
-       bool set_visibility (bool yn);
        std::string name() const { return _name; }
 
        void add_automation_event (ArdourCanvas::Item *item, GdkEvent *event, framepos_t, double);
@@ -99,7 +98,6 @@ class AutomationTimeAxisView : public TimeAxisView {
 
        int  set_state (const XMLNode&, int version);
        guint32 show_at (double y, int& nth, Gtk::VBox *parent);
-       void hide ();
 
        static const std::string state_node_name;
        XMLNode* get_state_node();
@@ -120,6 +118,8 @@ class AutomationTimeAxisView : public TimeAxisView {
                return _route;
        }
 
+       static void what_has_visible_automation (const boost::shared_ptr<ARDOUR::Automatable>& automatable, std::set<Evoral::Parameter>& visible);
+
   protected:
        /** parent route */
        boost::shared_ptr<ARDOUR::Route> _route;
@@ -156,6 +156,9 @@ class AutomationTimeAxisView : public TimeAxisView {
        Gtk::CheckMenuItem* mode_discrete_item;
        Gtk::CheckMenuItem* mode_line_item;
 
+       void hide ();
+       void show ();
+
        void add_line (boost::shared_ptr<AutomationLine>);
 
        void clear_clicked ();
index 0aae18d7939b20579e5abbd3e595798e95df3c65..9e27c7725e6c6b6deff0562a12c42514993d8a3e 100644 (file)
@@ -439,8 +439,7 @@ EditorRoutes::redisplay ()
                        position += tv->show_at (position, n, &_editor->edit_controls_vbox);
                        tv->clip_to_viewport ();
                } else {
-                       tv->set_marked_for_display (false);
-                       tv->hide ();
+                       tv->set_visibility (false);
                }
 
                n++;
index 9cda4185579e9899e45c2a629fba3857dad08f60..9fbddfd241984d204d754a79f30dff234e0c0c28 100644 (file)
@@ -846,41 +846,71 @@ MidiTimeAxisView::create_automation_child (const Evoral::Parameter& param, bool
        }
 
        AutomationTracks::iterator existing = _automation_tracks.find (param);
+
        if (existing != _automation_tracks.end()) {
+
+               /* automation track created because we had existing data for
+                * the processor, but visibility may need to be controlled
+                * since it will have been set visible by default.
+                */
+
+               existing->second->set_visibility (show);
+               
+               if (!no_redraw) {
+                       _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
+               }
+
                return;
        }
 
-       if (param.type() == GainAutomation) {
-               create_gain_automation_child (param, show);
-       } else {
+       boost::shared_ptr<AutomationTimeAxisView> track;
+
+       switch (param.type()) {
 
-               /* These controllers are region "automation", so we do not create
-                * an AutomationList/Line for the track */
-
-               boost::shared_ptr<AutomationTimeAxisView> track (
-                       new AutomationTimeAxisView (
-                               _session,
-                               _route,
-                               boost::shared_ptr<Automatable> (),
-                               boost::shared_ptr<AutomationControl> (),
-                               param,
-                               _editor,
-                               *this,
-                               true,
-                               parent_canvas,
-                               _route->describe_parameter(param)
-                               )
-                       );
+       case GainAutomation:
+               create_gain_automation_child (param, show);
+               break;
+
+       case PluginAutomation:
+               /* handled elsewhere */
+               break;
+
+       case MidiCCAutomation:
+       case MidiPgmChangeAutomation:
+       case MidiPitchBenderAutomation:
+       case MidiChannelPressureAutomation:
+       case MidiSystemExclusiveAutomation:
+               /* These controllers are region "automation" - they are owned
+                * by regions (and their MidiModels), not by the track. As a
+                * result we do not create an AutomationList/Line for the track
+                * ... except here we are doing something!! XXX 
+                */
+
+               track.reset (new AutomationTimeAxisView (
+                                    _session,
+                                    _route,
+                                    boost::shared_ptr<Automatable> (),
+                                    boost::shared_ptr<AutomationControl> (),
+                                    param,
+                                    _editor,
+                                    *this,
+                                    true,
+                                    parent_canvas,
+                                    _route->describe_parameter(param)
+                                    ));
 
                if (_view) {
                        _view->foreach_regionview (sigc::mem_fun (*track.get(), &TimeAxisView::add_ghost));
                }
 
                add_automation_child (param, track, show);
+               break;
+
+       default:
+               error << "MidiTimeAxisView: unknown automation child " << EventTypeMap::instance().to_symbol(param) << endmsg;
        }
 }
 
-
 void
 MidiTimeAxisView::route_active_changed ()
 {
index 485425e966cceefefcef196d1d82eb9258ac4d6e..6a557af568daa1a279efd2bc5dbd371aba261ffd 100644 (file)
@@ -67,7 +67,6 @@ class MidiTimeAxisView : public RouteTimeAxisView
        /* overridden from parent to store display state */
        guint32 show_at (double y, int& nth, Gtk::VBox *parent);
        void set_height (uint32_t);
-       void hide ();
 
         void enter_internal_edit_mode ();
         void leave_internal_edit_mode ();
@@ -110,6 +109,7 @@ class MidiTimeAxisView : public RouteTimeAxisView
   private:
        sigc::signal<void, std::string, std::string>  _midi_patch_settings_changed;
 
+       void hide ();
        void model_changed();
        void custom_device_mode_changed();
 
index 456c60d17be761a881ebc49b4afae230a42186e0..b4ad4da1f4c1dfdb27d5a9b821bbc6ccfc3e0d42 100644 (file)
@@ -359,19 +359,6 @@ RouteTimeAxisView::set_state (const XMLNode& node, int version)
                set_layer_display (LayerDisplay (string_2_enum (prop->value(), _view->layer_display ())));
        }
 
-       for (iter = kids.begin(); iter != kids.end(); ++iter) {
-               if ((*iter)->name() == AutomationTimeAxisView::state_node_name) {
-                       if ((prop = (*iter)->property ("automation-id")) != 0) {
-
-                               Evoral::Parameter param = ARDOUR::EventTypeMap::instance().new_parameter(prop->value());
-                               bool show = ((prop = (*iter)->property ("shown")) != 0) && string_is_affirmative (prop->value());
-                               create_automation_child(param, show);
-                       } else {
-                               warning << "Automation child has no ID" << endmsg;
-                       }
-               }
-       }
-
        return 0;
 }
 
@@ -1664,9 +1651,6 @@ RouteTimeAxisView::automation_track_hidden (Evoral::Parameter param)
 
        Gtk::CheckMenuItem* menu = automation_child_menu_item (param);
 
-       // if Evoral::Parameter::operator< doesn't obey strict weak ordering, we may crash here....
-       track->get_state_node()->add_property (X_("shown"), X_("no"));
-
        if (menu && !_hidden) {
                ignore_toggle = true;
                menu->set_active (false);
@@ -1690,9 +1674,7 @@ RouteTimeAxisView::show_all_automation (bool apply_to_selection)
                /* Show our automation */
 
                for (AutomationTracks::iterator i = _automation_tracks.begin(); i != _automation_tracks.end(); ++i) {
-                       i->second->set_marked_for_display (true);
-                       i->second->canvas_display()->show();
-                       i->second->get_state_node()->add_property ("shown", X_("yes"));
+                       i->second->set_visibility (true);
 
                        Gtk::CheckMenuItem* menu = automation_child_menu_item (i->first);
 
@@ -1734,9 +1716,7 @@ RouteTimeAxisView::show_existing_automation (bool apply_to_selection)
 
                for (AutomationTracks::iterator i = _automation_tracks.begin(); i != _automation_tracks.end(); ++i) {
                        if (i->second->has_automation()) {
-                               i->second->set_marked_for_display (true);
-                               i->second->canvas_display()->show();
-                               i->second->get_state_node()->add_property ("shown", X_("yes"));
+                               i->second->set_visibility (true);
 
                                Gtk::CheckMenuItem* menu = automation_child_menu_item (i->first);
                                if (menu) {
@@ -1745,7 +1725,6 @@ RouteTimeAxisView::show_existing_automation (bool apply_to_selection)
                        }
                }
 
-
                /* Show processor automation */
 
                for (list<ProcessorAutomationInfo*>::iterator i = processor_automation.begin(); i != processor_automation.end(); ++i) {
@@ -1773,9 +1752,7 @@ RouteTimeAxisView::hide_all_automation (bool apply_to_selection)
                /* Hide our automation */
 
                for (AutomationTracks::iterator i = _automation_tracks.begin(); i != _automation_tracks.end(); ++i) {
-                       i->second->set_marked_for_display (false);
-                       i->second->hide ();
-                       i->second->get_state_node()->add_property ("shown", X_("no"));
+                       i->second->set_visibility (false);
 
                        Gtk::CheckMenuItem* menu = automation_child_menu_item (i->first);
 
@@ -1854,25 +1831,6 @@ RouteTimeAxisView::find_processor_automation_node (boost::shared_ptr<Processor>
        return 0;
 }
 
-static string
-legalize_for_xml_node (string str)
-{
-       string::size_type pos;
-       string legal_chars = "abcdefghijklmnopqrtsuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_=:";
-       string legal;
-
-       legal = str;
-       pos = 0;
-
-       while ((pos = legal.find_first_not_of (legal_chars, pos)) != string::npos) {
-               legal.replace (pos, 1, "_");
-               pos += 1;
-       }
-
-       return legal;
-}
-
-
 void
 RouteTimeAxisView::add_processor_automation_curve (boost::shared_ptr<Processor> processor, Evoral::Parameter what)
 {
@@ -1893,37 +1851,21 @@ RouteTimeAxisView::add_processor_automation_curve (boost::shared_ptr<Processor>
                return;
        }
 
-       name = processor->describe_parameter (what);
-
-       /* create a string that is a legal XML node name that can be used to refer to this redirect+port combination */
-
-       /* FIXME: ew */
-
-       char state_name[256];
-       snprintf (state_name, sizeof (state_name), "%s-%" PRIu32, legalize_for_xml_node (processor->name()).c_str(), what.id());
-
        boost::shared_ptr<AutomationControl> control
-                       = boost::dynamic_pointer_cast<AutomationControl>(processor->control(what, true));
-
+               = boost::dynamic_pointer_cast<AutomationControl>(processor->control(what, true));
+       
        pan->view = boost::shared_ptr<AutomationTimeAxisView>(
                new AutomationTimeAxisView (_session, _route, processor, control, control->parameter (),
-                                           _editor, *this, false, parent_canvas, name, state_name));
+                                           _editor, *this, false, parent_canvas, 
+                                           processor->describe_parameter (what), processor->name()));
 
        pan->view->Hiding.connect (sigc::bind (sigc::mem_fun(*this, &RouteTimeAxisView::processor_automation_track_hidden), pan, processor));
 
-       if (!pan->view->marked_for_display()) {
-               pan->view->hide ();
-       } else {
-               pan->menu_item->set_active (true);
-       }
-
-       add_automation_child (control->parameter(), pan->view, true);
+       add_automation_child (control->parameter(), pan->view, pan->view->marked_for_display ());
 
        if (_view) {
                _view->foreach_regionview (sigc::mem_fun(*pan->view.get(), &TimeAxisView::add_ghost));
        }
-
-       processor->mark_automation_visible (what, true);
 }
 
 void
@@ -1933,8 +1875,6 @@ RouteTimeAxisView::processor_automation_track_hidden (RouteTimeAxisView::Process
                pan->menu_item->set_active (false);
        }
 
-       i->mark_automation_visible (pan->what, false);
-
        if (!no_redraw) {
                _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
        }
@@ -1944,21 +1884,24 @@ void
 RouteTimeAxisView::add_existing_processor_automation_curves (boost::weak_ptr<Processor> p)
 {
        boost::shared_ptr<Processor> processor (p.lock ());
+
        if (!processor) {
                return;
        }
 
-       set<Evoral::Parameter> s;
-       boost::shared_ptr<AutomationLine> al;
+       set<Evoral::Parameter> existing;
 
-       processor->what_has_visible_data (s);
+       processor->what_has_data (existing);
 
-       for (set<Evoral::Parameter>::iterator i = s.begin(); i != s.end(); ++i) {
+       for (set<Evoral::Parameter>::iterator i = existing.begin(); i != existing.end(); ++i) {
+               
+               Evoral::Parameter param (*i);
+               boost::shared_ptr<AutomationLine> al;
 
-               if ((al = find_processor_automation_curve (processor, *i)) != 0) {
+               if ((al = find_processor_automation_curve (processor, param)) != 0) {
                        al->queue_reset ();
                } else {
-                       add_processor_automation_curve (processor, (*i));
+                       add_processor_automation_curve (processor, param);
                }
        }
 }
@@ -1975,19 +1918,16 @@ RouteTimeAxisView::add_automation_child (Evoral::Parameter param, boost::shared_
 
        track->Hiding.connect (sigc::bind (sigc::mem_fun (*this, &RouteTimeAxisView::automation_track_hidden), param));
 
-       bool hideit = (!show);
+       _automation_tracks[param] = track;
 
        if ((node = track->get_state_node()) != 0) {
                if  ((prop = node->property ("shown")) != 0) {
-                       if (string_is_affirmative (prop->value())) {
-                               hideit = false;
-                       }
+                       /* existing state overrides "show" argument */
+                       show = string_is_affirmative (prop->value());
                }
        }
 
-       _automation_tracks[param] = track;
-
-       track->set_visibility (!hideit);
+       track->set_visibility (show);
 
        if (!no_redraw) {
                _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
@@ -2013,14 +1953,20 @@ RouteTimeAxisView::add_processor_to_subplugin_menu (boost::weak_ptr<Processor> p
                return;
        }
 
+       /* we use this override to veto the Amp processor from the plugin menu,
+          as its automation lane can be accessed using the special "Fader" menu
+          option
+       */
+
+       if (boost::dynamic_pointer_cast<Amp> (processor) != 0) {
+               return;
+       }
+
        using namespace Menu_Helpers;
        ProcessorAutomationInfo *rai;
        list<ProcessorAutomationInfo*>::iterator x;
 
        const std::set<Evoral::Parameter>& automatable = processor->what_can_be_automated ();
-       std::set<Evoral::Parameter> has_visible_automation;
-
-       processor->what_has_visible_data(has_visible_automation);
 
        if (automatable.empty()) {
                return;
@@ -2053,6 +1999,9 @@ RouteTimeAxisView::add_processor_to_subplugin_menu (boost::weak_ptr<Processor> p
 
        items.clear ();
 
+       std::set<Evoral::Parameter> has_visible_automation;
+       AutomationTimeAxisView::what_has_visible_automation (processor, has_visible_automation);
+
        for (std::set<Evoral::Parameter>::const_iterator i = automatable.begin(); i != automatable.end(); ++i) {
 
                ProcessorAutomationNode* pan;
@@ -2062,7 +2011,7 @@ RouteTimeAxisView::add_processor_to_subplugin_menu (boost::weak_ptr<Processor> p
 
                items.push_back (CheckMenuElem (name));
                mitem = dynamic_cast<CheckMenuItem*> (&items.back());
-
+               
                _subplugin_menu_map[*i] = mitem;
 
                if (has_visible_automation.find((*i)) != has_visible_automation.end()) {
@@ -2109,24 +2058,12 @@ RouteTimeAxisView::processor_menu_item_toggled (RouteTimeAxisView::ProcessorAuto
        }
 
        if (pan->view && showit != pan->view->marked_for_display()) {
-
-               if (showit) {
-                       pan->view->set_marked_for_display (true);
-                       pan->view->canvas_display()->show();
-                       pan->view->canvas_background()->show();
-               } else {
-                       rai->processor->mark_automation_visible (pan->what, true);
-                       pan->view->set_marked_for_display (false);
-                       pan->view->hide ();
-               }
-
+               pan->view->set_visibility (showit);
                redraw = true;
-
        }
 
        if (redraw && !no_redraw) {
                 _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
-
        }
 }
 
index 9f7fbff54d73308e0a04ff8436c959fc8f7eadd7..e087199c87af80ebfd36c86b732160668ea0eac0 100644 (file)
@@ -117,10 +117,6 @@ public:
 
        virtual void create_automation_child (const Evoral::Parameter& param, bool show) = 0;
 
-       /* make sure we get the right version of this */
-
-       XMLNode* get_automation_child_xml_node (Evoral::Parameter param) { return RouteUI::get_automation_child_xml_node (param); }
-
        typedef std::map<Evoral::Parameter, boost::shared_ptr<AutomationTimeAxisView> > AutomationTracks;
        AutomationTracks automation_tracks() { return _automation_tracks; }
 
index 7750f6c39972eb2413d084e024eec5e4593e7bd5..525013ecaa1dd8480279939a5fd315ad0211e124 100644 (file)
@@ -1306,18 +1306,10 @@ RouteUI::ensure_xml_node ()
                                        new_xml_node->add_property ((*i)->name().c_str (), (*i)->value().c_str ());
                                }
 
-                               XMLNodeList old_children = xml_node->children ();
-                               for (XMLNodeConstIterator i = old_children.begin(); i != old_children.end(); ++i) {
-                                       XMLNode* new_child = new XMLNode (AutomationTimeAxisView::state_node_name);
-                                       new_child->add_property (X_("automation-id"), (*i)->name());
-
-                                       XMLPropertyList old_props = (*i)->properties ();
-                                       for (XMLPropertyIterator j = old_props.begin(); j != old_props.end(); ++j) {
-                                               new_child->add_property ((*j)->name().c_str (), (*j)->value().c_str ());
-                                       }
-
-                                       new_xml_node->add_child_nocopy (*new_child);
-                               }
+                               /* we can't fix up the automation track nodes,
+                                * because the data is no longer stored
+                                * per-route, but per Controllable.
+                                */
 
                                _route->add_extra_xml (*new_xml_node);
                                xml_node = new_xml_node;
@@ -1326,34 +1318,6 @@ RouteUI::ensure_xml_node ()
        }
 }
 
-XMLNode*
-RouteUI::get_automation_child_xml_node (Evoral::Parameter param)
-{
-       ensure_xml_node ();
-
-       XMLNodeList kids = xml_node->children();
-       XMLNodeConstIterator iter;
-
-       const string sym = ARDOUR::EventTypeMap::instance().to_symbol(param);
-
-       for (iter = kids.begin(); iter != kids.end(); ++iter) {
-
-               if ((*iter)->name() == AutomationTimeAxisView::state_node_name) {
-                       XMLProperty* type = (*iter)->property("automation-id");
-                       if (type && type->value() == sym) {
-                               return *iter;
-                       }
-               }
-       }
-
-       // Didn't find it, make a new one
-       XMLNode* child = new XMLNode (AutomationTimeAxisView::state_node_name);
-       child->add_property("automation-id", sym);
-       xml_node->add_child_nocopy (*child);
-
-       return child;
-}
-
 int
 RouteUI::set_color_from_route ()
 {
index 9435b036e59beff142ae38b0cdfa485bb6baca41..0a72ed996693020baf770868e237ea7346639b15 100644 (file)
@@ -111,8 +111,6 @@ class RouteUI : public virtual AxisView
        XMLNode *xml_node;
        void ensure_xml_node ();
 
-       virtual XMLNode* get_automation_child_xml_node (Evoral::Parameter);
-
        bool mute_press(GdkEventButton*);
        bool mute_release(GdkEventButton*);
        bool solo_press(GdkEventButton*);
index 925107d9e833d15a230c5640948ead05b8a1fba2..fa216818f4f9e5aa1d01a1f11e287f27121097d1 100644 (file)
@@ -349,6 +349,13 @@ TimeAxisView::selection_click (GdkEventButton* ev)
        _editor.set_selected_track (*this, op, false);
 }
 
+void
+TimeAxisView::show ()
+{
+       canvas_display()->show();
+       canvas_background()->show();
+}
+
 void
 TimeAxisView::hide ()
 {
@@ -1287,7 +1294,7 @@ TimeAxisView::set_visibility (bool yn)
        if (yn != marked_for_display()) {
                if (yn) {
                        set_marked_for_display (true);
-                       canvas_display()->show();
+                       show ();
                } else {
                        set_marked_for_display (false);
                        hide ();
@@ -1298,6 +1305,7 @@ TimeAxisView::set_visibility (bool yn)
        return false;
 }
 
+
 uint32_t
 TimeAxisView::preset_height (Height h)
 {
index fde5bf0b3478c5b49f8ce4fde4a380288fcc5970..8e7d6f394a5fe8eb883d7fd2747dbee1ea42372d 100644 (file)
@@ -136,9 +136,6 @@ class TimeAxisView : public virtual AxisView, public PBD::Stateful
 
        bool touched (double top, double bot);
 
-       /** Hide this TrackView */
-       virtual void hide ();
-
        /** @return true if hidden, otherwise false */
        bool hidden () const { return _hidden; }
 
@@ -201,10 +198,6 @@ class TimeAxisView : public virtual AxisView, public PBD::Stateful
        void set_parent (TimeAxisView& p);
        bool has_state () const;
 
-       /* call this on the parent */
-
-       virtual XMLNode* get_automation_child_xml_node (Evoral::Parameter) { return 0; }
-
        virtual LayerDisplay layer_display () const { return Overlaid; }
        virtual StreamView* view () const { return 0; }
 
@@ -286,6 +279,9 @@ class TimeAxisView : public virtual AxisView, public PBD::Stateful
        void remove_child (boost::shared_ptr<TimeAxisView>);
        void add_child (boost::shared_ptr<TimeAxisView>);
 
+       virtual void hide ();
+       virtual void show ();
+
        /* selection display */
 
        ArdourCanvas::Group      *selection_group;
index 8e89884b22eaccbb925995c3bc7fe93c8c1a581d..10628334fdae605d9ba51e3852f80dfc970eb646 100644 (file)
@@ -229,6 +229,8 @@ UIConfiguration::set_state (const XMLNode& root, int /*version*/)
                return -1;
        }
 
+       Stateful::save_extra_xml (root);
+
        XMLNodeList nlist = root.children();
        XMLNodeConstIterator niter;
        XMLNode *node;
@@ -236,12 +238,10 @@ UIConfiguration::set_state (const XMLNode& root, int /*version*/)
        for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
 
                node = *niter;
+
                if (node->name() == "Canvas" ||  node->name() == "UI") {
                        set_variables (*node);
 
-               } else if (node->name() == "Extra") {
-                       _extra_xml = new XMLNode (*node);
-
                }
        }
        return 0;
index 69ef7d3ecb2e5b0b93dc3a0618cf60a754779ecc..dc86c0cdddc5298f9924d08eedc6b4b2e71a2465 100644 (file)
@@ -73,10 +73,8 @@ public:
 
        void protect_automation ();
 
-       void what_has_visible_data(std::set<Evoral::Parameter>&) const;
        const std::set<Evoral::Parameter>& what_can_be_automated() const { return _can_automate_list; }
-
-       void mark_automation_visible(Evoral::Parameter, bool);
+       void what_has_existing_automation (std::set<Evoral::Parameter>&) const;
 
        inline bool should_snapshot (framepos_t now) {
                return (_last_automation_snapshot > now
@@ -91,8 +89,6 @@ public:
                return _automation_interval;
        }
 
-       typedef Evoral::ControlSet::Controls Controls;
-
        static const std::string xml_node_name;
 
        int set_automation_xml_state (const XMLNode&, Evoral::Parameter default_param);
@@ -108,7 +104,6 @@ public:
        int load_automation (const std::string& path);
        int old_set_automation_state(const XMLNode&);
 
-       std::set<Evoral::Parameter> _visible_controls;
        std::set<Evoral::Parameter> _can_automate_list;
 
        framepos_t _last_automation_snapshot;
index 8c17a99beac891f69b4daca871157896a08eb861..6d8114939de2c3d8130aa5ae112575cdf4b9bd8c 100644 (file)
@@ -79,22 +79,6 @@ Automatable::old_set_automation_state (const XMLNode& node)
                warning << _("Automation node has no path property") << endmsg;
        }
 
-       if ((prop = node.property ("visible")) != 0) {
-               uint32_t what;
-               stringstream sstr;
-
-               _visible_controls.clear ();
-
-               sstr << prop->value();
-               while (1) {
-                       sstr >> what;
-                       if (sstr.fail()) {
-                               break;
-                       }
-                       mark_automation_visible (Evoral::Parameter(PluginAutomation, 0, what), true);
-               }
-       }
-
        _last_automation_snapshot = 0;
 
        return 0;
@@ -167,17 +151,6 @@ Automatable::add_control(boost::shared_ptr<Evoral::Control> ac)
        automation_list_automation_state_changed (param, al->automation_state ()); // sync everything up
 }
 
-void
-Automatable::what_has_visible_data(set<Evoral::Parameter>& s) const
-{
-       Glib::Mutex::Lock lm (control_lock());
-       set<Evoral::Parameter>::const_iterator li;
-
-       for (li = _visible_controls.begin(); li != _visible_controls.end(); ++li) {
-               s.insert  (*li);
-       }
-}
-
 string
 Automatable::describe_parameter (Evoral::Parameter param)
 {
@@ -205,20 +178,6 @@ Automatable::can_automate (Evoral::Parameter what)
        _can_automate_list.insert (what);
 }
 
-void
-Automatable::mark_automation_visible (Evoral::Parameter what, bool yn)
-{
-       if (yn) {
-               _visible_controls.insert (what);
-       } else {
-               set<Evoral::Parameter>::iterator i;
-
-               if ((i = _visible_controls.find (what)) != _visible_controls.end()) {
-                       _visible_controls.erase (i);
-               }
-       }
-}
-
 /** \a legacy_param is used for loading legacy sessions where an object (IO, Panner)
  * had a single automation parameter, with it's type implicit.  Derived objects should
  * pass that type and it will be used for the untyped AutomationList found.
@@ -230,8 +189,6 @@ Automatable::set_automation_xml_state (const XMLNode& node, Evoral::Parameter le
 
        /* Don't clear controls, since some may be special derived Controllable classes */
 
-       _visible_controls.clear ();
-
        XMLNodeList nlist = node.children();
        XMLNodeIterator niter;
 
@@ -292,8 +249,7 @@ Automatable::get_automation_xml_state ()
        }
 
        for (Controls::iterator li = controls().begin(); li != controls().end(); ++li) {
-               boost::shared_ptr<AutomationList> l
-                               = boost::dynamic_pointer_cast<AutomationList>(li->second->list());
+               boost::shared_ptr<AutomationList> l = boost::dynamic_pointer_cast<AutomationList>(li->second->list());
                if (!l->empty()) {
                        node->add_child_nocopy (l->get_state ());
                }
@@ -364,11 +320,9 @@ void
 Automatable::protect_automation ()
 {
        typedef set<Evoral::Parameter> ParameterSet;
-       ParameterSet automated_params;
-
-       what_has_data(automated_params);
+       const ParameterSet& automated_params = what_can_be_automated ();
 
-       for (ParameterSet::iterator i = automated_params.begin(); i != automated_params.end(); ++i) {
+       for (ParameterSet::const_iterator i = automated_params.begin(); i != automated_params.end(); ++i) {
 
                boost::shared_ptr<Evoral::Control> c = control(*i);
                boost::shared_ptr<AutomationList> l = boost::dynamic_pointer_cast<AutomationList>(c->list());
index 2a45ba672c898df1f53ff4ab45f4406ae0cf6d44..4b21d32e583a34c5dc5a2a3b007b1d84a3cee787 100644 (file)
@@ -244,7 +244,7 @@ EventTypeMap::new_parameter(const string& str) const
        } else {
                PBD::warning << "Unknown Parameter '" << str << "'" << endmsg;
        }
-
+       
        return new_parameter(p_type, p_channel, p_id);
 }
 
index 4de47fc62b29ceb6a599b03d051ce7e4f41a7b39..e020c19451c137abaf0d5870a598764465c05e02 100644 (file)
@@ -185,33 +185,12 @@ XMLNode&
 Pannable::state (bool full)
 {
        XMLNode* node = new XMLNode (X_("Pannable"));
-       XMLNode* control_node;
-       char buf[32];
-
-       control_node = new XMLNode (X_("azimuth"));
-       snprintf (buf, sizeof(buf), "%.12g", pan_azimuth_control->get_value());
-       control_node->add_property (X_("value"), buf);
-       node->add_child_nocopy (*control_node);
-
-       control_node = new XMLNode (X_("width"));
-       snprintf (buf, sizeof(buf), "%.12g", pan_width_control->get_value());
-       control_node->add_property (X_("value"), buf);
-       node->add_child_nocopy (*control_node);
-
-       control_node = new XMLNode (X_("elevation"));
-       snprintf (buf, sizeof(buf), "%.12g", pan_elevation_control->get_value());
-       control_node->add_property (X_("value"), buf);
-       node->add_child_nocopy (*control_node);
-
-       control_node = new XMLNode (X_("frontback"));
-       snprintf (buf, sizeof(buf), "%.12g", pan_frontback_control->get_value());
-       control_node->add_property (X_("value"), buf);
-       node->add_child_nocopy (*control_node);
-
-       control_node = new XMLNode (X_("lfe"));
-       snprintf (buf, sizeof(buf), "%.12g", pan_lfe_control->get_value());
-       control_node->add_property (X_("value"), buf);
-       node->add_child_nocopy (*control_node);
+
+       node->add_child_nocopy (pan_azimuth_control->get_state());
+       node->add_child_nocopy (pan_width_control->get_state());
+       node->add_child_nocopy (pan_elevation_control->get_state());
+       node->add_child_nocopy (pan_frontback_control->get_state());
+       node->add_child_nocopy (pan_lfe_control->get_state());
 
        node->add_child_nocopy (get_automation_xml_state ());
 
@@ -219,45 +198,27 @@ Pannable::state (bool full)
 }
 
 int
-Pannable::set_state (const XMLNode& root, int /*version - not used*/)
+Pannable::set_state (const XMLNode& root, int version)
 {
        if (root.name() != X_("Pannable")) {
                warning << string_compose (_("Pannable given XML data for %1 - ignored"), root.name()) << endmsg;
                return -1;
        }
 
-       XMLNodeList nlist;
+       const XMLNodeList& nlist (root.children());
        XMLNodeConstIterator niter;
-       const XMLProperty *prop;
-
-       nlist = root.children();
 
        for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
-               if ((*niter)->name() == X_("azimuth")) {
-                       prop = (*niter)->property (X_("value"));
-                       if (prop) {
-                               pan_azimuth_control->set_value (atof (prop->value()));
-                       }
-               } else if ((*niter)->name() == X_("width")) {
-                       prop = (*niter)->property (X_("value"));
-                       if (prop) {
-                               pan_width_control->set_value (atof (prop->value()));
-                       }
-               } else if ((*niter)->name() == X_("elevation")) {
-                       prop = (*niter)->property (X_("value"));
-                       if (prop) {
-                               pan_elevation_control->set_value (atof (prop->value()));
-                       }
-               } else if ((*niter)->name() == X_("azimuth")) {
-                       prop = (*niter)->property (X_("value"));
-                       if (prop) {
-                               pan_frontback_control->set_value (atof (prop->value()));
-                       }
-               } else if ((*niter)->name() == X_("lfe")) {
-                       prop = (*niter)->property (X_("value"));
-                       if (prop) {
-                               pan_lfe_control->set_value (atof (prop->value()));
-                       }
+               if ((*niter)->name() == pan_azimuth_control->name()) {
+                       pan_azimuth_control->set_state (**niter, version);
+               } else if ((*niter)->name() == pan_width_control->name()) {
+                       pan_width_control->set_state (**niter, version);
+               } else if ((*niter)->name() == pan_elevation_control->name()) {
+                       pan_elevation_control->set_state (**niter, version);
+               } else if ((*niter)->name() == pan_frontback_control->name()) {
+                       pan_frontback_control->set_state (**niter, version);
+               } else if ((*niter)->name() == pan_lfe_control->name()) {
+                       pan_lfe_control->set_state (**niter, version);
                } else if ((*niter)->name() == Automatable::xml_node_name) {
                        set_automation_xml_state (**niter, PanAzimuthAutomation);
                }
index bb004c313d3f97beab2ab1f174c9f2c3fa1c29c2..bf4a8ea6cbb69eb74374ecf8c2d01d00286673f0 100644 (file)
@@ -123,21 +123,7 @@ Processor::state (bool full_state)
 
        if (full_state) {
                XMLNode& automation = Automatable::get_automation_xml_state();
-               if (!automation.children().empty()
-                               || !automation.properties().empty()
-                               || !_visible_controls.empty()) {
-
-                       stringstream sstr;
-                       for (set<Evoral::Parameter>::iterator x = _visible_controls.begin();
-                                       x != _visible_controls.end(); ++x) {
-
-                               if (x != _visible_controls.begin()) {
-                                       sstr << ' ';
-                               }
-                               sstr << (*x).id();
-                       }
-
-                       automation.add_property ("visible", sstr.str());
+               if (!automation.children().empty() || !automation.properties().empty()) {
                        node->add_child_nocopy (automation);
                }
        }
@@ -206,6 +192,8 @@ Processor::set_state (const XMLNode& node, int version)
        XMLNodeList nlist = node.children();
        XMLNodeIterator niter;
 
+       Stateful::save_extra_xml (node);
+
        for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
 
                if ((*niter)->name() == X_("Automation")) {
@@ -218,25 +206,6 @@ Processor::set_state (const XMLNode& node, int version)
                                set_automation_xml_state (*(*niter), Evoral::Parameter(PluginAutomation));
                        }
 
-                       if ((prop = (*niter)->property ("visible")) != 0) {
-                               uint32_t what;
-                               stringstream sstr;
-
-                               _visible_controls.clear ();
-
-                               sstr << prop->value();
-                               while (1) {
-                                       sstr >> what;
-                                       if (sstr.fail()) {
-                                               break;
-                                       }
-                                       // FIXME: other automation types?
-                                       mark_automation_visible (Evoral::Parameter(PluginAutomation, 0, what), true);
-                               }
-                       }
-
-               } else if ((*niter)->name() == "Extra") {
-                       _extra_xml = new XMLNode (*(*niter));
                } else if ((*niter)->name() == "Redirect") {
                        if ( !(legacy_active = (*niter)->property("active"))) {
                                error << string_compose(_("No %1 property flag in element %2"), "active", (*niter)->name()) << endl;
index a17fd9f5a509fcb5f9f3717d0bcb596b5b59823a..1dc1ea636b835b9c0c09d2086f31e1d295e06138 100644 (file)
@@ -268,14 +268,14 @@ RCConfiguration::set_state (const XMLNode& root, int /*version*/)
 
        _midi_port_states.clear ();
 
+       Stateful::save_extra_xml (root);
+
        for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
 
                node = *niter;
 
                if (node->name() == "Config") {
                        set_variables (*node);
-               } else if (node->name() == "Extra") {
-                       _extra_xml = new XMLNode (*node);
                } else if (node->name() == ControlProtocolManager::state_node_name) {
                        _control_protocol_state = new XMLNode (*node);
                } else if (node->name() == MIDI::Port::state_node_name) {
index 17698d88a75f22fd1f223a581816ceea7933f973..30a0b6f24a821292a563b68095d61d75de819aff 100644 (file)
@@ -1251,15 +1251,7 @@ Region::_set_state (const XMLNode& node, int /*version*/, PropertyChange& what_c
        const XMLProperty* prop;
        const XMLNodeList& nlist = node.children();
 
-       for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) {
-
-               XMLNode *child = (*niter);
-
-               if (child->name () == "Extra") {
-                       delete _extra_xml;
-                       _extra_xml = new XMLNode (*child);
-               }
-       }
+       Stateful::save_extra_xml (node);
 
        what_changed = set_values (node);
 
index 0e8c93d75e0b364f74b3bc00a5afe40a5e624808..459ea674807b174f050f9197fceab32b5d3848cf 100644 (file)
@@ -1902,6 +1902,8 @@ Route::_set_state (const XMLNode& node, int version, bool /*call_base*/)
        nlist = node.children();
        XMLNode processor_state (X_("processor_state"));
 
+       Stateful::save_extra_xml (node);
+
        for (niter = nlist.begin(); niter != nlist.end(); ++niter){
 
                child = *niter;
@@ -2015,10 +2017,6 @@ Route::_set_state (const XMLNode& node, int version, bool /*call_base*/)
                        XMLNode *cmt = *(child->children().begin());
                        _comment = cmt->content();
 
-               } else if (child->name() == X_("Extra")) {
-
-                       _extra_xml = new XMLNode (*child);
-
                } else if (child->name() == Controllable::xml_node_name && (prop = child->property("name")) != 0) {
                        if (prop->value() == "solo") {
                                _solo_control->set_state (*child, version);
@@ -2255,6 +2253,8 @@ Route::_set_state_2X (const XMLNode& node, int version)
 
        set_processor_state_2X (redirect_nodes, version);
 
+       Stateful::save_extra_xml (node);
+
        for (niter = nlist.begin(); niter != nlist.end(); ++niter){
                child = *niter;
 
@@ -2265,10 +2265,6 @@ Route::_set_state_2X (const XMLNode& node, int version)
                        XMLNode *cmt = *(child->children().begin());
                        _comment = cmt->content();
 
-               } else if (child->name() == X_("extra")) {
-
-                       _extra_xml = new XMLNode (*child);
-
                } else if (child->name() == Controllable::xml_node_name && (prop = child->property("name")) != 0) {
                        if (prop->value() == X_("solo")) {
                                _solo_control->set_state (*child, version);
index 182b399877115b3a68eccab7edf7c784395d67fc..5d9967cc98dd5d01f79645296da707861e15b19d 100644 (file)
@@ -1250,9 +1250,7 @@ Session::set_state (const XMLNode& node, int version)
 
        IO::disable_connecting ();
 
-       if ((child = find_named_node (node, "Extra")) != 0) {
-               _extra_xml = new XMLNode (*child);
-       }
+       Stateful::save_extra_xml (node);
 
        if (((child = find_named_node (node, "Options")) != 0)) { /* old style */
                load_options (*child);
index bc525a0e721639789b92a50a49ccfdb39ac2c838..5c45823184a24d2a51cf6de932a325cd1a98d524 100644 (file)
@@ -40,7 +40,6 @@ public:
        virtual void   set_double(double val, bool to_list=false, double frame=0);
        virtual double get_double(bool from_list=false, double frame=0) const;
 
-
        /** Get the latest user-set value
         * (which may not equal get_value() when automation is playing back).
         *
@@ -51,7 +50,6 @@ public:
 
        void set_list(boost::shared_ptr<ControlList>);
 
-
        boost::shared_ptr<ControlList>       list()       { return _list; }
        boost::shared_ptr<const ControlList> list() const { return _list; }
 
index 1dd73c0115d966e19977f31a6256785fb3061b9c..6b793a08eae91c89644e3938ca768ecd91e733e6 100644 (file)
@@ -54,8 +54,11 @@ void
 ControlSet::what_has_data (set<Parameter>& s) const
 {
        Glib::Mutex::Lock lm (_control_lock);
+
        for (Controls::const_iterator li = _controls.begin(); li != _controls.end(); ++li) {
-               s.insert(li->first);
+               if (li->second->list() && !li->second->list()->empty()) {
+                       s.insert (li->first);
+               }
        }
 }
 
index f3da7e8cb352d777a97b1af0b1af50cfb0c4cc10..5a7f4309ed5ac0118ec3d6d691131de0df0c1243 100644 (file)
@@ -287,7 +287,14 @@ CairoEditableText::set_text (CairoTextCell* cell, const string& text)
 bool
 CairoEditableText::on_expose_event (GdkEventExpose* ev)
 {
-       Cairo::RefPtr<Cairo::Context> context = get_window()->create_cairo_context();
+       Glib::RefPtr<Gdk::Window> win = get_window ();
+
+       if (!win) {
+               std::cerr << "CET: no window to draw on\n";
+               return false;
+       }
+
+       Cairo::RefPtr<Cairo::Context> context = win->create_cairo_context();
 
        if (cells.empty()) {
                return true;
index 8dd6cd8a16c726c02eac29196722fc172172d755..2839d4266bdf8e327a670d2f60737b86b2919f04 100644 (file)
@@ -27,7 +27,7 @@
 #include <boost/shared_ptr.hpp>
 
 #include <cairomm/cairomm.h>
-#include <gtkmm.h>
+#include <gtkmm/misc.h>
 
 class CairoCell
 {
index 0112ff2b1ccabf76200fdcf30a94e24a196eeac9..959abe443d9c8e9d93b9ae3e207f3e7a9ec276a9 100644 (file)
@@ -113,6 +113,10 @@ Controllable::get_state ()
        snprintf (buf, sizeof (buf), "%2.12f", get_value());
         node->add_property (X_("value"), buf);
 
+       if (_extra_xml) {
+               node->add_child_copy (*_extra_xml);
+       }
+
        return *node;
 }
 
@@ -123,6 +127,8 @@ Controllable::set_state (const XMLNode& node, int /*version*/)
        LocaleGuard lg (X_("POSIX"));
        const XMLProperty* prop;
 
+       Stateful::save_extra_xml (node);
+
        if ((prop = node.property (X_("id"))) != 0) {
                _id = prop->value();
        } else {
index 80a5a2f75f5ef94a18ddb3dfb221bed2c8d2b4f8..dd1659db556e1d1b8d3df6dcbc938c47160df744 100644 (file)
@@ -61,7 +61,8 @@ class Stateful {
         */
 
        void add_extra_xml (XMLNode&);
-       XMLNode *extra_xml (const std::string& str);
+       XMLNode *extra_xml (const std::string& str, bool add_if_missing = false);
+       void save_extra_xml (const XMLNode&);
 
        const PBD::ID& id() const { return _id; }
         
index 4eb8434af298d27f69a6eda6ad23b9ccaf4443a8..47d1e66ef4fcf29f53da5599a73c431c688967ad 100644 (file)
@@ -68,22 +68,37 @@ Stateful::add_extra_xml (XMLNode& node)
 }
 
 XMLNode *
-Stateful::extra_xml (const string& str)
+Stateful::extra_xml (const string& str, bool add_if_missing)
 {
-       if (_extra_xml == 0) {
-               return 0;
+       XMLNode* node = 0;
+
+       if (_extra_xml) {
+               node = _extra_xml->child (str.c_str());
        }
 
-       const XMLNodeList& nlist = _extra_xml->children();
-       XMLNodeConstIterator i;
+       if (!node && add_if_missing) {
+               node = new XMLNode (str);
+               add_extra_xml (*node);
+       } 
 
-       for (i = nlist.begin(); i != nlist.end(); ++i) {
-               if ((*i)->name() == str) {
-                       return (*i);
-               }
-       }
+       return node;
+}
 
-       return 0;
+void
+Stateful::save_extra_xml (const XMLNode& node)
+{
+       /* Looks for the child node called "Extra" and makes _extra_xml 
+          point to a copy of it. Will delete any existing node pointed
+          to by _extra_xml if a new Extra node is found, but not
+          otherwise.
+       */
+       
+       const XMLNode* xtra = node.child ("Extra");
+
+       if (xtra) {
+               delete _extra_xml;
+               _extra_xml = new XMLNode (*xtra);
+       }
 }
 
 void