[chronojump] New feature! Webcam working on encoder!



commit ab2eca57f6258164323f766b2d8ee42968e56ac7
Author: Xavier de Blas <xaviblas gmail com>
Date:   Fri Mar 15 16:36:19 2019 +0100

    New feature! Webcam working on encoder!

 glade/app1.glade           | 194 ++++++++++++++--
 src/gui/chronojump.cs      | 480 ++-------------------------------------
 src/gui/chronojumpIcons.cs |   6 +-
 src/gui/encoder.cs         |  86 +++----
 src/gui/networks.cs        |   2 +
 src/gui/webcam.cs          | 543 ++++++++++++++++++++++++++++++++++++++++++++-
 src/webcam.cs              |  17 +-
 src/webcamFfmpeg.cs        |   5 +-
 src/webcamMplayer.cs       |   5 +-
 9 files changed, 783 insertions(+), 555 deletions(-)
---
diff --git a/glade/app1.glade b/glade/app1.glade
index c4ee4854..740671d7 100644
--- a/glade/app1.glade
+++ b/glade/app1.glade
@@ -1869,6 +1869,12 @@
                                                             <placeholder/>
                                                             </child>
                                                             <child>
+                                                            <placeholder/>
+                                                            </child>
+                                                            <child>
+                                                            <placeholder/>
+                                                            </child>
+                                                            <child>
                                                             <widget class="GtkLabel" 
id="label_start_selector_jumps">
                                                             <property name="visible">True</property>
                                                             <property name="can_focus">False</property>
@@ -20440,18 +20446,6 @@ Concentric</property>
                                                             <placeholder/>
                                                             </child>
                                                             <child>
-                                                            <placeholder/>
-                                                            </child>
-                                                            <child>
-                                                            <placeholder/>
-                                                            </child>
-                                                            <child>
-                                                            <placeholder/>
-                                                            </child>
-                                                            <child>
-                                                            <placeholder/>
-                                                            </child>
-                                                            <child>
                                                             <widget class="GtkCheckButton" 
id="checkbutton_force_sensor_ai_b">
                                                             <property name="width_request">30</property>
                                                             <property name="visible">True</property>
@@ -20615,6 +20609,12 @@ Concentric</property>
                                                             <child>
                                                             <placeholder/>
                                                             </child>
+                                                            <child>
+                                                            <placeholder/>
+                                                            </child>
+                                                            <child>
+                                                            <placeholder/>
+                                                            </child>
                                                             </widget>
                                                             <packing>
                                                             <property name="expand">False</property>
@@ -22493,7 +22493,160 @@ Concentric</property>
                                                           </packing>
                                                         </child>
                                                         <child>
-                                                          <placeholder/>
+                                                          <widget class="GtkAlignment" id="alignment45">
+                                                            <property name="visible">True</property>
+                                                            <property name="can_focus">False</property>
+                                                            <property name="right_padding">6</property>
+                                                            <child>
+                                                            <widget class="GtkHBox" id="hbox_video_encoder">
+                                                            <property name="visible">True</property>
+                                                            <property name="can_focus">False</property>
+                                                            <property name="spacing">6</property>
+                                                            <child>
+                                                            <widget class="GtkHBox" 
id="hbox_video_encoder_capturing">
+                                                            <property name="can_focus">False</property>
+                                                            <property name="spacing">4</property>
+                                                            <child>
+                                                            <widget class="GtkImage" 
id="image_video_encoder_yes1">
+                                                            <property name="visible">True</property>
+                                                            <property name="can_focus">False</property>
+                                                            <property 
name="stock">gtk-missing-image</property>
+                                                            <property name="icon-size">1</property>
+                                                            </widget>
+                                                            <packing>
+                                                            <property name="expand">False</property>
+                                                            <property name="fill">False</property>
+                                                            <property name="position">0</property>
+                                                            </packing>
+                                                            </child>
+                                                            <child>
+                                                            <widget class="GtkLabel" 
id="label_video_encoder_feedback">
+                                                            <property name="visible">True</property>
+                                                            <property name="can_focus">False</property>
+                                                            </widget>
+                                                            <packing>
+                                                            <property name="expand">False</property>
+                                                            <property name="fill">False</property>
+                                                            <property name="position">1</property>
+                                                            </packing>
+                                                            </child>
+                                                            </widget>
+                                                            <packing>
+                                                            <property name="expand">False</property>
+                                                            <property name="fill">False</property>
+                                                            <property name="pack_type">end</property>
+                                                            <property name="position">0</property>
+                                                            </packing>
+                                                            </child>
+                                                            <child>
+                                                            <widget class="GtkHBox" 
id="hbox_video_encoder_no_capturing">
+                                                            <property name="visible">True</property>
+                                                            <property name="can_focus">False</property>
+                                                            <property name="spacing">6</property>
+                                                            <child>
+                                                            <widget class="GtkCheckButton" 
id="checkbutton_video_encoder">
+                                                            <property name="visible">True</property>
+                                                            <property name="can_focus">True</property>
+                                                            <property 
name="receives_default">False</property>
+                                                            <property name="has_tooltip">True</property>
+                                                            <property name="tooltip" 
translatable="yes">Record video (on / off)</property>
+                                                            <property name="active">True</property>
+                                                            <property name="draw_indicator">False</property>
+                                                            <signal name="clicked" 
handler="on_checkbutton_video_encoder_clicked" swapped="no"/>
+                                                            <child>
+                                                            <widget class="GtkHBox" id="hbox322">
+                                                            <property name="visible">True</property>
+                                                            <property name="can_focus">False</property>
+                                                            <property name="spacing">2</property>
+                                                            <child>
+                                                            <widget class="GtkImage" 
id="image_video_encoder_yes">
+                                                            <property name="visible">True</property>
+                                                            <property name="can_focus">False</property>
+                                                            <property 
name="stock">gtk-missing-image</property>
+                                                            <property name="icon-size">1</property>
+                                                            </widget>
+                                                            <packing>
+                                                            <property name="expand">False</property>
+                                                            <property name="fill">False</property>
+                                                            <property name="position">0</property>
+                                                            </packing>
+                                                            </child>
+                                                            <child>
+                                                            <widget class="GtkImage" 
id="image_video_encoder_no">
+                                                            <property name="visible">True</property>
+                                                            <property name="can_focus">False</property>
+                                                            <property 
name="stock">gtk-missing-image</property>
+                                                            <property name="icon-size">1</property>
+                                                            </widget>
+                                                            <packing>
+                                                            <property name="expand">False</property>
+                                                            <property name="fill">False</property>
+                                                            <property name="position">1</property>
+                                                            </packing>
+                                                            </child>
+                                                            </widget>
+                                                            </child>
+                                                            </widget>
+                                                            <packing>
+                                                            <property name="expand">False</property>
+                                                            <property name="fill">False</property>
+                                                            <property name="position">0</property>
+                                                            </packing>
+                                                            </child>
+                                                            <child>
+                                                            <widget class="GtkButton" 
id="button_video_encoder_preview">
+                                                            <property name="label" 
translatable="yes">Preview</property>
+                                                            <property name="can_focus">True</property>
+                                                            <property name="receives_default">True</property>
+                                                            <property name="tooltip" 
translatable="yes">Preview video</property>
+                                                            <signal name="clicked" 
handler="on_button_video_encoder_preview_clicked" swapped="no"/>
+                                                            </widget>
+                                                            <packing>
+                                                            <property name="expand">False</property>
+                                                            <property name="fill">False</property>
+                                                            <property name="position">1</property>
+                                                            </packing>
+                                                            </child>
+                                                            <child>
+                                                            <widget class="GtkButton" 
id="button_video_play_this_test_encoder">
+                                                            <property name="visible">True</property>
+                                                            <property name="can_focus">True</property>
+                                                            <property name="receives_default">True</property>
+                                                            <property name="has_tooltip">True</property>
+                                                            <property name="tooltip" translatable="yes">Play 
Video (v)</property>
+                                                            <signal name="clicked" 
handler="on_button_video_play_this_test_encoder_clicked" swapped="no"/>
+                                                            <accelerator key="v" signal="clicked"/>
+                                                            <child>
+                                                            <widget class="GtkImage" 
id="image_video_play_this_test_encoder">
+                                                            <property name="visible">True</property>
+                                                            <property name="can_focus">False</property>
+                                                            <property 
name="stock">gtk-missing-image</property>
+                                                            <property name="icon-size">1</property>
+                                                            </widget>
+                                                            </child>
+                                                            </widget>
+                                                            <packing>
+                                                            <property name="expand">False</property>
+                                                            <property name="fill">False</property>
+                                                            <property name="position">2</property>
+                                                            </packing>
+                                                            </child>
+                                                            </widget>
+                                                            <packing>
+                                                            <property name="expand">False</property>
+                                                            <property name="fill">False</property>
+                                                            <property name="pack_type">end</property>
+                                                            <property name="position">1</property>
+                                                            </packing>
+                                                            </child>
+                                                            </widget>
+                                                            </child>
+                                                          </widget>
+                                                          <packing>
+                                                            <property name="expand">True</property>
+                                                            <property name="fill">True</property>
+                                                            <property name="position">1</property>
+                                                          </packing>
                                                         </child>
                                                       </widget>
                                                       <packing>
@@ -24463,7 +24616,6 @@ then click this button.</property>
                                                         <child>
                                                           <widget class="GtkAlignment" 
id="alignment_video_encoder">
                                                             <property name="width_request">275</property>
-                                                            <property name="visible">True</property>
                                                             <property name="can_focus">False</property>
                                                             <property name="border_width">4</property>
                                                             <child>
@@ -24488,7 +24640,6 @@ then click this button.</property>
                                                             <property name="tooltip" 
translatable="yes">Record</property>
                                                             <property name="active">True</property>
                                                             <property name="draw_indicator">False</property>
-                                                            <signal name="toggled" 
handler="on_radiobutton_video_encoder_capture_toggled" swapped="no"/>
                                                             <child>
                                                             <widget class="GtkImage" id="image2">
                                                             <property name="visible">True</property>
@@ -24511,7 +24662,6 @@ then click this button.</property>
                                                             <property name="tooltip" 
translatable="yes">Play</property>
                                                             <property name="draw_indicator">False</property>
                                                             <property 
name="group">radiobutton_video_encoder_capture</property>
-                                                            <signal name="toggled" 
handler="on_radiobutton_video_encoder_play_toggled" swapped="no"/>
                                                             <child>
                                                             <widget class="GtkImage" 
id="image_video_encoder_play">
                                                             <property name="visible">True</property>
@@ -24534,7 +24684,6 @@ then click this button.</property>
                                                             <property name="tooltip" 
translatable="yes">Options</property>
                                                             <property name="draw_indicator">False</property>
                                                             <property 
name="group">radiobutton_video_encoder_capture</property>
-                                                            <signal name="toggled" 
handler="on_radiobutton_video_encoder_options_toggled" swapped="no"/>
                                                             <child>
                                                             <widget class="GtkImage" id="image56">
                                                             <property name="visible">True</property>
@@ -24608,14 +24757,13 @@ then click this button.</property>
                                                             <property name="visible">True</property>
                                                             <property name="can_focus">False</property>
                                                             <child>
-                                                            <widget class="GtkCheckButton" 
id="checkbutton_video_encoder">
+                                                            <widget class="GtkCheckButton" 
id="checkbutton_video_encoder_old">
                                                             <property name="label" translatable="yes">Record 
video on capture</property>
                                                             <property name="visible">True</property>
                                                             <property name="can_focus">True</property>
                                                             <property 
name="receives_default">False</property>
                                                             <property name="tooltip" 
translatable="yes">Record video (on / off)</property>
                                                             <property name="draw_indicator">True</property>
-                                                            <signal name="clicked" 
handler="on_checkbutton_video_encoder_clicked" swapped="no"/>
                                                             </widget>
                                                             <packing>
                                                             <property name="expand">False</property>
@@ -24625,7 +24773,7 @@ then click this button.</property>
                                                             </packing>
                                                             </child>
                                                             <child>
-                                                            <widget class="GtkLabel" 
id="label_video_feedback_encoder">
+                                                            <widget class="GtkLabel" 
id="label_video_encoder_feedback_old">
                                                             <property name="visible">True</property>
                                                             <property name="can_focus">False</property>
                                                             <property name="use_markup">True</property>
@@ -28967,6 +29115,12 @@ then click this button.</property>
                                                             <child>
                                                             <placeholder/>
                                                             </child>
+                                                            <child>
+                                                            <placeholder/>
+                                                            </child>
+                                                            <child>
+                                                            <placeholder/>
+                                                            </child>
                                                             </widget>
                                                             <packing>
                                                             <property name="expand">False</property>
diff --git a/src/gui/chronojump.cs b/src/gui/chronojump.cs
index fadc38cb..443829b6 100644
--- a/src/gui/chronojump.cs
+++ b/src/gui/chronojump.cs
@@ -293,14 +293,6 @@ public partial class ChronoJumpWindow
 
        [Widget] Gtk.Label label_threshold;
 
-       [Widget] Gtk.HBox hbox_video_capture;
-       [Widget] Gtk.Label label_video_feedback;
-       [Widget] Gtk.CheckButton checkbutton_video;
-       [Widget] Gtk.Button button_video_preview;
-       //[Widget] Gtk.Label label_video;
-       [Widget] Gtk.Image image_video_yes;
-       [Widget] Gtk.Image image_video_no;
-
        //force sensor
        [Widget] Gtk.HBox hbox_capture_phases_time;
 
@@ -335,7 +327,6 @@ public partial class ChronoJumpWindow
        [Widget] Gtk.Image image_test;
        [Widget] Gtk.Button button_image_test_zoom;
        [Widget] Gtk.Image image_test_zoom;
-       [Widget] Gtk.Button button_video_play_this_test;
        [Widget] Gtk.Button button_delete_last_test;
        [Widget] Gtk.Button button_inspect_last_test;
        [Widget] Gtk.VBox vbox_last_test_buttons;
@@ -3745,188 +3736,6 @@ public partial class ChronoJumpWindow
 
        
 
-       /*
-        * videoOn
-        */
-       
-
-       //at what tab of notebook_sup there's the video_capture
-       private int video_capture_notebook_sup = 0;
-
-       //changed by user clicking on notebook tabs
-       private void on_notebook_sup_switch_page (object o, SwitchPageArgs args) {
-               if( 
-                               (notebook_sup.CurrentPage == 0 && video_capture_notebook_sup == 1) ||
-                               (notebook_sup.CurrentPage == 1 && video_capture_notebook_sup == 0)) 
-               {
-                       //first stop showing video
-                       bool wasActive = false;
-                       if(checkbutton_video.Active) {
-                               wasActive = true;
-                               checkbutton_video.Active = false;
-                       }
-
-                       if(notebook_sup.CurrentPage == 0) {
-                               /*
-                                * TODO:
-                               //remove video capture from encoder tab
-                               viewport_video_capture_encoder.Remove(capturer);
-                               //add in contacts tab
-                               hbox_video_capture.PackStart(capturer, true, true, 0);
-                               */
-                       } else {
-                               /*
-                                * TODO:
-                               //remove video capture from contacts tab
-                               hbox_video_capture.Remove(capturer);
-                               //add in encoder tab
-
-                               //switch to capture tab                 
-                               radiobutton_video_encoder_capture.Active = true;
-
-                               //sometimes it seems is not removed and then cannot be added again
-                               //just add if not exists
-                               //maybe this error was because before we were not doing the:
-                               //radiobutton_video_encoder_capture.Active = true;
-                               if(viewport_video_capture_encoder.Child == null)
-                                       viewport_video_capture_encoder.Add(capturer);
-                                       */
-                       }
-               
-                       if(wasActive) 
-                               checkbutton_video.Active = true;
-               
-                       video_capture_notebook_sup = notebook_sup.CurrentPage;
-               }
-       }
-
-       //CapturerBin capturer;
-       private void videoCaptureInitialize() 
-       {
-               /*
-                * TODO: reimplement this with ffmpeg
-                *
-               capturer = new CapturerBin();
-               
-               hbox_video_capture.PackStart(capturer, true, true, 0);
-               
-               videoCapturePrepare(false); //if error, show message
-               */
-       }
-
-       //int videoDeviceNum = 0;
-       private void videoCapturePrepare(bool showErrorMessage) {
-               /*
-                * TODO: reimplement this with ffmpeg
-                *
-               LogB.Information("videoCapturePPPPPPPPPPPPPPPPPrepare");
-               List<LongoMatch.Video.Utils.Device> devices = 
LongoMatch.Video.Utils.Device.ListVideoDevices();
-               if(devices.Count == 0) {
-                       if(showErrorMessage)
-                               new DialogMessage(Constants.MessageTypes.WARNING, Constants.CameraNotFound);
-                       return;
-               }
-
-
-               CapturePropertiesStruct s = new CapturePropertiesStruct();
-
-               s.OutputFile = Util.GetVideoTempFileName();
-
-               s.VideoBitrate =  1000;
-               s.AudioBitrate =  128;
-               s.CaptureSourceType = CaptureSourceType.System;
-               s.Width = 360;
-               s.Height = 288;
-               
-               foreach(LongoMatch.Video.Utils.Device dev in devices){
-                       LogB.Information(dev.ID.ToString());
-                       LogB.Information(dev.IDProperty.ToString());
-                       LogB.Information(dev.DeviceType.ToString());
-               }
-                       
-               s.DeviceID = devices[videoDeviceNum].ID;
-               
-
-               capturer.CaptureProperties = s;
-
-               //checkbutton_video and checkbutton_video_encoder are synchronized
-               if(checkbutton_video.Active)
-                       capturer.Type = CapturerType.Live;
-               else
-                       capturer.Type = CapturerType.Fake;
-               capturer.Visible=true;
-
-               try {
-                       capturer.Stop();
-               } catch {}
-               LogB.Information("videoCapturePPPPPPPPPPPPPPPPPrepare done !");
-               capturer.Run();
-               */
-       }
-       
-       
-       private void changeVideoButtons(bool myVideo) {
-               image_video_yes.Visible = myVideo;
-               image_video_no.Visible = ! myVideo;
-       }
-       
-       private void on_checkbutton_video_clicked(object o, EventArgs args)
-       {
-               if(checkbutton_video.Active)
-               {
-                       if(preferences.videoDevice == "" || preferences.videoDevice == "0")
-                       {
-                               new DialogMessage(Constants.MessageTypes.WARNING, "Video device is not 
configured. Check Preferences / Multimedia.");
-                               checkbutton_video.Active = false;
-                               return;
-                       }
-
-                       preferences.videoOn = true;
-                       SqlitePreferences.Update("videoOn", "True", false);
-               } else {
-                       preferences.videoOn = false;
-                       SqlitePreferences.Update("videoOn", "False", false);
-               }
-               //change encoder checkbox but don't raise the signal    
-               checkbutton_video_encoder.Clicked -= new EventHandler(on_checkbutton_video_encoder_clicked);
-               checkbutton_video_encoder.Active = preferences.videoOn;
-               checkbutton_video_encoder.Clicked += new EventHandler(on_checkbutton_video_encoder_clicked);
-
-               button_video_preview.Visible = checkbutton_video.Active;
-               changeVideoButtons(preferences.videoOn);
-               
-               videoCapturePrepare(true); //if error, show message
-       }
-
-       private void on_checkbutton_video_encoder_clicked(object o, EventArgs args)
-       {
-               if(checkbutton_video_encoder.Active)
-               {
-                       if(preferences.videoDevice == "" || preferences.videoDevice == "0")
-                       {
-                               new DialogMessage(Constants.MessageTypes.WARNING, "Video device is not 
configured. Check Preferences / Multimedia.");
-                               checkbutton_video_encoder.Active = false;
-                               return;
-                       }
-
-                       preferences.videoOn = true;
-                       SqlitePreferences.Update("videoOn", "True", false);
-               } else {
-                       preferences.videoOn = false;
-                       SqlitePreferences.Update("videoOn", "False", false);
-               }
-               //change contacts checkbox but don't raise the signal   
-               checkbutton_video.Clicked -= new EventHandler(on_checkbutton_video_clicked);
-               checkbutton_video.Active = preferences.videoOn;
-               checkbutton_video.Clicked += new EventHandler(on_checkbutton_video_clicked);
-               
-               //changeVideoButtons(preferences.videoOn);
-       
-               //will start on record  
-               videoCapturePrepare(true); //if error, show message
-       }
-
-
        /*
         * cancel and finish
         */
@@ -4261,116 +4070,6 @@ public partial class ChronoJumpWindow
                return false;
        }
 
-       /* ---------------------------------------------------------
-        * ----------------  Webcam manage on execution ------------
-        *  --------------------------------------------------------
-        */
-
-       /*
-        * TODO:
-        * if there are two cameras
-        * have two webcam and call: webcamRecordStart and webcamRecordEnd two times
-        * take care pngs of 2n camera have to be in different area
-        * maybe use on /tmp/chronojump-video0 /tmp/chronojump-video1 ...
-        * and at the end merge both mp4s with:
-        *
-        * ffmpeg \
-        *  -i RUN-12.mp4 \
-        *  -i RUN-11.mp4 \
-        *  -filter_complex '[0:v]pad=iw*2:ih[int];[int][1:v]overlay=W/2:0[vid]' \
-        *  -map [vid] \
-        *  -c:v libx264 \
-        *  -crf 23 \
-        *  -preset veryfast \
-        *  output.mp4
-        *
-        *  
https://unix.stackexchange.com/questions/233832/merge-two-video-clips-into-one-placing-them-next-to-each-other
-        *  2nd solution merges audios
-        *  3a solucio diu que la primera perd molts frames
-        */
-
-       WebcamManage webcamManage;
-
-       private void webcamStart (int ncams)
-       {
-               if(! preferences.videoOn || webcamManage == null)
-                       return;
-
-               button_video_preview.Visible = false;
-               string errorMessage = "";
-               if(ncams == 1 && webcamManage.RecordPrepare(preferences.videoDevice).success)
-               {
-                       webcamManage.RecordStart(1);
-                       label_video_feedback.Text = "Preparing camera";
-               }
-               else if(ncams == 2 && webcamManage.RecordPrepare(preferences.videoDevice, 
"/dev/video1").success)
-               {
-                       webcamManage.RecordStart(2);
-                       label_video_feedback.Text = "Preparing camera";
-               }
-               //TODO depending on errorMessage:
-               //new DialogMessage(Constants.MessageTypes.WARNING, result.error);
-               //button_video_play_this_test.Sensitive = false;
-       }
-
-       //can pass a -1 uniqueID if test is cancelled
-       private void webcamEnd (Constants.TestTypes testType, int uniqueID)
-       {
-               button_video_play_this_test.Sensitive = false;
-
-               if(! preferences.videoOn || webcamManage == null)
-                       return;
-
-               Webcam.Result result = webcamManage.RecordEnd (1);
-               if(result.success)
-               {
-                       Webcam.Result resultExit = webcamManage.ExitAndFinish (1, currentSession.UniqueID, 
testType, uniqueID);
-                       if(uniqueID != -1 && ! resultExit.success)
-                               new DialogMessage(Constants.MessageTypes.WARNING, resultExit.error);
-               }
-               else
-                       new DialogMessage(Constants.MessageTypes.WARNING, result.error);
-
-               button_video_play_this_test.Sensitive = result.success;
-       }
-
-       //do this to start them at the "same moment"
-       //can pass a -1 uniqueID if test is cancelled
-       private void webcamEndTwoCams (Constants.TestTypes testType, int uniqueID)
-       {
-               button_video_play_this_test.Sensitive = false;
-
-               if(! preferences.videoOn || webcamManage == null)
-                       return;
-
-               Webcam.Result result1 = webcamManage.RecordEnd (1);
-               Webcam.Result result2 = webcamManage.RecordEnd (2);
-
-               string errorMessage = "";
-               if(result1.success)
-               {
-                       Webcam.Result result1Exit = webcamManage.ExitAndFinish (1, currentSession.UniqueID, 
testType, uniqueID);
-                       if(uniqueID != -1 && ! result1Exit.success)
-                               errorMessage += result1Exit.error + "\n";
-               }
-               else
-                       errorMessage += result1.error + "\n";
-
-               if(result2.success)
-               {
-                       Webcam.Result result2Exit = webcamManage.ExitAndFinish (2, currentSession.UniqueID, 
testType, -1 * uniqueID);
-                       if(uniqueID != -1 && ! result2Exit.success)
-                               errorMessage += result2Exit.error + "\n";
-               }
-               else
-                       errorMessage += result2.error + "\n";
-
-               if(errorMessage != "")
-                       new DialogMessage(Constants.MessageTypes.WARNING, errorMessage);
-
-               button_video_play_this_test.Sensitive = (uniqueID != -1 && errorMessage == "");
-       }
-
 
        /* ---------------------------------------------------------
         * ----------------  JUMPS EXECUTION (no RJ) ----------------
@@ -4459,8 +4158,8 @@ public partial class ChronoJumpWindow
 
                //UtilGtk.ChronopicColors(viewport_chronopics, label_chronopics, label_connected_chronopics, 
chronopicWin.Connected);
 
-               webcamStart (1);
-               currentEventExecute.WebcamStarting = (preferences.videoOn && webcamManage != null); //to show 
info on label_video_feedback
+               currentEventExecute.WebcamStarting =
+                       webcamStart (WebcamManage.GuiContactsEncoder.CONTACTS, 1);
 
                if (! canCaptureC)
                        currentEventExecute.SimulateInitValues(rand);
@@ -4769,8 +4468,8 @@ public partial class ChronoJumpWindow
                                );
                
                //webcamStart (2);
-               webcamStart (1);
-               currentEventExecute.WebcamStarting = (preferences.videoOn && webcamManage != null); //to show 
info on label_video_feedback
+               currentEventExecute.WebcamStarting =
+                       webcamStart (WebcamManage.GuiContactsEncoder.CONTACTS, 1);
 
                //suitable for limited by jump and time
                //simulated always simulate limited by jumps
@@ -4917,8 +4616,8 @@ public partial class ChronoJumpWindow
                                image_run_execute_photocell
                                );
 
-               webcamStart (1);
-               currentEventExecute.WebcamStarting = (preferences.videoOn && webcamManage != null); //to show 
info on label_video_feedback
+               currentEventExecute.WebcamStarting =
+                       webcamStart (WebcamManage.GuiContactsEncoder.CONTACTS, 1);
 
                if (! canCaptureC)
                        currentEventExecute.SimulateInitValues(rand);
@@ -5052,8 +4751,8 @@ public partial class ChronoJumpWindow
                                image_run_execute_photocell
                                );
 
-               webcamStart (1);
-               currentEventExecute.WebcamStarting = (preferences.videoOn && webcamManage != null); //to show 
info on label_video_feedback
+               currentEventExecute.WebcamStarting =
+                       webcamStart (WebcamManage.GuiContactsEncoder.CONTACTS, 1);
 
                //suitable for limited by tracks and time
                if(! canCaptureC)
@@ -5273,8 +4972,8 @@ public partial class ChronoJumpWindow
                                progressbarLimit, egd, description
                                );
 
-               webcamStart (1);
-               currentEventExecute.WebcamStarting = (preferences.videoOn && webcamManage != null); //to show 
info on label_video_feedback
+               currentEventExecute.WebcamStarting =
+                       webcamStart (WebcamManage.GuiContactsEncoder.CONTACTS, 1);
 
                if (! canCaptureC)
                        currentEventExecute.SimulateInitValues(rand);
@@ -5433,8 +5132,8 @@ public partial class ChronoJumpWindow
                                preferences.volumeOn, preferences.gstreamer, egd
                                );
                
-               webcamStart (1);
-               currentEventExecute.WebcamStarting = (preferences.videoOn && webcamManage != null); //to show 
info on label_video_feedback
+               currentEventExecute.WebcamStarting =
+                       webcamStart (WebcamManage.GuiContactsEncoder.CONTACTS, 1);
 
                if(! canCaptureC)
                        currentEventExecute.SimulateInitValues(rand);
@@ -5721,8 +5420,8 @@ public partial class ChronoJumpWindow
                                app1, egd
                                );
 
-               webcamStart (1);
-               currentEventExecute.WebcamStarting = (preferences.videoOn && webcamManage != null); //to show 
info on label_video_feedback
+               currentEventExecute.WebcamStarting =
+                       webcamStart (WebcamManage.GuiContactsEncoder.CONTACTS, 1);
 
                //mark to only get inside on_multi_chronopic_finished one time
                multiFinishing = false;
@@ -6128,157 +5827,6 @@ LogB.Debug("mc finished 5");
                }
        }
        
-       /* ---------------------------------------------------------
-        * ----------------  EVENTS PLAY VIDEO ---------------------
-        *  --------------------------------------------------------
-        */
-
-       //TODO: manage different playVideo. Playing is very different than capturing, separate it.
-       Webcam webcamPlay;
-
-       private void on_button_video_preview_clicked (object o, EventArgs args)
-       {
-               playPreview();
-       }
-       private void playPreview ()
-       {
-               //constructor for playpreview
-               webcamPlay = new WebcamFfmpeg (Webcam.Action.PLAYPREVIEW, UtilAll.GetOSEnum(), 
preferences.videoDevice);
-               Webcam.Result result = webcamPlay.PlayPreview ();
-       }
-
-       private void on_button_video_debug_clicked (object o, EventArgs args)
-       {
-               string executable = "debug";
-               if(UtilAll.GetOSEnum() == UtilAll.OperatingSystems.WINDOWS)
-                       executable = System.IO.Path.Combine(Util.GetPrefixDir(), "bin/debug.bat");
-
-               LogB.Information("Calling debug: " + executable);
-               ExecuteProcess.Result execute_result = ExecuteProcess.run (executable, true, true);
-               LogB.Information("Called debug.");
-       }
-
-       //Not used on encoder   
-       private void playVideo (string fileName)
-       {
-               //constructor for playpreview
-               webcamPlay = new WebcamFfmpeg (Webcam.Action.PLAYFILE, UtilAll.GetOSEnum(), "");
-               Webcam.Result result = webcamPlay.PlayFile (fileName);
-
-               /*
-                * TODO: reimplement this with ffmpeg
-                *
-               if(File.Exists(fileName)) {
-                       LogB.Information("Play video starting...");
-                       PlayerBin player = new PlayerBin();
-                       player.Open(fileName);
-
-                       //without these lines works also but has less functionalities (speed, go to ms)
-                       Gtk.Window d = new Gtk.Window(Catalog.GetString("Playing video"));
-                       d.Add(player);
-                       d.Modal = true;
-                       d.SetDefaultSize(500,400);
-                       d.ShowAll();
-                       d.DeleteEvent += delegate(object sender, DeleteEventArgs e) {player.Close(); 
player.Dispose();};
-
-                       if(play) {
-                               LogB.Information("Play video playing...");
-                               player.Play();
-                       }
-                       return true;    
-               }
-               */
-       }
-
-
-       private void on_video_play_last_test_clicked (object o, EventArgs args)
-       {
-               Constants.TestTypes type = Constants.TestTypes.JUMP;
-               int id = 0;
-               switch (currentEventType.Type) {
-                       case EventType.Types.JUMP:
-                               if(lastJumpIsSimple) {
-                                       type = Constants.TestTypes.JUMP;
-                                       id = currentJump.UniqueID;
-                               }
-                               else {
-                                       type = Constants.TestTypes.JUMP_RJ;
-                                       id = currentJumpRj.UniqueID;
-                               } break;
-                       case EventType.Types.RUN:
-                               if(lastRunIsSimple) {
-                                       type = Constants.TestTypes.RUN;
-                                       id = currentRun.UniqueID;
-                               } else {
-                                       type = Constants.TestTypes.RUN_I;
-                                       id = currentRunInterval.UniqueID;
-                               }
-                               break;
-                       case EventType.Types.PULSE:
-                               type = Constants.TestTypes.PULSE;
-                               id = currentPulse.UniqueID;
-                               break;
-                       case EventType.Types.REACTIONTIME:
-                               type = Constants.TestTypes.RT;
-                               id = currentReactionTime.UniqueID;
-                               break;
-                       case EventType.Types.MULTICHRONOPIC:
-                               type = Constants.TestTypes.MULTICHRONOPIC;
-                               id = currentMultiChronopic.UniqueID;
-                               break;
-               }
-
-               playVideo(Util.GetVideoFileName(currentSession.UniqueID, type, id));
-       }
-
-       private void on_video_play_selected_jump_clicked (object o, EventArgs args) {
-               if (myTreeViewJumps.EventSelectedID > 0) 
-                       playVideo(Util.GetVideoFileName(currentSession.UniqueID, 
-                                               Constants.TestTypes.JUMP,
-                                               myTreeViewJumps.EventSelectedID));
-       }
-
-       private void on_video_play_selected_jump_rj_clicked (object o, EventArgs args) {
-               if (myTreeViewJumpsRj.EventSelectedID > 0) 
-                       playVideo(Util.GetVideoFileName(currentSession.UniqueID, 
-                                               Constants.TestTypes.JUMP_RJ,
-                                               myTreeViewJumpsRj.EventSelectedID));
-       }
-
-       private void on_video_play_selected_run_clicked (object o, EventArgs args) {
-               if (myTreeViewRuns.EventSelectedID > 0) 
-                       playVideo(Util.GetVideoFileName(currentSession.UniqueID, 
-                                               Constants.TestTypes.RUN,
-                                               myTreeViewRuns.EventSelectedID));
-       }
-
-       private void on_video_play_selected_run_interval_clicked (object o, EventArgs args) {
-               if (myTreeViewRunsInterval.EventSelectedID > 0) 
-                       playVideo(Util.GetVideoFileName(currentSession.UniqueID, 
-                                               Constants.TestTypes.RUN_I,
-                                               myTreeViewRunsInterval.EventSelectedID));
-       }
-
-       private void on_video_play_selected_reaction_time_clicked (object o, EventArgs args) {
-               if (myTreeViewReactionTimes.EventSelectedID > 0) 
-                       playVideo(Util.GetVideoFileName(currentSession.UniqueID, 
-                                               Constants.TestTypes.RT,
-                                               myTreeViewReactionTimes.EventSelectedID));
-       }
-
-       private void on_video_play_selected_pulse_clicked (object o, EventArgs args) {
-               if (myTreeViewPulses.EventSelectedID > 0) 
-                       playVideo(Util.GetVideoFileName(currentSession.UniqueID, 
-                                               Constants.TestTypes.PULSE,
-                                               myTreeViewPulses.EventSelectedID));
-       }
-
-       private void on_video_play_selected_multi_chronopic_clicked (object o, EventArgs args) {
-               if (myTreeViewMultiChronopic.EventSelectedID > 0) 
-                       playVideo(Util.GetVideoFileName(currentSession.UniqueID, 
-                                               Constants.TestTypes.MULTICHRONOPIC,
-                                               myTreeViewMultiChronopic.EventSelectedID));
-       }
 
        /* ---------------------------------------------------------
         * ----------------  EVENTS DELETE -------------------------
diff --git a/src/gui/chronojumpIcons.cs b/src/gui/chronojumpIcons.cs
index 1e24491f..c33459c7 100644
--- a/src/gui/chronojumpIcons.cs
+++ b/src/gui/chronojumpIcons.cs
@@ -147,7 +147,7 @@ public partial class ChronoJumpWindow
 
        //video play icons
        [Widget] Gtk.Image image_video_play_this_test;
-       [Widget] Gtk.Image image_video_encoder_play;
+       [Widget] Gtk.Image image_video_play_this_test_encoder;
        [Widget] Gtk.Image image_video_play_selected_jump;
        [Widget] Gtk.Image image_video_play_selected_jump_rj;
        [Widget] Gtk.Image image_video_play_selected_run;
@@ -375,7 +375,9 @@ public partial class ChronoJumpWindow
                image_encoder_recalibrate.Pixbuf = pixbuf;
 
                image_video_yes.Pixbuf = new Pixbuf (null, Util.GetImagePath(false) + 
"image_photo_start_camera.png");
+               image_video_encoder_yes.Pixbuf = new Pixbuf (null, Util.GetImagePath(false) + 
"image_photo_start_camera.png");
                image_video_no.Pixbuf = new Pixbuf (null, Util.GetImagePath(false) + 
"image_photo_end_camera.png");
+               image_video_encoder_no.Pixbuf = new Pixbuf (null, Util.GetImagePath(false) + 
"image_photo_end_camera.png");
 
                /*
                 * <------ end of material design icons
@@ -522,7 +524,7 @@ public partial class ChronoJumpWindow
                //video play icons
                pixbuf = new Pixbuf (null, Util.GetImagePath(false) + "video_play.png");
                image_video_play_this_test.Pixbuf = pixbuf;
-               image_video_encoder_play.Pixbuf = pixbuf;
+               image_video_play_this_test_encoder.Pixbuf = pixbuf;
                image_video_play_selected_jump.Pixbuf = pixbuf;
                image_video_play_selected_jump_rj.Pixbuf = pixbuf;
                image_video_play_selected_run.Pixbuf = pixbuf;
diff --git a/src/gui/encoder.cs b/src/gui/encoder.cs
index b85e431e..a0f2c28a 100644
--- a/src/gui/encoder.cs
+++ b/src/gui/encoder.cs
@@ -110,21 +110,7 @@ public partial class ChronoJumpWindow
        
        [Widget] Gtk.VPaned vpaned_encoder_main;
        [Widget] Gtk.VPaned vpaned_encoder_capture_video_and_set_graph;
-               
-       //encoder video
-       [Widget] Gtk.Alignment alignment_video_encoder;
-       [Widget] Gtk.Notebook notebook_video_encoder;
-       [Widget] Gtk.Viewport viewport_video_capture_encoder;
-       [Widget] Gtk.Viewport viewport_video_play_encoder;
-       [Widget] Gtk.RadioButton radiobutton_video_encoder_capture;
-       [Widget] Gtk.RadioButton radiobutton_video_encoder_play;
-       [Widget] Gtk.RadioButton radiobutton_video_encoder_options;
-       [Widget] Gtk.Label label_video_encoder_filename;
-       [Widget] Gtk.TextView textview_video_encoder_folder;
-       [Widget] Gtk.Button button_video_encoder_open_folder;
-       [Widget] Gtk.Label label_video_feedback_encoder;
-       [Widget] Gtk.CheckButton checkbutton_video_encoder;
-       
+
        [Widget] Gtk.Notebook notebook_encoder_sup;
        [Widget] Gtk.Notebook notebook_encoder_capture;
 
@@ -935,8 +921,6 @@ public partial class ChronoJumpWindow
                if(notebook_encoder_capture.CurrentPage == 1)
                        notebook_encoder_capture.PrevPage();
 
-               radiobutton_video_encoder_capture.Active = true;
-
                sensitiveGuiEventDoing(radio_encoder_capture_cont.Active);
 
                LogB.Debug("Calling encoderThreadStart for capture");
@@ -1691,10 +1675,9 @@ public partial class ChronoJumpWindow
                                textview_encoder_signal_comment.Buffer.Text = eSQL.description;
                                encoderTimeStamp = eSQL.GetDate(false); 
                                encoderSignalUniqueID = eSQL.uniqueID;
-                       
+
                                //has to be done here, because if done in encoderThreadStart or in 
finishPulsebar it crashes 
-                               //notebook_video_encoder.CurrentPage = 1;
-                               radiobutton_video_encoder_play.Active = true;
+                               button_video_play_this_test_encoder.Sensitive = (eSQL.videoURL != "");
 
                                encoderConfigurationCurrent = eSQL.encoderConfiguration;
                                setEncoderTypePixbuf();
@@ -2523,7 +2506,6 @@ public partial class ChronoJumpWindow
                                encoderSignalUniqueID = myID;
                                feedback = Catalog.GetString("Set saved");
                        
-                               viewport_video_play_encoder.Sensitive = false;
                                //copy video    
                                if(preferences.videoOn) {
                                        if(Util.CopyTempVideo(currentSession.UniqueID, 
@@ -2535,11 +2517,9 @@ public partial class ChronoJumpWindow
                                                //need assign uniqueID to update and add the URL of video
                                                eSQL.uniqueID = encoderSignalUniqueID;
                                                SqliteEncoder.Update(dbconOpened, eSQL);
-                                       
-                                               //notebook_video_encoder.CurrentPage = 1;
-                                               radiobutton_video_encoder_play.Active  = true;
-                                               
-                                               viewport_video_play_encoder.Sensitive = true;
+
+                                               button_video_play_this_test_encoder.Sensitive = true;
+
 
                                        } else {
                                                new DialogMessage(Constants.MessageTypes.WARNING, 
@@ -4811,6 +4791,8 @@ public partial class ChronoJumpWindow
                button_encoder_analyze_AB_save.Sensitive = false;
                button_encoder_analyze_table_save.Sensitive = false;
                button_encoder_analyze_1RM_save.Visible = false;
+
+               button_video_play_this_test_encoder.Sensitive = false;
        }
 
        private void encoderButtonsSensitive(encoderSensEnum option) 
@@ -5754,8 +5736,14 @@ public partial class ChronoJumpWindow
 
                        //eccaCreated = false;
 
-                       if(action == encoderActions.CAPTURE) {
-                               encoderStartVideoRecord();
+                       if(action == encoderActions.CAPTURE)
+                       {
+                               webcamManage = new WebcamManage();
+                               bool camStarted = webcamStart (WebcamManage.GuiContactsEncoder.ENCODER, 1);
+                               if(camStarted)
+                                       webcamEncoderFileStarted = WebcamEncoderFileStarted.NEEDTOCHECK;
+                               else
+                                       webcamEncoderFileStarted = WebcamEncoderFileStarted.NOCAMERA;
 
                                //remove treeview columns
                                if( ! (action == encoderActions.CAPTURE && radio_encoder_capture_cont.Active) 
)
@@ -6340,7 +6328,7 @@ public partial class ChronoJumpWindow
 
                        if(encoderProcessCancel) {
                                //stop video            
-                               encoderStopVideoRecord();
+                               webcamEnd (Constants.TestTypes.ENCODER, -1);
                        }
 
                        LogB.ThreadEnded(); 
@@ -6397,6 +6385,13 @@ public partial class ChronoJumpWindow
                                needToRefreshTreeviewCapture = false;
                        }
 
+                       if(webcamEncoderFileStarted == WebcamEncoderFileStarted.NEEDTOCHECK)
+                               if(WebcamManage.RecordingFileStarted ())
+                               {
+                                       webcamEncoderFileStarted = WebcamEncoderFileStarted.RECORDSTARTED;
+                                       label_video_encoder_feedback.Text = "Recording video.";
+                               }
+
                        if(encoderRhythm.Active)
                                updatePulsebarRhythm();
 
@@ -6405,7 +6400,7 @@ public partial class ChronoJumpWindow
                        //LogB.Information(" Cap:" + encoderThread.ThreadState.ToString());
                } else if(capturingCsharp == encoderCaptureProcess.STOPPING) {
                        //stop video            
-                       encoderStopVideoRecord();
+                       webcamEnd (Constants.TestTypes.ENCODER, -1); //this will end but file will be copied 
later (when we have encoderSignalUniqueID)
 
                        //don't allow to press cancel or finish
                        button_encoder_capture_cancel.Sensitive = false;
@@ -7021,18 +7016,6 @@ public partial class ChronoJumpWindow
                                }
                                
                                playVideoEncoderPrepare(false); //do not play
-                               
-                               //set encoder video labels
-                               string videofile = Util.GetVideoFileName(currentSession.UniqueID, 
-                                               Constants.TestTypes.ENCODER, 
Convert.ToInt32(encoderSignalUniqueID));
-                               if(videofile != null && videofile != "" && File.Exists(videofile)) {
-                                       label_video_encoder_filename.Text = Util.GetVideoFileNameOnlyName(
-                                                       Constants.TestTypes.ENCODER, 
-                                                       Convert.ToInt32(encoderSignalUniqueID));
-                                       textview_video_encoder_folder.Buffer.Text = 
Util.GetVideoFileNameOnlyFolder(currentSession.UniqueID);
-                                       button_video_encoder_open_folder.Visible = true;
-                               } else
-                                       button_video_encoder_open_folder.Visible = false;
                        }
 
                        if(action == encoderActions.CAPTURE_IM && ! encoderProcessCancel && ! 
encoderProcessProblems) 
@@ -7436,23 +7419,9 @@ public partial class ChronoJumpWindow
                }
                */
        }       
-       
-       public void on_radiobutton_video_encoder_capture_toggled (object obj, EventArgs args) {
-               if(radiobutton_video_encoder_capture.Active) {
-                       notebook_video_encoder.CurrentPage = 0;
-               }
-       }
-       public void on_radiobutton_video_encoder_play_toggled (object obj, EventArgs args) {
-               if(radiobutton_video_encoder_play.Active) {
-                       notebook_video_encoder.CurrentPage = 1;
-               }
-       }
-       public void on_radiobutton_video_encoder_options_toggled (object obj, EventArgs args) {
-               if(radiobutton_video_encoder_options.Active) {
-                       notebook_video_encoder.CurrentPage = 2;
-               }
-       }
+
        public void on_button_video_encoder_open_folder_clicked (object obj, EventArgs args) {
+               /*
                string dir = textview_video_encoder_folder.Buffer.Text;
                try {
                        System.Diagnostics.Process.Start(dir); 
@@ -7461,6 +7430,7 @@ public partial class ChronoJumpWindow
                        new DialogMessage(Constants.MessageTypes.WARNING, 
                                        Constants.DirectoryCannotOpen + "\n\n" + dir);
                }
+               */
        }
 
        /* end of video stuff */
diff --git a/src/gui/networks.cs b/src/gui/networks.cs
index 2f5400cc..df553a9d 100644
--- a/src/gui/networks.cs
+++ b/src/gui/networks.cs
@@ -337,9 +337,11 @@ public partial class ChronoJumpWindow
                        hbox_encoder_analyze_signal_or_curves.HeightRequest = 40;
                        button_encoder_analyze.SetSizeRequest(120,40);
                }
+               /*
                if(! configChronojump.UseVideo) {
                        alignment_video_encoder.Visible = false;
                }
+               */
                //restriction for configured Compujump clients
                //if(configChronojump.Compujump)
                //      hbox_encoder_im_weights_n.Sensitive = false;
diff --git a/src/gui/webcam.cs b/src/gui/webcam.cs
index 9d35f0dc..ab4e964b 100644
--- a/src/gui/webcam.cs
+++ b/src/gui/webcam.cs
@@ -18,14 +18,35 @@
  * Copyright (C) 2019   Xavier de Blas <xaviblas gmail com>
  */
 
+using System;
 using Gtk;
-//using Gdk;
 using Glade;
 
 public partial class ChronoJumpWindow 
 {
        [Widget] Gtk.VSeparator vseparator_force_sensor_camera_space;
        [Widget] Gtk.VBox vbox_contacts_camera;
+       [Widget] Gtk.CheckButton checkbutton_video;
+       [Widget] Gtk.CheckButton checkbutton_video_encoder;
+       [Widget] Gtk.HBox hbox_video_capture;
+       [Widget] Gtk.HBox hbox_video_encoder;
+       [Widget] Gtk.HBox hbox_video_encoder_no_capturing;
+       [Widget] Gtk.HBox hbox_video_encoder_capturing;
+       [Widget] Gtk.Label label_video_feedback;
+       [Widget] Gtk.Label label_video_encoder_feedback;
+       [Widget] Gtk.Button button_video_preview;
+       [Widget] Gtk.Button button_video_encoder_preview;
+       //[Widget] Gtk.Label label_video;
+       [Widget] Gtk.Image image_video_yes;
+       [Widget] Gtk.Image image_video_no;
+       [Widget] Gtk.Image image_video_encoder_yes;
+       [Widget] Gtk.Image image_video_encoder_no;
+       [Widget] Gtk.Button button_video_play_this_test;
+       [Widget] Gtk.Button button_video_play_this_test_encoder;
+
+
+       private enum WebcamEncoderFileStarted { NEEDTOCHECK, RECORDSTARTED, NOCAMERA }
+       private WebcamEncoderFileStarted webcamEncoderFileStarted;
 
        //should be visible on all contacts, but right now hide it on force sensor and runEncoder
        //but we need database stuff first
@@ -35,4 +56,524 @@ public partial class ChronoJumpWindow
                vbox_contacts_camera.Visible = show;
                button_video_play_this_test.Visible = show;
        }
+
+       /* ---------------------------------------------------------
+        * ----------------  Webcam manage on execution ------------
+        *  --------------------------------------------------------
+        */
+
+       /*
+        * TODO:
+        * if there are two cameras
+        * have two webcam and call: webcamRecordStart and webcamRecordEnd two times
+        * take care pngs of 2n camera have to be in different area
+        * maybe use on /tmp/chronojump-video0 /tmp/chronojump-video1 ...
+        * and at the end merge both mp4s with:
+        *
+        * ffmpeg \
+        *  -i RUN-12.mp4 \
+        *  -i RUN-11.mp4 \
+        *  -filter_complex '[0:v]pad=iw*2:ih[int];[int][1:v]overlay=W/2:0[vid]' \
+        *  -map [vid] \
+        *  -c:v libx264 \
+        *  -crf 23 \
+        *  -preset veryfast \
+        *  output.mp4
+        *
+        *  
https://unix.stackexchange.com/questions/233832/merge-two-video-clips-into-one-placing-them-next-to-each-other
+        *  2nd solution merges audios
+        *  3a solucio diu que la primera perd molts frames
+        */
+
+       WebcamManage webcamManage;
+
+       private bool webcamStart (WebcamManage.GuiContactsEncoder guiContactsEncoder, int ncams)
+       {
+               if(guiContactsEncoder == WebcamManage.GuiContactsEncoder.ENCODER)
+                       hbox_video_encoder.Sensitive = false;
+
+               if(! preferences.videoOn || webcamManage == null)
+                       return false;
+
+               if(guiContactsEncoder == WebcamManage.GuiContactsEncoder.ENCODER)
+               {
+                       hbox_video_encoder_no_capturing.Visible = false;
+                       hbox_video_encoder_capturing.Visible = true;
+               }
+
+               button_video_preview_visibile (guiContactsEncoder, false);
+
+               string errorMessage = "";
+               if(ncams == 1 && webcamManage.RecordPrepare(preferences.videoDevice).success)
+               {
+                       webcamManage.RecordStart(1);
+                       //label_video_feedback.Text = "Preparing camera";
+                       label_video_feedback_text (guiContactsEncoder, "Preparing camera");
+               }
+               else if(ncams == 2 && webcamManage.RecordPrepare(preferences.videoDevice, 
"/dev/video1").success)
+               {
+                       webcamManage.RecordStart(2);
+                       //label_video_feedback.Text = "Preparing camera";
+                       label_video_feedback_text (guiContactsEncoder, "Preparing camera");
+               }
+               //TODO depending on errorMessage:
+               //new DialogMessage(Constants.MessageTypes.WARNING, result.error);
+               //button_video_play_this_test.Sensitive = false;
+
+               return true;
+       }
+
+       private void button_video_preview_visibile (WebcamManage.GuiContactsEncoder guiContactsEncoder, bool 
visible)
+       {
+               if(guiContactsEncoder == WebcamManage.GuiContactsEncoder.CONTACTS)
+                       button_video_preview.Visible = visible;
+               else
+                       button_video_encoder_preview.Visible = visible;
+       }
+       private void label_video_feedback_text (WebcamManage.GuiContactsEncoder guiContactsEncoder, string 
text)
+       {
+               if(guiContactsEncoder == WebcamManage.GuiContactsEncoder.CONTACTS)
+                       label_video_feedback.Text = text;
+               else
+                       label_video_encoder_feedback.Text = text;
+       }
+       private void button_video_play_this_test_sensitive (WebcamManage.GuiContactsEncoder 
guiContactsEncoder, bool s)
+       {
+               if(guiContactsEncoder == WebcamManage.GuiContactsEncoder.CONTACTS)
+                       button_video_play_this_test.Sensitive = s;
+               else
+                       //button_video_encoder_play_this_test.Sensitive = s;
+                       button_video_play_this_test_encoder.Sensitive = s; //TODO:jugar amb la sensitivitat 
de aixo quan hi ha o no signalUniqueID 
+       }
+
+
+       //can pass a -1 uniqueID if test is cancelled
+       private void webcamEnd (Constants.TestTypes testType, int uniqueID)
+       {
+               WebcamManage.GuiContactsEncoder guiContactsEncoder = WebcamManage.GuiContactsEncoder.CONTACTS;
+               if(testType == Constants.TestTypes.ENCODER)
+               {
+                       guiContactsEncoder = WebcamManage.GuiContactsEncoder.ENCODER;
+                       label_video_encoder_feedback.Text = "";
+
+                       hbox_video_encoder.Sensitive = true;
+                       hbox_video_encoder_no_capturing.Visible = true;
+                       hbox_video_encoder_capturing.Visible = false;
+               }
+
+               //button_video_play_this_test.Sensitive = false;
+               button_video_play_this_test_sensitive (guiContactsEncoder, false);
+
+               if(! preferences.videoOn || webcamManage == null)
+                       return;
+
+               Webcam.Result result = webcamManage.RecordEnd (1);
+               if(result.success)
+               {
+                       Webcam.Result resultExit = webcamManage.ExitAndFinish (1, currentSession.UniqueID, 
testType, uniqueID, guiContactsEncoder);
+                       if(uniqueID != -1 && ! resultExit.success)
+                               new DialogMessage(Constants.MessageTypes.WARNING, resultExit.error);
+               }
+               else
+                       new DialogMessage(Constants.MessageTypes.WARNING, result.error);
+
+               //button_video_play_this_test.Sensitive = result.success;
+               button_video_play_this_test_sensitive (guiContactsEncoder, result.success);
+       }
+
+       //do this to start them at the "same moment"
+       //can pass a -1 uniqueID if test is cancelled
+       private void webcamEndTwoCams (Constants.TestTypes testType, int uniqueID)
+       {
+               WebcamManage.GuiContactsEncoder guiContactsEncoder = WebcamManage.GuiContactsEncoder.CONTACTS;
+               if(testType == Constants.TestTypes.ENCODER)
+               {
+                       guiContactsEncoder = WebcamManage.GuiContactsEncoder.ENCODER;
+                       label_video_encoder_feedback.Text = "";
+               }
+
+               //button_video_play_this_test.Sensitive = false;
+               button_video_play_this_test_sensitive (guiContactsEncoder, false);
+
+               if(! preferences.videoOn || webcamManage == null)
+                       return;
+
+               Webcam.Result result1 = webcamManage.RecordEnd (1);
+               Webcam.Result result2 = webcamManage.RecordEnd (2);
+
+               string errorMessage = "";
+               if(result1.success)
+               {
+                       Webcam.Result result1Exit = webcamManage.ExitAndFinish (1, currentSession.UniqueID, 
testType, uniqueID, guiContactsEncoder);
+                       if(uniqueID != -1 && ! result1Exit.success)
+                               errorMessage += result1Exit.error + "\n";
+               }
+               else
+                       errorMessage += result1.error + "\n";
+
+               if(result2.success)
+               {
+                       Webcam.Result result2Exit = webcamManage.ExitAndFinish (2, currentSession.UniqueID, 
testType, -1 * uniqueID, guiContactsEncoder);
+                       if(uniqueID != -1 && ! result2Exit.success)
+                               errorMessage += result2Exit.error + "\n";
+               }
+               else
+                       errorMessage += result2.error + "\n";
+
+               if(errorMessage != "")
+                       new DialogMessage(Constants.MessageTypes.WARNING, errorMessage);
+
+               //button_video_play_this_test.Sensitive = (uniqueID != -1 && errorMessage == "");
+               button_video_play_this_test_sensitive (guiContactsEncoder, (uniqueID != -1 && errorMessage == 
""));
+       }
+
+
+       /*
+        * videoOn
+        */
+
+       //at what tab of notebook_sup there's the video_capture
+       private int video_capture_notebook_sup = 0;
+
+       //changed by user clicking on notebook tabs
+       private void on_notebook_sup_switch_page (object o, SwitchPageArgs args) {
+               if(
+                               (notebook_sup.CurrentPage == 0 && video_capture_notebook_sup == 1) ||
+                               (notebook_sup.CurrentPage == 1 && video_capture_notebook_sup == 0))
+               {
+                       //first stop showing video
+                       bool wasActive = false;
+                       if(checkbutton_video.Active) {
+                               wasActive = true;
+                               checkbutton_video.Active = false;
+                       }
+
+                       if(notebook_sup.CurrentPage == 0) {
+                               /*
+                                * TODO:
+                               //remove video capture from encoder tab
+                               viewport_video_capture_encoder.Remove(capturer);
+                               //add in contacts tab
+                               hbox_video_capture.PackStart(capturer, true, true, 0);
+                               */
+                       } else {
+                               /*
+                                * TODO:
+                               //remove video capture from contacts tab
+                               hbox_video_capture.Remove(capturer);
+                               //add in encoder tab
+
+                               //switch to capture tab
+                               radiobutton_video_encoder_capture.Active = true;
+
+                               //sometimes it seems is not removed and then cannot be added again
+                               //just add if not exists
+                               //maybe this error was because before we were not doing the:
+                               //radiobutton_video_encoder_capture.Active = true;
+                               if(viewport_video_capture_encoder.Child == null)
+                                       viewport_video_capture_encoder.Add(capturer);
+                                       */
+                       }
+
+                       if(wasActive)
+                               checkbutton_video.Active = true;
+
+                       video_capture_notebook_sup = notebook_sup.CurrentPage;
+               }
+       }
+
+       //CapturerBin capturer;
+       private void videoCaptureInitialize()
+       {
+               /*
+                * TODO: reimplement this with ffmpeg
+                *
+               capturer = new CapturerBin();
+
+               hbox_video_capture.PackStart(capturer, true, true, 0);
+
+               videoCapturePrepare(false); //if error, show message
+               */
+       }
+
+       //int videoDeviceNum = 0;
+       private void videoCapturePrepare(bool showErrorMessage) {
+               /*
+                * TODO: reimplement this with ffmpeg
+                *
+               LogB.Information("videoCapturePPPPPPPPPPPPPPPPPrepare");
+               List<LongoMatch.Video.Utils.Device> devices = 
LongoMatch.Video.Utils.Device.ListVideoDevices();
+               if(devices.Count == 0) {
+                       if(showErrorMessage)
+                               new DialogMessage(Constants.MessageTypes.WARNING, Constants.CameraNotFound);
+                       return;
+               }
+
+
+               CapturePropertiesStruct s = new CapturePropertiesStruct();
+
+               s.OutputFile = Util.GetVideoTempFileName();
+
+               s.VideoBitrate =  1000;
+               s.AudioBitrate =  128;
+               s.CaptureSourceType = CaptureSourceType.System;
+               s.Width = 360;
+               s.Height = 288;
+
+               foreach(LongoMatch.Video.Utils.Device dev in devices){
+                       LogB.Information(dev.ID.ToString());
+                       LogB.Information(dev.IDProperty.ToString());
+                       LogB.Information(dev.DeviceType.ToString());
+               }
+
+               s.DeviceID = devices[videoDeviceNum].ID;
+
+
+               capturer.CaptureProperties = s;
+
+               //checkbutton_video and checkbutton_video_encoder are synchronized
+               if(checkbutton_video.Active)
+                       capturer.Type = CapturerType.Live;
+               else
+                       capturer.Type = CapturerType.Fake;
+               capturer.Visible=true;
+
+               try {
+                       capturer.Stop();
+               } catch {}
+               LogB.Information("videoCapturePPPPPPPPPPPPPPPPPrepare done !");
+               capturer.Run();
+               */
+       }
+
+
+       private void changeVideoButtons(bool myVideo)
+       {
+               image_video_yes.Visible = myVideo;
+               image_video_no.Visible = ! myVideo;
+
+               image_video_encoder_yes.Visible = myVideo;
+               image_video_encoder_no.Visible = ! myVideo;
+
+               button_video_preview.Visible = myVideo;
+               button_video_encoder_preview.Visible = myVideo;
+       }
+
+       private void on_checkbutton_video_clicked(object o, EventArgs args)
+       {
+               if(checkbutton_video.Active)
+               {
+                       if(preferences.videoDevice == "" || preferences.videoDevice == "0")
+                       {
+                               new DialogMessage(Constants.MessageTypes.WARNING, "Video device is not 
configured. Check Preferences / Multimedia.");
+                               checkbutton_video.Active = false;
+                               return;
+                       }
+
+                       preferences.videoOn = true;
+                       SqlitePreferences.Update("videoOn", "True", false);
+               } else {
+                       preferences.videoOn = false;
+                       SqlitePreferences.Update("videoOn", "False", false);
+               }
+               //change encoder checkbox but don't raise the signal
+               checkbutton_video_encoder.Clicked -= new EventHandler(on_checkbutton_video_encoder_clicked);
+               checkbutton_video_encoder.Active = preferences.videoOn;
+               checkbutton_video_encoder.Clicked += new EventHandler(on_checkbutton_video_encoder_clicked);
+
+               changeVideoButtons(preferences.videoOn);
+
+               videoCapturePrepare(true); //if error, show message
+       }
+
+       private void on_checkbutton_video_encoder_clicked(object o, EventArgs args)
+       {
+               if(checkbutton_video_encoder.Active)
+               {
+                       if(preferences.videoDevice == "" || preferences.videoDevice == "0")
+                       {
+                               new DialogMessage(Constants.MessageTypes.WARNING, "Video device is not 
configured. Check Preferences / Multimedia.");
+                               checkbutton_video_encoder.Active = false;
+                               return;
+                       }
+
+                       preferences.videoOn = true;
+                       SqlitePreferences.Update("videoOn", "True", false);
+               } else {
+                       preferences.videoOn = false;
+                       SqlitePreferences.Update("videoOn", "False", false);
+               }
+               //change contacts checkbox but don't raise the signal
+               checkbutton_video.Clicked -= new EventHandler(on_checkbutton_video_clicked);
+               checkbutton_video.Active = preferences.videoOn;
+               checkbutton_video.Clicked += new EventHandler(on_checkbutton_video_clicked);
+
+               changeVideoButtons(preferences.videoOn);
+
+               //will start on record
+               videoCapturePrepare(true); //if error, show message
+       }
+
+       /* ---------------------------------------------------------
+        * ----------------  EVENTS PLAY VIDEO ---------------------
+        *  --------------------------------------------------------
+        */
+
+       //TODO: manage different playVideo. Playing is very different than capturing, separate it.
+       Webcam webcamPlay;
+
+       private void on_button_video_preview_clicked (object o, EventArgs args)
+       {
+               playPreview();
+       }
+       private void on_button_video_encoder_preview_clicked (object o, EventArgs args)
+       {
+               playPreview();
+       }
+       private void playPreview ()
+       {
+               //constructor for playpreview
+               webcamPlay = new WebcamFfmpeg (Webcam.Action.PLAYPREVIEW, UtilAll.GetOSEnum(), 
preferences.videoDevice);
+               Webcam.Result result = webcamPlay.PlayPreviewNoBackground ();
+       }
+
+       private void on_button_video_debug_clicked (object o, EventArgs args)
+       {
+               string executable = "debug";
+               if(UtilAll.GetOSEnum() == UtilAll.OperatingSystems.WINDOWS)
+                       executable = System.IO.Path.Combine(Util.GetPrefixDir(), "bin/debug.bat");
+
+               LogB.Information("Calling debug: " + executable);
+               ExecuteProcess.Result execute_result = ExecuteProcess.run (executable, true, true);
+               LogB.Information("Called debug.");
+       }
+
+       //Not used on encoder
+       private void playVideo (string fileName)
+       {
+               //constructor for playpreview
+               webcamPlay = new WebcamFfmpeg (Webcam.Action.PLAYFILE, UtilAll.GetOSEnum(), "");
+               Webcam.Result result = webcamPlay.PlayFile (fileName);
+
+               /*
+                * TODO: reimplement this with ffmpeg
+                *
+               if(File.Exists(fileName)) {
+                       LogB.Information("Play video starting...");
+                       PlayerBin player = new PlayerBin();
+                       player.Open(fileName);
+
+                       //without these lines works also but has less functionalities (speed, go to ms)
+                       Gtk.Window d = new Gtk.Window(Catalog.GetString("Playing video"));
+                       d.Add(player);
+                       d.Modal = true;
+                       d.SetDefaultSize(500,400);
+                       d.ShowAll();
+                       d.DeleteEvent += delegate(object sender, DeleteEventArgs e) {player.Close(); 
player.Dispose();};
+
+                       if(play) {
+                               LogB.Information("Play video playing...");
+                               player.Play();
+                       }
+                       return true;
+               }
+               */
+       }
+
+
+       private void on_video_play_last_test_clicked (object o, EventArgs args)
+       {
+               Constants.TestTypes type = Constants.TestTypes.JUMP;
+               int id = 0;
+               switch (currentEventType.Type) {
+                       case EventType.Types.JUMP:
+                               if(lastJumpIsSimple) {
+                                       type = Constants.TestTypes.JUMP;
+                                       id = currentJump.UniqueID;
+                               }
+                               else {
+                                       type = Constants.TestTypes.JUMP_RJ;
+                                       id = currentJumpRj.UniqueID;
+                               } break;
+                       case EventType.Types.RUN:
+                               if(lastRunIsSimple) {
+                                       type = Constants.TestTypes.RUN;
+                                       id = currentRun.UniqueID;
+                               } else {
+                                       type = Constants.TestTypes.RUN_I;
+                                       id = currentRunInterval.UniqueID;
+                               }
+                               break;
+                       case EventType.Types.PULSE:
+                               type = Constants.TestTypes.PULSE;
+                               id = currentPulse.UniqueID;
+                               break;
+                       case EventType.Types.REACTIONTIME:
+                               type = Constants.TestTypes.RT;
+                               id = currentReactionTime.UniqueID;
+                               break;
+                       case EventType.Types.MULTICHRONOPIC:
+                               type = Constants.TestTypes.MULTICHRONOPIC;
+                               id = currentMultiChronopic.UniqueID;
+                               break;
+               }
+
+               playVideo(Util.GetVideoFileName(currentSession.UniqueID, type, id));
+       }
+
+       private void on_video_play_selected_jump_clicked (object o, EventArgs args) {
+               if (myTreeViewJumps.EventSelectedID > 0)
+                       playVideo(Util.GetVideoFileName(currentSession.UniqueID,
+                                               Constants.TestTypes.JUMP,
+                                               myTreeViewJumps.EventSelectedID));
+       }
+
+       private void on_video_play_selected_jump_rj_clicked (object o, EventArgs args) {
+               if (myTreeViewJumpsRj.EventSelectedID > 0)
+                       playVideo(Util.GetVideoFileName(currentSession.UniqueID,
+                                               Constants.TestTypes.JUMP_RJ,
+                                               myTreeViewJumpsRj.EventSelectedID));
+       }
+
+       private void on_video_play_selected_run_clicked (object o, EventArgs args) {
+               if (myTreeViewRuns.EventSelectedID > 0)
+                       playVideo(Util.GetVideoFileName(currentSession.UniqueID,
+                                               Constants.TestTypes.RUN,
+                                               myTreeViewRuns.EventSelectedID));
+       }
+
+       private void on_video_play_selected_run_interval_clicked (object o, EventArgs args) {
+               if (myTreeViewRunsInterval.EventSelectedID > 0)
+                       playVideo(Util.GetVideoFileName(currentSession.UniqueID,
+                                               Constants.TestTypes.RUN_I,
+                                               myTreeViewRunsInterval.EventSelectedID));
+       }
+
+       private void on_video_play_selected_reaction_time_clicked (object o, EventArgs args) {
+               if (myTreeViewReactionTimes.EventSelectedID > 0)
+                       playVideo(Util.GetVideoFileName(currentSession.UniqueID,
+                                               Constants.TestTypes.RT,
+                                               myTreeViewReactionTimes.EventSelectedID));
+       }
+
+       private void on_video_play_selected_pulse_clicked (object o, EventArgs args) {
+               if (myTreeViewPulses.EventSelectedID > 0)
+                       playVideo(Util.GetVideoFileName(currentSession.UniqueID,
+                                               Constants.TestTypes.PULSE,
+                                               myTreeViewPulses.EventSelectedID));
+       }
+
+       private void on_video_play_selected_multi_chronopic_clicked (object o, EventArgs args) {
+               if (myTreeViewMultiChronopic.EventSelectedID > 0)
+                       playVideo(Util.GetVideoFileName(currentSession.UniqueID,
+                                               Constants.TestTypes.MULTICHRONOPIC,
+                                               myTreeViewMultiChronopic.EventSelectedID));
+       }
+
+       private void on_button_video_play_this_test_encoder_clicked (object o, EventArgs args)
+       {
+               playVideo(Util.GetVideoFileName(currentSession.UniqueID,
+                               Constants.TestTypes.ENCODER, Convert.ToInt32(encoderSignalUniqueID)));
+       }
+
 }
diff --git a/src/webcam.cs b/src/webcam.cs
index 191df103..a74103ca 100644
--- a/src/webcam.cs
+++ b/src/webcam.cs
@@ -151,7 +151,7 @@ public abstract class Webcam
        //short process, to do end capture (good if there's more than one camera to end capture all at same 
time)
        public abstract Result VideoCaptureEnd();
 
-       public abstract Result ExitAndFinish (int sessionID, Constants.TestTypes testType, int testID);
+       public abstract Result ExitAndFinish (int sessionID, Constants.TestTypes testType, int testID, bool 
moveTempFiles);
 
        public abstract void ExitCamera();
 
@@ -178,6 +178,8 @@ public class WebcamManage
        private UtilAll.OperatingSystems os;
        //TODO: implement an List<T> of objects containing webcam and video device
 
+       public enum GuiContactsEncoder { CONTACTS, ENCODER }
+
        public WebcamManage()
        {
                os = UtilAll.GetOSEnum();
@@ -259,17 +261,20 @@ public class WebcamManage
                return result;
        }
 
-       public Webcam.Result ExitAndFinish (int ncam, int sessionID, Constants.TestTypes testType, int testID)
+       public Webcam.Result ExitAndFinish (int ncam, int sessionID,
+                       Constants.TestTypes testType, int testID, GuiContactsEncoder guiContactsEncoder)
        {
+               bool moveTempFiles = guiContactsEncoder == GuiContactsEncoder.CONTACTS;
                if(ncam == 1)
-                       return exitAndFinishDo (ref webcam, sessionID, testType, testID);
+                       return exitAndFinishDo (ref webcam, sessionID, testType, testID, moveTempFiles);
                else //ncam == 2
-                       return exitAndFinishDo (ref webcam2, sessionID, testType, testID);
+                       return exitAndFinishDo (ref webcam2, sessionID, testType, testID, moveTempFiles);
        }
 
-       private Webcam.Result exitAndFinishDo (ref Webcam webcam, int sessionID, Constants.TestTypes 
testType, int testID)
+       private Webcam.Result exitAndFinishDo (ref Webcam webcam, int sessionID,
+                       Constants.TestTypes testType, int testID, bool moveTempFiles)
        {
-               return webcam.ExitAndFinish (sessionID, testType, testID);
+               return webcam.ExitAndFinish (sessionID, testType, testID, moveTempFiles);
        }
 
        public static bool RecordingFileStarted ()
diff --git a/src/webcamFfmpeg.cs b/src/webcamFfmpeg.cs
index b41769bd..80108675 100644
--- a/src/webcamFfmpeg.cs
+++ b/src/webcamFfmpeg.cs
@@ -308,10 +308,13 @@ public class WebcamFfmpeg : Webcam
        }
 
         //can pass a -1 uniqueID if test is cancelled
-       public override Result ExitAndFinish (int sessionID, Constants.TestTypes testType, int testID)
+       public override Result ExitAndFinish (int sessionID, Constants.TestTypes testType, int testID, bool 
moveTempFiles)
        {
                ExitCamera();
 
+               if(! moveTempFiles)
+                       return new Result (true, "");
+
                //Copy the video to expected place
                //but only if the test has not been cancelled
                if(testID != -1)
diff --git a/src/webcamMplayer.cs b/src/webcamMplayer.cs
index 155fee87..6046fe4a 100644
--- a/src/webcamMplayer.cs
+++ b/src/webcamMplayer.cs
@@ -183,7 +183,7 @@ public class WebcamMplayer : Webcam
        }
 
 
-       public override Result ExitAndFinish (int sessionID, Constants.TestTypes testType, int testID)
+       public override Result ExitAndFinish (int sessionID, Constants.TestTypes testType, int testID, bool 
moveTempFiles)
        {
                ExitCamera();
 
@@ -194,6 +194,9 @@ public class WebcamMplayer : Webcam
                if(! convertImagesToVideo())
                        return new Result (false, "", programFfmpegNotInstalled);
 
+               if(! moveTempFiles)
+                       return new Result (true, "");
+
                //Copy the video to expected place
                if (! Util.CopyTempVideo(sessionID, testType, testID))
                        return new Result (false, "", Constants.FileCopyProblem);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]