vtl: video-monitor interaction
authorRobin Gareus <robin@gareus.org>
Wed, 3 Apr 2013 20:29:04 +0000 (22:29 +0200)
committerRobin Gareus <robin@gareus.org>
Wed, 3 Apr 2013 20:29:37 +0000 (22:29 +0200)
* Menu > View > Video Monitor -- bi-directional communication
with xjadeo for window-state and OSD.
* fix saving state on session close (wait for xjadeo to terminate)

gtk2_ardour/ardour.menus.in
gtk2_ardour/editor.h
gtk2_ardour/editor_actions.cc
gtk2_ardour/public_editor.h
gtk2_ardour/system_exec.cc
gtk2_ardour/video_monitor.cc
gtk2_ardour/video_monitor.h
gtk2_ardour/video_timeline.cc
gtk2_ardour/video_timeline.h

index 608f4dd6e4f4147426f1aeca897778eab1b7b565..f101a9dc4fcf6c2552eef86efc7ceae91504cbaa 100644 (file)
 #ifdef WITH_VIDEOTIMELINE
         <separator/>
         <menuitem action="toggle-video-ruler"/>
+      </menu>
+      <menu action="VideoMonitorMenu">
+        <menuitem action="toggle-vmon-ontop"/>
+        <menuitem action="toggle-vmon-timecode"/>
+        <menuitem action="toggle-vmon-frame"/>
+        <menuitem action="toggle-vmon-osdbg"/>
+        <menuitem action="toggle-vmon-fullscreen"/>
 #endif
       </menu>
       <menu action="ScrollMenu">
index 6155dea745b4cf0972d623f751d5c173a93ae539..c287a259eaa5bc29012d6de4d10bf0e532a20a0d 100644 (file)
@@ -928,9 +928,16 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
        ArdourCanvas::Group*      videotl_group;
        Glib::RefPtr<Gtk::ToggleAction> ruler_video_action;
        Glib::RefPtr<Gtk::ToggleAction> xjadeo_proc_action;
+       Glib::RefPtr<Gtk::ToggleAction> xjadeo_ontop_action;
+       Glib::RefPtr<Gtk::ToggleAction> xjadeo_timecode_action;
+       Glib::RefPtr<Gtk::ToggleAction> xjadeo_frame_action;
+       Glib::RefPtr<Gtk::ToggleAction> xjadeo_osdbg_action;
+       Glib::RefPtr<Gtk::ToggleAction> xjadeo_fullscreen_action;
        void set_xjadeo_proc ();
        void toggle_xjadeo_proc (int state=-1);
        void set_xjadeo_sensitive (bool onoff);
+       void set_xjadeo_viewoption (int);
+       void toggle_xjadeo_viewoption (int what, int state=-1);
        void toggle_ruler_video (bool onoff) {ruler_video_action->set_active(onoff);}
        int videotl_bar_height; /* in units of timebar_height; default: 4 */
        int get_videotl_bar_height () const { return videotl_bar_height; }
index a8c381cd5f3c3700c65e1866c06f7130fd9672a4..8c81a6122e83df2c2d6d3d0d1ac5e384d34abab3 100644 (file)
@@ -544,8 +544,17 @@ Editor::register_actions ()
        ruler_timecode_action = Glib::RefPtr<ToggleAction>::cast_static (ActionManager::register_toggle_action (ruler_actions, X_("toggle-timecode-ruler"), _("Timecode"), sigc::bind (sigc::mem_fun(*this, &Editor::toggle_ruler_visibility), ruler_metric_timecode)));
        ruler_minsec_action = Glib::RefPtr<ToggleAction>::cast_static (ActionManager::register_toggle_action (ruler_actions, X_("toggle-minsec-ruler"), _("Min:Sec"), sigc::bind (sigc::mem_fun(*this, &Editor::toggle_ruler_visibility), ruler_metric_minsec)));
 #ifdef WITH_VIDEOTIMELINE
+
+       ActionManager::register_action (editor_menu_actions, X_("VideoMonitorMenu"), _("Video Monitor"));
+
        ruler_video_action = Glib::RefPtr<ToggleAction>::cast_static (ActionManager::register_toggle_action (ruler_actions, X_("toggle-video-ruler"), _("Video"), sigc::bind (sigc::mem_fun(*this, &Editor::toggle_ruler_visibility), ruler_video_timeline)));
-       xjadeo_proc_action = Glib::RefPtr<ToggleAction>::cast_static (ActionManager::register_toggle_action (editor_actions, X_("ToggleJadeo"), _("Show Video Monitor"), sigc::mem_fun (*this, &Editor::set_xjadeo_proc)));
+       xjadeo_proc_action = Glib::RefPtr<ToggleAction>::cast_static (ActionManager::register_toggle_action (editor_actions, X_("ToggleJadeo"), _("Video Monitor"), sigc::mem_fun (*this, &Editor::set_xjadeo_proc)));
+
+       xjadeo_ontop_action = Glib::RefPtr<ToggleAction>::cast_static (ActionManager::register_toggle_action (editor_actions, X_("toggle-vmon-ontop"), _("Always on Top"), sigc::bind (sigc::mem_fun (*this, &Editor::set_xjadeo_viewoption), (int) 1)));
+       xjadeo_timecode_action = Glib::RefPtr<ToggleAction>::cast_static (ActionManager::register_toggle_action (editor_actions, X_("toggle-vmon-timecode"), _("Timecode"), sigc::bind (sigc::mem_fun (*this, &Editor::set_xjadeo_viewoption), (int) 2)));
+       xjadeo_frame_action = Glib::RefPtr<ToggleAction>::cast_static (ActionManager::register_toggle_action (editor_actions, X_("toggle-vmon-frame"), _("Framenumber"), sigc::bind (sigc::mem_fun (*this, &Editor::set_xjadeo_viewoption), (int) 3)));
+       xjadeo_osdbg_action = Glib::RefPtr<ToggleAction>::cast_static (ActionManager::register_toggle_action (editor_actions, X_("toggle-vmon-osdbg"), _("Timecode Background"), sigc::bind (sigc::mem_fun (*this, &Editor::set_xjadeo_viewoption), (int) 4)));
+       xjadeo_fullscreen_action = Glib::RefPtr<ToggleAction>::cast_static (ActionManager::register_toggle_action (editor_actions, X_("toggle-vmon-fullscreen"), _("Fullscreen"), sigc::bind (sigc::mem_fun (*this, &Editor::set_xjadeo_viewoption), (int) 5)));
 
 #endif
 
@@ -562,6 +571,16 @@ Editor::register_actions ()
        ruler_video_action->set_active (false);
        xjadeo_proc_action->set_active (false);
        xjadeo_proc_action->set_sensitive (false);
+       xjadeo_ontop_action->set_active (false);
+       xjadeo_ontop_action->set_sensitive (false);
+       xjadeo_timecode_action->set_active (false);
+       xjadeo_timecode_action->set_sensitive (false);
+       xjadeo_frame_action->set_active (false);
+       xjadeo_frame_action->set_sensitive (false);
+       xjadeo_osdbg_action->set_active (false);
+       xjadeo_osdbg_action->set_sensitive (false);
+       xjadeo_fullscreen_action->set_active (false);
+       xjadeo_fullscreen_action->set_sensitive (false);
 #endif
        if (Profile->get_sae()) {
                ruler_bbt_action->set_active (true);
@@ -760,6 +779,7 @@ Editor::set_xjadeo_sensitive (bool onoff)
 {
        xjadeo_proc_action->set_sensitive(onoff);
 }
+
 void
 Editor::toggle_xjadeo_proc (int state)
 {
@@ -774,6 +794,12 @@ Editor::toggle_xjadeo_proc (int state)
                        xjadeo_proc_action->set_active(!xjadeo_proc_action->get_active());
                        break;
        }
+       bool onoff = xjadeo_proc_action->get_active();
+       xjadeo_ontop_action->set_sensitive(onoff);
+       xjadeo_timecode_action->set_sensitive(onoff);
+       xjadeo_frame_action->set_sensitive(onoff);
+       xjadeo_osdbg_action->set_sensitive(onoff);
+       xjadeo_fullscreen_action->set_sensitive(onoff);
 }
 
 void
@@ -785,6 +811,73 @@ Editor::set_xjadeo_proc ()
                ARDOUR_UI::instance()->video_timeline->close_video_monitor();
        }
 }
+
+void
+Editor::toggle_xjadeo_viewoption (int what, int state)
+{
+       Glib::RefPtr<Gtk::ToggleAction> action;
+       switch (what) {
+               case 1:
+                       action = xjadeo_ontop_action;
+                       break;
+               case 2:
+                       action = xjadeo_timecode_action;
+                       break;
+               case 3:
+                       action = xjadeo_frame_action;
+                       break;
+               case 4:
+                       action = xjadeo_osdbg_action;
+                       break;
+               case 5:
+                       action = xjadeo_fullscreen_action;
+                       break;
+               default:
+                       return;
+       }
+
+       switch(state) {
+               case 1:
+                       action->set_active(true);
+                       break;
+               case 0:
+                       action->set_active(false);
+                       break;
+               default:
+                       action->set_active(!action->get_active());
+                       break;
+       }
+}
+
+void
+Editor::set_xjadeo_viewoption (int what)
+{
+       Glib::RefPtr<Gtk::ToggleAction> action;
+       switch (what) {
+               case 1:
+                       action = xjadeo_ontop_action;
+                       break;
+               case 2:
+                       action = xjadeo_timecode_action;
+                       break;
+               case 3:
+                       action = xjadeo_frame_action;
+                       break;
+               case 4:
+                       action = xjadeo_osdbg_action;
+                       break;
+               case 5:
+                       action = xjadeo_fullscreen_action;
+                       break;
+               default:
+                       return;
+       }
+       if (action->get_active()) {
+               ARDOUR_UI::instance()->video_timeline->control_video_monitor(what, 1);
+       } else {
+               ARDOUR_UI::instance()->video_timeline->control_video_monitor(what, 0);
+       }
+}
 #endif
 
 void
index 0dabc5f5e8e1bc0e741179e9b4145fa40c98cc2e..ce21b8a40dd2779d9d35d48bfbf0ff64c59bbe3a 100644 (file)
@@ -296,6 +296,7 @@ class PublicEditor : public Gtk::Window, public PBD::StatefulDestructible {
        virtual void queue_visual_videotimeline_update () = 0;
        virtual void toggle_ruler_video (bool) = 0;
        virtual void toggle_xjadeo_proc (int) = 0;
+       virtual void toggle_xjadeo_viewoption (int, int) = 0;
        virtual void set_xjadeo_sensitive (bool onoff) = 0;
        virtual int  get_videotl_bar_height () const = 0;
        virtual void set_video_timeline_height (const int h) = 0;
index 00b212710e63392a610d702523b9eac09c0fc83f..3af660ef77b60889f362796664bd133099f89a12 100644 (file)
@@ -418,7 +418,7 @@ SystemExec::terminate ()
        if (pid) {
                ::fprintf(stderr, "Child process is running. trying SIGTERM\n");
                ::kill(pid, SIGTERM);
-               ::usleep(10000);
+               ::usleep(50000);
                wait(WNOHANG);
        }
        if (pid) {
index f29712e326a570bd9a9ba6d570a80b1ec87c5c26..fabe4201dd61dd6d5f5227bb047227c9ebcbcc6d 100644 (file)
@@ -39,10 +39,14 @@ VideoMonitor::VideoMonitor (PublicEditor *ed, std::string xjadeo_bin_path)
        sync_by_manual_seek = false;
        _restore_settings_mask = 0;
        clock_connection = sigc::connection();
+       state_connection = sigc::connection();
        debug_enable = false;
+       state_clk_divide = 0;
+       starting = 0;
+       osdmode = 10; // 1: frameno, 2: timecode, 8: box
 
        process = new SystemExec(xjadeo_bin_path, X_("-R"));
-       process->ReadStdout.connect (*this, invalidator (*this), boost::bind (&VideoMonitor::parse_output, this, _1 ,_2), gui_context());
+       process->ReadStdout.connect_same_thread (*this, boost::bind (&VideoMonitor::parse_output, this, _1 ,_2));
        process->Terminated.connect (*this, invalidator (*this), boost::bind (&VideoMonitor::terminated, this), gui_context());
 }
 
@@ -51,6 +55,9 @@ VideoMonitor::~VideoMonitor ()
        if (clock_connection.connected()) {
                clock_connection.disconnect();
        }
+       if (state_connection.connected()) {
+               state_connection.disconnect();
+       }
        delete process;
 }
 
@@ -75,6 +82,8 @@ 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("get windowsize\n");
        process->write_to_stdin("get windowpos\n");
        process->write_to_stdin("get letterbox\n");
@@ -92,13 +101,14 @@ VideoMonitor::quit ()
        int timeout = 40;
        while (is_started() && --timeout) {
                usleep(50000);
+               sched_yield();
        }
-       if (timeout == 0) {
+       if (timeout <= 0) {
                printf("xjadeo connection: time-out. session may not be saved.\n");
+               process->terminate();
        }
 #endif
-       process->terminate();
-       if (clock_connection.connected()) { clock_connection.disconnect(); }
+       save_session();
 }
 
 void
@@ -106,7 +116,9 @@ VideoMonitor::open (std::string filename)
 {
        if (!is_started()) return;
        manually_seeked_frame = 0;
+       osdmode = 10; // 1: frameno, 2: timecode, 8: box
        sync_by_manual_seek = false;
+       starting = 7;
        process->write_to_stdin("load " + filename + "\n");
        process->write_to_stdin("set fps -1\n");
        process->write_to_stdin("window resize 100%\n");
@@ -119,9 +131,29 @@ VideoMonitor::open (std::string filename)
                if (skip_setting(it->first)) { continue; }
                process->write_to_stdin(it->first + " " + it->second + "\n");
        }
+       if (!state_connection.connected()) {
+               starting = 7;
+               querystate();
+               state_clk_divide = 0;
+               /* TODO once every two second or so -- state_clk_divide hack below */
+               state_connection = ARDOUR_UI::RapidScreenUpdate.connect (sigc::mem_fun (*this, &VideoMonitor::querystate));
+       }
        xjadeo_sync_setup();
 }
 
+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;
+
+       process->write_to_stdin("get fullscreen\n");
+       process->write_to_stdin("get ontop\n");
+       process->write_to_stdin("get osdcfg\n");
+       process->write_to_stdin("get letterbox\n");
+}
+
 bool
 VideoMonitor::skip_setting (std::string which)
 {
@@ -136,6 +168,44 @@ VideoMonitor::skip_setting (std::string which)
        return false;
 }
 
+void
+VideoMonitor::send_cmd (int what, int param)
+{
+       bool osd_update = false;
+       if (!is_started()) return;
+       switch (what) {
+               case 1:
+                       if (param) process->write_to_stdin("window ontop on\n");
+                       else process->write_to_stdin("window ontop off\n");
+                       break;
+               case 2:
+                       if (param) osdmode |= 2;
+                       else osdmode &= ~2;
+                       osd_update = true;
+                       break;
+               case 3:
+                       if (param) osdmode |= 1;
+                       else osdmode &= ~1;
+                       osd_update = true;
+                       break;
+               case 4:
+                       if (param) osdmode |= 8;
+                       else osdmode &= ~8;
+                       osd_update = true;
+                       break;
+               case 5:
+                       if (param) process->write_to_stdin("window zoom on\n");
+                       else process->write_to_stdin("window zoom off\n");
+                       break;
+               default:
+                       break;
+       }
+       if (osd_update >= 0) {
+               std::ostringstream osstream; osstream << "osd mode " << osdmode << "\n";
+               process->write_to_stdin(osstream.str());
+       }
+}
+
 bool
 VideoMonitor::is_started ()
 {
@@ -196,12 +266,32 @@ VideoMonitor::parse_output (std::string d, size_t s)
                                        } else if(key ==  "windowsize") {
                                                xjadeo_settings["window size"] = value;
                                        } else if(key ==  "windowontop") {
+                                               if (starting || xjadeo_settings["window ontop"] != value) {
+                                                       starting &= ~2;
+                                                       if (atoi(value.c_str())) { UiState("xjadeo-window-ontop-on"); }
+                                                       else { UiState("xjadeo-window-ontop-off"); }
+                                               }
                                                xjadeo_settings["window ontop"] = value;
                                        } else if(key ==  "fullscreen") {
+                                               if (starting || xjadeo_settings["window zoom"] != value) {
+                                                       starting &= ~4;
+                                                       if (atoi(value.c_str())) { UiState("xjadeo-window-fullscreen-on"); }
+                                                       else { UiState("xjadeo-window-fullscreen-off"); }
+                                               }
                                                xjadeo_settings["window zoom"] = value;
                                        } else if(key ==  "letterbox") {
                                                xjadeo_settings["window letterbox"] = value;
                                        } else if(key ==  "osdmode") {
+                                               if (starting || xjadeo_settings["osd mode"] != value) {
+                                                       starting &= ~1;
+                                                       osdmode = atoi(value.c_str());
+                                                       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"); }
+                                                       if ((osdmode & 2) == 0) { UiState("xjadeo-window-osd-timecode-off"); }
+                                                       if ((osdmode & 8) == 8) { UiState("xjadeo-window-osd-box-on"); }
+                                                       if ((osdmode & 8) == 0) { UiState("xjadeo-window-osd-box-off"); }
+                                               }
                                                xjadeo_settings["osd mode"] = value;
                                        } else if(key ==  "offset") {
                                                xjadeo_settings["set offset"] = value;
@@ -218,6 +308,7 @@ VideoMonitor::parse_output (std::string d, size_t s)
 void
 VideoMonitor::terminated ()
 {
+       process->terminate(); // from gui-context clean up
        save_session();
        Terminated();
 }
@@ -298,6 +389,7 @@ VideoMonitor::get_custom_setting (const std::string k)
 {
        return (xjadeo_settings[k]);
 }
+
 #define NO_OFFSET (1<<31) //< skip setting or modifying offset --  TODO check ARDOUR::frameoffset_t max value.
 void
 VideoMonitor::srsupdate ()
index 7bb74c7e05561262ff48cb65108f92eda96521ab..be3b76f9a47340741355275d356893c09c8e98e1 100644 (file)
@@ -71,9 +71,12 @@ class VideoMonitor : public sigc::trackable , public ARDOUR::SessionHandlePtr, p
        void set_offset (ARDOUR::frameoffset_t);
        void manual_seek (ARDOUR::framepos_t, bool, ARDOUR::frameoffset_t);
        void srsupdate ();
+       void querystate ();
        bool synced_by_manual_seeks() { return sync_by_manual_seek; }
 
        sigc::signal<void> Terminated;
+       PBD::Signal1<void,std::string> UiState;
+       void send_cmd (int what, int param);
 
 #if 1
        void set_debug (bool onoff) { debug_enable = onoff; }
@@ -99,6 +102,10 @@ class VideoMonitor : public sigc::trackable , public ARDOUR::SessionHandlePtr, p
        ARDOUR::framepos_t manually_seeked_frame;
        bool sync_by_manual_seek;
        sigc::connection clock_connection;
+       sigc::connection state_connection;
+       int state_clk_divide;
+       int starting;
+       int osdmode;
 #if 1
        bool debug_enable;
 #endif
index dd47a829709256b208a4185e7641af44f9524198..d68df6bc2f00162c518b826a72d5159cf244d50f 100644 (file)
@@ -155,8 +155,8 @@ VideoTimeLine::close_session ()
        if (video_duration == 0) {
                return;
        }
-       close_video_monitor();
        save_session();
+       close_video_monitor();
 
        remove_frames();
        video_filename = "";
@@ -581,6 +581,26 @@ VideoTimeLine::gui_update(std::string const & t) {
                editor->toggle_xjadeo_proc(0);
                //close_video_monitor();
                editor->set_xjadeo_sensitive(false);
+       } else if (t == "xjadeo-window-ontop-on") {
+               editor->toggle_xjadeo_viewoption(1, 1);
+       } else if (t == "xjadeo-window-ontop-off") {
+               editor->toggle_xjadeo_viewoption(1, 0);
+       } else if (t == "xjadeo-window-osd-timecode-on") {
+               editor->toggle_xjadeo_viewoption(2, 1);
+       } else if (t == "xjadeo-window-osd-timecode-off") {
+               editor->toggle_xjadeo_viewoption(2, 0);
+       } else if (t == "xjadeo-window-osd-frame-on") {
+               editor->toggle_xjadeo_viewoption(3, 1);
+       } else if (t == "xjadeo-window-osd-frame-off") {
+               editor->toggle_xjadeo_viewoption(3, 0);
+       } else if (t == "xjadeo-window-osd-box-on") {
+               editor->toggle_xjadeo_viewoption(4, 1);
+       } else if (t == "xjadeo-window-osd-box-off") {
+               editor->toggle_xjadeo_viewoption(4, 0);
+       } else if (t == "xjadeo-window-fullscreen-on") {
+               editor->toggle_xjadeo_viewoption(5, 1);
+       } else if (t == "xjadeo-window-fullscreen-off") {
+               editor->toggle_xjadeo_viewoption(5, 0);
        }
 }
 
@@ -688,6 +708,7 @@ VideoTimeLine::open_video_monitor() {
                vmonitor = new VideoMonitor(editor, _xjadeo_bin);
                vmonitor->set_session(_session);
                vmonitor->Terminated.connect (sigc::mem_fun (*this, &VideoTimeLine::terminated_video_monitor));
+               vmonitor->UiState.connect (*this, invalidator (*this), boost::bind (&VideoTimeLine::gui_update, this, _1), gui_context());
        } else if (vmonitor->is_started()) {
                return;
        }
@@ -723,6 +744,15 @@ VideoTimeLine::close_video_monitor() {
        }
 }
 
+void
+VideoTimeLine::control_video_monitor(int what, int param) {
+       if (!vmonitor || !vmonitor->is_started()) {
+               return;
+       }
+       vmonitor->send_cmd(what, param);
+}
+
+
 void
 VideoTimeLine::terminated_video_monitor () {
        if (vmonitor) {
index ef889af452d140b9fa23866dd5a81506942797ce..ab1a9a92d85e0b85799edc0116ec7974ee742cf1 100644 (file)
@@ -78,6 +78,7 @@ class VideoTimeLine : public sigc::trackable, public ARDOUR::SessionHandlePtr, p
 
        void open_video_monitor ();
        void close_video_monitor ();
+       void control_video_monitor (int, int);
        void terminated_video_monitor ();
        void manual_seek_video_monitor (framepos_t pos);