db6bdd65f97901d17df735e59fdac7842337b19e
[glsdk/dual-decode.git] / src / gui.c
1 /*
2  *  Copyright (c) 2012-2013, Texas Instruments Incorporated
3  *
4  *  Redistribution and use in source and binary forms, with or without
5  *  modification, are permitted provided that the following conditions
6  *  are met:
7  *
8  *  *  Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer.
10  *
11  *  *  Redistributions in binary form must reproduce the above copyright
12  *     notice, this list of conditions and the following disclaimer in the
13  *     documentation and/or other materials provided with the distribution.
14  *
15  *  *  Neither the name of Texas Instruments Incorporated nor the names of
16  *     its contributors may be used to endorse or promote products derived
17  *     from this software without specific prior written permission.
18  *
19  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21  *  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  *  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23  *  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24  *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25  *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26  *  OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27  *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28  *  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
29  *  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  *
31  *  Contact information for paper mail:
32  *  Texas Instruments
33  *  Post Office Box 655303
34  *  Dallas, Texas 75265
35  *  Contact information:
36  *  http://www-k.ext.ti.com/sc/technical-support/product-information-centers.htm
37  *  ?DCMP=TIHomeTracking&HQS=Other+OT+home_d_contact
38  *  ============================================================================
39  *
40  */
42 /**
43  * @file                gui.c
44  *
45  * @brief               Defines the functions exported by the GUI.
46  *                              Also, defines the static functions and the callback funtions
47  */
48 #include <string.h>
49 #include <linux/limits.h>
50 #include <gtk/gtk.h>
51 #include <gdk/gdkx.h>                                                           
52 #include <gst/interfaces/xoverlay.h>  
54 #include <gui.h>
55 #include <common.h>
56 #include <gst-controller.h>
58 /******************************************************************************
59  *      Static variables declaration
60  ******************************************************************************/
61 static GUIWindow *window[]              = {NULL, NULL};
62 static Pipeline *pipes[]                = {NULL, NULL};
63 static GtkWidget *logWindow[]   = {NULL, NULL};
64 static GtkWidget *helpWindow    = NULL;
67 /******************************************************************************
68  *      Static functions declaration
69  ******************************************************************************/
70 static gint setAbsolutePathname (gchar *file, gchar **uri)  ;
71 static void setControlMode (GUIWindow *thisWindow,gint modeFlag,gint activeFlag);
72 static void setControlActive (GUIWindow *window, gboolean activeFlag);
73 static void setup();
74 static void setDecodeSwitch (gint decodeSwitch);
75 static GtkWidget *createLogWindow();
76 static GtkWidget *createHelpWindow();
77 static GstElement *createImageSinkFromWindow (GtkWidget * window, gchar *name);
78 static void setWindowSizeLocation();
79 static GUIWindow *createWindow();
81 static gboolean cbOpenClicked (GtkWidget *widget, gpointer data);
82 static gboolean cbPlayClicked (GtkWidget *widget, gpointer data);
83 static gboolean cbPauseClicked (GtkWidget *widget, gpointer data);
84 static gboolean cbStopClicked (GtkWidget *widget, gpointer data);
85 static gboolean cbWindowClosed (GtkWidget *widget, gpointer data);
86 static gboolean cbHelpClicked (GtkWidget *widget, gpointer data);
87 static gboolean cbTimerInterval (gpointer data);
88 static gboolean cbSeekValueChanged (GtkWidget *widget, gpointer data);
89 static gboolean cbSwitchButtonClicked (GtkWidget *widget, gpointer data);
90 static gboolean cbHelpClosed (GtkWidget *widget, gpointer data);
91 //static void logGUI (GtkWidget *logWindow, gchar *format, ...); 
93 static gint setAbsolutePathname (gchar *file, gchar **uri)                             
94 {                                                                               
95     gchar *realPath = NULL;                                                     
96     gint ret        = ERR_SUCCESS;                                              
97                                                                                 
98     if(NULL == uri){                                                            
99         return ERR_INVALIDPARAM;                                                
100     }                                                                           
101                                                                                 
102     if(NULL == file){                                                           
103         /*A BUG Here*/                                                          
104         g_printerr("BUG: file: " __FILE__ " line: %d" "\n", __LINE__);          
105         return ERR_BUG;                                                         
106     }                                                                           
107                                                                                 
108     *uri = (gchar *) g_malloc (sizeof(gchar) * PATH_MAX_LEN);                   
109     realPath = realpath (file, realPath);                                       
110     if (NULL == realPath) {                                                     
111         /*TODO: a debug trace here*/                                            
112         g_printerr ("File %s not found\n", file);                               
113         ret = ERR_FILENOTFOUND;                                                 
114         goto destroy;                                                           
115     }                                                                           
116     g_snprintf(*uri,PATH_MAX_LEN,"file://%s",realPath);                         
117                                                                                 
118     goto last;                                                                  
119                                                                                 
120 destroy:                                                                        
121     g_free(*uri);                                                               
122     *uri=NULL;                                                                  
123 last:                                                                           
124     free (realPath);                                                            
125     return ret;                                                                 
126 }        
127 /******************************************************************************
128  *      Callback functions definition
129  ******************************************************************************/
131 /*Timer Interval Callback Function*/
132 static gboolean cbTimerInterval(gpointer data)
134         gdouble seekScaleValue = 0.0;
135         gchar *timeLabelText = TIME_LABEL_ORIGIN;
136         GUIWindow *thisWindow = (GUIWindow *)data;
137         gboolean ret = TRUE;
138     
139     //g_print ("IN timer");
140         if (DECODE_MODE_SINGLE == decodeMode){
141                 ret = DualDecode_getMediaPosition(pipes[DECODER_INDEX_SINGLE],
142                                 &seekScaleValue,
143                                 &timeLabelText);
144         //g_print ("Seek Value %f", seekScaleValue);
146                 g_signal_handler_block (window[DECODER_INDEX_SINGLE]->seekScale,
147                                 window[DECODER_INDEX_SINGLE]->seekSignal);
148         gtk_range_set_value (GTK_RANGE(window[DECODER_INDEX_SINGLE]->seekScale),
149                                 seekScaleValue);
150                 gtk_label_set_text (GTK_LABEL (window[DECODER_INDEX_SINGLE]->timeLabel),
151                                 timeLabelText);
152                 g_signal_handler_unblock (GTK_RANGE (window[DECODER_INDEX_SINGLE]->seekScale),
153                                 window[DECODER_INDEX_SINGLE]->seekSignal);
155                 g_signal_handler_block(GTK_RANGE (window[DECODER_INDEX_DOUBLE]->seekScale),
156                                 window[DECODER_INDEX_DOUBLE]->seekSignal);
157                 gtk_range_set_value(GTK_RANGE (window[DECODER_INDEX_DOUBLE]->seekScale),
158                                 seekScaleValue);
159                 gtk_label_set_text(GTK_LABEL (window[DECODER_INDEX_DOUBLE]->timeLabel),
160                                 timeLabelText);
161                 g_signal_handler_unblock(GTK_RANGE (window[DECODER_INDEX_DOUBLE]->seekScale),
162                                 window[DECODER_INDEX_DOUBLE]->seekSignal);
163         }else{
164                 if (window[DECODER_INDEX_SINGLE] == thisWindow){
165                         ret = DualDecode_getMediaPosition(pipes[DECODER_INDEX_SINGLE],
166                                         &seekScaleValue,
167                                         &timeLabelText);
168                         
169             g_signal_handler_block(GTK_RANGE(window[DECODER_INDEX_SINGLE]->seekScale),
170                                         window[DECODER_INDEX_SINGLE]->seekSignal);
171                         gtk_range_set_value(GTK_RANGE (window[DECODER_INDEX_SINGLE]->seekScale),
172                                         seekScaleValue);
173                         gtk_label_set_text(GTK_LABEL (window[DECODER_INDEX_SINGLE]->timeLabel),
174                                         timeLabelText);
175                         g_signal_handler_unblock(GTK_RANGE (window[DECODER_INDEX_SINGLE]->seekScale),
176                                         window[DECODER_INDEX_SINGLE]->seekSignal);
177                 }else{
178                         ret = DualDecode_getMediaPosition(pipes[DECODER_INDEX_DOUBLE],
179                                         &seekScaleValue,
180                                         &timeLabelText);
182                         g_signal_handler_block(GTK_RANGE (window[DECODER_INDEX_DOUBLE]->seekScale),
183                                         window[DECODER_INDEX_DOUBLE]->seekSignal);
184                         gtk_range_set_value(GTK_RANGE (window[DECODER_INDEX_DOUBLE]->seekScale),
185                                         seekScaleValue);
186                         gtk_label_set_text (GTK_LABEL(window[DECODER_INDEX_DOUBLE]->timeLabel),
187                                         timeLabelText);
188                         g_signal_handler_unblock(GTK_RANGE (window[DECODER_INDEX_DOUBLE]->seekScale),
189                                         window[DECODER_INDEX_DOUBLE]->seekSignal);
190                 }
191         }
192         if(ret){
193                 g_free(timeLabelText);
194         }
195     return ret;
198 /*Seek Scale Changed Value Callback Function*/
199 static gboolean cbSeekValueChanged(GtkWidget *widget, gpointer data)
201     gboolean ret = TRUE;
202     GstFormat format = GST_FORMAT_TIME; 
203     gint64 duration = 0;
204     gint seekPoint = 0;
205     gdouble percent = gtk_range_get_value ((GtkRange *)widget);
206     g_print ("PERCENT %f\n", percent);
207     GUIWindow *thisWindow = (GUIWindow *)data; 
209     g_print ("IN SEEK VALUE CHANGED\n");
210     if (DECODE_MODE_SINGLE == decodeMode){
211                                                                                     
212         gst_element_query_duration (pipes[DECODER_INDEX_SINGLE]->pipe,
213                                     &format,&duration);
214         seekPoint = (gint64) (duration * percent/ (gdouble)100);
215         g_print ("SEEK POINT %d\n", seekPoint);
216         ret = DualDecode_seekMedia(pipes[DECODER_INDEX_SINGLE], seekPoint);
217     }
218     else{                                                                      
219         if(window[DECODER_INDEX_SINGLE] == thisWindow){    
220             gst_element_query_duration (pipes[DECODER_INDEX_SINGLE]->pipe,
221                                         &format,&duration);              
222             seekPoint = (gint64) (duration * percent/ (gdouble)100);
223             ret = DualDecode_seekMedia(pipes[DECODER_INDEX_SINGLE], seekPoint);
224         } 
225         else {
226             gst_element_query_duration(pipes[DECODER_INDEX_SINGLE]->pipe,
227                                        &format,&duration);              
228             seekPoint = (gint64) (duration * percent/ (gdouble)100);
229             ret = DualDecode_seekMedia(pipes[DECODER_INDEX_DOUBLE], seekPoint); 
230         }
231     }   
232     
233         return ret;
236 /*Open Button Clicked Callback Function*/
237 static gboolean cbOpenClicked(GtkWidget *widget, gpointer data)
239     gboolean ret = TRUE;
240     gchar *uri = NULL;
241     gchar *file = NULL;
242         GUIWindow *thisWindow = (GUIWindow *)data;
243         GtkWidget *fileChooser = gtk_file_chooser_dialog_new(
244                         "Open",
245                         GTK_WINDOW(thisWindow->window),
246                         GTK_FILE_CHOOSER_ACTION_OPEN,
247                         GTK_STOCK_OPEN,
248                         GTK_RESPONSE_OK,
249                         GTK_STOCK_CANCEL,
250                         GTK_RESPONSE_CANCEL,
251                         NULL);
252         gtk_window_set_modal(GTK_WINDOW(fileChooser),TRUE);
253         gtk_window_set_destroy_with_parent(GTK_WINDOW(fileChooser),TRUE);
254         gtk_widget_set_sensitive(thisWindow->window,FALSE);
255         
256         if(GTK_RESPONSE_OK == gtk_dialog_run(GTK_DIALOG(fileChooser))){
257                 
258                 file = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fileChooser));
259                 
260         if (ERR_SUCCESS != setAbsolutePathname (file, &uri)){
261             ret = FALSE;
262             goto last;
263         }
264         //g_print ("FILE URI :%s", uri);
265                 if(DECODE_MODE_SINGLE == decodeMode){
266             filename[DECODER_INDEX_SINGLE] = uri;
267                         setControlMode(window[DECODER_INDEX_SINGLE],
268                                         CONTROL_MODE_PLAYING,
269                                         window[DECODER_INDEX_SINGLE]->activeFlag);
270                         setControlMode(window[DECODER_INDEX_DOUBLE],
271                                         CONTROL_MODE_PLAYING,
272                                         window[DECODER_INDEX_DOUBLE]->activeFlag);
273                         DualDecode_playMedia(pipes[DECODER_INDEX_SINGLE],
274                                         filename[DECODER_INDEX_SINGLE],
275                                         SEEK_START);
276                 }else{
277             filename[DECODER_INDEX_SINGLE] = uri;
278                         if(window[DECODER_INDEX_SINGLE] == thisWindow){
279                                 setControlMode(window[DECODER_INDEX_SINGLE],
280                                                 CONTROL_MODE_PLAYING,
281                                                 window[DECODER_INDEX_SINGLE]->activeFlag);
282                                 DualDecode_playMedia(pipes[DECODER_INDEX_SINGLE],
283                                                 filename[DECODER_INDEX_SINGLE],
284                                                 SEEK_START);
285                         }else{
286                 filename[DECODER_INDEX_DOUBLE] = uri;   
287                                 setControlMode(window[DECODER_INDEX_DOUBLE],
288                                                 CONTROL_MODE_PLAYING,
289                                                 window[DECODER_INDEX_DOUBLE]->activeFlag);
290                                 DualDecode_playMedia(pipes[DECODER_INDEX_DOUBLE],
291                                                 filename[DECODER_INDEX_DOUBLE],
292                                                 SEEK_START);
293                         }
294                 }
295         }
296         if (GTK_IS_WIDGET (fileChooser))
297                 gtk_widget_destroy (fileChooser);
299         if( GTK_IS_WIDGET (thisWindow->window))
300                 gtk_widget_set_sensitive (thisWindow->window,TRUE);
302 last:    return ret;
305 /*Play Button Clicked Callback Function*/
306 static gboolean cbPlayClicked(GtkWidget *widget, gpointer data)
308         gboolean ret = TRUE;
309     GUIWindow *thisWindow = (GUIWindow *)data;
311         if(DECODE_MODE_SINGLE == decodeMode){
312                 setControlMode(window[DECODER_INDEX_SINGLE],
313                                 CONTROL_MODE_PLAYING,
314                                 window[DECODER_INDEX_SINGLE]->activeFlag);
315                 setControlMode(window[DECODER_INDEX_DOUBLE],
316                                 CONTROL_MODE_PLAYING,
317                                 window[DECODER_INDEX_DOUBLE]->activeFlag);
318                 if(GST_STATE_PAUSED == 
319                                 DualDecode_getMediaState(pipes[DECODER_INDEX_SINGLE])){
320                         DualDecode_resumeMedia(pipes[DECODER_INDEX_SINGLE]);
321                 }else{
322                         DualDecode_playMedia(pipes[DECODER_INDEX_SINGLE],
323                                         filename[DECODER_INDEX_SINGLE],
324                                         SEEK_START);
325              }
326         }else{
327                 if(window[DECODER_INDEX_SINGLE] == thisWindow){
328                         setControlMode(window[DECODER_INDEX_SINGLE],
329                                         CONTROL_MODE_PLAYING,
330                                         window[DECODER_INDEX_SINGLE]->activeFlag);
331                         if(GST_STATE_PAUSED == 
332                                         DualDecode_getMediaState(pipes[DECODER_INDEX_SINGLE])){
333                                 DualDecode_resumeMedia(pipes[DECODER_INDEX_SINGLE]);
334                         }else{
335                                 DualDecode_playMedia(pipes[DECODER_INDEX_SINGLE],
336                                                 filename[DECODER_INDEX_SINGLE],
337                                                 SEEK_START);
338                         }
339                 }else{
340                         setControlMode(window[DECODER_INDEX_DOUBLE],
341                                         CONTROL_MODE_PLAYING,
342                                         window[DECODER_INDEX_DOUBLE]->activeFlag);
343                         if(GST_STATE_PAUSED == 
344                                         DualDecode_getMediaState(pipes[DECODER_INDEX_DOUBLE])){
345                                 DualDecode_resumeMedia(pipes[DECODER_INDEX_DOUBLE]);
346                         }else{
347                                 DualDecode_playMedia(pipes[DECODER_INDEX_DOUBLE],
348                                                 filename[DECODER_INDEX_DOUBLE],
349                                                 SEEK_START);
350                         }
351                 }
352         }
353     return ret;
356 /*Pause Button Clicked Callback Function*/
357 static gboolean cbPauseClicked(GtkWidget *widget, gpointer data)
359         gboolean ret = TRUE;
360     GUIWindow *thisWindow = (GUIWindow *)data;
362         if(DECODE_MODE_SINGLE == decodeMode){
363                 setControlMode(window[DECODER_INDEX_SINGLE],
364                                 CONTROL_MODE_PAUSED,
365                                 window[DECODER_INDEX_SINGLE]->activeFlag);
366                 setControlMode(window[DECODER_INDEX_DOUBLE],
367                                 CONTROL_MODE_PAUSED,
368                                 window[DECODER_INDEX_DOUBLE]->activeFlag);
369                 DualDecode_pauseMedia(pipes[DECODER_INDEX_SINGLE]);
370         }else{
371                 if(window[DECODER_INDEX_SINGLE] == thisWindow){
372                         setControlMode(window[DECODER_INDEX_SINGLE],
373                                         CONTROL_MODE_PAUSED,
374                                         window[DECODER_INDEX_SINGLE]->activeFlag);
375                         DualDecode_pauseMedia(pipes[DECODER_INDEX_SINGLE]);
376                 }else{
377                         setControlMode(window[DECODER_INDEX_DOUBLE],
378                                         CONTROL_MODE_PAUSED,
379                                         window[DECODER_INDEX_DOUBLE]->activeFlag);
380                         DualDecode_pauseMedia(pipes[DECODER_INDEX_DOUBLE]);
381                 }
382         }
383     return ret;
386 /*Stop Button Clicked Callback Function*/
387 static gboolean cbStopClicked(GtkWidget *widget, gpointer data)
389         gboolean ret = TRUE;
390     GUIWindow *thisWindow = (GUIWindow *)data;
391    
393         if(DECODE_MODE_SINGLE == decodeMode){
394                 setControlMode(window[DECODER_INDEX_SINGLE],
395                                 CONTROL_MODE_STOPPED,
396                                 window[DECODER_INDEX_SINGLE]->activeFlag);
397                 setControlMode(window[DECODER_INDEX_DOUBLE],
398                                 CONTROL_MODE_STOPPED,
399                                 window[DECODER_INDEX_DOUBLE]->activeFlag);
400                 DualDecode_stopMedia(pipes[DECODER_INDEX_SINGLE]);
401         }else{
402                 if(window[DECODER_INDEX_SINGLE] == thisWindow){
403                         setControlMode(window[DECODER_INDEX_SINGLE],
404                                         CONTROL_MODE_STOPPED,
405                                         window[DECODER_INDEX_SINGLE]->activeFlag);
406                         DualDecode_stopMedia(pipes[DECODER_INDEX_SINGLE]);
407                 }else{
408                         setControlMode(window[DECODER_INDEX_DOUBLE],
409                                         CONTROL_MODE_STOPPED,
410                                         window[DECODER_INDEX_DOUBLE]->activeFlag);
411                         DualDecode_stopMedia(pipes[DECODER_INDEX_DOUBLE]);
412                 }
413         }
414     return ret;
416 static gboolean cbSwitchButtonClicked (GtkWidget *widget, gpointer data)
418     gboolean ret = TRUE;
419     gboolean noFile = FALSE;
420     GUIWindow *thisWindow = (GUIWindow *) data;
421     gint otherWindowIndex = 0;
422     gint thisWindowIndex = 0;
424     /*No file is given yet to play. Application may be just started. */
425     if (NULL == filename[DECODER_INDEX_SINGLE])
426         noFile = TRUE;
428          
429         
431     if (thisWindow == window[DECODER_INDEX_SINGLE]){
432         thisWindowIndex = DECODER_INDEX_SINGLE;
433         otherWindowIndex = DECODER_INDEX_DOUBLE;
434     }
435     else {
436         otherWindowIndex = DECODER_INDEX_SINGLE;
437         thisWindowIndex = DECODER_INDEX_DOUBLE;
438     }
440     switch (decodeMode)
441     {
442       case DECODE_MODE_SINGLE :  
443           setControlMode (window[otherWindowIndex], window[otherWindowIndex]->modeFlag, 
444                           CONTROL_MODE_ACTIVE);
445           setControlMode (thisWindow, thisWindow->modeFlag,       
446                           CONTROL_MODE_ACTIVE);
448           if (FALSE == noFile) {
449           ret = DualDecode_singleToDual (pipes,
450                                          window[otherWindowIndex]->sink,
451                                          thisWindowIndex, otherWindowIndex, 
452                                          filename[DECODER_INDEX_SINGLE]);
453           }
454           decodeMode = DECODE_MODE_DUAL;
455           setDecodeSwitch(DECODE_MODE_SINGLE);
456           break;
458       case DECODE_MODE_DUAL :      
459           setControlMode (window[otherWindowIndex], thisWindow->modeFlag, 
460                           CONTROL_MODE_INACTIVE);  
462           if (FALSE == noFile) {
463           ret = DualDecode_dualToSingle (pipes,
464                                          window[otherWindowIndex]->sink,        
465                                          thisWindowIndex, otherWindowIndex);
466            }
467            decodeMode = DECODE_MODE_SINGLE; 
468            setDecodeSwitch(DECODE_MODE_DUAL);  
469           
470           break;
471     } 
474     return ret;
476 /*Window Close Callback Function*/
477 static gboolean cbWindowClosed(GtkWidget *widget, gpointer data){
478         DualDecode_exitApplication();
479     return TRUE;
482 static gboolean cbHelpClicked (GtkWidget *widget, gpointer data){
483     g_print ("HELP BUTTON CLICKED\n");
484     gtk_widget_show (helpWindow);
485     return TRUE;
488 static gboolean cbHelpClosed (GtkWidget *widget, gpointer data){
489     g_print ("IN HELP CLOSED\n");
490     gtk_widget_hide (helpWindow);
491     return TRUE;
493 /******************************************************************************
494  *      static utility functions definition
495  ******************************************************************************/
496 static void setControlActive(GUIWindow *window, gboolean activeFlag)
498         gtk_widget_set_sensitive(window->playButton,activeFlag);
499         gtk_widget_set_sensitive(window->pauseButton,activeFlag);
500         gtk_widget_set_sensitive(window->stopButton,activeFlag);
501         gtk_widget_set_sensitive(window->rewindButton,activeFlag);
502         gtk_widget_set_sensitive(window->forwardButton,activeFlag);
503         gtk_widget_set_sensitive(window->openButton,activeFlag);
504         gtk_widget_set_sensitive(window->seekScale,activeFlag);
505     gtk_widget_set_sensitive (window->switchButton, activeFlag);
506     
509 static void setControlMode(GUIWindow *thisWindow,
510                 gint modeFlag,
511                 gint activeFlag)
513         setControlActive(thisWindow, activeFlag);
514         if(activeFlag){
515                 switch(modeFlag){
516                         case CONTROL_MODE_NO_FILE:
517                                 gtk_widget_set_sensitive(thisWindow->playButton,FALSE);
518                                 gtk_widget_set_sensitive(thisWindow->pauseButton,FALSE);
520                                 gtk_widget_set_sensitive(thisWindow->stopButton,FALSE);
521                                 gtk_widget_set_sensitive(thisWindow->rewindButton,FALSE);
522                                 gtk_widget_set_sensitive(thisWindow->forwardButton,FALSE);
523                                 gtk_widget_set_sensitive(thisWindow->seekScale,FALSE);
525                                 break;
526                         case CONTROL_MODE_PLAYING:
527                                 gtk_widget_set_sensitive(thisWindow->playButton,TRUE);
528                                 gtk_widget_set_sensitive(thisWindow->pauseButton,TRUE);
530                                 gtk_widget_set_sensitive(thisWindow->stopButton,TRUE);
531                                 gtk_widget_set_sensitive(thisWindow->rewindButton,TRUE);
532                                 gtk_widget_set_sensitive(thisWindow->forwardButton,TRUE);
533                                 gtk_widget_set_sensitive(thisWindow->seekScale,TRUE);
535                                 break;
536                         case CONTROL_MODE_STOPPED:
537                                 gtk_widget_set_sensitive(thisWindow->playButton,TRUE);
538                                 gtk_widget_set_sensitive(thisWindow->pauseButton,TRUE);
540                                 gtk_widget_set_sensitive(thisWindow->stopButton,TRUE);
541                                 gtk_widget_set_sensitive(thisWindow->rewindButton,TRUE);
542                                 gtk_widget_set_sensitive(thisWindow->forwardButton,TRUE);
543                                 gtk_widget_set_sensitive(thisWindow->seekScale,FALSE);
545                                 break;
546                         case CONTROL_MODE_PAUSED:
547                                 gtk_widget_set_sensitive(thisWindow->playButton,TRUE);
548                                 gtk_widget_set_sensitive(thisWindow->pauseButton,TRUE);
550                                 gtk_widget_set_sensitive(thisWindow->stopButton,TRUE);
551                                 gtk_widget_set_sensitive(thisWindow->rewindButton,TRUE);
552                                 gtk_widget_set_sensitive(thisWindow->forwardButton,TRUE);
553                                 gtk_widget_set_sensitive(thisWindow->seekScale,TRUE);
555                                 break;
556                 }
557         }
558         switch(modeFlag){
559                 case CONTROL_MODE_NO_FILE:
560                         gtk_widget_show(thisWindow->playButton);
561                         gtk_widget_hide(thisWindow->pauseButton);
563                         gtk_label_set_text(GTK_LABEL(thisWindow->statusLabel),
564                                         LABEL_TEXT_NO_FILE);
565                         gtk_label_set_text(GTK_LABEL(thisWindow->timeLabel),
566                                         TIME_LABEL_ORIGIN);
567                         if(thisWindow->timerSignal != TIMER_SIGNAL_NONE){
568                                 g_source_remove(thisWindow->timerSignal);
569                                 thisWindow->timerSignal = TIMER_SIGNAL_NONE;
570                         }
571                         break;
572                 case CONTROL_MODE_PLAYING:
573                         gtk_widget_show(thisWindow->pauseButton);
574                         gtk_widget_hide(thisWindow->playButton);
576                         gtk_label_set_text(GTK_LABEL(thisWindow->statusLabel),
577                                         LABEL_TEXT_PLAYING);
578                         gtk_label_set_text(GTK_LABEL(thisWindow->timeLabel),
579                                         TIME_LABEL_ORIGIN);
581                         if(thisWindow->timerSignal != TIMER_SIGNAL_NONE){
582                                 g_source_remove(thisWindow->timerSignal);
583             }
584                         thisWindow->timerSignal = g_timeout_add(TIMER_INTERVAL,
585                                                 cbTimerInterval,
586                                                 thisWindow); 
587                         
588                         break;
589                 case CONTROL_MODE_STOPPED:
590                         gtk_widget_show(thisWindow->playButton);
591                         gtk_widget_hide(thisWindow->pauseButton);
593                         gtk_label_set_text(GTK_LABEL(thisWindow->statusLabel),
594                                         LABEL_TEXT_STOPPED);
595                         gtk_label_set_text(GTK_LABEL(thisWindow->timeLabel),
596                                         TIME_LABEL_ORIGIN);
598                         if(thisWindow->timerSignal != TIMER_SIGNAL_NONE){
599                                 g_source_remove(thisWindow->timerSignal);
600                                 thisWindow->timerSignal = TIMER_SIGNAL_NONE;
601                         }
602                         break;
603                 case CONTROL_MODE_PAUSED:
604                         gtk_widget_show(thisWindow->playButton);
605                         gtk_widget_hide(thisWindow->pauseButton);
607                         gtk_label_set_text(GTK_LABEL(thisWindow->statusLabel),
608                                         LABEL_TEXT_PAUSED);
609                         break;
611         }
612         thisWindow->modeFlag = modeFlag;
613         thisWindow->activeFlag = activeFlag;
616 static void setDecodeSwitch(gint decodeSwitch)
618         switch (decodeSwitch){
619                 case DECODE_MODE_SINGLE:
620                         gtk_button_set_label(
621                                         GTK_BUTTON(window[DECODER_INDEX_SINGLE]->switchButton),
622                                         SWITCH_TEXT_SINGLE);
623                         gtk_button_set_label(
624                                         GTK_BUTTON(window[DECODER_INDEX_DOUBLE]->switchButton),
625                                         SWITCH_TEXT_SINGLE);
626                         break;
627                 case DECODE_MODE_DUAL:
628                         gtk_button_set_label(
629                                         GTK_BUTTON(window[DECODER_INDEX_SINGLE]->switchButton),
630                                         SWITCH_TEXT_DUAL);
631                         gtk_button_set_label(
632                                         GTK_BUTTON(window[DECODER_INDEX_DOUBLE]->switchButton),
633                                         SWITCH_TEXT_DUAL);
634         }
637 static void setup()
640     g_print ("SINK TO BE USED %s\n", sink);
641         gtk_widget_show_all(window[DECODER_INDEX_SINGLE]->window);
642         gtk_widget_show_all(window[DECODER_INDEX_DOUBLE]->window);
644     window[DECODER_INDEX_SINGLE]->sink = createImageSinkFromWindow (            
645                                         window[DECODER_INDEX_SINGLE]->drawArea, 
646                                         "windowsink0"); 
648     window[DECODER_INDEX_DOUBLE]->sink = createImageSinkFromWindow (           
649                                         window[DECODER_INDEX_DOUBLE]->drawArea, 
650                                         "windowsink1"); 
652     /*If any of the sinks is NULL the application exits*/
654     if (NULL == window[DECODER_INDEX_SINGLE]->sink || 
655         NULL == window[DECODER_INDEX_DOUBLE]->sink) {
656             DualDecode_exitApplication();
657     
658     }
659     //DualDecode_setSinksForPipes (pipes,window[DECODER_INDEX_SINGLE]->sink,
660      //                            window[DECODER_INDEX_DOUBLE]->sink);
661         switch(decodeMode){
662                 case DECODE_MODE_NONE:
663                         setControlMode(window[DECODER_INDEX_SINGLE],
664                                         CONTROL_MODE_NO_FILE,
665                                         CONTROL_MODE_ACTIVE);
666                         setControlMode(window[DECODER_INDEX_DOUBLE],
667                                         CONTROL_MODE_NO_FILE,
668                                         CONTROL_MODE_ACTIVE);
669              DualDecode_setPipelineSink (pipes[DECODER_INDEX_SINGLE], window[DECODER_INDEX_SINGLE]->sink,
670                                               NULL);                            
671              DualDecode_setPipelineSink (pipes[DECODER_INDEX_DOUBLE], window[DECODER_INDEX_DOUBLE]->sink,
672                                               NULL);
673                         decodeMode = DECODE_MODE_DUAL;
674                         setDecodeSwitch(DECODE_MODE_SINGLE);
675                         break;
676                 case DECODE_MODE_SINGLE:
677                         setControlMode (window[DECODER_INDEX_SINGLE],
678                                         CONTROL_MODE_PLAYING,
679                                         CONTROL_MODE_ACTIVE);
680                         setControlMode (window[DECODER_INDEX_DOUBLE],
681                                         CONTROL_MODE_PLAYING,
682                                         CONTROL_MODE_INACTIVE);
683             DualDecode_setPipelineSink (pipes[DECODER_INDEX_SINGLE], window[DECODER_INDEX_SINGLE]->sink,
684                                               window[DECODER_INDEX_DOUBLE]->sink);
685             DualDecode_setPipelineSink (pipes[DECODER_INDEX_DOUBLE], NULL,
686                                             NULL);
687                         DualDecode_playMedia (pipes[DECODER_INDEX_SINGLE],
688                                         filename[DECODER_INDEX_SINGLE],
689                                         SEEK_START);
690                         setDecodeSwitch(DECODE_MODE_DUAL);
691                         break;
692                 case DECODE_MODE_DUAL:
693                         setControlMode(window[DECODER_INDEX_SINGLE],
694                                         CONTROL_MODE_PLAYING,
695                                         CONTROL_MODE_ACTIVE);
696              DualDecode_setPipelineSink (pipes[DECODER_INDEX_SINGLE], window[DECODER_INDEX_SINGLE]->sink,
697                                               NULL);
698              DualDecode_setPipelineSink (pipes[DECODER_INDEX_DOUBLE], window[DECODER_INDEX_DOUBLE]->sink,
699                                               NULL);
701                         DualDecode_playMedia(pipes[DECODER_INDEX_SINGLE],
702                                         filename[DECODER_INDEX_SINGLE],
703                                         SEEK_START);
704                         setControlMode(window[DECODER_INDEX_DOUBLE],
705                                         CONTROL_MODE_PLAYING,
706                                         CONTROL_MODE_ACTIVE);
707                         DualDecode_playMedia(pipes[DECODER_INDEX_DOUBLE],
708                                         filename[DECODER_INDEX_DOUBLE],
709                                         SEEK_START);
710                         setDecodeSwitch(DECODE_MODE_SINGLE);
711                         break;
712         }
715 static GUIWindow *createWindow()
717         GUIWindow *ret  = NULL;
718         ret = g_malloc0(sizeof(GUIWindow));
719         if(NULL == ret){
720                 return ret;
721         }
722         DualDecode_builderCreate();
724         ret->window = DualDecode_getWidget("decodeWindowSingle");
725         if(NULL == ret->window){
726                 goto memCleanup;
727         }
728         ret->windowCloseSignal = g_signal_connect(G_OBJECT(ret->window),
729                         "delete-event",
730                         G_CALLBACK(cbWindowClosed),
731                         NULL);
733         GtkWidget *toolbar = DualDecode_getWidget("toolbarSingle");
734         if(NULL == toolbar){
735                 goto memCleanup;
736         }
737         ret->drawArea = DualDecode_getWidget("videoViewerSingle");
738         if(NULL == ret->drawArea){
739                 goto memCleanup;
740         }
742         ret->openButton = GTK_WIDGET(
743                         gtk_tool_button_new_from_stock(GTK_STOCK_OPEN));
744         if(NULL == ret->openButton){
745                 goto memCleanup;
746         }
747         ret->rewindButton = GTK_WIDGET(
748                         gtk_tool_button_new_from_stock(GTK_STOCK_MEDIA_REWIND));
749         if(NULL == ret->rewindButton){
750                 goto memCleanup;
751         }
752         ret->playButton = GTK_WIDGET(
753                         gtk_tool_button_new_from_stock(GTK_STOCK_MEDIA_PLAY));
754         if(NULL == ret->playButton){
755                 goto memCleanup;
756         }
757         ret->pauseButton = GTK_WIDGET(
758                         gtk_tool_button_new_from_stock(GTK_STOCK_MEDIA_PAUSE));
759         if(NULL == ret->pauseButton){
760                 goto memCleanup;
761         }
762         ret->stopButton = GTK_WIDGET(
763                         gtk_tool_button_new_from_stock(GTK_STOCK_MEDIA_STOP));
764         if(NULL == ret->stopButton){
765                 goto memCleanup;
766         }
767         ret->forwardButton = GTK_WIDGET(
768                         gtk_tool_button_new_from_stock(GTK_STOCK_MEDIA_FORWARD));
769         if(NULL == ret->forwardButton){
770                 goto memCleanup;
771         }
772         ret->helpButton = GTK_WIDGET(
773                         gtk_tool_button_new_from_stock(GTK_STOCK_HELP));
774         if(NULL == ret->helpButton){
775                 goto memCleanup;
776         }
778         gtk_toolbar_insert(GTK_TOOLBAR(toolbar),
779                         GTK_TOOL_ITEM(ret->openButton),
780                         -1);
781         gtk_toolbar_insert(GTK_TOOLBAR(toolbar),
782                         gtk_separator_tool_item_new(),
783                         -1);
784         gtk_toolbar_insert(GTK_TOOLBAR(toolbar),
785                         GTK_TOOL_ITEM(ret->rewindButton),
786                         -1);
787         gtk_toolbar_insert(GTK_TOOLBAR(toolbar),
788                         GTK_TOOL_ITEM(ret->playButton),
789                         -1);
790         gtk_toolbar_insert(GTK_TOOLBAR(toolbar),
791                         GTK_TOOL_ITEM(ret->pauseButton),
792                         -1);
793         gtk_toolbar_insert(GTK_TOOLBAR(toolbar),
794                         GTK_TOOL_ITEM(ret->stopButton),
795                         -1);
796         gtk_toolbar_insert(GTK_TOOLBAR(toolbar),
797                         GTK_TOOL_ITEM(ret->forwardButton),
798                         -1);
799         gtk_toolbar_insert(GTK_TOOLBAR(toolbar),
800                         gtk_separator_tool_item_new(),
801                         -1);
802         gtk_toolbar_insert(GTK_TOOLBAR(toolbar),
803                         GTK_TOOL_ITEM(ret->helpButton),
804                         -1);
806         ret->openSignal = g_signal_connect(G_OBJECT(ret->openButton),
807                         "clicked",
808                         G_CALLBACK(cbOpenClicked),
809                         ret);
810         ret->stopSignal = g_signal_connect(G_OBJECT(ret->stopButton),
811                         "clicked",
812                         G_CALLBACK(cbStopClicked),
813                         ret);
814         ret->pauseSignal = g_signal_connect(G_OBJECT(ret->pauseButton),
815                         "clicked",
816                         G_CALLBACK(cbPauseClicked),
817                         ret);
818         ret->playSignal = g_signal_connect(G_OBJECT(ret->playButton),
819                         "clicked",
820                         G_CALLBACK(cbPlayClicked),
821                         ret);
823     ret->playSignal = g_signal_connect(G_OBJECT(ret->helpButton),               
824             "clicked",                                                          
825             G_CALLBACK(cbHelpClicked),                                          
826             ret);   
829         ret->switchButton = DualDecode_getWidget("switchButtonSingle");
830         if(NULL == ret->switchButton){
831                 goto memCleanup;
832         }
834         ret->switchSignal = g_signal_connect (G_OBJECT (ret->switchButton),
835                         "clicked",
836                         G_CALLBACK (cbSwitchButtonClicked),
837                         ret);
839         ret->seekScale = DualDecode_getWidget("seekScaleSingle");
840         if(NULL == ret->seekScale){
841                 goto memCleanup;
842         }
844     ret->seekSignal = g_signal_connect (G_OBJECT (ret->seekScale),
845              "value_changed",
846              G_CALLBACK (cbSeekValueChanged),
847              ret);
848         
850         ret->statusLabel = DualDecode_getWidget("statusLabelSingle");
851         if(NULL == ret->statusLabel){
852                 goto memCleanup;
853         }
855         ret->timeLabel = DualDecode_getWidget("timeLabelSingle");
856         if(NULL == ret->timeLabel){
857                 goto memCleanup;
858         }
859     ret->activeFlag = FALSE;
861         goto last;
863         gtk_widget_destroy(ret->window);
864 memCleanup:
865         g_free(ret);
866 last:
867         DualDecode_builderClose();
868         return ret;
871 static GtkWidget *createLogWindow()
873         /*TODO: create help window*/
874         return gtk_window_new(GTK_WINDOW_TOPLEVEL);
877 static GtkWidget *createHelpWindow()
879     GtkWidget * helpWindow;
880     gint width;
881     gint height;
883     helpWindow = gtk_window_new (GTK_WINDOW_TOPLEVEL);
884     gtk_window_set_title ( (GtkWindow *) helpWindow, "Help");
885     gtk_window_set_resizable ( (GtkWindow * )helpWindow, FALSE);
887     /*Set size same as display windows*/
888     gtk_widget_get_size_request (window[DECODER_INDEX_SINGLE]->window,
889                                  &width,
890                                  &height);  
891     gtk_widget_set_size_request (helpWindow, width, height);
892     /*Connect signal to close button handler*/
893     g_signal_connect(G_OBJECT (helpWindow), "delete-event", 
894       G_CALLBACK (cbHelpClosed), NULL);
895     g_print ("RETURNING FROM CREATE HELP\n");
896     return helpWindow;
900                                                          
901 /*static void logGUI(GtkWidget *logWindow, gchar *format, ...)
903         //TODO: dummy now
904 }*/
905 static void setWindowSizeLocation()
907         GdkScreen *screen               = NULL;
908         gint screenWidth                = -1;
909         gint screenHeight               = -1;
910         gint windowWidth                = -1;
911         gint windowHeight               = -1;
913         screen = gdk_screen_get_default();
914         screenWidth = gdk_screen_get_width(screen);
915         screenHeight = gdk_screen_get_height(screen);
916         windowWidth = screenWidth/SCREEN_WIDTH_FACTOR;
917         windowHeight = screenHeight/SCREEN_HEIGHT_FACTOR;
919         gtk_widget_set_size_request(window[DECODER_INDEX_SINGLE]->window,
920                         windowWidth,windowHeight);
921         gtk_widget_set_size_request(window[DECODER_INDEX_DOUBLE]->window,
922                         windowWidth,windowHeight);
923         gtk_window_move(GTK_WINDOW(window[DECODER_INDEX_SINGLE]->window),
924                         (screenWidth-2*windowWidth)/2,
925                         0);
926         gtk_window_move(GTK_WINDOW(window[DECODER_INDEX_DOUBLE]->window),
927                         (screenWidth-2*windowWidth)/2+windowWidth,
928                         0);
931 static GstElement *createImageSinkFromWindow (GtkWidget * window, gchar *name)
933     GstElement *sinkElement        = NULL;                                             
934     XID xid                 = 0;                                                
935     GdkDrawable *drawable   = NULL;                                             
936                                                                                 
937     /*make an xvimagesink element from factory*/                                
938                                      
939     sinkElement = gst_element_factory_make (sink,name);                        
940     if (NULL == sinkElement){
941         g_print ("%s sink cannot be created\n", sink);                                                           
942         goto return_pos;                                                        
943     }                                                                           
944                                                                                 
945     /*get the XID of the display window's drawable*/                            
946     drawable = gtk_widget_get_window (GTK_WIDGET (window));                     
947     if(FALSE == GDK_IS_DRAWABLE(drawable)){                                     
948         /*TODO: A BUG HERE?*/                                                   
949         g_object_unref(G_OBJECT(sinkElement));                                         
950         sinkElement=NULL;                                                              
951         goto return_pos;                                                        
952     }                                                                           
953     xid = gdk_x11_drawable_get_xid(drawable);                                   
954                                                                                 
955     /*link the gst sink element to the XID*/                                    
956     gst_x_overlay_set_xwindow_id (GST_X_OVERLAY (sinkElement),xid);                    
957                                                                                 
958 return_pos:                                                                     
959     return sinkElement;                                                                
960 }   
962 /******************************************************************************
963  *      Exported Function Definition
964  ******************************************************************************/
966 /******************************************************************************
967  *      See gui.h
968  ******************************************************************************/
969 void DualDecode_startApplication()
972         window[DECODER_INDEX_SINGLE] = createWindow();
973         g_assert(window[DECODER_INDEX_SINGLE] != NULL);
975     /*window[DECODER_INDEX_SINGLE]->sink = createImageSinkFromWindow (
976                                         window[DECODER_INDEX_SINGLE]->drawArea,
977                                         "sink0");
979     */
980         window[DECODER_INDEX_DOUBLE] = createWindow();
981         g_assert(window[DECODER_INDEX_DOUBLE] != NULL);
983  /*  window[DECODER_INDEX_DOUBLE]->sink = createImageSinkFromWindow (            
984                                         window[DECODER_INDEX_DOUBLE]->drawArea,          
985                                         "sink1"); 
986   */
987         setWindowSizeLocation();
989         helpWindow = createHelpWindow();
990         g_assert (helpWindow != NULL);
992         logWindow[DECODER_INDEX_SINGLE] = createLogWindow();
993         g_assert (logWindow[DECODER_INDEX_SINGLE] != NULL);
995         logWindow[DECODER_INDEX_DOUBLE] = createLogWindow();
996         g_assert (logWindow[DECODER_INDEX_DOUBLE] != NULL);
998         pipes[DECODER_INDEX_SINGLE] = DualDecode_createPipeline();
999 /*      DualDecode_setLogFunction(pipes[DECODER_INDEX_SINGLE],
1000                         logGUI,
1001                         logWindow[DECODER_INDEX_SINGLE]);
1002 */
1003         pipes[DECODER_INDEX_DOUBLE] = DualDecode_createPipeline();
1004 /*      DualDecode_setLogFunction(pipes[DECODER_INDEX_DOUBLE],
1005                         logGUI,
1006                         logWindow[DECODER_INDEX_DOUBLE]);
1007 */
1008         setup();
1010         gtk_main();
1011     
1014 /******************************************************************************
1015  *      See gui.h
1016  ******************************************************************************/
1017 void DualDecode_exitApplication()
1019         gtk_widget_destroy(window[DECODER_INDEX_SINGLE]->window);
1020         gtk_widget_destroy(window[DECODER_INDEX_DOUBLE]->window);
1021         g_free(window[DECODER_INDEX_SINGLE]);
1022         g_free(window[DECODER_INDEX_DOUBLE]);
1023         gtk_widget_destroy(logWindow[DECODER_INDEX_SINGLE]);
1024         gtk_widget_destroy(logWindow[DECODER_INDEX_DOUBLE]);
1025         gtk_widget_destroy (helpWindow);
1027         /*TODO: destroy pipes here*/
1029     if (gtk_main_level())
1030         gtk_main_quit();
1031     exit(0);
1034 /******************************************************************************
1035  *      See gui.h
1036  ******************************************************************************/
1037 gboolean DualDecode_initGUI(gint *argc, char **argv[])
1039         return gtk_init_check(argc,argv);