Switch Button Handling.
[glsdk/dual-decode.git] / src / gst-controller.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  */                                                                             
41                                                                                 
42 /**                                                                             
43  * @file  gst-controller.c                                                                 
44  *                                                                              
45  * @brief                                                                       
46  */ 
47 #include <stdint.h>
48 #include <string.h>
49 #include <gst/gst.h>
51 #include "gst-controller.h"
53 gchar * fsinkArr [] = {"fsink0", "fsink1"};
54 static gint fsinkCounter = 0;
55 static void getTime (gint64 arr[], gint64 time);
57 gboolean attachPipeElements (Pipeline *pipePtr, GstElement *sink0, 
58                              GstElement *sink1)
59 {
60     gboolean ret = TRUE;
61     GstElement *fsink0 = NULL; 
62     GstElement *fsink1 = NULL;
63     GstElement *bin = NULL;   
64     GstElement *tee = NULL;                                                     
65     GstElement *queue0 = NULL;                                                  
66     GstElement *queue1 = NULL;                                                  
67     GstPad *pad = NULL;   
68     
69     
70     
71         bin = gst_bin_new ("vsinkbin");
72         tee = gst_element_factory_make ("tee","splitter"); 
73         //sink0 = createImageSinkFromWindow (drawArea1, "sink0");
74         queue0 = gst_element_factory_make ("queue","q0");  
75         queue1 = gst_element_factory_make ("queue","q1");
77         if (NULL == sink0)
78            fsink0 = gst_element_factory_make ("fakesink", fsinkArr[fsinkCounter++]);
79         if (NULL == sink1)                         
80             fsink1 = gst_element_factory_make ("fakesink", fsinkArr[fsinkCounter++]); 
81                 
83         if ( !bin || !tee || !queue0 || !queue1) {
84             ret = FALSE;
85             goto exit;
86         }
87         if (NULL == sink0 && NULL == sink1) {           
88             gst_bin_add_many (GST_BIN (bin), tee, 
89                               fsink0, fsink1, queue0, queue1,NULL); 
90             gst_element_link (queue0, fsink0);
91             gst_element_link(queue1,fsink1);
92        }
94         else if (NULL != sink0 && NULL == sink1){
95             gst_bin_add_many (GST_BIN (bin), tee,                               
96                               sink0, fsink1, queue0, queue1,NULL);
97             gst_element_link (queue0, sink0);
98             gst_element_link(queue1,fsink1);
99         }
100         else if (NULL!= sink0 && NULL!=sink1) {
101              gst_bin_add_many (GST_BIN (bin), tee,                               
102                               sink0, sink1, queue0, queue1,NULL);              
103             gst_element_link (queue0, sink0);                                    
104             gst_element_link(queue1,sink1);                                    
105         }      
106     
107         else {
108             ret = FALSE;
109             goto exit;
110         }
111         /*Connecting the tee through queues is necessary to sync the two displays*/ 
112         gst_element_link(tee,queue0);                                               
113         gst_element_link(tee,queue1);                                               
114         //gst_element_link(queue0,sink0);                                             
115         //gst_element_link(queue1,sink1);                                             
116                                                                                 
117         pad = gst_element_get_static_pad (tee, "sink");                             
118         gst_element_add_pad (bin, gst_ghost_pad_new ("sink", pad));                 
119         gst_object_unref (GST_OBJECT (pad)); 
120         g_object_set (G_OBJECT (pipePtr->pipe), "video-sink", bin, NULL);     
121  
122                 
123     
124 exit:    return ret;
126 gboolean setSink (Pipeline *pipePtr, GstElement *sink)
128     gboolean ret = TRUE;
129     GstElement *bin = NULL;
130     GstElement *queue1 = NULL;
131    
133     return ret;
134 }  
135 gboolean busCallback(GstBus *bus, GstMessage *msg, gpointer data)
136 {    
137         gchar *name             = (gchar *)data;
138     gchar *debugMsg     = NULL;                                                 
139     GError *err         = NULL;                                                 
140     static int count = 0;
142     switch(GST_MESSAGE_TYPE(msg)){                                              
143                                                                                 
144         case GST_MESSAGE_EOS:                                                   
145             g_printerr("%s -> Message (EOS) : End of stream.\n",name);                          
146                         count++;
147             break;                                                              
148                                                                                
149          case GST_MESSAGE_ERROR: {                                             
150             gst_message_parse_error(msg,&err,&debugMsg);                      
151             g_printerr("%s -> Message (ERROR) : %s : debug ( %s )\n", name,err->message,debugMsg);                                                      
152             g_free(debugMsg);                                                   
153             g_error_free(err);                                                  
154                         count++;
155             break;                                                              
156         }                                                                       
157         case GST_MESSAGE_WARNING: {                                             
158             gst_message_parse_warning(msg,&err,&debugMsg);                      
159             g_printerr("%s -> Message (WARNING) : %s : debug ( %s )\n",
160                                            name,err->message,debugMsg);                                                      
161             g_free(debugMsg);                                                   
162             g_error_free(err);                                                  
163             break;                                                              
164         }                                                                       
165                                                                                 
166         default:                                                                
167             break;                                                              
168     }                                                                           
169                                                                                 
170     return TRUE;                                                                
171
172        
173 Pipeline * DualDecode_createPipeline()
175     Pipeline *pipelinePtr = (Pipeline *) malloc (sizeof(Pipeline));
176     pipelinePtr->pipe = NULL;
177                                                   
178     GstBus *bus = NULL;
179                                                                                 
180            
181     pipelinePtr->pipe = gst_element_factory_make("playbin2",NULL);                 
182     bus = gst_pipeline_get_bus (GST_PIPELINE(pipelinePtr->pipe));                    
183     pipelinePtr->busSignal = gst_bus_add_watch (bus,busCallback, NULL);                                   
184     gst_object_unref (bus);     
185     pipelinePtr->logFunc = NULL;
186                                                                           
187                                                                                 
188     return pipelinePtr;                
191 gboolean DualDecode_setSinksForPipes (Pipeline **pipes,GstElement *sink0, GstElement *sink1)
193     gboolean ret = TRUE;
194     attachPipeElements (pipes[0], sink0, NULL);
195     attachPipeElements (pipes[1], sink1, NULL);
196        
198     return ret;
200 gboolean DualDecode_seekMedia(Pipeline *pipePtr, gint64 position)
202         if(position < 0){
203                 return FALSE;
204         }
205         return gst_element_seek_simple(pipePtr->pipe,
206                         GST_FORMAT_TIME,
207                         GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT,
208                         position);
211 gboolean DualDecode_playMedia (Pipeline *pipePtr, gchar *filename, gint64 position,  
212                                GstElement *sink0, GstElement *sink1)
214     gboolean ret = TRUE;
215     
216     g_object_set(G_OBJECT(pipePtr->pipe),"uri", filename,NULL);
217 /*      if (!(attachPipeElements (pipePtr, sink0, sink1))) {
218         ret = FALSE;
219         goto exit;
220     }*/
221         gst_element_set_state (pipePtr->pipe, GST_STATE_NULL);                                 
222     gst_element_set_state (pipePtr->pipe, GST_STATE_PLAYING);                                 
224         DualDecode_getMediaState(pipePtr);
225         DualDecode_seekMedia(pipePtr, position);
226     
227      
228 exit:    return ret;
231 gboolean DualDecode_pauseMedia (Pipeline *pipePtr)
233     gboolean ret = TRUE;
234     if (GST_STATE_CHANGE_ASYNC == gst_element_set_state (pipePtr->pipe, GST_STATE_PAUSED)){
235         g_print ("SET CHANGE RETURNED ASYNC \n");
236         gst_element_get_state (pipePtr->pipe,
237                                 NULL,
238                                 NULL,
239                                 GST_CLOCK_TIME_NONE);
240     }
242     
243     
244     
245     return ret;
248 gboolean DualDecode_resumeMedia (Pipeline *pipePtr)                              
249 {                                                                               
250     gboolean ret = TRUE;                                                        
251     if(!gst_element_set_state (pipePtr->pipe, GST_STATE_PLAYING))                
252         ret = FALSE;                                                            
253     g_print ("IN RESUME MEDIA\n");                                                                            
254     return ret;                                                                 
255
257 gboolean DualDecode_stopMedia (Pipeline *pipePtr)                             
258 {                                                                               
259     gboolean ret = TRUE;                                                        
260     if(!gst_element_set_state (pipePtr->pipe, GST_STATE_NULL))               
261         ret = FALSE;                                                            
262                                                                                 
263     return ret;                                                                 
264 }  
267 gboolean DualDecode_setLogFunction (Pipeline *pipePtr, LogFunc func, gpointer data)
269     gboolean ret = TRUE;
270     
272     return ret;   
275 GstState DualDecode_getMediaState(Pipeline *pipePtr)
277         GstState state, pending;
278     g_print ("IN GET MEDIA STATE ENTRY\n");
279         if(GST_STATE_CHANGE_SUCCESS != gst_element_get_state(
280                                 pipePtr->pipe,
281                                 &state,
282                                 &pending,
283                                 GST_CLOCK_TIME_NONE)){
284                 /*TODO : a bug here*/
285                 g_printerr("No state in GstElement\n");
286         }
287     g_print("EXITING FROM GET MEDIA STATE\n");
288         return state;
292 gboolean DualDecode_getMediaPosition (Pipeline *pipePtr, gdouble *seekScaleValue,
293                                       gchar **timeLabelText)
295         gboolean ret = TRUE;
296     gint64 position = 0, duration = 0;
297     gint64 pos[3], dur[3];
298     GstFormat format = GST_FORMAT_TIME; 
300     if (TRUE == gst_element_query_position (pipePtr->pipe, &format, &position) 
301     && (TRUE == gst_element_query_duration (pipePtr->pipe, &format, &duration))) {
302        
303         getTime (pos, position);
304         getTime (dur, duration); 
305         *timeLabelText = g_strdup_printf ("%ld:%ld:%ld/%ld:%ld:%ld", 
306         pos[HH], pos[MM], pos[SS], dur[HH], dur[MM], dur[SS]);
307         if (duration)
308             *seekScaleValue = (gdouble)position/ (gdouble)duration * 100;
309         
310     }    
311     else 
312         ret = FALSE;
313     
315     return ret;
318 static void getTime (gint64 arr[], gint64 time)
320     gint8 i = 0;
321     time = time / (gint64) NANOSEC;
323     for (i = 0; i < 3; i++){
324         arr[i] = time % 60;
325         time = time / 60;
326     } 
327     
330 void DualDecode_setPipelineSink (Pipeline *pipePtr, GstElement *sink0, GstElement *sink1)
332     g_print ("IN SET PIPE IN SINGLE MODE");
333     attachPipeElements (pipePtr, sink0, sink1);
334     //gst_element_set_state (pipePtr->pipe, GST_STATE_READY);
337 gboolean DualDecode_playMedia2 (Pipeline *pipePtr, gchar *filename, gint64 position)            
338 {                                                                               
339     gboolean ret = TRUE;                                                        
341     g_print ("IN PLAYMEDIA2");                                                                                
342     g_object_set(G_OBJECT(pipePtr->pipe),"uri", filename,NULL);                 
343 /*  if (!(attachPipeElements (pipePtr, sink0, sink1))) {                        
344         ret = FALSE;                                                            
345         goto exit;                                                              
346     }*/                                                                         
347     gst_element_set_state (pipePtr->pipe, GST_STATE_NULL);                      
348     gst_element_set_state (pipePtr->pipe, GST_STATE_PLAYING);                   
349                                                                                 
350     DualDecode_getMediaState(pipePtr);                                          
351     DualDecode_seekMedia(pipePtr, position);                                    
352                                                                                 
353                                                                                 
354 exit:    return ret;                                                            
357 gboolean DualDecode_singleToDual (Pipeline **pipes,GstElement * otherWindowSink,
358                                   gint thisWindow, gint otherWindow,
359                                   gchar **filename)
361     gboolean ret = TRUE;
363     GstElement *thisbin = NULL;
364     GstElement *otherbin = NULL;
365     GstElement *fsink = NULL;
366     GstElement *queue0 = NULL;                                                  
367     GstElement *queue1 = NULL;                                                  
368     GstState state0 ; 
369    
370     //gst_element_set_state (pipes[thisWindow]->pipe, GST_STATE_PAUSED);
371     gst_element_get_state(                                              
372                 pipes[thisWindow]->pipe,                                                  
373                 &state0,                                                         
374                 NULL,                                                        
375                 GST_CLOCK_TIME_NONE);  
377     g_object_get (G_OBJECT (pipes[thisWindow]->pipe),"video-sink", &thisbin,NULL);
378     queue1 = gst_bin_get_by_name (GST_BIN (thisbin), "q1");                   
379     gst_element_unlink (queue1, otherWindowSink);          
380     gst_object_ref (otherWindowSink);                      
381     gst_bin_remove (GST_BIN (thisbin), otherWindowSink);       
382                                                                                 
383     g_object_get (G_OBJECT (pipes[otherWindow]->pipe), "video-sink", &otherbin, NULL);
384     queue0 = gst_bin_get_by_name (GST_BIN (otherbin), "q0");                  
385     fsink = gst_bin_get_by_name (GST_BIN (otherbin), "fsink0");               
386     gst_element_unlink (queue0, fsink);                                   
387     gst_object_ref (fsink);                                               
388     gst_bin_remove (GST_BIN (otherbin), fsink);                               
389                                                                                 
390     gst_bin_add (GST_BIN (thisbin), fsink);                                  
391     gst_element_sync_state_with_parent (fsink);                          
392     gst_element_link (queue1, fsink);                                    
393                                                                                 
394     gst_element_set_state (otherWindowSink, GST_STATE_READY);
395     gst_bin_add (GST_BIN (otherbin), otherWindowSink);        
396     //gst_element_sync_state_with_parent (window[otherWindow]->sink);                          
397     gst_element_link (queue0, otherWindowSink);           
398                                                                                 
399     DualDecode_playMedia2 (pipes[otherWindow], filename, 0);
400     //DualDecode_playMedia2 (pipes[thiswindow], filename[DECODER_INDEX_SINGLE], SEEK_START);
401     gst_element_set_state (pipes[thisWindow]->pipe, state0); 
403     return ret;
405  
406 gboolean DualDecode_dualToSingle (Pipeline **pipes,GstElement * otherWindowSink,
407                                   gint thisWindow, gint otherWindow)  
409     gboolean ret = TRUE;
411     GstElement *bin = NULL;
412     GstElement *bin2 = NULL;
413     GstElement *fsink = NULL;
414     GstElement *fsink0 = NULL;
415     GstElement *queue0 = NULL;
416     GstElement *queue1 = NULL; 
417     gchar *name = NULL;
418     gst_element_set_state (pipes[otherWindow]->pipe, GST_STATE_PAUSED);
419                                                                                 
420     g_object_get (G_OBJECT (pipes[otherWindow]->pipe), "video-sink", &bin2, NULL);
421     queue0 = gst_bin_get_by_name (GST_BIN (bin2), "q0");                  
422     gst_element_unlink (queue0, otherWindowSink);          
423     gst_object_ref (otherWindowSink);                      
424     gst_bin_remove (GST_BIN (bin2), otherWindowSink);       
425                                                                                 
426     g_object_get (G_OBJECT (pipes[thisWindow]->pipe), "video-sink", &bin, NULL);
427     queue1 = gst_bin_get_by_name (GST_BIN (bin), "q1");                   
428     fsink = gst_bin_get_by_name (GST_BIN (bin), "fsink0");                
429     if (NULL == fsink)                                                    
430         fsink = gst_bin_get_by_name (GST_BIN (bin), "fsink1");            
431     name = gst_element_get_name(fsink);                                   
432                                                                                 
433     gst_element_unlink (queue1, fsink);                                   
434     gst_object_ref (fsink);                                               
435     gst_bin_remove (GST_BIN (bin),fsink);                                 
436                                                                                 
437     gst_element_set_state (otherWindowSink, GST_STATE_READY);
438                                                                                 
439     gst_bin_add (GST_BIN (bin2), fsink);                                  
440     gst_element_sync_state_with_parent (fsink);                           
441                                                                                 
442     if (!g_strcmp0 (name, "fsink0")){                                   
443                                                                                 
444         g_print ("NAME IS fsink0\n");                                   
445         gst_element_link (queue0, fsink);                               
446     }                                                                     
447     else if (!g_strcmp0 (name, "fsink1")){                                
448         g_print ("NAME IS fsink1\n");                                     
449         fsink0 = gst_bin_get_by_name (GST_BIN (bin2), "fsink0");          
450         queue1 = gst_bin_get_by_name (GST_BIN (bin2), "q1");              
451         gst_element_unlink (queue1, fsink0);                              
452         gst_element_link (queue1, fsink);                                 
453         gst_element_link (queue0, fsink0);                                
454     }                                                                     
455     g_free (name);                                                       
456     gst_bin_add (GST_BIN (bin), otherWindowSink);         
457     gst_element_sync_state_with_parent (otherWindowSink); 
458     gst_element_link (queue1, otherWindowSink); 
461     return ret;