Removed typecast warnings.
[glsdk/dual-decode.git] / src / gst-controller.c
1 /*                                                                              
2  *  Copyright (c) 2010-2011, 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>
50 #include <gtk/gtk.h>
51 #include <gdk/gdkx.h>
52 #include <gst/interfaces/xoverlay.h>
54 #include "gst-controller.h"
56 static void getTime (gint64 arr[], gint64 time);
57 GstElement * createImageSinkFromWindow(GtkWidget *window,gchar *name)
58 {
59         GstElement *sink                = NULL;
60         XID xid                                 = 0;
61         GdkDrawable *drawable   = NULL;
63         /*make an xvimagesink element from factory*/
64         /*TODO : hard coded strings. will change*/
65         sink = gst_element_factory_make("xvimagesink",name);
66         if(NULL == sink){
67                 goto return_pos;
68         }
70         /*get the XID of the display window's drawable*/
71         drawable = gtk_widget_get_window (GTK_WIDGET (window));
72         if(FALSE == GDK_IS_DRAWABLE(drawable)){
73                 /*TODO: A BUG HERE?*/
74                 g_object_unref(G_OBJECT(sink));
75                 sink=NULL;
76                 goto return_pos;
77         }
78         xid = gdk_x11_drawable_get_xid(drawable);
79         
80         /*link the gst sink element to the XID*/
81         gst_x_overlay_set_xwindow_id (GST_X_OVERLAY (sink),xid);
83 return_pos:
84         return sink;
85 }
87 gboolean attachPipeElements (Pipeline *pipePtr, GtkWidget *drawArea1, 
88                              GtkWidget *drawArea2)
89 {
90     gboolean ret = TRUE;
91  
92     GstElement *bin = NULL;   
93     GstElement *tee = NULL;                                                     
94     GstElement *queue0 = NULL;                                                  
95     GstElement *queue1 = NULL;                                                  
96     GstElement *sink0 = NULL;                                                   
97     GstElement *sink1 = NULL;                                                   
98     GstPad *pad = NULL;   
99     
100     
101     if (NULL != drawArea2) { 
102         bin = gst_bin_new ("vsinkbin");
103         tee = gst_element_factory_make ("tee","splitter"); 
104         sink0 = createImageSinkFromWindow (drawArea1, "sink0");
105         queue0 = gst_element_factory_make ("queue","q0");                           
106         sink1 = createImageSinkFromWindow (drawArea2, "sink1"); 
107                 queue1 = gst_element_factory_make ("queue","q1");  
109         if ( !bin || !tee || !sink0 || !sink1 || !queue0 || !queue1) {
110             ret = FALSE;
111             goto exit;
112         }
113                    
114         gst_bin_add_many (GST_BIN (bin), tee, sink0, sink1, queue0, queue1,NULL); 
115     
116         /*Connecting the tee through queues is necessary to sync the two displays*/ 
117         gst_element_link(tee,queue0);                                               
118         gst_element_link(tee,queue1);                                               
119         gst_element_link(queue0,sink0);                                             
120         gst_element_link(queue1,sink1);                                             
121                                                                                 
122         pad = gst_element_get_static_pad (tee, "sink");                             
123         gst_element_add_pad (bin, gst_ghost_pad_new ("sink", pad));                 
124         gst_object_unref (GST_OBJECT (pad)); 
125         g_object_set (G_OBJECT (pipePtr->pipe), "video-sink", bin, NULL);              
126     }
127     else {
128     
129      sink0 = createImageSinkFromWindow (drawArea1, "sink0"); 
130      if (!sink0)
131     {
132          ret = FALSE;
133          goto exit;
134     }
135     g_object_set (G_OBJECT (pipePtr->pipe), "video-sink", sink0, NULL);
136     }
138 exit:    return ret;
140 gboolean busCallback(GstBus *bus, GstMessage *msg, gpointer data)
141 {    
142         gchar *name             = (gchar *)data;
143     gchar *debugMsg     = NULL;                                                 
144     GError *err         = NULL;                                                 
145     static int count = 0;
147     switch(GST_MESSAGE_TYPE(msg)){                                              
148                                                                                 
149         case GST_MESSAGE_EOS:                                                   
150             g_printerr("%s -> Message (EOS) : End of stream.\n",name);                          
151                         count++;
152             break;                                                              
153                                                                                
154          case GST_MESSAGE_ERROR: {                                             
155             gst_message_parse_error(msg,&err,&debugMsg);                      
156             g_printerr("%s -> Message (ERROR) : %s : debug ( %s )\n", name,err->message,debugMsg);                                                      
157             g_free(debugMsg);                                                   
158             g_error_free(err);                                                  
159                         count++;
160             break;                                                              
161         }                                                                       
162         case GST_MESSAGE_WARNING: {                                             
163             gst_message_parse_warning(msg,&err,&debugMsg);                      
164             g_printerr("%s -> Message (WARNING) : %s : debug ( %s )\n",
165                                            name,err->message,debugMsg);                                                      
166             g_free(debugMsg);                                                   
167             g_error_free(err);                                                  
168             break;                                                              
169         }                                                                       
170                                                                                 
171         default:                                                                
172             break;                                                              
173     }                                                                           
174                                                                                 
175     return TRUE;                                                                
176
177        
178 Pipeline * DualDecode_createPipeline()
180     Pipeline *pipelinePtr = (Pipeline *) malloc (sizeof(Pipeline));
181     pipelinePtr->pipe = NULL;
182                                                   
183     GstBus *bus = NULL;
184                                                                                 
185            
186     pipelinePtr->pipe = gst_element_factory_make("playbin2",NULL);                 
187     bus = gst_pipeline_get_bus (GST_PIPELINE(pipelinePtr->pipe));                    
188     pipelinePtr->busSignal = gst_bus_add_watch (bus,busCallback, NULL);                                   
189     gst_object_unref (bus);     
190     pipelinePtr->logFunc = NULL;
191                                                                           
192                                                                                 
193     return pipelinePtr;                
196 gboolean DualDecode_seekMedia(Pipeline *pipePtr, gint64 position)
198         if(position < 0){
199                 return FALSE;
200         }
201         return gst_element_seek_simple(pipePtr->pipe,
202                         GST_FORMAT_TIME,
203                         GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT,
204                         position);
207 gboolean DualDecode_playMedia (Pipeline *pipePtr, gchar *filename, gint64 position,  
208                                GtkWidget *drawArea1, GtkWidget *drawArea2)
210     gboolean ret = TRUE;
211     
212     g_object_set(G_OBJECT(pipePtr->pipe),"uri", filename,NULL);
213         if (!(attachPipeElements (pipePtr, drawArea1, drawArea2))) {
214         ret = FALSE;
215         goto exit;
216     }
217         gst_element_set_state (pipePtr->pipe, GST_STATE_NULL);                                 
218     gst_element_set_state (pipePtr->pipe, GST_STATE_PLAYING);                                 
220         DualDecode_getMediaState(pipePtr);
221         DualDecode_seekMedia(pipePtr, position);
222     
223      
224 exit:    return ret;
227 gboolean DualDecode_pauseMedia (Pipeline *pipePtr)
229     gboolean ret = TRUE;
230     if (!gst_element_set_state (pipePtr->pipe, GST_STATE_PAUSED))
231         ret = FALSE;  
232     
233     return ret;
236 gboolean DualDecode_resumeMedia (Pipeline *pipePtr)                              
237 {                                                                               
238     gboolean ret = TRUE;                                                        
239     if(!gst_element_set_state (pipePtr->pipe, GST_STATE_PLAYING))                
240         ret = FALSE;                                                            
241                                                                                 
242     return ret;                                                                 
243
245 gboolean DualDecode_stopMedia (Pipeline *pipePtr)                             
246 {                                                                               
247     gboolean ret = TRUE;                                                        
248     if(!gst_element_set_state (pipePtr->pipe, GST_STATE_NULL))               
249         ret = FALSE;                                                            
250                                                                                 
251     return ret;                                                                 
252 }  
254 gboolean DualDecode_setLogFunction (Pipeline *pipePtr, LogFunc func, gpointer data)
256     gboolean ret = TRUE;
257     
259     return ret;   
262 GstState DualDecode_getMediaState(Pipeline *pipePtr)
264         GstState state, pending;
265         if(GST_STATE_CHANGE_SUCCESS != gst_element_get_state(
266                                 pipePtr->pipe,
267                                 &state,
268                                 &pending,
269                                 GST_CLOCK_TIME_NONE)){
270                 /*TODO : a bug here*/
271                 g_printerr("No state in GstElement\n");
272         }
273         return state;
277 gboolean DualDecode_getMediaPosition (Pipeline *pipePtr, gdouble *seekScaleValue,
278                                       gchar **timeLabelText)
280         gboolean ret = TRUE;
281     gint64 position = 0, duration = 0;
282     gint64 pos[3], dur[3];
283     GstFormat format = GST_FORMAT_TIME; 
285     if (TRUE == gst_element_query_position (pipePtr->pipe, &format, &position) 
286     && (TRUE == gst_element_query_duration (pipePtr->pipe, &format, &duration))) {
287        
288         getTime (pos, position);
289         getTime (dur, duration); 
290         *timeLabelText = g_strdup_printf ("%ld:%ld:%ld/%ld:%ld:%ld", 
291         pos[HH], pos[MM], pos[SS], dur[HH], dur[MM], dur[SS]);
292         if (duration)
293             *seekScaleValue = (gdouble)position/ (gdouble)duration * 100;
294         
295     }    
296     else 
297         ret = FALSE;
298     
300     return ret;
303 static void getTime (gint64 arr[], gint64 time)
305     gint8 i = 0;
306     time = time / (gint64) NANOSEC;
308     for (i = 0; i < 3; i++){
309         arr[i] = time % 60;
310         time = time / 60;
311     } 
312