Modified in accordance to coding guidelines for header and C files.
[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  */                                                                             
43 /**
44  * @file                gui.c
45  *
46  * @brief               Defines the functions exported by the GUI.
47  *                              Also, defines the static functions and the callback funtions
48  */
49 #include <string.h>
50 #include <linux/limits.h>
51 #include <gtk/gtk.h>
52 #include <gdk/gdkx.h>                                                           
53 #include <gst/interfaces/xoverlay.h>  
55 #include <gui.h>
56 #include <common.h>
57 #include <gst-controller.h>
59 /******************************************************************************
60         
61                       Static variables declaration
62  
63 *****************************************************************************/
64 static GUIWindow *window[]              = {NULL, NULL};
65 static Pipeline *pipes[]                = {NULL, NULL};
66 static GtkWidget *logWindow[]   = {NULL, NULL};
67 static GtkWidget *helpWindow    = NULL;
70 /******************************************************************************
71  
72                            Static functions declaration
74  ******************************************************************************/
75 static gint setAbsolutePathname (gchar *file, gchar **uri)  ;
76 static void setControlMode (GUIWindow *thisWindow,gint modeFlag,gint activeFlag);
77 static void setControlActive (GUIWindow *window, gboolean activeFlag);
78 static void setup();
79 static void setDecodeSwitch (gint decodeSwitch);
80 static GtkWidget *createLogWindow ();
81 static GtkWidget *createHelpWindow ();
82 static GstElement *createImageSinkFromWindow (GtkWidget * window, gchar *name);
83 static void setWindowSizeLocation ();
84 static GUIWindow *createWindow ();
86 static gboolean cbOpenClicked (GtkWidget *widget, gpointer data);
87 static gboolean cbPlayClicked (GtkWidget *widget, gpointer data);
88 static gboolean cbPauseClicked (GtkWidget *widget, gpointer data);
89 static gboolean cbStopClicked (GtkWidget *widget, gpointer data);
90 static gboolean cbForwardClicked (GtkWidget *widget, gpointer data);
91 static gboolean cbRewindClicked (GtkWidget *widget, gpointer data);
92 static gboolean cbWindowClosed (GtkWidget *widget, gpointer data);
93 static gboolean cbHelpClicked (GtkWidget *widget, gpointer data);
94 static gboolean cbTimerInterval (gpointer data);
95 static gboolean cbSeekValueChanged (GtkWidget *widget, gpointer data);
96 static gboolean cbSwitchButtonClicked (GtkWidget *widget, gpointer data);
97 static gboolean cbHelpClosed (GtkWidget *widget, gpointer data);
99 static gint setAbsolutePathname (gchar *file, gchar **uri)                             
100 {                                                                               
101     gchar *realPath = NULL;                                                     
102     gint ret        = ERR_SUCCESS;                                              
103                                                                                 
104     if (NULL == uri){                                                            
105         return ERR_INVALIDPARAM;                                                
106     }                                                                           
107                                                                                 
108     if (NULL == file){                                                           
109         /*A BUG Here*/                                                          
110         g_printerr ("BUG: file: " __FILE__ " line: %d" "\n", __LINE__);          
111         return ERR_BUG;                                                         
112     }                                                                           
113                                                                                 
114     *uri = (gchar *) g_malloc (sizeof(gchar) * PATH_MAX_LEN);                   
115     realPath = realpath (file, realPath);                                       
116     if (NULL == realPath) {                                                     
117         /*TODO: a debug trace here*/                                            
118         g_printerr ("File %s not found\n", file);                               
119         ret = ERR_FILENOTFOUND;                                                 
120         goto destroy;                                                           
121     }                                                                           
122     g_snprintf (*uri,PATH_MAX_LEN,"file://%s",realPath);                         
123                                                                                 
124     goto last;                                                                  
125                                                                                 
126 destroy:                                                                        
127     g_free(*uri);                                                               
128     *uri=NULL;                                                                  
129 last:                                                                           
130     free (realPath);                                                            
131     return ret;                                                                 
132 }        
133 /******************************************************************************
134  
135                         Callback functions definition
137  ******************************************************************************/
139 /*Timer Interval Callback Function*/
140 static gboolean cbTimerInterval(gpointer data)
142         gdouble seekScaleValue = 0.0;
143         gchar *timeLabelText = TIME_LABEL_ORIGIN;
144         GUIWindow *thisWindow = (GUIWindow *)data;
145         gboolean ret = TRUE;
146     
147         if (DECODE_MODE_SINGLE == decodeMode) {
148                 ret = DualDecode_getMediaPosition(pipes[DECODER_INDEX_SINGLE],
149                                                           &seekScaleValue, &timeLabelText);
151                 g_signal_handler_block (window[DECODER_INDEX_SINGLE]->seekScale,
152                                 window[DECODER_INDEX_SINGLE]->seekSignal);
153         gtk_range_set_value (GTK_RANGE(window[DECODER_INDEX_SINGLE]->seekScale),
154                                 seekScaleValue);
155                 gtk_label_set_text (GTK_LABEL (window[DECODER_INDEX_SINGLE]->timeLabel),
156                                 timeLabelText);
157                 g_signal_handler_unblock (GTK_RANGE (window[DECODER_INDEX_SINGLE]->seekScale),
158                                                   window[DECODER_INDEX_SINGLE]->seekSignal);
160                 g_signal_handler_block (GTK_RANGE (window[DECODER_INDEX_DOUBLE]->seekScale),
161                                                  window[DECODER_INDEX_DOUBLE]->seekSignal);
162                 gtk_range_set_value (GTK_RANGE (window[DECODER_INDEX_DOUBLE]->seekScale),
163                                             seekScaleValue);
164                 gtk_label_set_text (GTK_LABEL (window[DECODER_INDEX_DOUBLE]->timeLabel),
165                                            timeLabelText);
166                 g_signal_handler_unblock (GTK_RANGE (window[DECODER_INDEX_DOUBLE]->seekScale),
167                                                   window[DECODER_INDEX_DOUBLE]->seekSignal);
168         }
169     else {
170                 if (window[DECODER_INDEX_SINGLE] == thisWindow){
171                         ret = DualDecode_getMediaPosition (pipes[DECODER_INDEX_SINGLE],
172                                                                    &seekScaleValue, &timeLabelText);
173                         
174             g_signal_handler_block (GTK_RANGE(window[DECODER_INDEX_SINGLE]->seekScale),
175                                                         window[DECODER_INDEX_SINGLE]->seekSignal);
176                         gtk_range_set_value (GTK_RANGE (window[DECODER_INDEX_SINGLE]->seekScale),
177                                                      seekScaleValue);
178                         gtk_label_set_text (GTK_LABEL (window[DECODER_INDEX_SINGLE]->timeLabel),
179                                                     timeLabelText);
180                         g_signal_handler_unblock (GTK_RANGE (window[DECODER_INDEX_SINGLE]->seekScale),
181                                                           window[DECODER_INDEX_SINGLE]->seekSignal);
182                 }
183         else {
184                         ret = DualDecode_getMediaPosition (pipes[DECODER_INDEX_DOUBLE],
185                                                                    &seekScaleValue, &timeLabelText);
187                         g_signal_handler_block (GTK_RANGE (window[DECODER_INDEX_DOUBLE]->seekScale),
188                                                         window[DECODER_INDEX_DOUBLE]->seekSignal);
189                         gtk_range_set_value (GTK_RANGE (window[DECODER_INDEX_DOUBLE]->seekScale),
190                                                      seekScaleValue);
191                         gtk_label_set_text (GTK_LABEL(window[DECODER_INDEX_DOUBLE]->timeLabel),
192                                                     timeLabelText);
193                         g_signal_handler_unblock (GTK_RANGE (window[DECODER_INDEX_DOUBLE]->seekScale),
194                                                           window[DECODER_INDEX_DOUBLE]->seekSignal);
195                 }
196         }
197         if (ret) {
198                 g_free (timeLabelText);
199         }
200     return ret;
203 /*Seek Scale Changed Value Callback Function*/
204 static gboolean cbSeekValueChanged (GtkWidget *widget, gpointer data)
206     gboolean ret = TRUE;
207     GstFormat format = GST_FORMAT_TIME; 
208     gint64 duration = 0;
209     gint seekPoint = 0;
210     gdouble percent = gtk_range_get_value ((GtkRange *)widget);
211     g_print ("PERCENT %f\n", percent);
212     GUIWindow *thisWindow = (GUIWindow *)data; 
214     g_print ("IN SEEK VALUE CHANGED\n");
215     if (DECODE_MODE_SINGLE == decodeMode) {
216                                                                                     
217         gst_element_query_duration (pipes[DECODER_INDEX_SINGLE]->pipe,
218                                     &format,&duration);
219         seekPoint = (gint64) (duration * percent/ (gdouble)100);
220         g_print ("SEEK POINT %d\n", seekPoint);
221         ret = DualDecode_seekMedia (pipes[DECODER_INDEX_SINGLE], seekPoint);
222     }
223     else {                                                                      
224         if (window[DECODER_INDEX_SINGLE] == thisWindow){    
225             gst_element_query_duration (pipes[DECODER_INDEX_SINGLE]->pipe,
226                                         &format,&duration);              
227             seekPoint = (gint64) (duration * percent/ (gdouble)100);
228             ret = DualDecode_seekMedia (pipes[DECODER_INDEX_SINGLE], seekPoint);
229     } 
230         else {
231             gst_element_query_duration (pipes[DECODER_INDEX_SINGLE]->pipe,
232                                         &format,&duration);              
233             seekPoint = (gint64) (duration * percent/ (gdouble)100);
234             ret = DualDecode_seekMedia (pipes[DECODER_INDEX_DOUBLE], seekPoint); 
235         }
236     }   
237     
238         return ret;
241 /*Open Button Clicked Callback Function*/
242 static gboolean cbOpenClicked (GtkWidget *widget, gpointer data)
244     gboolean ret = TRUE;
245     gchar *uri = NULL;
246     gchar *file = NULL;
247         GUIWindow *thisWindow = (GUIWindow *)data;
248         GtkWidget *fileChooser = gtk_file_chooser_dialog_new ("Open",
249                              GTK_WINDOW(thisWindow->window),
250                                          GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_OPEN,
251                                          GTK_RESPONSE_OK, GTK_STOCK_CANCEL, 
252                              GTK_RESPONSE_CANCEL, NULL);
253         gtk_window_set_modal (GTK_WINDOW (fileChooser),TRUE);
254         gtk_window_set_destroy_with_parent (GTK_WINDOW (fileChooser),TRUE);
255         gtk_widget_set_sensitive (thisWindow->window,FALSE);
256         
257         if (GTK_RESPONSE_OK == gtk_dialog_run (GTK_DIALOG (fileChooser))) {
258                 
259                 file = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER(fileChooser));
260         if (ERR_SUCCESS != setAbsolutePathname (file, &uri)) {
261             ret = FALSE;
262             goto last;
263         }
264                 if (DECODE_MODE_SINGLE == decodeMode) {
265             filename[DECODER_INDEX_SINGLE] = uri;
266                         setControlMode (window[DECODER_INDEX_SINGLE], CONTROL_MODE_PLAYING,
267                                                window[DECODER_INDEX_SINGLE]->activeFlag);
268                         setControlMode (window[DECODER_INDEX_DOUBLE], CONTROL_MODE_PLAYING,
269                                                window[DECODER_INDEX_DOUBLE]->activeFlag);
270                         DualDecode_playMedia (pipes[DECODER_INDEX_SINGLE], 
271                                   filename[DECODER_INDEX_SINGLE], SEEK_START);
272                 }
273         else {
274             filename[DECODER_INDEX_SINGLE] = uri;
275                         if (window[DECODER_INDEX_SINGLE] == thisWindow) {
276                                 setControlMode (window[DECODER_INDEX_SINGLE], 
277                                CONTROL_MODE_PLAYING,
278                                                        window[DECODER_INDEX_SINGLE]->activeFlag);
279                                 DualDecode_playMedia (pipes[DECODER_INDEX_SINGLE],
280                                                               filename[DECODER_INDEX_SINGLE], SEEK_START);
281                         }
282             else {
283                 filename[DECODER_INDEX_DOUBLE] = uri;   
284                                 setControlMode (window[DECODER_INDEX_DOUBLE], 
285                                 CONTROL_MODE_PLAYING,
286                                                         window[DECODER_INDEX_DOUBLE]->activeFlag);
287                                 DualDecode_playMedia (pipes[DECODER_INDEX_DOUBLE],
288                                                               filename[DECODER_INDEX_DOUBLE],
289                                                               SEEK_START);
290                         }
291                 }
292         }
293         if (GTK_IS_WIDGET (fileChooser))
294                 gtk_widget_destroy (fileChooser);
296         if (GTK_IS_WIDGET (thisWindow->window))
297                 gtk_widget_set_sensitive (thisWindow->window,TRUE);
299 last:    return ret;
302 /*Play Button Clicked Callback Function*/
303 static gboolean cbPlayClicked (GtkWidget *widget, gpointer data)
305         gboolean ret = TRUE;
306     GUIWindow *thisWindow = (GUIWindow *)data;
308         if (DECODE_MODE_SINGLE == decodeMode) {
309                 setControlMode (window[DECODER_INDEX_SINGLE], CONTROL_MODE_PLAYING,
310                                         window[DECODER_INDEX_SINGLE]->activeFlag);
311                 setControlMode (window[DECODER_INDEX_DOUBLE], CONTROL_MODE_PLAYING,
312                                         window[DECODER_INDEX_DOUBLE]->activeFlag);
313                 if (GST_STATE_PAUSED == 
314                                 DualDecode_getMediaState (pipes[DECODER_INDEX_SINGLE])) {
315                         DualDecode_resumeMedia (pipes[DECODER_INDEX_SINGLE]);
316                 }
317         else {
318                         DualDecode_playMedia (pipes[DECODER_INDEX_SINGLE],
319                                   filename[DECODER_INDEX_SINGLE], SEEK_START);
320         }
321         }
322     else {
323                 if (window[DECODER_INDEX_SINGLE] == thisWindow) {
324                         setControlMode (window[DECODER_INDEX_SINGLE], CONTROL_MODE_PLAYING,
325                                                 window[DECODER_INDEX_SINGLE]->activeFlag);
326                         if (GST_STATE_PAUSED == 
327                                         DualDecode_getMediaState (pipes[DECODER_INDEX_SINGLE])) {
328                                 DualDecode_resumeMedia (pipes[DECODER_INDEX_SINGLE]);
329                         }
330             else if (GST_STATE_READY == 
331                       DualDecode_getMediaState (pipes[DECODER_INDEX_SINGLE])) {
332                g_print ("\nPipeline state is READY\n");
333                DualDecode_setPipelineSink (pipes[DECODER_INDEX_SINGLE], 
334                                                  window[DECODER_INDEX_SINGLE]->sink, 
335                                                  NULL); 
336                DualDecode_playMedia (pipes[DECODER_INDEX_SINGLE], filename[0],0);
337             }
339             else {
340                                   DualDecode_playMedia (pipes[DECODER_INDEX_SINGLE], 
341                                         filename[DECODER_INDEX_SINGLE], 
342                                         SEEK_START);
343                         }
344                 }
345         else {
346                         setControlMode (window[DECODER_INDEX_DOUBLE], CONTROL_MODE_PLAYING,
347                                                 window[DECODER_INDEX_DOUBLE]->activeFlag);
348                         if (GST_STATE_PAUSED == 
349                                         DualDecode_getMediaState (pipes[DECODER_INDEX_DOUBLE])) {
350                                 DualDecode_resumeMedia (pipes[DECODER_INDEX_DOUBLE]);
351                         }
352             else if (GST_STATE_READY ==                                        
353                      DualDecode_getMediaState (pipes[DECODER_INDEX_DOUBLE])) {
354                DualDecode_resumeMedia (pipes[DECODER_INDEX_DOUBLE]);            
355             }   
357             else {
358                                 DualDecode_playMedia (pipes[DECODER_INDEX_DOUBLE],
359                                                               filename[DECODER_INDEX_DOUBLE],
360                                       SEEK_START);
361                         }
362                 }
363         }
364     return ret;
367 /*Pause Button Clicked Callback Function*/
368 static gboolean cbPauseClicked (GtkWidget *widget, gpointer data)
370         gboolean ret = TRUE;
371     GUIWindow *thisWindow = (GUIWindow *)data;
373         if (DECODE_MODE_SINGLE == decodeMode) {
374                 setControlMode (window[DECODER_INDEX_SINGLE], CONTROL_MODE_PAUSED,
375                                         window[DECODER_INDEX_SINGLE]->activeFlag);
376                 setControlMode (window[DECODER_INDEX_DOUBLE], CONTROL_MODE_PAUSED,
377                                         window[DECODER_INDEX_DOUBLE]->activeFlag);
378                 DualDecode_pauseMedia (pipes[DECODER_INDEX_SINGLE]);
379         }
380     else {
381                 if (window[DECODER_INDEX_SINGLE] == thisWindow) {
382                         setControlMode (window[DECODER_INDEX_SINGLE], CONTROL_MODE_PAUSED,
383                                                 window[DECODER_INDEX_SINGLE]->activeFlag);
384                         DualDecode_pauseMedia (pipes[DECODER_INDEX_SINGLE]);
385                 }
386         else {
387                         setControlMode (window[DECODER_INDEX_DOUBLE], CONTROL_MODE_PAUSED,
388                                                 window[DECODER_INDEX_DOUBLE]->activeFlag);
389                         DualDecode_pauseMedia (pipes[DECODER_INDEX_DOUBLE]);
390                 }
391         } 
392     return ret;
395 /*Stop Button Clicked Callback Function*/
396 static gboolean cbStopClicked (GtkWidget *widget, gpointer data)
398         gboolean ret = TRUE;
399     GUIWindow *thisWindow = (GUIWindow *)data;
400    
402         if (DECODE_MODE_SINGLE == decodeMode) {
403                 setControlMode (window[DECODER_INDEX_SINGLE], CONTROL_MODE_STOPPED,
404                                         window[DECODER_INDEX_SINGLE]->activeFlag);
405                 setControlMode (window[DECODER_INDEX_DOUBLE], CONTROL_MODE_STOPPED,
406                                         window[DECODER_INDEX_DOUBLE]->activeFlag);
407                 DualDecode_stopMedia (pipes[DECODER_INDEX_SINGLE]);
408         }
409     else {
410                 if (window[DECODER_INDEX_SINGLE] == thisWindow) {
411                         setControlMode (window[DECODER_INDEX_SINGLE], CONTROL_MODE_STOPPED,
412                                                 window[DECODER_INDEX_SINGLE]->activeFlag);
413                         DualDecode_stopMedia (pipes[DECODER_INDEX_SINGLE]);
414                 }
415         else {
416                         setControlMode (window[DECODER_INDEX_DOUBLE], CONTROL_MODE_STOPPED,
417                                                 window[DECODER_INDEX_DOUBLE]->activeFlag);
418                         DualDecode_stopMedia (pipes[DECODER_INDEX_DOUBLE]);
419                 }
420         }
421     return ret;
423 static gboolean cbForwardClicked (GtkWidget *widget, gpointer data)                 
424 {                                                                               
425     gboolean ret = TRUE;                                                        
426     GstFormat format = GST_FORMAT_TIME;                                         
427     gint64 duration = 0;                                                        
428     gint64 seekPoint = 0;                                                         
429     GUIWindow *thisWindow = (GUIWindow *)data;               
430     gdouble percent = gtk_range_get_value ((GtkRange *) (thisWindow->seekScale));                   
431                                                                                 
432     g_print ("IN FORWARD CLICKED\n");                                        
433     if (DECODE_MODE_SINGLE == decodeMode) {                                      
434                                                                                 
435         gst_element_query_duration (pipes[DECODER_INDEX_SINGLE]->pipe,          
436                                     &format,&duration);                         
437         seekPoint =  (duration * percent/ (gdouble)100)+ FORWARD;                
438         g_print ("SEEK POINT %ld\n", seekPoint);                                 
439         ret = DualDecode_seekMedia (pipes[DECODER_INDEX_SINGLE], seekPoint);     
440     }                                                                           
441     else {                                                                       
442         if (window[DECODER_INDEX_SINGLE] == thisWindow) {                         
443             gst_element_query_duration (pipes[DECODER_INDEX_SINGLE]->pipe,      
444                                         &format, &duration);                     
445             seekPoint =  (duration * percent/ (gdouble)100) + FORWARD;
446             g_print ("SEEK POINT %ld\n", seekPoint);            
447             ret = DualDecode_seekMedia (pipes[DECODER_INDEX_SINGLE], seekPoint); 
448         }                                                                       
449         else {                                                                  
450             gst_element_query_duration (pipes[DECODER_INDEX_SINGLE]->pipe,       
451                                        &format,&duration);                      
452             seekPoint = (duration * percent/ (gdouble)100)+ FORWARD;            
453             ret = DualDecode_seekMedia (pipes[DECODER_INDEX_DOUBLE], seekPoint); 
454         }                                                                       
455     }                                                                           
456                                                                                 
457         return ret; 
458 }                                                                                
459 static gboolean cbRewindClicked (GtkWidget *widget, gpointer data)                 
461     gboolean ret = TRUE;                                                        
462     GstFormat format = GST_FORMAT_TIME;                                         
463     gint64 duration = 0;                                                        
464     gint64 seekPoint = 0;                                                       
465     GUIWindow *thisWindow = (GUIWindow *)data;                                  
466     gdouble percent = gtk_range_get_value ((GtkRange *) (thisWindow->seekScale));
467                                                                                 
468     g_print ("IN FORWARD CLICKED\n");                                           
469     if (DECODE_MODE_SINGLE == decodeMode) {                                      
470                                                                                 
471         gst_element_query_duration (pipes[DECODER_INDEX_SINGLE]->pipe,          
472                                     &format,&duration);                         
473         seekPoint =  (duration * percent/ (gdouble)100) - REWIND;               
474         g_print ("SEEK POINT %ld\n", seekPoint);
475         seekPoint = (seekPoint < 0) ? 0 : seekPoint;                                 
476         ret = DualDecode_seekMedia (pipes[DECODER_INDEX_SINGLE], seekPoint);     
477     }                                                                           
478     else {                                                                       
479         if (window[DECODER_INDEX_SINGLE] == thisWindow) {                         
480             gst_element_query_duration (pipes[DECODER_INDEX_SINGLE]->pipe,      
481                                         &format, &duration);                    
482             seekPoint =  (duration * percent/ (gdouble)100) - REWIND;          
483             g_print ("SEEK POINT %ld\n", seekPoint);
484             seekPoint = (seekPoint < 0) ? 0 : seekPoint;                             
485             ret = DualDecode_seekMedia (pipes[DECODER_INDEX_SINGLE], seekPoint); 
486         }                                                                       
487         else {                                                                  
488             gst_element_query_duration (pipes[DECODER_INDEX_SINGLE]->pipe,       
489                                        &format,&duration);                      
490             seekPoint = (duration * percent/ (gdouble)100) - REWIND;    
491             seekPoint = (seekPoint < 0) ? 0 : seekPoint;        
492             ret = DualDecode_seekMedia (pipes[DECODER_INDEX_DOUBLE], seekPoint); 
493         }                                                                       
494     }                                                                           
495                                                                                 
496         return ret;                                                                                  
497 }    
498 static gboolean cbSwitchButtonClicked (GtkWidget *widget, gpointer data)
500     gboolean ret = TRUE;
501     gboolean noFile = FALSE;
502     GUIWindow *thisWindow = (GUIWindow *) data;
503     gint otherWindowIndex = 0;
504     gint thisWindowIndex = 0;
506     /*No file is given yet to play. Application may be just started. */
507     if (NULL == filename[DECODER_INDEX_SINGLE])
508         noFile = TRUE;
510     if (thisWindow == window[DECODER_INDEX_SINGLE]) {
511         thisWindowIndex = DECODER_INDEX_SINGLE;
512         otherWindowIndex = DECODER_INDEX_DOUBLE;
513     }
514     else 
515     {
516         otherWindowIndex = DECODER_INDEX_SINGLE;
517         thisWindowIndex = DECODER_INDEX_DOUBLE;
518     }
520     switch (decodeMode) {
521     case DECODE_MODE_SINGLE :  
522         setControlMode (window[otherWindowIndex], 
523                         window[otherWindowIndex]->modeFlag, CONTROL_MODE_ACTIVE);
524         setControlMode (thisWindow, thisWindow->modeFlag, CONTROL_MODE_ACTIVE);
526         if (FALSE == noFile) {
527           ret = DualDecode_singleToDual (pipes,
528                                          window[otherWindowIndex]->sink,
529                                          thisWindowIndex, otherWindowIndex, 
530                                          filename[DECODER_INDEX_SINGLE]);
531         }
532         decodeMode = DECODE_MODE_DUAL;
533         setDecodeSwitch(DECODE_MODE_SINGLE);
534         break;
536     case DECODE_MODE_DUAL :      
537         setControlMode (window[otherWindowIndex], thisWindow->modeFlag, 
538                           CONTROL_MODE_INACTIVE);  
540         if (FALSE == noFile) {
541         ret = DualDecode_dualToSingle (pipes,
542                                        window[otherWindowIndex]->sink,        
543                                          thisWindowIndex, otherWindowIndex);
544          }
545          decodeMode = DECODE_MODE_SINGLE; 
546          setDecodeSwitch (DECODE_MODE_DUAL);     
547          break;
548     } 
551     return ret;
553 /*Window Close Callback Function*/
554 static gboolean cbWindowClosed (GtkWidget *widget, gpointer data){
555         DualDecode_exitApplication();
556     return TRUE;
559 static gboolean cbHelpClicked (GtkWidget *widget, gpointer data){
560     g_print ("HELP BUTTON CLICKED\n");
561     gtk_widget_show (helpWindow);
562     return TRUE;
565 static gboolean cbHelpClosed (GtkWidget *widget, gpointer data){
566     g_print ("IN HELP CLOSED\n");
567     gtk_widget_hide (helpWindow);
568     return TRUE;
570 /******************************************************************************
571  
572                         Static utility functions definition
574  ******************************************************************************/
575 static void setControlActive (GUIWindow *window, gboolean activeFlag)
577         gtk_widget_set_sensitive (window->playButton,activeFlag);
578         gtk_widget_set_sensitive (window->pauseButton,activeFlag);
579         gtk_widget_set_sensitive (window->stopButton,activeFlag);
580         gtk_widget_set_sensitive (window->rewindButton,activeFlag);
581         gtk_widget_set_sensitive (window->forwardButton,activeFlag);
582         gtk_widget_set_sensitive (window->openButton,activeFlag);
583         gtk_widget_set_sensitive (window->seekScale,activeFlag);
584     gtk_widget_set_sensitive (window->switchButton, activeFlag);
585     
588 static void setControlMode (GUIWindow *thisWindow, gint modeFlag, 
589                             gint activeFlag)
591         setControlActive (thisWindow, activeFlag);
592         if (activeFlag) {
593                 switch (modeFlag) {
594             case CONTROL_MODE_NO_FILE:
595                     gtk_widget_set_sensitive (thisWindow->playButton,FALSE);
596                         gtk_widget_set_sensitive (thisWindow->pauseButton,FALSE);
597                         gtk_widget_set_sensitive (thisWindow->stopButton,FALSE);
598                         gtk_widget_set_sensitive (thisWindow->rewindButton,FALSE);
599                         gtk_widget_set_sensitive (thisWindow->forwardButton,FALSE);
600                         gtk_widget_set_sensitive (thisWindow->seekScale,FALSE);
601                         break;
602                 case CONTROL_MODE_PLAYING:
603                         gtk_widget_set_sensitive (thisWindow->playButton,TRUE);
604                         gtk_widget_set_sensitive (thisWindow->pauseButton,TRUE);
605                         gtk_widget_set_sensitive (thisWindow->stopButton,TRUE);
606                         gtk_widget_set_sensitive (thisWindow->rewindButton,TRUE);
607                         gtk_widget_set_sensitive (thisWindow->forwardButton,TRUE);
608                         gtk_widget_set_sensitive (thisWindow->seekScale,TRUE);
609                 break; 
610                 case CONTROL_MODE_STOPPED:
611                     gtk_widget_set_sensitive (thisWindow->playButton,TRUE);
612                         gtk_widget_set_sensitive (thisWindow->pauseButton,TRUE);
613                         gtk_widget_set_sensitive (thisWindow->stopButton,TRUE);
614                         gtk_widget_set_sensitive (thisWindow->rewindButton,TRUE);
615                         gtk_widget_set_sensitive (thisWindow->forwardButton,TRUE);
616                         gtk_widget_set_sensitive (thisWindow->seekScale,FALSE);
617                         break;
618                 case CONTROL_MODE_PAUSED:
619                         gtk_widget_set_sensitive (thisWindow->playButton,TRUE);
620                         gtk_widget_set_sensitive (thisWindow->pauseButton,TRUE);
621                 gtk_widget_set_sensitive (thisWindow->stopButton,TRUE);
622                         gtk_widget_set_sensitive (thisWindow->rewindButton,TRUE);
623                         gtk_widget_set_sensitive (thisWindow->forwardButton,TRUE);
624                         gtk_widget_set_sensitive (thisWindow->seekScale,TRUE);
625                 break;
626                 }
627         }
628         switch (modeFlag) {
629         case CONTROL_MODE_NO_FILE:
630                 gtk_widget_show (thisWindow->playButton);
631                 gtk_widget_hide (thisWindow->pauseButton);
633                 gtk_label_set_text (GTK_LABEL(thisWindow->statusLabel),
634                                         LABEL_TEXT_NO_FILE);
635                 gtk_label_set_text (GTK_LABEL(thisWindow->timeLabel),
636                                         TIME_LABEL_ORIGIN);
637                 if (thisWindow->timerSignal != TIMER_SIGNAL_NONE) {
638                     g_source_remove (thisWindow->timerSignal);
639                         thisWindow->timerSignal = TIMER_SIGNAL_NONE;
640                 }
641                 break;
642         case CONTROL_MODE_PLAYING:
643                 gtk_widget_show (thisWindow->pauseButton);
644                 gtk_widget_hide (thisWindow->playButton);
646                 gtk_label_set_text (GTK_LABEL(thisWindow->statusLabel),
647                                         LABEL_TEXT_PLAYING);
648                 gtk_label_set_text (GTK_LABEL(thisWindow->timeLabel),
649                                         TIME_LABEL_ORIGIN);
651                 if (thisWindow->timerSignal != TIMER_SIGNAL_NONE) {
652                                 g_source_remove (thisWindow->timerSignal);
653         }
654                 thisWindow->timerSignal = g_timeout_add (TIMER_INTERVAL, cbTimerInterval,
655                                                                         thisWindow); 
656                         
657                 break;
658         case CONTROL_MODE_STOPPED:
659                 gtk_widget_show (thisWindow->playButton);
660                 gtk_widget_hide (thisWindow->pauseButton);
662                 gtk_label_set_text (GTK_LABEL(thisWindow->statusLabel), 
663                             LABEL_TEXT_STOPPED);
664                 gtk_label_set_text (GTK_LABEL(thisWindow->timeLabel), TIME_LABEL_ORIGIN);
666                 if (thisWindow->timerSignal != TIMER_SIGNAL_NONE) {
667                         g_source_remove(thisWindow->timerSignal);
668                         thisWindow->timerSignal = TIMER_SIGNAL_NONE;
669                 }
670                 break;
671         case CONTROL_MODE_PAUSED:
672                 gtk_widget_show(thisWindow->playButton);
673                 gtk_widget_hide(thisWindow->pauseButton);
675                 gtk_label_set_text (GTK_LABEL (thisWindow->statusLabel), 
676                             LABEL_TEXT_PAUSED);
677             break;
679         }
680         thisWindow->modeFlag = modeFlag;
681         thisWindow->activeFlag = activeFlag;
684 static void setDecodeSwitch (gint decodeSwitch)
686         switch (decodeSwitch) {
687         case DECODE_MODE_SINGLE:
688                 gtk_button_set_label (
689                                         GTK_BUTTON (window[DECODER_INDEX_SINGLE]->switchButton),
690                                         SWITCH_TEXT_SINGLE);
691                 gtk_button_set_label (
692                                         GTK_BUTTON (window[DECODER_INDEX_DOUBLE]->switchButton),
693                                         SWITCH_TEXT_SINGLE);
694                 break;
695         case DECODE_MODE_DUAL:
696                 gtk_button_set_label (
697                                         GTK_BUTTON(window[DECODER_INDEX_SINGLE]->switchButton),
698                                         SWITCH_TEXT_DUAL);
699                 gtk_button_set_label (
700                                         GTK_BUTTON(window[DECODER_INDEX_DOUBLE]->switchButton),
701                                         SWITCH_TEXT_DUAL);
702         }
705 static void setup()
708     g_print ("SINK TO BE USED %s\n", sink);
709         gtk_widget_show_all (window[DECODER_INDEX_SINGLE]->window);
710         gtk_widget_show_all (window[DECODER_INDEX_DOUBLE]->window);
712     window[DECODER_INDEX_SINGLE]->sink = createImageSinkFromWindow (            
713                                         window[DECODER_INDEX_SINGLE]->drawArea, 
714                                         "windowsink0"); 
716     window[DECODER_INDEX_DOUBLE]->sink = createImageSinkFromWindow (           
717                                         window[DECODER_INDEX_DOUBLE]->drawArea, 
718                                         "windowsink1"); 
720     /*If any of the sinks is NULL the application exits*/
722     if (NULL == window[DECODER_INDEX_SINGLE]->sink || 
723         NULL == window[DECODER_INDEX_DOUBLE]->sink) {
724             DualDecode_exitApplication();
725     
726     }
727         switch (decodeMode) {
728         case DECODE_MODE_NONE:
729                 setControlMode (window[DECODER_INDEX_SINGLE], CONTROL_MODE_NO_FILE,
730                                         CONTROL_MODE_ACTIVE);
731                 setControlMode (window[DECODER_INDEX_DOUBLE], CONTROL_MODE_NO_FILE,
732                                         CONTROL_MODE_ACTIVE);
733         DualDecode_setPipelineSink (pipes[DECODER_INDEX_SINGLE], 
734                                     window[DECODER_INDEX_SINGLE]->sink, NULL);                            
735         DualDecode_setPipelineSink (pipes[DECODER_INDEX_DOUBLE], 
736                                     window[DECODER_INDEX_DOUBLE]->sink, NULL);
737             decodeMode = DECODE_MODE_DUAL;
738             setDecodeSwitch (DECODE_MODE_SINGLE);
739                 break;
740         case DECODE_MODE_SINGLE:
741                 setControlMode (window[DECODER_INDEX_SINGLE],
742                                     CONTROL_MODE_PLAYING, CONTROL_MODE_ACTIVE);
743                 setControlMode (window[DECODER_INDEX_DOUBLE],CONTROL_MODE_PLAYING,
744                                             CONTROL_MODE_INACTIVE);
745         DualDecode_setPipelineSink (pipes[DECODER_INDEX_SINGLE], 
746                                     window[DECODER_INDEX_SINGLE]->sink,
747                                     window[DECODER_INDEX_DOUBLE]->sink);
748         DualDecode_setPipelineSink (pipes[DECODER_INDEX_DOUBLE], NULL, NULL);
749             DualDecode_playMedia (pipes[DECODER_INDEX_SINGLE], 
750                               filename[DECODER_INDEX_SINGLE], SEEK_START);
751                 setDecodeSwitch (DECODE_MODE_DUAL);
752                 break;
753         case DECODE_MODE_DUAL:
754                 setControlMode (window[DECODER_INDEX_SINGLE], CONTROL_MODE_PLAYING,
755                                            CONTROL_MODE_ACTIVE);
756         DualDecode_setPipelineSink (pipes[DECODER_INDEX_SINGLE], 
757                                     window[DECODER_INDEX_SINGLE]->sink, NULL);
758         DualDecode_setPipelineSink (pipes[DECODER_INDEX_DOUBLE], 
759                                     window[DECODER_INDEX_DOUBLE]->sink, NULL);
761                 DualDecode_playMedia (pipes[DECODER_INDEX_SINGLE],
762                               filename[DECODER_INDEX_SINGLE], SEEK_START);
763                 setControlMode (window[DECODER_INDEX_DOUBLE], CONTROL_MODE_PLAYING,
764                                             CONTROL_MODE_ACTIVE);
765                 DualDecode_playMedia (pipes[DECODER_INDEX_DOUBLE], 
766                               filename[DECODER_INDEX_DOUBLE], SEEK_START);
767                 setDecodeSwitch (DECODE_MODE_SINGLE);
768                 break;
769         }
772 static GUIWindow *createWindow()
774         GUIWindow *ret  = NULL;
775         ret = g_malloc0 (sizeof(GUIWindow));
776         if(NULL == ret){
777                 return ret;
778         }
779         DualDecode_builderCreate ();
781         ret->window = DualDecode_getWidget ("decodeWindowSingle");
782         if (NULL == ret->window) {
783                 goto memCleanup;
784         }
785         ret->windowCloseSignal = g_signal_connect(G_OBJECT(ret->window),
786                         "delete-event",
787                         G_CALLBACK(cbWindowClosed),
788                         NULL);
790         GtkWidget *toolbar = DualDecode_getWidget ("toolbarSingle");
791         if (NULL == toolbar) {
792                 goto memCleanup;
793         }
794         ret->drawArea = DualDecode_getWidget ("videoViewerSingle");
795         if (NULL == ret->drawArea) {
796                 goto memCleanup;
797         }
799         ret->openButton = GTK_WIDGET (
800                       gtk_tool_button_new_from_stock(GTK_STOCK_OPEN));
801         if (NULL == ret->openButton) {
802                 goto memCleanup;
803         }
804         ret->rewindButton = GTK_WIDGET (
805                                     gtk_tool_button_new_from_stock(GTK_STOCK_MEDIA_REWIND));
806         if (NULL == ret->rewindButton) {
807                 goto memCleanup;
808         }
809         ret->playButton = GTK_WIDGET (
810                                   gtk_tool_button_new_from_stock(GTK_STOCK_MEDIA_PLAY));
811         if (NULL == ret->playButton) {
812                 goto memCleanup;
813         }
814         ret->pauseButton = GTK_WIDGET (
815                                    gtk_tool_button_new_from_stock(GTK_STOCK_MEDIA_PAUSE));
816         if (NULL == ret->pauseButton) {
817                 goto memCleanup;
818         }
819         ret->stopButton = GTK_WIDGET (
820                                   gtk_tool_button_new_from_stock(GTK_STOCK_MEDIA_STOP));
821         if (NULL == ret->stopButton) {
822                 goto memCleanup;
823         }
824         ret->forwardButton = GTK_WIDGET (
825                                      gtk_tool_button_new_from_stock(GTK_STOCK_MEDIA_FORWARD));
826         if (NULL == ret->forwardButton) {
827                 goto memCleanup;
828         }
829         ret->helpButton = GTK_WIDGET (
830                                   gtk_tool_button_new_from_stock(GTK_STOCK_HELP));
831         if (NULL == ret->helpButton) {
832                 goto memCleanup;
833         }
835         gtk_toolbar_insert (GTK_TOOLBAR (toolbar), GTK_TOOL_ITEM (ret->openButton),
836                                    -1);
837         gtk_toolbar_insert (GTK_TOOLBAR (toolbar), gtk_separator_tool_item_new(),
838                                     -1);
839         gtk_toolbar_insert (GTK_TOOLBAR (toolbar), GTK_TOOL_ITEM(ret->rewindButton),
840                                     -1);
841         gtk_toolbar_insert (GTK_TOOLBAR (toolbar), GTK_TOOL_ITEM(ret->playButton),
842                                     -1);
843         gtk_toolbar_insert (GTK_TOOLBAR (toolbar), GTK_TOOL_ITEM(ret->pauseButton),
844                                     -1);
845         gtk_toolbar_insert (GTK_TOOLBAR(toolbar), GTK_TOOL_ITEM(ret->stopButton),
846                                     -1);
847         gtk_toolbar_insert (GTK_TOOLBAR(toolbar), GTK_TOOL_ITEM(ret->forwardButton),
848                                     -1);
849         gtk_toolbar_insert (GTK_TOOLBAR(toolbar), gtk_separator_tool_item_new(),
850                                     -1);
851         gtk_toolbar_insert (GTK_TOOLBAR(toolbar), GTK_TOOL_ITEM(ret->helpButton),
852                                     -1);
854         ret->openSignal = g_signal_connect (G_OBJECT (ret->openButton), "clicked",
855                                                     G_CALLBACK (cbOpenClicked), ret);
856         ret->stopSignal = g_signal_connect (G_OBJECT (ret->stopButton), "clicked",
857                                                     G_CALLBACK (cbStopClicked), ret);
858         ret->pauseSignal = g_signal_connect (G_OBJECT (ret->pauseButton), "clicked",
859                                                      G_CALLBACK (cbPauseClicked), ret);
860         ret->playSignal = g_signal_connect (G_OBJECT (ret->playButton), "clicked",
861                                                     G_CALLBACK (cbPlayClicked),
862                         ret);
863     ret->forwardSignal = g_signal_connect (G_OBJECT (ret->forwardButton),"clicked",                                                          
864                                            G_CALLBACK (cbForwardClicked), ret);
865     ret->rewindSignal = g_signal_connect (G_OBJECT (ret->rewindButton),"clicked",                                                          
866                                           G_CALLBACK (cbRewindClicked), ret);
868     ret->helpSignal = g_signal_connect (G_OBJECT (ret->helpButton), "clicked",                                                          
869                                         G_CALLBACK(cbHelpClicked), ret);   
872         ret->switchButton = DualDecode_getWidget ("switchButtonSingle");
873         if (NULL == ret->switchButton) {
874                 goto memCleanup;
875         }
877         ret->switchSignal = g_signal_connect (G_OBJECT (ret->switchButton), "clicked",
878                                           G_CALLBACK (cbSwitchButtonClicked),
879                                           ret);
881         ret->seekScale = DualDecode_getWidget ("seekScaleSingle");
882         if (NULL == ret->seekScale) {
883                 goto memCleanup;
884         }
886     ret->seekSignal = g_signal_connect (G_OBJECT (ret->seekScale), 
887                                         "value_changed",
888                                         G_CALLBACK (cbSeekValueChanged), ret);
889         
891         ret->statusLabel = DualDecode_getWidget ("statusLabelSingle");
892         if (NULL == ret->statusLabel) {
893                 goto memCleanup;
894         }
896         ret->timeLabel = DualDecode_getWidget ("timeLabelSingle");
897         if (NULL == ret->timeLabel) {
898                 goto memCleanup;
899         }
900     ret->activeFlag = FALSE;
902         goto last;
904         gtk_widget_destroy (ret->window);
905 memCleanup:
906         g_free (ret);
907 last:
908         DualDecode_builderClose ();
909         return ret;
912 static GtkWidget *createLogWindow ()
914         return gtk_window_new (GTK_WINDOW_TOPLEVEL);
917 static GtkWidget *createHelpWindow ()
919     GtkWidget * helpWindow;
920     gint width;
921     gint height;
923     helpWindow = gtk_window_new (GTK_WINDOW_TOPLEVEL);
924     gtk_window_set_title ( (GtkWindow *) helpWindow, "Help");
925     gtk_window_set_resizable ( (GtkWindow * )helpWindow, FALSE);
927     /*Set size same as display windows*/
928     gtk_widget_get_size_request (window[DECODER_INDEX_SINGLE]->window,
929                                  &width,
930                                  &height);  
931     gtk_widget_set_size_request (helpWindow, width, height);
932     /*Connect signal to close button handler*/
933     g_signal_connect(G_OBJECT (helpWindow), "delete-event", 
934       G_CALLBACK (cbHelpClosed), NULL);
935     g_print ("RETURNING FROM CREATE HELP\n");
936     return helpWindow;
940                                                          
941 static void setWindowSizeLocation ()
943         GdkScreen *screen               = NULL;
944         gint screenWidth                = -1;
945         gint screenHeight               = -1;
946         gint windowWidth                = -1;
947         gint windowHeight               = -1;
949         screen = gdk_screen_get_default ();
950         screenWidth = gdk_screen_get_width (screen);
951         screenHeight = gdk_screen_get_height (screen);
952         windowWidth = screenWidth/SCREEN_WIDTH_FACTOR;
953         windowHeight = screenHeight/SCREEN_HEIGHT_FACTOR;
955         gtk_widget_set_size_request (window[DECODER_INDEX_SINGLE]->window,
956                                              windowWidth,windowHeight);
957         gtk_widget_set_size_request (window[DECODER_INDEX_DOUBLE]->window,
958                                              windowWidth,windowHeight);
959         gtk_window_move (GTK_WINDOW (window[DECODER_INDEX_SINGLE]->window),
960                                             (screenWidth - 2 * windowWidth) / 2, 0);
961         gtk_window_move (GTK_WINDOW (window[DECODER_INDEX_DOUBLE]->window),
962                                  (screenWidth - 2 * windowWidth) / 2 + windowWidth,
963                         0);
966 static GstElement *createImageSinkFromWindow (GtkWidget * window, gchar *name)
968     GstElement *sinkElement = NULL;                                             
969     XID xid                 = 0;                                                
970     GdkDrawable *drawable   = NULL;                                             
971                                                                                 
972     /*make an xvimagesink element from factory*/                                
973                                      
974     sinkElement = gst_element_factory_make (sink,name);                        
975     if (NULL == sinkElement) {
976         g_print ("%s sink cannot be created\n", sink);                                                           
977         goto return_pos;                                                        
978     }                                                                           
979                                                                                 
980     /*get the XID of the display window's drawable*/                            
981     drawable = gtk_widget_get_window (GTK_WIDGET (window));                     
982     if (FALSE == GDK_IS_DRAWABLE (drawable)) {                                     
983         /*TODO: A BUG HERE?*/                                                   
984         g_object_unref (G_OBJECT (sinkElement));                                         
985         sinkElement=NULL;                                                              
986         goto return_pos;                                                        
987     }                                                                           
988     xid = gdk_x11_drawable_get_xid (drawable);                                   
989                                                                                 
990     /*link the gst sink element to the XID*/                                    
991     gst_x_overlay_set_xwindow_id (GST_X_OVERLAY (sinkElement),xid);                    
992                                                                                 
993 return_pos:                                                                     
994     return sinkElement;                                                                
995 }   
997 /******************************************************************************
998  
999                                Public Functions
1001  ******************************************************************************/
1003 /******************************************************************************
1004                                 See gui.h
1005  ******************************************************************************/
1006 void DualDecode_startApplication ()
1009         window[DECODER_INDEX_SINGLE] = createWindow();
1010         g_assert (window[DECODER_INDEX_SINGLE] != NULL);
1012         window[DECODER_INDEX_DOUBLE] = createWindow();
1013         g_assert (window[DECODER_INDEX_DOUBLE] != NULL);
1015         setWindowSizeLocation();
1017         helpWindow = createHelpWindow();
1018         g_assert (helpWindow != NULL);
1020         logWindow[DECODER_INDEX_SINGLE] = createLogWindow ();
1021         g_assert (logWindow[DECODER_INDEX_SINGLE] != NULL);
1023         logWindow[DECODER_INDEX_DOUBLE] = createLogWindow ();
1024         g_assert (logWindow[DECODER_INDEX_DOUBLE] != NULL);
1026         pipes[DECODER_INDEX_SINGLE] = DualDecode_createPipeline ();
1027         pipes[DECODER_INDEX_DOUBLE] = DualDecode_createPipeline ();
1028         setup ();
1030         gtk_main ();
1031     
1034 void DualDecode_exitApplication()
1036         gtk_widget_destroy (window[DECODER_INDEX_SINGLE]->window);
1037         gtk_widget_destroy (window[DECODER_INDEX_DOUBLE]->window);
1038         g_free (window[DECODER_INDEX_SINGLE]);
1039         g_free (window[DECODER_INDEX_DOUBLE]);
1040         gtk_widget_destroy (logWindow[DECODER_INDEX_SINGLE]);
1041         gtk_widget_destroy (logWindow[DECODER_INDEX_DOUBLE]);
1042         gtk_widget_destroy (helpWindow);
1044         /*TODO: destroy pipes here*/
1046     if (gtk_main_level())
1047         gtk_main_quit ();
1048     exit (0);
1051 gboolean DualDecode_initGUI(gint *argc, char **argv[])
1053         return gtk_init_check (argc,argv);