vtl: rework session-needs-save logic
authorRobin Gareus <robin@gareus.org>
Tue, 9 Apr 2013 02:05:07 +0000 (04:05 +0200)
committerRobin Gareus <robin@gareus.org>
Tue, 9 Apr 2013 02:05:46 +0000 (04:05 +0200)
* videotimeline now immediately marks the session dirty on
  every state-changing operation
* video-montor is polled every 2.5 seconds for menu-relevant state info
  (ontop, OSD,..) and every 30 seconds for full state (window pos, size,..)
* new interface to query the video-monitor for its state and wait for
  all replies - terminating the process and using ::wait() is no longer
  required
* Ardour> quit and Ardour > close-session does no longer close the video
  session to enforce video-monitor state sync but uses above new interface

gtk2_ardour/ardour_ui.cc
gtk2_ardour/ardour_ui_dialogs.cc
gtk2_ardour/video_monitor.cc
gtk2_ardour/video_monitor.h
gtk2_ardour/video_timeline.cc
gtk2_ardour/video_timeline.h

index 83931816be1780d98b50576c514cd83059036b24..b7cccbfaa5f06d1f5229179932402feb1db3204c 100644 (file)
@@ -834,13 +834,10 @@ ARDOUR_UI::idle_finish ()
 void
 ARDOUR_UI::finish()
 {
+       if (_session) {
 #ifdef WITH_VIDEOTIMELINE
-       /* close video-monitor & pending requests
-        * would better be done in ~Editor() but that is not called..
-        */
-       ARDOUR_UI::instance()->video_timeline->close_session();
+               ARDOUR_UI::instance()->video_timeline->sync_session_state();
 #endif
-       if (_session) {
 
                if (_session->dirty()) {
                        vector<string> actions;
@@ -849,7 +846,6 @@ ARDOUR_UI::finish()
                        actions.push_back (_("Save and quit"));
                        switch (ask_about_saving_session(actions)) {
                        case -1:
-                               ARDOUR_UI::instance()->video_timeline->set_session(_session);
                                return;
                                break;
                        case 1:
@@ -2558,7 +2554,7 @@ ARDOUR_UI::get_session_parameters (bool quit_on_cancel, bool should_be_new, stri
         */
 #ifdef WITH_VIDEOTIMELINE
        if (_session && ARDOUR_UI::instance()->video_timeline) {
-               ARDOUR_UI::instance()->video_timeline->close_session();
+               ARDOUR_UI::instance()->video_timeline->sync_session_state();
        }
 #endif
        if (_session && _session->dirty()) {
@@ -2745,9 +2741,6 @@ ARDOUR_UI::get_session_parameters (bool quit_on_cancel, bool should_be_new, stri
 void
 ARDOUR_UI::close_session()
 {
-#ifdef WITH_VIDEOTIMELINE
-       ARDOUR_UI::instance()->video_timeline->close_session();
-#endif
        if (!check_audioengine()) {
                return;
        }
index fb31ba513a0543e4caf227f8af6e6d8dda71919b..0cfe3412112145dab6d9aacc72cec9bc3e5081a2 100644 (file)
@@ -217,11 +217,7 @@ ARDOUR_UI::unload_session (bool hide_stuff)
 {
 #ifdef WITH_VIDEOTIMELINE
        if (_session) {
-               /* close video-monitor
-                * this needed to enfore querying its settings (window size,..)
-                * which are reported asynchroneously.
-                */
-               ARDOUR_UI::instance()->video_timeline->close_session();
+               ARDOUR_UI::instance()->video_timeline->sync_session_state();
        }
 #endif
        if (_session && _session->dirty()) {
@@ -231,7 +227,6 @@ ARDOUR_UI::unload_session (bool hide_stuff)
                actions.push_back (_("Save and close"));
                switch (ask_about_saving_session (actions)) {
                case -1:
-                       ARDOUR_UI::instance()->video_timeline->set_session(_session);
                        // cancel
                        return 1;
 
@@ -255,6 +250,9 @@ ARDOUR_UI::unload_session (bool hide_stuff)
        ActionManager::set_sensitive (ActionManager::session_sensitive_actions, false);
 
        rec_button.set_sensitive (false);
+#ifdef WITH_VIDEOTIMELINE
+       ARDOUR_UI::instance()->video_timeline->close_session();
+#endif
 
        stop_blinking ();
        stop_clocking ();
index 5bc6bb67771439c59c7f42dd03bdd50b9540953e..9bcd244cf05924b5ca6ad3023475274adce44df3 100644 (file)
@@ -79,11 +79,9 @@ VideoMonitor::start ()
 }
 
 void
-VideoMonitor::quit ()
+VideoMonitor::query_full_state (bool wait)
 {
-       if (!is_started()) return;
-       if (state_connection.connected()) { state_connection.disconnect(); }
-       if (clock_connection.connected()) { clock_connection.disconnect(); }
+       knownstate = 0;
        process->write_to_stdin("get windowsize\n");
        process->write_to_stdin("get windowpos\n");
        process->write_to_stdin("get letterbox\n");
@@ -91,10 +89,21 @@ VideoMonitor::quit ()
        process->write_to_stdin("get ontop\n");
        process->write_to_stdin("get offset\n");
        process->write_to_stdin("get osdcfg\n");
+       int timeout = 40;
+       if (wait && knownstate !=127 && --timeout) {
+               usleep(50000);
+               sched_yield();
+       }
+}
+
+void
+VideoMonitor::quit ()
+{
+       if (!is_started()) return;
+       if (state_connection.connected()) { state_connection.disconnect(); }
+       if (clock_connection.connected()) { clock_connection.disconnect(); }
        process->write_to_stdin("quit\n");
-#if 1
-       /* wait for replies to the config requests above.
-        * the 'quit' command should result in process termination
+       /* the 'quit' command should result in process termination
         * but in case it fails (communication failure, SIGSTOP, ??)
         * here's a timeout..
         */
@@ -104,11 +113,8 @@ VideoMonitor::quit ()
                sched_yield();
        }
        if (timeout <= 0) {
-               printf("xjadeo connection: time-out. session may not be saved.\n");
                process->terminate();
        }
-#endif
-       save_session();
 }
 
 void
@@ -145,9 +151,16 @@ void
 VideoMonitor::querystate ()
 {
        /* clock-divider hack -- RapidScreenUpdate == every_point_one_seconds */
-       state_clk_divide = (state_clk_divide + 1) % 15; // every 1.5 seconds
-       if (state_clk_divide != 0) return;
-
+       state_clk_divide = (state_clk_divide + 1) % 300; // 30 secs
+       if (state_clk_divide == 0) {
+               // every 30 seconds
+               query_full_state(false);
+               return;
+       }
+       if (state_clk_divide%25 != 0) {
+               return;
+       }
+       // every 2.5 seconds:
        process->write_to_stdin("get fullscreen\n");
        process->write_to_stdin("get ontop\n");
        process->write_to_stdin("get osdcfg\n");
@@ -268,35 +281,50 @@ VideoMonitor::parse_output (std::string d, size_t s)
 #if 0 /* DEBUG */
                                        std::cout << "parsed: " << key << " => " << value << std::endl;
 #endif
-                                              if(key ==  "windowpos") {
+                                       if       (key ==  "windowpos") {
+                                               knownstate |= 16;
+                                               if (xjadeo_settings["window xy"] != value) {
+                                                       if (!starting && _session) _session->set_dirty ();
+                                               }
                                                xjadeo_settings["window xy"] = value;
                                        } else if(key ==  "windowsize") {
+                                               knownstate |= 32;
+                                               if (xjadeo_settings["window size"] != value) {
+                                                       if (!starting && _session) _session->set_dirty ();
+                                               }
                                                xjadeo_settings["window size"] = value;
                                        } else if(key ==  "windowontop") {
+                                               knownstate |= 2;
                                                if (starting || xjadeo_settings["window ontop"] != value) {
-                                                       starting &= ~2;
+                                                       if (!starting && _session) _session->set_dirty ();
                                                        if (atoi(value.c_str())) { UiState("xjadeo-window-ontop-on"); }
                                                        else { UiState("xjadeo-window-ontop-off"); }
+                                                       starting &= ~2;
                                                }
                                                xjadeo_settings["window ontop"] = value;
                                        } else if(key ==  "fullscreen") {
+                                               knownstate |= 4;
                                                if (starting || xjadeo_settings["window zoom"] != value) {
-                                                       starting &= ~4;
+                                                       if (!starting && _session) _session->set_dirty ();
                                                        if (atoi(value.c_str())) { UiState("xjadeo-window-fullscreen-on"); }
                                                        else { UiState("xjadeo-window-fullscreen-off"); }
+                                                       starting &= ~4;
                                                }
                                                xjadeo_settings["window zoom"] = value;
                                        } else if(key ==  "letterbox") {
+                                               knownstate |= 8;
                                                if (starting || xjadeo_settings["window letterbox"] != value) {
-                                                       starting &= ~8;
+                                                       if (!starting && _session) _session->set_dirty ();
                                                        if (atoi(value.c_str())) { UiState("xjadeo-window-letterbox-on"); }
                                                        else { UiState("xjadeo-window-letterbox-off"); }
+                                                       starting &= ~8;
                                                }
                                                xjadeo_settings["window letterbox"] = value;
                                        } else if(key ==  "osdmode") {
-                                               if (starting || xjadeo_settings["osd mode"] != value) {
-                                                       starting &= ~1;
-                                                       osdmode = atoi(value.c_str());
+                                               knownstate |= 1;
+                                               osdmode = atoi(value.c_str());
+                                               if (starting || atoi(xjadeo_settings["osd mode"].c_str()) != osdmode) {
+                                                       if (!starting && _session) _session->set_dirty ();
                                                        if ((osdmode & 1) == 1) { UiState("xjadeo-window-osd-frame-on"); }
                                                        if ((osdmode & 1) == 0) { UiState("xjadeo-window-osd-frame-off"); }
                                                        if ((osdmode & 2) == 2) { UiState("xjadeo-window-osd-timecode-on"); }
@@ -304,8 +332,13 @@ VideoMonitor::parse_output (std::string d, size_t s)
                                                        if ((osdmode & 8) == 8) { UiState("xjadeo-window-osd-box-on"); }
                                                        if ((osdmode & 8) == 0) { UiState("xjadeo-window-osd-box-off"); }
                                                }
+                                               starting &= ~1;
                                                xjadeo_settings["osd mode"] = value;
                                        } else if(key ==  "offset") {
+                                               knownstate |= 64;
+                                               if (xjadeo_settings["set offset"] != value) {
+                                                       if (!starting && _session) _session->set_dirty ();
+                                               }
                                                xjadeo_settings["set offset"] = value;
                                        }
                                }
@@ -321,7 +354,6 @@ void
 VideoMonitor::terminated ()
 {
        process->terminate(); // from gui-context clean up
-       save_session();
        Terminated();
 }
 
@@ -329,35 +361,13 @@ void
 VideoMonitor::save_session ()
 {
        if (!_session) { return; }
-       bool is_dirty = false;
-
-       XMLNode* prev = _session->extra_xml (X_("XJSettings"));
-       XMLNode* node = new XMLNode(X_("XJSettings"));
-       XMLNodeList nlist;
-       if (!prev) { is_dirty = true; }
-       else { nlist = prev->children(); }
+       XMLNode* node = _session->extra_xml (X_("XJSettings"));
+       if (!node) return;
 
        for(XJSettings::const_iterator it = xjadeo_settings.begin(); it != xjadeo_settings.end(); ++it) {
          XMLNode* child = node->add_child (X_("XJSetting"));
                child->add_property (X_("k"), it->first);
                child->add_property (X_("v"), it->second);
-               if (!is_dirty) {
-                       bool found = false;
-                       XMLNodeConstIterator i;
-                       for (i = nlist.begin(); i != nlist.end(); ++i) {
-                               if ((*i)->property(X_("k"))->value() == it->first &&
-                                   (*i)->property(X_("v"))->value() == it->second ) {
-                                       found=true;
-                                       break;
-                               }
-                       }
-                       if (!found) {is_dirty = true;}
-               }
-       }
-
-       if (is_dirty) {
-         _session->add_extra_xml (*node);
-         _session->set_dirty ();
        }
 }
 
index be3b76f9a47340741355275d356893c09c8e98e1..0f954e9cd5c3cf5de467fd7d12ff5a2bf565614e 100644 (file)
@@ -62,7 +62,9 @@ class VideoMonitor : public sigc::trackable , public ARDOUR::SessionHandlePtr, p
        void open (std::string);
 
        void set_session (ARDOUR::Session *s);
+       void save_session ();
        void clear_session_state ();
+       void query_full_state (bool);
        bool set_custom_setting (const std::string, const std::string);
        const std::string get_custom_setting (const std::string);
        void restore_settings_mask (int i)  { _restore_settings_mask = i;}
@@ -89,7 +91,6 @@ class VideoMonitor : public sigc::trackable , public ARDOUR::SessionHandlePtr, p
        void parse_output (std::string d, size_t s);
        void terminated ();
 
-       void save_session ();
        void parameter_changed (std::string const & p);
 
        typedef std::map<std::string,std::string> XJSettings;
@@ -105,6 +106,7 @@ class VideoMonitor : public sigc::trackable , public ARDOUR::SessionHandlePtr, p
        sigc::connection state_connection;
        int state_clk_divide;
        int starting;
+       int knownstate;
        int osdmode;
 #if 1
        bool debug_enable;
index 563a6a366ebfcbbfbcf7a6d36c9a84434da5c947..78b5f0345da819373ceb7948a72f0e5b60eb51cd 100644 (file)
@@ -89,63 +89,23 @@ VideoTimeLine::save_session ()
 
        LocaleGuard lg (X_("POSIX"));
 
-       bool is_dirty = false;
-
-       XMLNode* prev = _session->extra_xml (X_("Videomonitor"));
-
-       /* remember if vmonitor was open.. */
        XMLNode* node = new XMLNode(X_("Videomonitor"));
-
+       if (!node) return;
        node->add_property (X_("active"), (vmonitor && vmonitor->is_started())?"yes":"no");
-       if (!prev || !(prev->property (X_("active")) && prev->property (X_("active"))->value() == node->property(X_("active"))->value()) ){
-               _session->add_extra_xml (*node);
-               is_dirty=true; // TODO not if !prev && value==default
+       _session->add_extra_xml (*node);
+
+       if (vmonitor) {
+               vmonitor->save_session();
        }
 
        /* VTL settings */
        node = _session->extra_xml (X_("Videotimeline"));
-
-       if (node) {
-               if (!(node->property(X_("id")) && node->property(X_("id"))->value() == id().to_s())) {
-                       node->add_property (X_("id"), id().to_s());
-                       is_dirty=true;
-               }
-       }
-
-       /* remember timeline height.. */
-       if (node) {
-               int h = editor->get_videotl_bar_height();
-               if (!(node->property(X_("Height")) && atoi(node->property(X_("Height"))->value().c_str())==h)) {
-                       node->add_property (X_("Height"), h);
-                       is_dirty=true;
-               }
-       }
-
-       /* save video-offset-lock */
-       if (node) {
-               if (!(node->property(X_("VideoOffsetLock")) && atoi(node->property(X_("VideoOffsetLock"))->value().c_str())==video_offset_lock)) {
-                       node->add_property (X_("VideoOffsetLock"), video_offset_lock?X_("1"):X_("0"));
-                       is_dirty=true;
-               }
-       }
-       /* save video-offset */
-       if (node) {
-               if (!(node->property(X_("VideoOffset")) && atoll(node->property(X_("VideoOffset"))->value().c_str())==video_offset)) {
-                       node->add_property (X_("VideoOffset"), video_offset);
-                       is_dirty=true;
-               }
-       }
-
-       /* save 'auto_set_session_fps' */
-       if (node) {
-               if (!(node->property(X_("AutoFPS")) && atoi(node->property(X_("AutoFPS"))->value().c_str())==auto_set_session_fps)) {
-                       node->add_property (X_("AutoFPS"), auto_set_session_fps?X_("1"):X_("0"));
-                       is_dirty=true;
-               }
-       }
-       if (is_dirty) {
-               _session->set_dirty ();
-       }
+       if (!node) return;
+       node->add_property (X_("id"), id().to_s());
+       node->add_property (X_("Height"), editor->get_videotl_bar_height());
+       node->add_property (X_("VideoOffsetLock"), video_offset_lock?X_("1"):X_("0"));
+       node->add_property (X_("VideoOffset"), video_offset);
+       node->add_property (X_("AutoFPS"), auto_set_session_fps?X_("1"):X_("0"));
 }
 
 /* close and save settings */
@@ -156,7 +116,6 @@ VideoTimeLine::close_session ()
                return;
        }
        sessionsave.disconnect();
-       save_session();
        close_video_monitor();
 
        remove_frames();
@@ -165,6 +124,16 @@ VideoTimeLine::close_session ()
        GuiUpdate("set-xjadeo-sensitive-off");
 }
 
+void
+VideoTimeLine::sync_session_state ()
+{
+       if (!_session || !vmonitor || !vmonitor->is_started()) {
+               return;
+       }
+       vmonitor->query_full_state(true);
+       save_session();
+}
+
 /** load settings from session */
 void
 VideoTimeLine::set_session (ARDOUR::Session *s)
@@ -762,6 +731,17 @@ VideoTimeLine::open_video_monitor() {
                GuiUpdate("set-xjadeo-active-on");
                vmonitor->set_fps(video_file_fps);
                vmonitor->open(video_filename);
+
+               if (_session) {
+                       XMLNode* node = _session->extra_xml (X_("Videomonitor"));
+                       if (node) {
+                               const XMLProperty* prop = node->property (X_("active"));
+                               if (prop && prop->value() != "yes") _session->set_dirty ();
+                       } else {
+                               _session->set_dirty ();
+                       }
+               }
+
        }
 }
 
@@ -788,9 +768,13 @@ VideoTimeLine::terminated_video_monitor () {
        }
        GuiUpdate("set-xjadeo-active-off");
        vmonitor=0;
-  if (reopen_vmonitor) {
+       if (reopen_vmonitor) {
                reopen_vmonitor=false;
                open_video_monitor();
+       } else {
+               if (_session) {
+                       _session->set_dirty ();
+               }
        }
 }
 
index 4bc3eb86c70fce593dcbbe18e2ab46c683ab0133..b80faa3b27cb20e07339c0b7c9fdf45fb3a3fb1f 100644 (file)
@@ -93,6 +93,7 @@ class VideoTimeLine : public sigc::trackable, public ARDOUR::SessionHandlePtr, p
        void flush_cache ();
        void save_session ();
        void close_session ();
+       void sync_session_state (); /* video-monitor does not actively report window/pos changes, query it */
        float get_apv(); /* audio frames per video frame; */
        ARDOUR::framecnt_t get_duration () { return video_duration;}
        ARDOUR::frameoffset_t get_offset () { return video_offset;}