fix crash when loading a session with non-default clock modes.
authorRobin Gareus <robin@gareus.org>
Sun, 24 Apr 2016 12:39:12 +0000 (14:39 +0200)
committerRobin Gareus <robin@gareus.org>
Sun, 24 Apr 2016 12:43:18 +0000 (14:43 +0200)
set_mode() emits ModeChanged which results in save_extra_xml().
If this happens during session-load, the XML iterator is invalidated.

gtk2_ardour/ardour_ui_ed.cc
gtk2_ardour/audio_clock.cc
gtk2_ardour/audio_clock.h

index 6af4c37f70e61dc6ff0423f28667b0994c1e8415..4303f1eab62ffa1bee26b663df0e84ac1313344e 100644 (file)
@@ -460,22 +460,22 @@ ARDOUR_UI::install_actions ()
        ActionManager::session_sensitive_actions.push_back (act);
        ActionManager::transport_sensitive_actions.push_back (act);
 
-       act = global_actions.register_action (transport_actions, X_("primary-clock-timecode"), _("Timecode"), sigc::bind (sigc::mem_fun(primary_clock, &AudioClock::set_mode), AudioClock::Timecode));
+       act = global_actions.register_action (transport_actions, X_("primary-clock-timecode"), _("Timecode"), sigc::bind (sigc::mem_fun(primary_clock, &AudioClock::set_mode), AudioClock::Timecode, false));
        ActionManager::session_sensitive_actions.push_back (act);
-       act = global_actions.register_action (transport_actions, X_("primary-clock-bbt"), _("Bars & Beats"), sigc::bind (sigc::mem_fun(primary_clock, &AudioClock::set_mode), AudioClock::BBT));
+       act = global_actions.register_action (transport_actions, X_("primary-clock-bbt"), _("Bars & Beats"), sigc::bind (sigc::mem_fun(primary_clock, &AudioClock::set_mode), AudioClock::BBT, false));
        ActionManager::session_sensitive_actions.push_back (act);
-       act = global_actions.register_action (transport_actions, X_("primary-clock-minsec"), _("Minutes & Seconds"), sigc::bind (sigc::mem_fun(primary_clock, &AudioClock::set_mode), AudioClock::MinSec));
+       act = global_actions.register_action (transport_actions, X_("primary-clock-minsec"), _("Minutes & Seconds"), sigc::bind (sigc::mem_fun(primary_clock, &AudioClock::set_mode), AudioClock::MinSec, false));
        ActionManager::session_sensitive_actions.push_back (act);
-       act = global_actions.register_action (transport_actions, X_("primary-clock-samples"), _("Samples"), sigc::bind (sigc::mem_fun(primary_clock, &AudioClock::set_mode), AudioClock::Frames));
+       act = global_actions.register_action (transport_actions, X_("primary-clock-samples"), _("Samples"), sigc::bind (sigc::mem_fun(primary_clock, &AudioClock::set_mode), AudioClock::Frames, false));
        ActionManager::session_sensitive_actions.push_back (act);
 
-       act = global_actions.register_action (transport_actions, X_("secondary-clock-timecode"), _("Timecode"), sigc::bind (sigc::mem_fun(secondary_clock, &AudioClock::set_mode), AudioClock::Timecode));
+       act = global_actions.register_action (transport_actions, X_("secondary-clock-timecode"), _("Timecode"), sigc::bind (sigc::mem_fun(secondary_clock, &AudioClock::set_mode), AudioClock::Timecode, false));
        ActionManager::session_sensitive_actions.push_back (act);
-       act = global_actions.register_action (transport_actions, X_("secondary-clock-bbt"), _("Bars & Beats"), sigc::bind (sigc::mem_fun(secondary_clock, &AudioClock::set_mode), AudioClock::BBT));
+       act = global_actions.register_action (transport_actions, X_("secondary-clock-bbt"), _("Bars & Beats"), sigc::bind (sigc::mem_fun(secondary_clock, &AudioClock::set_mode), AudioClock::BBT, false));
        ActionManager::session_sensitive_actions.push_back (act);
-       act = global_actions.register_action (transport_actions, X_("secondary-clock-minsec"), _("Minutes & Seconds"), sigc::bind (sigc::mem_fun(secondary_clock, &AudioClock::set_mode), AudioClock::MinSec));
+       act = global_actions.register_action (transport_actions, X_("secondary-clock-minsec"), _("Minutes & Seconds"), sigc::bind (sigc::mem_fun(secondary_clock, &AudioClock::set_mode), AudioClock::MinSec, false));
        ActionManager::session_sensitive_actions.push_back (act);
-       act = global_actions.register_action (transport_actions, X_("secondary-clock-samples"), _("Samples"), sigc::bind (sigc::mem_fun(secondary_clock, &AudioClock::set_mode), AudioClock::Frames));
+       act = global_actions.register_action (transport_actions, X_("secondary-clock-samples"), _("Samples"), sigc::bind (sigc::mem_fun(secondary_clock, &AudioClock::set_mode), AudioClock::Frames, false));
        ActionManager::session_sensitive_actions.push_back (act);
 
        act = global_actions.register_toggle_action (transport_actions, X_("TogglePunchIn"), _("Punch In"), sigc::mem_fun(*this, &ARDOUR_UI::toggle_punch_in));
index 5a05b208940800f4d100d8630efdcafe5c432420..834f7f31f7aad9735ea1fd551e1d2ef989a3bbd3 100644 (file)
@@ -1311,7 +1311,7 @@ AudioClock::set_session (Session *s)
 
                                        if ((prop = (*i)->property (X_("mode"))) != 0) {
                                                amode = AudioClock::Mode (string_2_enum (prop->value(), amode));
-                                               set_mode (amode);
+                                               set_mode (amode, true);
                                        }
                                        if ((prop = (*i)->property (X_("on"))) != 0) {
                                                set_off (!string_is_affirmative (prop->value()));
@@ -2112,10 +2112,10 @@ AudioClock::build_ops_menu ()
        MenuList& ops_items = ops_menu->items();
        ops_menu->set_name ("ArdourContextMenu");
 
-       ops_items.push_back (MenuElem (_("Timecode"), sigc::bind (sigc::mem_fun(*this, &AudioClock::set_mode), Timecode)));
-       ops_items.push_back (MenuElem (_("Bars:Beats"), sigc::bind (sigc::mem_fun(*this, &AudioClock::set_mode), BBT)));
-       ops_items.push_back (MenuElem (_("Minutes:Seconds"), sigc::bind (sigc::mem_fun(*this, &AudioClock::set_mode), MinSec)));
-       ops_items.push_back (MenuElem (_("Samples"), sigc::bind (sigc::mem_fun(*this, &AudioClock::set_mode), Frames)));
+       ops_items.push_back (MenuElem (_("Timecode"), sigc::bind (sigc::mem_fun(*this, &AudioClock::set_mode), Timecode, false)));
+       ops_items.push_back (MenuElem (_("Bars:Beats"), sigc::bind (sigc::mem_fun(*this, &AudioClock::set_mode), BBT, false)));
+       ops_items.push_back (MenuElem (_("Minutes:Seconds"), sigc::bind (sigc::mem_fun(*this, &AudioClock::set_mode), MinSec, false)));
+       ops_items.push_back (MenuElem (_("Samples"), sigc::bind (sigc::mem_fun(*this, &AudioClock::set_mode), Frames, false)));
 
        if (editable && !_off && !is_duration && !_follows_playhead) {
                ops_items.push_back (SeparatorElem());
@@ -2148,7 +2148,7 @@ AudioClock::locate ()
 }
 
 void
-AudioClock::set_mode (Mode m)
+AudioClock::set_mode (Mode m, bool noemit)
 {
        if (_mode == m) {
                return;
@@ -2222,11 +2222,11 @@ AudioClock::set_mode (Mode m)
 
        set (last_when, true);
 
-        if (!is_transient) {
-                ModeChanged (); /* EMIT SIGNAL (the static one)*/
-        }
+       if (!is_transient && !noemit) {
+               ModeChanged (); /* EMIT SIGNAL (the static one)*/
+       }
 
-        mode_changed (); /* EMIT SIGNAL (the member one) */
+       mode_changed (); /* EMIT SIGNAL (the member one) */
 }
 
 void
index 3790fa88ef590bf0519eea618bc8f5d1a6814fe3..b7cee0339e6445a690bfb1c09b899f8d6cc4b020 100644 (file)
@@ -67,7 +67,7 @@ class AudioClock : public CairoWidget, public ARDOUR::SessionHandlePtr
        void set (framepos_t, bool force = false, ARDOUR::framecnt_t offset = 0);
        void set_from_playhead ();
        void locate ();
-       void set_mode (Mode);
+       void set_mode (Mode, bool noemit = false);
        void set_bbt_reference (framepos_t);
         void set_is_duration (bool);