use XML state to store processors in mixer (strips) and fixup crash caused by missing...
authorPaul Davis <paul@linuxaudiosystems.com>
Wed, 1 Aug 2007 22:18:46 +0000 (22:18 +0000)
committerPaul Davis <paul@linuxaudiosystems.com>
Wed, 1 Aug 2007 22:18:46 +0000 (22:18 +0000)
git-svn-id: svn://localhost/ardour2/trunk@2215 d708f5d6-7413-0410-9779-e7cbd77b26cf

16 files changed:
gtk2_ardour/ardour_ui.cc
gtk2_ardour/ardour_ui.h
gtk2_ardour/ardour_ui2.cc
gtk2_ardour/ardour_ui_dependents.cc
gtk2_ardour/ardour_ui_ed.cc
gtk2_ardour/ladspa_pluginui.cc
gtk2_ardour/processor_box.cc
gtk2_ardour/processor_box.h
gtk2_ardour/processor_selection.h
gtk2_ardour/route_processor_selection.cc
gtk2_ardour/route_processor_selection.h
gtk2_ardour/selection.cc
gtk2_ardour/selection.h
libs/ardour/ardour/plugin.h
libs/ardour/automatable.cc
libs/ardour/plugin_insert.cc

index b58990b0d6e83da19fb432adea30f5243f0362ef..cd0f412692ea4dfac656a0c99e0b4e19b8ede41d 100644 (file)
@@ -197,6 +197,11 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[])
 
        keybindings_path = key_bindings_file.to_string();
 
+       /* store all bindings changes in per-user file, no matter where they were loaded from */
+       user_keybindings_path = user_config_directory().to_string ();
+       user_keybindings_path += '/';
+       user_keybindings_path += "ardour.bindings";
+
        can_save_keybindings = false;
 
        last_configure_time.tv_sec = 0;
@@ -2724,7 +2729,7 @@ void
 ARDOUR_UI::save_keybindings ()
 {
        if (can_save_keybindings) {
-               AccelMap::save (keybindings_path);
+               AccelMap::save (user_keybindings_path);
        } 
 }
 
index 42f0ae21439402d1c57c61c4d38a26e65eeb9a07..39bd8db4a6ad9bc9ad697b094bc30e1344e5980f 100644 (file)
@@ -577,6 +577,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI
        void we_have_dependents ();
        
        std::string keybindings_path;
+       std::string user_keybindings_path;
 
        void setup_keybindings ();
        void setup_session_options ();
index be7fbb5f09dae1f3fcb15a9873709f871b552bb8..5a4c676cadeef4044a1018dc15fff8a48bd9de9e 100644 (file)
@@ -835,7 +835,11 @@ void
 ARDOUR_UI::sync_option_changed ()
 {
        if (session) {
-               session->request_slave_source (string_to_slave_source (sync_option_combo.get_active_text()));
+               ustring txt = sync_option_combo.get_active_text ();
+               if (txt.length()) {
+                       cerr << "Changing to slave source based on " << txt << endl;
+                       session->request_slave_source (string_to_slave_source (txt));
+               }
        }
 }
 
index 89abebf9cb6848b021fe7ec77583f27ccf657d94..4e9f84d0721728454cd1706b821356a45c633237 100644 (file)
@@ -90,6 +90,8 @@ ARDOUR_UI::setup_keybindings ()
        GtkAccelMap* accelmap = gtk_accel_map_get();
        g_signal_connect (accelmap, "changed", (GCallback) accel_map_changed, this);
 
+       
+
 }
 
 void
index 6aedb3d8dff9ef1a9b9c4f70a4629cf6848151f9..41665cffbbd71799e3ec3c438c5263d90895a26e 100644 (file)
@@ -80,7 +80,6 @@ ARDOUR_UI::install_actions ()
        /* menus + submenus that need action items */
 
        ActionManager::register_action (main_actions, X_("Session"), _("Session"));
-       ActionManager::register_action (main_actions, X_("Export"), _("Export"));
        ActionManager::register_action (main_actions, X_("Cleanup"), _("Cleanup"));
        ActionManager::register_action (main_actions, X_("Sync"), _("Sync"));
        ActionManager::register_action (main_actions, X_("Options"), _("Options"));
index 7abee4fe23292087c5f82848f44ca2c26fe7a613..ad1f8fbc7e2035a00512d9ddf85a8c25dffee818 100644 (file)
@@ -423,7 +423,11 @@ LadspaPluginUI::build_control_ui (guint32 port_index, boost::shared_ptr<Automati
 
                        return control_ui;
                }
+
+               /* create the controller */
        
+               control_ui->controller = AutomationController::create(insert, mcontrol->list(), mcontrol);
+
                /* XXX this code is not right yet, because it doesn't handle
                   the absence of bounds in any sensible fashion.
                */
@@ -456,7 +460,6 @@ LadspaPluginUI::build_control_ui (guint32 port_index, boost::shared_ptr<Automati
                } else {
                        //sigc::slot<void,char*,uint32_t> pslot = sigc::bind (mem_fun(*this, &LadspaPluginUI::print_parameter), (uint32_t) port_index);
 
-                       control_ui->controller = AutomationController::create(insert, mcontrol->list(), mcontrol);
                        control_ui->controller->set_size_request (200, req.height);
                        control_ui->controller->set_name (X_("PluginSlider"));
                        control_ui->controller->set_style (BarController::LeftToRight);
index 068a3896f3d881fb779ba3474b819286cc80cd50..fc264c661fc736e0ffaf10636f9189c8cd2f69d8 100644 (file)
@@ -739,39 +739,38 @@ void
 ProcessorBox::cut_processors ()
 {
        vector<boost::shared_ptr<Processor> > to_be_removed;
-       
+       XMLNode* node = new XMLNode (X_("cut"));
+
        get_selected_processors (to_be_removed);
 
        if (to_be_removed.empty()) {
                return;
        }
 
-       /* this essentially transfers ownership of the processor
-          of the processor from the route to the mixer
-          selection.
-       */
-       
-       _rr_selection.set (to_be_removed);
-
        no_processor_redisplay = true;
        for (vector<boost::shared_ptr<Processor> >::iterator i = to_be_removed.begin(); i != to_be_removed.end(); ++i) {
-               // Do not cut processors or sends
+               // Do not cut inserts or sends
+
                if (boost::dynamic_pointer_cast<PluginInsert>((*i)) != 0) {
                        void* gui = (*i)->get_gui ();
                
                        if (gui) {
                                static_cast<Gtk::Widget*>(gui)->hide ();
                        }
-               
-                       if (_route->remove_processor (*i)) {
-                               /* removal failed */
-                               _rr_selection.remove (*i);
-                       }
-               } else {
-                       _rr_selection.remove (*i);
-               }
+                       
+                       XMLNode& child ((*i)->get_state());
 
+                       if (_route->remove_processor (*i) == 0) {
+                               /* success */
+                               node->add_child_nocopy (child);
+                       } else {
+                               delete &child;
+                       }
+               } 
        }
+
+       _rr_selection.set (node);
+
        no_processor_redisplay = false;
        redisplay_processors ();
 }
@@ -780,7 +779,7 @@ void
 ProcessorBox::copy_processors ()
 {
        vector<boost::shared_ptr<Processor> > to_be_copied;
-       vector<boost::shared_ptr<Processor> > copies;
+       XMLNode* node = new XMLNode (X_("copy"));
 
        get_selected_processors (to_be_copied);
 
@@ -791,12 +790,11 @@ ProcessorBox::copy_processors ()
        for (vector<boost::shared_ptr<Processor> >::iterator i = to_be_copied.begin(); i != to_be_copied.end(); ++i) {
                // Do not copy processors or sends
                if (boost::dynamic_pointer_cast<PluginInsert>((*i)) != 0) {
-                       copies.push_back (Processor::clone (*i));
+                       node->add_child_nocopy ((*i)->get_state());
                }
        }
 
-       _rr_selection.set (copies);
-
+       _rr_selection.set (node);
 }
 
 void
@@ -869,57 +867,64 @@ ProcessorBox::rename_processor (boost::shared_ptr<Processor> processor)
 }
 
 void
-ProcessorBox::cut_processor (boost::shared_ptr<Processor> processor)
+ProcessorBox::paste_processors ()
 {
-       /* this essentially transfers ownership of the processor
-          of the processor from the route to the mixer
-          selection.
-       */
+       if (_rr_selection.processors.empty()) {
+               return;
+       }
 
-       _rr_selection.add (processor);
-       
-       void* gui = processor->get_gui ();
+       cerr << "paste from node called " << _rr_selection.processors.get_node().name() << endl;
 
-       if (gui) {
-               static_cast<Gtk::Widget*>(gui)->hide ();
-       }
-       
-       no_processor_redisplay = true;
-       if (_route->remove_processor (processor)) {
-               _rr_selection.remove (processor);
-       }
-       no_processor_redisplay = false;
-       redisplay_processors ();
+       paste_processor_state (_rr_selection.processors.get_node());
 }
 
 void
-ProcessorBox::copy_processor (boost::shared_ptr<Processor> processor)
+ProcessorBox::paste_processor_list (list<boost::shared_ptr<Processor> >& processors)
 {
-       boost::shared_ptr<Processor> copy = Processor::clone (processor);
-       _rr_selection.add (copy);
-}
+       list<boost::shared_ptr<Processor> > copies;
+       
+       for (list<boost::shared_ptr<Processor> >::iterator i = processors.begin(); i != processors.end(); ++i) {
+               
+               boost::shared_ptr<Processor> copy = Processor::clone (*i);
+               
+               copy->set_placement (_placement);
+               copies.push_back (copy);
+       }
 
-void
-ProcessorBox::paste_processors ()
-{
-       if (_rr_selection.processors.empty()) {
-               return;
-       }
+       if (_route->add_processors (copies)) {
 
-       paste_processor_list (_rr_selection.processors);
+               string msg = _(
+                       "Copying the set of processors on the clipboard failed,\n\
+probably because the I/O configuration of the plugins\n\
+could not match the configuration of this track.");
+               MessageDialog am (msg);
+               am.run ();
+       }
 }
 
 void
-ProcessorBox::paste_processor_list (list<boost::shared_ptr<Processor> >& processors)
+ProcessorBox::paste_processor_state (const XMLNode& node)
 {
+       XMLNodeList nlist;
+       XMLNodeConstIterator niter;
        list<boost::shared_ptr<Processor> > copies;
 
-       for (list<boost::shared_ptr<Processor> >::iterator i = processors.begin(); i != processors.end(); ++i) {
+       nlist = node.children();
 
-               boost::shared_ptr<Processor> copy = Processor::clone (*i);
+       cerr << "Pasting processor selection containing " << nlist.size() << endl;
 
-               copy->set_placement (_placement);
-               copies.push_back (copy);
+       if (nlist.empty()) {
+               return;
+       }
+
+       for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
+               cerr << "try using " << (*niter)->name() << endl;
+               try {
+                       copies.push_back (boost::shared_ptr<Processor> (new PluginInsert (_session, **niter)));
+               }
+               catch (...) {
+                       cerr << "plugin insert constructor failed\n";
+               }
        }
 
        if (_route->add_processors (copies)) {
index e4d0fca365d4496439c8877a5fb0e7b62b6079bc..1ed0bcb39efd190f942a68235f22ee5138981530 100644 (file)
@@ -186,11 +186,10 @@ class ProcessorBox : public Gtk::HBox
 
        static Glib::RefPtr<Gtk::Action> paste_action;
        void paste_processor_list (std::list<boost::shared_ptr<ARDOUR::Processor> >& processors);
+       void paste_processor_state (const XMLNode&);
        
        void activate_processor (boost::shared_ptr<ARDOUR::Processor>);
        void deactivate_processor (boost::shared_ptr<ARDOUR::Processor>);
-       void cut_processor (boost::shared_ptr<ARDOUR::Processor>);
-       void copy_processor (boost::shared_ptr<ARDOUR::Processor>);
        void edit_processor (boost::shared_ptr<ARDOUR::Processor>);
        void hide_processor_editor (boost::shared_ptr<ARDOUR::Processor>);
        void rename_processor (boost::shared_ptr<ARDOUR::Processor>);
index e9abcea2dc078f4084d3298a0124f88aad5f07ee..59354c05acdda075bf1c57da9e80d4a15e84d7f9 100644 (file)
 #ifndef __ardour_gtk_processor_selection_h__
 #define __ardour_gtk_processor_selection_h__
 
-#include <list>
-#include <boost/shared_ptr.hpp>
-
-namespace ARDOUR {
-       class Processor;
-}
-
-struct ProcessorSelection : list<boost::shared_ptr<ARDOUR::Processor> > {};
+#include <pbd/xml++.h>
+
+class ProcessorSelection {
+  public:
+    ProcessorSelection() : node (0) {}
+    ~ProcessorSelection() { if (node) { delete node; } }
+
+    void set (XMLNode* n) {
+           if (node) {
+                   delete node;
+           }
+           node = n;
+    }
+
+    void add (XMLNode* newchild) {
+           if (!node) {
+                   node = new XMLNode ("add");
+           }
+           node->add_child_nocopy (*newchild);
+    }
+
+    void clear () { 
+           if (node) { 
+                   delete node;
+                   node = 0;
+           }
+    }
+
+    bool empty () const { return node == 0 || node->children().empty(); }
+           
+    const XMLNode& get_node() const { return *node; }
+
+  private:
+    XMLNode* node;
+};
 
 #endif /* __ardour_gtk_processor_selection_h__ */
index 33dd1bfe7b426bca03a9a2a3a90e53257967aeb5..552de1b412028c75d3ad8eeb00f618c811f1a0f3 100644 (file)
@@ -46,8 +46,8 @@ RouteRedirectSelection::operator= (const RouteRedirectSelection& other)
 bool
 operator== (const RouteRedirectSelection& a, const RouteRedirectSelection& b)
 {
-       return a.processors == b.processors &&
-               a.routes == b.routes;
+       // XXX MUST TEST PROCESSORS SOMEHOW
+       return a.routes == b.routes;
 }
 
 void
@@ -72,63 +72,19 @@ RouteRedirectSelection::clear_routes ()
 }
 
 void
-RouteRedirectSelection::add (boost::shared_ptr<Processor> r)
+RouteRedirectSelection::add (XMLNode* node)
 {
-       if (find (processors.begin(), processors.end(), r) == processors.end()) {
-               processors.push_back (r);
-
-               // XXX SHAREDPTR FIXME
-               // void (RouteRedirectSelection::*pmf)(Redirect*) = &RouteRedirectSelection::remove;
-               // r->GoingAway.connect (mem_fun(*this, pmf));
-
-               ProcessorsChanged();
-       }
-}
-
-void
-RouteRedirectSelection::add (const vector<boost::shared_ptr<Processor> >& rlist)
-{
-       bool changed = false;
-
-       for (vector<boost::shared_ptr<Processor> >::const_iterator i = rlist.begin(); i != rlist.end(); ++i) {
-               if (find (processors.begin(), processors.end(), *i) == processors.end()) {
-                       processors.push_back (*i);
-                       
-                       // XXX SHAREDPTR FIXME
-
-                       //void (RouteRedirectSelection::*pmf)(Redirect*) = &RouteRedirectSelection::remove;
-                       // (*i)->GoingAway.connect (mem_fun(*this, pmf));
-                       changed = true;
-               }
-       }
-
-       if (changed) {
-               ProcessorsChanged();
-       }
+       // XXX check for duplicate
+       processors.add (node);
+       ProcessorsChanged();
 }
 
 void
-RouteRedirectSelection::remove (boost::shared_ptr<Processor> r)
-{
-       list<boost::shared_ptr<Processor> >::iterator i;
-       if ((i = find (processors.begin(), processors.end(), r)) != processors.end()) {
-               processors.erase (i);
-               ProcessorsChanged ();
-       }
-}
-
-void
-RouteRedirectSelection::set (boost::shared_ptr<Processor> r)
+RouteRedirectSelection::set (XMLNode* node)
 {
        clear_processors ();
-       add (r);
-}
-
-void
-RouteRedirectSelection::set (const vector<boost::shared_ptr<Processor> >& rlist)
-{
-       clear_processors ();
-       add (rlist);
+       processors.set (node);
+       ProcessorsChanged ();
 }
 
 void
index 78f6ddca4886d09a5fd5cdfd28214021e786c945..bb0e6701e1816b1cfc5b6e1878b463e907bfce53 100644 (file)
@@ -42,11 +42,8 @@ class RouteRedirectSelection : public sigc::trackable
        void clear ();
        bool empty();
 
-       void set (boost::shared_ptr<ARDOUR::Processor>);
-       void set (const std::vector<boost::shared_ptr<ARDOUR::Processor> >&);
-       void add (boost::shared_ptr<ARDOUR::Processor>);
-       void add (const std::vector<boost::shared_ptr<ARDOUR::Processor> >&);
-       void remove (boost::shared_ptr<ARDOUR::Processor>);
+       void set (XMLNode* node);
+       void add (XMLNode* node);
 
        void set (boost::shared_ptr<ARDOUR::Route>);
        void add (boost::shared_ptr<ARDOUR::Route>);
index 43dd75df61f9606af3d73570cecb9494c926b39d..b9c44bea1393d6d6047ccdb85feb079ad4411d92 100644 (file)
@@ -63,8 +63,7 @@ operator== (const Selection& a, const Selection& b)
                a.time.group == b.time.group && 
                a.time == b.time &&
                a.lines == b.lines &&
-               a.playlists == b.playlists &&
-               a.processors == b.processors;
+               a.playlists == b.playlists;
 }
 
 /** Clear everything from the Selection */
@@ -77,7 +76,6 @@ Selection::clear ()
        clear_lines();
        clear_time ();
        clear_playlists ();
-       clear_processors ();
 }
 
 void
@@ -90,15 +88,6 @@ Selection::dump_region_layers()
 }
 
 
-void
-Selection::clear_processors ()
-{
-       if (!processors.empty()) {
-               processors.clear ();
-               ProcessorsChanged ();
-       }
-}
-
 void
 Selection::clear_regions ()
 {
@@ -153,20 +142,6 @@ Selection::clear_lines ()
        }
 }
 
-void
-Selection::toggle (boost::shared_ptr<Processor> r)
-{
-       ProcessorSelection::iterator i;
-
-       if ((i = find (processors.begin(), processors.end(), r)) == processors.end()) {
-               processors.push_back (r);
-       } else {
-               processors.erase (i);
-       }
-       ProcessorsChanged();
-
-}
-
 void
 Selection::toggle (boost::shared_ptr<Playlist> pl)
 {
@@ -252,16 +227,6 @@ Selection::toggle (nframes_t start, nframes_t end)
        return next_time_id - 1;
 }
 
-
-void
-Selection::add (boost::shared_ptr<Processor> i)
-{
-       if (find (processors.begin(), processors.end(), i) == processors.end()) {
-               processors.push_back (i);
-               ProcessorsChanged();
-       }
-}
-
 void
 Selection::add (boost::shared_ptr<Playlist> pl)
 {
@@ -394,16 +359,6 @@ Selection::add (AutomationList* ac)
        }
 }
 
-void
-Selection::remove (boost::shared_ptr<Processor> r)
-{
-       ProcessorSelection::iterator i;
-       if ((i = find (processors.begin(), processors.end(), r)) != processors.end()) {
-               processors.erase (i);
-               ProcessorsChanged ();
-       }
-}
-
 void
 Selection::remove (TimeAxisView* track)
 {
@@ -509,13 +464,6 @@ Selection::remove (AutomationList *ac)
        }
 }
 
-void
-Selection::set (boost::shared_ptr<Processor> i)
-{
-       clear_processors ();
-       add (i);
-}
-
 void
 Selection::set (TimeAxisView* track)
 {
@@ -624,8 +572,7 @@ Selection::empty ()
                playlists.empty () && 
                lines.empty () &&
                time.empty () &&
-               playlists.empty () &&
-               processors.empty ()
+               playlists.empty ()
                ;
 }
 
index 4ffb2bb9b0de6f67aa3e2b463f16a85a27d6eff4..a8f298434a54a6e982f9645c00954d97c3e50b61 100644 (file)
@@ -69,7 +69,6 @@ class Selection : public sigc::trackable
        TimeSelection        time;
        AutomationSelection  lines;
        PlaylistSelection    playlists;
-       ProcessorSelection   processors;
        PointSelection       points;
 
        Selection() {
@@ -84,7 +83,6 @@ class Selection : public sigc::trackable
        sigc::signal<void> TimeChanged;
        sigc::signal<void> LinesChanged;
        sigc::signal<void> PlaylistsChanged;
-       sigc::signal<void> ProcessorsChanged;
        sigc::signal<void> PointsChanged;
 
        void clear ();
@@ -107,7 +105,6 @@ class Selection : public sigc::trackable
        void set (ARDOUR::AutomationList*);
        void set (boost::shared_ptr<ARDOUR::Playlist>);
        void set (const std::list<boost::shared_ptr<ARDOUR::Playlist> >&);
-       void set (boost::shared_ptr<ARDOUR::Processor>);
        void set (AutomationSelectable*);
 
        void toggle (TimeAxisView*);
@@ -118,7 +115,6 @@ class Selection : public sigc::trackable
        void toggle (ARDOUR::AutomationList*);
        void toggle (boost::shared_ptr<ARDOUR::Playlist>);
        void toggle (const std::list<boost::shared_ptr<ARDOUR::Playlist> >&);
-       void toggle (boost::shared_ptr<ARDOUR::Processor>);
        void toggle (const std::vector<AutomationSelectable*>&);
 
        void add (TimeAxisView*);
@@ -129,7 +125,6 @@ class Selection : public sigc::trackable
        void add (ARDOUR::AutomationList*);
        void add (boost::shared_ptr<ARDOUR::Playlist>);
        void add (const std::list<boost::shared_ptr<ARDOUR::Playlist> >&);
-       void add (boost::shared_ptr<ARDOUR::Processor>);
        
        void remove (TimeAxisView*);
        void remove (const std::list<TimeAxisView*>&);
@@ -139,7 +134,6 @@ class Selection : public sigc::trackable
        void remove (ARDOUR::AutomationList*);
        void remove (boost::shared_ptr<ARDOUR::Playlist>);
        void remove (const std::list<boost::shared_ptr<ARDOUR::Playlist> >&);
-       void remove (boost::shared_ptr<ARDOUR::Processor>);
        void remove (const list<Selectable*>&);
 
        void replace (uint32_t time_index, nframes_t start, nframes_t end);
@@ -149,7 +143,6 @@ class Selection : public sigc::trackable
        void clear_time();
        void clear_lines ();
        void clear_playlists ();
-       void clear_processors ();
        void clear_points ();
 
        void foreach_region (void (ARDOUR::Region::*method)(void));
index d4a65672eea839debcf9c9e5904db43b26bf72b1..830ed7c02531fd85d132abcd16ef6156f09485e7 100644 (file)
@@ -59,8 +59,14 @@ class PluginInfo {
   public:
        PluginInfo () { }
        PluginInfo (const PluginInfo &o)
-               : name(o.name), n_inputs(o.n_inputs), n_outputs(o.n_outputs),
-               path (o.path), unique_id(o.unique_id), index(o.index) {}
+               : name(o.name), 
+               category (o.category), 
+               creator (o.creator),
+               path (o.path), 
+               n_inputs(o.n_inputs), 
+               n_outputs(o.n_outputs),
+               unique_id(o.unique_id), 
+               index(o.index) {}
        virtual ~PluginInfo () { }
 
        string name;
index b942a086e7123d429a627377ece2b25b9916e680..0609b8d38037bac67abbb8dbe2a7a5c220b66600 100644 (file)
@@ -125,8 +125,6 @@ Automatable::add_control(boost::shared_ptr<AutomationControl> ac)
 
        _controls[param] = ac;
        
-       cerr << _name << ": added parameter " << param.to_string() << endl;
-
        _can_automate_list.insert(param);
 
        // Sync everything (derived classes) up to initial values
@@ -459,7 +457,6 @@ Automatable::control_factory(boost::shared_ptr<AutomationList> list)
                // FIXME: this will die horribly if this is not a MidiTrack
                return boost::shared_ptr<AutomationControl>(new MidiTrack::MidiControl((MidiTrack*)this, list));
        } else {
-               cerr << "WARNING: Default AutomationControl created for " << list->parameter().to_string() << endl;
                return boost::shared_ptr<AutomationControl>(new AutomationControl(_session, list));
        }
 }
index 58009e6b5a4643ccee12e5f71df204905ca7f19c..81c615aa11b3f9e65c815d5b0387647608f76e8a 100644 (file)
@@ -76,7 +76,7 @@ PluginInsert::PluginInsert (Session& s, const XMLNode& node)
                throw failed_constructor();
        }
 
-       set_automatable ();
+       // set_automatable ();
 
        {
                Glib::Mutex::Lock em (_session.engine().process_lock());