save tearoff state; restore monitor section state reasonably well; fixup access contr...
authorPaul Davis <paul@linuxaudiosystems.com>
Fri, 19 Mar 2010 02:49:01 +0000 (02:49 +0000)
committerPaul Davis <paul@linuxaudiosystems.com>
Fri, 19 Mar 2010 02:49:01 +0000 (02:49 +0000)
git-svn-id: svn://localhost/ardour2/branches/3.0@6774 d708f5d6-7413-0410-9779-e7cbd77b26cf

15 files changed:
gtk2_ardour/ardour_ui.cc
gtk2_ardour/ardour_ui_dependents.cc
gtk2_ardour/ardour_ui_ed.cc
gtk2_ardour/editor.cc
gtk2_ardour/editor.h
gtk2_ardour/level_meter.h
gtk2_ardour/mixer_ui.cc
gtk2_ardour/mixer_ui.h
gtk2_ardour/monitor_section.cc
gtk2_ardour/monitor_section.h
gtk2_ardour/public_editor.h
libs/gtkmm2ext/gtkmm2ext/tearoff.h
libs/gtkmm2ext/tearoff.cc
libs/pbd/crossthread.cc
libs/pbd/pbd/crossthread.h

index 786e14aa693754853f6ea9297e3c9d0bb47b38aa..b216acae2902052e042813fb360cca43b0696954 100644 (file)
@@ -404,7 +404,7 @@ ARDOUR_UI::post_engine ()
        /* start the time-of-day-clock */
 
 #ifndef GTKOSX
-       /* OS X provides aalways visible wallclock, so don't be stupid */
+       /* OS X provides a nearly-always visible wallclock, so don't be stupid */
        update_wall_clock ();
        Glib::signal_timeout().connect (sigc::mem_fun(*this, &ARDOUR_UI::update_wall_clock), 60000);
 #endif
@@ -431,8 +431,6 @@ ARDOUR_UI::post_engine ()
 
 ARDOUR_UI::~ARDOUR_UI ()
 {
-       save_ardour_state ();
-
        delete keyboard;
        delete editor;
        delete mixer;
@@ -453,18 +451,19 @@ ARDOUR_UI::configure_timeout ()
 {
        if (last_configure_time == 0) {
                /* no configure events yet */
-               return TRUE;
+               return true;
        }
 
        /* force a gap of 0.5 seconds since the last configure event
         */
 
        if (get_microseconds() - last_configure_time < 500000) {
-               return TRUE;
+               return true;
        } else {
                have_configure_timeout = false;
+                cerr << "config event-driven save\n";
                save_ardour_state ();
-               return FALSE;
+               return false;
        }
 }
 
@@ -538,67 +537,6 @@ ARDOUR_UI::get_transport_controllable_state ()
        return *node;
 }
 
-void
-ARDOUR_UI::save_ardour_state ()
-{
-       if (!keyboard || !mixer || !editor) {
-               return;
-       }
-
-       /* XXX this is all a bit dubious. add_extra_xml() uses
-          a different lifetime model from add_instant_xml().
-       */
-
-       XMLNode* node = new XMLNode (keyboard->get_state());
-       Config->add_extra_xml (*node);
-       Config->add_extra_xml (get_transport_controllable_state());
-
-        XMLNode* window_node = new XMLNode (X_("UI"));
-        
-        window_node->add_property ("show-big-clock", (big_clock_window && big_clock_window->is_visible() ? "yes" : "no"));
-
-        Glib::RefPtr<Gdk::Window> win;
-
-        if (big_clock_window && (win = big_clock_window->get_window())) {
-
-                int w, h;
-                int xoff, yoff;
-                char buf[32];
-
-                win->get_size (w, h);
-                win->get_position (xoff, yoff);
-
-                snprintf (buf, sizeof (buf), "%d", w);
-                window_node->add_property ("big-clock-x-size", buf);
-                snprintf (buf, sizeof (buf), "%d", h);
-                window_node->add_property ("big-clock-y-size", buf);
-                snprintf (buf, sizeof (buf), "%d", xoff);
-                window_node->add_property ("big-clock-x-off", buf);
-                snprintf (buf, sizeof (buf), "%d", yoff);
-                window_node->add_property ("big-clock-y-off", buf);
-        }
-
-        Config->add_extra_xml (*window_node);
-
-       if (_startup && _startup->engine_control() && _startup->engine_control()->was_used()) {
-               Config->add_extra_xml (_startup->engine_control()->get_state());
-       }
-       Config->save_state();
-       ui_config->save_state ();
-
-       XMLNode enode(static_cast<Stateful*>(editor)->get_state());
-       XMLNode mnode(mixer->get_state());
-
-       if (_session) {
-               _session->add_instant_xml (enode);
-               _session->add_instant_xml (mnode);
-       } else {
-               Config->add_instant_xml (enode);
-               Config->add_instant_xml (mnode);
-       }
-
-       Keyboard::save_keybindings ();
-}
 
 gint
 ARDOUR_UI::autosave_session ()
@@ -831,6 +769,7 @@ If you still wish to quit, please use the\n\n\
 
        ArdourDialog::close_all_dialogs ();
        engine->stop (true);
+        cerr << "Save before quit\n";
        save_ardour_state ();
        quit ();
 }
@@ -2091,7 +2030,7 @@ ARDOUR_UI::snapshot_session ()
 void
 ARDOUR_UI::save_state (const string & name)
 {
-       (void) save_state_canfail (name);
+       save_state_canfail (name);
 }
 
 int
@@ -2108,6 +2047,7 @@ ARDOUR_UI::save_state_canfail (string name)
                        return ret;
                }
        }
+        cerr << "SS canfail\n";
        save_ardour_state (); /* XXX cannot fail? yeah, right ... */
        return 0;
 }
index 6f48bee04ba4952655f80e0be935f14d094e5743..fb5757a8092043646c70a259c62577dce115f64c 100644 (file)
@@ -130,3 +130,4 @@ ARDOUR_UI::exit_on_main_window_close (GdkEventAny * /*ev*/)
        return TRUE;
 #endif
 }
+
index 9630c37fae6338c32e14c80a8746c0b16d360244..46cd5d952d504e75dea503a86b0b568f9f98334d 100644 (file)
 #include <cmath>
 
 #include <glibmm/miscutils.h>
-
-#include <gtkmm2ext/utils.h>
-#include <gtkmm2ext/window_title.h>
 #include <gtk/gtk.h>
 
+#include "gtkmm2ext/utils.h"
+#include "gtkmm2ext/window_title.h"
+#include "gtkmm2ext/tearoff.h"
+
 #include "pbd/file_utils.h"
 #include "pbd/fpu.h"
 #include "pbd/convert.h"
 #include "ardour_ui.h"
 #include "public_editor.h"
 #include "audio_clock.h"
+#include "keyboard.h"
+#include "monitor_section.h"
 #include "engine_dialog.h"
 #include "editor.h"
 #include "actions.h"
 #include "mixer_ui.h"
+#include "startup.h"
 #include "utils.h"
 
 #ifdef GTKOSX
@@ -671,3 +675,90 @@ ARDOUR_UI::idle_big_clock_text_resizer (int win_w, int win_h)
 
        return false;
 }
+
+void
+ARDOUR_UI::save_ardour_state ()
+{
+       if (!keyboard || !mixer || !editor) {
+               return;
+       }
+
+       /* XXX this is all a bit dubious. add_extra_xml() uses
+          a different lifetime model from add_instant_xml().
+       */
+
+       XMLNode* node = new XMLNode (keyboard->get_state());
+       Config->add_extra_xml (*node);
+       Config->add_extra_xml (get_transport_controllable_state());
+
+        XMLNode* window_node = new XMLNode (X_("UI"));
+        
+        window_node->add_property ("show-big-clock", (big_clock_window && big_clock_window->is_visible() ? "yes" : "no"));
+
+        Glib::RefPtr<Gdk::Window> win;
+
+        if (big_clock_window && (win = big_clock_window->get_window())) {
+
+                int w, h;
+                int xoff, yoff;
+                char buf[32];
+
+                win->get_size (w, h);
+                win->get_position (xoff, yoff);
+
+                snprintf (buf, sizeof (buf), "%d", w);
+                window_node->add_property ("big-clock-x-size", buf);
+                snprintf (buf, sizeof (buf), "%d", h);
+                window_node->add_property ("big-clock-y-size", buf);
+                snprintf (buf, sizeof (buf), "%d", xoff);
+                window_node->add_property ("big-clock-x-off", buf);
+                snprintf (buf, sizeof (buf), "%d", yoff);
+                window_node->add_property ("big-clock-y-off", buf);
+        }
+
+        /* tearoffs */
+
+        XMLNode* tearoff_node = new XMLNode (X_("Tearoffs"));
+
+        if (transport_tearoff) {
+                XMLNode* t = new XMLNode (X_("transport"));
+                transport_tearoff->add_tornoff_state (*t);
+                tearoff_node->add_child_nocopy (*t);
+        } 
+
+        if (mixer && mixer->monitor_section()) {
+                XMLNode* t = new XMLNode (X_("monitor-section"));
+                mixer->monitor_section()->tearoff()->add_tornoff_state (*t);
+                tearoff_node->add_child_nocopy (*t);
+        } 
+
+        if (editor && editor->mouse_mode_tearoff()) {
+                XMLNode* t = new XMLNode (X_("mouse-mode"));
+                editor->mouse_mode_tearoff ()->add_tornoff_state (*t);
+                tearoff_node->add_child_nocopy (*t);
+        } 
+        
+        window_node->add_child_nocopy (*tearoff_node);
+
+        Config->add_extra_xml (*window_node);
+
+       if (_startup && _startup->engine_control() && _startup->engine_control()->was_used()) {
+               Config->add_extra_xml (_startup->engine_control()->get_state());
+       }
+       Config->save_state();
+       ui_config->save_state ();
+
+       XMLNode enode(static_cast<Stateful*>(editor)->get_state());
+       XMLNode mnode(mixer->get_state());
+
+       if (_session) {
+               _session->add_instant_xml (enode);
+               _session->add_instant_xml (mnode);
+       } else {
+               Config->add_instant_xml (enode);
+               Config->add_instant_xml (mnode);
+       }
+
+       Keyboard::save_keybindings ();
+}
+
index 572e1923573a13654d4c21ebaf31c282ecbe93ae..5d47554f08baf32ec9dce525bd498c6964a6ff10 100644 (file)
@@ -2802,22 +2802,22 @@ Editor::setup_toolbar ()
        mode_box->pack_start (edit_mode_selector);
        mode_box->pack_start (*mouse_mode_button_box);
 
-       mouse_mode_tearoff = manage (new TearOff (*mode_box));
-       mouse_mode_tearoff->set_name ("MouseModeBase");
-       mouse_mode_tearoff->tearoff_window().signal_key_press_event().connect (sigc::bind (sigc::ptr_fun (relay_key_press), &mouse_mode_tearoff->tearoff_window()), false);
+       _mouse_mode_tearoff = manage (new TearOff (*mode_box));
+       _mouse_mode_tearoff->set_name ("MouseModeBase");
+       _mouse_mode_tearoff->tearoff_window().signal_key_press_event().connect (sigc::bind (sigc::ptr_fun (relay_key_press), &_mouse_mode_tearoff->tearoff_window()), false);
 
        if (Profile->get_sae()) {
-               mouse_mode_tearoff->set_can_be_torn_off (false);
+               _mouse_mode_tearoff->set_can_be_torn_off (false);
        }
 
-       mouse_mode_tearoff->Detach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
-                                                 &mouse_mode_tearoff->tearoff_window()));
-       mouse_mode_tearoff->Attach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
-                                                 &mouse_mode_tearoff->tearoff_window(), 1));
-       mouse_mode_tearoff->Hidden.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
-                                                 &mouse_mode_tearoff->tearoff_window()));
-       mouse_mode_tearoff->Visible.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
-                                                  &mouse_mode_tearoff->tearoff_window(), 1));
+       _mouse_mode_tearoff->Detach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
+                                                         &_mouse_mode_tearoff->tearoff_window()));
+       _mouse_mode_tearoff->Attach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
+                                                         &_mouse_mode_tearoff->tearoff_window(), 1));
+       _mouse_mode_tearoff->Hidden.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
+                                                         &_mouse_mode_tearoff->tearoff_window()));
+       _mouse_mode_tearoff->Visible.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
+                                                          &_mouse_mode_tearoff->tearoff_window(), 1));
 
        mouse_move_button.set_mode (false);
        mouse_select_button.set_mode (false);
@@ -2931,28 +2931,28 @@ Editor::setup_toolbar ()
        HBox* hbox = manage (new HBox);
        hbox->set_spacing(10);
 
-       tools_tearoff = manage (new TearOff (*hbox));
-       tools_tearoff->set_name ("MouseModeBase");
-       tools_tearoff->tearoff_window().signal_key_press_event().connect (sigc::bind (sigc::ptr_fun (relay_key_press), &tools_tearoff->tearoff_window()), false);
-
+       _tools_tearoff = manage (new TearOff (*hbox));
+       _tools_tearoff->set_name ("MouseModeBase");
+       _tools_tearoff->tearoff_window().signal_key_press_event().connect (sigc::bind (sigc::ptr_fun (relay_key_press), &_tools_tearoff->tearoff_window()), false);
+        
        if (Profile->get_sae()) {
-               tools_tearoff->set_can_be_torn_off (false);
+               _tools_tearoff->set_can_be_torn_off (false);
        }
 
-       tools_tearoff->Detach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
-                                            &tools_tearoff->tearoff_window()));
-       tools_tearoff->Attach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
-                                            &tools_tearoff->tearoff_window(), 0));
-       tools_tearoff->Hidden.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
-                                            &tools_tearoff->tearoff_window()));
-       tools_tearoff->Visible.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
-                                             &tools_tearoff->tearoff_window(), 0));
+       _tools_tearoff->Detach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
+                                                    &_tools_tearoff->tearoff_window()));
+       _tools_tearoff->Attach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
+                                                    &_tools_tearoff->tearoff_window(), 0));
+       _tools_tearoff->Hidden.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
+                                                    &_tools_tearoff->tearoff_window()));
+       _tools_tearoff->Visible.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
+                                                     &_tools_tearoff->tearoff_window(), 0));
 
        toolbar_hbox.set_spacing (10);
        toolbar_hbox.set_border_width (1);
 
-       toolbar_hbox.pack_start (*mouse_mode_tearoff, false, false);
-       toolbar_hbox.pack_start (*tools_tearoff, false, false);
+       toolbar_hbox.pack_start (*_mouse_mode_tearoff, false, false);
+       toolbar_hbox.pack_start (*_tools_tearoff, false, false);
 
        hbox->pack_start (snap_box, false, false);
        hbox->pack_start (*nudge_box, false, false);
@@ -3660,10 +3660,7 @@ Editor::pane_allocation_handler (Allocation &alloc, Paned* which)
 void
 Editor::detach_tearoff (Box* /*b*/, Window* /*w*/)
 {
-       cerr << "remove tearoff\n";
-
-       if (tools_tearoff->torn_off() &&
-           mouse_mode_tearoff->torn_off()) {
+       if (_tools_tearoff->torn_off() && _mouse_mode_tearoff->torn_off()) {
                top_hbox.remove (toolbar_frame);
        }
 }
@@ -3671,7 +3668,6 @@ Editor::detach_tearoff (Box* /*b*/, Window* /*w*/)
 void
 Editor::reattach_tearoff (Box* /*b*/, Window* /*w*/, int32_t /*n*/)
 {
-       cerr << "reattach tearoff\n";
        if (toolbar_frame.get_parent() == 0) {
                top_hbox.pack_end (toolbar_frame);
        }
@@ -3985,8 +3981,8 @@ Editor::session_state_saved (string snap_name)
 void
 Editor::maximise_editing_space ()
 {
-       mouse_mode_tearoff->set_visible (false);
-       tools_tearoff->set_visible (false);
+       _mouse_mode_tearoff->set_visible (false);
+       _tools_tearoff->set_visible (false);
 
        pre_maximal_pane_position = edit_pane.get_position();
        pre_maximal_editor_width = this->get_width();
@@ -4016,8 +4012,8 @@ Editor::restore_editing_space ()
 
        unfullscreen();
 
-       mouse_mode_tearoff->set_visible (true);
-       tools_tearoff->set_visible (true);
+       _mouse_mode_tearoff->set_visible (true);
+       _tools_tearoff->set_visible (true);
        post_maximal_editor_width = this->get_width();
 
        edit_pane.set_position (pre_maximal_pane_position + abs(this->get_width() - pre_maximal_editor_width));
@@ -4702,8 +4698,8 @@ Editor::first_idle ()
        _have_idled = true;
 }
 
-static gboolean
-_idle_resizer (gpointer arg)
+gboolean
+Editor::_idle_resize (gpointer arg)
 {
        return ((Editor*)arg)->idle_resize ();
 }
@@ -4711,10 +4707,8 @@ _idle_resizer (gpointer arg)
 void
 Editor::add_to_idle_resize (TimeAxisView* view, int32_t h)
 {
-        cerr << "add tav " << view << " with hdelta = " << h << endl;
-
        if (resize_idle_id < 0) {
-               resize_idle_id = g_idle_add (_idle_resizer, this);
+               resize_idle_id = g_idle_add (_idle_resize, this);
                _pending_resize_amount = 0;
        }
 
@@ -4726,8 +4720,6 @@ Editor::add_to_idle_resize (TimeAxisView* view, int32_t h)
        _pending_resize_amount += h;
        _pending_resize_view = view;
 
-        cerr << "Pending resize amount initially set at " << _pending_resize_amount << endl;
-
        min_resulting = min (min_resulting, int32_t (_pending_resize_view->current_height()) + _pending_resize_amount);
 
        if (selection->tracks.contains (_pending_resize_view)) {
@@ -4743,7 +4735,6 @@ Editor::add_to_idle_resize (TimeAxisView* view, int32_t h)
        /* clamp */
        if (uint32_t (min_resulting) < TimeAxisView::hSmall) {
                _pending_resize_amount += TimeAxisView::hSmall - min_resulting;
-                cerr << "pending resize amount = " << _pending_resize_amount << endl;
        }
 }
 
@@ -4751,9 +4742,6 @@ Editor::add_to_idle_resize (TimeAxisView* view, int32_t h)
 bool
 Editor::idle_resize ()
 {
-        cerr << "Idle resize, pra = " << _pending_resize_amount 
-             << " set height to " << _pending_resize_view->current_height() << " + " << _pending_resize_amount << endl;
-
        _pending_resize_view->idle_resize (_pending_resize_view->current_height() + _pending_resize_amount);
 
        if (dynamic_cast<AutomationTimeAxisView*> (_pending_resize_view) == 0 &&
index 0fc433d2fb45faa8f3cd355295f1b42d20d28c75..b2e1a380341322797f4392503116186bdddba4cf 100644 (file)
@@ -444,6 +444,15 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
        void center_screen (nframes64_t);
 
        TrackViewList axis_views_from_routes (boost::shared_ptr<ARDOUR::RouteList>) const;
+       Gtkmm2ext::TearOff* mouse_mode_tearoff () const { return _mouse_mode_tearoff; }
+       Gtkmm2ext::TearOff* tools_tearoff () const { return _tools_tearoff; }
+
+       void snap_to (nframes64_t& first, int32_t direction = 0, bool for_mark = false);
+       void snap_to_with_modifier (nframes64_t& first, GdkEvent const *, int32_t direction = 0, bool for_mark = false);
+       void snap_to (nframes64_t& first, nframes64_t& last, int32_t direction = 0, bool for_mark = false);
+
+       void begin_reversible_command (std::string cmd_name);
+       void commit_reversible_command ();
 
   protected:
        void map_transport_state ();
@@ -1347,8 +1356,8 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
 private:
        ArdourCanvas::Item *last_item_entered;
        int last_item_entered_n;
-public:
 
+public:
        bool canvas_region_view_event (GdkEvent* event,ArdourCanvas::Item*, RegionView*);
        bool canvas_frame_handle_event (GdkEvent* event,ArdourCanvas::Item*, RegionView*);
        bool canvas_region_view_name_highlight_event (GdkEvent* event,ArdourCanvas::Item*, RegionView*);
@@ -1377,6 +1386,11 @@ public:
        bool canvas_markerview_start_handle_event(GdkEvent* event, ArdourCanvas::Item*,MarkerView*);
        bool canvas_markerview_end_handle_event(GdkEvent* event, ArdourCanvas::Item*,MarkerView*);
 
+  private:
+        friend class DragManager;
+        friend class EditorRouteGroups;
+        friend class EditorRegions;
+
        /* non-public event handlers */
 
        bool canvas_playhead_cursor_event (GdkEvent* event, ArdourCanvas::Item*);
@@ -1488,10 +1502,6 @@ public:
        void tempo_map_changed (const PBD::PropertyChange&);
        void redisplay_tempo (bool immediate_redraw);
 
-       void snap_to (nframes64_t& first, int32_t direction = 0, bool for_mark = false);
-       void snap_to_with_modifier (nframes64_t& first, GdkEvent const *, int32_t direction = 0, bool for_mark = false);
-       void snap_to (nframes64_t& first, nframes64_t& last, int32_t direction = 0, bool for_mark = false);
-
        uint32_t bbt_beat_subdivision;
 
        /* toolbar */
@@ -1515,7 +1525,7 @@ public:
        Gtk::Table               toolbar_selection_clock_table;
        Gtk::Label               toolbar_selection_cursor_label;
 
-       Gtkmm2ext::TearOff*      mouse_mode_tearoff;
+       Gtkmm2ext::TearOff*      _mouse_mode_tearoff;
        Gtk::ToggleButton         mouse_select_button;
        Gtk::ToggleButton         mouse_move_button;
        Gtk::ToggleButton         mouse_gain_button;
@@ -1578,7 +1588,7 @@ public:
 
        void setup_tooltips ();
 
-       Gtkmm2ext::TearOff*      tools_tearoff;
+       Gtkmm2ext::TearOff*     _tools_tearoff;
        Gtk::HBox                toolbar_hbox;
        Gtk::EventBox            toolbar_base;
        Gtk::Frame               toolbar_frame;
@@ -1766,9 +1776,6 @@ public:
 
        XMLNode *before; /* used in *_reversible_command */
 
-       void begin_reversible_command (std::string cmd_name);
-       void commit_reversible_command ();
-
        void update_title ();
        void update_title_s (const std::string & snapshot_name);
 
@@ -1999,8 +2006,8 @@ public:
 
        bool _have_idled;
        int resize_idle_id;
+       static gboolean _idle_resize (gpointer);
        bool idle_resize();
-       friend gboolean _idle_resize (gpointer);
        int32_t _pending_resize_amount;
        TimeAxisView* _pending_resize_view;
 
index 06c7230b7caaeca7ed589e41c8a30d24ab7e2eee..6b3c33cac514ff113c6889e25801824a527f0195 100644 (file)
@@ -31,6 +31,7 @@
 #include <gtkmm/drawingarea.h>
 
 #include "ardour/types.h"
+#include "ardour/chan_count.h"
 #include "ardour/session_handle.h"
 
 #include <gtkmm2ext/click_box.h>
index c98d0028e97d86162c6ffd8bddf1ba4ac1e13006..badd96154a88025f4fbcf4ad1b305c6182d0055d 100644 (file)
@@ -30,6 +30,7 @@
 #include <gtkmm2ext/gtk_ui.h>
 #include <gtkmm2ext/utils.h>
 #include <gtkmm2ext/stop_signal.h>
+#include <gtkmm2ext/tearoff.h>
 #include <gtkmm2ext/window_title.h>
 
 #include "ardour/audio_diskstream.h"
@@ -67,7 +68,7 @@ Mixer_UI::Mixer_UI ()
 {
        _strip_width = Config->get_default_narrow_ms() ? Narrow : Wide;
        track_menu = 0;
-        monitor_section = 0;
+        _monitor_section = 0;
        route_group_context_menu = 0;
        no_track_list_redisplay = false;
        in_group_row_change = false;
@@ -321,14 +322,35 @@ Mixer_UI::add_strip (RouteList& routes)
                }
 
                 if (route->is_control()) {
-                        monitor_section = new MonitorSection (_session);
-                        out_packer.pack_end (monitor_section->pack_widget(), false, false);
-                        monitor_section->pack_widget().show_all ();
-                        /* no regular strip */
+                        if (!_monitor_section) {
+                                _monitor_section = new MonitorSection (_session);
+                                out_packer.pack_end (_monitor_section->pack_widget(), false, false);
+                        } else {
+                                _monitor_section->set_session (_session);
+                        }
+
+                        _monitor_section->pack_widget().show_all ();
+
+                        XMLNode* ui_node = Config->extra_xml(X_("UI"));
+
+                        if (ui_node) {
+                                cerr << "Got UI node\n";
+                                XMLNode* tearoff_node = ui_node->child (X_("Tearoffs"));
+                                if (tearoff_node) {
+                                        cerr << "Got tearoff node\n";
+                                        XMLNode* mnode = tearoff_node->child (X_("monitor-section"));
+                                        if (mnode) {
+                                                cerr << "got mndeo\n";
+                                                _monitor_section->tearoff()->set_tornoff_state (*mnode);
+                                        }
+                                }
+                        }
+
+                        /* no regular strip shown for control out */
+
                         continue;
                 }
 
-
                strip = new MixerStrip (*this, _session, route);
                strips.push_back (strip);
 
@@ -521,14 +543,13 @@ Mixer_UI::session_going_away ()
        group_model->clear ();
        _selection.clear ();
        track_model->clear ();
-        
-        delete monitor_section;
-        monitor_section = 0;
 
        for (list<MixerStrip *>::iterator i = strips.begin(); i != strips.end(); ++i) {
                delete (*i);
        }
 
+        _monitor_section->pack_widget().hide ();
+
        strips.clear ();
 
        WindowTitle title(Glib::get_application_name());
@@ -594,8 +615,8 @@ Mixer_UI::fast_update_strips ()
                        (*i)->fast_update ();
                }
 
-                if (monitor_section) {
-                        monitor_section->fast_update ();
+                if (_monitor_section) {
+                        _monitor_section->fast_update ();
                 }
        }
 }
index 87bf57a6df1979f06e2d1e089a1a510c903e9159..c8d3bacae00fce801ca0a0febe0f649c78e024a5 100644 (file)
@@ -81,6 +81,7 @@ class Mixer_UI : public Gtk::Window, public PBD::ScopedConnectionList, public AR
        void set_auto_rebinding(bool);
 
        RouteRedirectSelection& selection() { return _selection; }
+        MonitorSection* monitor_section() const { return _monitor_section; }
 
   private:
        bool                                    _visible;
@@ -195,8 +196,7 @@ class Mixer_UI : public Gtk::Window, public PBD::ScopedConnectionList, public AR
        void track_column_click (gint);
        void build_track_menu ();
 
-        MonitorSection* monitor_section;
-
+        MonitorSection* _monitor_section;
        PluginSelector    *_plugin_selector;
 
        void strip_property_changed (const PBD::PropertyChange&, MixerStrip *);
index 8909a1649c95e24fd5c85c8f399510e4b3446819..480786eb2c3317a0917b7e2a08ecffa89c33b060 100644 (file)
@@ -61,18 +61,8 @@ MonitorSection::MonitorSection (Session* s)
 
         }
         
-        _route = _session->control_out ();
-
-        if (!_route) {
-                throw failed_constructor ();
-        }
-
-        _monitor = _route->monitor_control ();
-
-        if (!_monitor) {
-                throw failed_constructor ();
-        }
-
+        set_session (s);
+        
         VBox* sub_knob_packer = manage (new VBox);
         sub_knob_packer->set_spacing (12);
 
@@ -264,6 +254,36 @@ MonitorSection::~MonitorSection ()
         delete _tearoff;
 }
 
+void
+MonitorSection::set_session (Session* s)
+{
+        AxisView::set_session (s);
+
+        if (_session) {
+
+                _route = _session->control_out ();
+
+                if (_route) {
+                        /* session with control outs */
+                        _monitor = _route->monitor_control ();
+                        meter.set_meter (&_route->peak_meter());
+                } else { 
+                        /* session with no control outs */
+                        _monitor.reset ();
+                        _route.reset ();
+                        meter.set_meter (0);
+                }
+                        
+        } else {
+                /* no session */
+                _monitor.reset ();
+                _route.reset ();
+                meter.set_meter (0);
+        }
+
+        /* both might be null */
+}
+
 MonitorSection::ChannelButtonSet::ChannelButtonSet ()
         : cut (X_(""))
         , dim (X_(""))
@@ -283,6 +303,10 @@ MonitorSection::ChannelButtonSet::ChannelButtonSet ()
 void
 MonitorSection::populate_buttons ()
 {
+        if (!_monitor) {
+                return;
+        }
+
         Glib::RefPtr<Action> act;
         uint32_t nchans = _monitor->output_streams().n_audio();
         
@@ -378,6 +402,10 @@ MonitorSection::pack_widget () const
 void
 MonitorSection::dim_all ()
 {
+        if (!_monitor) {
+                return;
+        }
+
         Glib::RefPtr<Action> act = ActionManager::get_action (X_("Monitor"), "monitor-dim-all");
         if (act) {
                Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
@@ -389,6 +417,10 @@ MonitorSection::dim_all ()
 void
 MonitorSection::cut_all ()
 {
+        if (!_monitor) {
+                return;
+        }
+
         Glib::RefPtr<Action> act = ActionManager::get_action (X_("Monitor"), "monitor-cut-all");
         if (act) {
                Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
@@ -399,6 +431,10 @@ MonitorSection::cut_all ()
 void
 MonitorSection::mono ()
 {
+        if (!_monitor) {
+                return;
+        }
+
         Glib::RefPtr<Action> act = ActionManager::get_action (X_("Monitor"), "monitor-mono");
         if (act) {
                Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
@@ -409,6 +445,10 @@ MonitorSection::mono ()
 void
 MonitorSection::cut_channel (uint32_t chn)
 {
+        if (!_monitor) {
+                return;
+        }
+
         char buf[64];
         snprintf (buf, sizeof (buf), "monitor-cut-%u", chn);
 
@@ -424,6 +464,10 @@ MonitorSection::cut_channel (uint32_t chn)
 void
 MonitorSection::dim_channel (uint32_t chn)
 {
+        if (!_monitor) {
+                return;
+        }
+
         char buf[64];
         snprintf (buf, sizeof (buf), "monitor-dim-%u", chn);
 
@@ -440,6 +484,10 @@ MonitorSection::dim_channel (uint32_t chn)
 void
 MonitorSection::solo_channel (uint32_t chn)
 {
+        if (!_monitor) {
+                return;
+        }
+
         char buf[64];
         snprintf (buf, sizeof (buf), "monitor-solo-%u", chn);
 
@@ -456,6 +504,10 @@ MonitorSection::solo_channel (uint32_t chn)
 void
 MonitorSection::invert_channel (uint32_t chn)
 {
+        if (!_monitor) {
+                return;
+        }
+
         char buf[64];
         snprintf (buf, sizeof (buf), "monitor-invert-%u", chn);
 
@@ -625,19 +677,25 @@ MonitorSection::setup_knob_images ()
 void
 MonitorSection::gain_value_changed ()
 {
-        _route->set_gain (slider_position_to_gain (gain_adjustment.get_value()), this);
+        if (_route) {
+                _route->set_gain (slider_position_to_gain (gain_adjustment.get_value()), this);
+        }
 }
 
 void
 MonitorSection::dim_level_changed ()
 {
-        _monitor->set_dim_level (dim_adjustment.get_value());
+        if (_monitor) {
+                _monitor->set_dim_level (dim_adjustment.get_value());
+        }
 }
 
 void
 MonitorSection::solo_boost_changed ()
 {
-        _monitor->set_solo_boost_level (solo_boost_adjustment.get_value());
+        if (_monitor) {
+                _monitor->set_solo_boost_level (solo_boost_adjustment.get_value());
+        }
 }
 
 bool
@@ -663,6 +721,10 @@ MonitorSection::linear_gain_printer (SpinButton* button)
 void
 MonitorSection::map_state ()
 {
+        if (!_route || !_monitor) {
+                return;
+        }
+
         gain_control->get_adjustment()->set_value (gain_to_slider_position (_route->gain_control()->get_value()));
         dim_control->get_adjustment()->set_value (_monitor->dim_level());
         solo_boost_control->get_adjustment()->set_value (_monitor->solo_boost_level());
index 0a8909def8440e5aaf63051cfb21aadf8402bedf..405b8eba87015315da4ad4650bb376bdbfa145bf 100644 (file)
@@ -38,10 +38,14 @@ class MonitorSection : public RouteUI
         MonitorSection (ARDOUR::Session*);
         ~MonitorSection ();
 
+        void set_session (ARDOUR::Session*);
+
         Gtk::Widget& pack_widget () const;
         void fast_update ();
         static void setup_knob_images ();
 
+        Gtkmm2ext::TearOff* tearoff() const { return _tearoff; }
+
   private:
         Gtk::VBox vpacker;
         Gtk::HBox hpacker;
index 1ddee9a585ac8e4201034f0d31dcb8d7aba3f0cd..d84cf589fbed5a7cec895ca7be0fb11a452c0b6f 100644 (file)
@@ -52,6 +52,10 @@ namespace Gtk {
        class Menu;
 }
 
+namespace Gtkmm2ext { 
+        class TearOff;
+}
+
 class Editor;
 class TimeAxisViewItem;
 class TimeAxisView;
@@ -359,6 +363,9 @@ class PublicEditor : public Gtk::Window, public PBD::StatefulDestructible {
        virtual TrackViewList axis_views_from_routes (boost::shared_ptr<ARDOUR::RouteList>) const = 0;
        virtual TrackViewList const & get_track_views () = 0;
        
+       virtual Gtkmm2ext::TearOff* mouse_mode_tearoff () const = 0;
+       virtual Gtkmm2ext::TearOff* tools_tearoff () const = 0;
+
        /// Singleton instance, set up by Editor::Editor()
 
        static PublicEditor* _instance;
index 737a6ddd03441b95ddf8a90933e7b84e69f0edc0..db01684e2f2f825ab1aa0ebb067d618aadb74648 100644 (file)
@@ -25,6 +25,8 @@
 #include <gtkmm/box.h>
 #include <gtkmm/eventbox.h>
 
+class XMLNode;
+
 namespace Gtkmm2ext {
 
 class TearOff : public Gtk::HBox
@@ -44,6 +46,11 @@ class TearOff : public Gtk::HBox
 
        Gtk::Window& tearoff_window() { return own_window; }
        bool torn_off() const;
+        void tear_it_off ();
+        void put_it_back ();
+
+        void set_tornoff_state (const XMLNode&);
+        void add_tornoff_state (XMLNode&) const;
 
   private:
        Gtk::Widget&   contents;
@@ -58,6 +65,10 @@ class TearOff : public Gtk::HBox
        bool           dragging;
        bool          _visible;
        bool          _can_be_torn_off;
+        int            own_window_width;
+        int            own_window_height;
+        int            own_window_xpos;
+        int            own_window_ypos;
 
        gint tearoff_click (GdkEventButton*);
        gint close_click (GdkEventButton*);
@@ -66,6 +77,9 @@ class TearOff : public Gtk::HBox
        gint window_button_press (GdkEventButton*);
        gint window_button_release (GdkEventButton*);
        gint window_delete_event (GdkEventAny*);
+
+        void own_window_realized ();
+        bool own_window_configured (GdkEventConfigure*);
 };
 
 } /* namespace */
index c33663e8f745cc3fa624e3992b6fa376d104b32c..28fb5ba4ef60f37e987c8d79886a73de654eae12 100644 (file)
 
 #include <cmath>
 #include <iostream>
-#include <gtkmm2ext/tearoff.h>
-#include <gtkmm2ext/utils.h>
+
+#include "pbd/xml++.h"
+
+#include "gtkmm2ext/tearoff.h"
+#include "gtkmm2ext/utils.h"
+
+#include "i18n.h"
 
 using namespace Gtkmm2ext;
 using namespace Gtk;
@@ -38,6 +43,10 @@ TearOff::TearOff (Widget& c, bool allow_resize)
        dragging = false;
        _visible = true;
        _can_be_torn_off = true;
+        own_window_width = 0;
+        own_window_height = 0;
+        own_window_xpos = 0;
+        own_window_ypos = 0;
 
        tearoff_event_box.add (tearoff_arrow);
        tearoff_event_box.set_events (BUTTON_PRESS_MASK|BUTTON_RELEASE_MASK);
@@ -50,7 +59,9 @@ TearOff::TearOff (Widget& c, bool allow_resize)
        own_window.add_events (KEY_PRESS_MASK|KEY_RELEASE_MASK|BUTTON_PRESS_MASK|BUTTON_RELEASE_MASK|POINTER_MOTION_MASK|POINTER_MOTION_HINT_MASK);
        own_window.set_resizable (allow_resize);
        own_window.set_type_hint (WINDOW_TYPE_HINT_TOOLBAR);
-       
+        own_window.signal_realize().connect (sigc::mem_fun (*this, &TearOff::own_window_realized));
+        own_window.signal_configure_event().connect (sigc::mem_fun (*this, &TearOff::own_window_configured), false);
+
        VBox* box1;
        box1 = manage (new VBox);
        box1->pack_start (close_event_box, false, false, 2);
@@ -73,7 +84,6 @@ TearOff::TearOff (Widget& c, bool allow_resize)
 
        pack_start (contents);
        pack_start (*box2, false, false, 2);
-
 }
 
 TearOff::~TearOff ()
@@ -119,32 +129,52 @@ TearOff::set_visible (bool yn)
 gint
 TearOff::tearoff_click (GdkEventButton* /*ev*/)
 {
-       if (_can_be_torn_off) {
-               remove (contents);
-               window_box.pack_start (contents);
-               own_window.set_name (get_name());
-               close_event_box.set_name (get_name());
-               own_window.show_all ();
-               own_window.present ();
-               std::cerr << "own window should be visible\n";
-               hide ();
-               Detach ();
-       }
-
+        tear_it_off ();
        return true;
 }
 
+void
+TearOff::tear_it_off ()
+{
+       if (!_can_be_torn_off) {
+                return;
+        }
+                
+        if (torn_off()) {
+                return;
+        }
+
+        remove (contents);
+        window_box.pack_start (contents);
+        own_window.set_name (get_name());
+        close_event_box.set_name (get_name());
+        own_window.show_all ();
+        own_window.present ();
+        hide ();
+        Detach ();
+}        
+
 gint
 TearOff::close_click (GdkEventButton* /*ev*/)
 {
+        put_it_back ();
+       return true;
+}              
+
+void
+TearOff::put_it_back ()
+{
+        if (!torn_off()) {
+                return;
+        }
+
        window_box.remove (contents);
        pack_start (contents);
        reorder_child (contents, 0);
        own_window.hide ();
        show_all ();
        Attach ();
-       return true;
-}              
+}
 
 gint
 TearOff::window_button_press (GdkEventButton* ev)
@@ -217,3 +247,79 @@ TearOff::torn_off() const
 {
        return own_window.is_visible();
 }
+
+void
+TearOff::add_tornoff_state (XMLNode& node) const
+{
+        node.add_property ("tornoff", (own_window.is_visible() ? "yes" : "no"));
+
+        if (own_window_width > 0) {
+                char buf[32];
+
+                snprintf (buf, sizeof (buf), "%d", own_window_width);
+                node.add_property ("width", buf);
+                snprintf (buf, sizeof (buf), "%d", own_window_height);
+                node.add_property ("height", buf);
+                snprintf (buf, sizeof (buf), "%d", own_window_xpos);
+                node.add_property ("xpos", buf);
+                snprintf (buf, sizeof (buf), "%d", own_window_ypos);
+                node.add_property ("ypos", buf);
+        }
+}        
+
+void
+TearOff::set_tornoff_state (const XMLNode& node)
+{
+        Glib::RefPtr<Gdk::Window> win;
+        const XMLProperty* prop;
+
+        if ((prop = node.property (X_("tornoff"))) == 0) {
+                return;
+        }
+
+        if (prop->value() == "yes") {
+                tear_it_off ();
+        } else {
+                put_it_back ();
+        }
+
+        if ((prop = node.property (X_("width"))) != 0) {
+                sscanf (prop->value().c_str(), "%d", &own_window_width);
+        }
+        if ((prop = node.property (X_("height"))) != 0) {
+                sscanf (prop->value().c_str(), "%d", &own_window_height);
+        }
+        if ((prop = node.property (X_("xpos"))) != 0) {
+                sscanf (prop->value().c_str(), "%d", &own_window_xpos);
+        }
+        if ((prop = node.property (X_("ypos"))) != 0) {
+                sscanf (prop->value().c_str(), "%d", &own_window_ypos);
+        }
+
+        own_window.set_default_size (own_window_width, own_window_height);
+        own_window.move (own_window_xpos, own_window_ypos);
+}        
+
+void
+TearOff::own_window_realized ()
+{
+        if (own_window_width > 0) {
+                own_window.set_default_size (own_window_width, own_window_height);
+                own_window.move (own_window_xpos, own_window_ypos);
+        }
+}
+
+bool
+TearOff::own_window_configured (GdkEventConfigure*)
+{
+        Glib::RefPtr<const Gdk::Window> win;
+
+        win = own_window.get_window ();
+        
+        if (win) {
+                win->get_size (own_window_width, own_window_height);
+                win->get_position (own_window_xpos, own_window_ypos);
+        }
+
+        return false;
+}
index 2bcb444b366ef322c1468231d7efa313d478ba0a..7ccf7413806a07408200b068d73be0afbc4ca3c4 100644 (file)
@@ -104,3 +104,15 @@ CrossThreadChannel::drain (int fd)
        char buf[64];
        while (::read (fd, buf, sizeof (buf)) > 0);
 }
+
+int
+CrossThreadChannel::deliver (char msg)
+{
+        return ::write (fds[1], &msg, 1);
+}
+
+int 
+CrossThreadChannel::receive (char& msg)
+{
+        return ::read (fds[0], &msg, 1);
+}
index 7a323e198fb29d320c5c86db3aefd6e012054381..f9845eedf07fa115427ec420fe6fa9fb0051db03 100644 (file)
@@ -30,6 +30,9 @@ class CrossThreadChannel {
        void wakeup();
        int selectable() const { return fds[0]; }
 
+        int deliver (char msg);
+        int receive (char& msg);
+        
        void drain ();
        static void drain (int fd);