4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
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>
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
13 * http://www.apache.org/licenses/LICENSE-2.0
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.
24 #include "mm_player_pd.h"
25 #include "mm_player_utils.h"
26 #include "mm_player_priv.h"
28 /*---------------------------------------------------------------------------------------
29 | LOCAL FUNCTION PROTOTYPES: |
30 ---------------------------------------------------------------------------------------*/
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);
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);
39 /*=======================================================================================
40 | FUNCTION DEFINITIONS |
41 =======================================================================================*/
43 __pd_downloader_callback(GstBus *bus, GstMessage *msg, gpointer data)
45 mm_player_t * player = NULL;
46 mm_player_pd_t *pd = NULL;
51 /* chech player handle */
52 return_val_if_fail ( data, MM_ERROR_INVALID_ARGUMENT );
54 player = MM_PLAYER_CAST((MMHandleType)data);
56 /* get PD downloader handle */
57 pd = MM_PLAYER_GET_PD((MMHandleType)data);
59 return_val_if_fail ( pd, MM_ERROR_INVALID_ARGUMENT );
61 // g_print("%s\n", GST_MESSAGE_TYPE_NAME(msg));
63 switch ( GST_MESSAGE_TYPE( msg ) )
67 debug_log("PD Downloader EOS received....\n");
69 g_object_set (G_OBJECT (pd->playback_pipeline_src), "eos", TRUE, NULL);
71 /* notify application that download is completed */
72 __pd_downloader_post_message(player, MM_MESSAGE_PD_DOWNLOADER_END, NULL);
74 #ifdef PD_SELF_DOWNLOAD
75 _mmplayer_unrealize_pd_downloader ((MMHandleType)data);
80 case GST_MESSAGE_ERROR:
85 GstMessage *new_msg = NULL;
88 gst_message_parse_error( msg, &error, &debug );
89 debug_error ("GST_MESSAGE_ERROR = %s\n", debug);
91 new_msg = gst_message_new_error (GST_OBJECT_CAST (pd->playback_pipeline_src), error, debug);
93 /* notify application that pd has any error */
94 ret = gst_element_post_message (pd->playback_pipeline_src, new_msg);
96 _mmplayer_unrealize_pd_downloader ((MMHandleType)data);
100 case GST_MESSAGE_WARNING:
103 GError* error = NULL;
105 gst_message_parse_warning(msg, &error, &debug);
106 debug_warning("warning : %s\n", error->message);
107 debug_warning("debug : %s\n", debug);
109 MMPLAYER_FREEIF(debug);
110 g_error_free( error);
114 case GST_MESSAGE_STATE_CHANGED:
116 GstState old_state, new_state;
119 /* get old and new state */
120 gst_message_parse_state_changed (msg, &old_state, &new_state, NULL);
122 if (old_state == new_state)
125 /* we only care about pipeline state changes */
126 if (GST_MESSAGE_SRC (msg) != GST_OBJECT (pd->downloader_pipeline))
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));
137 case GST_STATE_VOID_PENDING:
139 case GST_STATE_READY:
140 case GST_STATE_PAUSED:
143 case GST_STATE_PLAYING:
144 /* notify application that download is stated */
145 __pd_downloader_post_message(player, MM_MESSAGE_PD_DOWNLOADER_START, NULL);
154 case GST_MESSAGE_DURATION:
156 #ifndef GST_API_VERSION_1
157 GstFormat fmt= GST_FORMAT_BYTES;
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 ) )
167 GstMessage *new_msg = NULL;
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);
175 // TODO: check if playback pipeline is closed well or not
176 g_object_set (G_OBJECT (pd->playback_pipeline_src), "eos", TRUE, NULL);
178 _mmplayer_unrealize_pd_downloader ((MMHandleType)data);
180 debug_error("failed to query total size for download\n");
184 if ( ! gst_element_query_duration( pd->downloader_pipeline, &fmt, &size ) )
187 GstMessage *new_msg = NULL;
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);
195 // TODO: check if playback pipeline is closed well or not
196 g_object_set (G_OBJECT (pd->playback_pipeline_src), "eos", TRUE, NULL);
198 _mmplayer_unrealize_pd_downloader ((MMHandleType)data);
200 debug_error("failed to query total size for download\n");
205 pd->total_size = size;
207 debug_log("PD total size : %lld bytes\n", size);
212 debug_warning("unhandled message\n");
222 gboolean __pd_downloader_post_message(mm_player_t * player, enum MMMessageType msgtype, MMMessageParamType* param)
226 return_val_if_fail( player, FALSE );
228 if ( !player->pd_msg_cb )
230 debug_warning("no msg callback. can't post\n");
234 player->pd_msg_cb(msgtype, param, player->pd_msg_cb_param);
242 gboolean _mmplayer_get_pd_downloader_status(MMHandleType handle, guint64 *current_pos, guint64 *total_size)
246 mm_player_pd_t * pd = NULL;
249 return_val_if_fail(handle, MM_ERROR_INVALID_ARGUMENT);
251 pd = MM_PLAYER_GET_PD(handle);
253 return_val_if_fail(pd, MM_ERROR_INVALID_ARGUMENT);
254 return_val_if_fail(pd->downloader_pipeline, MM_ERROR_INVALID_ARGUMENT);
256 if ( !pd->total_size )
258 debug_warning("not ready to get total size\n");
262 g_object_get(pd->downloader_sink, "current-bytes", &bytes, NULL);
264 debug_log("PD status : %lld / %lld\n", bytes, pd->total_size);
266 *current_pos = bytes;
267 *total_size = pd->total_size;
275 mm_player_pd_t * _mmplayer_create_pd_downloader()
279 mm_player_pd_t * pd = NULL;
281 /* create PD handle */
282 pd = (mm_player_pd_t *) malloc (sizeof (mm_player_pd_t));
285 debug_error ("Failed to create pd downloader handle...\n");
295 gboolean _mmplayer_destroy_pd_downloader (MMHandleType handle)
299 mm_player_pd_t * pd = NULL;
301 return_val_if_fail ( handle, MM_ERROR_INVALID_ARGUMENT );
303 pd = MM_PLAYER_GET_PD(handle);
305 if (pd && pd->downloader_pipeline)
306 _mmplayer_unrealize_pd_downloader (handle);
308 /* release PD handle */
317 gboolean _mmplayer_realize_pd_downloader (MMHandleType handle, gchar *src_uri, gchar *dst_uri, GstElement *pushsrc)
321 mm_player_pd_t * pd = NULL;
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 );
328 pd = MM_PLAYER_GET_PD(handle);
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;
342 gboolean _mmplayer_start_pd_downloader (MMHandleType handle)
345 gboolean bret = FALSE;
346 GstStateChangeReturn sret = GST_STATE_CHANGE_SUCCESS;
348 GstState pending_state;
352 mm_player_pd_t * pd = NULL;
354 return_val_if_fail ( handle, MM_ERROR_INVALID_ARGUMENT );
356 pd = MM_PLAYER_GET_PD(handle);
359 pd->downloader_pipeline = gst_pipeline_new ("PD Downloader");
360 if (NULL == pd->downloader_pipeline)
362 debug_error ("Can't create PD download pipeline...");
367 pd->downloader_src = gst_element_factory_make ("souphttpsrc", "PD HTTP download source");
368 if (NULL == pd->downloader_src)
370 debug_error ("Can't create PD download src...");
375 pd->downloader_queue = gst_element_factory_make ("queue", "PD download queue");
376 if (NULL == pd->downloader_queue)
378 debug_error ("Can't create PD download queue...");
383 pd->downloader_sink = gst_element_factory_make ("filesink", "PD download sink");
384 if (NULL == pd->downloader_sink)
386 debug_error ("Can't create PD download sink...");
390 g_object_set(pd->downloader_sink, "sync", FALSE, NULL);
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,
397 bret = gst_element_link_many (pd->downloader_src, pd->downloader_queue, pd->downloader_sink, NULL);
400 debug_error ("Can't link elements src and sink...");
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);
409 /* Set URI on HTTP source */
410 g_object_set (G_OBJECT (pd->downloader_src), "location", pd->path_read_from, NULL);
412 /* set file download location on filesink*/
413 g_object_set (G_OBJECT (pd->downloader_sink), "location", pd->location_to_save, NULL);
415 debug_log ("src location = %s, save location = %s\n", pd->path_read_from, pd->location_to_save);
417 /* Start to download */
418 sret = gst_element_set_state (pd->downloader_pipeline, GST_STATE_PLAYING);
419 if (GST_STATE_CHANGE_FAILURE == sret)
421 debug_error ("PD download pipeline failed to go to PLAYING state...");
425 debug_log ("set_state :: sret = %d\n", sret);
427 sret = gst_element_get_state (pd->downloader_pipeline, &cur_state, &pending_state, GST_CLOCK_TIME_NONE);
428 if (GST_STATE_CHANGE_FAILURE == sret)
430 debug_error ("PD download pipeline failed to do get_state...");
434 debug_log ("get-state :: sret = %d\n", sret);
442 gboolean _mmplayer_unrealize_pd_downloader (MMHandleType handle)
446 mm_player_pd_t * pd = NULL;
448 return_val_if_fail ( handle, FALSE );
450 pd = MM_PLAYER_GET_PD(handle);
452 return_val_if_fail ( pd && pd->downloader_pipeline, FALSE );
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);
457 gst_object_unref (G_OBJECT (pd->downloader_pipeline));
458 pd->downloader_pipeline = NULL;
461 MMPLAYER_FREEIF(pd->path_read_from);
462 MMPLAYER_FREEIF(pd->location_to_save);
470 gint _mm_player_set_pd_downloader_message_cb(MMHandleType handle, MMMessageCallback callback, gpointer user_param)
474 mm_player_t * player = NULL;
476 return_val_if_fail ( handle, MM_ERROR_INVALID_ARGUMENT );
478 player = MM_PLAYER_CAST((MMHandleType)handle);
480 /* PD callback can be set as soon as player handle is created.
481 * So, player handle must have it.
483 player->pd_msg_cb = callback;
484 player->pd_msg_cb_param = user_param;
486 debug_log("msg_cb : 0x%x msg_cb_param : 0x%x\n", (guint)callback, (guint)user_param);
490 return MM_ERROR_NONE;