Turn out remaining gst-1.0 code
[platform/core/multimedia/libmm-player.git] / src / mm_player_pd.c
1 /*
2  * libmm-player
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: JongHyuk Choi <jhchoi.choi@samsung.com>, naveen cherukuri <naveen.ch@samsung.com>,
7  * YeJin Cho <cho.yejin@samsung.com>, YoungHwan An <younghwan_.an@samsung.com>
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  * http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  */
22 #include <mm_debug.h>
23 #include <mm_error.h>
24 #include "mm_player_pd.h"
25 #include "mm_player_utils.h"
26 #include "mm_player_priv.h"
27
28 /*---------------------------------------------------------------------------------------
29 |    LOCAL FUNCTION PROTOTYPES:                                                                                                                 |
30 ---------------------------------------------------------------------------------------*/
31
32 /* It's callback to process whenever there is some changes in PD downloader. */
33 static gboolean __pd_downloader_callback(GstBus *bus, GstMessage *msg, gpointer data);
34
35 /* This function posts messages to application. */
36 /* Currently, MM_MESSAGE_PD_DOWNLOADER_START and MM_MESSAGE_PD_DOWNLOADER_END are used. */
37 static gboolean __pd_downloader_post_message(mm_player_t * player, enum MMMessageType msgtype, MMMessageParamType* param);
38
39 /*=======================================================================================
40 |  FUNCTION DEFINITIONS                                                                                                                                                       |
41 =======================================================================================*/
42 static gboolean
43 __pd_downloader_callback(GstBus *bus, GstMessage *msg, gpointer data)
44 {
45         mm_player_t * player = NULL;
46         mm_player_pd_t *pd = NULL;
47         gboolean bret = TRUE;
48         
49         debug_fenter();
50
51         /* chech player handle */
52         return_val_if_fail ( data, MM_ERROR_INVALID_ARGUMENT );
53
54         player = MM_PLAYER_CAST((MMHandleType)data);
55
56         /* get PD downloader handle */
57         pd = MM_PLAYER_GET_PD((MMHandleType)data);
58
59         return_val_if_fail ( pd, MM_ERROR_INVALID_ARGUMENT );
60
61 //      g_print("%s\n", GST_MESSAGE_TYPE_NAME(msg));
62
63         switch ( GST_MESSAGE_TYPE( msg ) )
64         {
65                 case GST_MESSAGE_EOS:
66                         {
67                                 debug_log("PD Downloader EOS received....\n");
68
69                                 g_object_set (G_OBJECT (pd->playback_pipeline_src), "eos", TRUE, NULL);
70
71                                 /* notify application that download is completed */
72                                 __pd_downloader_post_message(player, MM_MESSAGE_PD_DOWNLOADER_END, NULL);
73
74                                 #ifdef PD_SELF_DOWNLOAD
75                                 _mmplayer_unrealize_pd_downloader ((MMHandleType)data);
76                                 #endif
77                         }
78                         break;
79
80                 case GST_MESSAGE_ERROR:
81                         {
82                                 gboolean ret = FALSE;
83                                 GError *error = NULL;
84                                 gchar* debug = NULL;
85                                 GstMessage *new_msg = NULL;
86                                 
87                                 /* get error code */
88                                 gst_message_parse_error( msg, &error, &debug );
89                                 debug_error ("GST_MESSAGE_ERROR = %s\n", debug);
90                                 
91                                 new_msg = gst_message_new_error (GST_OBJECT_CAST (pd->playback_pipeline_src), error, debug);
92
93                                 /* notify application that pd has any error */
94                                 ret = gst_element_post_message (pd->playback_pipeline_src, new_msg);
95
96                                 _mmplayer_unrealize_pd_downloader ((MMHandleType)data);
97                         }
98                         break;
99
100                 case GST_MESSAGE_WARNING:
101                         {
102                                 char* debug = NULL;
103                                 GError* error = NULL;
104
105                                 gst_message_parse_warning(msg, &error, &debug);
106                                 debug_warning("warning : %s\n", error->message);
107                                 debug_warning("debug : %s\n", debug);
108
109                                 MMPLAYER_FREEIF(debug);
110                                 g_error_free( error);
111                         }
112                         break;
113
114                 case GST_MESSAGE_STATE_CHANGED:
115                 {
116                         GstState old_state, new_state;
117                         gchar *src_name;
118
119                         /* get old and new state */
120                         gst_message_parse_state_changed (msg, &old_state, &new_state, NULL);
121
122                         if (old_state == new_state)
123                                 break;
124
125                         /* we only care about pipeline state changes */
126                         if (GST_MESSAGE_SRC (msg) != GST_OBJECT (pd->downloader_pipeline))
127                                 break;
128
129                         src_name = gst_object_get_name (msg->src);
130                         debug_log ("%s changed state from %s to %s", src_name,
131                                 gst_element_state_get_name (old_state),
132                                 gst_element_state_get_name (new_state));
133                         g_free (src_name);
134
135                         switch(new_state)
136                         {
137                                 case GST_STATE_VOID_PENDING:
138                                 case GST_STATE_NULL:
139                                 case GST_STATE_READY:
140                                 case GST_STATE_PAUSED:
141                                         break;
142
143                                 case GST_STATE_PLAYING:
144                                         /* notify application that download is stated */
145                                         __pd_downloader_post_message(player, MM_MESSAGE_PD_DOWNLOADER_START, NULL);
146                                         break;
147
148                                 default:
149                                         break;
150                         }
151                 }
152                 break;
153
154                 case GST_MESSAGE_DURATION:
155                 {
156 #ifndef GST_API_VERSION_1
157                         GstFormat fmt= GST_FORMAT_BYTES;
158 #endif
159
160                         gint64 size = 0LL;
161
162                         /* get total size  of download file, (bytes) */
163 #ifdef GST_API_VERSION_1
164                         if ( ! gst_element_query_duration( pd->downloader_pipeline, GST_FORMAT_BYTES, &size ) )
165                         {
166                                 GError *err = NULL;
167                                 GstMessage *new_msg = NULL;
168
169                                 err = g_error_new (GST_STREAM_ERROR, GST_STREAM_ERROR_FAILED, "can't get total size");
170                                 new_msg = gst_message_new_error (GST_OBJECT_CAST (pd->playback_pipeline_src), err, NULL);
171                                 gst_element_post_message (pd->playback_pipeline_src, new_msg);
172
173                                 g_error_free (err);
174
175                                 // TODO: check if playback pipeline is closed well or not
176                                 g_object_set (G_OBJECT (pd->playback_pipeline_src), "eos", TRUE, NULL);
177
178                                 _mmplayer_unrealize_pd_downloader ((MMHandleType)data);
179
180                                 debug_error("failed to query total size for download\n");
181                                 break;
182                         }
183 #else
184                         if ( ! gst_element_query_duration( pd->downloader_pipeline, &fmt, &size ) )
185                         {
186                                 GError *err = NULL;
187                                 GstMessage *new_msg = NULL;
188
189                                 err = g_error_new (GST_STREAM_ERROR, GST_STREAM_ERROR_FAILED, "can't get total size");
190                                 new_msg = gst_message_new_error (GST_OBJECT_CAST (pd->playback_pipeline_src), err, NULL);
191                                 gst_element_post_message (pd->playback_pipeline_src, new_msg);
192
193                                 g_error_free (err);
194
195                                 // TODO: check if playback pipeline is closed well or not
196                                 g_object_set (G_OBJECT (pd->playback_pipeline_src), "eos", TRUE, NULL);
197
198                                 _mmplayer_unrealize_pd_downloader ((MMHandleType)data);
199
200                                 debug_error("failed to query total size for download\n");
201                                 break;
202                         }
203 #endif
204
205                         pd->total_size = size;
206
207                         debug_log("PD total size : %lld bytes\n", size);
208                 }
209                 break;
210
211                 default:
212                         debug_warning("unhandled message\n");
213                         break;
214         }
215
216         debug_fleave();
217
218         return bret;
219 }
220
221
222 gboolean __pd_downloader_post_message(mm_player_t * player, enum MMMessageType msgtype, MMMessageParamType* param)
223 {
224         debug_fenter();
225
226         return_val_if_fail( player, FALSE );
227
228         if ( !player->pd_msg_cb )
229         {
230                 debug_warning("no msg callback. can't post\n");
231                 return FALSE;
232         }
233
234         player->pd_msg_cb(msgtype, param, player->pd_msg_cb_param);
235
236         debug_fleave();
237
238         return TRUE;
239 }
240
241
242 gboolean _mmplayer_get_pd_downloader_status(MMHandleType handle, guint64 *current_pos, guint64 *total_size)
243 {
244         debug_fenter();
245
246         mm_player_pd_t * pd = NULL;
247         guint64 bytes = 0;
248
249         return_val_if_fail(handle, MM_ERROR_INVALID_ARGUMENT);
250
251         pd = MM_PLAYER_GET_PD(handle);
252
253         return_val_if_fail(pd, MM_ERROR_INVALID_ARGUMENT);
254         return_val_if_fail(pd->downloader_pipeline, MM_ERROR_INVALID_ARGUMENT);
255
256         if ( !pd->total_size )
257         {
258                 debug_warning("not ready to get total size\n");
259                 return FALSE;
260         }
261
262         g_object_get(pd->downloader_sink, "current-bytes", &bytes, NULL);
263
264         debug_log("PD status : %lld / %lld\n", bytes, pd->total_size);
265
266         *current_pos = bytes;
267         *total_size = pd->total_size;
268
269         debug_fleave();
270
271         return TRUE;
272 }
273
274
275 mm_player_pd_t * _mmplayer_create_pd_downloader()
276 {
277         debug_fenter();
278
279         mm_player_pd_t * pd = NULL;
280
281         /* create PD handle */
282         pd = (mm_player_pd_t *) malloc (sizeof (mm_player_pd_t));
283         if ( !pd )
284         {
285                 debug_error ("Failed to create pd downloader handle...\n");
286                 return FALSE;
287         }
288
289         debug_fleave();
290
291         return pd;
292 }
293
294
295 gboolean _mmplayer_destroy_pd_downloader (MMHandleType handle)
296 {
297         debug_fenter();
298
299         mm_player_pd_t * pd = NULL;
300
301         return_val_if_fail ( handle, MM_ERROR_INVALID_ARGUMENT );
302
303         pd = MM_PLAYER_GET_PD(handle);
304
305         if (pd && pd->downloader_pipeline)
306                 _mmplayer_unrealize_pd_downloader (handle);
307
308         /* release PD handle */
309         MMPLAYER_FREEIF(pd);
310
311         debug_fleave();
312
313         return TRUE;
314 }
315
316
317 gboolean _mmplayer_realize_pd_downloader (MMHandleType handle, gchar *src_uri, gchar *dst_uri, GstElement *pushsrc)
318 {
319         debug_fenter();
320
321         mm_player_pd_t * pd = NULL;
322
323         return_val_if_fail ( handle, MM_ERROR_INVALID_ARGUMENT );
324         return_val_if_fail ( src_uri, MM_ERROR_INVALID_ARGUMENT );
325         return_val_if_fail ( dst_uri, MM_ERROR_INVALID_ARGUMENT );
326         return_val_if_fail ( pushsrc, MM_ERROR_INVALID_ARGUMENT );
327
328         pd = MM_PLAYER_GET_PD(handle);
329
330         /* initialize */
331         pd->path_read_from = g_strdup (src_uri);
332         pd->location_to_save = g_strdup (dst_uri);
333         pd->playback_pipeline_src = pushsrc;
334         pd->total_size = 0LL;
335
336         debug_fleave();
337         
338         return TRUE;
339 }
340
341
342 gboolean _mmplayer_start_pd_downloader (MMHandleType handle)
343 {
344         GstBus* bus = NULL;
345         gboolean bret = FALSE;
346         GstStateChangeReturn sret = GST_STATE_CHANGE_SUCCESS;
347         GstState cur_state;
348         GstState pending_state;
349
350         debug_fenter();
351
352         mm_player_pd_t * pd = NULL;
353
354         return_val_if_fail ( handle, MM_ERROR_INVALID_ARGUMENT );
355
356         pd = MM_PLAYER_GET_PD(handle);
357
358         /* pipeline */
359         pd->downloader_pipeline = gst_pipeline_new ("PD Downloader");
360         if (NULL == pd->downloader_pipeline)
361         {
362                 debug_error ("Can't create PD download pipeline...");
363                 return FALSE;
364         }
365
366         /* source */
367         pd->downloader_src = gst_element_factory_make ("souphttpsrc", "PD HTTP download source");
368         if (NULL == pd->downloader_src)
369         {
370                 debug_error ("Can't create PD download src...");
371                 return FALSE;
372         }
373
374         /* queue */
375         pd->downloader_queue = gst_element_factory_make ("queue", "PD download queue");
376         if (NULL == pd->downloader_queue)
377         {
378                 debug_error ("Can't create PD download queue...");
379                 return FALSE;
380         }
381
382         /* filesink */
383         pd->downloader_sink = gst_element_factory_make ("filesink", "PD download sink");
384         if (NULL == pd->downloader_sink)
385         {
386                 debug_error ("Can't create PD download sink...");
387                 return FALSE;
388         }
389
390         g_object_set(pd->downloader_sink, "sync", FALSE, NULL);
391         
392         /* Add to bin and link */
393         gst_bin_add_many (GST_BIN (pd->downloader_pipeline),
394                                         pd->downloader_src, pd->downloader_queue, pd->downloader_sink,
395                                         NULL);
396         
397         bret = gst_element_link_many (pd->downloader_src, pd->downloader_queue, pd->downloader_sink, NULL);
398         if (FALSE == bret)
399         {
400                 debug_error ("Can't link elements src and sink...");
401                 return FALSE;
402         }
403         
404         /* Get Bus and set callback to watch */
405         bus = gst_pipeline_get_bus (GST_PIPELINE (pd->downloader_pipeline));
406         gst_bus_add_watch (bus, __pd_downloader_callback, (gpointer)handle);
407         gst_object_unref (bus);
408         
409         /* Set URI on HTTP source */
410         g_object_set (G_OBJECT (pd->downloader_src), "location", pd->path_read_from, NULL);
411
412         /* set file download location on filesink*/
413         g_object_set (G_OBJECT (pd->downloader_sink), "location", pd->location_to_save, NULL);
414
415         debug_log ("src location = %s, save location = %s\n", pd->path_read_from, pd->location_to_save);
416
417         /* Start to download */
418         sret = gst_element_set_state (pd->downloader_pipeline, GST_STATE_PLAYING);
419         if (GST_STATE_CHANGE_FAILURE == sret)
420         {
421                 debug_error ("PD download pipeline failed to go to PLAYING state...");
422                 return FALSE;
423         }
424
425         debug_log ("set_state :: sret = %d\n", sret);
426
427         sret = gst_element_get_state (pd->downloader_pipeline, &cur_state, &pending_state, GST_CLOCK_TIME_NONE);
428         if (GST_STATE_CHANGE_FAILURE == sret)
429         {
430                 debug_error ("PD download pipeline failed to do get_state...");
431                 return FALSE;
432         }
433
434         debug_log ("get-state :: sret = %d\n", sret);
435
436         debug_fleave();
437
438         return TRUE;
439 }
440
441
442 gboolean _mmplayer_unrealize_pd_downloader (MMHandleType handle)
443 {
444         debug_fenter();
445
446         mm_player_pd_t * pd = NULL;
447
448         return_val_if_fail ( handle, FALSE );
449
450         pd = MM_PLAYER_GET_PD(handle);
451
452         return_val_if_fail ( pd && pd->downloader_pipeline, FALSE );
453
454         gst_element_set_state (pd->downloader_pipeline, GST_STATE_NULL);
455         gst_element_get_state (pd->downloader_pipeline, NULL, NULL, GST_CLOCK_TIME_NONE);
456
457         gst_object_unref (G_OBJECT (pd->downloader_pipeline));
458         pd->downloader_pipeline = NULL;
459
460         /* free */
461         MMPLAYER_FREEIF(pd->path_read_from);
462         MMPLAYER_FREEIF(pd->location_to_save);
463
464         debug_fleave();
465
466         return TRUE;
467 }
468
469
470 gint _mm_player_set_pd_downloader_message_cb(MMHandleType handle, MMMessageCallback callback, gpointer user_param)
471 {
472         debug_fenter();
473
474         mm_player_t * player = NULL;
475
476         return_val_if_fail ( handle, MM_ERROR_INVALID_ARGUMENT );
477
478         player = MM_PLAYER_CAST((MMHandleType)handle);
479
480         /* PD callback can be set as soon as player handle is created.
481           * So, player handle must have it.
482           */
483         player->pd_msg_cb = callback;
484         player->pd_msg_cb_param = user_param;
485
486         debug_log("msg_cb : 0x%x     msg_cb_param : 0x%x\n", (guint)callback, (guint)user_param);
487
488         debug_fleave();
489
490         return MM_ERROR_NONE;
491 }