remove useless code
[platform/core/multimedia/libmm-player.git] / src / mm_player_priv.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>, YeJin Cho <cho.yejin@samsung.com>, YoungHwan An <younghwan_.an@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21
22 /*===========================================================================================
23 |                                                                                                                                                                                       |
24 |  INCLUDE FILES                                                                                                                                                        |
25 |                                                                                                                                                                                       |
26 ========================================================================================== */
27 #include <glib.h>
28 #include <gst/gst.h>
29 #include <gst/app/gstappsrc.h>
30 #include <gst/interfaces/xoverlay.h>
31 #include <unistd.h>
32 #include <string.h>
33 #include <sys/time.h>
34 #include <stdlib.h>
35
36 #include <mm_error.h>
37 #include <mm_attrs.h>
38 #include <mm_attrs_private.h>
39 #include <mm_debug.h>
40
41 #include "mm_player_priv.h"
42 #include "mm_player_ini.h"
43 #include "mm_player_attrs.h"
44 #include "mm_player_capture.h"
45
46 /*===========================================================================================
47 |                                                                                                                                                                                       |
48 |  LOCAL DEFINITIONS AND DECLARATIONS FOR MODULE                                                                                        |
49 |                                                                                                                                                                                       |
50 ========================================================================================== */
51
52 /*---------------------------------------------------------------------------
53 |    GLOBAL CONSTANT DEFINITIONS:                                                                                       |
54 ---------------------------------------------------------------------------*/
55
56 /*---------------------------------------------------------------------------
57 |    IMPORTED VARIABLE DECLARATIONS:                                                                            |
58 ---------------------------------------------------------------------------*/
59
60 /*---------------------------------------------------------------------------
61 |    IMPORTED FUNCTION DECLARATIONS:                                                                            |
62 ---------------------------------------------------------------------------*/
63
64 /*---------------------------------------------------------------------------
65 |    LOCAL #defines:                                                                                                            |
66 ---------------------------------------------------------------------------*/
67 #define TRICK_PLAY_MUTE_THRESHOLD_MAX   2.0
68 #define TRICK_PLAY_MUTE_THRESHOLD_MIN   0.0
69
70 #define MM_VOLUME_FACTOR_DEFAULT                1.0
71 #define MM_VOLUME_FACTOR_MIN                            0
72 #define MM_VOLUME_FACTOR_MAX                            1.0
73
74 #define MM_PLAYER_FADEOUT_TIME_DEFAULT  700000 // 700 msec
75
76 #define MM_PLAYER_MPEG_VNAME                            "mpegversion"
77 #define MM_PLAYER_DIVX_VNAME                            "divxversion"
78 #define MM_PLAYER_WMV_VNAME                             "wmvversion"
79 #define MM_PLAYER_WMA_VNAME                             "wmaversion"
80
81 #define DEFAULT_PLAYBACK_RATE                   1.0
82
83 #define GST_QUEUE_DEFAULT_TIME                  2
84 #define GST_QUEUE_HLS_TIME                              8
85
86 /* video capture callback*/
87 gulong ahs_appsrc_cb_probe_id = 0;
88
89 #define MMPLAYER_USE_FILE_FOR_BUFFERING(player) (((player)->profile.uri_type != MM_PLAYER_URI_TYPE_HLS) && (PLAYER_INI()->http_file_buffer_path) && (strlen(PLAYER_INI()->http_file_buffer_path) > 0) )
90 #define MMPLAYER_PLAY_SUBTITLE(player) ((player)->play_subtitle)
91
92 #define LAZY_PAUSE_TIMEOUT_MSEC 700     
93
94 /*---------------------------------------------------------------------------
95 |    LOCAL CONSTANT DEFINITIONS:                                                                                        |
96 ---------------------------------------------------------------------------*/
97
98 /*---------------------------------------------------------------------------
99 |    LOCAL DATA TYPE DEFINITIONS:                                                                                       |
100 ---------------------------------------------------------------------------*/
101
102 /*---------------------------------------------------------------------------
103 |    GLOBAL VARIABLE DEFINITIONS:                                                                                       |
104 ---------------------------------------------------------------------------*/
105
106 /*---------------------------------------------------------------------------
107 |    LOCAL VARIABLE DEFINITIONS:                                                                                        |
108 ---------------------------------------------------------------------------*/
109
110 /*---------------------------------------------------------------------------
111 |    LOCAL FUNCTION PROTOTYPES:                                                                                         |
112 ---------------------------------------------------------------------------*/
113 static gboolean __mmplayer_set_state(mm_player_t* player, int state);
114 static int              __mmplayer_get_state(mm_player_t* player);
115 static int              __mmplayer_gst_create_video_pipeline(mm_player_t* player, GstCaps *caps, MMDisplaySurfaceType surface_type);
116 static int              __mmplayer_gst_create_audio_pipeline(mm_player_t* player);
117 static int              __mmplayer_gst_create_text_pipeline(mm_player_t* player);
118 static int              __mmplayer_gst_create_subtitle_pipeline(mm_player_t* player);
119 static int              __mmplayer_gst_create_pipeline(mm_player_t* player);
120 static int              __mmplayer_gst_destroy_pipeline(mm_player_t* player);
121 static int              __mmplayer_gst_element_link_bucket(GList* element_bucket);
122
123 static gboolean __mmplayer_gst_callback(GstBus *bus, GstMessage *msg, gpointer data);
124 static void     __mmplayer_gst_decode_callback(GstElement *decodebin, GstPad *pad, gboolean last, gpointer data);
125
126 static void     __mmplayer_typefind_have_type(  GstElement *tf, guint probability, GstCaps *caps, gpointer data);
127 static gboolean __mmplayer_try_to_plug(mm_player_t* player, GstPad *pad, const GstCaps *caps);
128 static void     __mmplayer_pipeline_complete(GstElement *decodebin,  gpointer data);
129 static gboolean __mmplayer_is_midi_type(gchar* str_caps);
130 static gboolean __mmplayer_is_amr_type (gchar *str_caps);
131 static gboolean __mmplayer_is_only_mp3_type (gchar *str_caps);
132
133 static gboolean __mmplayer_close_link(mm_player_t* player, GstPad *srcpad, GstElement *sinkelement, const char *padname, const GList *templlist);
134 static gboolean __mmplayer_feature_filter(GstPluginFeature *feature, gpointer data);
135 static void     __mmplayer_add_new_pad(GstElement *element, GstPad *pad, gpointer data);
136
137 static void             __mmplayer_gst_rtp_no_more_pads (GstElement *element,  gpointer data);
138 static void             __mmplayer_gst_rtp_dynamic_pad (GstElement *element, GstPad *pad, gpointer data);
139 static gboolean __mmplayer_update_stream_service_type( mm_player_t* player );
140 static gboolean __mmplayer_update_subtitle( GstElement* object, GstBuffer *buffer, GstPad *pad, gpointer data);
141
142
143 static void     __mmplayer_init_factories(mm_player_t* player);
144 static void     __mmplayer_release_factories(mm_player_t* player);
145 static void     __mmplayer_release_misc(mm_player_t* player);
146 static gboolean __mmplayer_gstreamer_init(void);
147
148 static int              __mmplayer_gst_set_state (mm_player_t* player, GstElement * pipeline,  GstState state, gboolean async, gint timeout );
149 gboolean __mmplayer_post_message(mm_player_t* player, enum MMMessageType msgtype, MMMessageParamType* param);
150 static gboolean __mmplayer_gst_extract_tag_from_msg(mm_player_t* player, GstMessage *msg);
151 int             __mmplayer_switch_audio_sink (mm_player_t* player);
152 static gboolean __mmplayer_gst_remove_fakesink(mm_player_t* player, MMPlayerGstElement* fakesink);
153 static int              __mmplayer_check_state(mm_player_t* player, enum PlayerCommandState command);
154 static gboolean __mmplayer_audio_stream_probe (GstPad *pad, GstBuffer *buffer, gpointer u_data);
155
156 static gboolean __mmplayer_dump_pipeline_state( mm_player_t* player );
157 static gboolean __mmplayer_check_subtitle( mm_player_t* player );
158 static gboolean __mmplayer_handle_gst_error ( mm_player_t* player, GstMessage * message, GError* error );
159 static gboolean __mmplayer_handle_streaming_error  ( mm_player_t* player, GstMessage * message );
160 static void             __mmplayer_post_delayed_eos( mm_player_t* player, int delay_in_ms );
161 static void     __mmplayer_cancel_delayed_eos( mm_player_t* player );
162 static gboolean __mmplayer_eos_timer_cb(gpointer u_data);
163 static gboolean __mmplayer_link_decoder( mm_player_t* player,GstPad *srcpad);
164 static gboolean __mmplayer_link_sink( mm_player_t* player,GstPad *srcpad);
165 static int      __mmplayer_post_missed_plugin(mm_player_t* player);
166 static int              __mmplayer_check_not_supported_codec(mm_player_t* player, gchar* mime);
167 static gboolean __mmplayer_configure_audio_callback(mm_player_t* player);
168 static void     __mmplayer_add_sink( mm_player_t* player, GstElement* sink);
169 static void     __mmplayer_del_sink( mm_player_t* player, GstElement* sink);
170 static void             __mmplayer_release_signal_connection(mm_player_t* player);
171 static void __mmplayer_set_antishock( mm_player_t* player, gboolean disable_by_force);
172 static gpointer __mmplayer_repeat_thread(gpointer data);
173 int _mmplayer_get_track_count(MMHandleType hplayer,  MMPlayerTrackType track_type, int *count);
174
175 static int              __gst_realize(mm_player_t* player);
176 static int              __gst_unrealize(mm_player_t* player);
177 static int              __gst_start(mm_player_t* player);
178 static int              __gst_stop(mm_player_t* player);
179 static int              __gst_pause(mm_player_t* player, gboolean async);
180 static int              __gst_resume(mm_player_t* player, gboolean async);
181 static gboolean __gst_seek(mm_player_t* player, GstElement * element, gdouble rate,
182                                         GstFormat format, GstSeekFlags flags, GstSeekType cur_type,
183                                         gint64 cur, GstSeekType stop_type, gint64 stop );
184 static int __gst_pending_seek ( mm_player_t* player );
185
186 static int              __gst_set_position(mm_player_t* player, int format, unsigned long position, gboolean internal_called);
187 static int              __gst_get_position(mm_player_t* player, int format, unsigned long *position);
188 static int              __gst_get_buffer_position(mm_player_t* player, int format, unsigned long* start_pos, unsigned long* stop_pos);
189 static int              __gst_adjust_subtitle_position(mm_player_t* player, int format, int position);
190 static int              __gst_set_message_callback(mm_player_t* player, MMMessageCallback callback, gpointer user_param);
191 static void     __gst_set_async_state_change(mm_player_t* player, gboolean async);
192
193 static gint     __gst_handle_core_error( mm_player_t* player, int code );
194 static gint     __gst_handle_library_error( mm_player_t* player, int code );
195 static gint     __gst_handle_resource_error( mm_player_t* player, int code );
196 static gint     __gst_handle_stream_error( mm_player_t* player, GError* error, GstMessage * message );
197 static gint             __gst_transform_gsterror( mm_player_t* player, GstMessage * message, GError* error);
198 static gboolean __gst_send_event_to_sink( mm_player_t* player, GstEvent* event );
199
200 static int __mmplayer_set_pcm_extraction(mm_player_t* player);
201 static gboolean __mmplayer_can_extract_pcm( mm_player_t* player );
202
203 /*fadeout */
204 static void __mmplayer_do_sound_fadedown(mm_player_t* player, unsigned int time);
205 static void __mmplayer_undo_sound_fadedown(mm_player_t* player);
206
207 static void     __mmplayer_add_new_caps(GstPad* pad, GParamSpec* unused, gpointer data);
208 static void __mmplayer_set_unlinked_mime_type(mm_player_t* player, GstCaps *caps);
209
210 /* util */
211 const gchar * __get_state_name ( int state );
212 static gboolean __is_streaming( mm_player_t* player );
213 static gboolean __is_rtsp_streaming( mm_player_t* player );
214 static gboolean __is_live_streaming ( mm_player_t* player );
215 static gboolean __is_http_streaming( mm_player_t* player );
216 static gboolean __is_http_live_streaming( mm_player_t* player );
217 static gboolean __is_http_progressive_down(mm_player_t* player);
218
219 static gboolean __mmplayer_warm_up_video_codec( mm_player_t* player,  GstElementFactory *factory);
220 static GstBusSyncReply __mmplayer_bus_sync_callback (GstBus * bus, GstMessage * message, gpointer data);
221
222 static int  __mmplayer_realize_streaming_ext(mm_player_t* player);
223 static int __mmplayer_unrealize_streaming_ext(mm_player_t *player);
224 static int __mmplayer_start_streaming_ext(mm_player_t *player);
225 static int __mmplayer_destroy_streaming_ext(mm_player_t* player);
226
227
228 /*===========================================================================================
229 |                                                                                                                                                                                       |
230 |  FUNCTION DEFINITIONS                                                                                                                                         |
231 |                                                                                                                                                                                       |
232 ========================================================================================== */
233
234 /* implementing player FSM */
235 /* FIXIT : We need to handle state transition also at here since start api is no more sync */
236 static int
237 __mmplayer_check_state(mm_player_t* player, enum PlayerCommandState command)
238 {
239         MMPlayerStateType current_state = MM_PLAYER_STATE_NUM;
240         MMPlayerStateType pending_state = MM_PLAYER_STATE_NUM;
241         MMPlayerStateType target_state = MM_PLAYER_STATE_NUM;
242         MMPlayerStateType prev_state = MM_PLAYER_STATE_NUM;
243
244         debug_fenter();
245
246         return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
247
248         //debug_log("incomming command : %d \n", command );
249
250         current_state = MMPLAYER_CURRENT_STATE(player);
251         pending_state = MMPLAYER_PENDING_STATE(player);
252         target_state = MMPLAYER_TARGET_STATE(player);
253         prev_state = MMPLAYER_PREV_STATE(player);
254
255         MMPLAYER_PRINT_STATE(player);
256
257         switch( command )
258         {
259                 case MMPLAYER_COMMAND_CREATE:
260                 {
261                         MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_NULL;
262                         
263                         if ( current_state == MM_PLAYER_STATE_NULL ||
264                                 current_state == MM_PLAYER_STATE_READY ||
265                                 current_state == MM_PLAYER_STATE_PAUSED ||
266                                 current_state == MM_PLAYER_STATE_PLAYING )
267                                 goto NO_OP;
268                 }
269                 break;
270
271                 case MMPLAYER_COMMAND_DESTROY:
272                 {
273                         /* destroy can called anytime */
274
275                         MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_NONE;
276                 }
277                 break;
278
279                 case MMPLAYER_COMMAND_REALIZE:
280                 {
281                         MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_READY;
282
283                         if ( pending_state != MM_PLAYER_STATE_NONE )
284                         {
285                                 goto INVALID_STATE;
286                         }
287                         else
288                         {
289                                 /* need ready state to realize */
290                                 if ( current_state == MM_PLAYER_STATE_READY )
291                                         goto NO_OP;
292
293                                 if ( current_state != MM_PLAYER_STATE_NULL )
294                                         goto INVALID_STATE;
295                         }
296                 }
297                 break;
298
299                 case MMPLAYER_COMMAND_UNREALIZE:
300                 {
301                         MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_NULL;
302
303                         if ( current_state == MM_PLAYER_STATE_NULL )
304                                 goto NO_OP;
305                 }
306                 break;
307
308                 case MMPLAYER_COMMAND_START:
309                 {
310                         if (MMPLAYER_IS_HTTP_PD(player))
311                                 goto INVALID_STATE;
312
313                         MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_PLAYING;
314
315                         if ( pending_state == MM_PLAYER_STATE_NONE )
316                         {
317                                 if ( current_state == MM_PLAYER_STATE_PLAYING )
318                                         goto NO_OP;
319                                 else if ( current_state  != MM_PLAYER_STATE_READY &&
320                                         current_state != MM_PLAYER_STATE_PAUSED )
321                                         goto INVALID_STATE;
322                         }
323                         else if ( pending_state == MM_PLAYER_STATE_PLAYING )
324                         {
325                                 goto ALREADY_GOING;
326                         }
327                         else if ( pending_state == MM_PLAYER_STATE_PAUSED )
328                         {
329                                 debug_log("player is going to paused state, just change the pending state as playing");
330                         }
331                         else
332                         {
333                                 goto INVALID_STATE;
334                         }
335                 }
336                 break;
337
338                 case MMPLAYER_COMMAND_STOP:
339                 {
340                         MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_READY;
341
342                         if ( current_state == MM_PLAYER_STATE_READY )
343                                 goto NO_OP;
344                         
345                         /* need playing/paused state to stop */
346                         if ( current_state != MM_PLAYER_STATE_PLAYING &&
347                                  current_state != MM_PLAYER_STATE_PAUSED )
348                                 goto INVALID_STATE;
349                 }
350                 break;
351
352                 case MMPLAYER_COMMAND_PAUSE:
353                 {
354                         if ( MMPLAYER_IS_LIVE_STREAMING( player ) )
355                                 goto NO_OP;
356
357                         if (player->doing_seek)
358                                 goto NOT_COMPLETED_SEEK;
359
360                         MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_PAUSED;
361
362                         if ( pending_state == MM_PLAYER_STATE_NONE )
363                         {
364                                 if ( current_state == MM_PLAYER_STATE_PAUSED )
365                                         goto NO_OP;
366                                 else if ( current_state != MM_PLAYER_STATE_PLAYING && current_state != MM_PLAYER_STATE_READY ) // support loading state of broswer
367                                         goto INVALID_STATE;
368                         }
369                         else if ( pending_state == MM_PLAYER_STATE_PAUSED )
370                         {
371                                 goto ALREADY_GOING;
372                         }
373                         else if ( pending_state == MM_PLAYER_STATE_PLAYING )
374                         {
375                                 if ( current_state == MM_PLAYER_STATE_PAUSED ) {
376                                         debug_log("player is PAUSED going to PLAYING, just change the pending state as PAUSED");
377                                 } else {
378                                         goto INVALID_STATE;
379                                 }
380                         }
381                 }
382                 break;
383
384                 case MMPLAYER_COMMAND_RESUME:
385                 {
386                         if ( MMPLAYER_IS_LIVE_STREAMING(player) )
387                                 goto NO_OP;
388
389                         if (player->doing_seek)
390                                 goto NOT_COMPLETED_SEEK;
391
392                         MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_PLAYING;
393
394                         if ( pending_state == MM_PLAYER_STATE_NONE )
395                         {
396                                 if ( current_state == MM_PLAYER_STATE_PLAYING )
397                                         goto NO_OP;
398                                 else if (  current_state != MM_PLAYER_STATE_PAUSED )
399                                         goto INVALID_STATE;
400                         }
401                         else if ( pending_state == MM_PLAYER_STATE_PLAYING )
402                         {
403                                 goto ALREADY_GOING;
404                         }
405                         else if ( pending_state == MM_PLAYER_STATE_PAUSED )
406                         {
407                                 debug_log("player is going to paused state, just change the pending state as playing");
408                         }
409                         else
410                         {
411                                 goto INVALID_STATE;
412                         }
413                 }
414                 break;
415
416                 default:
417                 break;
418         }
419         player->cmd = command;
420
421         debug_fleave();
422         return MM_ERROR_NONE;
423
424 INVALID_STATE:
425         debug_warning("since player is in wrong state(%s). it's not able to apply the command(%d)",
426                 MMPLAYER_STATE_GET_NAME(current_state), command);
427         return MM_ERROR_PLAYER_INVALID_STATE;
428
429 NOT_COMPLETED_SEEK:
430         debug_warning("not completed seek");
431         return MM_ERROR_PLAYER_DOING_SEEK;
432
433 NO_OP:
434         debug_warning("player is in the desired state(%s). doing noting", MMPLAYER_STATE_GET_NAME(current_state));
435         return MM_ERROR_PLAYER_NO_OP;
436
437 ALREADY_GOING:
438         debug_warning("player is already going to %s, doing nothing", MMPLAYER_STATE_GET_NAME(pending_state));
439         return MM_ERROR_PLAYER_NO_OP;
440 }
441
442 int
443 __mmplayer_gst_set_state (mm_player_t* player, GstElement * element,  GstState state, gboolean async, gint timeout) // @
444 {
445         GstState element_state = GST_STATE_VOID_PENDING;
446         GstState element_pending_state = GST_STATE_VOID_PENDING;
447         GstStateChangeReturn ret = GST_STATE_CHANGE_FAILURE;
448
449         debug_fenter();
450         
451         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
452         return_val_if_fail ( element, MM_ERROR_INVALID_ARGUMENT );
453
454         debug_log("setting [%s] element state to : %d\n", GST_ELEMENT_NAME(element),  state);
455
456         /* set state */
457         ret = gst_element_set_state(element, state);
458
459         if ( ret == GST_STATE_CHANGE_FAILURE )
460         {
461                 debug_error("failed to set  [%s] state to [%d]\n", GST_ELEMENT_NAME(element), state);
462                 return MM_ERROR_PLAYER_INTERNAL;
463         }
464         
465         /* return here so state transition to be done in async mode */
466         if ( async )
467         {
468                 debug_log("async state transition. not waiting for state complete.\n");
469                 return MM_ERROR_NONE;
470         }
471
472         /* wait for state transition */
473         ret = gst_element_get_state( element, &element_state, &element_pending_state, timeout * GST_SECOND );
474
475         if ( ret == GST_STATE_CHANGE_FAILURE || ( state != element_state ) )
476         {
477                 debug_error("failed to change [%s] element state to [%s] within %d sec\n",
478                         GST_ELEMENT_NAME(element), 
479                         gst_element_state_get_name(state), timeout );
480                 
481                 debug_error(" [%s] state : %s   pending : %s \n", 
482                         GST_ELEMENT_NAME(element), 
483                         gst_element_state_get_name(element_state), 
484                         gst_element_state_get_name(element_pending_state) );
485
486                 return MM_ERROR_PLAYER_INTERNAL;
487         }
488
489         debug_log("[%s] element state has changed to %s \n",
490                 GST_ELEMENT_NAME(element), 
491                 gst_element_state_get_name(element_state));
492
493         debug_fleave();
494         
495         return MM_ERROR_NONE;
496 }
497
498 static void
499 __mmplayer_videostream_cb(GstElement *element, void *stream,
500 int width, int height, gpointer data) // @
501 {
502         mm_player_t* player = (mm_player_t*)data;
503         int length = 0;
504
505         return_if_fail ( player );
506
507         debug_fenter();
508
509         if (player->video_stream_cb )
510         {
511                 length = width * height * 4; // for rgb 32bit
512                 player->video_stream_cb(stream, length, player->video_stream_cb_user_param, width, height);
513         }
514
515         debug_fleave();
516 }
517
518 gboolean
519 _mmplayer_update_content_attrs(mm_player_t* player) // @
520 {
521         GstFormat fmt  = GST_FORMAT_TIME;
522         gint64 dur_nsec = 0;
523         GstStructure* p = NULL;
524         MMHandleType attrs = 0;
525         gint retry_count = 0;
526         gint retry_count_max = 10;
527         gchar *path = NULL;
528         struct stat sb;
529
530         return_val_if_fail ( player, FALSE );
531
532         if ( ! player->need_update_content_attrs )
533         {
534                 debug_log("content attributes are already updated");
535                 return TRUE;
536         }
537
538         /* get content attribute first */
539         attrs = MMPLAYER_GET_ATTRS(player);
540         if ( !attrs )
541         {
542                 debug_error("cannot get content attribute");
543                 return FALSE;
544         }
545
546         /* update duration
547          * NOTE : we need to wait for a while until is possible to get duration from pipeline
548          * as getting duration timing is depends on behavier of demuxers ( or etc ).
549          * we set timeout 100ms * 10 as initial value. fix it if needed.
550          */
551         if ( player->need_update_content_dur  )
552         {
553                 while ( retry_count <  retry_count_max)
554                 {
555                         if ( FALSE == gst_element_query_duration( player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,
556                                 &fmt, &dur_nsec ) )
557                         {
558                                 /* retry if failed */
559                                 debug_warning("failed to get duraton. waiting 100ms and then retrying...");
560                                 usleep(100000);
561                                 retry_count++;
562                                 continue;
563                         }
564
565                         if ( dur_nsec == 0 && ( !MMPLAYER_IS_LIVE_STREAMING( player ) ) )
566                         {
567                                 /* retry if duration is zero in case of not live stream */
568                                 debug_warning("returned duration is zero. but it's not an live stream. retrying...");
569                                 usleep(100000);
570                                 retry_count++;
571                                 continue;
572                         }
573
574                         break;
575                 }
576
577                 player->duration = dur_nsec;
578                 debug_log("duration : %lld msec", GST_TIME_AS_MSECONDS(dur_nsec));
579
580                 /* try to get streaming service type */
581                 __mmplayer_update_stream_service_type( player );
582
583                 /* check duration is OK */
584                 if ( dur_nsec == 0 && !MMPLAYER_IS_LIVE_STREAMING( player ) )
585                 {
586                         /* FIXIT : find another way to get duration here. */
587                         debug_error("finally it's failed to get duration from pipeline. progressbar will not work correctely!");
588                 }
589                 else
590                 {
591                         player->need_update_content_dur = FALSE;
592                 }
593
594                 /*update duration */
595                 mm_attrs_set_int_by_name(attrs, "content_duration", GST_TIME_AS_MSECONDS(dur_nsec));
596         }
597         else
598         {
599                 debug_log("not ready to get duration or already updated");
600         }
601
602         /* update rate, channels */
603         if ( player->pipeline->audiobin &&
604                  player->pipeline->audiobin[MMPLAYER_A_SINK].gst )
605         {
606                 GstCaps *caps_a = NULL;
607                 GstPad* pad = NULL;
608                 gint samplerate = 0, channels = 0;
609
610                 pad = gst_element_get_static_pad(
611                                 player->pipeline->audiobin[MMPLAYER_A_CONV].gst, "sink" );
612
613                 if ( pad )
614                 {
615                         caps_a = gst_pad_get_negotiated_caps( pad );
616
617                         if ( caps_a )
618                         {
619                                 p = gst_caps_get_structure (caps_a, 0);
620
621                                 mm_attrs_get_int_by_name(attrs, "content_audio_samplerate", &samplerate);
622                                 if ( ! samplerate ) // check if update already or not
623                                 {
624                                         gst_structure_get_int (p, "rate", &samplerate);
625                                         mm_attrs_set_int_by_name(attrs, "content_audio_samplerate", samplerate);
626
627                                         gst_structure_get_int (p, "channels", &channels);
628                                         mm_attrs_set_int_by_name(attrs, "content_audio_channels", channels);
629
630                                         debug_log("samplerate : %d      channels : %d", samplerate, channels);
631                                 }
632                                 gst_caps_unref( caps_a );
633                                 caps_a = NULL;
634                         }
635                         else
636                         {
637                                 debug_warning("not ready to get audio caps");
638                         }
639
640                         gst_object_unref( pad );
641                 }
642                 else
643                 {
644                         debug_warning("failed to get pad from audiosink");
645                 }
646         }
647
648         /* update width, height, framerate */
649         if ( player->pipeline->videobin &&
650                  player->pipeline->videobin[MMPLAYER_V_SINK].gst )
651         {
652                 GstCaps *caps_v = NULL;
653                 GstPad* pad = NULL;
654                 gint tmpNu, tmpDe;
655                 gint width, height;
656
657                 pad = gst_element_get_static_pad( player->pipeline->videobin[MMPLAYER_V_SINK].gst, "sink" );
658                 if ( pad )
659                 {
660                         caps_v = gst_pad_get_negotiated_caps( pad );
661                         if (caps_v)
662                         {
663                                 p = gst_caps_get_structure (caps_v, 0);
664                                 gst_structure_get_int (p, "width", &width);
665                                 mm_attrs_set_int_by_name(attrs, "content_video_width", width);
666
667                                 gst_structure_get_int (p, "height", &height);
668                                 mm_attrs_set_int_by_name(attrs, "content_video_height", height);
669
670                                 gst_structure_get_fraction (p, "framerate", &tmpNu, &tmpDe);
671
672                                 debug_log("width : %d     height : %d", width, height );
673
674                                 gst_caps_unref( caps_v );
675                                 caps_v = NULL;
676
677                                 if (tmpDe > 0)
678                                 {
679                                         mm_attrs_set_int_by_name(attrs, "content_video_fps", tmpNu / tmpDe);
680                                         debug_log("fps : %d", tmpNu / tmpDe);
681                                 }
682                         }
683                         else
684                         {
685                                 debug_warning("failed to get negitiated caps from videosink");
686                         }
687                         gst_object_unref( pad );
688                         pad = NULL;
689                 }
690                 else
691                 {
692                         debug_warning("failed to get pad from videosink");
693                 }
694         }
695
696         if (player->duration)
697         {
698                 guint64 data_size = 0;
699
700                 if (!MMPLAYER_IS_STREAMING(player) && (player->can_support_codec & FOUND_PLUGIN_VIDEO))
701                 {
702                         mm_attrs_get_string_by_name(attrs, "profile_uri", &path);
703
704                         if (stat(path, &sb) == 0)
705                         {
706                                 data_size = (guint64)sb.st_size;
707                         }
708                 }
709                 else if (MMPLAYER_IS_HTTP_STREAMING(player))
710                 {
711                         data_size = player->http_content_size;
712                 }
713
714                 if (data_size)
715                 {
716                         guint64 bitrate = 0;
717                         guint64 msec_dur = 0;
718
719                         msec_dur = GST_TIME_AS_MSECONDS(player->duration);
720                         bitrate = data_size * 8 * 1000 / msec_dur;
721                         debug_log("file size : %u, video bitrate = %llu", data_size, bitrate);
722                         mm_attrs_set_int_by_name(attrs, "content_video_bitrate", bitrate);
723                 }
724         }
725
726
727         /* validate all */
728         if (  mmf_attrs_commit ( attrs ) )
729         {
730                 debug_error("failed to update attributes\n");
731                 return FALSE;
732         }
733
734         player->need_update_content_attrs = FALSE;
735
736         return TRUE;
737 }
738
739 gboolean __mmplayer_update_stream_service_type( mm_player_t* player )
740 {
741         MMHandleType attrs = 0;
742         gint streaming_type = STREAMING_SERVICE_NONE;
743
744         debug_fenter();
745
746         return_val_if_fail ( player &&
747                                         player->pipeline &&
748                                         player->pipeline->mainbin &&
749                                         player->pipeline->mainbin[MMPLAYER_M_SRC].gst,
750                                         FALSE );
751
752         /* streaming service type if streaming */
753         if ( ! MMPLAYER_IS_STREAMING(player) );
754                 return FALSE;
755
756         if (MMPLAYER_IS_RTSP_STREAMING(player))
757         {
758                 /* get property from rtspsrc element */
759                 g_object_get(G_OBJECT(player->pipeline->mainbin[MMPLAYER_M_SRC].gst), "service_type", &streaming_type, NULL);
760         }
761         else if (MMPLAYER_IS_HTTP_STREAMING(player))
762         {
763                 if ( player->duration <= 0)
764                         streaming_type = STREAMING_SERVICE_LIVE;
765                 else
766                         streaming_type = STREAMING_SERVICE_VOD;                 
767         }
768                 
769         player->streaming_type = streaming_type;
770
771         if ( player->streaming_type == STREAMING_SERVICE_LIVE)
772         {
773                 debug_log("It's live streaming. pause/resume/seek are not working.\n");
774         }
775         else if (player->streaming_type == STREAMING_SERVICE_LIVE)
776         {
777                 debug_log("It's vod streaming. pause/resume/seek are working.\n");
778         }
779         else
780         {
781                 debug_warning("fail to determine streaming type. pause/resume/seek may not working properly if stream is live stream\n");
782         }
783
784         /* get profile attribute */
785         attrs = MMPLAYER_GET_ATTRS(player);
786         if ( !attrs )
787         {
788                 debug_error("cannot get content attribute\n");
789                 return FALSE;
790         }
791
792         mm_attrs_set_int_by_name ( attrs, "streaming_type", streaming_type );
793         /* validate all */
794         if (  mmf_attrs_commit ( attrs ) )
795         {
796                 debug_warning("updating streaming service type failed. pause/resume/seek may not working properly if stream is live stream\n");
797                 return FALSE;
798         }
799
800         debug_fleave();
801
802         return TRUE;
803 }
804
805
806 /* this function sets the player state and also report
807  * it to applicaton by calling callback function
808  */
809 static gboolean
810 __mmplayer_set_state(mm_player_t* player, int state) // @
811 {
812         MMMessageParamType msg = {0, };
813         int asm_result = MM_ERROR_NONE;
814
815         debug_fenter();
816         return_val_if_fail ( player, FALSE );
817
818         if ( MMPLAYER_CURRENT_STATE(player) == state )
819         {
820                 debug_warning("already same state(%s)\n", MMPLAYER_STATE_GET_NAME(state));
821                 MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_NONE;
822                 return TRUE;
823         }
824
825         /* post message to application */
826         if (MMPLAYER_TARGET_STATE(player) == state)
827         {
828                 /* fill the message with state of player */
829                 msg.state.previous = MMPLAYER_CURRENT_STATE(player);
830                 msg.state.current = state;
831
832                 /* state changed by asm callback */
833                 if ( player->sm.by_asm_cb )
834                 {
835                         msg.union_type = MM_MSG_UNION_CODE;
836                         msg.code = player->sm.event_src;
837                         MMPLAYER_POST_MSG( player, MM_MESSAGE_STATE_INTERRUPTED, &msg );
838                 }
839                 /* state changed by usecase */
840                 else
841                 {
842                         MMPLAYER_POST_MSG( player, MM_MESSAGE_STATE_CHANGED, &msg );
843                 }
844
845                 debug_log ("player reach the target state, then do something in each state(%s).\n", 
846                         MMPLAYER_STATE_GET_NAME(MMPLAYER_TARGET_STATE(player)));
847         }
848         else
849         {
850                 debug_log ("intermediate state, do nothing.\n");
851                 MMPLAYER_PRINT_STATE(player);
852
853                 return TRUE;
854         }
855
856         /* update player states */
857         MMPLAYER_PREV_STATE(player) = MMPLAYER_CURRENT_STATE(player);
858         MMPLAYER_CURRENT_STATE(player) = state;
859         if ( MMPLAYER_CURRENT_STATE(player) == MMPLAYER_PENDING_STATE(player) )
860                 MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_NONE;
861
862         /* print state */
863         MMPLAYER_PRINT_STATE(player);
864         
865         switch ( MMPLAYER_TARGET_STATE(player) )
866         {
867                 case MM_PLAYER_STATE_NULL:      
868                 case MM_PLAYER_STATE_READY:
869                 {
870                         if (player->cmd == MMPLAYER_COMMAND_STOP)
871                         {
872                                 asm_result = _mmplayer_asm_set_state((MMHandleType)player, ASM_STATE_STOP);
873                                 if ( asm_result != MM_ERROR_NONE )
874                                 {
875                                         debug_error("failed to set asm state to stop\n");
876                                         return FALSE;
877                                 }
878                         }
879                 }
880                 break;
881                         
882                 case MM_PLAYER_STATE_PAUSED:
883                 {
884                         /* special care for local playback. normaly we can get some content attribute
885                          * when the demuxer is changed to PAUSED. so we are trying it. it will be tried again
886                          * when PLAYING state has signalled if failed.
887                          * note that this is only happening pause command has come before the state of pipeline
888                          * reach to the PLAYING.
889                          */
890                          if ( ! player->sent_bos ) // managed prepare sync case
891                          {
892                                 player->need_update_content_dur = TRUE;
893                                 _mmplayer_update_content_attrs( player );
894                          }
895
896                         /* add audio callback probe if condition is satisfied */
897                         if ( ! player->audio_cb_probe_id && player->is_sound_extraction )
898                                 __mmplayer_configure_audio_callback(player);
899
900                         asm_result = _mmplayer_asm_set_state((MMHandleType)player, ASM_STATE_PAUSE);
901                         if ( asm_result )
902                         {
903                                 debug_error("failed to set asm state to PAUSE\n");
904                                 return FALSE;
905                         }
906                 }
907                 break;
908
909                 case MM_PLAYER_STATE_PLAYING:
910                 {
911                         /* non-managed prepare case, should be updated */
912                         if ( ! player->need_update_content_dur)
913                         {
914                                 player->need_update_content_dur = TRUE;
915                                 _mmplayer_update_content_attrs ( player );
916                         }
917
918                         if ( player->cmd == MMPLAYER_COMMAND_START  && !player->sent_bos )
919                         {
920                                 __mmplayer_post_missed_plugin ( player );
921
922                                 /* update video resource status */
923                                 if ( ( player->can_support_codec & 0x02) == FOUND_PLUGIN_VIDEO )
924                                 {
925                                         asm_result = _mmplayer_asm_set_state((MMHandleType)player, ASM_STATE_PLAYING);
926                                         if ( asm_result )
927                                         {
928                                                 MMMessageParamType msg = {0, };
929                                                                 
930                                                 debug_error("failed to go ahead because of video conflict\n");
931                                                                                                         
932                                                 msg.union_type = MM_MSG_UNION_CODE;
933                                                 msg.code = MM_ERROR_POLICY_INTERRUPTED;
934                                                 MMPLAYER_POST_MSG( player, MM_MESSAGE_STATE_INTERRUPTED, &msg);
935
936                                                 _mmplayer_unrealize((MMHandleType)player);
937                                                                                                                 
938                                                 return FALSE;                                                           
939                                         }
940                                 }
941                         }
942
943                         if ( player->resumed_by_rewind && player->playback_rate < 0.0 )
944                         {
945                                 /* initialize because auto resume is done well. */
946                                 player->resumed_by_rewind = FALSE;
947                                 player->playback_rate = 1.0;
948                         }
949
950                         if ( !player->sent_bos )
951                         {
952                                 /* check audio codec field is set or not
953                                  * we can get it from typefinder or codec's caps.
954                                  */
955                                 gchar *audio_codec = NULL;
956                                 mm_attrs_get_string_by_name(player->attrs, "content_audio_codec", &audio_codec);
957
958                                 /* The codec format can't be sent for audio only case like amr, mid etc.
959                                  * Because, parser don't make related TAG.
960                                  * So, if it's not set yet, fill it with found data.
961                                  */
962                                 if ( ! audio_codec )
963                                 {
964                                         if ( g_strrstr(player->type, "audio/midi"))
965                                         {
966                                                 audio_codec = g_strdup("MIDI");
967
968                                         }
969                                         else if ( g_strrstr(player->type, "audio/x-amr"))
970                                         {
971                                                 audio_codec = g_strdup("AMR");
972                                         }
973                                         else if ( g_strrstr(player->type, "audio/mpeg") && !g_strrstr(player->type, "mpegversion=(int)1"))
974                                         {
975                                                 audio_codec = g_strdup("AAC");
976                                         }
977                                         else
978                                         {
979                                                 audio_codec = g_strdup("unknown");
980                                         }
981                                         mm_attrs_set_string_by_name(player->attrs, "content_audio_codec", audio_codec);
982
983                                         MMPLAYER_FREEIF(audio_codec);
984                                         mmf_attrs_commit(player->attrs);
985                                         debug_log("set audio codec type with caps\n");
986                                 }
987
988                                 MMTA_ACUM_ITEM_END("[KPI] start media player service", FALSE);
989                                 MMTA_ACUM_ITEM_END("[KPI] media player service create->playing", FALSE);
990
991                                 MMPLAYER_POST_MSG ( player, MM_MESSAGE_BEGIN_OF_STREAM, NULL );
992                                 player->sent_bos = TRUE;
993                         }
994                 }
995                 break;
996
997                 case MM_PLAYER_STATE_NONE:
998                 default:
999                         debug_warning("invalid target state, there is nothing to do.\n");
1000                         break;
1001         }
1002
1003         debug_fleave();
1004
1005         return TRUE;
1006 }
1007
1008
1009 gboolean
1010 __mmplayer_post_message(mm_player_t* player, enum MMMessageType msgtype, MMMessageParamType* param) // @
1011 {
1012         return_val_if_fail( player, FALSE );
1013
1014         debug_fenter();
1015
1016         if ( !player->msg_cb )
1017         {
1018                 debug_warning("no msg callback. can't post\n");
1019                 return FALSE;
1020         }
1021
1022         //debug_log("Message (type : %d)  will be posted using msg-cb(%p). \n", msgtype, player->msg_cb);
1023
1024         player->msg_cb(msgtype, param, player->msg_cb_param);
1025
1026         debug_fleave();
1027
1028         return TRUE;
1029 }
1030
1031
1032 static int
1033 __mmplayer_get_state(mm_player_t* player) // @
1034 {
1035         int state = MM_PLAYER_STATE_NONE;
1036
1037         debug_fenter();
1038         
1039         return_val_if_fail ( player, MM_PLAYER_STATE_NONE );
1040
1041         state = MMPLAYER_CURRENT_STATE(player);
1042
1043         debug_log("player state is %s.\n", MMPLAYER_STATE_GET_NAME(state));
1044
1045         debug_fleave();
1046         
1047         return state;
1048 }
1049
1050 static void
1051 __gst_set_async_state_change(mm_player_t* player, gboolean async)
1052 {
1053         //debug_fenter();
1054         return_if_fail( player && player->pipeline && player->pipeline->mainbin );
1055
1056         /* need only when we are using decodebin */
1057         if ( ! PLAYER_INI()->use_decodebin )
1058                 return;
1059
1060         /* audio sink */
1061         if ( player->pipeline->audiobin &&
1062                  player->pipeline->audiobin[MMPLAYER_A_SINK].gst )
1063         {
1064                 debug_log("audiosink async : %d\n", async);
1065                 g_object_set (G_OBJECT (player->pipeline->audiobin[MMPLAYER_A_SINK].gst), "async", async, NULL);
1066         }
1067
1068         /* video sink */
1069         if ( player->pipeline->videobin &&
1070                  player->pipeline->videobin[MMPLAYER_V_SINK].gst )
1071         {
1072                 debug_log("videosink async : %d\n", async);
1073                 g_object_set (G_OBJECT (player->pipeline->videobin[MMPLAYER_V_SINK].gst), "async", async, NULL);
1074         }
1075
1076         /* decodebin if enabled */
1077         if ( PLAYER_INI()->use_decodebin )
1078         {
1079                 debug_log("decodebin async : %d\n", async);
1080                 g_object_set (G_OBJECT (player->pipeline->mainbin[MMPLAYER_M_AUTOPLUG].gst), "async-handling", async, NULL);
1081         }
1082
1083         //debug_fleave();
1084 }
1085
1086 static gpointer __mmplayer_repeat_thread(gpointer data)
1087 {
1088         mm_player_t* player = (mm_player_t*) data;
1089         gboolean ret_value = FALSE;
1090         MMHandleType attrs = 0;
1091         gint count = 0;
1092
1093         return_val_if_fail ( player, NULL );
1094
1095         while ( ! player->repeat_thread_exit )
1096         {
1097                 debug_log("repeat thread started. waiting for signal.\n");
1098                 g_cond_wait( player->repeat_thread_cond, player->repeat_thread_mutex );
1099
1100                 if ( player->repeat_thread_exit )
1101                 {
1102                         debug_log("exiting repeat thread\n");
1103                         break;
1104                 }
1105
1106                 if ( !player->cmd_lock )
1107                 {
1108                         debug_log("can't get cmd lock\n");
1109                         return NULL;
1110                 }
1111
1112                 /* lock */
1113                 g_mutex_lock(player->cmd_lock); 
1114
1115                 attrs = MMPLAYER_GET_ATTRS(player);
1116
1117                 if (mm_attrs_get_int_by_name(attrs, "profile_play_count", &count) != MM_ERROR_NONE)
1118                 {
1119                         debug_error("can not get play count\n");
1120                         break;
1121                 }
1122
1123                 if ( player->section_repeat )
1124                 {
1125                         ret_value = _mmplayer_activate_section_repeat((MMHandleType)player, player->section_repeat_start, player->section_repeat_end);
1126                 }
1127                 else
1128                 {
1129                         if ( player->playback_rate < 0.0 )
1130                         {
1131                                 player->resumed_by_rewind = TRUE;
1132                                 _mmplayer_set_mute((MMHandleType)player, 0);
1133                                 MMPLAYER_POST_MSG( player, MM_MESSAGE_RESUMED_BY_REW, NULL );
1134                         }
1135
1136                         ret_value = __gst_seek( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, 1.0,
1137                                 GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET,
1138                                 0, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
1139
1140                         /* initialize */
1141                         player->sent_bos = FALSE;
1142                 }
1143
1144                 if ( ! ret_value )
1145                 {
1146                         debug_error("failed to set position to zero for rewind\n");
1147                         continue;
1148                 }
1149
1150                 /* decrease play count */
1151                 if ( count > 1 )
1152                 {
1153                         /* we successeded to rewind. update play count and then wait for next EOS */
1154                         count--;
1155
1156                         mm_attrs_set_int_by_name(attrs, "profile_play_count", count);
1157
1158                         /* commit attribute */
1159                         if ( mmf_attrs_commit ( attrs ) )
1160                         {
1161                                 debug_error("failed to commit attribute\n");
1162                         }
1163                 }
1164
1165                 /* unlock */
1166                 g_mutex_unlock(player->cmd_lock);
1167         }
1168
1169         return NULL;
1170 }
1171
1172 static void
1173 __mmplayer_handle_buffering_message ( mm_player_t* player )
1174 {
1175         MMPlayerStateType prev_state = MM_PLAYER_STATE_NONE;
1176         MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
1177         MMPlayerStateType target_state = MM_PLAYER_STATE_NONE;
1178         MMPlayerStateType pending_state = MM_PLAYER_STATE_NONE;
1179
1180         return_if_fail ( player );
1181
1182         prev_state = MMPLAYER_PREV_STATE(player),
1183         current_state = MMPLAYER_CURRENT_STATE(player);
1184         target_state = MMPLAYER_TARGET_STATE(player);
1185         pending_state = MMPLAYER_PENDING_STATE(player);
1186
1187         if ( MMPLAYER_IS_RTSP_STREAMING(player) )
1188                 return;
1189
1190         if ( !player->streamer->is_buffering )
1191         {
1192                 debug_log( "player state : prev %s, current %s, pending %s, target %s \n",
1193                         MMPLAYER_STATE_GET_NAME(prev_state),
1194                         MMPLAYER_STATE_GET_NAME(current_state),
1195                         MMPLAYER_STATE_GET_NAME(pending_state),
1196                         MMPLAYER_STATE_GET_NAME(target_state));
1197
1198                 /* NOTE : if buffering has done, player has to go to target state. */
1199                 switch ( target_state )
1200                 {
1201                         case MM_PLAYER_STATE_PAUSED :
1202                         {
1203                                 switch ( pending_state )
1204                                 {
1205                                         case MM_PLAYER_STATE_PLAYING:
1206                                         {
1207                                                 __gst_pause ( player, TRUE );
1208                                         }
1209                                         break;
1210
1211                                         case MM_PLAYER_STATE_PAUSED:
1212                                         {
1213                                                  debug_log("player is already going to paused state, there is nothing to do.\n");
1214                                         }
1215                                         break;
1216
1217                                         case MM_PLAYER_STATE_NONE:
1218                                         case MM_PLAYER_STATE_NULL:
1219                                         case MM_PLAYER_STATE_READY:
1220                                         default :
1221                                         {
1222                                                 debug_warning("invalid pending state [%s].\n", MMPLAYER_STATE_GET_NAME(pending_state) );
1223                                         }
1224                                                 break;
1225                                 }
1226                         }
1227                         break;
1228
1229                         case MM_PLAYER_STATE_PLAYING :
1230                         {
1231                                 switch ( pending_state )
1232                                 {
1233                                         case MM_PLAYER_STATE_NONE:
1234                                         {
1235                                                 if (current_state != MM_PLAYER_STATE_PLAYING)
1236                                                         __gst_resume ( player, TRUE );
1237                                         }
1238                                         break;
1239
1240                                         case MM_PLAYER_STATE_PAUSED:
1241                                         {
1242                                                 /* NOTE: It should be worked as asynchronously.
1243                                                  * Because, buffering can be completed during autoplugging when pipeline would try to go playing state directly.
1244                                                  */
1245                                                 __gst_resume ( player, TRUE );
1246                                         }
1247                                         break;
1248
1249                                         case MM_PLAYER_STATE_PLAYING:
1250                                         {
1251                                                  debug_log("player is already going to playing state, there is nothing to do.\n");
1252                                         }
1253                                         break;
1254
1255                                         case MM_PLAYER_STATE_NULL:
1256                                         case MM_PLAYER_STATE_READY:
1257                                         default :
1258                                         {
1259                                                 debug_warning("invalid pending state [%s].\n", MMPLAYER_STATE_GET_NAME(pending_state) );
1260                                         }
1261                                                 break;
1262                                 }
1263                         }
1264                         break;
1265
1266                         case MM_PLAYER_STATE_NULL :
1267                         case MM_PLAYER_STATE_READY :
1268                         case MM_PLAYER_STATE_NONE :
1269                         default:
1270                         {
1271                                 debug_warning("invalid target state [%s].\n", MMPLAYER_STATE_GET_NAME(target_state) );
1272                         }
1273                                 break;
1274                 }
1275         }
1276         else
1277         {
1278                 /* NOTE : during the buffering, pause the player for stopping pipeline clock.
1279                  *      it's for stopping the pipeline clock to prevent dropping the data in sink element.
1280                  */
1281                 switch ( pending_state )
1282                 {
1283                         case MM_PLAYER_STATE_NONE:
1284                         {
1285                                 if (current_state != MM_PLAYER_STATE_PAUSED)
1286                                         __gst_pause ( player, TRUE );
1287                         }
1288                         break;
1289
1290                         case MM_PLAYER_STATE_PLAYING:
1291                         {
1292                                 __gst_pause ( player, TRUE );
1293                         }
1294                         break;
1295
1296                         case MM_PLAYER_STATE_PAUSED:
1297                         {
1298                                  debug_log("player is already going to paused state, there is nothing to do.\n");
1299                         }
1300                         break;
1301
1302                         case MM_PLAYER_STATE_NULL:
1303                         case MM_PLAYER_STATE_READY:
1304                         default :
1305                         {
1306                                 debug_warning("invalid pending state [%s].\n", MMPLAYER_STATE_GET_NAME(pending_state) );
1307                         }
1308                                 break;
1309                 }
1310         }
1311 }
1312
1313 static gboolean
1314 __mmplayer_gst_callback(GstBus *bus, GstMessage *msg, gpointer data) // @
1315 {
1316         mm_player_t* player = (mm_player_t*) data;
1317         gboolean ret = TRUE;
1318         static gboolean async_done = FALSE;
1319
1320         return_val_if_fail ( player, FALSE );
1321         return_val_if_fail ( msg && GST_IS_MESSAGE(msg), FALSE );
1322
1323         switch ( GST_MESSAGE_TYPE( msg ) )
1324         {
1325                 case GST_MESSAGE_UNKNOWN:
1326                         debug_warning("unknown message received\n");
1327                 break;
1328
1329                 case GST_MESSAGE_EOS:
1330                 {
1331                         MMHandleType attrs = 0;
1332                         gint count = 0;
1333
1334                         debug_log("GST_MESSAGE_EOS received\n");
1335
1336                         /* NOTE : EOS event is comming multiple time. watch out it */
1337                         /* check state. we only process EOS when pipeline state goes to PLAYING */
1338                         if ( ! (player->cmd == MMPLAYER_COMMAND_START || player->cmd == MMPLAYER_COMMAND_RESUME) )
1339                         {
1340                                 debug_warning("EOS received on non-playing state. ignoring it\n");
1341                                 break;
1342                         }
1343
1344                         if ( (player->audio_stream_cb) && (player->is_sound_extraction) )
1345                         {
1346                                 GstPad *pad = NULL;
1347         
1348                                 pad = gst_element_get_static_pad (player->pipeline->audiobin[MMPLAYER_A_SINK].gst, "sink");
1349
1350                                 debug_error("release audio callback\n");
1351                                 
1352                                 /* release audio callback */
1353                                 gst_pad_remove_buffer_probe (pad, player->audio_cb_probe_id);
1354                                 player->audio_cb_probe_id = 0;
1355                                 /* audio callback should be free because it can be called even though probe remove.*/
1356                                 player->audio_stream_cb = NULL;
1357                                 player->audio_stream_cb_user_param = NULL;
1358
1359                         }
1360
1361                         /* rewind if repeat count is greater then zero */
1362                         /* get play count */
1363                         attrs = MMPLAYER_GET_ATTRS(player);
1364
1365                         if ( attrs )
1366                         {
1367                                 gboolean smooth_repeat = FALSE;
1368
1369                                 mm_attrs_get_int_by_name(attrs, "profile_play_count", &count);
1370                                 mm_attrs_get_int_by_name(attrs, "profile_smooth_repeat", &smooth_repeat);
1371
1372                                 debug_log("remaining play count: %d, playback rate: %f\n", count, player->playback_rate);
1373
1374                                 if ( count > 1 || count == -1 || player->playback_rate < 0.0 ) /* default value is 1 */
1375                                 {
1376                                         if ( smooth_repeat )
1377                                         {
1378                                                 debug_log("smooth repeat enabled. seeking operation will be excuted in new thread\n");
1379
1380                                                 g_cond_signal( player->repeat_thread_cond );
1381
1382                                                 break;
1383                                         }
1384                                         else
1385                                         {
1386                                                 gint ret_value = 0;
1387
1388                                                 if ( player->section_repeat )
1389                                                 {
1390                                                         ret_value = _mmplayer_activate_section_repeat((MMHandleType)player, player->section_repeat_start, player->section_repeat_end);
1391                                                 }
1392                                                 else
1393                                                 {
1394
1395                                                         if ( player->playback_rate < 0.0 )
1396                                                         {
1397                                                         player->resumed_by_rewind = TRUE;
1398                                                                 _mmplayer_set_mute((MMHandleType)player, 0);
1399                                                                 MMPLAYER_POST_MSG( player, MM_MESSAGE_RESUMED_BY_REW, NULL );
1400                                                         }
1401
1402                                                         ret_value = __gst_set_position( player, MM_PLAYER_POS_FORMAT_TIME, 0, TRUE);
1403
1404                                                         /* initialize */
1405                                                         player->sent_bos = FALSE;
1406                                                 }
1407
1408                                                 if ( MM_ERROR_NONE != ret_value )
1409                                                 {
1410                                                         debug_error("failed to set position to zero for rewind\n");
1411                                                 }
1412                                                 else
1413                                                 {
1414                                                         if ( count > 1 )
1415                                                         {
1416                                                                 /* we successeded to rewind. update play count and then wait for next EOS */
1417                                                                 count--;
1418
1419                                                                 mm_attrs_set_int_by_name(attrs, "profile_play_count", count);
1420
1421                                                                 if ( mmf_attrs_commit ( attrs ) )
1422                                                                         debug_error("failed to commit attrs\n");
1423                                                         }
1424                                                 }
1425
1426                                                 break;
1427                                         }
1428                                 }
1429                         }
1430
1431                         MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-eos" );
1432
1433                         /* post eos message to application */
1434                         __mmplayer_post_delayed_eos( player, PLAYER_INI()->eos_delay );
1435
1436                         /* reset last position */
1437                         player->last_position = 0;
1438                 }
1439                 break;
1440
1441                 case GST_MESSAGE_ERROR:
1442                 {
1443                         GError *error = NULL;
1444                         gchar* debug = NULL;
1445                         gchar *msg_src_element = NULL;
1446
1447                         /* generating debug info before returning error */
1448                         MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-error" );
1449
1450                         /* get error code */
1451                         gst_message_parse_error( msg, &error, &debug );
1452
1453                         msg_src_element = GST_ELEMENT_NAME( GST_ELEMENT_CAST( msg->src ) );
1454                         if ( gst_structure_has_name ( msg->structure, "streaming_error" ) )
1455                         {
1456                                 /* Note : the streaming error from the streaming source is handled
1457                                  *   using __mmplayer_handle_streaming_error.
1458                                  */
1459                                 __mmplayer_handle_streaming_error ( player, msg );
1460
1461                                 /* dump state of all element */
1462                                 __mmplayer_dump_pipeline_state( player );
1463                         }
1464                         else
1465                         {
1466                                 /* traslate gst error code to msl error code. then post it
1467                                  * to application if needed
1468                                  */
1469                                 __mmplayer_handle_gst_error( player, msg, error );
1470
1471                                 /* dump state of all element */
1472                                 __mmplayer_dump_pipeline_state( player );
1473
1474                         }
1475
1476                         if (MMPLAYER_IS_HTTP_PD(player))
1477                         {       
1478                                 _mmplayer_unrealize_pd_downloader ((MMHandleType)player);
1479                         }
1480                         
1481                         MMPLAYER_FREEIF( debug );
1482                         g_error_free( error );
1483                 }
1484                 break;
1485
1486                 case GST_MESSAGE_WARNING:
1487                 {
1488                         char* debug = NULL;
1489                         GError* error = NULL;
1490
1491                         gst_message_parse_warning(msg, &error, &debug);
1492
1493                         debug_warning("warning : %s\n", error->message);
1494                         debug_warning("debug : %s\n", debug);
1495
1496                         MMPLAYER_POST_MSG( player, MM_MESSAGE_WARNING, NULL );
1497
1498                         MMPLAYER_FREEIF( debug );
1499                         g_error_free( error );
1500                 }
1501                 break;
1502
1503                 case GST_MESSAGE_INFO:                          debug_log("GST_MESSAGE_STATE_DIRTY\n"); break;
1504
1505                 case GST_MESSAGE_TAG:
1506                 {
1507                         debug_log("GST_MESSAGE_TAG\n");
1508                         if ( ! __mmplayer_gst_extract_tag_from_msg( player, msg ) )
1509                         {
1510                                 debug_warning("failed to extract tags from gstmessage\n");
1511                         }
1512                 }
1513                 break;
1514
1515                 case GST_MESSAGE_BUFFERING:
1516                 {
1517                         MMMessageParamType msg_param = {0, };
1518                         gboolean update_buffering_percent = TRUE;
1519
1520                         if ( !MMPLAYER_IS_STREAMING(player) || (player->profile.uri_type == MM_PLAYER_URI_TYPE_HLS) ) // pure hlsdemux case, don't consider buffering of msl currently
1521                                 break;
1522
1523                         __mm_player_streaming_buffering (player->streamer, msg);
1524
1525                         __mmplayer_handle_buffering_message ( player );
1526
1527                         update_buffering_percent = (player->pipeline_is_constructed || MMPLAYER_IS_RTSP_STREAMING(player) );
1528                         if (update_buffering_percent)
1529                         {
1530                                 msg_param.connection.buffering = player->streamer->buffering_percent;
1531                                 MMPLAYER_POST_MSG ( player, MM_MESSAGE_BUFFERING, &msg_param );
1532                         }
1533                 }
1534                 break;
1535
1536                 case GST_MESSAGE_STATE_CHANGED:
1537                 {
1538                         MMPlayerGstElement *mainbin;
1539                         const GValue *voldstate, *vnewstate, *vpending;
1540                         GstState oldstate, newstate, pending;
1541
1542                         if ( ! ( player->pipeline && player->pipeline->mainbin ) )
1543                         {
1544                                 debug_error("player pipeline handle is null");
1545
1546                                 break;
1547                         }
1548
1549                         mainbin = player->pipeline->mainbin;
1550
1551                         /* get state info from msg */
1552                         voldstate = gst_structure_get_value (msg->structure, "old-state");
1553                         vnewstate = gst_structure_get_value (msg->structure, "new-state");
1554                         vpending = gst_structure_get_value (msg->structure, "pending-state");
1555
1556                         oldstate = (GstState)voldstate->data[0].v_int;
1557                         newstate = (GstState)vnewstate->data[0].v_int;
1558                         pending = (GstState)vpending->data[0].v_int;
1559
1560                         if (oldstate == newstate)
1561                                 break;
1562
1563                         debug_log("state changed [%s] : %s ---> %s     final : %s\n",
1564                                 GST_OBJECT_NAME(GST_MESSAGE_SRC(msg)),
1565                                 gst_element_state_get_name( (GstState)oldstate ),
1566                                 gst_element_state_get_name( (GstState)newstate ),
1567                                 gst_element_state_get_name( (GstState)pending ) );
1568
1569                         /* we only handle messages from pipeline */
1570                         if( msg->src != (GstObject *)mainbin[MMPLAYER_M_PIPE].gst )
1571                                 break;
1572
1573                         switch(newstate)
1574                         {
1575                                 case GST_STATE_VOID_PENDING:
1576                                 break;
1577
1578                                 case GST_STATE_NULL:
1579                                 break;
1580
1581                                 case GST_STATE_READY:
1582                                 break;
1583
1584                                 case GST_STATE_PAUSED:
1585                                 {
1586                                         gboolean prepare_async = FALSE;
1587
1588                                         player->need_update_content_dur = TRUE;
1589
1590                                         if ( ! player->audio_cb_probe_id && player->is_sound_extraction )
1591                                                 __mmplayer_configure_audio_callback(player);
1592
1593                                         if ( ! player->sent_bos && oldstate == GST_STATE_READY) // managed prepare async case
1594                                         {
1595                                                 mm_attrs_get_int_by_name(player->attrs, "profile_prepare_async", &prepare_async);
1596                                                 debug_log("checking prepare mode for async transition - %d", prepare_async);
1597                                         }
1598
1599                                         if ( MMPLAYER_IS_STREAMING(player) || prepare_async )
1600                                         {
1601                                                 MMPLAYER_SET_STATE ( player, MM_PLAYER_STATE_PAUSED );
1602
1603                                                 if (player->streamer)
1604                                                         __mm_player_streaming_set_content_bitrate(player->streamer, player->total_maximum_bitrate, player->total_bitrate);
1605                                         }
1606                                 }                                       
1607                                 break;
1608
1609                                 case GST_STATE_PLAYING:
1610                                 {
1611                                         if (player->doing_seek && async_done)
1612                                         {
1613                                                 player->doing_seek = FALSE;
1614                                                 async_done = FALSE;
1615                                                 MMPLAYER_POST_MSG ( player, MM_MESSAGE_SEEK_COMPLETED, NULL );
1616                                         }
1617
1618                                         if ( MMPLAYER_IS_STREAMING(player) ) // managed prepare async case when buffering is completed
1619                                         {
1620                                                 // pending state should be reset oyherwise, it's still playing even though it's resumed after bufferging.
1621                                                 MMPLAYER_SET_STATE ( player, MM_PLAYER_STATE_PLAYING);
1622                                         }
1623                                 }
1624                                 break;
1625
1626                                 default:
1627                                 break;
1628                         }
1629                 }
1630                 break;
1631
1632                 case GST_MESSAGE_STATE_DIRTY:           debug_log("GST_MESSAGE_STATE_DIRTY\n"); break;
1633                 case GST_MESSAGE_STEP_DONE:                     debug_log("GST_MESSAGE_STEP_DONE\n"); break;
1634                 case GST_MESSAGE_CLOCK_PROVIDE:         debug_log("GST_MESSAGE_CLOCK_PROVIDE\n"); break;
1635                 
1636                 case GST_MESSAGE_CLOCK_LOST:
1637                         {
1638                                 GstClock *clock = NULL;
1639                                 gst_message_parse_clock_lost (msg, &clock);
1640                                 debug_log("GST_MESSAGE_CLOCK_LOST : %s\n", (clock ? GST_OBJECT_NAME (clock) : "NULL"));
1641                                 g_print ("GST_MESSAGE_CLOCK_LOST : %s\n", (clock ? GST_OBJECT_NAME (clock) : "NULL"));
1642
1643                                 if (PLAYER_INI()->provide_clock)
1644                                 {
1645                                         debug_log ("Provide clock is TRUE, do pause->resume\n");
1646                                         __gst_pause(player, FALSE);
1647                                         __gst_resume(player, FALSE);
1648                                 }
1649                         }
1650                         break;
1651                         
1652                 case GST_MESSAGE_NEW_CLOCK:
1653                         {
1654                                 GstClock *clock = NULL;
1655                                 gst_message_parse_new_clock (msg, &clock);
1656                                 debug_log("GST_MESSAGE_NEW_CLOCK : %s\n", (clock ? GST_OBJECT_NAME (clock) : "NULL"));
1657                         }
1658                         break;
1659
1660                 case GST_MESSAGE_STRUCTURE_CHANGE:      debug_log("GST_MESSAGE_STRUCTURE_CHANGE\n"); break;
1661                 case GST_MESSAGE_STREAM_STATUS:         debug_log("GST_MESSAGE_STREAM_STATUS\n"); break;
1662                 case GST_MESSAGE_APPLICATION:           debug_log("GST_MESSAGE_APPLICATION\n"); break;
1663
1664                 case GST_MESSAGE_ELEMENT:
1665                 {
1666                         debug_log("GST_MESSAGE_ELEMENT\n");
1667                 }
1668                 break;
1669                 
1670                 case GST_MESSAGE_SEGMENT_START:         debug_log("GST_MESSAGE_SEGMENT_START\n"); break;
1671                 case GST_MESSAGE_SEGMENT_DONE:          debug_log("GST_MESSAGE_SEGMENT_DONE\n"); break;
1672                 
1673                 case GST_MESSAGE_DURATION:
1674                 {
1675                         debug_log("GST_MESSAGE_DURATION\n");
1676
1677                         if (MMPLAYER_IS_STREAMING(player))
1678                         {
1679                                 GstFormat format;
1680                                 gint64 bytes = 0;
1681
1682                                 gst_message_parse_duration (msg, &format, &bytes);
1683                                 if (format == GST_FORMAT_BYTES)
1684                                 {
1685                                         debug_log("data total size of http content: %lld", bytes);
1686                                         player->http_content_size = bytes;
1687                                 }
1688                         }
1689
1690                         player->need_update_content_attrs = TRUE;
1691                         player->need_update_content_dur = TRUE;
1692                         _mmplayer_update_content_attrs(player);
1693                 }
1694                 break;
1695
1696                 case GST_MESSAGE_LATENCY:                               debug_log("GST_MESSAGE_LATENCY\n"); break;
1697                 case GST_MESSAGE_ASYNC_START:           debug_log("GST_MESSAGE_ASYNC_DONE : %s\n", gst_element_get_name(GST_MESSAGE_SRC(msg))); break;
1698                 
1699                 case GST_MESSAGE_ASYNC_DONE:    
1700                 {
1701                         debug_log("GST_MESSAGE_ASYNC_DONE : %s\n", gst_element_get_name(GST_MESSAGE_SRC(msg)));
1702
1703                         if (player->doing_seek)
1704                         {
1705                                 if (MMPLAYER_TARGET_STATE(player) == MM_PLAYER_STATE_PAUSED)
1706                                 {
1707                                         player->doing_seek = FALSE;
1708                                         MMPLAYER_POST_MSG ( player, MM_MESSAGE_SEEK_COMPLETED, NULL );
1709                                 }
1710                                 else if (MMPLAYER_TARGET_STATE(player) == MM_PLAYER_STATE_PLAYING)
1711                                 {
1712                                         async_done = TRUE;
1713                                 }
1714                         }
1715                 }
1716                 break;
1717                 
1718                 case GST_MESSAGE_REQUEST_STATE:         debug_log("GST_MESSAGE_REQUEST_STATE\n"); break;
1719                 case GST_MESSAGE_STEP_START:            debug_log("GST_MESSAGE_STEP_START\n"); break;
1720                 case GST_MESSAGE_QOS:                                   debug_log("GST_MESSAGE_QOS\n"); break;
1721                 case GST_MESSAGE_PROGRESS:                      debug_log("GST_MESSAGE_PROGRESS\n"); break;
1722                 case GST_MESSAGE_ANY:                           debug_log("GST_MESSAGE_ANY\n"); break;
1723
1724                 default:
1725                         debug_warning("unhandled message\n");
1726                 break;
1727         }
1728
1729         /* FIXIT : this cause so many warnings/errors from glib/gstreamer. we should not call it since
1730          * gst_element_post_message api takes ownership of the message.
1731          */
1732         //gst_message_unref( msg );
1733
1734         return ret;
1735 }
1736
1737 static gboolean
1738 __mmplayer_gst_extract_tag_from_msg(mm_player_t* player, GstMessage* msg) // @
1739 {
1740
1741 /* macro for better code readability */
1742 #define MMPLAYER_UPDATE_TAG_STRING(gsttag, attribute, playertag) \
1743 if (gst_tag_list_get_string(tag_list, gsttag, &string)) \
1744 {\
1745         if (string != NULL)\
1746         {\
1747                 debug_log ( "update tag string : %s\n", string); \
1748                 mm_attrs_set_string_by_name(attribute, playertag, string); \
1749                 g_free(string);\
1750                 string = NULL;\
1751         }\
1752 }
1753
1754 #define MMPLAYER_UPDATE_TAG_IMAGE(gsttag, attribute, playertag) \
1755 value = gst_tag_list_get_value_index(tag_list, gsttag, index); \
1756 if (value) \
1757 {\
1758         buffer = gst_value_get_buffer (value); \
1759         debug_log ( "update album cover data : %p, size : %d\n", GST_BUFFER_DATA(buffer), GST_BUFFER_SIZE(buffer)); \
1760         player->album_art = (gchar *)g_malloc(GST_BUFFER_SIZE(buffer)); \
1761         if (player->album_art); \
1762         { \
1763                 memcpy(player->album_art, GST_BUFFER_DATA(buffer), GST_BUFFER_SIZE(buffer)); \
1764                 mm_attrs_set_data_by_name(attribute, playertag, (void *)player->album_art, GST_BUFFER_SIZE(buffer)); \
1765         } \
1766 }
1767
1768 #define MMPLAYER_UPDATE_TAG_UINT(gsttag, attribute, playertag) \
1769 if (gst_tag_list_get_uint(tag_list, gsttag, &v_uint))\
1770 {\
1771         if(v_uint)\
1772         {\
1773                 if(gsttag==GST_TAG_BITRATE)\
1774                 {\
1775                         if (player->updated_bitrate_count == 0) \
1776                                 mm_attrs_set_int_by_name(attribute, "content_audio_bitrate", v_uint); \
1777                         if (player->updated_bitrate_count<MM_PLAYER_STREAM_COUNT_MAX) \
1778                         {\
1779                                 player->bitrate[player->updated_bitrate_count] = v_uint;\
1780                                 player->total_bitrate += player->bitrate[player->updated_maximum_bitrate_count]; \
1781                                 player->updated_bitrate_count++; \
1782                                 mm_attrs_set_int_by_name(attribute, playertag, player->total_bitrate);\
1783                                 debug_log ( "update bitrate %d[bps] of stream #%d.\n", v_uint, player->updated_bitrate_count);\
1784                         }\
1785                 }\
1786                 else if (gsttag==GST_TAG_MAXIMUM_BITRATE)\
1787                 {\
1788                         if (player->updated_maximum_bitrate_count<MM_PLAYER_STREAM_COUNT_MAX) \
1789                         {\
1790                                 player->maximum_bitrate[player->updated_maximum_bitrate_count] = v_uint;\
1791                                 player->total_maximum_bitrate += player->maximum_bitrate[player->updated_maximum_bitrate_count]; \
1792                                 player->updated_maximum_bitrate_count++; \
1793                                 mm_attrs_set_int_by_name(attribute, playertag, player->total_maximum_bitrate); \
1794                                 debug_log ( "update maximum bitrate %d[bps] of stream #%d\n", v_uint, player->updated_maximum_bitrate_count);\
1795                         }\
1796                 }\
1797                 else\
1798                 {\
1799                         mm_attrs_set_int_by_name(attribute, playertag, v_uint); \
1800                 }\
1801                 v_uint = 0;\
1802         }\
1803 }
1804
1805 #define MMPLAYER_UPDATE_TAG_DATE(gsttag, attribute, playertag) \
1806 if (gst_tag_list_get_date(tag_list, gsttag, &date))\
1807 {\
1808         if (date != NULL)\
1809         {\
1810                 string = g_strdup_printf("%d", g_date_get_year(date));\
1811                 mm_attrs_set_string_by_name(attribute, playertag, string);\
1812                 debug_log ( "metainfo year : %s\n", string);\
1813                 MMPLAYER_FREEIF(string);\
1814                 g_date_free(date);\
1815         }\
1816 }
1817
1818 #define MMPLAYER_UPDATE_TAG_UINT64(gsttag, attribute, playertag) \
1819 if(gst_tag_list_get_uint64(tag_list, gsttag, &v_uint64))\
1820 {\
1821         if(v_uint64)\
1822         {\
1823                 /* FIXIT : don't know how to store date */\
1824                 g_assert(1);\
1825                 v_uint64 = 0;\
1826         }\
1827 }
1828
1829 #define MMPLAYER_UPDATE_TAG_DOUBLE(gsttag, attribute, playertag) \
1830 if(gst_tag_list_get_double(tag_list, gsttag, &v_double))\
1831 {\
1832         if(v_double)\
1833         {\
1834                 /* FIXIT : don't know how to store date */\
1835                 g_assert(1);\
1836                 v_double = 0;\
1837         }\
1838 }
1839
1840         /* function start */
1841         GstTagList* tag_list = NULL;
1842
1843         MMHandleType attrs = 0;
1844
1845         char *string = NULL;
1846         guint v_uint = 0;
1847         GDate *date = NULL;
1848         /* album cover */
1849         GstBuffer *buffer = NULL;
1850         gint index = 0;
1851         const GValue *value;
1852
1853         /* currently not used. but those are needed for above macro */
1854         //guint64 v_uint64 = 0;
1855         //gdouble v_double = 0;
1856
1857         return_val_if_fail( player && msg, FALSE );
1858
1859         attrs = MMPLAYER_GET_ATTRS(player);
1860
1861         return_val_if_fail( attrs, FALSE );
1862
1863         /* get tag list from gst message */
1864         gst_message_parse_tag(msg, &tag_list);
1865
1866         /* store tags to player attributes */
1867         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_TITLE, attrs, "tag_title");
1868         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_TITLE_SORTNAME, ?, ?); */
1869         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ARTIST, attrs, "tag_artist");
1870         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ARTIST_SORTNAME, ?, ?); */
1871         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ALBUM, attrs, "tag_album");
1872         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ALBUM_SORTNAME, ?, ?); */
1873         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_COMPOSER, attrs, "tag_author");
1874         MMPLAYER_UPDATE_TAG_DATE(GST_TAG_DATE, attrs, "tag_date");
1875         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_GENRE, attrs, "tag_genre");
1876         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_COMMENT, ?, ?); */
1877         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_EXTENDED_COMMENT, ?, ?); */
1878         MMPLAYER_UPDATE_TAG_UINT(GST_TAG_TRACK_NUMBER, attrs, "tag_track_num");
1879         /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_TRACK_COUNT, ?, ?); */
1880         /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_ALBUM_VOLUME_NUMBER, ?, ?); */
1881         /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_ALBUM_VOLUME_COUNT, ?, ?); */
1882         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_LOCATION, ?, ?); */
1883         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_DESCRIPTION, attrs, "tag_description");
1884         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_VERSION, ?, ?); */
1885         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ISRC, ?, ?); */
1886         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ORGANIZATION, ?, ?); */
1887         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_COPYRIGHT, attrs, "tag_copyright");
1888         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_COPYRIGHT_URI, ?, ?); */
1889         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_CONTACT, ?, ?); */
1890         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_LICENSE, ?, ?); */
1891         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_LICENSE_URI, ?, ?); */
1892         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_PERFORMER, ?, ?); */
1893         /* MMPLAYER_UPDATE_TAG_UINT64(GST_TAG_DURATION, ?, ?); */
1894         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_CODEC, ?, ?); */
1895         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_VIDEO_CODEC, attrs, "content_video_codec");
1896         MMPLAYER_UPDATE_TAG_STRING(GST_TAG_AUDIO_CODEC, attrs, "content_audio_codec");
1897         MMPLAYER_UPDATE_TAG_UINT(GST_TAG_BITRATE, attrs, "content_bitrate");
1898         MMPLAYER_UPDATE_TAG_UINT(GST_TAG_MAXIMUM_BITRATE, attrs, "content_max_bitrate");
1899         MMPLAYER_UPDATE_TAG_IMAGE(GST_TAG_IMAGE, attrs, "tag_album_cover");
1900         /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_NOMINAL_BITRATE, ?, ?); */
1901         /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_MINIMUM_BITRATE, ?, ?); */
1902         /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_SERIAL, ?, ?); */
1903         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_ENCODER, ?, ?); */
1904         /* MMPLAYER_UPDATE_TAG_UINT(GST_TAG_ENCODER_VERSION, ?, ?); */
1905         /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_TRACK_GAIN, ?, ?); */
1906         /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_TRACK_PEAK, ?, ?); */
1907         /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_ALBUM_GAIN, ?, ?); */
1908         /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_ALBUM_PEAK, ?, ?); */
1909         /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_REFERENCE_LEVEL, ?, ?); */
1910         /* MMPLAYER_UPDATE_TAG_STRING(GST_TAG_LANGUAGE_CODE, ?, ?); */
1911         /* MMPLAYER_UPDATE_TAG_DOUBLE(GST_TAG_BEATS_PER_MINUTE, ?, ?); */
1912
1913         if ( mmf_attrs_commit ( attrs ) )
1914                 debug_error("failed to commit.\n");
1915
1916         gst_tag_list_free(tag_list);
1917
1918         return TRUE;
1919 }
1920
1921 static void
1922 __mmplayer_gst_rtp_no_more_pads (GstElement *element,  gpointer data)  // @
1923 {
1924         mm_player_t* player = (mm_player_t*) data;
1925
1926         debug_fenter();
1927
1928         /* NOTE : we can remove fakesink here if there's no rtp_dynamic_pad. because whenever
1929           * we connect autoplugging element to the pad which is just added to rtspsrc, we increase
1930           * num_dynamic_pad. and this is no-more-pad situation which means mo more pad will be added.
1931           * So we can say this. if num_dynamic_pad is zero, it must be one of followings
1932
1933           * [1] audio and video will be dumped with filesink.
1934           * [2] autoplugging is done by just using pad caps.
1935           * [3] typefinding has happend in audio but audiosink is created already before no-more-pad signal
1936           * and the video will be dumped via filesink.
1937           */
1938         if ( player->num_dynamic_pad == 0 )
1939         {
1940                 debug_log("it seems pad caps is directely used for autoplugging. removing fakesink now\n");
1941
1942                 if ( ! __mmplayer_gst_remove_fakesink( player,
1943                         &player->pipeline->mainbin[MMPLAYER_M_SRC_FAKESINK]) );
1944         }
1945
1946         /* create dot before error-return. for debugging */
1947         MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-no-more-pad" );
1948
1949         /* NOTE : if rtspsrc goes to PLAYING before adding it's src pads, a/v sink elements will
1950          * not goes to PLAYING. they will just remain in PAUSED state. simply we are giving
1951          * PLAYING state again.
1952          */
1953         __mmplayer_gst_set_state(player,
1954                 player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_PLAYING, TRUE, 5000 );
1955
1956         player->no_more_pad = TRUE;
1957
1958         debug_fleave();
1959 }
1960
1961 static gboolean
1962 __mmplayer_gst_remove_fakesink(mm_player_t* player, MMPlayerGstElement* fakesink) // @
1963 {
1964         GstElement* parent = NULL;
1965
1966         return_val_if_fail(player && player->pipeline && fakesink, FALSE);
1967
1968         /* lock */
1969         g_mutex_lock( player->fsink_lock );
1970
1971         if ( ! fakesink->gst )
1972         {
1973                 goto ERROR;
1974         }
1975
1976         /* get parent of fakesink */
1977         parent = (GstElement*)gst_object_get_parent( (GstObject*)fakesink->gst );
1978         if ( ! parent )
1979         {
1980                 debug_log("fakesink already removed\n");
1981                 goto ERROR;
1982         }
1983
1984         gst_element_set_locked_state( fakesink->gst, TRUE );
1985
1986         /* setting the state to NULL never returns async
1987          * so no need to wait for completion of state transiton
1988          */
1989         if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state (fakesink->gst, GST_STATE_NULL) )
1990         {
1991                 debug_error("fakesink state change failure!\n");
1992
1993                 /* FIXIT : should I return here? or try to proceed to next? */
1994                 /* return FALSE; */
1995         }
1996
1997         /* remove fakesink from it's parent */
1998         if ( ! gst_bin_remove( GST_BIN( parent ), fakesink->gst ) )
1999         {
2000                 debug_error("failed to remove fakesink\n");
2001
2002                 gst_object_unref( parent );
2003
2004                 goto ERROR;
2005         }
2006
2007         gst_object_unref( parent );
2008
2009         /* FIXIT : releasing fakesink takes too much time (around 700ms)
2010          * we need to figure out the reason why. just for now, fakesink will be released
2011          * in __mmplayer_gst_destroy_pipeline()
2012          */
2013         //      gst_object_unref ( fakesink->gst );
2014         //      fakesink->gst = NULL;
2015
2016         debug_log("state-holder removed\n");
2017
2018         gst_element_set_locked_state( fakesink->gst, FALSE );
2019
2020         g_mutex_unlock( player->fsink_lock );
2021         return TRUE;
2022
2023 ERROR:
2024         if ( fakesink->gst )
2025         {
2026                 gst_element_set_locked_state( fakesink->gst, FALSE );
2027         }
2028
2029         g_mutex_unlock( player->fsink_lock );
2030         return FALSE;
2031 }
2032
2033
2034 static void
2035 __mmplayer_gst_rtp_dynamic_pad (GstElement *element, GstPad *pad, gpointer data) // @
2036 {
2037         GstPad *sinkpad = NULL;
2038         GstCaps* caps = NULL;
2039         GstElement* new_element = NULL;
2040
2041         mm_player_t* player = (mm_player_t*) data;
2042
2043         debug_fenter();
2044
2045         return_if_fail( element && pad );
2046         return_if_fail( player &&
2047                                         player->pipeline &&
2048                                         player->pipeline->mainbin );
2049
2050
2051         /* payload type is recognizable. increase num_dynamic and wait for sinkbin creation.
2052          * num_dynamic_pad will decreased after creating a sinkbin.
2053          */
2054         player->num_dynamic_pad++;
2055         debug_log("stream count inc : %d\n", player->num_dynamic_pad);
2056
2057         /* perform autoplugging if dump is disabled */
2058         if ( PLAYER_INI()->rtsp_do_typefinding )
2059         {
2060                 /* create typefind */
2061                 new_element = gst_element_factory_make( "typefind", NULL );
2062                 if ( ! new_element )
2063                 {
2064                         debug_error("failed to create typefind\n");
2065                         goto ERROR;
2066                 }
2067
2068                 MMPLAYER_SIGNAL_CONNECT(        player,
2069                                                                         G_OBJECT(new_element),
2070                                                                         "have-type",
2071                                                                         G_CALLBACK(__mmplayer_typefind_have_type),
2072                                                                         (gpointer)player);
2073
2074                 /* FIXIT : try to remove it */
2075                 player->have_dynamic_pad = FALSE;
2076         }
2077         else  /* NOTE : use pad's caps directely. if enabled. what I am assuming is there's no elemnt has dynamic pad */
2078         {
2079                 debug_log("using pad caps to autopluging instead of doing typefind\n");
2080
2081                 caps = gst_pad_get_caps( pad );
2082
2083                 MMPLAYER_CHECK_NULL( caps );
2084
2085                 /* clear  previous result*/
2086                 player->have_dynamic_pad = FALSE;
2087
2088                 if ( ! __mmplayer_try_to_plug( player, pad, caps ) )
2089                 {
2090                         debug_error("failed to autoplug for caps : %s\n", gst_caps_to_string( caps ) );
2091                         goto ERROR;
2092                 }
2093
2094                 /* check if there's dynamic pad*/
2095                 if( player->have_dynamic_pad )
2096                 {
2097                         debug_error("using pad caps assums there's no dynamic pad !\n");
2098                         debug_error("try with enalbing rtsp_do_typefinding\n");
2099                         goto ERROR;
2100                 }
2101
2102                 gst_caps_unref( caps );
2103                 caps = NULL;
2104         }
2105
2106         /* excute new_element if created*/
2107         if ( new_element )
2108         {
2109                 debug_log("adding new element to pipeline\n");
2110
2111                 /* set state to READY before add to bin */
2112                 MMPLAYER_ELEMENT_SET_STATE( new_element, GST_STATE_READY );
2113
2114                 /* add new element to the pipeline */
2115                 if ( FALSE == gst_bin_add( GST_BIN(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst), new_element)  )
2116                 {
2117                         debug_error("failed to add autoplug element to bin\n");
2118                         goto ERROR;
2119                 }
2120
2121                 /* get pad from element */
2122                 sinkpad = gst_element_get_static_pad ( GST_ELEMENT(new_element), "sink" );
2123                 if ( !sinkpad )
2124                 {
2125                         debug_error("failed to get sinkpad from autoplug element\n");
2126                         goto ERROR;
2127                 }
2128
2129                 /* link it */
2130                 if ( GST_PAD_LINK_OK != GST_PAD_LINK(pad, sinkpad) )
2131                 {
2132                         debug_error("failed to link autoplug element\n");
2133                         goto ERROR;
2134                 }
2135
2136                 gst_object_unref (sinkpad);
2137                 sinkpad = NULL;
2138
2139                 /* run. setting PLAYING here since streamming source is live source */
2140                 MMPLAYER_ELEMENT_SET_STATE( new_element, GST_STATE_PLAYING );
2141         }
2142
2143         debug_fleave();
2144
2145         return;
2146
2147 STATE_CHANGE_FAILED:
2148 ERROR:
2149         /* FIXIT : take care if new_element has already added to pipeline */
2150         if ( new_element )
2151                 gst_object_unref(GST_OBJECT(new_element));
2152
2153         if ( sinkpad )
2154                 gst_object_unref(GST_OBJECT(sinkpad));
2155
2156         if ( caps )
2157                 gst_object_unref(GST_OBJECT(caps));
2158
2159         /* FIXIT : how to inform this error to MSL ????? */
2160         /* FIXIT : I think we'd better to use g_idle_add() to destroy pipeline and
2161          * then post an error to application
2162          */
2163 }
2164
2165
2166 static void
2167 __mmplayer_gst_decode_callback(GstElement *decodebin, GstPad *pad, gboolean last, gpointer data) // @
2168 {
2169         mm_player_t* player = NULL;
2170         MMHandleType attrs = 0;
2171         GstElement* pipeline = NULL;
2172         GstCaps* caps = NULL;
2173         GstStructure* str = NULL;
2174         const gchar* name = NULL;
2175         GstPad* sinkpad = NULL;
2176         GstElement* sinkbin = NULL;
2177
2178         /* check handles */
2179         player = (mm_player_t*) data;
2180
2181         return_if_fail( decodebin && pad );
2182         return_if_fail(player && player->pipeline && player->pipeline->mainbin);
2183
2184         pipeline = player->pipeline->mainbin[MMPLAYER_M_PIPE].gst;
2185
2186         attrs = MMPLAYER_GET_ATTRS(player);
2187         if ( !attrs )
2188         {
2189                 debug_error("cannot get content attribute\n");
2190                 goto ERROR;
2191         }
2192
2193         /* get mimetype from caps */
2194         caps = gst_pad_get_caps( pad );
2195         if ( !caps )
2196         {
2197                 debug_error("cannot get caps from pad.\n");
2198                 goto ERROR;
2199         }
2200
2201         str = gst_caps_get_structure( caps, 0 );
2202         if ( ! str )
2203         {
2204                 debug_error("cannot get structure from capse.\n");
2205                 goto ERROR;
2206         }
2207
2208         name = gst_structure_get_name(str);
2209         if ( ! name )
2210         {
2211                 debug_error("cannot get mimetype from structure.\n");
2212                 goto ERROR;
2213         }
2214
2215         debug_log("detected mimetype : %s\n", name);
2216
2217         if (strstr(name, "audio"))
2218         {
2219                 if (player->pipeline->audiobin == NULL)
2220                 {
2221                         __ta__("__mmplayer_gst_create_audio_pipeline",
2222                                 if (MM_ERROR_NONE !=  __mmplayer_gst_create_audio_pipeline(player))
2223                                 {
2224                                         debug_error("failed to create audiobin. continuing without audio\n");
2225                                         goto ERROR;
2226                                 }
2227                         )
2228
2229                         sinkbin = player->pipeline->audiobin[MMPLAYER_A_BIN].gst;
2230                         debug_log("creating audiosink bin success\n");
2231                 }
2232                 else
2233                 {
2234                         sinkbin = player->pipeline->audiobin[MMPLAYER_A_BIN].gst;
2235                         debug_log("re-using audiobin\n");
2236                 }
2237
2238                 /* FIXIT : track number shouldn't be hardcoded */
2239                 mm_attrs_set_int_by_name(attrs, "content_audio_track_num", 1);
2240
2241                 player->audiosink_linked  = 1;
2242                 debug_msg("player->audsink_linked set to 1\n");
2243
2244         }
2245         else if (strstr(name, "video"))
2246         {
2247                 if (player->pipeline->videobin == NULL)
2248                 {
2249                         /*      NOTE : not make videobin because application dose not want to play it even though file has video stream.
2250                         */
2251
2252                         /* get video surface type */
2253                         int surface_type = 0;
2254                         mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &surface_type);
2255                         debug_log("check display surface type attribute: %d", surface_type);
2256                         if (surface_type == MM_DISPLAY_SURFACE_NULL)
2257                         {
2258                                 debug_log("not make videobin because it dose not want\n");
2259                                 goto ERROR;
2260                         }
2261
2262                         __ta__("__mmplayer_gst_create_video_pipeline",
2263                         if (MM_ERROR_NONE !=  __mmplayer_gst_create_video_pipeline(player, caps, surface_type) )
2264                         {
2265                                 debug_error("failed to create videobin. continuing without video\n");
2266                                 goto ERROR;
2267                         }
2268                         )
2269
2270                         sinkbin = player->pipeline->videobin[MMPLAYER_V_BIN].gst;
2271                         debug_log("creating videosink bin success\n");
2272                 }
2273                 else
2274                 {
2275                         sinkbin = player->pipeline->videobin[MMPLAYER_V_BIN].gst;
2276                         debug_log("re-using videobin\n");
2277                 }
2278
2279                 /* FIXIT : track number shouldn't be hardcoded */
2280                 mm_attrs_set_int_by_name(attrs, "content_video_track_num", 1);
2281
2282                 player->videosink_linked  = 1;
2283                 debug_msg("player->videosink_linked set to 1\n");
2284
2285         }
2286         else if (strstr(name, "text"))
2287         {
2288                 if (player->pipeline->textbin == NULL)
2289                 {
2290                         __ta__("__mmplayer_gst_create_text_pipeline",
2291                                 if (MM_ERROR_NONE !=  __mmplayer_gst_create_text_pipeline(player))
2292                                 {
2293                                         debug_error("failed to create textbin. continuing without text\n");
2294                                         goto ERROR;
2295                                 }
2296                         )
2297
2298                         sinkbin = player->pipeline->textbin[MMPLAYER_T_BIN].gst;
2299                         debug_log("creating textink bin success\n");
2300                 }
2301                 else
2302                 {
2303                         sinkbin = player->pipeline->textbin[MMPLAYER_T_BIN].gst;
2304                         debug_log("re-using textbin\n");
2305                 }
2306
2307                 /* FIXIT : track number shouldn't be hardcoded */
2308                 mm_attrs_set_int_by_name(attrs, "content_text_track_num", 1);
2309
2310                 player->textsink_linked  = 1;
2311                 debug_msg("player->textsink_linked set to 1\n");
2312         }
2313         else
2314         {
2315                 debug_warning("unknown type of elementary stream! ignoring it...\n");
2316                 goto ERROR;
2317         }
2318
2319         if ( sinkbin )
2320         {
2321                 /* warm up */
2322                 if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state( sinkbin, GST_STATE_READY ) )
2323                 {
2324                         debug_error("failed to set state(READY) to sinkbin\n");
2325                         goto ERROR;
2326                 }
2327
2328                 /* add */
2329                 if ( FALSE == gst_bin_add( GST_BIN(pipeline), sinkbin ) )
2330                 {
2331                         debug_error("failed to add sinkbin to pipeline\n");
2332                         goto ERROR;
2333                 }
2334
2335                 sinkpad = gst_element_get_static_pad( GST_ELEMENT(sinkbin), "sink" );
2336
2337                 if ( !sinkpad )
2338                 {
2339                         debug_error("failed to get pad from sinkbin\n");
2340                         goto ERROR;
2341                 }
2342
2343                 /* link */
2344                 if ( GST_PAD_LINK_OK != GST_PAD_LINK(pad, sinkpad) )
2345                 {
2346                         debug_error("failed to get pad from sinkbin\n");
2347                         goto ERROR;
2348                 }
2349
2350                 /* run */
2351                 if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state( sinkbin, GST_STATE_PAUSED ) )
2352                 {
2353                         debug_error("failed to set state(PLAYING) to sinkbin\n");
2354                         goto ERROR;
2355                 }
2356
2357                 gst_object_unref( sinkpad );
2358                 sinkpad = NULL;
2359         }
2360
2361         /* update track number attributes */
2362         if ( mmf_attrs_commit ( attrs ) )
2363                 debug_error("failed to commit attrs\n");
2364
2365         debug_log("linking sink bin success\n");
2366
2367
2368         /* FIXIT : we cannot hold callback for 'no-more-pad' signal because signal was emitted in
2369          * streaming task. if the task blocked, then buffer will not flow to the next element
2370          * ( autoplugging element ). so this is special hack for streaming. please try to remove it
2371          */
2372         /* dec stream count. we can remove fakesink if it's zero */
2373         player->num_dynamic_pad--;
2374
2375         debug_log("stream count dec : %d (num of dynamic pad)\n", player->num_dynamic_pad);
2376
2377         if ( ( player->no_more_pad ) && ( player->num_dynamic_pad == 0 ) )
2378         {
2379                 __mmplayer_pipeline_complete( NULL, player );
2380         }
2381
2382 ERROR:
2383         if ( caps )
2384                 gst_caps_unref( caps );
2385
2386         if ( sinkpad )
2387                 gst_object_unref(GST_OBJECT(sinkpad));
2388
2389         return;
2390 }
2391
2392 int
2393 _mmplayer_update_video_param(mm_player_t* player) // @
2394 {
2395         MMHandleType attrs = 0;
2396         int surface_type = 0;
2397
2398         debug_fenter();
2399
2400         /* check video sinkbin is created */
2401         return_val_if_fail ( player && 
2402                 player->pipeline &&
2403                 player->pipeline->videobin &&
2404                 player->pipeline->videobin[MMPLAYER_V_BIN].gst &&
2405                 player->pipeline->videobin[MMPLAYER_V_SINK].gst, 
2406                 MM_ERROR_PLAYER_NOT_INITIALIZED );
2407
2408         attrs = MMPLAYER_GET_ATTRS(player);
2409         if ( !attrs )
2410         {
2411                 debug_error("cannot get content attribute");
2412                 return MM_ERROR_PLAYER_INTERNAL;
2413         }
2414
2415         /* update display surface */
2416         mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &surface_type);
2417         debug_log("check display surface type attribute: %d", surface_type);
2418
2419         /* check video stream callback is used */
2420         if( player->use_video_stream )
2421         {
2422                 int rotate, width, height, orientation;
2423
2424                 rotate = width = height = orientation = 0;
2425
2426                 debug_log("using video stream callback with memsink. player handle : [%p]", player);
2427
2428                 mm_attrs_get_int_by_name(attrs, "display_width", &width);
2429                 mm_attrs_get_int_by_name(attrs, "display_height", &height);
2430                 mm_attrs_get_int_by_name(attrs, "display_rotation", &rotate);
2431                 mm_attrs_get_int_by_name(attrs, "display_orientation", &orientation);
2432
2433                 if (rotate < MM_DISPLAY_ROTATION_NONE || rotate > MM_DISPLAY_ROTATION_270)
2434                         rotate = 0;
2435                 else
2436                         rotate *= 90;
2437
2438                 if(orientation == 1)        rotate = 90;
2439                 else if(orientation == 2)   rotate = 180;
2440                 else if(orientation == 3)   rotate = 270;
2441
2442                 if (width)
2443                         g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "width", width, NULL);
2444
2445                 if (height)
2446                         g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "height", height, NULL);
2447
2448                 g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst, "rotate", rotate,NULL);
2449                 
2450                 return MM_ERROR_NONE;
2451         }
2452
2453         /* configuring display */
2454         switch ( surface_type )
2455         {
2456                 case MM_DISPLAY_SURFACE_X:
2457                 {
2458                 /* ximagesink or xvimagesink */
2459                         void *xid = NULL;
2460                         int zoom = 0;
2461                         int degree = 0;
2462                         int display_method = 0;
2463                         int roi_x = 0;
2464                         int roi_y = 0;
2465                         int roi_w = 0;
2466                         int roi_h = 0;
2467                         int force_aspect_ratio = 0;
2468
2469                         gboolean visible = TRUE;
2470
2471                         /* common case if using x surface */
2472                         mm_attrs_get_data_by_name(attrs, "display_overlay", &xid);
2473                         if ( xid )
2474                         {
2475                                 debug_log("set video param : xid %d", *(int*)xid);
2476                                 gst_x_overlay_set_xwindow_id( GST_X_OVERLAY( player->pipeline->videobin[MMPLAYER_V_SINK].gst ), *(int*)xid );
2477                         }
2478                         else
2479                         {
2480                                 /* FIXIT : is it error case? */
2481                                 debug_warning("still we don't have xid on player attribute. create it's own surface.");
2482                         }
2483
2484                         /* if xvimagesink */
2485                         if (!strcmp(PLAYER_INI()->videosink_element_x,"xvimagesink"))
2486                         {
2487                                 mm_attrs_get_int_by_name(attrs, "display_force_aspect_ration", &force_aspect_ratio);
2488                                 mm_attrs_get_int_by_name(attrs, "display_zoom", &zoom);
2489                                 mm_attrs_get_int_by_name(attrs, "display_rotation", &degree);
2490                                 mm_attrs_get_int_by_name(attrs, "display_method", &display_method);
2491                                 mm_attrs_get_int_by_name(attrs, "display_roi_x", &roi_x);
2492                                 mm_attrs_get_int_by_name(attrs, "display_roi_y", &roi_y);
2493                                 mm_attrs_get_int_by_name(attrs, "display_roi_width", &roi_w);
2494                                 mm_attrs_get_int_by_name(attrs, "display_roi_height", &roi_h);
2495                                 mm_attrs_get_int_by_name(attrs, "display_visible", &visible);
2496
2497                                 g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
2498                                         "force-aspect-ratio", force_aspect_ratio,
2499                                         "zoom", zoom,
2500                                         "rotate", degree,
2501                                         "handle-events", TRUE,
2502                                         "display-geometry-method", display_method,
2503                                         "draw-borders", FALSE,
2504                                         "dst-roi-x", roi_x,
2505                                         "dst-roi-y", roi_y,
2506                                         "dst-roi-w", roi_w,
2507                                         "dst-roi-h", roi_h,
2508                                         "visible", visible,
2509                                         NULL );
2510
2511                                 debug_log("set video param : zoom %d", zoom);
2512                                 debug_log("set video param : rotate %d", degree);
2513                                 debug_log("set video param : method %d", display_method);
2514                                 debug_log("set video param : dst-roi-x: %d, dst-roi-y: %d, dst-roi-w: %d, dst-roi-h: %d",
2515                                                                 roi_x, roi_y, roi_w, roi_h );
2516                                 debug_log("set video param : visible %d", visible);
2517                                 debug_log("set video param : force aspect ratio %d", force_aspect_ratio);
2518                         }
2519                 }
2520                 break;
2521                 case MM_DISPLAY_SURFACE_EVAS:
2522                 {
2523                         void *object = NULL;
2524                         int scaling = 0;
2525                         gboolean visible = TRUE;
2526
2527                         /* common case if using evas surface */
2528                         mm_attrs_get_data_by_name(attrs, "display_overlay", &object);
2529                         mm_attrs_get_int_by_name(attrs, "display_visible", &visible);
2530                         mm_attrs_get_int_by_name(attrs, "display_evas_do_scaling", &scaling);
2531                         if (object)
2532                         {
2533                                 g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
2534                                                 "evas-object", object,
2535                                                 "visible", visible,
2536                                                 NULL);
2537                                 debug_log("set video param : evas-object %x", object);
2538                                 debug_log("set video param : visible %d", visible);
2539                         }
2540                         else
2541                         {
2542                                 debug_error("no evas object");
2543                                 return MM_ERROR_PLAYER_INTERNAL;
2544                         }
2545
2546                         /* if evaspixmapsink */
2547                         if (!strcmp(PLAYER_INI()->videosink_element_evas,"evaspixmapsink"))
2548                         {
2549                                 int display_method = 0;
2550                                 int roi_x = 0;
2551                                 int roi_y = 0;
2552                                 int roi_w = 0;
2553                                 int roi_h = 0;
2554                                 int force_aspect_ratio = 0;
2555                                 int origin_size = !scaling;
2556
2557                                 mm_attrs_get_int_by_name(attrs, "display_force_aspect_ration", &force_aspect_ratio);
2558                                 mm_attrs_get_int_by_name(attrs, "display_method", &display_method);
2559                                 mm_attrs_get_int_by_name(attrs, "display_roi_x", &roi_x);
2560                                 mm_attrs_get_int_by_name(attrs, "display_roi_y", &roi_y);
2561                                 mm_attrs_get_int_by_name(attrs, "display_roi_width", &roi_w);
2562                                 mm_attrs_get_int_by_name(attrs, "display_roi_height", &roi_h);
2563
2564                                 g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
2565                                         "force-aspect-ratio", force_aspect_ratio,
2566                                         "origin-size", origin_size,
2567                                         "dst-roi-x", roi_x,
2568                                         "dst-roi-y", roi_y,
2569                                         "dst-roi-w", roi_w,
2570                                         "dst-roi-h", roi_h,
2571                                         "display-geometry-method", display_method,
2572                                         NULL );
2573
2574                                 debug_log("set video param : method %d", display_method);
2575                                 debug_log("set video param : dst-roi-x: %d, dst-roi-y: %d, dst-roi-w: %d, dst-roi-h: %d",
2576                                                                 roi_x, roi_y, roi_w, roi_h );
2577                                 debug_log("set video param : force aspect ratio %d", force_aspect_ratio);
2578                                 debug_log("set video param : display_evas_do_scaling %d (origin-size %d)", scaling, origin_size);
2579                         }
2580                 }
2581                 break;
2582                 case MM_DISPLAY_SURFACE_X_EXT:  /* NOTE : this surface type is for the video texture(canvas texture) */
2583                 {
2584                         void *pixmap_id_cb = NULL;
2585                         void *pixmap_id_cb_user_data = NULL;
2586                         int zoom = 0;
2587                         int degree = 0;
2588                         int display_method = 0;
2589                         int roi_x = 0;
2590                         int roi_y = 0;
2591                         int roi_w = 0;
2592                         int roi_h = 0;
2593                         int force_aspect_ratio = 0;
2594                         gboolean visible = TRUE;
2595
2596                         /* if xvimagesink */
2597                         if (strcmp(PLAYER_INI()->videosink_element_x,"xvimagesink"))
2598                         {
2599                                 debug_error("videosink is not xvimagesink");
2600                                 return MM_ERROR_PLAYER_INTERNAL;
2601                         }
2602
2603                         /* get information from attributes */
2604                         mm_attrs_get_data_by_name(attrs, "display_overlay", &pixmap_id_cb);
2605                         mm_attrs_get_data_by_name(attrs, "display_overlay_user_data", &pixmap_id_cb_user_data);
2606                         mm_attrs_get_int_by_name(attrs, "display_method", &display_method);
2607
2608                         if ( pixmap_id_cb )
2609                         {
2610                                 debug_log("set video param : display_overlay(0x%x)", pixmap_id_cb);
2611                                 if (pixmap_id_cb_user_data)
2612                                 {
2613                                         debug_log("set video param : display_overlay_user_data(0x%x)", pixmap_id_cb_user_data);
2614                                 }
2615                         }
2616                         else
2617                         {
2618                                 debug_error("failed to set pixmap-id-callback");
2619                                 return MM_ERROR_PLAYER_INTERNAL;
2620                         }
2621                         debug_log("set video param : method %d", display_method);
2622                         debug_log("set video param : visible %d", visible);
2623
2624                         /* set properties of videosink plugin */
2625                         g_object_set(player->pipeline->videobin[MMPLAYER_V_SINK].gst,
2626                                 "display-geometry-method", display_method,
2627                                 "draw-borders", FALSE,
2628                                 "visible", visible,
2629                                 "pixmap-id-callback", pixmap_id_cb,
2630                                 "pixmap-id-callback-userdata", pixmap_id_cb_user_data,
2631                                 NULL );
2632                 }
2633                 break;
2634                 case MM_DISPLAY_SURFACE_NULL:
2635                 {
2636                         /* do nothing */
2637                 }
2638                 break;
2639         }
2640
2641         debug_fleave();
2642
2643         return MM_ERROR_NONE;
2644 }
2645
2646 static int
2647 __mmplayer_gst_element_link_bucket(GList* element_bucket) // @
2648 {
2649         GList* bucket = element_bucket;
2650         MMPlayerGstElement* element = NULL;
2651         MMPlayerGstElement* prv_element = NULL;
2652         gint successful_link_count = 0;
2653
2654         debug_fenter();
2655
2656         return_val_if_fail(element_bucket, -1);
2657
2658         prv_element = (MMPlayerGstElement*)bucket->data;
2659         bucket = bucket->next;
2660
2661         for ( ; bucket; bucket = bucket->next )
2662         {
2663                 element = (MMPlayerGstElement*)bucket->data;
2664
2665                 if ( element && element->gst )
2666                 {
2667                         if ( GST_ELEMENT_LINK(GST_ELEMENT(prv_element->gst), GST_ELEMENT(element->gst)) )
2668                         {
2669                                 debug_log("linking [%s] to [%s] success\n",
2670                                         GST_ELEMENT_NAME(GST_ELEMENT(prv_element->gst)),
2671                                         GST_ELEMENT_NAME(GST_ELEMENT(element->gst)) );
2672                                 successful_link_count ++;
2673                         }
2674                         else
2675                         {
2676                                 debug_log("linking [%s] to [%s] failed\n",
2677                                         GST_ELEMENT_NAME(GST_ELEMENT(prv_element->gst)),
2678                                         GST_ELEMENT_NAME(GST_ELEMENT(element->gst)) );
2679                                 return -1;
2680                         }
2681                 }
2682
2683                 prv_element = element;
2684         }
2685
2686         debug_fleave();
2687
2688         return successful_link_count;
2689 }
2690
2691 static int
2692 __mmplayer_gst_element_add_bucket_to_bin(GstBin* bin, GList* element_bucket) // @
2693 {
2694         GList* bucket = element_bucket;
2695         MMPlayerGstElement* element = NULL;
2696         int successful_add_count = 0;
2697
2698         debug_fenter();
2699
2700         return_val_if_fail(element_bucket, 0);
2701         return_val_if_fail(bin, 0);
2702
2703         for ( ; bucket; bucket = bucket->next )
2704         {
2705                 element = (MMPlayerGstElement*)bucket->data;
2706
2707                 if ( element && element->gst )
2708                 {
2709                         if( !gst_bin_add(bin, GST_ELEMENT(element->gst)) )
2710                         {
2711                                 debug_log("__mmplayer_gst_element_link_bucket : Adding element [%s]  to bin [%s] failed\n",
2712                                         GST_ELEMENT_NAME(GST_ELEMENT(element->gst)),
2713                                         GST_ELEMENT_NAME(GST_ELEMENT(bin) ) );
2714                                 return 0;
2715                         }
2716                         successful_add_count ++;
2717                 }
2718         }
2719
2720         debug_fleave();
2721
2722         return successful_add_count;
2723 }
2724
2725
2726
2727 /**
2728  * This function is to create audio pipeline for playing.
2729  *
2730  * @param       player          [in]    handle of player
2731  *
2732  * @return      This function returns zero on success.
2733  * @remark
2734  * @see         __mmplayer_gst_create_midi_pipeline, __mmplayer_gst_create_video_pipeline
2735  */
2736 #define MMPLAYER_CREATEONLY_ELEMENT(x_bin, x_id, x_factory, x_name) \
2737 x_bin[x_id].id = x_id;\
2738 x_bin[x_id].gst = gst_element_factory_make(x_factory, x_name);\
2739 if ( ! x_bin[x_id].gst )\
2740 {\
2741         debug_critical("failed to create %s \n", x_factory);\
2742         goto ERROR;\
2743 }\
2744
2745 /* macro for code readability. just for sinkbin-creation functions */
2746 #define MMPLAYER_CREATE_ELEMENT(x_bin, x_id, x_factory, x_name, x_add_bucket) \
2747 do \
2748 { \
2749         x_bin[x_id].id = x_id;\
2750         x_bin[x_id].gst = gst_element_factory_make(x_factory, x_name);\
2751         if ( ! x_bin[x_id].gst )\
2752         {\
2753                 debug_critical("failed to create %s \n", x_factory);\
2754                 goto ERROR;\
2755         }\
2756         if ( x_add_bucket )\
2757                 element_bucket = g_list_append(element_bucket, &x_bin[x_id]);\
2758 } while(0);
2759
2760
2761 /**
2762   * AUDIO PIPELINE 
2763   * - Local playback    : audioconvert !volume ! capsfilter ! dnse ! audiosink
2764   * - Streaming                 : audioconvert !volume ! audiosink
2765   * - PCM extraction    : audioconvert ! audioresample ! capsfilter ! fakesink 
2766   */
2767 static int
2768 __mmplayer_gst_create_audio_pipeline(mm_player_t* player)
2769 {
2770         MMPlayerGstElement* first_element = NULL;
2771         MMPlayerGstElement* audiobin = NULL;
2772         MMHandleType attrs = 0;
2773         GstPad *pad = NULL;
2774         GstPad *ghostpad = NULL;
2775         GList* element_bucket = NULL;
2776         char *device_name = NULL;
2777         gboolean link_audio_sink_now = TRUE;
2778         int i =0;
2779
2780         debug_fenter();
2781
2782         return_val_if_fail( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
2783
2784         /* alloc handles */
2785         audiobin = (MMPlayerGstElement*)g_malloc0(sizeof(MMPlayerGstElement) * MMPLAYER_A_NUM);
2786         audiobin = (MMPlayerGstElement*)g_malloc0(sizeof(MMPlayerGstElement) * MMPLAYER_A_NUM);
2787         if ( ! audiobin )
2788         {
2789                 debug_error("failed to allocate memory for audiobin\n");
2790                 return MM_ERROR_PLAYER_NO_FREE_SPACE;
2791         }
2792
2793         attrs = MMPLAYER_GET_ATTRS(player);
2794
2795         /* create bin */
2796         audiobin[MMPLAYER_A_BIN].id = MMPLAYER_A_BIN;
2797         audiobin[MMPLAYER_A_BIN].gst = gst_bin_new("audiobin");
2798         if ( !audiobin[MMPLAYER_A_BIN].gst )
2799         {
2800                 debug_critical("failed to create audiobin\n");
2801                 goto ERROR;
2802         }
2803
2804         /* take it */
2805         player->pipeline->audiobin = audiobin;
2806
2807         player->is_sound_extraction = __mmplayer_can_extract_pcm(player);
2808
2809         /* Adding audiotp plugin for reverse trickplay feature */
2810         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_TP, "audiotp", "audiotrickplay", TRUE);
2811
2812         /* converter */
2813         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_CONV, "audioconvert", "audioconverter", TRUE);
2814
2815         if ( ! player->is_sound_extraction )
2816         {
2817                 GstCaps* caps = NULL;
2818
2819                 /* for logical volume control */
2820                 MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_VOL, "volume", "volume", TRUE);
2821                 g_object_set(G_OBJECT (audiobin[MMPLAYER_A_VOL].gst), "volume", player->sound.volume, NULL);
2822
2823                 if (player->sound.mute)
2824                 {
2825                         debug_log("mute enabled\n");
2826                         g_object_set(G_OBJECT (audiobin[MMPLAYER_A_VOL].gst), "mute", player->sound.mute, NULL);
2827                 }
2828
2829                 /*capsfilter */
2830                 MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_CAPS_DEFAULT, "capsfilter", "audiocapsfilter", TRUE);
2831
2832                 caps = gst_caps_from_string(            "audio/x-raw-int, "
2833                                                                                 "endianness = (int) LITTLE_ENDIAN, "
2834                                                                                 "signed = (boolean) true, "
2835                                                                                 "width = (int) 16, "
2836                                                                                 "depth = (int) 16"      );
2837
2838                 g_object_set (GST_ELEMENT(audiobin[MMPLAYER_A_CAPS_DEFAULT].gst), "caps", caps, NULL );
2839
2840                 gst_caps_unref( caps );
2841
2842                 /* audio filter. if enabled */
2843                 if ( PLAYER_INI()->use_audio_filter_preset || PLAYER_INI()->use_audio_filter_custom )
2844                 {
2845                         MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_FILTER, "soundalive", "audiofilter", TRUE);
2846                 }
2847
2848                 /* create audio sink */
2849                 MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_SINK, PLAYER_INI()->name_of_audiosink,
2850                         "audiosink", link_audio_sink_now);
2851
2852                 /* sync on */
2853                 if (MMPLAYER_IS_RTSP_STREAMING(player))
2854                         g_object_set (G_OBJECT (audiobin[MMPLAYER_A_SINK].gst), "sync", FALSE, NULL);   /* sync off */
2855                 else
2856                         g_object_set (G_OBJECT (audiobin[MMPLAYER_A_SINK].gst), "sync", TRUE, NULL);    /* sync on */
2857
2858                 /* qos on */
2859                 g_object_set (G_OBJECT (audiobin[MMPLAYER_A_SINK].gst), "qos", TRUE, NULL);     /* qos on */
2860
2861                 /* FIXIT : using system clock. isn't there another way? */
2862                 g_object_set (G_OBJECT (audiobin[MMPLAYER_A_SINK].gst), "provide-clock", PLAYER_INI()->provide_clock,  NULL);
2863
2864                 __mmplayer_add_sink( player, audiobin[MMPLAYER_A_SINK].gst );
2865
2866                 if(player->audio_buffer_cb)
2867                 {
2868                     g_object_set(audiobin[MMPLAYER_A_SINK].gst, "audio-handle", player->audio_buffer_cb_user_param, NULL);
2869                     g_object_set(audiobin[MMPLAYER_A_SINK].gst, "audio-callback", player->audio_buffer_cb, NULL);
2870                 }
2871
2872                 if ( g_strrstr(PLAYER_INI()->name_of_audiosink, "avsysaudiosink") )
2873                 {
2874                         gint volume_type = 0;
2875                         gint audio_route = 0;
2876                         gint sound_priority = FALSE;
2877                         gint is_spk_out_only = 0;
2878
2879                         /* set volume table
2880                          * It should be set after player creation through attribute.
2881                          * But, it can not be changed during playing.
2882                          */
2883                         mm_attrs_get_int_by_name(attrs, "sound_volume_type", &volume_type);
2884                         mm_attrs_get_int_by_name(attrs, "sound_route", &audio_route);
2885                         mm_attrs_get_int_by_name(attrs, "sound_priority", &sound_priority);
2886                         mm_attrs_get_int_by_name(attrs, "sound_spk_out_only", &is_spk_out_only);
2887
2888                         /* hook sound_type if emergency case */
2889                         if ( player->sm.event == ASM_EVENT_EMERGENCY)
2890                         {
2891                                 debug_log ("This is emergency session, hook sound_type from [%d] to [%d]\n", volume_type, MM_SOUND_VOLUME_TYPE_EMERGENCY);
2892                                 volume_type = MM_SOUND_VOLUME_TYPE_EMERGENCY;
2893                         }
2894
2895                         g_object_set(audiobin[MMPLAYER_A_SINK].gst,
2896                                                                 "volumetype", volume_type,
2897                                                                 "audio-route", audio_route,
2898                                                                 "priority", sound_priority,
2899                                                                 "user-route", is_spk_out_only,
2900                                                                 NULL);
2901
2902                         debug_log("audiosink property status...volume type:%d, route:%d, priority=%d, user-route=%d\n",
2903                                 volume_type, audio_route, sound_priority, is_spk_out_only);
2904                 }
2905
2906                 /* Antishock can be enabled when player is resumed by soundCM.
2907                  * But, it's not used in MMS, setting and etc.
2908                  * Because, player start seems like late.
2909                  */
2910                 __mmplayer_set_antishock( player , FALSE );
2911         }
2912         else // pcm extraction only and no sound output 
2913         {
2914                 int dst_samplerate = 0;
2915                 int dst_channels = 0;
2916                 int dst_depth = 0;
2917                 char *caps_type = NULL;
2918                 GstCaps* caps = NULL;
2919
2920                 /* resampler */
2921                 MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_RESAMPLER, "audioresample", "resampler", TRUE);
2922
2923                 /* get conf. values */
2924                 mm_attrs_multiple_get(player->attrs, 
2925                                                 NULL,
2926                                                 "pcm_extraction_samplerate", &dst_samplerate,
2927                                                 "pcm_extraction_channels", &dst_channels,
2928                                                 "pcm_extraction_depth", &dst_depth,
2929                                                 NULL);
2930                 /* capsfilter */
2931                 MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_CAPS_DEFAULT, "capsfilter", "audiocapsfilter", TRUE);
2932
2933                 caps = gst_caps_new_simple ("audio/x-raw-int",
2934                                                "rate", G_TYPE_INT, dst_samplerate,
2935                                                "channels", G_TYPE_INT, dst_channels,
2936                                                "depth", G_TYPE_INT, dst_depth,
2937                                                 NULL);
2938
2939                 caps_type = gst_caps_to_string(caps);
2940                 debug_log("resampler new caps : %s\n", caps_type);
2941
2942                         g_object_set (GST_ELEMENT(audiobin[MMPLAYER_A_CAPS_DEFAULT].gst), "caps", caps, NULL );
2943
2944                         /* clean */
2945                         gst_caps_unref( caps );
2946                         MMPLAYER_FREEIF( caps_type );
2947
2948                 /* fake sink */
2949                 MMPLAYER_CREATE_ELEMENT(audiobin, MMPLAYER_A_SINK, "fakesink", "fakesink", TRUE);
2950
2951                 /* set sync */
2952                 g_object_set (G_OBJECT (audiobin[MMPLAYER_A_SINK].gst), "sync", FALSE, NULL);
2953
2954                 __mmplayer_add_sink( player, audiobin[MMPLAYER_A_SINK].gst );
2955         }
2956
2957         /* adding created elements to bin */
2958         debug_log("adding created elements to bin\n");
2959         if( !__mmplayer_gst_element_add_bucket_to_bin( GST_BIN(audiobin[MMPLAYER_A_BIN].gst), element_bucket ))
2960         {
2961                 debug_error("failed to add elements\n");
2962                 goto ERROR;
2963         }
2964
2965         /* linking elements in the bucket by added order. */
2966         debug_log("Linking elements in the bucket by added order.\n");
2967         if ( __mmplayer_gst_element_link_bucket(element_bucket) == -1 )
2968         {
2969                 debug_error("failed to link elements\n");
2970                 goto ERROR;
2971         }
2972
2973         /* get first element's sinkpad for creating ghostpad */
2974         first_element = (MMPlayerGstElement *)element_bucket->data;
2975
2976         pad = gst_element_get_static_pad(GST_ELEMENT(first_element->gst), "sink");
2977         if ( ! pad )
2978         {
2979                 debug_error("failed to get pad from first element of audiobin\n");
2980                 goto ERROR;
2981         }
2982
2983         ghostpad = gst_ghost_pad_new("sink", pad);
2984         if ( ! ghostpad )
2985         {
2986                 debug_error("failed to create ghostpad\n");
2987                 goto ERROR;
2988         }
2989
2990         if ( FALSE == gst_element_add_pad(audiobin[MMPLAYER_A_BIN].gst, ghostpad) )
2991         {
2992                 debug_error("failed to add ghostpad to audiobin\n");
2993                 goto ERROR;
2994         }
2995
2996         gst_object_unref(pad);
2997
2998         if ( !player->bypass_sound_effect && (PLAYER_INI()->use_audio_filter_preset || PLAYER_INI()->use_audio_filter_custom) )
2999         {
3000                 if ( player->audio_filter_info.filter_type == MM_AUDIO_FILTER_TYPE_PRESET )
3001                 {
3002                         if (!_mmplayer_sound_filter_preset_apply(player, player->audio_filter_info.preset))
3003                         {
3004                                 debug_msg("apply sound effect(preset:%d) setting success\n",player->audio_filter_info.preset);
3005                         }
3006                 }
3007                 else if ( player->audio_filter_info.filter_type == MM_AUDIO_FILTER_TYPE_CUSTOM )
3008                 {
3009                         if (!_mmplayer_sound_filter_custom_apply(player))
3010                         {
3011                                 debug_msg("apply sound effect(custom) setting success\n");
3012                         }
3013                 }
3014         }
3015
3016         /* done. free allocated variables */
3017         MMPLAYER_FREEIF( device_name );
3018         g_list_free(element_bucket);
3019
3020         mm_attrs_set_int_by_name(attrs, "content_audio_found", TRUE);
3021         if ( mmf_attrs_commit ( attrs ) ) /* return -1 if error */
3022                 debug_error("failed to commit attribute ""content_audio_found"".\n");
3023
3024         debug_fleave();
3025
3026         return MM_ERROR_NONE;
3027
3028 ERROR:
3029
3030         debug_log("ERROR : releasing audiobin\n");
3031
3032         MMPLAYER_FREEIF( device_name );
3033
3034         if ( pad )
3035                 gst_object_unref(GST_OBJECT(pad));
3036
3037         if ( ghostpad )
3038                 gst_object_unref(GST_OBJECT(ghostpad));
3039
3040         g_list_free( element_bucket );
3041
3042
3043         /* release element which are not added to bin */
3044         for ( i = 1; i < MMPLAYER_A_NUM; i++ )  /* NOTE : skip bin */
3045         {
3046                 if ( audiobin[i].gst )
3047                 {
3048                         GstObject* parent = NULL;
3049                         parent = gst_element_get_parent( audiobin[i].gst );
3050
3051                         if ( !parent )
3052                         {
3053                                 gst_object_unref(GST_OBJECT(audiobin[i].gst));
3054                                 audiobin[i].gst = NULL;
3055                         }
3056                         else
3057                         {
3058                                 gst_object_unref(GST_OBJECT(parent));
3059                         }
3060                 }
3061         }
3062
3063         /* release audiobin with it's childs */
3064         if ( audiobin[MMPLAYER_A_BIN].gst )
3065         {
3066                 gst_object_unref(GST_OBJECT(audiobin[MMPLAYER_A_BIN].gst));
3067         }
3068
3069         MMPLAYER_FREEIF( audiobin );
3070
3071         player->pipeline->audiobin = NULL;
3072
3073         return MM_ERROR_PLAYER_INTERNAL;
3074 }
3075
3076 static gboolean
3077 __mmplayer_audio_stream_probe (GstPad *pad, GstBuffer *buffer, gpointer u_data)
3078 {
3079         mm_player_t* player = (mm_player_t*) u_data;
3080         gint size;
3081         guint8 *data;
3082
3083         data = GST_BUFFER_DATA(buffer);
3084         size = GST_BUFFER_SIZE(buffer);
3085
3086         if (player->audio_stream_cb && size && data)
3087                 player->audio_stream_cb((void *)data, size, player->audio_stream_cb_user_param);
3088
3089         return TRUE;
3090 }
3091
3092 /**
3093  * This function is to create video pipeline.
3094  *
3095  * @param       player          [in]    handle of player
3096  *              caps            [in]    src caps of decoder
3097  *              surface_type    [in]    surface type for video rendering
3098  *
3099  * @return      This function returns zero on success.
3100  * @remark
3101  * @see         __mmplayer_gst_create_audio_pipeline, __mmplayer_gst_create_midi_pipeline
3102  */
3103 /**
3104   * VIDEO PIPELINE
3105   * - x surface (arm/x86) : xvimagesink
3106   * - evas surface  (arm) : ffmpegcolorspace ! evasimagesink
3107   * - evas surface  (x86) : videoconvertor ! evasimagesink
3108   */
3109 static int
3110 __mmplayer_gst_create_video_pipeline(mm_player_t* player, GstCaps* caps, MMDisplaySurfaceType surface_type)
3111 {
3112         GstPad *pad = NULL;
3113         MMHandleType attrs;
3114         GList*element_bucket = NULL;
3115         MMPlayerGstElement* first_element = NULL;
3116         MMPlayerGstElement* videobin = NULL;
3117         gchar* vconv_factory = NULL;
3118         gchar *videosink_element = NULL;
3119
3120         debug_fenter();
3121
3122         return_val_if_fail(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
3123
3124         /* alloc handles */
3125         videobin = (MMPlayerGstElement*)g_malloc0(sizeof(MMPlayerGstElement) * MMPLAYER_V_NUM);
3126         if ( !videobin )
3127                 return MM_ERROR_PLAYER_NO_FREE_SPACE;
3128
3129         player->pipeline->videobin = videobin;
3130
3131         attrs = MMPLAYER_GET_ATTRS(player);
3132
3133         /* create bin */
3134         videobin[MMPLAYER_V_BIN].id = MMPLAYER_V_BIN;
3135         videobin[MMPLAYER_V_BIN].gst = gst_bin_new("videobin");
3136         if ( !videobin[MMPLAYER_V_BIN].gst )
3137         {
3138                 debug_critical("failed to create videobin");
3139                 goto ERROR;
3140         }
3141
3142         if( player->use_video_stream ) // video stream callack, so send raw video data to application
3143         {
3144                 GstStructure *str = NULL;
3145                 guint32 fourcc = 0;
3146                 gint ret = 0;
3147
3148                 debug_log("using memsink\n");
3149
3150                 /* first, create colorspace convert */
3151                 if (strlen(PLAYER_INI()->name_of_video_converter) > 0)
3152                 {
3153                                 vconv_factory = PLAYER_INI()->name_of_video_converter;
3154                 }
3155
3156                 if (vconv_factory)
3157                 {
3158                         MMPLAYER_CREATE_ELEMENT(videobin, MMPLAYER_V_CONV, vconv_factory, "video converter", TRUE);
3159                 }
3160                 
3161                 /* then, create video scale to resize if needed */
3162                 str = gst_caps_get_structure (caps, 0);
3163
3164                 if ( ! str )
3165                 {
3166                         debug_error("cannot get structure\n");
3167                         goto ERROR;
3168                 }
3169
3170                 MMPLAYER_LOG_GST_CAPS_TYPE(caps);
3171
3172                 ret = gst_structure_get_fourcc (str, "format", &fourcc);
3173
3174                 if ( !ret )
3175                         debug_log("not fixed format at this point, and not consider this case\n")
3176
3177                 /* NOTE :  if the width of I420 format is not multiple of 8, it should be resize before colorspace conversion.
3178                   * so, video scale is required for this case only.
3179                   */
3180                 if ( GST_MAKE_FOURCC ('I', '4', '2', '0') == fourcc )
3181                 {
3182                         gint width = 0;                         //width of video
3183                         gint height = 0;                        //height of video
3184                         gint framerate_n = 0;           //numerator of frame rate
3185                         gint framerate_d = 0;           //denominator of frame rate
3186                         GstCaps* video_caps = NULL;
3187                         const GValue *fps = NULL;
3188
3189                         /* video scale  */
3190                         MMPLAYER_CREATE_ELEMENT(videobin, MMPLAYER_V_SCALE, "videoscale", "videoscale", TRUE);
3191
3192                         /*to limit width as multiple of 8 */
3193                         MMPLAYER_CREATE_ELEMENT(videobin, MMPLAYER_V_CAPS, "capsfilter", "videocapsfilter", TRUE);
3194
3195                         /* get video stream caps parsed by demuxer */
3196                         str = gst_caps_get_structure (player->v_stream_caps, 0);
3197                         if ( ! str )
3198                         {
3199                                 debug_error("cannot get structure\n");
3200                                 goto ERROR;
3201                         }
3202
3203                         /* check the width if it's a multiple of 8 or not */
3204                         ret = gst_structure_get_int (str, "width", &width);
3205                         if ( ! ret )
3206                         {
3207                                 debug_error("cannot get width\n");
3208                                 goto ERROR;
3209                         }
3210                         width = GST_ROUND_UP_8(width);
3211
3212                         ret = gst_structure_get_int(str, "height", &height);
3213                         if ( ! ret )
3214                         {
3215                                 debug_error("cannot get height\n");
3216                                 goto ERROR;
3217                         }
3218
3219                         fps = gst_structure_get_value (str, "framerate");
3220                         if ( ! fps )
3221                         {
3222                                 debug_error("cannot get fps\n");
3223                                 goto ERROR;
3224                         }
3225                         framerate_n = gst_value_get_fraction_numerator (fps);
3226                         framerate_d = gst_value_get_fraction_denominator (fps);
3227
3228                         video_caps = gst_caps_new_simple( "video/x-raw-yuv",
3229                                                                                         "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('I', '4', '2', '0'),
3230                                                                                         "width", G_TYPE_INT, width,
3231                                                                                         "height", G_TYPE_INT, height,
3232                                                                                         "framerate", GST_TYPE_FRACTION, framerate_n, framerate_d,
3233                                                                                         NULL);
3234
3235                         g_object_set (GST_ELEMENT(videobin[MMPLAYER_V_CAPS].gst), "caps", video_caps, NULL );
3236
3237                         gst_caps_unref( video_caps );
3238                 }
3239
3240                 /* finally, create video sink. its oupput should be BGRX8888 for application like cario surface. */
3241                 MMPLAYER_CREATE_ELEMENT(videobin, MMPLAYER_V_SINK, "avsysmemsink", "videosink", TRUE);
3242
3243                 MMPLAYER_SIGNAL_CONNECT( player,
3244                                                                          videobin[MMPLAYER_V_SINK].gst,
3245                                                                          "video-stream",
3246                                                                          G_CALLBACK(__mmplayer_videostream_cb),
3247                                                                          player );
3248         }
3249         else // render video data using sink pugin like xvimagesink
3250         {
3251                 debug_log("using videosink");
3252                 
3253                 /*set video converter */
3254                 if (strlen(PLAYER_INI()->name_of_video_converter) > 0)
3255                 {
3256                         vconv_factory = PLAYER_INI()->name_of_video_converter;
3257                         if (vconv_factory)
3258                         {
3259                                 MMPLAYER_CREATE_ELEMENT(videobin, MMPLAYER_V_CONV, vconv_factory, "video converter", TRUE);
3260                                 debug_log("using video converter: %s", vconv_factory);
3261                         }
3262                 }
3263
3264                 /* videoscaler */ /* NOTE : ini parsing method seems to be more suitable rather than define method */
3265                 #if !defined(__arm__)
3266                 MMPLAYER_CREATE_ELEMENT(videobin, MMPLAYER_V_SCALE, "videoscale", "videoscaler", TRUE);
3267                 #endif
3268
3269                 /* set video sink */
3270                 switch (surface_type)
3271                 {
3272                 case MM_DISPLAY_SURFACE_X:
3273                         if (strlen(PLAYER_INI()->videosink_element_x) > 0)
3274                                 videosink_element = PLAYER_INI()->videosink_element_x;
3275                         else
3276                                 goto ERROR;
3277                         break;
3278                 case MM_DISPLAY_SURFACE_EVAS:
3279                         if (strlen(PLAYER_INI()->videosink_element_evas) > 0)
3280                                 videosink_element = PLAYER_INI()->videosink_element_evas;
3281                         else
3282                                 goto ERROR;
3283                         break;
3284                 case MM_DISPLAY_SURFACE_X_EXT:
3285                 {
3286                         void *pixmap_id_cb = NULL;
3287                         mm_attrs_get_data_by_name(attrs, "display_overlay", &pixmap_id_cb);
3288                         if (pixmap_id_cb) /* this is for the video textue(canvas texture) */
3289                         {
3290                                 videosink_element = PLAYER_INI()->videosink_element_x;
3291                                 debug_warning("video texture usage");
3292                         }
3293                         else
3294                         {
3295                                 debug_error("something wrong.. callback function for getting pixmap id is null");
3296                                 goto ERROR;
3297                         }
3298                         break;
3299                 }
3300                 case MM_DISPLAY_SURFACE_NULL:
3301                         if (strlen(PLAYER_INI()->videosink_element_fake) > 0)
3302                                 videosink_element = PLAYER_INI()->videosink_element_fake;
3303                         else
3304                                 goto ERROR;
3305                         break;
3306                 default:
3307                         debug_error("unidentified surface type");
3308                         goto ERROR;
3309                 }
3310
3311                 MMPLAYER_CREATE_ELEMENT(videobin, MMPLAYER_V_SINK, videosink_element, videosink_element, TRUE);
3312                 debug_log("selected videosink name: %s", videosink_element);
3313         }
3314
3315         if ( _mmplayer_update_video_param(player) != MM_ERROR_NONE)
3316                 goto ERROR;
3317
3318         /* qos on */
3319         g_object_set (G_OBJECT (videobin[MMPLAYER_V_SINK].gst), "qos", TRUE, NULL);
3320
3321         /* store it as it's sink element */
3322         __mmplayer_add_sink( player, videobin[MMPLAYER_V_SINK].gst );
3323
3324         /* adding created elements to bin */
3325         if( ! __mmplayer_gst_element_add_bucket_to_bin(GST_BIN(videobin[MMPLAYER_V_BIN].gst), element_bucket) )
3326         {
3327                 debug_error("failed to add elements\n");
3328                 goto ERROR;
3329         }
3330
3331         /* Linking elements in the bucket by added order */
3332         if ( __mmplayer_gst_element_link_bucket(element_bucket) == -1 )
3333         {
3334                 debug_error("failed to link elements\n");
3335                 goto ERROR;
3336         }
3337
3338         /* get first element's sinkpad for creating ghostpad */
3339         first_element = (MMPlayerGstElement *)element_bucket->data;
3340         if ( !first_element )
3341         {
3342                 debug_error("failed to get first element from bucket\n");
3343                 goto ERROR;
3344         }
3345
3346         pad = gst_element_get_static_pad(GST_ELEMENT(first_element->gst), "sink");
3347         if ( !pad )
3348         {
3349                 debug_error("failed to get pad from first element\n");
3350                 goto ERROR;
3351         }
3352
3353         /* create ghostpad */
3354         if (FALSE == gst_element_add_pad(videobin[MMPLAYER_V_BIN].gst, gst_ghost_pad_new("sink", pad)))
3355         {
3356                 debug_error("failed to add ghostpad to videobin\n");
3357                 goto ERROR;
3358         }
3359         gst_object_unref(pad);
3360
3361         /* done. free allocated variables */
3362         g_list_free(element_bucket);
3363
3364         mm_attrs_set_int_by_name(attrs, "content_video_found", TRUE);
3365         if ( mmf_attrs_commit ( attrs ) ) /* return -1 if error */
3366                 debug_error("failed to commit attribute ""content_video_found"".\n");
3367
3368         debug_fleave();
3369
3370         return MM_ERROR_NONE;
3371
3372 ERROR:
3373         debug_error("ERROR : releasing videobin\n");
3374
3375         g_list_free( element_bucket );
3376
3377         if (pad)
3378                 gst_object_unref(GST_OBJECT(pad));
3379
3380         /* release videobin with it's childs */
3381         if ( videobin[MMPLAYER_V_BIN].gst )
3382         {
3383                 gst_object_unref(GST_OBJECT(videobin[MMPLAYER_V_BIN].gst));
3384         }
3385
3386
3387         MMPLAYER_FREEIF( videobin );
3388
3389         player->pipeline->videobin = NULL;
3390
3391         return MM_ERROR_PLAYER_INTERNAL;
3392 }
3393
3394 static int              __mmplayer_gst_create_text_pipeline(mm_player_t* player)
3395 {
3396         MMPlayerGstElement* first_element = NULL;
3397         MMPlayerGstElement* textbin = NULL;
3398         GList* element_bucket = NULL;
3399         GstPad *pad = NULL;
3400         GstPad *ghostpad = NULL;
3401         gint i = 0;
3402
3403         debug_fenter();
3404
3405         return_val_if_fail( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
3406
3407         /* alloc handles */
3408         textbin = (MMPlayerGstElement*)g_malloc0(sizeof(MMPlayerGstElement) * MMPLAYER_T_NUM);
3409         if ( ! textbin )
3410         {
3411                 debug_error("failed to allocate memory for textbin\n");
3412                 return MM_ERROR_PLAYER_NO_FREE_SPACE;
3413         }
3414
3415         /* create bin */
3416         textbin[MMPLAYER_T_BIN].id = MMPLAYER_T_BIN;
3417         textbin[MMPLAYER_T_BIN].gst = gst_bin_new("textbin");
3418         if ( !textbin[MMPLAYER_T_BIN].gst )
3419         {
3420                 debug_critical("failed to create textbin\n");
3421                 goto ERROR;
3422         }
3423
3424         /* take it */
3425         player->pipeline->textbin = textbin;
3426
3427         /* fakesink */
3428         MMPLAYER_CREATE_ELEMENT(textbin, MMPLAYER_T_SINK, "fakesink", "text_sink", TRUE);
3429
3430         g_object_set (G_OBJECT (textbin[MMPLAYER_T_SINK].gst), "sync", TRUE, NULL);
3431         g_object_set (G_OBJECT (textbin[MMPLAYER_T_SINK].gst), "async", FALSE, NULL);
3432         g_object_set (G_OBJECT (textbin[MMPLAYER_T_SINK].gst), "signal-handoffs", TRUE, NULL);
3433
3434         MMPLAYER_SIGNAL_CONNECT( player,
3435                                                         G_OBJECT(textbin[MMPLAYER_T_SINK].gst),
3436                                                         "handoff",
3437                                                         G_CALLBACK(__mmplayer_update_subtitle),
3438                                                         (gpointer)player );
3439
3440         __mmplayer_add_sink (player, GST_ELEMENT(textbin[MMPLAYER_T_SINK].gst));
3441
3442         /* adding created elements to bin */
3443         debug_log("adding created elements to bin\n");
3444         if( !__mmplayer_gst_element_add_bucket_to_bin( GST_BIN(textbin[MMPLAYER_T_BIN].gst), element_bucket ))
3445         {
3446                 debug_error("failed to add elements\n");
3447                 goto ERROR;
3448         }
3449
3450         /* linking elements in the bucket by added order. */
3451         debug_log("Linking elements in the bucket by added order.\n");
3452         if ( __mmplayer_gst_element_link_bucket(element_bucket) == -1 )
3453         {
3454                 debug_error("failed to link elements\n");
3455                 goto ERROR;
3456         }
3457
3458         /* get first element's sinkpad for creating ghostpad */
3459         first_element = (MMPlayerGstElement *)element_bucket->data;
3460
3461         pad = gst_element_get_static_pad(GST_ELEMENT(first_element->gst), "sink");
3462         if ( ! pad )
3463         {
3464                 debug_error("failed to get pad from first element of textbin\n");
3465                 goto ERROR;
3466         }
3467
3468         ghostpad = gst_ghost_pad_new("sink", pad);
3469         if ( ! ghostpad )
3470         {
3471                 debug_error("failed to create ghostpad\n");
3472                 goto ERROR;
3473         }
3474
3475         if ( FALSE == gst_element_add_pad(textbin[MMPLAYER_T_BIN].gst, ghostpad) )
3476         {
3477                 debug_error("failed to add ghostpad to textbin\n");
3478                 goto ERROR;
3479         }
3480
3481         gst_object_unref(pad);
3482
3483
3484         /* done. free allocated variables */
3485         g_list_free(element_bucket);
3486
3487         debug_fleave();
3488
3489         return MM_ERROR_NONE;
3490
3491 ERROR:
3492
3493         debug_log("ERROR : releasing textbin\n");
3494
3495         if ( pad )
3496                 gst_object_unref(GST_OBJECT(pad));
3497
3498         if ( ghostpad )
3499                 gst_object_unref(GST_OBJECT(ghostpad));
3500
3501         g_list_free( element_bucket );
3502
3503
3504         /* release element which are not added to bin */
3505         for ( i = 1; i < MMPLAYER_T_NUM; i++ )  /* NOTE : skip bin */
3506         {
3507                 if ( textbin[i].gst )
3508                 {
3509                         GstObject* parent = NULL;
3510                         parent = gst_element_get_parent( textbin[i].gst );
3511
3512                         if ( !parent )
3513                         {
3514                                 gst_object_unref(GST_OBJECT(textbin[i].gst));
3515                                 textbin[i].gst = NULL;
3516                         }
3517                         else
3518                         {
3519                                 gst_object_unref(GST_OBJECT(parent));
3520                         }
3521                 }
3522         }
3523
3524         /* release textbin with it's childs */
3525         if ( textbin[MMPLAYER_T_BIN].gst )
3526         {
3527                 gst_object_unref(GST_OBJECT(textbin[MMPLAYER_T_BIN].gst));
3528         }
3529
3530         MMPLAYER_FREEIF( textbin );
3531
3532         player->pipeline->textbin = NULL;
3533
3534         return MM_ERROR_PLAYER_INTERNAL;
3535 }
3536
3537
3538 static int
3539 __mmplayer_gst_create_subtitle_pipeline(mm_player_t* player)
3540 {
3541         MMPlayerGstElement* subtitlebin = NULL;
3542         MMHandleType attrs = 0;
3543         gchar *subtitle_uri =NULL;
3544         GList*element_bucket = NULL;
3545
3546         #define USE_MESSAGE_FOR_PLAYING_SUBTITLE 
3547 #ifndef USE_MESSAGE_FOR_PLAYING_SUBTITLE
3548         void *xid = NULL;
3549         gint width =0, height = 0;
3550         gboolean silent=FALSE;
3551 #endif
3552
3553         debug_fenter();
3554
3555         /* get mainbin */
3556         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED);
3557
3558         attrs = MMPLAYER_GET_ATTRS(player);
3559         if ( !attrs )
3560         {
3561                 debug_error("cannot get content attribute\n");
3562                 return MM_ERROR_PLAYER_INTERNAL;
3563         }
3564
3565         mm_attrs_get_string_by_name ( attrs, "subtitle_uri", &subtitle_uri );
3566         if ( !subtitle_uri || strlen(subtitle_uri) < 1)
3567         {
3568                 debug_error("subtitle uri is not proper filepath.\n");
3569                 return MM_ERROR_PLAYER_INVALID_URI;     
3570         }
3571         debug_log("subtitle file path is [%s].\n", subtitle_uri);
3572
3573
3574         /* alloc handles */
3575         subtitlebin = (MMPlayerGstElement*)g_malloc0(sizeof(MMPlayerGstElement) * MMPLAYER_SUB_NUM);
3576         if ( !subtitlebin )
3577         {
3578                 debug_error("failed to allocate memory\n");
3579                 return MM_ERROR_PLAYER_NO_FREE_SPACE;
3580         }
3581
3582         /* create bin */
3583         subtitlebin[MMPLAYER_SUB_PIPE].id = MMPLAYER_SUB_PIPE;
3584         subtitlebin[MMPLAYER_SUB_PIPE].gst = gst_pipeline_new("subtitlebin");
3585         if ( !subtitlebin[MMPLAYER_SUB_PIPE].gst )
3586         {
3587                 debug_error("failed to create text pipeline\n");
3588                 goto ERROR;
3589         }
3590         player->pipeline->subtitlebin = subtitlebin;
3591
3592         /* create the text file source */
3593         MMPLAYER_CREATE_ELEMENT(subtitlebin, MMPLAYER_SUB_SRC, "filesrc", "subtitle_source", TRUE);
3594         g_object_set(G_OBJECT (subtitlebin[MMPLAYER_SUB_SRC].gst), "location", subtitle_uri, NULL);
3595
3596         /* queue */
3597         MMPLAYER_CREATE_ELEMENT(subtitlebin, MMPLAYER_SUB_QUEUE, "queue", NULL, TRUE);
3598
3599         /* subparse */
3600         MMPLAYER_CREATE_ELEMENT(subtitlebin, MMPLAYER_SUB_SUBPARSE, "subparse", "subtitle_parser", TRUE);
3601
3602 #ifndef USE_MESSAGE_FOR_PLAYING_SUBTITLE
3603         /* textrender */
3604         MMPLAYER_CREATE_ELEMENT(subtitlebin, MMPLAYER_SUB_TEXTRENDER, "textrender", "subtitle_render", TRUE);
3605
3606         mm_attrs_get_int_by_name(attrs,"width", &width);
3607         mm_attrs_get_int_by_name(attrs,"height", &height);
3608         mm_attrs_get_int_by_name(attrs,"silent", &silent);
3609         g_object_set ( G_OBJECT (subtitlebin[MMPLAYER_SUB_TEXTRENDER].gst),"width", width, NULL);
3610         g_object_set ( G_OBJECT (subtitlebin[MMPLAYER_SUB_TEXTRENDER].gst),"height", height, NULL);
3611         g_object_set ( G_OBJECT (subtitlebin[MMPLAYER_SUB_TEXTRENDER].gst),"silent", silent, NULL);
3612
3613         debug_log ( "subtitle winow size is [%dX%d].\n", width, height );
3614         debug_log ( "subtitle silent is [%d].\n", silent );
3615
3616         /* converter1 */
3617         MMPLAYER_CREATE_ELEMENT(subtitlebin, MMPLAYER_SUB_CONV1, "ffmpegcolorspace", "subtitle_converter1", TRUE);
3618
3619         /* videofliper */
3620         MMPLAYER_CREATE_ELEMENT(subtitlebin, MMPLAYER_SUB_FLIP, "videoflip", "subtitle_fliper", TRUE);
3621
3622         /* converter2 */
3623         MMPLAYER_CREATE_ELEMENT(subtitlebin, MMPLAYER_SUB_CONV2, "ffmpegcolorspace", "subtitle_converter2", TRUE);
3624
3625         /* text sink */
3626         MMPLAYER_CREATE_ELEMENT(subtitlebin, MMPLAYER_SUB_SINK, "ximagesink", "subtitle_sink", TRUE);
3627
3628         mm_attrs_get_data_by_name(attrs, "xid", &xid);
3629         if ( xid )
3630         {
3631                 debug_log("setting subtitle xid = %d\n", *(int*)xid);
3632                 gst_x_overlay_set_xwindow_id(GST_X_OVERLAY(subtitlebin[MMPLAYER_SUB_SINK].gst), *(int*)xid);
3633         }
3634         else
3635         {
3636                 /* FIXIT : is it error case? */
3637                 debug_warning("still we don't have xid on player attribute. create it's own surface.\n");
3638         }
3639 #else
3640         /* text sink */
3641         MMPLAYER_CREATE_ELEMENT(subtitlebin, MMPLAYER_SUB_SINK, "fakesink", "subtitle_sink", TRUE);
3642
3643         g_object_set (G_OBJECT (subtitlebin[MMPLAYER_SUB_SINK].gst), "sync", TRUE, NULL);
3644         g_object_set (G_OBJECT (subtitlebin[MMPLAYER_SUB_SINK].gst), "async", FALSE, NULL);
3645         g_object_set (G_OBJECT (subtitlebin[MMPLAYER_SUB_SINK].gst), "signal-handoffs", TRUE, NULL);
3646
3647         MMPLAYER_SIGNAL_CONNECT( player,
3648                                                         G_OBJECT(subtitlebin[MMPLAYER_SUB_SINK].gst),
3649                                                         "handoff",
3650                                                         G_CALLBACK(__mmplayer_update_subtitle),
3651                                                         (gpointer)player );
3652 #endif
3653
3654         /* adding created elements to bin */
3655         if( ! __mmplayer_gst_element_add_bucket_to_bin(GST_BIN(subtitlebin[MMPLAYER_SUB_PIPE].gst), element_bucket) )
3656         {
3657                 debug_error("failed to add elements\n");
3658                 goto ERROR;
3659         }
3660
3661         /* Linking elements in the bucket by added order */
3662         if ( __mmplayer_gst_element_link_bucket(element_bucket) == -1 )
3663         {
3664                 debug_error("failed to link elements\n");
3665                 goto ERROR;
3666         }
3667
3668         /* done. free allocated variables */
3669         g_list_free(element_bucket);
3670
3671         player->play_subtitle = TRUE;
3672
3673         debug_fleave();
3674         
3675         return MM_ERROR_NONE;
3676
3677
3678 ERROR:
3679         debug_error("ERROR : releasing text pipeline\n");
3680
3681         g_list_free( element_bucket );
3682
3683         /* release subtitlebin with it's childs */
3684         if ( subtitlebin[MMPLAYER_SUB_PIPE].gst )
3685         {
3686                 gst_object_unref(GST_OBJECT(subtitlebin[MMPLAYER_SUB_PIPE].gst));
3687         }
3688
3689         MMPLAYER_FREEIF( subtitlebin );
3690
3691         player->pipeline->subtitlebin = NULL;
3692
3693         return MM_ERROR_PLAYER_INTERNAL;
3694 }
3695
3696 gboolean
3697 __mmplayer_update_subtitle( GstElement* object, GstBuffer *buffer, GstPad *pad, gpointer data)
3698 {
3699         mm_player_t* player = (mm_player_t*) data;
3700         MMMessageParamType msg = {0, };
3701         GstClockTime duration = 0;
3702         guint8 *text = NULL;
3703         gboolean ret = TRUE;
3704
3705         debug_fenter();
3706
3707         return_val_if_fail ( player, FALSE );
3708         return_val_if_fail ( buffer, FALSE );
3709
3710         text = GST_BUFFER_DATA(buffer);
3711         duration = GST_BUFFER_DURATION(buffer);
3712
3713         if ( player->is_subtitle_off )
3714         {
3715                 debug_log("subtitle is OFF.\n" );
3716                 return TRUE;
3717         }
3718
3719         if ( !text )
3720         {
3721                 debug_log("There is no subtitle to be displayed.\n" );
3722                 return TRUE;
3723         }
3724
3725         msg.data = (void *) text;
3726         msg.subtitle.duration = GST_TIME_AS_MSECONDS(duration);
3727
3728         debug_warning("update subtitle : [%ld msec] %s\n'", msg.subtitle.duration, (char*)msg.data );
3729
3730         MMPLAYER_POST_MSG( player, MM_MESSAGE_UPDATE_SUBTITLE, &msg );
3731
3732         debug_fleave();
3733
3734         return ret;
3735 }
3736
3737
3738 static int      __gst_adjust_subtitle_position(mm_player_t* player, int format, int position)
3739 {
3740         GstEvent* event = NULL;
3741         gint64 current_pos = 0;
3742         gint64 adusted_pos = 0;
3743         gboolean ret = TRUE;
3744
3745         debug_fenter();
3746
3747         /* check player and subtitlebin are created */
3748         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
3749         return_val_if_fail ( MMPLAYER_PLAY_SUBTITLE(player),    MM_ERROR_PLAYER_NOT_INITIALIZED );
3750
3751         if (position == 0)
3752         {
3753                 debug_log("adjusted values is 0, no need to adjust subtitle position.\n");
3754                 return MM_ERROR_NONE;
3755         }
3756
3757         switch (format)
3758         {
3759                 case MM_PLAYER_POS_FORMAT_TIME:
3760                 {
3761                         GstFormat fmt = GST_FORMAT_TIME;
3762                         /* check current postion */
3763                         ret = gst_element_query_position( GST_ELEMENT(player->pipeline->subtitlebin[MMPLAYER_SUB_PIPE].gst), &fmt, &current_pos );
3764                         if ( !ret )
3765                         {
3766                                 debug_warning("fail to query current postion.\n");
3767                                 return MM_ERROR_PLAYER_SEEK;
3768                         }
3769                         else
3770                         {
3771                                 adusted_pos = current_pos + ((gint64)position * G_GINT64_CONSTANT(1000000));
3772                                 if (adusted_pos < 0)
3773                                         adusted_pos = G_GINT64_CONSTANT(0);
3774                                 debug_log("adjust subtitle postion : %lu -> %lu [msec]\n", GST_TIME_AS_MSECONDS(current_pos), GST_TIME_AS_MSECONDS(adusted_pos));
3775                         }
3776
3777                         event = gst_event_new_seek (1.0,        GST_FORMAT_TIME,
3778                                         ( GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE ),
3779                                         GST_SEEK_TYPE_SET, adusted_pos,
3780                                         GST_SEEK_TYPE_SET, -1);
3781                 }
3782                 break;
3783
3784                 case MM_PLAYER_POS_FORMAT_PERCENT:
3785                 {
3786                         debug_warning("percent format is not supported yet.\n");
3787                         return MM_ERROR_INVALID_ARGUMENT;
3788                 }
3789                 break;
3790
3791                 default:
3792                 {
3793                         debug_warning("invalid format.\n");
3794                         return MM_ERROR_INVALID_ARGUMENT;
3795                 }
3796         }
3797
3798         /* keep ref to the event */
3799         gst_event_ref (event);
3800
3801         debug_log("sending event[%s] to sink element [%s]\n",
3802                         GST_EVENT_TYPE_NAME(event), GST_ELEMENT_NAME(player->pipeline->subtitlebin[MMPLAYER_SUB_SINK].gst) );
3803
3804         if ( ret = gst_element_send_event (player->pipeline->subtitlebin[MMPLAYER_SUB_SINK].gst, event) )
3805         {
3806                 debug_log("sending event[%s] to sink element [%s] success!\n",
3807                         GST_EVENT_TYPE_NAME(event), GST_ELEMENT_NAME(player->pipeline->subtitlebin[MMPLAYER_SUB_SINK].gst) );
3808         }
3809
3810         /* unref to the event */
3811         gst_event_unref (event);
3812
3813
3814         debug_fleave();
3815
3816         return MM_ERROR_NONE;
3817
3818 }
3819
3820 static void
3821 __gst_appsrc_feed_data_mem(GstElement *element, guint size, gpointer user_data) // @
3822 {
3823         GstElement *appsrc = element;
3824         tBuffer *buf = (tBuffer *)user_data;
3825         GstBuffer *buffer = NULL;
3826         GstFlowReturn ret = GST_FLOW_OK;
3827         gint len = size;
3828
3829         return_if_fail ( element );
3830         return_if_fail ( buf );
3831
3832         buffer = gst_buffer_new ();
3833
3834         if (buf->offset >= buf->len)
3835         {
3836                 debug_log("call eos appsrc\n");
3837                g_signal_emit_by_name (appsrc, "end-of-stream", &ret);
3838                return;
3839         }
3840
3841         if ( buf->len - buf->offset < size)
3842         {
3843                 len = buf->len - buf->offset + buf->offset;
3844         }
3845
3846         GST_BUFFER_DATA(buffer) = (guint8*)(buf->buf + buf->offset);
3847         GST_BUFFER_SIZE(buffer) = len;
3848         GST_BUFFER_OFFSET(buffer) = buf->offset;
3849         GST_BUFFER_OFFSET_END(buffer) = buf->offset + len;
3850
3851         debug_log("feed buffer %p, offset %u-%u length %u\n", buffer, buf->offset, buf->len,len);
3852         g_signal_emit_by_name (appsrc, "push-buffer", buffer, &ret);
3853
3854         buf->offset += len;
3855 }
3856
3857 static gboolean
3858 __gst_appsrc_seek_data_mem(GstElement *element, guint64 size, gpointer user_data) // @
3859 {
3860         tBuffer *buf = (tBuffer *)user_data;
3861
3862         return_val_if_fail ( buf, FALSE );
3863
3864         buf->offset  = (int)size;
3865
3866         return TRUE;
3867 }
3868
3869 static void
3870 __gst_appsrc_feed_data(GstElement *element, guint size, gpointer user_data) // @
3871 {
3872        mm_player_t *player  = (mm_player_t*)user_data;
3873
3874         return_if_fail ( player );
3875
3876         debug_msg("app-src: feed data\n");
3877              
3878         if(player->need_data_cb)
3879                 player->need_data_cb(size, player->buffer_cb_user_param);
3880 }
3881
3882 static gboolean
3883 __gst_appsrc_seek_data(GstElement *element, guint64 offset, gpointer user_data) // @
3884 {
3885         mm_player_t *player  = (mm_player_t*)user_data;
3886
3887         return_val_if_fail ( player, FALSE );
3888
3889         debug_msg("app-src: seek data\n");
3890
3891         if(player->seek_data_cb)
3892                 player->seek_data_cb(offset, player->buffer_cb_user_param);
3893
3894         return TRUE;
3895 }
3896
3897
3898 static gboolean
3899 __gst_appsrc_enough_data(GstElement *element, gpointer user_data) // @
3900 {
3901         mm_player_t *player  = (mm_player_t*)user_data;
3902
3903         return_val_if_fail ( player, FALSE );
3904
3905         debug_msg("app-src: enough data:%p\n", player->enough_data_cb);
3906         
3907         if(player->enough_data_cb)
3908                 player->enough_data_cb(player->buffer_cb_user_param);
3909
3910         return TRUE;
3911 }
3912
3913 int
3914 _mmplayer_push_buffer(MMHandleType hplayer, unsigned char *buf, int size) // @
3915 {
3916         mm_player_t* player = (mm_player_t*)hplayer;
3917         GstBuffer *buffer = NULL;
3918         GstFlowReturn gst_ret = GST_FLOW_OK;
3919         int ret = MM_ERROR_NONE;
3920
3921         debug_fenter();
3922
3923         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
3924
3925         /* check current state */
3926 //      MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_START );
3927
3928
3929         /* NOTE : we should check and create pipeline again if not created as we destroy
3930          * whole pipeline when stopping in streamming playback
3931          */
3932         if ( ! player->pipeline )
3933         {
3934                 if ( MM_ERROR_NONE != __gst_realize( player ) )
3935                 {
3936                         debug_error("failed to realize before starting. only in streamming\n");
3937                         return MM_ERROR_PLAYER_INTERNAL;
3938                 }
3939         }
3940
3941         debug_msg("app-src: pushing data\n");
3942
3943         if ( buf == NULL )
3944         {
3945                 debug_error("buf is null\n");
3946                 return MM_ERROR_NONE;
3947         }
3948
3949         buffer = gst_buffer_new ();
3950
3951         if (size <= 0)
3952         {
3953                 debug_log("call eos appsrc\n");
3954                 g_signal_emit_by_name (player->pipeline->mainbin[MMPLAYER_M_SRC].gst, "end-of-stream", &gst_ret);
3955                 return MM_ERROR_NONE;
3956         }
3957
3958         GST_BUFFER_DATA(buffer) = (guint8*)(buf);
3959         GST_BUFFER_SIZE(buffer) = size;
3960
3961         debug_log("feed buffer %p, length %u\n", buf, size);
3962         g_signal_emit_by_name (player->pipeline->mainbin[MMPLAYER_M_SRC].gst, "push-buffer", buffer, &gst_ret);
3963
3964         debug_fleave();
3965
3966         return ret;
3967 }
3968
3969 static GstBusSyncReply
3970 __mmplayer_bus_sync_callback (GstBus * bus, GstMessage * message, gpointer data)
3971 {
3972         mm_player_t *player = (mm_player_t *)data;
3973         GstElement *sender = (GstElement *) GST_MESSAGE_SRC (message);
3974         const gchar *name = gst_element_get_name (sender);
3975
3976         switch (GST_MESSAGE_TYPE (message))
3977         {
3978                 case GST_MESSAGE_TAG:
3979                         __mmplayer_gst_extract_tag_from_msg(player, message);
3980                         break;
3981
3982                 default:
3983                         return GST_BUS_PASS;
3984         }
3985         gst_message_unref (message);
3986
3987         return GST_BUS_DROP;
3988 }
3989
3990 /**
3991  * This function is to create  audio or video pipeline for playing.
3992  *
3993  * @param       player          [in]    handle of player
3994  *
3995  * @return      This function returns zero on success.
3996  * @remark
3997  * @see
3998  */
3999 static int
4000 __mmplayer_gst_create_pipeline(mm_player_t* player) // @
4001 {
4002         GstBus  *bus = NULL;
4003         MMPlayerGstElement *mainbin = NULL;
4004         MMHandleType attrs = 0;
4005         GstElement* element = NULL;
4006         GList* element_bucket = NULL;
4007         gboolean need_state_holder = TRUE;
4008         gint i = 0;
4009
4010         debug_fenter();
4011
4012         return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
4013
4014         /* get profile attribute */
4015         attrs = MMPLAYER_GET_ATTRS(player);
4016         if ( !attrs )
4017         {
4018                 debug_error("cannot get content attribute\n");
4019                 goto INIT_ERROR;
4020         }
4021
4022         /* create pipeline handles */
4023         if ( player->pipeline )
4024         {
4025                 debug_warning("pipeline should be released before create new one\n");
4026                 goto INIT_ERROR;
4027         }
4028
4029         player->pipeline = (MMPlayerGstPipelineInfo*) g_malloc0( sizeof(MMPlayerGstPipelineInfo) );
4030         if (player->pipeline == NULL)
4031                 goto INIT_ERROR;
4032
4033         memset( player->pipeline, 0, sizeof(MMPlayerGstPipelineInfo) );
4034
4035
4036         /* create mainbin */
4037         mainbin = (MMPlayerGstElement*) g_malloc0( sizeof(MMPlayerGstElement) * MMPLAYER_M_NUM );
4038         if (mainbin == NULL)
4039                 goto INIT_ERROR;
4040
4041         memset( mainbin, 0, sizeof(MMPlayerGstElement) * MMPLAYER_M_NUM);
4042
4043
4044         /* create pipeline */
4045         mainbin[MMPLAYER_M_PIPE].id = MMPLAYER_M_PIPE;
4046         mainbin[MMPLAYER_M_PIPE].gst = gst_pipeline_new("player");
4047         if ( ! mainbin[MMPLAYER_M_PIPE].gst )
4048         {
4049                 debug_error("failed to create pipeline\n");
4050                 goto INIT_ERROR;
4051         }
4052
4053
4054         /* create source element */
4055         switch ( player->profile.uri_type )
4056         {
4057                 /* rtsp streamming */
4058                 case MM_PLAYER_URI_TYPE_URL_RTSP:
4059                 {
4060                         gint network_bandwidth;
4061                         gchar *user_agent, *wap_profile;
4062
4063                         element = gst_element_factory_make(PLAYER_INI()->name_of_rtspsrc, "streaming_source");
4064
4065                         if ( !element )
4066                         {
4067                                 debug_critical("failed to create streaming source element\n");
4068                                 break;
4069                         }
4070
4071                         debug_log("using streamming source [%s].\n", PLAYER_INI()->name_of_rtspsrc);
4072
4073                         /* make it zero */
4074                         network_bandwidth = 0;
4075                         user_agent = wap_profile = NULL;
4076
4077                         /* get attribute */
4078                         mm_attrs_get_string_by_name ( attrs, "streaming_user_agent", &user_agent );
4079                         mm_attrs_get_string_by_name ( attrs,"streaming_wap_profile", &wap_profile );
4080                         mm_attrs_get_int_by_name ( attrs, "streaming_network_bandwidth", &network_bandwidth );
4081
4082                         debug_log("setting streaming source ----------------\n");
4083                         debug_log("user_agent : %s\n", user_agent);
4084                         debug_log("wap_profile : %s\n", wap_profile);
4085                         debug_log("network_bandwidth : %d\n", network_bandwidth);
4086                         debug_log("buffering time : %d\n", PLAYER_INI()->rtsp_buffering_time);
4087                         debug_log("rebuffering time : %d\n", PLAYER_INI()->rtsp_rebuffering_time);
4088                         debug_log("-----------------------------------------\n");
4089
4090                         /* setting property to streaming source */
4091                         g_object_set(G_OBJECT(element), "location", player->profile.uri, NULL);
4092                         g_object_set(G_OBJECT(element), "bandwidth", network_bandwidth, NULL);
4093                         g_object_set(G_OBJECT(element), "buffering_time", PLAYER_INI()->rtsp_buffering_time, NULL);
4094                         g_object_set(G_OBJECT(element), "rebuffering_time", PLAYER_INI()->rtsp_rebuffering_time, NULL);
4095                         if ( user_agent )
4096                                 g_object_set(G_OBJECT(element), "user_agent", user_agent, NULL);
4097                         if ( wap_profile )
4098                                 g_object_set(G_OBJECT(element), "wap_profile", wap_profile, NULL);
4099
4100                         MMPLAYER_SIGNAL_CONNECT ( player, G_OBJECT(element), "pad-added",
4101                                 G_CALLBACK (__mmplayer_gst_rtp_dynamic_pad), player );
4102                         MMPLAYER_SIGNAL_CONNECT ( player, G_OBJECT(element), "no-more-pads",
4103                                 G_CALLBACK (__mmplayer_gst_rtp_no_more_pads), player );
4104
4105                         player->no_more_pad = FALSE;
4106                         player->num_dynamic_pad = 0;
4107
4108                         /* NOTE : we cannot determine it yet. this filed will be filled by
4109                          * _mmplayer_update_content_attrs() after START.
4110                          */
4111                         player->streaming_type = STREAMING_SERVICE_NONE;
4112                 }
4113                 break;
4114
4115                 /* http streaming*/
4116                 case MM_PLAYER_URI_TYPE_URL_HTTP:
4117                 {
4118                         gchar *user_agent, *proxy, *cookies, **cookie_list;
4119                         user_agent = proxy = cookies = NULL;
4120                         cookie_list = NULL;
4121                         gint mode = MM_PLAYER_PD_MODE_NONE;
4122
4123                         mm_attrs_get_int_by_name ( attrs, "pd_mode", &mode );
4124
4125                         player->pd_mode = mode;
4126
4127                         debug_log("http playback, PD mode : %d\n", player->pd_mode);
4128
4129                         if ( ! MMPLAYER_IS_HTTP_PD(player) )
4130                         {
4131                                 element = gst_element_factory_make(PLAYER_INI()->name_of_httpsrc, "http_streaming_source");
4132                                 if ( !element )
4133                                 {
4134                                         debug_critical("failed to create http streaming source element[%s].\n", PLAYER_INI()->name_of_httpsrc);
4135                                         break;
4136                                 }
4137                                 debug_log("using http streamming source [%s].\n", PLAYER_INI()->name_of_httpsrc);
4138
4139                                 /* get attribute */
4140                                 mm_attrs_get_string_by_name ( attrs, "streaming_cookie", &cookies );
4141                                 mm_attrs_get_string_by_name ( attrs, "streaming_user_agent", &user_agent );
4142                                 mm_attrs_get_string_by_name ( attrs, "streaming_proxy", &proxy );
4143                                 
4144                                 /* get attribute */
4145                                 debug_log("setting http streaming source ----------------\n");
4146                                 debug_log("location : %s\n", player->profile.uri);
4147                                 debug_log("cookies : %s\n", cookies);
4148                                 debug_log("proxy : %s\n", proxy);
4149                                 debug_log("user_agent :  %s\n",  user_agent);
4150                                 debug_log("timeout : %d\n",  PLAYER_INI()->http_timeout);
4151                                 debug_log("-----------------------------------------\n");
4152
4153                                 /* setting property to streaming source */
4154                                 g_object_set(G_OBJECT(element), "location", player->profile.uri, NULL);
4155                                 g_object_set(G_OBJECT(element), "timeout", PLAYER_INI()->http_timeout, NULL);
4156                                 /* check if prosy is vailid or not */
4157                                 if ( util_check_valid_url ( proxy ) )
4158                                         g_object_set(G_OBJECT(element), "proxy", proxy, NULL);
4159                                 /* parsing cookies */
4160                                 if ( ( cookie_list = util_get_cookie_list ((const char*)cookies) ) )
4161                                         g_object_set(G_OBJECT(element), "cookies", cookie_list, NULL);
4162                                 if ( user_agent )
4163                                         g_object_set(G_OBJECT(element), "user_agent", user_agent, NULL);
4164                         }
4165                         else // progressive download 
4166                         {
4167                                 if (player->pd_mode == MM_PLAYER_PD_MODE_URI)
4168                                 {
4169                                         gchar *path = NULL;
4170                                         
4171                                         mm_attrs_get_string_by_name ( attrs, "pd_location", &path );
4172                                         
4173                                         MMPLAYER_FREEIF(player->pd_file_save_path);
4174
4175                                         debug_log("PD Location : %s\n", path);
4176
4177                                         if ( path )
4178                                         {
4179                                                 player->pd_file_save_path = g_strdup(path);
4180                                         }
4181                                         else
4182                                         {
4183                                                 debug_error("can't find pd location so, it should be set \n");
4184                                                 return MM_ERROR_PLAYER_FILE_NOT_FOUND;  
4185                                         }
4186                                 }
4187
4188                                 element = gst_element_factory_make("pdpushsrc", "PD pushsrc");
4189                                 if ( !element )
4190                                 {
4191                                         debug_critical("failed to create PD push source element[%s].\n", "pdpushsrc");
4192                                         break;
4193                                 }
4194
4195                                 g_object_set(G_OBJECT(element), "location", player->pd_file_save_path, NULL);
4196                         }
4197                         
4198                         player->streaming_type = STREAMING_SERVICE_NONE;
4199                 }
4200                 break;
4201
4202                 /* file source */
4203                 case MM_PLAYER_URI_TYPE_FILE:
4204                 {
4205                         char* drmsrc = PLAYER_INI()->name_of_drmsrc;
4206
4207                         debug_log("using [%s] for 'file://' handler.\n", drmsrc);
4208
4209                         element = gst_element_factory_make(drmsrc, "source");
4210                         if ( !element )
4211                         {
4212                                 debug_critical("failed to create %s\n", drmsrc);
4213                                 break;
4214                         }
4215
4216                         g_object_set(G_OBJECT(element), "location", (player->profile.uri)+7, NULL);     /* uri+7 -> remove "file:// */
4217                         //g_object_set(G_OBJECT(element), "use-mmap", TRUE, NULL);
4218                 }
4219                 break;
4220
4221                 /* appsrc */
4222                 case MM_PLAYER_URI_TYPE_BUFF:
4223                 {
4224                         guint64 stream_type = GST_APP_STREAM_TYPE_STREAM;
4225
4226                         debug_log("mem src is selected\n");
4227
4228                         element = gst_element_factory_make("appsrc", "buff-source");
4229                         if ( !element )
4230                         {
4231                                 debug_critical("failed to create appsrc element\n");
4232                                 break;
4233                         }
4234
4235                         g_object_set( element, "stream-type", stream_type, NULL );
4236                         //g_object_set( element, "size", player->mem_buf.len, NULL );
4237                         //g_object_set( element, "blocksize", (guint64)20480, NULL );
4238
4239                         MMPLAYER_SIGNAL_CONNECT( player, element, "seek-data",
4240                                 G_CALLBACK(__gst_appsrc_seek_data), player);
4241                         MMPLAYER_SIGNAL_CONNECT( player, element, "need-data",
4242                                 G_CALLBACK(__gst_appsrc_feed_data), player);
4243                         MMPLAYER_SIGNAL_CONNECT( player, element, "enough-data",
4244                                 G_CALLBACK(__gst_appsrc_enough_data), player);
4245                 }
4246                 break;
4247
4248                 /* appsrc */
4249                 case MM_PLAYER_URI_TYPE_MEM:
4250                 {
4251                         guint64 stream_type = GST_APP_STREAM_TYPE_RANDOM_ACCESS;
4252
4253                         debug_log("mem src is selected\n");
4254
4255                         element = gst_element_factory_make("appsrc", "mem-source");
4256                         if ( !element )
4257                         {
4258                                 debug_critical("failed to create appsrc element\n");
4259                                 break;
4260                         }
4261
4262                         g_object_set( element, "stream-type", stream_type, NULL );
4263                         g_object_set( element, "size", player->mem_buf.len, NULL );
4264                         g_object_set( element, "blocksize", (guint64)20480, NULL );
4265
4266                         MMPLAYER_SIGNAL_CONNECT( player, element, "seek-data",
4267                                 G_CALLBACK(__gst_appsrc_seek_data_mem), &player->mem_buf );
4268                         MMPLAYER_SIGNAL_CONNECT( player, element, "need-data",
4269                                 G_CALLBACK(__gst_appsrc_feed_data_mem), &player->mem_buf );
4270                 }
4271                 break;
4272                 case MM_PLAYER_URI_TYPE_URL:
4273                 break;
4274
4275                 case MM_PLAYER_URI_TYPE_TEMP:
4276                 break;
4277
4278                 case MM_PLAYER_URI_TYPE_NONE:
4279                 default:
4280                 break;
4281         }
4282
4283         /* check source element is OK */
4284         if ( ! element )
4285         {
4286                 debug_critical("no source element was created.\n");
4287                 goto INIT_ERROR;
4288         }
4289
4290         /* take source element */
4291         mainbin[MMPLAYER_M_SRC].id = MMPLAYER_M_SRC;
4292         mainbin[MMPLAYER_M_SRC].gst = element;
4293         element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_SRC]);
4294
4295         if (MMPLAYER_IS_STREAMING(player))
4296         {
4297                 player->streamer = __mm_player_streaming_create();
4298                 __mm_player_streaming_initialize(player->streamer);
4299         }
4300
4301         if ( MMPLAYER_IS_HTTP_PD(player) )
4302         {       
4303                debug_log ("Picked queue2 element....\n");
4304                 element = gst_element_factory_make("queue2", "hls_stream_buffer");
4305                 if ( !element )
4306                 {
4307                         debug_critical ( "failed to create http streaming buffer element\n" );
4308                         goto INIT_ERROR;
4309                 }
4310                         
4311                 /* take it */
4312                 mainbin[MMPLAYER_M_S_BUFFER].id = MMPLAYER_M_S_BUFFER;
4313                 mainbin[MMPLAYER_M_S_BUFFER].gst = element;
4314                 element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_S_BUFFER]);
4315
4316                 __mm_player_streaming_set_buffer(player->streamer,
4317                                 element,
4318                                 TRUE,
4319                                 PLAYER_INI()->http_max_size_bytes,
4320                                 1.0,
4321                                 PLAYER_INI()->http_buffering_limit,
4322                                 PLAYER_INI()->http_buffering_time,
4323                                 FALSE,
4324                                 NULL,
4325                                 0);
4326         }
4327
4328         /* create autoplugging element if src element is not a streamming src */
4329         if ( player->profile.uri_type != MM_PLAYER_URI_TYPE_URL_RTSP )
4330         {
4331                 element = NULL;
4332
4333                 if( PLAYER_INI()->use_decodebin )
4334                 {
4335                         /* create decodebin */
4336                         element = gst_element_factory_make("decodebin", "decodebin");
4337
4338                         g_object_set(G_OBJECT(element), "async-handling", TRUE, NULL);
4339
4340                         /* set signal handler */
4341                         MMPLAYER_SIGNAL_CONNECT( player, G_OBJECT(element), "new-decoded-pad",
4342                                         G_CALLBACK(__mmplayer_gst_decode_callback), player);
4343
4344                         /* we don't need state holder, bcz decodebin is doing well by itself */
4345                         need_state_holder = FALSE;
4346                 }
4347                 else
4348                 {
4349                         element = gst_element_factory_make("typefind", "typefinder");
4350                         MMPLAYER_SIGNAL_CONNECT( player, element, "have-type",
4351                                 G_CALLBACK(__mmplayer_typefind_have_type), (gpointer)player );
4352                 }
4353
4354                 /* check autoplug element is OK */
4355                 if ( ! element )
4356                 {
4357                         debug_critical("can not create autoplug element\n");
4358                         goto INIT_ERROR;
4359                 }
4360
4361                 mainbin[MMPLAYER_M_AUTOPLUG].id = MMPLAYER_M_AUTOPLUG;
4362                 mainbin[MMPLAYER_M_AUTOPLUG].gst = element;
4363
4364                 element_bucket = g_list_append(element_bucket, &mainbin[MMPLAYER_M_AUTOPLUG]);
4365         }
4366
4367
4368         /* add elements to pipeline */
4369         if( !__mmplayer_gst_element_add_bucket_to_bin(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), element_bucket))
4370         {
4371                 debug_error("Failed to add elements to pipeline\n");
4372                 goto INIT_ERROR;
4373         }
4374
4375
4376         /* linking elements in the bucket by added order. */
4377         if ( __mmplayer_gst_element_link_bucket(element_bucket) == -1 )
4378         {
4379                 debug_error("Failed to link some elements\n");
4380                 goto INIT_ERROR;
4381         }
4382
4383
4384         /* create fakesink element for keeping the pipeline state PAUSED. if needed */
4385         if ( need_state_holder )
4386         {
4387                 /* create */
4388                 mainbin[MMPLAYER_M_SRC_FAKESINK].id = MMPLAYER_M_SRC_FAKESINK;
4389                 mainbin[MMPLAYER_M_SRC_FAKESINK].gst = gst_element_factory_make ("fakesink", "state-holder");
4390
4391                 if (!mainbin[MMPLAYER_M_SRC_FAKESINK].gst)
4392                 {
4393                         debug_error ("fakesink element could not be created\n");
4394                         goto INIT_ERROR;
4395                 }
4396                 GST_OBJECT_FLAG_UNSET (mainbin[MMPLAYER_M_SRC_FAKESINK].gst, GST_ELEMENT_IS_SINK);
4397
4398                 /* take ownership of fakesink. we are reusing it */
4399                 gst_object_ref( mainbin[MMPLAYER_M_SRC_FAKESINK].gst );
4400
4401                 /* add */
4402                 if ( FALSE == gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst),
4403                         mainbin[MMPLAYER_M_SRC_FAKESINK].gst) )
4404                 {
4405                         debug_error("failed to add fakesink to bin\n");
4406                         goto INIT_ERROR;
4407                 }
4408         }
4409
4410         /* now we have completed mainbin. take it */
4411         player->pipeline->mainbin = mainbin;
4412
4413         /* connect bus callback */
4414         bus = gst_pipeline_get_bus(GST_PIPELINE(mainbin[MMPLAYER_M_PIPE].gst));
4415         if ( !bus )
4416         {
4417                 debug_error ("cannot get bus from pipeline.\n");
4418                 goto INIT_ERROR;
4419         }
4420         player->bus_watcher = gst_bus_add_watch(bus, (GstBusFunc)__mmplayer_gst_callback, player);
4421
4422         /* Note : check whether subtitle atrribute uri is set. If uri is set, then create the text pipeline */
4423         if ( __mmplayer_check_subtitle ( player ) )
4424         {
4425                 debug_log("try to create subtitle pipeline \n");
4426
4427                 if ( MM_ERROR_NONE != __mmplayer_gst_create_subtitle_pipeline(player) )
4428                         debug_error("fail to create subtitle pipeline")
4429                 else
4430                         debug_log("subtitle pipeline is created successfully\n");
4431         }
4432
4433         /* set sync handler to get tag synchronously */
4434         gst_bus_set_sync_handler(bus, __mmplayer_bus_sync_callback, player);
4435
4436
4437         /* finished */
4438         gst_object_unref(GST_OBJECT(bus));
4439         g_list_free(element_bucket);
4440
4441         debug_fleave();
4442
4443         return MM_ERROR_NONE;
4444
4445 INIT_ERROR:
4446
4447         __mmplayer_gst_destroy_pipeline(player);
4448         g_list_free(element_bucket);
4449
4450         /* release element which are not added to bin */
4451         for ( i = 1; i < MMPLAYER_M_NUM; i++ )  /* NOTE : skip pipeline */
4452         {
4453                 if ( mainbin[i].gst )
4454                 {
4455                         GstObject* parent = NULL;
4456                         parent = gst_element_get_parent( mainbin[i].gst );
4457
4458                         if ( !parent )
4459                         {
4460                                 gst_object_unref(GST_OBJECT(mainbin[i].gst));
4461                                 mainbin[i].gst = NULL;
4462                         }
4463                         else
4464                         {
4465                                 gst_object_unref(GST_OBJECT(parent));
4466                         }
4467                 }
4468         }
4469
4470         /* release pipeline with it's childs */
4471         if ( mainbin[MMPLAYER_M_PIPE].gst )
4472         {
4473                 gst_object_unref(GST_OBJECT(mainbin[MMPLAYER_M_PIPE].gst));
4474         }
4475
4476         MMPLAYER_FREEIF( player->pipeline );
4477         MMPLAYER_FREEIF( mainbin );
4478
4479         return MM_ERROR_PLAYER_INTERNAL;
4480 }
4481
4482
4483 static int
4484 __mmplayer_gst_destroy_pipeline(mm_player_t* player) // @
4485 {
4486         gint timeout = 0;
4487         int ret = MM_ERROR_NONE;
4488
4489         debug_fenter();
4490         
4491         return_val_if_fail ( player, MM_ERROR_INVALID_HANDLE );
4492
4493         /* cleanup stuffs */
4494         MMPLAYER_FREEIF(player->type);
4495         player->have_dynamic_pad = FALSE;
4496         player->no_more_pad = FALSE;
4497         player->num_dynamic_pad = 0;
4498
4499         if (player->v_stream_caps)
4500         {
4501                 gst_caps_unref(player->v_stream_caps);
4502                 player->v_stream_caps = NULL;
4503         }
4504
4505         if (ahs_appsrc_cb_probe_id )
4506         {
4507                 GstPad *pad = NULL;
4508                 pad = gst_element_get_static_pad(player->pipeline->mainbin[MMPLAYER_M_SRC].gst, "src" );
4509
4510                 gst_pad_remove_buffer_probe (pad, ahs_appsrc_cb_probe_id);
4511                 gst_object_unref(pad);
4512                 pad = NULL;
4513                 ahs_appsrc_cb_probe_id = 0;
4514         }
4515
4516         if ( player->sink_elements )
4517                 g_list_free ( player->sink_elements );
4518         player->sink_elements = NULL;
4519
4520         /* cleanup unlinked mime type */
4521         MMPLAYER_FREEIF(player->unlinked_audio_mime);
4522         MMPLAYER_FREEIF(player->unlinked_video_mime);
4523         MMPLAYER_FREEIF(player->unlinked_demuxer_mime); 
4524
4525         /* cleanup running stuffs */
4526         __mmplayer_cancel_delayed_eos( player );
4527
4528         /* cleanup gst stuffs */
4529         if ( player->pipeline )
4530         {
4531                 MMPlayerGstElement* mainbin = player->pipeline->mainbin;
4532                 GstTagList* tag_list = player->pipeline->tag_list;
4533
4534                 /* first we need to disconnect all signal hander */
4535                 __mmplayer_release_signal_connection( player );
4536
4537                 /* disconnecting bus watch */
4538                 if ( player->bus_watcher )
4539                         g_source_remove( player->bus_watcher );
4540                 player->bus_watcher = 0;
4541
4542
4543                 if ( mainbin )
4544                 {
4545                         MMPlayerGstElement* audiobin = player->pipeline->audiobin;
4546                         MMPlayerGstElement* videobin = player->pipeline->videobin;
4547                         MMPlayerGstElement* textbin = player->pipeline->textbin;
4548                         MMPlayerGstElement* subtitlebin = player->pipeline->subtitlebin;
4549                         GstBus *bus = gst_pipeline_get_bus (GST_PIPELINE (mainbin[MMPLAYER_M_PIPE].gst));
4550                         gst_bus_set_sync_handler (bus, NULL, NULL);
4551
4552                         debug_log("pipeline status before set state to NULL\n");
4553                         __mmplayer_dump_pipeline_state( player );
4554
4555                         timeout = MMPLAYER_STATE_CHANGE_TIMEOUT(player);
4556                         ret = __mmplayer_gst_set_state ( player, mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_NULL, FALSE, timeout );
4557                         if ( ret != MM_ERROR_NONE )
4558                         {
4559                                 debug_error("fail to change state to NULL\n");
4560                                 return MM_ERROR_PLAYER_INTERNAL;
4561                         }
4562
4563                         debug_log("pipeline status before unrefering pipeline\n");
4564                         __mmplayer_dump_pipeline_state( player );
4565
4566                         gst_object_unref(GST_OBJECT(mainbin[MMPLAYER_M_PIPE].gst));
4567
4568                         /* free fakesink */
4569                         if ( mainbin[MMPLAYER_M_SRC_FAKESINK].gst )
4570                                 gst_object_unref(GST_OBJECT(mainbin[MMPLAYER_M_SRC_FAKESINK].gst));
4571
4572                         /* free avsysaudiosink
4573                            avsysaudiosink should be unref when destory pipeline just after start play with BT.
4574                            Because audiosink is created but never added to bin, and therefore it will not be unref when pipeline is destroyed.
4575                         */
4576                         MMPLAYER_FREEIF( audiobin );
4577                         MMPLAYER_FREEIF( videobin );
4578                         MMPLAYER_FREEIF( textbin );
4579                         MMPLAYER_FREEIF( subtitlebin);
4580                         MMPLAYER_FREEIF( mainbin );
4581                 }
4582
4583                 if ( tag_list )
4584                         gst_tag_list_free(tag_list);
4585
4586                 MMPLAYER_FREEIF( player->pipeline );
4587         }
4588
4589         player->pipeline_is_constructed = FALSE;
4590         
4591         debug_fleave();
4592
4593         return ret;
4594 }
4595
4596 static int __gst_realize(mm_player_t* player) // @
4597 {
4598         gint timeout = 0;
4599         int ret = MM_ERROR_NONE;
4600
4601         debug_fenter();
4602
4603         return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
4604
4605         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_READY;
4606
4607         __ta__("__mmplayer_gst_create_pipeline",
4608                 ret = __mmplayer_gst_create_pipeline(player);
4609                 if ( ret )
4610                 {
4611                         debug_critical("failed to create pipeline\n");
4612                         return ret;
4613                 }
4614         )
4615
4616         /* set pipeline state to READY */
4617         /* NOTE : state change to READY must be performed sync. */
4618         timeout = MMPLAYER_STATE_CHANGE_TIMEOUT(player);
4619         ret = __mmplayer_gst_set_state(player,
4620                                 player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_READY, FALSE, timeout);
4621
4622         if (MMPLAYER_PLAY_SUBTITLE(player))
4623                 ret = __mmplayer_gst_set_state(player,
4624                                         player->pipeline->subtitlebin[MMPLAYER_SUB_PIPE].gst, GST_STATE_READY, FALSE, timeout);
4625
4626         if ( ret != MM_ERROR_NONE )
4627         {
4628                 /* return error if failed to set state */
4629                 debug_error("failed to set state PAUSED (live : READY).\n");
4630
4631                 /* dump state of all element */
4632                 __mmplayer_dump_pipeline_state( player );
4633
4634                 return ret;
4635         }
4636         else 
4637         {
4638                 MMPLAYER_SET_STATE ( player, MM_PLAYER_STATE_READY );
4639         }
4640
4641         /* create dot before error-return. for debugging */
4642         MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-realize" );
4643
4644         debug_fleave();
4645
4646         return ret;
4647 }
4648
4649 static int __gst_unrealize(mm_player_t* player) // @
4650 {
4651         int ret = MM_ERROR_NONE;
4652
4653         debug_fenter();
4654
4655         return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
4656
4657         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_NULL;
4658         MMPLAYER_PRINT_STATE(player);   
4659
4660         /* release miscellaneous information */
4661         __mmplayer_release_misc( player );
4662
4663         /* destroy pipeline */
4664         ret = __mmplayer_gst_destroy_pipeline( player );
4665         if ( ret != MM_ERROR_NONE )
4666         {
4667                 debug_error("failed to destory pipeline\n");
4668                 return ret;
4669         }
4670
4671         MMPLAYER_SET_STATE ( player, MM_PLAYER_STATE_NULL );
4672
4673         debug_fleave();
4674
4675         return ret;
4676 }
4677
4678 static int __gst_pending_seek ( mm_player_t* player )
4679 {
4680         MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
4681         MMPlayerStateType pending_state = MM_PLAYER_STATE_NONE;
4682         int ret = MM_ERROR_NONE;
4683
4684         debug_fenter();
4685
4686         return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
4687
4688         if ( !player->pending_seek.is_pending )
4689         {
4690                 debug_log("pending seek is not reserved. nothing to do.\n" );
4691                 return ret;
4692         }
4693
4694         /* check player state if player could pending seek or not. */
4695         current_state = MMPLAYER_CURRENT_STATE(player);
4696         pending_state = MMPLAYER_PENDING_STATE(player);
4697
4698         if ( current_state != MM_PLAYER_STATE_PAUSED && current_state != MM_PLAYER_STATE_PLAYING  )
4699         {
4700                 debug_warning("try to pending seek in %s state, try next time. \n",
4701                         MMPLAYER_STATE_GET_NAME(current_state));
4702                 return ret;
4703         }
4704         
4705         debug_log("trying to play from (%lu) pending position\n", player->pending_seek.pos);
4706         
4707         ret = __gst_set_position ( player, player->pending_seek.format, player->pending_seek.pos, FALSE );
4708         
4709         if ( MM_ERROR_NONE != ret )
4710                 debug_error("failed to seek pending postion. just keep staying current position.\n");
4711
4712         player->pending_seek.is_pending = FALSE;
4713
4714         debug_fleave();
4715
4716         return ret;
4717 }
4718
4719 static int __gst_start(mm_player_t* player) // @
4720 {
4721         gboolean sound_extraction = 0;
4722         int ret = MM_ERROR_NONE;
4723
4724         debug_fenter();
4725
4726         return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
4727
4728         /* get sound_extraction property */
4729         mm_attrs_get_int_by_name(player->attrs, "pcm_extraction", &sound_extraction);
4730
4731         /* NOTE : if SetPosition was called before Start. do it now */
4732         /* streaming doesn't support it. so it should be always sync */
4733         /* !! create one more api to check if there is pending seek rather than checking variables */
4734         if ( (player->pending_seek.is_pending || sound_extraction) && !MMPLAYER_IS_STREAMING(player))
4735         {
4736                 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_PAUSED;
4737                 ret = __gst_pause(player, FALSE);
4738                 if ( ret != MM_ERROR_NONE )
4739                 {
4740                         debug_error("failed to set state to PAUSED for pending seek\n");
4741                         return ret;
4742                 }
4743
4744                 MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_PLAYING;
4745
4746                 if ( sound_extraction )
4747                 {
4748                         debug_log("setting pcm extraction\n");
4749
4750                         ret = __mmplayer_set_pcm_extraction(player);
4751                         if ( MM_ERROR_NONE != ret )
4752                         {
4753                                 debug_warning("failed to set pcm extraction\n");
4754                                 return ret;
4755                         }
4756                 }
4757                 else
4758                 {                       
4759                         if ( MM_ERROR_NONE != __gst_pending_seek(player) )
4760                         {
4761                                 debug_warning("failed to seek pending postion. starting from the begin of content.\n");
4762                         }
4763                 }
4764         }
4765
4766         debug_log("current state before doing transition");
4767         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_PLAYING;
4768         MMPLAYER_PRINT_STATE(player);
4769
4770         /* set pipeline state to PLAYING  */
4771         ret = __mmplayer_gst_set_state(player,
4772                 player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_PLAYING, FALSE, MMPLAYER_STATE_CHANGE_TIMEOUT(player) );
4773
4774         if (MMPLAYER_PLAY_SUBTITLE(player))
4775                 ret = __mmplayer_gst_set_state(player,
4776                         player->pipeline->subtitlebin[MMPLAYER_SUB_PIPE].gst, GST_STATE_PLAYING, FALSE, MMPLAYER_STATE_CHANGE_TIMEOUT(player) );
4777
4778         if (ret == MM_ERROR_NONE)
4779         {
4780                 MMPLAYER_SET_STATE(player, MM_PLAYER_STATE_PLAYING);
4781         }
4782         else
4783         {
4784                 debug_error("failed to set state to PLAYING");
4785
4786                 /* dump state of all element */
4787                 __mmplayer_dump_pipeline_state( player );
4788
4789                 return ret;
4790         }
4791
4792         /* FIXIT : analyze so called "async problem" */
4793         /* set async off */
4794         __gst_set_async_state_change( player, FALSE );
4795
4796         /* generating debug info before returning error */
4797         MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-start" );
4798
4799         debug_fleave();
4800
4801         return ret;
4802 }
4803
4804 static void __mmplayer_do_sound_fadedown(mm_player_t* player, unsigned int time)
4805 {
4806         debug_fenter();
4807         
4808         return_if_fail(player 
4809                 && player->pipeline
4810                 && player->pipeline->audiobin
4811                 && player->pipeline->audiobin[MMPLAYER_A_SINK].gst);
4812
4813         g_object_set(G_OBJECT(player->pipeline->audiobin[MMPLAYER_A_SINK].gst), "mute", 2, NULL);
4814         
4815         usleep(time);
4816
4817         debug_fleave();
4818 }
4819
4820 static void __mmplayer_undo_sound_fadedown(mm_player_t* player)
4821 {
4822         debug_fenter();
4823         
4824         return_if_fail(player 
4825                 && player->pipeline
4826                 && player->pipeline->audiobin
4827                 && player->pipeline->audiobin[MMPLAYER_A_SINK].gst);
4828         
4829         g_object_set(G_OBJECT(player->pipeline->audiobin[MMPLAYER_A_SINK].gst), "mute", 0, NULL);       
4830
4831         debug_fleave();
4832 }
4833
4834 static int __gst_stop(mm_player_t* player) // @
4835 {
4836         GstStateChangeReturn change_ret = GST_STATE_CHANGE_SUCCESS;
4837         MMHandleType attrs = 0;
4838         gboolean fadewown = FALSE;
4839         gboolean rewind = FALSE;
4840         gint timeout = 0;
4841         int ret = MM_ERROR_NONE;
4842
4843         debug_fenter();
4844
4845         return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
4846
4847         debug_log("current state before doing transition");
4848         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_READY;
4849         MMPLAYER_PRINT_STATE(player);   
4850
4851         attrs = MMPLAYER_GET_ATTRS(player);
4852         if ( !attrs )
4853         {
4854                 debug_error("cannot get content attribute\n");
4855                 return MM_ERROR_PLAYER_INTERNAL;
4856         }
4857
4858         mm_attrs_get_int_by_name(attrs,"sound_fadedown", &fadewown);
4859
4860         /* enable fadedown */
4861         if (fadewown)
4862                 __mmplayer_do_sound_fadedown(player, MM_PLAYER_FADEOUT_TIME_DEFAULT);
4863
4864         /* Just set state to PAUESED and the rewind. it's usual player behavior. */
4865         timeout = MMPLAYER_STATE_CHANGE_TIMEOUT ( player );
4866         if  ( player->profile.uri_type == MM_PLAYER_URI_TYPE_BUFF || player->profile.uri_type == MM_PLAYER_URI_TYPE_HLS)
4867         {
4868                 ret = __mmplayer_gst_set_state(player, 
4869                         player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_READY, FALSE, timeout );
4870         }
4871         else
4872         {
4873                 ret = __mmplayer_gst_set_state( player,
4874                         player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_PAUSED, FALSE, timeout );
4875
4876                 if (MMPLAYER_PLAY_SUBTITLE(player))
4877                         ret = __mmplayer_gst_set_state( player,
4878                                 player->pipeline->subtitlebin[MMPLAYER_SUB_PIPE].gst, GST_STATE_PAUSED, FALSE, timeout );
4879
4880                 if ( !MMPLAYER_IS_STREAMING(player))
4881                         rewind = TRUE;
4882         }
4883
4884         /* disable fadeout */
4885         if (fadewown)
4886                 __mmplayer_undo_sound_fadedown(player);
4887
4888
4889         /* return if set_state has failed */
4890         if ( ret != MM_ERROR_NONE )
4891         {
4892                 debug_error("failed to set state.\n");
4893
4894                 /* dump state of all element. don't care it success or not */
4895                 __mmplayer_dump_pipeline_state( player );
4896
4897                 return ret;
4898         }
4899
4900         /* rewind */
4901         if ( rewind )
4902         {
4903                 if ( ! __gst_seek( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, 1.0,
4904                                 GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET, 0,
4905                                 GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE) )
4906                 {
4907                         debug_warning("failed to rewind\n");
4908                         ret = MM_ERROR_PLAYER_SEEK;
4909                 }
4910         }
4911
4912         /* initialize */
4913         player->sent_bos = FALSE;
4914
4915         /* wait for seek to complete */
4916         change_ret = gst_element_get_state (player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, NULL, NULL, timeout * GST_SECOND);
4917         if (MMPLAYER_PLAY_SUBTITLE(player))
4918                 change_ret = gst_element_get_state (player->pipeline->subtitlebin[MMPLAYER_SUB_PIPE].gst, NULL, NULL, timeout * GST_SECOND);
4919
4920         if ( change_ret == GST_STATE_CHANGE_SUCCESS || change_ret == GST_STATE_CHANGE_NO_PREROLL )
4921         {
4922                 MMPLAYER_SET_STATE ( player, MM_PLAYER_STATE_READY );
4923         }
4924         else
4925         {
4926                 debug_error("fail to stop player.\n");
4927                 ret = MM_ERROR_PLAYER_INTERNAL;
4928         }
4929
4930         /* generate dot file if enabled */
4931         MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-stop" );
4932
4933         debug_fleave(); 
4934
4935         return ret;
4936 }
4937
4938 int __gst_pause(mm_player_t* player, gboolean async) // @
4939 {
4940         int ret = MM_ERROR_NONE;
4941
4942         debug_fenter();
4943
4944         return_val_if_fail(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
4945
4946         debug_log("current state before doing transition");
4947         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_PAUSED;
4948         MMPLAYER_PRINT_STATE(player);   
4949
4950         /* set pipeline status to PAUSED */
4951         ret = __mmplayer_gst_set_state(player,
4952                 player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_PAUSED, async, MMPLAYER_STATE_CHANGE_TIMEOUT(player));
4953
4954         if (MMPLAYER_PLAY_SUBTITLE(player))
4955                 ret = __mmplayer_gst_set_state(player,
4956                         player->pipeline->subtitlebin[MMPLAYER_SUB_PIPE].gst, GST_STATE_PAUSED, async, MMPLAYER_STATE_CHANGE_TIMEOUT(player));
4957
4958         if ( ret != MM_ERROR_NONE )
4959         {
4960                 debug_error("failed to set state to PAUSED\n");
4961
4962                 /* dump state of all element */
4963                 __mmplayer_dump_pipeline_state( player );
4964
4965                 return ret;
4966         }
4967         else
4968         {       
4969                 if ( async == FALSE ) 
4970                 {
4971                         MMPLAYER_SET_STATE ( player, MM_PLAYER_STATE_PAUSED );
4972                 }
4973         } 
4974
4975         /* FIXIT : analyze so called "async problem" */
4976         /* set async off */
4977         __gst_set_async_state_change( player, TRUE);
4978
4979         /* generate dot file before returning error */
4980         MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-pause" );
4981
4982         debug_fleave();
4983
4984         return ret;
4985 }
4986
4987 int __gst_resume(mm_player_t* player, gboolean async) // @
4988 {
4989         int ret = MM_ERROR_NONE;
4990         gint timeout = 0;
4991
4992         debug_fenter();
4993
4994         return_val_if_fail(player && player->pipeline,
4995                 MM_ERROR_PLAYER_NOT_INITIALIZED);
4996
4997         debug_log("current state before doing transition");
4998         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_PLAYING;
4999         MMPLAYER_PRINT_STATE(player);   
5000
5001         /* generate dot file before returning error */
5002         MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-resume" );
5003
5004         __mmplayer_set_antishock( player , FALSE );
5005
5006         if ( async )
5007                 debug_log("do async state transition to PLAYING.\n");
5008
5009         /* set pipeline state to PLAYING */
5010         timeout = MMPLAYER_STATE_CHANGE_TIMEOUT(player);
5011         ret = __mmplayer_gst_set_state(player,
5012                 player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_PLAYING, async, timeout );
5013
5014         if (MMPLAYER_PLAY_SUBTITLE(player))
5015                 ret = __mmplayer_gst_set_state(player,
5016                         player->pipeline->subtitlebin[MMPLAYER_SUB_PIPE].gst, GST_STATE_PLAYING, async, timeout );
5017
5018         if (ret != MM_ERROR_NONE)
5019         {
5020                 debug_error("failed to set state to PLAYING\n");
5021
5022                 /* dump state of all element */
5023                 __mmplayer_dump_pipeline_state( player );
5024
5025                 return ret;
5026         }
5027         else
5028         {
5029                 if (async == FALSE)
5030                 {
5031                         MMPLAYER_SET_STATE ( player, MM_PLAYER_STATE_PLAYING );
5032                 }
5033         }
5034         
5035         /* FIXIT : analyze so called "async problem" */
5036         /* set async off */
5037         __gst_set_async_state_change( player, FALSE );
5038
5039         /* generate dot file before returning error */
5040         MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-resume" );
5041
5042         debug_fleave();
5043
5044         return ret;
5045 }
5046
5047 static int
5048 __gst_set_position(mm_player_t* player, int format, unsigned long position, gboolean internal_called) // @
5049 {
5050         GstFormat fmt  = GST_FORMAT_TIME;
5051         unsigned long dur_msec = 0;
5052         gint64 dur_nsec = 0;
5053         gint64 pos_nsec = 0;
5054         gboolean ret = TRUE;
5055
5056         debug_fenter();
5057         return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
5058         return_val_if_fail ( !MMPLAYER_IS_LIVE_STREAMING(player), MM_ERROR_PLAYER_NO_OP );
5059
5060         if ( MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PLAYING
5061                 && MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PAUSED )
5062                 goto PENDING;
5063
5064         /* check duration */
5065         /* NOTE : duration cannot be zero except live streaming.
5066          *              Since some element could have some timing problemn with quering duration, try again.
5067          */
5068         if ( !player->duration )
5069         {
5070                 if ( !gst_element_query_duration( player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, &fmt, &dur_nsec ))
5071                 {
5072                         goto SEEK_ERROR;
5073                 }
5074                 player->duration = dur_nsec;
5075         }
5076
5077         if ( player->duration )
5078         {
5079                 dur_msec = GST_TIME_AS_MSECONDS(player->duration);
5080         }
5081         else
5082         {
5083                 debug_error("could not get the duration. fail to seek.\n");
5084                 goto SEEK_ERROR;
5085         }
5086
5087         debug_log("playback rate: %f\n", player->playback_rate);
5088
5089         /* do seek */
5090         switch ( format )
5091         {
5092                 case MM_PLAYER_POS_FORMAT_TIME:
5093                 {
5094                         /* check position is valid or not */
5095                         if ( position > dur_msec )
5096                                 goto INVALID_ARGS;
5097
5098                         debug_log("seeking to (%lu) msec, duration is %d msec\n", position, dur_msec);
5099
5100                         if (player->doing_seek)
5101                         {
5102                                 debug_log("not completed seek");
5103                                 return MM_ERROR_PLAYER_DOING_SEEK;
5104                         }
5105
5106                         if ( !internal_called)
5107                                 player->doing_seek = TRUE;
5108
5109                         pos_nsec = position * G_GINT64_CONSTANT(1000000);
5110                         ret = __gst_seek ( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, 1.0,
5111                                                         GST_FORMAT_TIME, ( GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE ),
5112                                                         GST_SEEK_TYPE_SET, pos_nsec, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE );
5113                         if ( !ret  )
5114                         {
5115                                 debug_error("failed to set position. dur[%lu]  pos[%lu]  pos_msec[%llu]\n", dur_msec, position, pos_nsec);
5116                                 goto SEEK_ERROR;
5117                         }
5118                 }
5119                 break;
5120
5121                 case MM_PLAYER_POS_FORMAT_PERCENT:
5122                 {
5123                         if ( position < 0 && position > 100 )
5124                                 goto INVALID_ARGS;
5125
5126                         debug_log("seeking to (%lu)%% \n", position);
5127
5128                         if (player->doing_seek)
5129                         {
5130                                 debug_log("not completed seek");
5131                                 return MM_ERROR_PLAYER_DOING_SEEK;
5132                         }
5133
5134                         if ( !internal_called)
5135                                 player->doing_seek = TRUE;
5136
5137                         /* FIXIT : why don't we use 'GST_FORMAT_PERCENT' */
5138                         pos_nsec = (gint64) ( ( position * player->duration ) / 100 );
5139                         ret = __gst_seek ( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, 1.0,
5140                                                         GST_FORMAT_TIME, ( GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE ),
5141                                                         GST_SEEK_TYPE_SET, pos_nsec, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE );
5142                         if ( !ret  )
5143                         {
5144                                 debug_error("failed to set position. dur[%lud]  pos[%lud]  pos_msec[%llud]\n", dur_msec, position, pos_nsec);
5145                                 goto SEEK_ERROR;
5146                         }
5147                 }
5148                 break;
5149
5150                 default:
5151                         goto INVALID_ARGS;
5152                         
5153         }
5154
5155         /* NOTE : store last seeking point to overcome some bad operation 
5156           *      ( returning zero when getting current position ) of some elements 
5157           */
5158         player->last_position = pos_nsec;
5159
5160         /* MSL should guarante playback rate when seek is selected during trick play of fast forward. */
5161         if ( player->playback_rate > 1.0 )
5162                 _mmplayer_set_playspeed ( (MMHandleType)player, player->playback_rate );
5163
5164         debug_fleave();
5165         return MM_ERROR_NONE;
5166
5167 PENDING:
5168         player->pending_seek.is_pending = TRUE;
5169         player->pending_seek.format = format;
5170         player->pending_seek.pos = position;
5171         
5172         debug_warning("player current-state : %s, pending-state : %s, just preserve pending position(%lu).\n", 
5173                 MMPLAYER_STATE_GET_NAME(MMPLAYER_CURRENT_STATE(player)), MMPLAYER_STATE_GET_NAME(MMPLAYER_PENDING_STATE(player)), player->pending_seek.pos);
5174         
5175         return MM_ERROR_NONE;
5176         
5177 INVALID_ARGS:   
5178         debug_error("invalid arguments, position : %ld  dur : %ld format : %d \n", position, dur_msec, format);
5179         return MM_ERROR_INVALID_ARGUMENT;
5180
5181 SEEK_ERROR:
5182         player->doing_seek = FALSE;
5183         return MM_ERROR_PLAYER_SEEK;
5184 }
5185
5186 #define TRICKPLAY_OFFSET GST_MSECOND
5187
5188 static int
5189 __gst_get_position(mm_player_t* player, int format, unsigned long* position) // @
5190 {
5191         MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
5192         GstFormat fmt = GST_FORMAT_TIME;
5193         signed long long pos_msec = 0;
5194         gboolean ret = TRUE;
5195
5196         return_val_if_fail( player && position && player->pipeline && player->pipeline->mainbin,
5197                 MM_ERROR_PLAYER_NOT_INITIALIZED );
5198
5199         current_state = MMPLAYER_CURRENT_STATE(player);
5200
5201         /* NOTE : query position except paused state to overcome some bad operation
5202          * please refer to below comments in details
5203          */
5204         if ( current_state != MM_PLAYER_STATE_PAUSED )
5205         {
5206                 ret = gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, &fmt, &pos_msec);
5207         }
5208
5209         /* NOTE : get last point to overcome some bad operation of some elements
5210          * ( returning zero when getting current position in paused state
5211          * and when failed to get postion during seeking
5212          */
5213         if ( ( current_state == MM_PLAYER_STATE_PAUSED )
5214                 || ( ! ret ))
5215                 //|| ( player->last_position != 0 && pos_msec == 0 ) )
5216         {
5217                 debug_warning ("pos_msec = %"GST_TIME_FORMAT" and ret = %d and state = %d", GST_TIME_ARGS (pos_msec), ret, current_state);
5218
5219                 if(player->playback_rate < 0.0)
5220                         pos_msec = player->last_position - TRICKPLAY_OFFSET;
5221                 else
5222                         pos_msec = player->last_position;
5223
5224                 if (!ret)
5225                         pos_msec = player->last_position;
5226                 else
5227                         player->last_position = pos_msec;
5228
5229                 debug_warning("returning last point : %"GST_TIME_FORMAT, GST_TIME_ARGS(pos_msec));
5230
5231         }
5232         else
5233         {
5234                 player->last_position = pos_msec;
5235         }
5236
5237         switch (format) {
5238                 case MM_PLAYER_POS_FORMAT_TIME:
5239                         *position = GST_TIME_AS_MSECONDS(pos_msec);
5240                         break;
5241
5242                 case MM_PLAYER_POS_FORMAT_PERCENT:
5243                 {
5244                         int dur = 0;
5245                         int pos = 0;
5246
5247                         dur = player->duration / GST_SECOND;
5248                         if (dur <= 0)
5249                         {
5250                                 debug_log ("duration is [%d], so returning position 0\n",dur);
5251                                 *position = 0;
5252                         }
5253                         else
5254                         {
5255                                 pos = pos_msec / GST_SECOND;
5256                                 *position = pos * 100 / dur;
5257                         }
5258                         break;
5259                 }
5260                 default:
5261                         return MM_ERROR_PLAYER_INTERNAL;
5262         }
5263
5264         debug_log("current position : %lu\n", *position);
5265
5266         
5267         return MM_ERROR_NONE;
5268 }
5269
5270
5271 static int      __gst_get_buffer_position(mm_player_t* player, int format, unsigned long* start_pos, unsigned long* stop_pos)
5272 {
5273         GstElement *element = NULL;
5274         GstQuery *query = NULL;
5275
5276         return_val_if_fail( player && 
5277                 player->pipeline && 
5278                 player->pipeline->mainbin,
5279                 MM_ERROR_PLAYER_NOT_INITIALIZED );
5280
5281         return_val_if_fail( start_pos && stop_pos, MM_ERROR_INVALID_ARGUMENT );
5282
5283         if ( MMPLAYER_IS_HTTP_STREAMING ( player ))
5284         {
5285                 /* Note : In case of http streaming or HLS, the buffering queue [ queue2 ] could handle buffering query. */
5286                 element = GST_ELEMENT ( player->pipeline->mainbin[MMPLAYER_M_S_BUFFER].gst );
5287         }
5288         else if ( MMPLAYER_IS_RTSP_STREAMING ( player ) )
5289         {
5290                 debug_warning ( "it's not supported yet.\n" );
5291                 return MM_ERROR_NONE;
5292         }
5293         else
5294         {
5295                 debug_warning ( "it's only used for streaming case.\n" );
5296                 return MM_ERROR_NONE;   
5297         }
5298
5299         *start_pos = 0;
5300         *stop_pos = 0;
5301         
5302         switch ( format )
5303         {
5304                 case MM_PLAYER_POS_FORMAT_PERCENT :
5305                 {
5306                                 query = gst_query_new_buffering ( GST_FORMAT_PERCENT );
5307                                 if ( gst_element_query ( element, query ) ) 
5308                                 {
5309                                         gint64 start, stop;
5310                                         GstFormat format;
5311                                         gboolean busy;
5312                                         gint percent;
5313
5314                                         gst_query_parse_buffering_percent ( query, &busy, &percent);
5315                                         gst_query_parse_buffering_range ( query, &format, &start, &stop, NULL );
5316
5317                                         debug_log ( "buffering start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT "\n",  start, stop);
5318
5319                                         if ( start != -1)
5320                                                 *start_pos = 100 * start / GST_FORMAT_PERCENT_MAX;
5321                                         else
5322                                                 *start_pos = 0;
5323
5324                                         if ( stop != -1)
5325                                                 *stop_pos = 100 * stop / GST_FORMAT_PERCENT_MAX;
5326                                         else
5327                                                 *stop_pos = 0;
5328                                 }
5329                                 gst_query_unref (query);
5330                 }
5331                 break;
5332
5333                 case MM_PLAYER_POS_FORMAT_TIME :
5334                         debug_warning ( "Time format is not supported yet.\n" );
5335                         break;
5336                         
5337                 default :
5338                         break;
5339         }
5340
5341         debug_log("current buffer position : %lu~%lu \n", *start_pos, *stop_pos );
5342
5343         return MM_ERROR_NONE;
5344 }
5345
5346 static int
5347 __gst_set_message_callback(mm_player_t* player, MMMessageCallback callback, gpointer user_param) // @
5348 {
5349         debug_fenter();
5350
5351         if ( !player )
5352         {
5353                 debug_warning("set_message_callback is called with invalid player handle\n");
5354                 return MM_ERROR_PLAYER_NOT_INITIALIZED;
5355         }
5356
5357         player->msg_cb = callback;
5358         player->msg_cb_param = user_param;
5359
5360         debug_log("msg_cb : 0x%x     msg_cb_param : 0x%x\n", (guint)callback, (guint)user_param);
5361
5362         debug_fleave();
5363
5364         return MM_ERROR_NONE;
5365 }
5366
5367 static gboolean __mmfplayer_parse_profile(const char *uri, void *param, MMPlayerParseProfile* data) // @
5368 {
5369         gboolean ret = FALSE;
5370         char *path = NULL;
5371
5372         debug_fenter();
5373
5374         return_val_if_fail ( uri , FALSE);
5375         return_val_if_fail ( data , FALSE);
5376         return_val_if_fail ( ( strlen(uri) <= MM_MAX_URL_LEN ), FALSE );
5377
5378         memset(data, 0, sizeof(MMPlayerParseProfile));
5379
5380         if ((path = strstr(uri, "file://")))
5381         {
5382                 if (util_exist_file_path(path + 7)) {
5383                         strncpy(data->uri, path, MM_MAX_URL_LEN-1);                     
5384
5385                         if ( util_is_sdp_file ( path ) )
5386                         {
5387                                 debug_log("uri is actually a file but it's sdp file. giving it to rtspsrc\n");
5388                                 data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
5389                         }
5390                         else
5391                         {
5392                         data->uri_type = MM_PLAYER_URI_TYPE_FILE;
5393                         }
5394                         ret = TRUE;
5395                 }
5396                 else
5397                 {
5398                         debug_warning("could  access %s.\n", path);
5399                 }
5400         }
5401         else if ((path = strstr(uri, "buff://")))
5402         {
5403                         data->uri_type = MM_PLAYER_URI_TYPE_BUFF;
5404                         ret = TRUE;
5405         }
5406         else if ((path = strstr(uri, "rtsp://")))
5407         {
5408                 if (strlen(path)) {
5409                         strcpy(data->uri, uri);
5410                         data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
5411                         ret = TRUE;
5412                 }
5413         }
5414         else if ((path = strstr(uri, "http://")))
5415         {
5416                 if (strlen(path)) {
5417                         strcpy(data->uri, uri);
5418                                 data->uri_type = MM_PLAYER_URI_TYPE_URL_HTTP;
5419
5420                         ret = TRUE;
5421                 }
5422         }
5423         else if ((path = strstr(uri, "https://")))
5424         {
5425                 if (strlen(path)) {
5426                         strcpy(data->uri, uri);
5427                                 data->uri_type = MM_PLAYER_URI_TYPE_URL_HTTP;
5428                         
5429                         ret = TRUE;
5430                 }
5431         }
5432         else if ((path = strstr(uri, "rtspu://")))
5433         {
5434                 if (strlen(path)) {
5435                         strcpy(data->uri, uri);
5436                         data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
5437                         ret = TRUE;
5438                 }
5439         }
5440         else if ((path = strstr(uri, "rtspr://")))
5441         {
5442                 strcpy(data->uri, path);
5443                 char *separater =strstr(path, "*");
5444
5445                 if (separater) {
5446                         int urgent_len = 0;
5447                         char *urgent = separater + strlen("*");
5448
5449                         if ((urgent_len = strlen(urgent))) {
5450                                 data->uri[strlen(path) - urgent_len - strlen("*")] = '\0';
5451                                 strcpy(data->urgent, urgent);
5452                                 data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
5453                                 ret = TRUE;
5454                         }
5455                 }
5456         }
5457         else if ((path = strstr(uri, "mms://")))
5458         {
5459                 if (strlen(path)) {
5460                         strcpy(data->uri, uri);
5461                         data->uri_type = MM_PLAYER_URI_TYPE_URL_MMS;
5462                         ret = TRUE;
5463                 }
5464         }
5465         else if ((path = strstr(uri, "mem://")))
5466         {
5467                 if (strlen(path)) {
5468                         int mem_size = 0;
5469                         char *buffer = NULL;
5470                         char *seperator = strchr(path, ',');
5471                         char ext[100] = {0,}, size[100] = {0,};
5472
5473                         if (seperator) {
5474                                 if ((buffer = strstr(path, "ext="))) {
5475                                         buffer += strlen("ext=");
5476
5477                                         if (strlen(buffer)) {
5478                                                 strcpy(ext, buffer);
5479
5480                                                 if ((seperator = strchr(ext, ','))
5481                                                         || (seperator = strchr(ext, ' '))
5482                                                         || (seperator = strchr(ext, '\0'))) {
5483                                                         seperator[0] = '\0';
5484                                                 }
5485                                         }
5486                                 }
5487
5488                                 if ((buffer = strstr(path, "size="))) {
5489                                         buffer += strlen("size=");
5490
5491                                         if (strlen(buffer) > 0) {
5492                                                 strcpy(size, buffer);
5493
5494                                                 if ((seperator = strchr(size, ','))
5495                                                         || (seperator = strchr(size, ' '))
5496                                                         || (seperator = strchr(size, '\0'))) {
5497                                                         seperator[0] = '\0';
5498                                                 }
5499
5500                                                 mem_size = atoi(size);
5501                                         }
5502                                 }
5503                         }
5504
5505                         debug_log("ext: %s, mem_size: %d, mmap(param): %p\n", ext, mem_size, param);
5506                         if ( mem_size && param) {
5507                                         data->mem = param;
5508                                         data->mem_size = mem_size;
5509                                 data->uri_type = MM_PLAYER_URI_TYPE_MEM;
5510                                 ret = TRUE;
5511                         }
5512                 }
5513         }
5514         else
5515         {
5516                 /* if no protocol prefix exist. check file existence and then give file:// as it's prefix */
5517                 if (util_exist_file_path(uri))
5518                 {
5519                         debug_warning("uri has no protocol-prefix. giving 'file://' by default.\n");
5520                         g_snprintf(data->uri,  MM_MAX_URL_LEN, "file://%s", uri);
5521
5522                         if ( util_is_sdp_file( (char*)uri ) )
5523                         {
5524                                 debug_log("uri is actually a file but it's sdp file. giving it to rtspsrc\n");
5525                                 data->uri_type = MM_PLAYER_URI_TYPE_URL_RTSP;
5526                         }
5527                         else
5528                         {
5529                                 data->uri_type = MM_PLAYER_URI_TYPE_FILE;
5530                         }
5531                         ret = TRUE;
5532                 }
5533                 else
5534                 {
5535                         debug_error ("invalid uri, could not play..\n");
5536                         data->uri_type = MM_PLAYER_URI_TYPE_NONE;
5537                 }
5538         }
5539         
5540         if (data->uri_type == MM_PLAYER_URI_TYPE_NONE) {
5541                 ret = FALSE;
5542         }
5543
5544         /* dump parse result */
5545         debug_log("profile parsing result ---\n");
5546         debug_log("incomming uri : %s\n", uri);
5547         debug_log("uri : %s\n", data->uri);
5548         debug_log("uri_type : %d\n", data->uri_type);
5549         debug_log("play_mode : %d\n", data->play_mode);
5550         debug_log("mem : 0x%x\n", (guint)data->mem);
5551         debug_log("mem_size : %d\n", data->mem_size);
5552         debug_log("urgent : %s\n", data->urgent);
5553         debug_log("--------------------------\n");
5554
5555         debug_fleave();
5556
5557         return ret;
5558 }
5559
5560 gboolean _asm_postmsg(gpointer *data)
5561 {
5562         mm_player_t* player = (mm_player_t*)data;
5563         MMMessageParamType msg = {0, };
5564
5565         debug_fenter();
5566
5567         return_val_if_fail ( player, FALSE );
5568
5569         msg.union_type = MM_MSG_UNION_CODE;
5570         msg.code = player->sm.event_src;
5571         
5572         MMPLAYER_POST_MSG( player, MM_MESSAGE_READY_TO_RESUME, &msg);
5573         
5574         return FALSE;
5575 }
5576 gboolean _asm_lazy_pause(gpointer *data)
5577 {
5578         mm_player_t* player = (mm_player_t*)data;
5579         int ret = MM_ERROR_NONE;
5580
5581         debug_fenter();
5582
5583         return_val_if_fail ( player, FALSE );
5584
5585         if (MMPLAYER_CURRENT_STATE(player) == MM_PLAYER_STATE_PLAYING)
5586         {
5587                 debug_log ("Ready to proceed lazy pause\n");
5588                 ret = _mmplayer_pause((MMHandleType)player);
5589                 if(MM_ERROR_NONE != ret)
5590                 {
5591                         debug_error("MMPlayer pause failed in ASM callback lazy pause\n");
5592                 }       
5593         }
5594         else
5595         {
5596                 debug_log ("Invalid state to proceed lazy pause\n");
5597         }
5598
5599         /* unset mute */
5600         if (player->pipeline && player->pipeline->audiobin)
5601                 g_object_set(G_OBJECT(player->pipeline->audiobin[MMPLAYER_A_SINK].gst), "mute", 0, NULL);
5602
5603         player->sm.by_asm_cb = 0; //should be reset here
5604
5605         debug_fleave();
5606
5607         return FALSE;
5608 }
5609 ASM_cb_result_t
5610 __mmplayer_asm_callback(int handle, ASM_event_sources_t event_src, ASM_sound_commands_t command, unsigned int sound_status, void* cb_data)
5611 {
5612         mm_player_t* player = (mm_player_t*) cb_data;
5613         ASM_cb_result_t cb_res = ASM_CB_RES_IGNORE;
5614         int result = MM_ERROR_NONE;
5615         gboolean lazy_pause = FALSE;
5616
5617         debug_fenter();
5618
5619         return_val_if_fail ( player && player->pipeline, ASM_CB_RES_IGNORE );
5620         return_val_if_fail ( player->attrs, MM_ERROR_PLAYER_INTERNAL );
5621
5622         if (player->is_sound_extraction)
5623         {
5624                 debug_log("sound extraction is working...so, asm command is ignored.\n");
5625                 return result;
5626         }
5627         
5628         player->sm.by_asm_cb = 1; // it should be enabled for player state transition with called application command
5629         player->sm.event_src = event_src;
5630
5631         if(event_src == ASM_EVENT_SOURCE_OTHER_PLAYER_APP)
5632         {
5633                 player->sm.event_src = ASM_EVENT_SOURCE_OTHER_APP;
5634         }
5635         else if(event_src == ASM_EVENT_SOURCE_EARJACK_UNPLUG )
5636         {
5637                 int stop_by_asm = 0;
5638
5639                 mm_attrs_get_int_by_name(player->attrs, "sound_stop_when_unplugged", &stop_by_asm);
5640                 if (!stop_by_asm)
5641                         return cb_res;
5642         }
5643         else if (event_src == ASM_EVENT_SOURCE_RESOURCE_CONFLICT)
5644         {
5645                 /* can use video overlay simultaneously */
5646                 /* video resource conflict */
5647                 if(player->pipeline->videobin) 
5648                 {
5649                         if (PLAYER_INI()->multiple_codec_supported)
5650                         {
5651                                 debug_log("video conflict but, can support to use video overlay simultaneously");
5652                                 result = _mmplayer_pause((MMHandleType)player);
5653                                 cb_res = ASM_CB_RES_PAUSE;
5654                         }
5655                         else
5656                         {
5657                                 debug_log("video conflict, can't support for multiple codec instance");
5658                                 result = _mmplayer_unrealize((MMHandleType)player);
5659                                 cb_res = ASM_CB_RES_STOP;
5660                         }
5661                 }
5662                 return cb_res;
5663         }
5664
5665         switch(command)
5666         {
5667                 case ASM_COMMAND_PLAY:
5668                 case ASM_COMMAND_STOP:
5669                         debug_warning ("Got unexpected asm command (%d)", command);
5670                 break;
5671                         
5672                 case ASM_COMMAND_PAUSE:
5673                 {
5674                         debug_log("Got msg from asm to Pause");
5675                         
5676                         if(event_src == ASM_EVENT_SOURCE_CALL_START
5677                                 || event_src == ASM_EVENT_SOURCE_ALARM_START
5678                                 || event_src == ASM_EVENT_SOURCE_OTHER_APP)
5679                         {
5680                                 //hold 0.7 second to excute "fadedown mute" effect
5681                                 debug_log ("do fade down->pause->undo fade down");
5682                                         
5683                                 __mmplayer_do_sound_fadedown(player, MM_PLAYER_FADEOUT_TIME_DEFAULT);
5684                                         
5685                                 result = _mmplayer_pause((MMHandleType)player);
5686                                 if (result != MM_ERROR_NONE)
5687                                 {
5688                                         debug_warning("fail to set Pause state by asm");
5689                                         cb_res = ASM_CB_RES_IGNORE;
5690                                         break;
5691                                 }
5692                                 __mmplayer_undo_sound_fadedown(player);
5693                         }
5694                         else if(event_src == ASM_EVENT_SOURCE_OTHER_PLAYER_APP)
5695                         {
5696                                 lazy_pause = TRUE; // return as soon as possible, for fast start of other app
5697
5698                                 if ( player->pipeline->audiobin && player->pipeline->audiobin[MMPLAYER_A_SINK].gst )
5699                                         g_object_set( player->pipeline->audiobin[MMPLAYER_A_SINK].gst, "mute", 2, NULL);
5700
5701                                 player->lazy_pause_event_id = g_timeout_add(LAZY_PAUSE_TIMEOUT_MSEC, (GSourceFunc)_asm_lazy_pause, (gpointer)player);
5702                                 debug_log ("set lazy pause timer (id=[%d], timeout=[%d ms])", player->lazy_pause_event_id, LAZY_PAUSE_TIMEOUT_MSEC);
5703                         }
5704                         else
5705                         {
5706                                 //immediate pause
5707                                 debug_log ("immediate pause");
5708                                 result = _mmplayer_pause((MMHandleType)player);
5709                         }
5710                         cb_res = ASM_CB_RES_PAUSE;
5711                 }
5712                 break;
5713                         
5714                 case ASM_COMMAND_RESUME:
5715                 {
5716                         debug_log("Got msg from asm to Resume. So, application can resume. code (%d) \n", event_src);
5717                         player->sm.by_asm_cb = 0;
5718                         //ASM server is single thread daemon. So use g_idle_add() to post resume msg
5719                         g_idle_add((GSourceFunc)_asm_postmsg, (gpointer)player);
5720                         cb_res = ASM_CB_RES_IGNORE;
5721                 }
5722                 break;
5723
5724                 default:
5725                 break;
5726         }
5727
5728         if (!lazy_pause)
5729                 player->sm.by_asm_cb = 0;
5730
5731         debug_fleave();
5732
5733         return cb_res;
5734 }
5735
5736 int
5737 _mmplayer_create_player(MMHandleType handle) // @
5738 {
5739         mm_player_t* player = MM_PLAYER_CAST(handle);
5740         gint i;
5741
5742         debug_fenter();
5743
5744         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
5745
5746         MMTA_ACUM_ITEM_BEGIN("[KPI] media player service create->playing", FALSE);
5747
5748         /* initialize player state */
5749         MMPLAYER_CURRENT_STATE(player) = MM_PLAYER_STATE_NONE;
5750         MMPLAYER_PREV_STATE(player) = MM_PLAYER_STATE_NONE;
5751         MMPLAYER_PENDING_STATE(player) = MM_PLAYER_STATE_NONE;
5752         MMPLAYER_TARGET_STATE(player) = MM_PLAYER_STATE_NONE;
5753
5754         /* check current state */
5755         MMPLAYER_CHECK_STATE_RETURN_IF_FAIL ( player, MMPLAYER_COMMAND_CREATE );
5756
5757         /* construct attributes */
5758         player->attrs = _mmplayer_construct_attribute(handle);
5759
5760         if ( !player->attrs )
5761         {
5762                 debug_critical("Failed to construct attributes\n");
5763                 goto ERROR;
5764         }
5765
5766         /* initialize gstreamer with configured parameter */
5767         if ( ! __mmplayer_gstreamer_init() )
5768         {
5769                 debug_critical("Initializing gstreamer failed\n");
5770                 goto ERROR;
5771         }
5772
5773         /* initialize factories if not using decodebin */
5774         if ( FALSE == PLAYER_INI()->use_decodebin )
5775         {
5776                 if( player->factories == NULL )
5777                     __mmplayer_init_factories(player);
5778         }
5779
5780         /* create lock. note that g_tread_init() has already called in gst_init() */
5781         player->fsink_lock = g_mutex_new();
5782         if ( ! player->fsink_lock )
5783         {
5784                 debug_critical("Cannot create mutex for command lock\n");
5785                 goto ERROR;
5786         }
5787
5788         /* create repeat mutex */
5789         player->repeat_thread_mutex = g_mutex_new();
5790         if ( ! player->repeat_thread_mutex )
5791         {
5792                 debug_critical("Cannot create repeat mutex\n");
5793                 goto ERROR;
5794         }
5795
5796         /* create repeat cond */
5797         player->repeat_thread_cond = g_cond_new();
5798         if ( ! player->repeat_thread_cond )
5799         {
5800                 debug_critical("Cannot create repeat cond\n");
5801                 goto ERROR;
5802         }
5803
5804         /* create repeat thread */
5805         player->repeat_thread =
5806                 g_thread_create (__mmplayer_repeat_thread, (gpointer)player, TRUE, NULL);
5807         if ( ! player->repeat_thread )
5808         {
5809                 goto ERROR;
5810         }
5811
5812         if ( MM_ERROR_NONE != _mmplayer_initialize_video_capture(player))
5813         {
5814                 debug_error("failed to initialize video capture\n");
5815                 goto ERROR;
5816         }
5817
5818         /* register to asm */
5819         if ( MM_ERROR_NONE != _mmplayer_asm_register(&player->sm, (ASM_sound_cb_t)__mmplayer_asm_callback, (void*)player) )
5820         {
5821                 /* NOTE : we are dealing it as an error since we cannot expect it's behavior */
5822                 debug_error("failed to register asm server\n");
5823                 return MM_ERROR_POLICY_INTERNAL;
5824         }
5825
5826         if (MMPLAYER_IS_HTTP_PD(player))
5827         {
5828                 player->pd_downloader = NULL;
5829                 player->pd_file_save_path = NULL;
5830         }
5831
5832         /* give default value of sound effect setting */
5833         player->bypass_sound_effect = TRUE;
5834         player->sound.volume = MM_VOLUME_FACTOR_DEFAULT;
5835         player->playback_rate = DEFAULT_PLAYBACK_RATE;
5836         player->no_more_pad = TRUE;
5837
5838         /* set player state to null */
5839         MMPLAYER_STATE_CHANGE_TIMEOUT(player) = PLAYER_INI()->localplayback_state_change_timeout;
5840         MMPLAYER_SET_STATE ( player, MM_PLAYER_STATE_NULL );
5841
5842         debug_fleave();
5843         return MM_ERROR_NONE;
5844
5845 ERROR:
5846         /* free lock */
5847         if ( player->fsink_lock )
5848                 g_mutex_free( player->fsink_lock );
5849         player->fsink_lock = NULL;
5850
5851         /* free thread */
5852         if ( player->repeat_thread_cond &&
5853                  player->repeat_thread_mutex &&
5854                  player->repeat_thread )
5855         {
5856                 player->repeat_thread_exit = TRUE;
5857                 g_cond_signal( player->repeat_thread_cond );
5858
5859                 g_thread_join( player->repeat_thread );
5860                 player->repeat_thread = NULL;
5861
5862                 g_mutex_free ( player->repeat_thread_mutex );
5863                 player->repeat_thread_mutex = NULL;
5864
5865                 g_cond_free ( player->repeat_thread_cond );
5866                 player->repeat_thread_cond = NULL;
5867         }
5868         /* clear repeat thread mutex/cond if still alive
5869          * this can happen if only thread creating has failed
5870          */
5871         if ( player->repeat_thread_mutex )
5872                 g_mutex_free ( player->repeat_thread_mutex );
5873
5874         if ( player->repeat_thread_cond )
5875                 g_cond_free ( player->repeat_thread_cond );
5876
5877         /* release attributes */
5878         _mmplayer_deconstruct_attribute(handle);
5879
5880         return MM_ERROR_PLAYER_INTERNAL;
5881 }
5882
5883 static gboolean
5884 __mmplayer_gstreamer_init(void) // @
5885 {
5886         static gboolean initialized = FALSE;
5887         static const int max_argc = 50;
5888         gint* argc = NULL;
5889         gchar** argv = NULL;
5890         GError *err = NULL;
5891         int i = 0;
5892
5893         debug_fenter();
5894
5895         if ( initialized )
5896         {
5897                 debug_log("gstreamer already initialized.\n");
5898                 return TRUE;
5899         }
5900
5901         /* alloc */
5902         argc = malloc( sizeof(int) );
5903         argv = malloc( sizeof(gchar*) * max_argc );
5904
5905         if ( !argc || !argv )
5906                 goto ERROR;
5907
5908         memset( argv, 0, sizeof(gchar*) * max_argc );
5909
5910         /* add initial */
5911         *argc = 1;
5912         argv[0] = g_strdup( "mmplayer" );
5913
5914         /* add gst_param */
5915         for ( i = 0; i < 5; i++ ) /* FIXIT : num of param is now fixed to 5. make it dynamic */
5916         {
5917                 if ( strlen( PLAYER_INI()->gst_param[i] ) > 0 )
5918                 {
5919                         argv[*argc] = g_strdup( PLAYER_INI()->gst_param[i] );
5920                         (*argc)++;
5921                 }
5922         }
5923
5924         /* we would not do fork for scanning plugins */
5925         argv[*argc] = g_strdup("--gst-disable-registry-fork");
5926         (*argc)++;
5927
5928         /* check disable registry scan */
5929         if ( PLAYER_INI()->skip_rescan )
5930         {
5931                 argv[*argc] = g_strdup("--gst-disable-registry-update");
5932                 (*argc)++;
5933         }
5934
5935         /* check disable segtrap */
5936         if ( PLAYER_INI()->disable_segtrap )
5937         {
5938                 argv[*argc] = g_strdup("--gst-disable-segtrap");
5939                 (*argc)++;
5940         }
5941
5942         debug_log("initializing gstreamer with following parameter\n");
5943         debug_log("argc : %d\n", *argc);
5944
5945         for ( i = 0; i < *argc; i++ )
5946         {
5947                 debug_log("argv[%d] : %s\n", i, argv[i]);
5948         }
5949
5950
5951         /* initializing gstreamer */
5952         __ta__("gst_init time",
5953
5954                 if ( ! gst_init_check (argc, &argv, &err))
5955                 {
5956                         debug_error("Could not initialize GStreamer: %s\n", err ? err->message : "unknown error occurred");
5957                         if (err)
5958                         {
5959                                 g_error_free (err);
5960                         }
5961
5962                         goto ERROR;
5963                 }
5964         );
5965
5966         /* release */
5967         for ( i = 0; i < *argc; i++ )
5968         {
5969                 MMPLAYER_FREEIF( argv[i] );
5970         }
5971
5972         MMPLAYER_FREEIF( argv );
5973         MMPLAYER_FREEIF( argc );
5974
5975         /* done */
5976         initialized = TRUE;
5977
5978         debug_fleave();
5979
5980         return TRUE;
5981
5982 ERROR:
5983
5984         MMPLAYER_FREEIF( argv );
5985         MMPLAYER_FREEIF( argc );
5986
5987         return FALSE;
5988 }
5989
5990 int 
5991 __mmplayer_destroy_streaming_ext(mm_player_t* player)
5992 {
5993         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
5994
5995         if (player->pd_downloader)
5996                 _mmplayer_unrealize_pd_downloader((MMHandleType)player);
5997
5998         if (MMPLAYER_IS_HTTP_PD(player))
5999                 _mmplayer_destroy_pd_downloader((MMHandleType)player);
6000
6001        if (MMPLAYER_IS_STREAMING(player))
6002        {
6003                 if (player->streamer)
6004                 {
6005                         __mm_player_streaming_deinitialize (player->streamer);
6006                         __mm_player_streaming_destroy(player->streamer);
6007                         player->streamer = NULL;
6008                 }
6009        }
6010 }
6011
6012 int
6013 _mmplayer_destroy(MMHandleType handle) // @
6014 {
6015         mm_player_t* player = MM_PLAYER_CAST(handle);
6016
6017         debug_fenter();
6018
6019         /* check player handle */
6020         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
6021
6022         /* destroy can called at anytime */
6023         MMPLAYER_CHECK_STATE_RETURN_IF_FAIL ( player, MMPLAYER_COMMAND_DESTROY );
6024
6025         __mmplayer_destroy_streaming_ext(player);
6026
6027         /* release repeat thread */
6028         if ( player->repeat_thread_cond &&
6029                  player->repeat_thread_mutex &&
6030                  player->repeat_thread )
6031         {
6032                 player->repeat_thread_exit = TRUE;
6033                 g_cond_signal( player->repeat_thread_cond );
6034
6035                 debug_log("waitting for repeat thread exit\n");
6036                 g_thread_join ( player->repeat_thread );
6037                 g_mutex_free ( player->repeat_thread_mutex );
6038                 g_cond_free ( player->repeat_thread_cond );
6039                 debug_log("repeat thread released\n");
6040         }
6041
6042         if (MM_ERROR_NONE != _mmplayer_release_video_capture(player))
6043         {
6044                 debug_error("failed to release video capture\n");
6045                 return MM_ERROR_PLAYER_INTERNAL;
6046         }
6047
6048         /* withdraw asm */
6049         if ( MM_ERROR_NONE != _mmplayer_asm_deregister(&player->sm) )
6050         {
6051                 debug_error("failed to deregister asm server\n");
6052                 return MM_ERROR_PLAYER_INTERNAL;
6053         }
6054
6055         /* release pipeline */
6056         if ( MM_ERROR_NONE != __mmplayer_gst_destroy_pipeline( player ) )
6057         {
6058                 debug_error("failed to destory pipeline\n");
6059                 return MM_ERROR_PLAYER_INTERNAL;
6060         }
6061
6062         /* release attributes */
6063         _mmplayer_deconstruct_attribute( handle );
6064
6065         /* release factories */
6066         __mmplayer_release_factories( player );
6067
6068         /* release lock */
6069         if ( player->fsink_lock )
6070                 g_mutex_free( player->fsink_lock );
6071
6072         if ( player->msg_cb_lock )
6073                 g_mutex_free( player->msg_cb_lock );
6074
6075         if (player->lazy_pause_event_id) 
6076         {
6077                 g_source_remove (player->lazy_pause_event_id);
6078                 player->lazy_pause_event_id = 0;
6079         }
6080
6081         debug_fleave();
6082
6083         return MM_ERROR_NONE;
6084 }
6085
6086 int 
6087 __mmplayer_realize_streaming_ext(mm_player_t* player)
6088 {
6089         int ret = MM_ERROR_NONE;
6090
6091         debug_fenter();
6092         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
6093
6094         if (MMPLAYER_IS_HTTP_PD(player))
6095         {
6096                 gboolean bret = FALSE;
6097
6098                 player->pd_downloader = _mmplayer_create_pd_downloader();
6099                 if ( !player->pd_downloader )
6100                 {
6101                         debug_error ("Unable to create PD Downloader...");
6102                         ret = MM_ERROR_PLAYER_NO_FREE_SPACE;
6103                 }
6104
6105                 bret = _mmplayer_realize_pd_downloader((MMHandleType)player, player->profile.uri, player->pd_file_save_path, player->pipeline->mainbin[MMPLAYER_M_SRC].gst);
6106                 
6107                 if (FALSE == bret)
6108                 {
6109                         debug_error ("Unable to create PD Downloader...");
6110                         ret = MM_ERROR_PLAYER_NOT_INITIALIZED;
6111                 }
6112         }
6113
6114         debug_fleave();
6115         return ret;
6116 }
6117
6118 int
6119 _mmplayer_realize(MMHandleType hplayer) // @
6120 {
6121         mm_player_t* player =  (mm_player_t*)hplayer;
6122         char *uri =NULL;
6123         void *param = NULL;
6124         int application_pid = -1;
6125         gboolean update_registry = FALSE;
6126         MMHandleType attrs = 0;
6127         int ret = MM_ERROR_NONE;
6128
6129         debug_fenter();
6130
6131         /* check player handle */
6132         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED )
6133
6134         /* check current state */
6135         MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_REALIZE );
6136
6137         attrs = MMPLAYER_GET_ATTRS(player);
6138         if ( !attrs )
6139         {
6140                 debug_error("fail to get attributes.\n");
6141                 return MM_ERROR_PLAYER_INTERNAL;
6142         }
6143
6144         mm_attrs_get_int_by_name(attrs, "sound_application_pid", &application_pid );
6145         player->sm.pid = application_pid;
6146
6147         mm_attrs_get_string_by_name(attrs, "profile_uri", &uri);
6148         mm_attrs_get_data_by_name(attrs, "profile_user_param", &param);
6149
6150         if (! __mmfplayer_parse_profile((const char*)uri, param, &player->profile) )
6151         {
6152                 debug_error("failed to parse profile\n");
6153                 return MM_ERROR_PLAYER_INVALID_URI;
6154         }
6155
6156         /* FIXIT : we can use thouse in player->profile directly */
6157         if (player->profile.uri_type == MM_PLAYER_URI_TYPE_MEM)
6158         {
6159                 player->mem_buf.buf = (char *)player->profile.mem;
6160                 player->mem_buf.len = player->profile.mem_size;
6161                 player->mem_buf.offset = 0;
6162         }
6163
6164         if (player->profile.uri_type == MM_PLAYER_URI_TYPE_URL_MMS)
6165         {
6166                 debug_warning("mms protocol is not supported format.\n");
6167                 return MM_ERROR_PLAYER_NOT_SUPPORTED_FORMAT;
6168         }
6169
6170         if (MMPLAYER_IS_STREAMING(player))
6171                 MMPLAYER_STATE_CHANGE_TIMEOUT(player) = PLAYER_INI()->live_state_change_timeout;
6172         else
6173                 MMPLAYER_STATE_CHANGE_TIMEOUT(player) = PLAYER_INI()->localplayback_state_change_timeout;
6174
6175         player->videodec_linked  = 0;
6176         player->videosink_linked = 0;
6177         player->audiodec_linked  = 0;
6178         player->audiosink_linked = 0;
6179         player->textsink_linked = 0;
6180
6181         /* set the subtitle ON default */
6182         player->is_subtitle_off = FALSE;
6183
6184         /* we need to update content attrs only the content has changed */
6185         player->need_update_content_attrs = TRUE;
6186         player->need_update_content_dur = FALSE;
6187
6188         /* registry should be updated for downloadable codec */
6189         mm_attrs_get_int_by_name(attrs, "profile_update_registry", &update_registry);
6190
6191         if ( update_registry )
6192         {
6193                 debug_log("updating registry...\n");
6194                 gst_update_registry();
6195
6196                 /* then we have to rebuild factories */
6197                 __mmplayer_release_factories( player );
6198                 __mmplayer_init_factories(player);
6199         }
6200
6201         /* realize pipeline */
6202         ret = __gst_realize( player );
6203         if ( ret != MM_ERROR_NONE )
6204         {
6205                 debug_error("fail to realize the player.\n");
6206         }
6207         else
6208         {
6209                 __mmplayer_realize_streaming_ext(player);
6210         }
6211
6212         debug_fleave();
6213
6214         return ret;
6215 }
6216
6217 int
6218 __mmplayer_unrealize_streaming_ext(mm_player_t *player)
6219 {
6220         debug_fenter();
6221         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
6222         
6223         /* destroy can called at anytime */
6224         if (player->pd_downloader && MMPLAYER_IS_HTTP_PD(player))
6225         {
6226                 _mmplayer_unrealize_pd_downloader ((MMHandleType)player);
6227                 player->pd_downloader = NULL;
6228         }
6229
6230         debug_fleave();
6231         return MM_ERROR_NONE;
6232 }
6233
6234 int
6235 _mmplayer_unrealize(MMHandleType hplayer) // @
6236 {
6237         mm_player_t* player = (mm_player_t*)hplayer;
6238         int ret = MM_ERROR_NONE;
6239
6240         debug_fenter();
6241
6242         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED )
6243
6244         /* check current state */
6245         MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_UNREALIZE );
6246
6247         __mmplayer_unrealize_streaming_ext(player);
6248
6249         /* unrealize pipeline */
6250         ret = __gst_unrealize( player );
6251
6252         /* set player state if success */
6253         if ( MM_ERROR_NONE == ret )
6254         {
6255                 ret = _mmplayer_asm_set_state(hplayer, ASM_STATE_STOP);
6256                 if ( ret )
6257                 {
6258                         debug_error("failed to set asm state to STOP\n");
6259                         return ret;
6260                 }
6261         }
6262
6263         debug_fleave();
6264
6265         return ret;
6266 }
6267
6268 int
6269 _mmplayer_set_message_callback(MMHandleType hplayer, MMMessageCallback callback, gpointer user_param) // @
6270 {
6271         mm_player_t* player = (mm_player_t*)hplayer;
6272
6273         return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
6274
6275         return __gst_set_message_callback(player, callback, user_param);
6276 }
6277
6278 int
6279 _mmplayer_get_state(MMHandleType hplayer, int* state) // @
6280 {
6281         mm_player_t *player = (mm_player_t*)hplayer;
6282
6283         return_val_if_fail(state, MM_ERROR_INVALID_ARGUMENT);
6284
6285         *state = MMPLAYER_CURRENT_STATE(player);
6286
6287         return MM_ERROR_NONE;
6288 }
6289
6290
6291 int
6292 _mmplayer_set_volume(MMHandleType hplayer, MMPlayerVolumeType volume) // @
6293 {
6294         mm_player_t* player = (mm_player_t*) hplayer;
6295         GstElement* vol_element = NULL;
6296         int i = 0;
6297
6298         debug_fenter();
6299
6300         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
6301
6302         debug_log("volume [L]=%f:[R]=%f\n", 
6303                 volume.level[MM_VOLUME_CHANNEL_LEFT], volume.level[MM_VOLUME_CHANNEL_RIGHT]);
6304
6305         /* invalid factor range or not */
6306         for ( i = 0; i < MM_VOLUME_CHANNEL_NUM; i++ )
6307         {
6308                 if (volume.level[i] < MM_VOLUME_FACTOR_MIN || volume.level[i] > MM_VOLUME_FACTOR_MAX) {
6309                         debug_error("Invalid factor! (valid factor:0~1.0)\n");
6310                         return MM_ERROR_INVALID_ARGUMENT;
6311                 }
6312         }
6313
6314         /* Save volume to handle. Currently the first array element will be saved. */
6315         player->sound.volume = volume.level[0];
6316
6317         /* check pipeline handle */
6318         if ( ! player->pipeline || ! player->pipeline->audiobin )
6319         {
6320                 debug_log("audiobin is not created yet\n");
6321                 debug_log("but, current stored volume will be set when it's created.\n");
6322
6323                 /* NOTE : stored volume will be used in create_audiobin
6324                  * returning MM_ERROR_NONE here makes application to able to
6325                  * set volume at anytime.
6326                  */
6327                 return MM_ERROR_NONE;
6328         }
6329
6330         /* setting volume to volume element */
6331         vol_element = player->pipeline->audiobin[MMPLAYER_A_VOL].gst;
6332
6333         if ( vol_element )
6334         {
6335                 debug_log("volume is set [%f]\n", player->sound.volume);
6336                 g_object_set(vol_element, "volume", player->sound.volume, NULL);
6337         }
6338
6339         debug_fleave();
6340
6341         return MM_ERROR_NONE;
6342 }
6343
6344
6345 int
6346 _mmplayer_get_volume(MMHandleType hplayer, MMPlayerVolumeType* volume)
6347 {
6348         mm_player_t* player = (mm_player_t*) hplayer;
6349         int i = 0;
6350
6351         debug_fenter();
6352
6353         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
6354         return_val_if_fail( volume, MM_ERROR_INVALID_ARGUMENT );
6355
6356         /* returning stored volume */
6357         for (i = 0; i < MM_VOLUME_CHANNEL_NUM; i++)
6358                 volume->level[i] = player->sound.volume;
6359
6360         debug_fleave();
6361
6362         return MM_ERROR_NONE;
6363 }
6364
6365
6366
6367 int
6368 _mmplayer_set_mute(MMHandleType hplayer, int mute) // @
6369 {
6370         mm_player_t* player = (mm_player_t*) hplayer;
6371         GstElement* vol_element = NULL;
6372
6373         debug_fenter();
6374
6375         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
6376
6377         debug_log("mute : %d\n", mute);
6378
6379         /* mute value shoud 0 or 1 */
6380         if ( mute != 0 && mute != 1 )
6381         {
6382                 debug_error("bad mute value\n");
6383
6384                 /* FIXIT : definitly, we need _BAD_PARAM error code */
6385                 return MM_ERROR_INVALID_ARGUMENT;
6386         }
6387
6388
6389         /* just hold mute value if pipeline is not ready */
6390         if ( !player->pipeline || !player->pipeline->audiobin )
6391         {
6392                 debug_log("pipeline is not ready. holding mute value\n");
6393                 player->sound.mute = mute;
6394                 return MM_ERROR_NONE;
6395         }
6396
6397
6398         vol_element = player->pipeline->audiobin[MMPLAYER_A_VOL].gst;
6399
6400         /* NOTE : volume will only created when the bt is enabled */
6401         if ( vol_element )
6402         {
6403                 g_object_set(vol_element, "mute", mute, NULL);
6404         }
6405         else
6406         {
6407                 debug_log("volume elemnet is not created. using volume in audiosink\n");
6408         }
6409
6410         player->sound.mute = mute;
6411
6412         debug_fleave();
6413
6414         return MM_ERROR_NONE;
6415 }
6416
6417 int
6418 _mmplayer_get_mute(MMHandleType hplayer, int* pmute) // @
6419 {
6420         mm_player_t* player = (mm_player_t*) hplayer;
6421         GstElement* vol_element = NULL;
6422
6423         debug_fenter();
6424
6425         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
6426         return_val_if_fail ( pmute, MM_ERROR_INVALID_ARGUMENT );
6427
6428         /* just hold mute value if pipeline is not ready */
6429         if ( !player->pipeline || !player->pipeline->audiobin )
6430         {
6431                 debug_log("pipeline is not ready. returning stored value\n");
6432                 *pmute = player->sound.mute;
6433                 return MM_ERROR_NONE;
6434         }
6435
6436
6437         vol_element = player->pipeline->audiobin[MMPLAYER_A_VOL].gst;
6438
6439         if ( vol_element )
6440         {
6441                 g_object_get(vol_element, "mute", pmute, NULL);
6442                 debug_log("mute=%d\n\n", *pmute);
6443         }
6444         else
6445         {
6446                 *pmute = player->sound.mute;
6447         }
6448
6449         debug_fleave();
6450
6451         return MM_ERROR_NONE;
6452 }
6453
6454 int
6455 _mmplayer_set_videostream_cb(MMHandleType hplayer, mm_player_video_stream_callback callback, void *user_param) // @
6456 {
6457         mm_player_t* player = (mm_player_t*) hplayer;
6458
6459         debug_fenter();
6460
6461         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
6462         return_val_if_fail ( callback, MM_ERROR_INVALID_ARGUMENT );
6463
6464         player->video_stream_cb = callback;
6465         player->video_stream_cb_user_param = user_param;
6466         player->use_video_stream = TRUE;
6467         debug_log("Stream cb Handle value is %p : %p\n", player, player->video_stream_cb);
6468
6469         debug_fleave();
6470
6471         return MM_ERROR_NONE;
6472 }
6473
6474 int
6475 _mmplayer_set_audiostream_cb(MMHandleType hplayer, mm_player_audio_stream_callback callback, void *user_param) // @
6476 {
6477         mm_player_t* player = (mm_player_t*) hplayer;
6478
6479         debug_fenter();
6480
6481         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
6482         return_val_if_fail(callback, MM_ERROR_INVALID_ARGUMENT);
6483
6484         player->audio_stream_cb = callback;
6485         player->audio_stream_cb_user_param = user_param;
6486         debug_log("Audio Stream cb Handle value is %p : %p\n", player, player->audio_stream_cb);
6487
6488         debug_fleave();
6489
6490         return MM_ERROR_NONE;
6491 }
6492
6493 int
6494 _mmplayer_set_audiobuffer_cb(MMHandleType hplayer, mm_player_audio_stream_callback callback, void *user_param) // @
6495 {
6496         mm_player_t* player = (mm_player_t*) hplayer;
6497
6498         debug_fenter();
6499
6500         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
6501         return_val_if_fail(callback, MM_ERROR_INVALID_ARGUMENT);
6502
6503         player->audio_buffer_cb = callback;
6504         player->audio_buffer_cb_user_param = user_param;
6505         debug_log("Audio Stream cb Handle value is %p : %p\n", player, player->audio_buffer_cb);
6506
6507         debug_fleave();
6508
6509         return MM_ERROR_NONE;
6510 }
6511
6512 int
6513 _mmplayer_set_buffer_need_data_cb(MMHandleType hplayer, mm_player_buffer_need_data_callback callback, void *user_param) // @
6514 {
6515         mm_player_t* player = (mm_player_t*) hplayer;
6516
6517         debug_fenter();
6518
6519         return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
6520         return_val_if_fail(callback, MM_ERROR_INVALID_ARGUMENT);
6521
6522         player->need_data_cb = callback;
6523         player->buffer_cb_user_param = user_param;
6524
6525         debug_log("buffer need dataHandle value is %p : %p\n", player, player->need_data_cb);
6526
6527         debug_fleave();
6528
6529         return MM_ERROR_NONE;
6530 }
6531
6532 int
6533 _mmplayer_set_buffer_enough_data_cb(MMHandleType hplayer, mm_player_buffer_enough_data_callback callback, void *user_param) // @
6534 {
6535         mm_player_t* player = (mm_player_t*) hplayer;
6536
6537         debug_fenter();
6538
6539         return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
6540         return_val_if_fail(callback, MM_ERROR_INVALID_ARGUMENT);
6541
6542         player->enough_data_cb = callback;
6543         player->buffer_cb_user_param = user_param;
6544
6545         debug_log("buffer enough data cb Handle value is %p : %p\n", player, player->enough_data_cb);
6546
6547         debug_fleave();
6548                 
6549         return MM_ERROR_NONE;
6550 }
6551
6552 int
6553 _mmplayer_set_buffer_seek_data_cb(MMHandleType hplayer, mm_player_buffer_seek_data_callback callback, void *user_param) // @
6554 {
6555         mm_player_t* player = (mm_player_t*) hplayer;
6556
6557         debug_fenter();
6558
6559         return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
6560         return_val_if_fail(callback, MM_ERROR_INVALID_ARGUMENT);
6561
6562         player->seek_data_cb = callback;
6563         player->buffer_cb_user_param = user_param;
6564
6565         debug_log("buffer seek data cb Handle value is %p : %p\n", player, player->seek_data_cb);
6566
6567         debug_fleave();
6568
6569         return MM_ERROR_NONE;
6570 }
6571
6572 int __mmplayer_start_streaming_ext(mm_player_t *player)
6573 {
6574         gint ret = MM_ERROR_NONE;
6575
6576         debug_fenter();
6577         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
6578
6579         if (MMPLAYER_IS_HTTP_PD(player))
6580         {
6581                 if ( !player->pd_downloader )
6582                 {
6583                         ret = __mmplayer_realize_streaming_ext(player);
6584
6585                         if ( ret != MM_ERROR_NONE)
6586                         {
6587                                 debug_error ("failed to realize streaming ext\n");
6588                                 return ret;
6589                         }
6590                 }
6591
6592                 if (player->pd_downloader && player->pd_mode == MM_PLAYER_PD_MODE_URI)
6593                 {
6594                         ret = _mmplayer_start_pd_downloader ((MMHandleType)player);
6595                         if ( !ret )
6596                         {
6597                                 debug_error ("ERROR while starting PD...\n");
6598                                 return MM_ERROR_PLAYER_NOT_INITIALIZED;
6599                         }
6600                         ret = MM_ERROR_NONE;
6601                 }
6602         }
6603
6604         debug_fleave();
6605         return ret;
6606 }
6607
6608 int
6609 _mmplayer_start(MMHandleType hplayer) // @
6610 {
6611         mm_player_t* player = (mm_player_t*) hplayer;
6612         gint ret = MM_ERROR_NONE;
6613         
6614         debug_fenter();
6615
6616         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
6617
6618         /* check current state */
6619         MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_START );
6620
6621         ret = _mmplayer_asm_set_state(hplayer, ASM_STATE_PLAYING);
6622         if ( ret != MM_ERROR_NONE )
6623         {
6624                 debug_error("failed to set asm state to PLAYING\n");
6625                 return ret;
6626         }
6627
6628         /* NOTE : we should check and create pipeline again if not created as we destroy
6629          * whole pipeline when stopping in streamming playback
6630          */
6631         if ( ! player->pipeline )
6632         {
6633                 ret = __gst_realize( player ); 
6634                 if ( MM_ERROR_NONE != ret )
6635                 {
6636                         debug_error("failed to realize before starting. only in streamming\n");
6637                         return ret;
6638                 }
6639         }
6640
6641         ret = __mmplayer_start_streaming_ext(player);
6642         if ( ret != MM_ERROR_NONE )
6643         {
6644                 debug_error("failed to start streaming ext \n");
6645         }
6646         
6647         /* start pipeline */
6648         ret = __gst_start( player );
6649         if ( ret != MM_ERROR_NONE )
6650         {
6651                 debug_error("failed to start player.\n");
6652         }
6653
6654         debug_fleave();
6655         
6656         return ret;
6657 }
6658
6659 /* NOTE: post "not supported codec message" to application
6660  * when one codec is not found during AUTOPLUGGING in MSL.
6661  * So, it's separated with error of __mmplayer_gst_callback().
6662  * And, if any codec is not found, don't send message here.
6663  * Because GST_ERROR_MESSAGE is posted by other plugin internally.
6664  */
6665 int
6666 __mmplayer_post_missed_plugin(mm_player_t* player)
6667 {
6668         MMMessageParamType msg_param;
6669         memset (&msg_param, 0, sizeof(MMMessageParamType));
6670         gboolean post_msg_direct = FALSE;
6671
6672         debug_fenter();
6673
6674         return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
6675
6676         debug_log("not_supported_codec = 0x%02x, can_support_codec = 0x%02x\n",
6677                         player->not_supported_codec, player->can_support_codec);
6678
6679         if( player->not_found_demuxer )
6680         {
6681                 msg_param.code = MM_ERROR_PLAYER_CODEC_NOT_FOUND;
6682                 msg_param.data = g_strdup_printf("%s", player->unlinked_demuxer_mime);
6683
6684                 MMPLAYER_POST_MSG( player, MM_MESSAGE_ERROR, &msg_param );
6685                 MMPLAYER_FREEIF(msg_param.data);
6686
6687                 return MM_ERROR_NONE;
6688         }
6689
6690         if (player->not_supported_codec)
6691         {
6692                 if ( player->can_support_codec ) // There is one codec to play
6693                 {
6694                         post_msg_direct = TRUE;
6695                 }
6696                 else
6697                 {
6698                         if ( player->pipeline->audiobin ) // Some content has only PCM data in container.
6699                                 post_msg_direct = TRUE;
6700                 }
6701
6702                 if ( post_msg_direct )
6703                 {
6704                         MMMessageParamType msg_param;
6705                         memset (&msg_param, 0, sizeof(MMMessageParamType));
6706
6707                         if ( player->not_supported_codec ==  MISSING_PLUGIN_AUDIO )
6708                         {
6709                                 debug_warning("not found AUDIO codec, posting error code to application.\n");
6710
6711                                 msg_param.code = MM_ERROR_PLAYER_AUDIO_CODEC_NOT_FOUND;
6712                                 msg_param.data = g_strdup_printf("%s", player->unlinked_audio_mime);
6713                         }
6714                         else if ( player->not_supported_codec ==  MISSING_PLUGIN_VIDEO )
6715                         {
6716                                 debug_warning("not found VIDEO codec, posting error code to application.\n");
6717
6718                                 msg_param.code = MM_ERROR_PLAYER_VIDEO_CODEC_NOT_FOUND;
6719                                 msg_param.data = g_strdup_printf("%s", player->unlinked_video_mime);
6720                         }
6721
6722                         MMPLAYER_POST_MSG( player, MM_MESSAGE_ERROR, &msg_param );
6723
6724                         MMPLAYER_FREEIF(msg_param.data);
6725
6726                         return MM_ERROR_NONE;
6727                 }
6728                 else // no any supported codec case 
6729                 {
6730                         debug_warning("not found any codec, posting error code to application.\n");
6731                         
6732                         if ( player->not_supported_codec ==  MISSING_PLUGIN_AUDIO )
6733                         {
6734                                 msg_param.code = MM_ERROR_PLAYER_AUDIO_CODEC_NOT_FOUND;
6735                                 msg_param.data = g_strdup_printf("%s", player->unlinked_audio_mime);
6736                         }
6737                         else
6738                         {
6739                                 msg_param.code = MM_ERROR_PLAYER_CODEC_NOT_FOUND;
6740                                 msg_param.data = g_strdup_printf("%s, %s", player->unlinked_video_mime, player->unlinked_audio_mime);
6741                         }
6742
6743                         MMPLAYER_POST_MSG( player, MM_MESSAGE_ERROR, &msg_param );
6744                         
6745                         MMPLAYER_FREEIF(msg_param.data);
6746                 }
6747         }
6748         
6749         debug_fleave();
6750
6751         return MM_ERROR_NONE;
6752 }
6753
6754 /* NOTE : it should be able to call 'stop' anytime*/
6755 int
6756 _mmplayer_stop(MMHandleType hplayer) // @
6757 {
6758         mm_player_t* player = (mm_player_t*)hplayer;
6759         int ret = MM_ERROR_NONE;
6760
6761         debug_fenter();
6762
6763         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
6764
6765         /* check current state */
6766         MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_STOP );
6767
6768         /* NOTE : application should not wait for EOS after calling STOP */
6769         __mmplayer_cancel_delayed_eos( player );
6770
6771         __mmplayer_unrealize_streaming_ext(player);
6772
6773         /* stop pipeline */
6774         ret = __gst_stop( player );
6775
6776         if ( ret != MM_ERROR_NONE )
6777         {
6778                 debug_error("failed to stop player.\n");
6779         }
6780
6781         debug_fleave();
6782
6783         return ret;
6784 }
6785
6786 int
6787 _mmplayer_pause(MMHandleType hplayer) // @
6788 {
6789         mm_player_t* player = (mm_player_t*)hplayer;
6790         GstFormat fmt = GST_FORMAT_TIME;
6791         gint64 pos_msec = 0;
6792         gboolean async = FALSE;
6793         gint ret = MM_ERROR_NONE;
6794
6795         debug_fenter();
6796
6797         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
6798
6799         /* check current state */
6800         MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_PAUSE );
6801
6802         switch (MMPLAYER_CURRENT_STATE(player))
6803         {
6804                 case MM_PLAYER_STATE_READY:
6805                 {
6806                         /* check prepare async or not.
6807                          * In the case of streaming playback, it's recommned to avoid blocking wait.
6808                          */
6809                         mm_attrs_get_int_by_name(player->attrs, "profile_prepare_async", &async);
6810                         debug_log("prepare mode : %s", (async ? "async" : "sync"));
6811
6812                         if (__mmplayer_start_streaming_ext(player) != MM_ERROR_NONE)
6813                                 return MM_ERROR_PLAYER_INTERNAL;
6814                 }
6815                 break;
6816
6817                 case MM_PLAYER_STATE_PLAYING:
6818                 {
6819                         /* NOTE : store current point to overcome some bad operation
6820                         * ( returning zero when getting current position in paused state) of some
6821                         * elements
6822                         */
6823                         ret = gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,        &fmt, &pos_msec);
6824                         if ( ! ret )
6825                         debug_warning("getting current position failed in paused\n");
6826
6827                         player->last_position = pos_msec;
6828                 }
6829                 break;
6830         }
6831
6832         /* pause pipeline */
6833         ret = __gst_pause( player, async );
6834
6835         if ( ret != MM_ERROR_NONE )
6836         {
6837                 debug_error("failed to pause player.\n");
6838         }
6839
6840         debug_fleave();
6841
6842         return ret;
6843 }
6844
6845 int
6846 _mmplayer_resume(MMHandleType hplayer)
6847 {
6848         mm_player_t* player = (mm_player_t*)hplayer;
6849         int ret = MM_ERROR_NONE;
6850
6851         debug_fenter();
6852
6853         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
6854
6855         ret = _mmplayer_asm_set_state(hplayer, ASM_STATE_PLAYING);
6856         if ( ret )
6857         {
6858                 debug_error("failed to set asm state to PLAYING\n");
6859                 return ret;
6860         }
6861
6862         /* check current state */
6863         MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_RESUME );
6864
6865         /* resume pipeline */
6866         ret = __gst_resume( player, FALSE );
6867
6868         if ( ret != MM_ERROR_NONE )
6869         {
6870                 debug_error("failed to resume player.\n");
6871         }
6872
6873
6874         debug_fleave();
6875
6876         return ret;
6877 }
6878
6879 int
6880 __mmplayer_set_play_count(mm_player_t* player, gint count)
6881 {
6882         MMHandleType attrs = 0;
6883
6884         debug_fenter();
6885
6886         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
6887
6888         attrs =  MMPLAYER_GET_ATTRS(player);
6889         if ( !attrs )
6890         {
6891                 debug_error("fail to get attributes.\n");
6892                 return MM_ERROR_PLAYER_INTERNAL;
6893         }
6894
6895         mm_attrs_set_int_by_name(attrs, "profile_play_count", count);
6896         if ( mmf_attrs_commit ( attrs ) ) /* return -1 if error */
6897                 debug_error("failed to commit\n");
6898
6899         debug_fleave();
6900
6901         return  MM_ERROR_NONE;
6902 }
6903
6904 int
6905 _mmplayer_activate_section_repeat(MMHandleType hplayer, unsigned long start, unsigned long end)
6906 {
6907         mm_player_t* player = (mm_player_t*)hplayer;
6908         gint64 start_pos = 0;
6909         gint64 end_pos = 0;
6910         gint infinity = -1;
6911
6912         debug_fenter();
6913
6914         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
6915         return_val_if_fail ( end <= GST_TIME_AS_MSECONDS(player->duration), MM_ERROR_INVALID_ARGUMENT );
6916
6917         player->section_repeat = TRUE;
6918         player->section_repeat_start = start;
6919         player->section_repeat_end = end;
6920
6921         start_pos = player->section_repeat_start * G_GINT64_CONSTANT(1000000);
6922         end_pos = player->section_repeat_end * G_GINT64_CONSTANT(1000000);
6923
6924         __mmplayer_set_play_count( player, infinity );
6925
6926         if ( (!__gst_seek( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,
6927                                         1.0,
6928                                         GST_FORMAT_TIME,
6929                                         ( GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE ),
6930                                         GST_SEEK_TYPE_SET, start_pos,
6931                                         GST_SEEK_TYPE_SET, end_pos)))
6932         {
6933                 debug_error("failed to activate section repeat\n");
6934
6935                 return MM_ERROR_PLAYER_SEEK;
6936         }
6937
6938         debug_log("succeeded to set section repeat from %d to %d\n",
6939                 player->section_repeat_start, player->section_repeat_end);
6940
6941         debug_fleave();
6942
6943         return  MM_ERROR_NONE;
6944 }
6945
6946 static int 
6947 __mmplayer_set_pcm_extraction(mm_player_t* player)
6948 {
6949         guint64 start_nsec = 0;
6950         guint64 end_nsec = 0;
6951         guint64 dur_nsec = 0;
6952         guint64 dur_msec = 0;
6953         GstFormat fmt = GST_FORMAT_TIME;
6954         int required_start = 0;
6955         int required_end = 0;
6956         int ret = 0;
6957
6958         debug_fenter();
6959
6960         return_val_if_fail( player, FALSE );
6961
6962         mm_attrs_multiple_get(player->attrs,
6963                 NULL,
6964                 "pcm_extraction_start_msec", &required_start,
6965                 "pcm_extraction_end_msec", &required_end,
6966                 NULL);
6967
6968         debug_log("pcm extraction required position is from [%d] to [%d] (msec)\n", required_start, required_end);
6969
6970         if (required_start == 0 && required_end == 0)
6971         {
6972                 debug_log("extracting entire stream");
6973                 return MM_ERROR_NONE;
6974         }
6975         else if (required_start < 0 || required_start > required_end || required_end < 0 )
6976         {
6977                 debug_log("invalid range for pcm extraction");
6978                 return MM_ERROR_INVALID_ARGUMENT;
6979         }
6980
6981         /* get duration */
6982         ret = gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, &fmt, &dur_nsec);
6983         if ( !ret )
6984         {
6985                 debug_error("failed to get duration");
6986                 return MM_ERROR_PLAYER_INTERNAL;
6987         }
6988         dur_msec = GST_TIME_AS_MSECONDS(dur_nsec);
6989
6990         if (dur_msec < required_end) // FIXME
6991         {
6992                 debug_log("invalid end pos for pcm extraction");
6993                 return MM_ERROR_INVALID_ARGUMENT;
6994         }
6995
6996         start_nsec = required_start * G_GINT64_CONSTANT(1000000);
6997         end_nsec = required_end * G_GINT64_CONSTANT(1000000);
6998
6999         if ( (!__gst_seek( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,
7000                                         1.0,
7001                                         GST_FORMAT_TIME,
7002                                         ( GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE ),
7003                                         GST_SEEK_TYPE_SET, start_nsec,
7004                                         GST_SEEK_TYPE_SET, end_nsec)))
7005         {
7006                 debug_error("failed to seek for pcm extraction\n");
7007
7008                 return MM_ERROR_PLAYER_SEEK;
7009         }
7010
7011         debug_log("succeeded to set up segment extraction from [%llu] to [%llu] (nsec)\n", start_nsec, end_nsec);
7012
7013         debug_fleave(); 
7014
7015         return MM_ERROR_NONE;
7016 }
7017
7018 int
7019 _mmplayer_deactivate_section_repeat(MMHandleType hplayer)
7020 {
7021         mm_player_t* player = (mm_player_t*)hplayer;
7022         gint64 cur_pos = 0;
7023         GstFormat fmt  = GST_FORMAT_TIME;
7024         gint onetime = 1;
7025
7026         debug_fenter();
7027
7028         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
7029
7030         player->section_repeat = FALSE;
7031
7032         __mmplayer_set_play_count( player, onetime );
7033
7034         gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, &fmt, &cur_pos);
7035
7036         if ( (!__gst_seek( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,
7037                                         1.0,
7038                                         GST_FORMAT_TIME,
7039                                         ( GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE ),
7040                                         GST_SEEK_TYPE_SET, cur_pos,
7041                                         GST_SEEK_TYPE_SET, player->duration )))
7042         {
7043                 debug_error("failed to deactivate section repeat\n");
7044
7045                 return MM_ERROR_PLAYER_SEEK;
7046         }
7047
7048         debug_fenter();
7049
7050         return MM_ERROR_NONE;
7051 }
7052
7053 int
7054 _mmplayer_set_playspeed(MMHandleType hplayer, gdouble rate)
7055 {
7056         mm_player_t* player = (mm_player_t*)hplayer;
7057         signed long long pos_msec = 0;
7058         int ret = MM_ERROR_NONE;
7059         int mute = FALSE;
7060         GstFormat format =GST_FORMAT_TIME;
7061         MMPlayerStateType current_state = MM_PLAYER_STATE_NONE;
7062         debug_fenter();
7063
7064         return_val_if_fail ( player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED );
7065         return_val_if_fail ( !MMPLAYER_IS_STREAMING(player), MM_ERROR_NOT_SUPPORT_API );
7066
7067         /* The sound of video is not supported under 0.0 and over 2.0. */
7068         if(rate >= TRICK_PLAY_MUTE_THRESHOLD_MAX || rate < TRICK_PLAY_MUTE_THRESHOLD_MIN)
7069         {
7070                 if (player->can_support_codec & FOUND_PLUGIN_VIDEO)
7071                         mute = TRUE;
7072         }
7073         _mmplayer_set_mute(hplayer, mute);
7074
7075         if (player->playback_rate == rate)
7076                 return MM_ERROR_NONE;
7077
7078         /* If the position is reached at start potion during fast backward, EOS is posted.
7079          * So, This EOS have to be classified with it which is posted at reaching the end of stream.
7080          * */
7081         player->playback_rate = rate;
7082
7083         current_state = MMPLAYER_CURRENT_STATE(player);
7084
7085         if ( current_state != MM_PLAYER_STATE_PAUSED )
7086                 ret = gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, &format, &pos_msec);
7087
7088         debug_log ("pos_msec = %"GST_TIME_FORMAT" and ret = %d and state = %d", GST_TIME_ARGS (pos_msec), ret, current_state);
7089
7090         if ( ( current_state == MM_PLAYER_STATE_PAUSED )
7091                 || ( ! ret ))
7092                 //|| ( player->last_position != 0 && pos_msec == 0 ) )
7093         {
7094                 debug_warning("returning last point : %lld\n", player->last_position );
7095                 pos_msec = player->last_position;
7096         }
7097
7098         if ((!gst_element_seek (player->pipeline->mainbin[MMPLAYER_M_PIPE].gst,
7099                                 rate,
7100                                 GST_FORMAT_TIME,
7101                                 ( GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE ),
7102                                 //( GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE | GST_SEEK_FLAG_KEY_UNIT),
7103                                 GST_SEEK_TYPE_SET, pos_msec,
7104                                 //GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE,
7105                 GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE)))
7106         {
7107                 debug_error("failed to set speed playback\n");
7108                 return MM_ERROR_PLAYER_SEEK;
7109         }
7110
7111         debug_log("succeeded to set speed playback as %fl\n", rate);
7112
7113         debug_fleave();
7114
7115         return MM_ERROR_NONE;;
7116 }
7117
7118 int
7119 _mmplayer_set_position(MMHandleType hplayer, int format, int position) // @
7120 {
7121         mm_player_t* player = (mm_player_t*)hplayer;
7122         int ret = MM_ERROR_NONE;
7123
7124         debug_fenter();
7125
7126         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
7127
7128         ret = __gst_set_position ( player, format, (unsigned long)position, FALSE );
7129
7130         debug_fleave(); 
7131
7132         return ret;
7133 }
7134
7135 int
7136 _mmplayer_get_position(MMHandleType hplayer, int format, unsigned long *position) // @
7137 {
7138         mm_player_t* player = (mm_player_t*)hplayer;
7139         int ret = MM_ERROR_NONE;
7140
7141         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
7142
7143         ret = __gst_get_position ( player, format, position );
7144         
7145         return ret;
7146 }
7147
7148 int
7149 _mmplayer_get_buffer_position(MMHandleType hplayer, int format, unsigned long* start_pos, unsigned long* stop_pos) // @
7150 {
7151         mm_player_t* player = (mm_player_t*)hplayer;
7152         int ret = MM_ERROR_NONE;
7153
7154         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
7155
7156         ret = __gst_get_buffer_position ( player, format, start_pos, stop_pos );
7157
7158         return ret;
7159 }
7160
7161 int
7162 _mmplayer_adjust_subtitle_postion(MMHandleType hplayer, int format, int position) // @
7163 {
7164         mm_player_t* player = (mm_player_t*)hplayer;
7165         int ret = MM_ERROR_NONE;
7166
7167         debug_fenter();
7168
7169         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
7170
7171         ret = __gst_adjust_subtitle_position(player, format, position);
7172
7173         debug_fleave();
7174
7175         return ret;
7176 }
7177
7178 static gboolean
7179 __mmplayer_is_midi_type( gchar* str_caps)
7180 {
7181         if ( ( g_strrstr(str_caps, "audio/midi") ) ||
7182                 ( g_strrstr(str_caps, "application/x-gst_ff-mmf") ) ||
7183                 ( g_strrstr(str_caps, "application/x-smaf") ) ||
7184                 ( g_strrstr(str_caps, "audio/x-imelody") ) ||
7185                 ( g_strrstr(str_caps, "audio/mobile-xmf") ) ||
7186                 ( g_strrstr(str_caps, "audio/xmf") ) ||
7187                 ( g_strrstr(str_caps, "audio/mxmf") ) )
7188         {
7189                 debug_log("midi\n");
7190
7191                 return TRUE;
7192         }
7193
7194         debug_log("not midi.\n");
7195
7196         return FALSE;
7197 }
7198
7199 static gboolean
7200 __mmplayer_is_amr_type (gchar *str_caps)
7201 {
7202         if ((g_strrstr(str_caps, "AMR")) ||
7203                 (g_strrstr(str_caps, "amr")))
7204         {
7205                 return TRUE;
7206         }
7207         return FALSE;
7208 }
7209
7210 static gboolean
7211 __mmplayer_is_only_mp3_type (gchar *str_caps)
7212 {
7213         if (g_strrstr(str_caps, "application/x-id3") ||
7214                 (g_strrstr(str_caps, "audio/mpeg") && g_strrstr(str_caps, "mpegversion=(int)1")))
7215         {
7216                 return TRUE;
7217         }
7218         return FALSE;
7219 }
7220
7221 static void
7222 __mmplayer_typefind_have_type(  GstElement *tf, guint probability,  // @
7223 GstCaps *caps, gpointer data)
7224 {
7225         mm_player_t* player = (mm_player_t*)data;
7226         GstPad* pad = NULL;
7227
7228         debug_fenter();
7229
7230         return_if_fail( player && tf && caps );
7231
7232         /* store type string */
7233         MMPLAYER_FREEIF(player->type);
7234         player->type = gst_caps_to_string(caps);
7235         if (player->type)
7236                 debug_log("meida type %s found, probability %d%% / %d\n", player->type, probability, gst_caps_get_size(caps));
7237
7238         /* midi type should be stored because it will be used to set audio gain in avsysauiosink */
7239         if ( __mmplayer_is_midi_type(player->type))
7240         {
7241                 player->profile.play_mode = MM_PLAYER_MODE_MIDI;
7242         }
7243         else if (__mmplayer_is_amr_type(player->type))
7244         {
7245                 player->bypass_sound_effect = FALSE;
7246                 if ( (PLAYER_INI()->use_audio_filter_preset || PLAYER_INI()->use_audio_filter_custom) )
7247                 {
7248                         if ( player->audio_filter_info.filter_type == MM_AUDIO_FILTER_TYPE_PRESET )
7249                         {
7250                                 if (!_mmplayer_sound_filter_preset_apply(player, player->audio_filter_info.preset))
7251                                 {
7252                                         debug_msg("apply sound effect(preset:%d) setting success\n",player->audio_filter_info.preset);
7253                                 }
7254                         }
7255                         else if ( player->audio_filter_info.filter_type == MM_AUDIO_FILTER_TYPE_CUSTOM )
7256                         {
7257                                 if (!_mmplayer_sound_filter_custom_apply(player))
7258                                 {
7259                                         debug_msg("apply sound effect(custom) setting success\n");
7260                                 }
7261                         }
7262                 }
7263         }
7264         else if ( g_strrstr(player->type, "application/x-hls"))
7265         {
7266                 /* If it can't know exact type when it parses uri because of redirection case,
7267                   * it will be fixed by typefinder here.
7268                   */
7269                 player->profile.uri_type = MM_PLAYER_URI_TYPE_HLS;
7270         }
7271
7272         pad = gst_element_get_static_pad(tf, "src");
7273         if ( !pad )
7274         {
7275                 debug_error("fail to get typefind src pad.\n");
7276                 return;
7277         }
7278
7279
7280         /* try to plug */
7281         if ( ! __mmplayer_try_to_plug( player, pad, caps ) )
7282         {
7283                 debug_error("failed to autoplug for type : %s\n", player->type);
7284
7285                 if ( ( PLAYER_INI()->async_start ) &&
7286                 ( player->posted_msg == FALSE ) )
7287                 {
7288                         __mmplayer_post_missed_plugin( player );
7289                 }
7290                         
7291                 goto DONE;
7292         }
7293
7294         /* finish autopluging if no dynamic pad waiting */
7295         if( ( ! player->have_dynamic_pad) && ( ! player->has_many_types) )
7296         {
7297                 if ( ! MMPLAYER_IS_RTSP_STREAMING( player ) )
7298                 {
7299                         __mmplayer_pipeline_complete( NULL, (gpointer)player );
7300                 }
7301         }
7302
7303 DONE:
7304         gst_object_unref( GST_OBJECT(pad) );
7305
7306         debug_fleave(); 
7307
7308         return;
7309 }
7310
7311 static gboolean
7312 __mmplayer_warm_up_video_codec( mm_player_t* player,  GstElementFactory *factory)
7313 {
7314         GstElement *element;
7315         GstStateChangeReturn  ret;
7316         gboolean usable = TRUE;
7317
7318         return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
7319         return_val_if_fail ( factory, MM_ERROR_COMMON_INVALID_ARGUMENT );
7320
7321         element = gst_element_factory_create (factory, NULL);
7322
7323         ret = gst_element_set_state (element, GST_STATE_READY);
7324
7325         if (ret != GST_STATE_CHANGE_SUCCESS)
7326         {
7327                 debug_error ("resource conflict so,  %s unusable\n", GST_PLUGIN_FEATURE_NAME (factory));
7328                 usable = FALSE;
7329         }
7330
7331         gst_element_set_state (element, GST_STATE_NULL);
7332         gst_object_unref (element);
7333
7334         return usable;
7335 }
7336
7337 /* it will return first created element */
7338 static gboolean
7339 __mmplayer_try_to_plug(mm_player_t* player, GstPad *pad, const GstCaps *caps) // @
7340 {
7341         MMPlayerGstElement* mainbin = NULL;
7342         const char* mime = NULL;
7343         const GList* item = NULL;
7344         const gchar* klass = NULL;
7345         GstCaps* res = NULL;
7346         gboolean skip = FALSE;
7347         GstPad* queue_pad = NULL;
7348         GstElement* queue = NULL;
7349         GstElement *element = NULL;
7350
7351         debug_fenter();
7352
7353         return_val_if_fail( player &&
7354                                                 player->pipeline &&
7355                                                 player->pipeline->mainbin,
7356                                                 FALSE );
7357
7358
7359         mainbin = player->pipeline->mainbin;
7360
7361         mime = gst_structure_get_name(gst_caps_get_structure(caps, 0));
7362
7363         /* return if we got raw output */
7364         if(g_str_has_prefix(mime, "video/x-raw") || g_str_has_prefix(mime, "audio/x-raw") ||g_str_has_prefix(mime, "text/plain") )
7365         {
7366
7367                 element = (GstElement*)gst_pad_get_parent(pad);
7368
7369
7370 /* NOTE : When no decoder has added during autoplugging. like a simple wave playback.
7371  * No queue will be added. I think it can caused breaking sound when playing raw audio
7372  * frames but there's no different. Decodebin also doesn't add with those wav fils.
7373  * Anyway, currentely raw-queue seems not necessary.
7374  */
7375 #if 1
7376
7377                 /* NOTE : check if previously linked element is demuxer/depayloader/parse means no decoder
7378                  * has linked. if so, we need to add queue for quality of output. note that
7379                  * decodebin also has same problem.
7380                  */
7381
7382                 klass = gst_element_factory_get_klass( gst_element_get_factory(element) );
7383
7384                 /* add queue if needed */
7385                 if( g_strrstr(klass, "Demux") ||
7386                 g_strrstr(klass, "Depayloader") ||
7387                         g_strrstr(klass, "Parse") )
7388                 {
7389                         debug_log("adding raw queue\n");
7390
7391                         queue = gst_element_factory_make("queue", NULL);
7392                         if ( ! queue )
7393                         {
7394                                 debug_warning("failed to create queue\n");
7395                                 goto ERROR;
7396                         }
7397
7398                         /* warmup */
7399                         if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state(queue, GST_STATE_READY) )
7400                         {
7401                                 debug_warning("failed to set state READY to queue\n");
7402                                 goto ERROR;
7403                         }
7404
7405                         /* add to pipeline */
7406                         if ( ! gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), queue) )
7407                         {
7408                                 debug_warning("failed to add queue\n");
7409                                 goto ERROR;
7410                         }
7411
7412                         /* link queue */
7413                         queue_pad = gst_element_get_static_pad(queue, "sink");
7414
7415                         if ( GST_PAD_LINK_OK != gst_pad_link(pad, queue_pad) )
7416                         {
7417                                 debug_warning("failed to link queue\n");
7418                                 goto ERROR;
7419                         }
7420                         gst_object_unref ( GST_OBJECT(queue_pad) );
7421                         queue_pad = NULL;
7422
7423                         /* running */
7424                         if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state(queue, GST_STATE_PAUSED) )
7425                         {
7426                                 debug_warning("failed to set state READY to queue\n");
7427                                 goto ERROR;
7428                         }
7429
7430                         /* replace given pad to queue:src */
7431                         pad = gst_element_get_static_pad(queue, "src");
7432                         if ( ! pad )
7433                         {
7434                                 debug_warning("failed to get pad from queue\n");
7435                                 goto ERROR;
7436                         }
7437                 }
7438 #endif
7439                 /* check if player can do start continually */
7440                 MMPLAYER_CHECK_CMD_IF_EXIT(player);
7441
7442                 if(__mmplayer_link_sink(player,pad))
7443                  __mmplayer_gst_decode_callback(element, pad, FALSE, player);
7444
7445                 gst_object_unref( GST_OBJECT(element));
7446                 element = NULL;
7447
7448
7449                 return TRUE;
7450         }
7451
7452         item = player->factories;
7453         for(; item != NULL ; item = item->next)
7454         {
7455
7456                 GstElementFactory *factory = GST_ELEMENT_FACTORY(item->data);
7457                 const GList *pads;
7458                 gint idx = 0;
7459
7460                 skip = FALSE;
7461
7462                 /* filtering exclude keyword */
7463                 for ( idx = 0; PLAYER_INI()->exclude_element_keyword[idx][0] != '\0'; idx++ )
7464                 {
7465                         if ( g_strrstr(GST_PLUGIN_FEATURE_NAME (factory),
7466                                         PLAYER_INI()->exclude_element_keyword[idx] ) )
7467                         {
7468                                 debug_warning("skipping [%s] by exculde keyword [%s]\n",
7469                                         GST_PLUGIN_FEATURE_NAME (factory),
7470                                         PLAYER_INI()->exclude_element_keyword[idx] );
7471
7472                                 skip = TRUE;
7473                                 break;
7474                         }
7475                 }
7476
7477                 if ( skip ) continue;
7478
7479
7480                 /* check factory class for filtering */
7481                 klass = gst_element_factory_get_klass(GST_ELEMENT_FACTORY(factory));
7482
7483                 /* NOTE : msl don't need to use image plugins.
7484                  * So, those plugins should be skipped for error handling.
7485                  */
7486                 if ( g_strrstr(klass, "Codec/Decoder/Image") )
7487                 {
7488                         debug_log("player doesn't need [%s] so, skipping it\n",
7489                                 GST_PLUGIN_FEATURE_NAME (factory) );
7490
7491                         continue;
7492                 }
7493
7494
7495                 /* check pad compatability */
7496                 for(pads = gst_element_factory_get_static_pad_templates(factory);
7497                      pads != NULL; pads=pads->next)
7498                {
7499                        GstStaticPadTemplate *temp1 = pads->data;
7500                         GstCaps* static_caps = NULL;
7501
7502                         if( temp1->direction != GST_PAD_SINK ||
7503                                 temp1->presence != GST_PAD_ALWAYS)
7504                                 continue;
7505
7506
7507                         if ( GST_IS_CAPS( &temp1->static_caps.caps) )
7508                         {
7509                                 /* using existing caps */
7510                                 static_caps = gst_caps_ref( &temp1->static_caps.caps );
7511                         }
7512                         else
7513                         {
7514                                 /* create one */
7515                                 static_caps = gst_caps_from_string ( temp1->static_caps.string );
7516                         }
7517
7518                         res = gst_caps_intersect(caps, static_caps);
7519
7520                         gst_caps_unref( static_caps );
7521                         static_caps = NULL;
7522
7523                         if( res && !gst_caps_is_empty(res) )
7524                         {
7525                                 GstElement *new_element;
7526                                 GList *elements = player->parsers;
7527                                 char *name_template = g_strdup(temp1->name_template);
7528                                 gchar *name_to_plug = GST_PLUGIN_FEATURE_NAME(factory);
7529
7530                                 gst_caps_unref(res);
7531
7532                                 debug_log("found %s to plug\n", name_to_plug);
7533
7534                                 new_element = gst_element_factory_create(GST_ELEMENT_FACTORY(factory), NULL);
7535                                 if ( ! new_element )
7536                                 {
7537                                         debug_error("failed to create element [%s]. continue with next.\n",
7538                                                 GST_PLUGIN_FEATURE_NAME (factory));
7539
7540                                         MMPLAYER_FREEIF(name_template);
7541
7542                                         continue;
7543                                 }
7544
7545                                 /* check and skip it if it was already used. Otherwise, it can be an infinite loop
7546                                  * because parser can accept its own output as input.
7547                                  */
7548                                 if (g_strrstr(klass, "Parser"))
7549                                 {
7550                                         gchar *selected = NULL;
7551
7552                                         for ( ; elements; elements = g_list_next(elements))
7553                                         {
7554                                                 gchar *element_name = elements->data;
7555
7556                                                 if (g_strrstr(element_name, name_to_plug))
7557                                                 {
7558                                                         debug_log("but, %s already linked, so skipping it\n", name_to_plug);
7559                                                         skip = TRUE;
7560                                                 }
7561                                         }
7562
7563                                         if (skip) continue;
7564
7565                                         selected = g_strdup(name_to_plug);
7566
7567                                         player->parsers = g_list_append(player->parsers, selected);
7568                                 }
7569
7570                                 /* store specific handles for futher control */
7571                                 if(g_strrstr(klass, "Demux") || g_strrstr(klass, "Parse"))
7572                         {
7573                                         /* FIXIT : first value will be overwritten if there's more
7574                                          * than 1 demuxer/parser
7575                                          */
7576                                         debug_log("plugged element is demuxer. take it\n");
7577                                         mainbin[MMPLAYER_M_DEMUX].id = MMPLAYER_M_DEMUX;
7578                                         mainbin[MMPLAYER_M_DEMUX].gst = new_element;
7579                                 }
7580                                 else if(g_strrstr(klass, "Decoder") && __mmplayer_link_decoder(player,pad))
7581                                 {                                                                       
7582                                     if(mainbin[MMPLAYER_M_DEC1].gst == NULL)
7583                                     {
7584                                                 debug_log("plugged element is decoder. take it[MMPLAYER_M_DEC1]\n");
7585                                                 mainbin[MMPLAYER_M_DEC1].id = MMPLAYER_M_DEC1;
7586                                                 mainbin[MMPLAYER_M_DEC1].gst = new_element;
7587                                     }
7588                                     else if(mainbin[MMPLAYER_M_DEC2].gst == NULL)
7589                                     {
7590                                                 debug_log("plugged element is decoder. take it[MMPLAYER_M_DEC2]\n");
7591                                                 mainbin[MMPLAYER_M_DEC2].id = MMPLAYER_M_DEC2;
7592                                                 mainbin[MMPLAYER_M_DEC2].gst = new_element;
7593                                     }
7594
7595                                         /* NOTE : IF one codec is found, add it to supported_codec and remove from
7596                                          * missing plugin. Both of them are used to check what's supported codec
7597                                          * before returning result of play start. And, missing plugin should be
7598                                          * updated here for multi track files.
7599                                          */
7600                                         if(g_str_has_prefix(mime, "video"))
7601                                         {
7602                                                 GstPad *src_pad = NULL;
7603                                                 GstPadTemplate *pad_templ = NULL;
7604                                                 GstCaps *caps = NULL;
7605                                                 gchar *caps_type = NULL;
7606                                                         
7607                                                 debug_log("found VIDEO decoder\n");
7608                                                 player->not_supported_codec &= MISSING_PLUGIN_AUDIO;
7609                                                 player->can_support_codec |= FOUND_PLUGIN_VIDEO;
7610
7611                                                 src_pad = gst_element_get_static_pad (new_element, "src");
7612                                                 pad_templ = gst_pad_get_pad_template (src_pad);
7613                                                 caps = GST_PAD_TEMPLATE_CAPS(pad_templ);
7614
7615                                                 caps_type = gst_caps_to_string(caps);
7616
7617                                                 if ( g_strrstr( caps_type, "ST12") )
7618                                                         player->is_nv12_tiled = TRUE;
7619
7620                                                 /* clean */
7621                                                 MMPLAYER_FREEIF( caps_type );
7622                                                 gst_object_unref (src_pad);
7623                                         }
7624                                         else if (g_str_has_prefix(mime, "audio"))
7625                                         {
7626                                                 debug_log("found AUDIO decoder\n");
7627                                                 player->not_supported_codec &= MISSING_PLUGIN_VIDEO;
7628                                                 player->can_support_codec |= FOUND_PLUGIN_AUDIO;
7629                                         }
7630                                 }
7631                                 if ( ! __mmplayer_close_link(player, pad, new_element,
7632                                             name_template,gst_element_factory_get_static_pad_templates(factory)) )
7633                                 {
7634                                         if (player->keep_detecting_vcodec)
7635                                                 continue;
7636
7637                                         /* Link is failed even though a supportable codec is found. */
7638                                         __mmplayer_check_not_supported_codec(player, (gchar *)mime);
7639
7640                                         MMPLAYER_FREEIF(name_template);
7641                                         debug_error("failed to call _close_link\n");
7642                                         return FALSE;
7643                                 }
7644
7645                                 MMPLAYER_FREEIF(name_template);
7646                                 return TRUE;
7647                         }
7648
7649                         gst_caps_unref(res);
7650
7651                         break;
7652                 }
7653         }
7654
7655         /* There is no any found codec. */
7656         __mmplayer_check_not_supported_codec(player,(gchar *)mime);
7657
7658         debug_error("failed to autoplug\n");
7659
7660         debug_fleave();
7661         
7662         return FALSE;
7663
7664
7665 ERROR:
7666
7667         /* release */
7668         if ( queue )
7669                 gst_object_unref( queue );
7670
7671
7672         if ( queue_pad )
7673                 gst_object_unref( queue_pad );
7674
7675         if ( element )
7676                 gst_object_unref ( element );
7677
7678         return FALSE;
7679 }
7680
7681
7682 static
7683 int __mmplayer_check_not_supported_codec(mm_player_t* player, gchar* mime)
7684 {
7685         debug_fenter();
7686
7687         return_val_if_fail(player && player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED);
7688         return_val_if_fail ( mime, MM_ERROR_INVALID_ARGUMENT );
7689
7690         debug_log("mimetype to check: %s\n", mime );
7691
7692         /* add missing plugin */
7693         /* NOTE : msl should check missing plugin for image mime type.
7694          * Some motion jpeg clips can have playable audio track.
7695          * So, msl have to play audio after displaying popup written video format not supported.
7696          */
7697         if ( !( player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst ) )
7698         {
7699                 if ( !( player->can_support_codec | player->videodec_linked | player->audiodec_linked ) )
7700                 {
7701                         debug_log("not found demuxer\n");
7702                         player->not_found_demuxer = TRUE;
7703                         player->unlinked_demuxer_mime = g_strdup_printf ( "%s", mime );
7704
7705                         goto DONE;
7706                 }
7707         }
7708
7709         if( ( g_str_has_prefix(mime, "video") ) ||( g_str_has_prefix(mime, "image") ) )
7710         {
7711                 debug_log("can support codec=%d, vdec_linked=%d, adec_linked=%d\n",
7712                         player->can_support_codec, player->videodec_linked, player->audiodec_linked);
7713
7714                 /* check that clip have multi tracks or not */
7715                 if ( ( player->can_support_codec & FOUND_PLUGIN_VIDEO ) && ( player->videodec_linked ) )
7716                 {
7717                         debug_log("video plugin is already linked\n");
7718                 }
7719                 else
7720                 {
7721                         debug_warning("add VIDEO to missing plugin\n");
7722                         player->not_supported_codec |= MISSING_PLUGIN_VIDEO;
7723                 }
7724         }
7725         else if ( g_str_has_prefix(mime, "audio") )
7726         {
7727                 if ( ( player->can_support_codec & FOUND_PLUGIN_AUDIO ) && ( player->audiodec_linked ) )
7728                 {
7729                         debug_log("audio plugin is already linked\n");
7730                 }
7731                 else
7732                 {
7733                         debug_warning("add AUDIO to missing plugin\n");
7734                         player->not_supported_codec |= MISSING_PLUGIN_AUDIO;
7735                 }
7736         }
7737
7738 DONE:
7739         debug_fleave(); 
7740
7741         return MM_ERROR_NONE;
7742 }
7743
7744
7745 static void __mmplayer_pipeline_complete(GstElement *decodebin,  gpointer data) // @
7746 {
7747     mm_player_t* player = (mm_player_t*)data;
7748
7749         debug_fenter();
7750
7751         return_if_fail( player );
7752
7753         /* remove fakesink */
7754         if ( ! __mmplayer_gst_remove_fakesink( player,
7755                 &player->pipeline->mainbin[MMPLAYER_M_SRC_FAKESINK]) )
7756         {
7757                 /* NOTE : __mmplayer_pipeline_complete() can be called several time. because
7758                  * signaling mechanism ( pad-added, no-more-pad, new-decoded-pad ) from various
7759                  * source element are not same. To overcome this situation, this function will called
7760                  * several places and several times. Therefore, this is not an error case.
7761                  */
7762                 return;
7763         }
7764         debug_log("pipeline has completely constructed\n");
7765
7766         player->pipeline_is_constructed = TRUE;
7767         
7768         if ( ( PLAYER_INI()->async_start ) &&
7769                 ( player->posted_msg == FALSE ) )
7770         {
7771                 __mmplayer_post_missed_plugin( player );
7772         }
7773         
7774         MMPLAYER_GENERATE_DOT_IF_ENABLED ( player, "pipeline-status-complate" );
7775 }
7776
7777 static gboolean __mmplayer_configure_audio_callback(mm_player_t* player)
7778 {
7779         debug_fenter();
7780
7781         return_val_if_fail ( player, FALSE );
7782
7783
7784         if ( MMPLAYER_IS_STREAMING(player) )
7785                 return FALSE;
7786
7787         /* This callback can be set to music player only. */
7788         if((player->can_support_codec & 0x02) == FOUND_PLUGIN_VIDEO)
7789         {
7790                 debug_warning("audio callback is not supported for video");
7791                 return FALSE;
7792         }
7793
7794         if (player->audio_stream_cb)
7795         {
7796                 {
7797                         GstPad *pad = NULL;
7798
7799                         pad = gst_element_get_static_pad (player->pipeline->audiobin[MMPLAYER_A_SINK].gst, "sink");
7800
7801                         if ( !pad )
7802                         {
7803                                 debug_error("failed to get sink pad from audiosink to probe data\n");
7804                                 return FALSE;
7805                         }
7806
7807                         player->audio_cb_probe_id = gst_pad_add_buffer_probe (pad,
7808                                 G_CALLBACK (__mmplayer_audio_stream_probe), player);
7809
7810                         gst_object_unref (pad);
7811
7812                         pad = NULL;
7813                }
7814         }
7815         else
7816         {
7817                 debug_error("There is no audio callback to configure.\n");
7818                 return FALSE;
7819         }
7820
7821         debug_fleave(); 
7822
7823         return TRUE;
7824 }
7825
7826 static void
7827 __mmplayer_init_factories(mm_player_t* player) // @
7828 {
7829         debug_fenter();
7830
7831         return_if_fail ( player );
7832
7833         player->factories = gst_registry_feature_filter(gst_registry_get_default(),
7834                                         (GstPluginFeatureFilter)__mmplayer_feature_filter, FALSE, NULL);
7835
7836         player->factories = g_list_sort(player->factories, (GCompareFunc)util_factory_rank_compare);
7837
7838         debug_fleave(); 
7839 }
7840
7841 static void
7842 __mmplayer_release_factories(mm_player_t* player) // @
7843 {
7844         debug_fenter();
7845
7846         return_if_fail ( player );
7847
7848         if (player->factories)
7849         {
7850                 gst_plugin_feature_list_free (player->factories);
7851                 player->factories = NULL;
7852         }
7853
7854         debug_fleave();
7855 }
7856
7857 static void
7858 __mmplayer_release_misc(mm_player_t* player)
7859 {
7860         int i;
7861         debug_fenter();
7862
7863         return_if_fail ( player );
7864
7865         player->use_video_stream = FALSE;
7866         player->video_stream_cb = NULL;
7867         player->video_stream_cb_user_param = NULL;
7868
7869         player->audio_stream_cb = NULL;
7870         player->audio_stream_cb_user_param = NULL;
7871
7872         player->audio_buffer_cb = NULL;
7873         player->audio_buffer_cb_user_param = NULL;
7874
7875         player->sent_bos = FALSE;
7876         player->playback_rate = DEFAULT_PLAYBACK_RATE;
7877
7878         player->doing_seek = FALSE;
7879
7880         player->streamer = NULL;
7881         player->updated_bitrate_count = 0;
7882         player->total_bitrate = 0;
7883         player->updated_maximum_bitrate_count = 0;
7884         player->total_maximum_bitrate = 0;
7885
7886         player->not_found_demuxer = 0;
7887
7888         player->last_position = 0;
7889         player->duration = 0;
7890         player->http_content_size = 0;
7891         player->not_supported_codec = MISSING_PLUGIN_NONE;
7892         player->can_support_codec = FOUND_PLUGIN_NONE;
7893         player->need_update_content_dur = FALSE;
7894         player->pending_seek.is_pending = FALSE;
7895         player->pending_seek.format = MM_PLAYER_POS_FORMAT_TIME;
7896         player->pending_seek.pos = 0;
7897         player->posted_msg == FALSE;
7898         player->has_many_types = FALSE;
7899
7900         for (i = 0; i < MM_PLAYER_STREAM_COUNT_MAX; i++)
7901         {
7902                 player->bitrate[i] = 0;
7903                 player->maximum_bitrate[i] = 0;
7904         }
7905
7906         /* clean found parsers */
7907         if (player->parsers)
7908         {
7909                 g_list_free(player->parsers);
7910                 player->parsers = NULL;
7911         }
7912
7913         MMPLAYER_FREEIF(player->album_art);
7914
7915         /* free memory related to sound effect */
7916         if(player->audio_filter_info.custom_ext_level_for_plugin)
7917         {
7918                 free(player->audio_filter_info.custom_ext_level_for_plugin);
7919         }
7920
7921         debug_fleave();
7922 }
7923
7924 static GstElement *__mmplayer_element_create_and_link(mm_player_t *player, GstPad* pad, const char* name)
7925 {
7926         GstElement *element = NULL;
7927         GstPad *sinkpad;
7928
7929         debug_log("creating %s to plug\n", name);
7930         
7931         element = gst_element_factory_make(name, NULL);
7932         if ( ! element )
7933         {
7934                 debug_error("failed to create queue\n");
7935                 return NULL;
7936         }
7937
7938         if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state(element, GST_STATE_READY) )
7939         {
7940                 debug_error("failed to set state READY to %s\n", name);
7941                 return NULL;
7942         }
7943
7944         if ( ! gst_bin_add(GST_BIN(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst), element))
7945         {
7946                 debug_error("failed to add %s\n", name);
7947                 return NULL;
7948         }
7949
7950         sinkpad = gst_element_get_static_pad(element, "sink");
7951
7952         if ( GST_PAD_LINK_OK != gst_pad_link(pad, sinkpad) )
7953         {
7954                 debug_error("failed to link %s\n", name);
7955                 gst_object_unref (sinkpad);
7956                 
7957                 return NULL;
7958         }
7959
7960         debug_log("linked %s to pipeline successfully\n", name);
7961
7962         gst_object_unref (sinkpad);
7963
7964         return element; 
7965 }
7966
7967 static gboolean
7968 __mmplayer_close_link(mm_player_t* player, GstPad *srcpad, GstElement *sinkelement,
7969 const char *padname, const GList *templlist)
7970 {
7971         GstPad *pad = NULL;
7972         gboolean has_dynamic_pads = FALSE;
7973         gboolean has_many_types = FALSE;        
7974         const char *klass = NULL;
7975         GstStaticPadTemplate *padtemplate = NULL;
7976         GstElementFactory *factory = NULL;
7977         GstElement* queue = NULL;
7978         GstElement* parser = NULL;      
7979         GstPad *pssrcpad = NULL;
7980         GstPad *qsrcpad = NULL, *qsinkpad = NULL;
7981         MMPlayerGstElement *mainbin = NULL;
7982         GstStructure* str = NULL;
7983         GstCaps* srccaps = NULL;
7984         GstState warmup = GST_STATE_READY;
7985         gboolean isvideo_decoder = FALSE;
7986         guint q_max_size_time = 0;
7987
7988         debug_fenter();
7989
7990         return_val_if_fail ( player && 
7991                 player->pipeline && 
7992                 player->pipeline->mainbin, 
7993                 FALSE );
7994
7995         mainbin = player->pipeline->mainbin;
7996
7997         debug_log("plugging pad %s:%s to newly create %s:%s\n",
7998                                         GST_ELEMENT_NAME( GST_PAD_PARENT ( srcpad ) ),
7999                         GST_PAD_NAME( srcpad ),
8000                         GST_ELEMENT_NAME( sinkelement ),
8001                         padname);
8002
8003         factory = gst_element_get_factory(sinkelement);
8004         klass = gst_element_factory_get_klass(factory);
8005
8006         /* check if player can do start continually */
8007         MMPLAYER_CHECK_CMD_IF_EXIT(player);
8008
8009         if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state(sinkelement, warmup) )
8010         {
8011                 if (isvideo_decoder)
8012                         player->keep_detecting_vcodec = TRUE;
8013
8014                 debug_error("failed to set %d state to %s\n", warmup, GST_ELEMENT_NAME( sinkelement ));
8015                 goto ERROR;
8016         }
8017
8018         /* add to pipeline */
8019         if ( ! gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), sinkelement) )
8020         {
8021                 debug_error("failed to add %s to mainbin\n", GST_ELEMENT_NAME( sinkelement ));
8022                 goto ERROR;
8023         }
8024
8025         debug_log("element klass : %s\n", klass);
8026
8027         /* added to support multi track files */
8028         /* only decoder case and any of the video/audio still need to link*/
8029         if(g_strrstr(klass, "Decoder") && __mmplayer_link_decoder(player,srcpad))
8030         {
8031                 gchar *name = NULL;
8032
8033                 name = g_strdup(GST_ELEMENT_NAME( GST_PAD_PARENT ( srcpad )));
8034                 
8035                 if (g_strrstr(name, "mpegtsdemux"))
8036                 {
8037                         gchar *demux_caps = NULL;
8038                         gchar *parser_name = NULL;
8039                         GstCaps *dcaps = NULL;
8040
8041                         dcaps = gst_pad_get_caps(srcpad);
8042                         demux_caps = gst_caps_to_string(dcaps);
8043                         
8044                         if (g_strrstr(demux_caps, "video/x-h264"))
8045                         {
8046                                 parser_name = g_strdup("h264parse");
8047                         }
8048                         else if (g_strrstr(demux_caps, "video/mpeg"))
8049                         {
8050                                 parser_name = g_strdup("mpeg4videoparse");
8051                         }
8052                         
8053                         gst_caps_unref(dcaps);
8054                         MMPLAYER_FREEIF( demux_caps );
8055
8056                         if (parser_name)
8057                         {
8058                                 parser = __mmplayer_element_create_and_link(player, srcpad, parser_name);
8059
8060                                 MMPLAYER_FREEIF(parser_name);
8061                                 
8062                                 if ( ! parser )
8063                                 {
8064                                         debug_error("failed to create parser\n");
8065                                 }
8066                                 else
8067                                 {
8068                                         /* update srcpad if parser is created */
8069                                         pssrcpad = gst_element_get_static_pad(parser, "src");
8070                                         srcpad = pssrcpad;
8071                                 }
8072                         }
8073                 }
8074                 MMPLAYER_FREEIF(name);
8075
8076                 queue = __mmplayer_element_create_and_link(player, srcpad, "queue"); // parser - queue or demuxer - queue
8077                 if ( ! queue )
8078                 {
8079                         debug_error("failed to create queue\n");
8080                         goto ERROR;
8081                 }
8082
8083                 /* update srcpad to link with decoder */
8084                 qsrcpad = gst_element_get_static_pad(queue, "src");
8085                 srcpad = qsrcpad;
8086
8087                 q_max_size_time = GST_QUEUE_DEFAULT_TIME;
8088
8089                 /* assigning queue handle for futher manipulation purpose */
8090                 /* FIXIT : make it some kind of list so that msl can support more then two stream (text, data, etc...) */
8091                 if(mainbin[MMPLAYER_M_Q1].gst == NULL)
8092                 {
8093                         mainbin[MMPLAYER_M_Q1].id = MMPLAYER_M_Q1;
8094                         mainbin[MMPLAYER_M_Q1].gst = queue;
8095
8096                         g_object_set (G_OBJECT (mainbin[MMPLAYER_M_Q1].gst), "max-size-time", q_max_size_time * GST_SECOND, NULL);
8097                 }
8098                 else if(mainbin[MMPLAYER_M_Q2].gst == NULL)
8099                 {
8100                         mainbin[MMPLAYER_M_Q2].id = MMPLAYER_M_Q2;
8101                         mainbin[MMPLAYER_M_Q2].gst = queue;
8102
8103                         g_object_set (G_OBJECT (mainbin[MMPLAYER_M_Q2].gst), "max-size-time", q_max_size_time * GST_SECOND, NULL);
8104                 }
8105                 else
8106                 {
8107                         debug_critical("Not supporting more then two elementary stream\n");
8108                         g_assert(1);
8109                 }
8110
8111                 pad = gst_element_get_static_pad(sinkelement, padname);
8112
8113                 if ( ! pad )
8114                 {
8115                         debug_warning("failed to get pad(%s) from %s. retrying with [sink]\n",
8116                                 padname, GST_ELEMENT_NAME(sinkelement) );
8117
8118                         pad = gst_element_get_static_pad(sinkelement, "sink");
8119                         if ( ! pad )
8120                         {
8121                                 debug_error("failed to get pad(sink) from %s. \n",
8122                                 GST_ELEMENT_NAME(sinkelement) );
8123                                 goto ERROR;
8124                         }
8125                 }
8126
8127                 /*  to check the video/audio type set the proper flag*/
8128                 {
8129                         srccaps = gst_pad_get_caps( srcpad );
8130                         if ( !srccaps )
8131                                 goto ERROR;
8132
8133                         str = gst_caps_get_structure( srccaps, 0 );
8134                         if ( ! str )
8135                                 goto ERROR;
8136
8137                         name = gst_structure_get_name(str);
8138                         if ( ! name )
8139                                 goto ERROR;
8140                 }
8141
8142                 /* link queue and decoder. so, it will be queue - decoder. */
8143                 if ( GST_PAD_LINK_OK != gst_pad_link(srcpad, pad) )
8144                 {
8145                         gst_object_unref(GST_OBJECT(pad));
8146                         debug_error("failed to link (%s) to pad(%s)\n", GST_ELEMENT_NAME( sinkelement ), padname );
8147
8148                         /* reconstitute supportable codec */
8149                         if (strstr(name, "video"))
8150                         {
8151                                 player->can_support_codec ^= FOUND_PLUGIN_VIDEO;
8152                         }
8153                         else if (strstr(name, "audio"))
8154                         {
8155                                 player->can_support_codec ^= FOUND_PLUGIN_AUDIO;
8156                         }
8157                         goto ERROR;
8158                 }
8159
8160                 if (strstr(name, "video"))
8161                 {
8162                         player->videodec_linked = 1;
8163                         debug_msg("player->videodec_linked set to 1\n");
8164
8165                 }
8166                 else if (strstr(name, "audio"))
8167                 {
8168                         player->audiodec_linked = 1;
8169                         debug_msg("player->auddiodec_linked set to 1\n");
8170                 }
8171
8172                 gst_object_unref(GST_OBJECT(pad));
8173                 gst_caps_unref(GST_CAPS(srccaps));
8174                 srccaps = NULL;
8175         }
8176
8177         if ( !MMPLAYER_IS_HTTP_PD(player) )
8178         {
8179                 if( (g_strrstr(klass, "Demux") && !g_strrstr(klass, "Metadata")) || (g_strrstr(klass, "Parser") ) )
8180                 {
8181                         if (MMPLAYER_IS_HTTP_STREAMING(player))
8182                         {
8183                                 GstFormat fmt  = GST_FORMAT_BYTES;
8184                                 gint64 dur_bytes = 0L;
8185                                 gchar *file_buffering_path = NULL;
8186                                 gboolean use_file_buffer = FALSE;
8187
8188                                 if ( !mainbin[MMPLAYER_M_S_BUFFER].gst)
8189                                 {
8190                                         debug_log("creating http streaming buffering queue\n");
8191
8192                                         queue = gst_element_factory_make("queue2", "http_streaming_buffer");
8193                                         if ( ! queue )
8194                                         {
8195                                                 debug_critical ( "failed to create buffering queue element\n" );
8196                                                 goto ERROR;
8197                                         }
8198
8199                                         if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state(queue, GST_STATE_READY) )
8200                                         {
8201                                                 debug_error("failed to set state READY to buffering queue\n");
8202                                                 goto ERROR;
8203                                         }
8204
8205                                         if ( !gst_bin_add(GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), queue) )
8206                                         {
8207                                                 debug_error("failed to add buffering queue\n");
8208                                                 goto ERROR;
8209                                         }
8210
8211                                         qsinkpad = gst_element_get_static_pad(queue, "sink");
8212                                         qsrcpad = gst_element_get_static_pad(queue, "src");
8213
8214                                         if ( GST_PAD_LINK_OK != gst_pad_link(srcpad, qsinkpad) )
8215                                         {
8216                                                 debug_error("failed to link buffering queue\n");
8217                                                 goto ERROR;
8218                                         }
8219                                         srcpad = qsrcpad;
8220
8221
8222                                         mainbin[MMPLAYER_M_S_BUFFER].id = MMPLAYER_M_S_BUFFER;
8223                                         mainbin[MMPLAYER_M_S_BUFFER].gst = queue;
8224
8225                                         if ( !MMPLAYER_IS_HTTP_LIVE_STREAMING(player))
8226                                          {
8227                                                 if ( !gst_element_query_duration(player->pipeline->mainbin[MMPLAYER_M_SRC].gst, &fmt, &dur_bytes))
8228                                                         debug_error("fail to get duration.\n");
8229
8230                                                 if (dur_bytes>0)
8231                                                 {
8232                                                         use_file_buffer = MMPLAYER_USE_FILE_FOR_BUFFERING(player);
8233                                                         file_buffering_path = g_strdup(PLAYER_INI()->http_file_buffer_path);
8234                                                 }
8235                                         }
8236
8237                                         __mm_player_streaming_set_buffer(player->streamer,
8238                                                 queue,
8239                                                 TRUE,
8240                                                 PLAYER_INI()->http_max_size_bytes,
8241                                                 1.0,
8242                                                 PLAYER_INI()->http_buffering_limit,
8243                                                 PLAYER_INI()->http_buffering_time,
8244                                                 use_file_buffer,
8245                                                 file_buffering_path,
8246                                                 dur_bytes);
8247
8248                                         MMPLAYER_FREEIF(file_buffering_path);
8249                                 }
8250                         }
8251                 }
8252         }
8253         /* if it is not decoder or */
8254         /* in decoder case any of the video/audio still need to link*/
8255         if(!g_strrstr(klass, "Decoder"))
8256         {
8257
8258                 pad = gst_element_get_static_pad(sinkelement, padname);
8259                 if ( ! pad )
8260                 {
8261                         debug_warning("failed to get pad(%s) from %s. retrying with [sink]\n",
8262                                         padname, GST_ELEMENT_NAME(sinkelement) );
8263
8264                         pad = gst_element_get_static_pad(sinkelement, "sink");
8265
8266                         if ( ! pad )
8267                         {
8268                                 debug_error("failed to get pad(sink) from %s. \n",
8269                                         GST_ELEMENT_NAME(sinkelement) );
8270                                 goto ERROR;
8271                         }
8272                 }
8273
8274                 if ( GST_PAD_LINK_OK != gst_pad_link(srcpad, pad) )
8275                 {
8276                         gst_object_unref(GST_OBJECT(pad));
8277                         debug_error("failed to link (%s) to pad(%s)\n", GST_ELEMENT_NAME( sinkelement ), padname );
8278                         goto ERROR;
8279                 }
8280
8281                 gst_object_unref(GST_OBJECT(pad));
8282         }
8283
8284         for(;templlist != NULL; templlist = templlist->next)
8285         {
8286                 padtemplate = templlist->data;
8287
8288                 debug_log ("director = [%d], presence = [%d]\n", padtemplate->direction, padtemplate->presence);
8289
8290                 if(     padtemplate->direction != GST_PAD_SRC ||
8291                         padtemplate->presence == GST_PAD_REQUEST        )
8292                         continue;
8293
8294                 switch(padtemplate->presence)
8295                 {
8296                         case GST_PAD_ALWAYS:
8297                         {
8298                                 GstPad *srcpad = gst_element_get_static_pad(sinkelement, "src");
8299                                 GstCaps *caps = gst_pad_get_caps(srcpad);
8300
8301                                 /* Check whether caps has many types */
8302                                 if ( gst_caps_get_size (caps) > 1 && g_strrstr(klass, "Parser")) {
8303                                         debug_log ("has_many_types for this caps [%s]\n", gst_caps_to_string(caps));
8304                                         has_many_types = TRUE;
8305                                         break;
8306                                 }
8307
8308                                 if ( ! __mmplayer_try_to_plug(player, srcpad, caps) )
8309                                 {
8310                                         gst_object_unref(GST_OBJECT(srcpad));
8311                                         gst_caps_unref(GST_CAPS(caps));
8312
8313                                         debug_error("failed to plug something after %s\n", GST_ELEMENT_NAME( sinkelement ));
8314                                         goto ERROR;
8315                                 }
8316
8317                                 gst_caps_unref(GST_CAPS(caps));
8318                                 gst_object_unref(GST_OBJECT(srcpad));
8319
8320                         }
8321                         break;
8322
8323
8324                         case GST_PAD_SOMETIMES:
8325                                 has_dynamic_pads = TRUE;
8326                         break;
8327
8328                         default:
8329                                 break;
8330                 }
8331         }
8332
8333         /* check if player can do start continually */
8334         MMPLAYER_CHECK_CMD_IF_EXIT(player);
8335
8336         if( has_dynamic_pads )
8337         {
8338                 player->have_dynamic_pad = TRUE;
8339                 MMPLAYER_SIGNAL_CONNECT ( player, sinkelement, "pad-added",
8340                         G_CALLBACK(__mmplayer_add_new_pad), player);
8341
8342                 /* for streaming, more then one typefind will used for each elementary stream
8343                  * so this doesn't mean the whole pipeline completion
8344                  */
8345                 if ( ! MMPLAYER_IS_RTSP_STREAMING( player ) )
8346                 {
8347                         MMPLAYER_SIGNAL_CONNECT( player, sinkelement, "no-more-pads",
8348                                 G_CALLBACK(__mmplayer_pipeline_complete), player);
8349                 }
8350         }
8351
8352         if (has_many_types)
8353         {
8354                 GstPad *pad = NULL;
8355
8356                 player->has_many_types = has_many_types;
8357                 
8358                 pad = gst_element_get_static_pad(sinkelement, "src");
8359                 MMPLAYER_SIGNAL_CONNECT (player, pad, "notify::caps", G_CALLBACK(__mmplayer_add_new_caps), player);
8360                 gst_object_unref (GST_OBJECT(pad));
8361         }
8362
8363
8364         /* check if player can do start continually */
8365         MMPLAYER_CHECK_CMD_IF_EXIT(player);
8366
8367         if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state(sinkelement, GST_STATE_PAUSED) )
8368         {
8369                 debug_error("failed to set state PAUSED to %s\n", GST_ELEMENT_NAME( sinkelement ));
8370                 goto ERROR;
8371         }
8372
8373         if ( queue )
8374         {
8375                 if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state (queue, GST_STATE_PAUSED) )
8376                 {
8377                         debug_error("failed to set state PAUSED to queue\n");
8378                         goto ERROR;
8379                 }
8380
8381                 queue = NULL;
8382
8383                 gst_object_unref (GST_OBJECT(qsrcpad));
8384                 qsrcpad = NULL;
8385         }
8386
8387         if ( parser )
8388         {
8389                 if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state (parser, GST_STATE_PAUSED) )
8390                 {
8391                         debug_error("failed to set state PAUSED to queue\n");
8392                         goto ERROR;
8393                 }
8394
8395                 parser = NULL;
8396
8397                 gst_object_unref (GST_OBJECT(pssrcpad));
8398                 pssrcpad = NULL;
8399         }
8400
8401         debug_fleave();
8402
8403         return TRUE;
8404
8405 ERROR:
8406
8407         if ( queue )
8408         {
8409                 gst_object_unref(GST_OBJECT(qsrcpad));
8410
8411                 /* NOTE : Trying to dispose element queue0, but it is in READY instead of the NULL state.
8412                  * You need to explicitly set elements to the NULL state before
8413                  * dropping the final reference, to allow them to clean up.
8414                  */
8415                 gst_element_set_state(queue, GST_STATE_NULL);
8416                 /* And, it still has a parent "player".
8417                  * You need to let the parent manage the object instead of unreffing the object directly.
8418                  */
8419
8420                 gst_bin_remove (GST_BIN(mainbin[MMPLAYER_M_PIPE].gst), queue);
8421                 //gst_object_unref( queue );
8422         }
8423
8424         if ( srccaps )
8425                 gst_caps_unref(GST_CAPS(srccaps));
8426
8427     return FALSE;
8428 }
8429
8430 static gboolean __mmplayer_feature_filter(GstPluginFeature *feature, gpointer data) // @
8431 {
8432         const gchar *klass;
8433         //const gchar *name;
8434
8435         /* we only care about element factories */
8436         if (!GST_IS_ELEMENT_FACTORY(feature))
8437                 return FALSE;
8438
8439         /* only parsers, demuxers and decoders */
8440         klass = gst_element_factory_get_klass(GST_ELEMENT_FACTORY(feature));
8441         //name = gst_element_factory_get_longname(GST_ELEMENT_FACTORY(feature));
8442
8443         if( g_strrstr(klass, "Demux") == NULL &&
8444                 g_strrstr(klass, "Codec/Decoder") == NULL &&
8445                 g_strrstr(klass, "Depayloader") == NULL &&
8446                 g_strrstr(klass, "Parse") == NULL)
8447         {
8448                 return FALSE;
8449         }
8450     return TRUE;
8451 }
8452
8453
8454 static void     __mmplayer_add_new_caps(GstPad* pad, GParamSpec* unused, gpointer data)
8455 {
8456         mm_player_t* player = (mm_player_t*) data;
8457         GstCaps *caps = NULL;
8458         GstStructure *str = NULL;
8459         const char *name;
8460
8461         debug_fenter();
8462
8463         return_if_fail ( pad )
8464         return_if_fail ( unused )
8465         return_if_fail ( data )
8466
8467         caps = gst_pad_get_caps(pad);
8468         if ( !caps )
8469                 return;
8470         
8471         str = gst_caps_get_structure(caps, 0);
8472         if ( !str )
8473                 return;
8474
8475         name = gst_structure_get_name(str);
8476         if ( !name )
8477                 return;
8478         debug_log("name=%s\n", name);
8479
8480         if ( ! __mmplayer_try_to_plug(player, pad, caps) )
8481         {
8482                 debug_error("failed to autoplug for type (%s)\n", name);
8483                 gst_caps_unref(caps);
8484                 return;
8485         }
8486
8487         gst_caps_unref(caps);
8488
8489         __mmplayer_pipeline_complete( NULL, (gpointer)player );
8490
8491         debug_fleave(); 
8492
8493         return;
8494 }
8495
8496 static void __mmplayer_set_unlinked_mime_type(mm_player_t* player, GstCaps *caps)
8497 {
8498         GstStructure *str;
8499         gint version = 0;
8500         const char *stream_type;
8501         gchar *version_field = NULL;
8502
8503         debug_fenter();
8504
8505         return_if_fail ( player );
8506         return_if_fail ( caps );
8507         
8508         str = gst_caps_get_structure(caps, 0);
8509         if ( !str )
8510                 return;
8511         
8512         stream_type = gst_structure_get_name(str);
8513         if ( !stream_type )
8514                 return;
8515
8516
8517         /* set unlinked mime type for downloadable codec */
8518         if (g_str_has_prefix(stream_type, "video/"))
8519         {       
8520                 if (g_str_has_prefix(stream_type, "video/mpeg")) 
8521                 {
8522                         gst_structure_get_int (str, MM_PLAYER_MPEG_VNAME, &version);
8523                         version_field = MM_PLAYER_MPEG_VNAME;
8524                 }
8525                 else if (g_str_has_prefix(stream_type, "video/x-wmv"))
8526                 {
8527                         gst_structure_get_int (str, MM_PLAYER_WMV_VNAME, &version);
8528                         version_field = MM_PLAYER_WMV_VNAME;
8529                         
8530                 }
8531                 else if (g_str_has_prefix(stream_type, "video/x-divx"))
8532                 {
8533                         gst_structure_get_int (str, MM_PLAYER_DIVX_VNAME, &version);
8534                         version_field = MM_PLAYER_DIVX_VNAME;
8535                 }
8536
8537                 if (version)
8538                 {
8539                         player->unlinked_video_mime = g_strdup_printf("%s, %s=%d", stream_type, version_field, version);
8540                 }
8541                 else
8542                 {
8543                         player->unlinked_video_mime = g_strdup_printf("%s", stream_type);
8544                 }
8545         }
8546         else if (g_str_has_prefix(stream_type, "audio/"))
8547         {
8548                 if (g_str_has_prefix(stream_type, "audio/mpeg")) // mp3 or aac
8549                 {
8550                         gst_structure_get_int (str, MM_PLAYER_MPEG_VNAME, &version);
8551                         version_field = MM_PLAYER_MPEG_VNAME;
8552                 }
8553                 else if (g_str_has_prefix(stream_type, "audio/x-wma")) 
8554                 {
8555                         gst_structure_get_int (str, MM_PLAYER_WMA_VNAME, &version);
8556                         version_field = MM_PLAYER_WMA_VNAME;
8557                 }
8558
8559                 if (version)
8560                 {
8561                         player->unlinked_audio_mime = g_strdup_printf("%s, %s=%d", stream_type, version_field, version);
8562                 }
8563                 else
8564                 {
8565                         player->unlinked_audio_mime = g_strdup_printf("%s", stream_type);
8566                 }
8567         }
8568
8569         debug_fleave();
8570 }
8571
8572 static void __mmplayer_add_new_pad(GstElement *element, GstPad *pad, gpointer data)
8573 {
8574         mm_player_t* player = (mm_player_t*) data;
8575         GstCaps *caps = NULL;
8576         GstStructure *str = NULL;
8577         const char *name;
8578
8579         debug_fenter();
8580         return_if_fail ( player );
8581         return_if_fail ( pad );
8582
8583         GST_OBJECT_LOCK (pad);
8584         if ((caps = GST_PAD_CAPS(pad)))
8585                 gst_caps_ref(caps);
8586         GST_OBJECT_UNLOCK (pad);
8587
8588         if ( NULL == caps )
8589         {
8590                 caps = gst_pad_get_caps(pad);
8591                 if ( !caps ) return;
8592         }
8593
8594         MMPLAYER_LOG_GST_CAPS_TYPE(caps);
8595         
8596         str = gst_caps_get_structure(caps, 0);
8597         if ( !str )
8598                 return;
8599
8600         name = gst_structure_get_name(str);
8601         if ( !name )
8602                 return;
8603
8604         player->num_dynamic_pad++;
8605         debug_log("stream count inc : %d\n", player->num_dynamic_pad);
8606
8607         /* Note : If the stream is the subtitle, we try not to play it. Just close the demuxer subtitle pad.
8608           *     If want to play it, remove this code.
8609           */
8610         if (g_strrstr(name, "application"))
8611         {
8612                 if (g_strrstr(name, "x-id3") || g_strrstr(name, "x-apetag"))
8613                 {
8614                         /* If id3/ape tag comes, keep going */
8615                         debug_log("application mime exception : id3/ape tag");
8616                 }
8617                 else
8618                 {
8619                         /* Otherwise, we assume that this stream is subtile. */
8620                         debug_log(" application mime type pad is closed.");
8621                         return;
8622                 }
8623         }
8624         else if (g_strrstr(name, "audio"))
8625         {
8626                 gint samplerate = 0, channels = 0;
8627
8628                 /* set stream information */
8629                 /* if possible, set it here because the caps is not distrubed by resampler. */
8630                 gst_structure_get_int (str, "rate", &samplerate);
8631                 mm_attrs_set_int_by_name(player->attrs, "content_audio_samplerate", samplerate);
8632
8633                 gst_structure_get_int (str, "channels", &channels);
8634                 mm_attrs_set_int_by_name(player->attrs, "content_audio_channels", channels);
8635
8636                 debug_log("audio samplerate : %d        channels : %d", samplerate, channels);
8637
8638                 /* validate all */
8639                 if (  mmf_attrs_commit ( player->attrs ) )
8640                 {
8641                         debug_error("failed to update attributes");
8642                         return;
8643                 }
8644         }
8645         else if (g_strrstr(name, "video"))
8646         {
8647                 gint stype;
8648                 mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &stype);
8649
8650                 /* don't make video because of not required */
8651                 if (stype == MM_DISPLAY_SURFACE_NULL)
8652                 {
8653                         debug_log("no video because it's not required");
8654                         return;
8655                 }
8656
8657                 player->v_stream_caps = gst_caps_copy(caps); //if needed, video caps is required when videobin is created
8658         }
8659
8660         if ( ! __mmplayer_try_to_plug(player, pad, caps) )
8661         {
8662                 debug_error("failed to autoplug for type (%s)", name);
8663
8664                 __mmplayer_set_unlinked_mime_type(player, caps);
8665         }
8666
8667         gst_caps_unref(caps);
8668
8669         debug_fleave();
8670         return;
8671 }
8672
8673 /* test API for tuning audio gain. this API should be
8674  * deprecated before the day of final release
8675  */
8676 int
8677 _mmplayer_set_volume_tune(MMHandleType hplayer, MMPlayerVolumeType volume)
8678 {
8679         mm_player_t* player = (mm_player_t*) hplayer;
8680         gint error = MM_ERROR_NONE;
8681         gint vol_max = 0;
8682         gboolean isMidi = FALSE;
8683         gint i = 0;
8684
8685         debug_fenter();
8686
8687         return_val_if_fail( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
8688         return_val_if_fail( player->pipeline, MM_ERROR_PLAYER_NOT_INITIALIZED )
8689
8690         debug_log("clip type=%d(1-midi, 0-others), volume [L]=%d:[R]=%d\n",
8691                 player->profile.play_mode, volume.level[0], volume.level[1]);
8692
8693         isMidi = ( player->profile.play_mode == MM_PLAYER_MODE_MIDI ) ? TRUE : FALSE;
8694
8695         if ( isMidi )
8696                 vol_max = 1000;
8697         else
8698                 vol_max = 100;
8699
8700         /* is it proper volume level? */
8701         for (i = 0; i < MM_VOLUME_CHANNEL_NUM; ++i)
8702         {
8703                 if (volume.level[i] < 0 || volume.level[i] > vol_max) {
8704                         debug_log("Invalid Volume level!!!! \n");
8705                         return MM_ERROR_INVALID_ARGUMENT;
8706                 }
8707         }
8708
8709         if ( isMidi )
8710         {
8711                 if ( player->pipeline->mainbin )
8712                 {
8713                         GstElement *midi_element = player->pipeline->mainbin[MMPLAYER_M_DEMUX].gst;
8714
8715                         if ( midi_element && ( strstr(GST_ELEMENT_NAME(midi_element), "midiparse")) )
8716                         {
8717                                 debug_log("setting volume (%d) level to midi plugin\n", volume.level[0]);
8718
8719                                 g_object_set(midi_element, "volume", volume.level[0], NULL);
8720                         }
8721                 }
8722         }
8723         else
8724         {
8725                 if ( player->pipeline->audiobin )
8726                 {
8727                         GstElement *sink_element = player->pipeline->audiobin[MMPLAYER_A_SINK].gst;
8728
8729                         /* Set to Avsysaudiosink element */
8730                         if ( sink_element )
8731                         {
8732                                 gint vol_value = 0;
8733                                 gboolean mute = FALSE;
8734                                 vol_value = volume.level[0];
8735
8736                                 g_object_set(G_OBJECT(sink_element), "tuningvolume", vol_value, NULL);
8737
8738                                 mute = (vol_value == 0)? TRUE:FALSE;
8739
8740                                 g_object_set(G_OBJECT(sink_element), "mute", mute, NULL);
8741                         }
8742
8743                 }
8744         }
8745
8746         debug_fleave();
8747
8748         return error;
8749 }
8750
8751 gboolean
8752 __mmplayer_dump_pipeline_state( mm_player_t* player )
8753 {
8754         GstIterator*iter = NULL;
8755         gboolean done = FALSE;
8756
8757         GstElement *item = NULL;
8758         GstElementFactory *factory = NULL;
8759
8760         GstState state = GST_STATE_VOID_PENDING;
8761         GstState pending = GST_STATE_VOID_PENDING;
8762         GstClockTime time = 200*GST_MSECOND;
8763
8764         debug_fenter();
8765
8766         return_val_if_fail ( player &&
8767                 player->pipeline &&
8768                 player->pipeline->mainbin,
8769                 FALSE );
8770
8771
8772         iter = gst_bin_iterate_recurse(GST_BIN(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst) );
8773
8774         if ( iter != NULL )
8775         {
8776                 while (!done) {
8777                          switch ( gst_iterator_next (iter, (gpointer)&item) )
8778                          {
8779                            case GST_ITERATOR_OK:
8780                                 gst_element_get_state(GST_ELEMENT (item),&state, &pending,time);
8781
8782                                 factory = gst_element_get_factory (item) ;
8783                                  debug_log("%s:%s : From:%s To:%s   refcount : %d\n", GST_OBJECT_NAME(factory) , GST_ELEMENT_NAME(item) ,
8784                                         gst_element_state_get_name(state), gst_element_state_get_name(pending) , GST_OBJECT_REFCOUNT_VALUE(item));
8785
8786
8787                                  gst_object_unref (item);
8788                                  break;
8789                            case GST_ITERATOR_RESYNC:
8790                                  gst_iterator_resync (iter);
8791                                  break;
8792                            case GST_ITERATOR_ERROR:
8793                                  done = TRUE;
8794                                  break;
8795                            case GST_ITERATOR_DONE:
8796                                  done = TRUE;
8797                                  break;
8798                          }
8799                 }
8800         }
8801
8802         item = GST_ELEMENT(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst);
8803
8804         gst_element_get_state(GST_ELEMENT (item),&state, &pending,time);
8805
8806         factory = gst_element_get_factory (item) ;
8807
8808         debug_log("%s:%s : From:%s To:%s  refcount : %d\n",
8809                 GST_OBJECT_NAME(factory),
8810                 GST_ELEMENT_NAME(item),
8811                 gst_element_state_get_name(state),
8812                 gst_element_state_get_name(pending),
8813                 GST_OBJECT_REFCOUNT_VALUE(item) );
8814
8815         if ( iter )
8816                 gst_iterator_free (iter);
8817
8818         debug_fleave();
8819
8820         return FALSE;
8821 }
8822
8823
8824 gboolean
8825 __mmplayer_check_subtitle( mm_player_t* player )
8826 {
8827         MMHandleType attrs = 0;
8828         char *subtitle_uri = NULL;
8829
8830         debug_fenter();
8831
8832         return_val_if_fail( player, FALSE );
8833
8834         /* get subtitle attribute */
8835         attrs = MMPLAYER_GET_ATTRS(player);
8836         if ( !attrs )
8837                 return FALSE;
8838
8839         mm_attrs_get_string_by_name(attrs, "subtitle_uri", &subtitle_uri);
8840         if ( !subtitle_uri || !strlen(subtitle_uri))
8841                 return FALSE;
8842
8843         debug_log ("subtite uri is %s[%d]\n", subtitle_uri, strlen(subtitle_uri));
8844
8845         debug_fleave();
8846
8847         return TRUE;
8848 }
8849
8850 static gboolean
8851 __mmplayer_can_extract_pcm( mm_player_t* player )
8852 {
8853         MMHandleType attrs = 0;
8854         gboolean is_drm = FALSE;
8855         gboolean sound_extraction = FALSE;
8856
8857         debug_fenter();
8858
8859         return_val_if_fail ( player, FALSE );
8860
8861         attrs = MMPLAYER_GET_ATTRS(player);
8862         if ( !attrs )
8863         {
8864                 debug_error("fail to get attributes.");
8865                 return FALSE;
8866         }
8867         
8868         /* check file is drm or not */
8869         g_object_get(G_OBJECT(player->pipeline->mainbin[MMPLAYER_M_SRC].gst), "is-drm", &is_drm, NULL);
8870
8871         /* get sound_extraction property */
8872         mm_attrs_get_int_by_name(attrs, "pcm_extraction", &sound_extraction);
8873
8874         if ( ! sound_extraction || is_drm )
8875         {
8876                 debug_log("pcm extraction param.. is drm = %d, extraction mode = %d", is_drm, sound_extraction);
8877                 return FALSE;
8878         }
8879
8880         debug_fleave();
8881
8882         return TRUE;
8883 }
8884
8885 static gboolean
8886 __mmplayer_handle_gst_error ( mm_player_t* player, GstMessage * message, GError* error )
8887 {
8888         MMMessageParamType msg_param;
8889        gchar *msg_src_element;
8890
8891         debug_fenter();
8892
8893         return_val_if_fail( player, FALSE );
8894         return_val_if_fail( error, FALSE );
8895
8896         /* NOTE : do somthing necessary inside of __gst_handle_XXX_error. not here */
8897
8898         memset (&msg_param, 0, sizeof(MMMessageParamType));
8899
8900         if ( error->domain == GST_CORE_ERROR )
8901         {
8902                 msg_param.code = __gst_handle_core_error( player, error->code );
8903         }
8904         else if ( error->domain == GST_LIBRARY_ERROR )
8905         {
8906                 msg_param.code = __gst_handle_library_error( player, error->code );
8907         }
8908         else if ( error->domain == GST_RESOURCE_ERROR )
8909         {
8910                 msg_param.code = __gst_handle_resource_error( player, error->code );
8911         }
8912         else if ( error->domain == GST_STREAM_ERROR )
8913         {
8914                 msg_param.code = __gst_handle_stream_error( player, error, message );
8915         }
8916         else
8917         {
8918                 debug_warning("This error domain is not defined.\n");
8919
8920                 /* we treat system error as an internal error */
8921                 msg_param.code = MM_ERROR_PLAYER_INVALID_STREAM;
8922         }
8923
8924         if ( message->src )
8925         {
8926                 msg_src_element = GST_ELEMENT_NAME( GST_ELEMENT_CAST( message->src ) );
8927
8928                 msg_param.data = (void *) error->message;
8929
8930                 debug_error("-Msg src : [%s]    Domain : [%s]   Error : [%s]  Code : [%d] is tranlated to error code : [0x%x]\n",
8931                         msg_src_element, g_quark_to_string (error->domain), error->message, error->code, msg_param.code);
8932         }
8933
8934         /* post error to application */
8935         if ( ! player->posted_msg )
8936         {
8937                 if (msg_param.code == MM_MESSAGE_DRM_NOT_AUTHORIZED)
8938                 {
8939                         MMPLAYER_POST_MSG( player, MM_MESSAGE_DRM_NOT_AUTHORIZED, NULL );
8940                 }
8941                 else
8942                 {
8943                         MMPLAYER_POST_MSG( player, MM_MESSAGE_ERROR, &msg_param );
8944                 }
8945
8946                 /* don't post more if one was sent already */
8947                 player->posted_msg = TRUE;
8948         }
8949         else
8950         {
8951                 debug_log("skip error post because it's sent already.\n");
8952         }
8953
8954         debug_fleave();
8955
8956         return TRUE;
8957 }
8958
8959 static gboolean
8960 __mmplayer_handle_streaming_error  ( mm_player_t* player, GstMessage * message )
8961 {
8962         debug_log("\n");
8963         MMMessageParamType msg_param;
8964         gchar *msg_src_element = NULL;
8965         GstStructure *s = NULL;
8966         guint error_id = 0;
8967         gchar *error_string = NULL;
8968
8969         debug_fenter();
8970
8971         return_val_if_fail ( player, FALSE );
8972         return_val_if_fail ( message, FALSE );
8973
8974         s = malloc( sizeof(GstStructure) );
8975         memcpy ( s, gst_message_get_structure ( message ), sizeof(GstStructure));
8976
8977         if ( !gst_structure_get_uint (s, "error_id", &error_id) )
8978                 error_id = MMPLAYER_STREAMING_ERROR_NONE;
8979
8980         switch ( error_id )
8981         {
8982                 case MMPLAYER_STREAMING_ERROR_UNSUPPORTED_AUDIO:
8983                         msg_param.code = MM_ERROR_PLAYER_STREAMING_UNSUPPORTED_AUDIO;
8984                         break;
8985                 case MMPLAYER_STREAMING_ERROR_UNSUPPORTED_VIDEO:
8986                         msg_param.code = MM_ERROR_PLAYER_STREAMING_UNSUPPORTED_VIDEO;
8987                         break;
8988                 case MMPLAYER_STREAMING_ERROR_CONNECTION_FAIL:
8989                         msg_param.code = MM_ERROR_PLAYER_STREAMING_CONNECTION_FAIL;
8990                         break;
8991                 case MMPLAYER_STREAMING_ERROR_DNS_FAIL:
8992                         msg_param.code = MM_ERROR_PLAYER_STREAMING_DNS_FAIL;
8993                         break;
8994                 case MMPLAYER_STREAMING_ERROR_SERVER_DISCONNECTED:
8995                         msg_param.code = MM_ERROR_PLAYER_STREAMING_SERVER_DISCONNECTED;
8996                         break;
8997                 case MMPLAYER_STREAMING_ERROR_BAD_SERVER:
8998                         msg_param.code = MM_ERROR_PLAYER_STREAMING_BAD_SERVER;
8999                         break;
9000                 case MMPLAYER_STREAMING_ERROR_INVALID_PROTOCOL:
9001                         msg_param.code = MM_ERROR_PLAYER_STREAMING_INVALID_PROTOCOL;
9002                         break;
9003                 case MMPLAYER_STREAMING_ERROR_INVALID_URL:
9004                         msg_param.code = MM_ERROR_PLAYER_STREAMING_INVALID_URL;
9005                         break;
9006                 case MMPLAYER_STREAMING_ERROR_UNEXPECTED_MSG:
9007                         msg_param.code = MM_ERROR_PLAYER_STREAMING_UNEXPECTED_MSG;
9008                         break;
9009                 case MMPLAYER_STREAMING_ERROR_OUT_OF_MEMORIES:
9010                         msg_param.code = MM_ERROR_PLAYER_STREAMING_OUT_OF_MEMORIES;
9011                         break;
9012                 case MMPLAYER_STREAMING_ERROR_RTSP_TIMEOUT:
9013                         msg_param.code = MM_ERROR_PLAYER_STREAMING_RTSP_TIMEOUT;
9014                         break;
9015                 case MMPLAYER_STREAMING_ERROR_BAD_REQUEST:
9016                         msg_param.code = MM_ERROR_PLAYER_STREAMING_BAD_REQUEST;
9017                         break;
9018                 case MMPLAYER_STREAMING_ERROR_NOT_AUTHORIZED:
9019                         msg_param.code = MM_ERROR_PLAYER_STREAMING_NOT_AUTHORIZED;
9020                         break;
9021                 case MMPLAYER_STREAMING_ERROR_PAYMENT_REQUIRED:
9022                         msg_param.code = MM_ERROR_PLAYER_STREAMING_PAYMENT_REQUIRED;
9023                         break;
9024                 case MMPLAYER_STREAMING_ERROR_FORBIDDEN:
9025                         msg_param.code = MM_ERROR_PLAYER_STREAMING_FORBIDDEN;
9026                         break;
9027                 case MMPLAYER_STREAMING_ERROR_CONTENT_NOT_FOUND:
9028                         msg_param.code = MM_ERROR_PLAYER_STREAMING_CONTENT_NOT_FOUND;
9029                         break;
9030                 case MMPLAYER_STREAMING_ERROR_METHOD_NOT_ALLOWED:
9031                         msg_param.code = MM_ERROR_PLAYER_STREAMING_METHOD_NOT_ALLOWED;
9032                         break;
9033                 case MMPLAYER_STREAMING_ERROR_NOT_ACCEPTABLE:
9034                         msg_param.code = MM_ERROR_PLAYER_STREAMING_NOT_ACCEPTABLE;
9035                         break;
9036                 case MMPLAYER_STREAMING_ERROR_PROXY_AUTHENTICATION_REQUIRED:
9037                         msg_param.code = MM_ERROR_PLAYER_STREAMING_PROXY_AUTHENTICATION_REQUIRED;
9038                         break;
9039                 case MMPLAYER_STREAMING_ERROR_SERVER_TIMEOUT:
9040                         msg_param.code = MM_ERROR_PLAYER_STREAMING_SERVER_TIMEOUT;
9041                         break;
9042                 case MMPLAYER_STREAMING_ERROR_GONE:
9043                         msg_param.code = MM_ERROR_PLAYER_STREAMING_GONE;
9044                         break;
9045                 case MMPLAYER_STREAMING_ERROR_LENGTH_REQUIRED:
9046                         msg_param.code = MM_ERROR_PLAYER_STREAMING_LENGTH_REQUIRED;
9047                         break;
9048                 case MMPLAYER_STREAMING_ERROR_PRECONDITION_FAILED:
9049                         msg_param.code = MM_ERROR_PLAYER_STREAMING_PRECONDITION_FAILED;
9050                         break;
9051                 case MMPLAYER_STREAMING_ERROR_REQUEST_ENTITY_TOO_LARGE:
9052                         msg_param.code = MM_ERROR_PLAYER_STREAMING_REQUEST_ENTITY_TOO_LARGE;
9053                         break;
9054                 case MMPLAYER_STREAMING_ERROR_REQUEST_URI_TOO_LARGE:
9055                         msg_param.code = MM_ERROR_PLAYER_STREAMING_REQUEST_URI_TOO_LARGE;
9056                         break;
9057                 case MMPLAYER_STREAMING_ERROR_UNSUPPORTED_MEDIA_TYPE:
9058                         msg_param.code = MM_ERROR_PLAYER_STREAMING_UNSUPPORTED_MEDIA_TYPE;
9059                         break;
9060                 case MMPLAYER_STREAMING_ERROR_PARAMETER_NOT_UNDERSTOOD:
9061                         msg_param.code = MM_ERROR_PLAYER_STREAMING_PARAMETER_NOT_UNDERSTOOD;
9062                         break;
9063                 case MMPLAYER_STREAMING_ERROR_CONFERENCE_NOT_FOUND:
9064                         msg_param.code = MM_ERROR_PLAYER_STREAMING_CONFERENCE_NOT_FOUND;
9065                         break;
9066                 case MMPLAYER_STREAMING_ERROR_NOT_ENOUGH_BANDWIDTH:
9067                         msg_param.code = MM_ERROR_PLAYER_STREAMING_NOT_ENOUGH_BANDWIDTH;
9068                         break;
9069                 case MMPLAYER_STREAMING_ERROR_NO_SESSION_ID:
9070                         msg_param.code = MM_ERROR_PLAYER_STREAMING_NO_SESSION_ID;
9071                         break;
9072                 case MMPLAYER_STREAMING_ERROR_METHOD_NOT_VALID_IN_THIS_STATE:
9073                         msg_param.code = MM_ERROR_PLAYER_STREAMING_METHOD_NOT_VALID_IN_THIS_STATE;
9074                         break;
9075                 case MMPLAYER_STREAMING_ERROR_HEADER_FIELD_NOT_VALID_FOR_SOURCE:
9076                         msg_param.code = MM_ERROR_PLAYER_STREAMING_HEADER_FIELD_NOT_VALID_FOR_SOURCE;
9077                         break;
9078                 case MMPLAYER_STREAMING_ERROR_INVALID_RANGE:
9079                         msg_param.code = MM_ERROR_PLAYER_STREAMING_INVALID_RANGE;
9080                         break;
9081                 case MMPLAYER_STREAMING_ERROR_PARAMETER_IS_READONLY:
9082                         msg_param.code = MM_ERROR_PLAYER_STREAMING_PARAMETER_IS_READONLY;
9083                         break;
9084                 case MMPLAYER_STREAMING_ERROR_AGGREGATE_OP_NOT_ALLOWED:
9085                         msg_param.code = MM_ERROR_PLAYER_STREAMING_AGGREGATE_OP_NOT_ALLOWED;
9086                         break;
9087                 case MMPLAYER_STREAMING_ERROR_ONLY_AGGREGATE_OP_ALLOWED:
9088                         msg_param.code = MM_ERROR_PLAYER_STREAMING_ONLY_AGGREGATE_OP_ALLOWED;
9089                         break;
9090                 case MMPLAYER_STREAMING_ERROR_BAD_TRANSPORT:
9091                         msg_param.code = MM_ERROR_PLAYER_STREAMING_BAD_TRANSPORT;
9092                         break;
9093                 case MMPLAYER_STREAMING_ERROR_DESTINATION_UNREACHABLE:
9094                         msg_param.code = MM_ERROR_PLAYER_STREAMING_DESTINATION_UNREACHABLE;
9095                         break;
9096                 case MMPLAYER_STREAMING_ERROR_INTERNAL_SERVER_ERROR:
9097                         msg_param.code = MM_ERROR_PLAYER_STREAMING_INTERNAL_SERVER_ERROR;
9098                         break;
9099                 case MMPLAYER_STREAMING_ERROR_NOT_IMPLEMENTED:
9100                         msg_param.code = MM_ERROR_PLAYER_STREAMING_NOT_IMPLEMENTED;
9101                         break;
9102                 case MMPLAYER_STREAMING_ERROR_BAD_GATEWAY:
9103                         msg_param.code = MM_ERROR_PLAYER_STREAMING_BAD_GATEWAY;
9104                         break;
9105                 case MMPLAYER_STREAMING_ERROR_SERVICE_UNAVAILABLE:
9106                         msg_param.code = MM_ERROR_PLAYER_STREAMING_SERVICE_UNAVAILABLE;
9107                         break;
9108                 case MMPLAYER_STREAMING_ERROR_GATEWAY_TIME_OUT:
9109                         msg_param.code = MM_ERROR_PLAYER_STREAMING_GATEWAY_TIME_OUT;
9110                         break;
9111                 case MMPLAYER_STREAMING_ERROR_RTSP_VERSION_NOT_SUPPORTED:
9112                         msg_param.code = MM_ERROR_PLAYER_STREAMING_RTSP_VERSION_NOT_SUPPORTED;
9113                         break;
9114                 case MMPLAYER_STREAMING_ERROR_OPTION_NOT_SUPPORTED:
9115                         msg_param.code = MM_ERROR_PLAYER_STREAMING_OPTION_NOT_SUPPORTED;
9116                         break;
9117                 default:
9118                         return MM_ERROR_PLAYER_STREAMING_FAIL;
9119         }
9120
9121         error_string = g_strdup(gst_structure_get_string (s, "error_string"));
9122         if ( error_string )
9123                 msg_param.data = (void *) error_string;
9124
9125         if ( message->src )
9126         {
9127                 msg_src_element = GST_ELEMENT_NAME( GST_ELEMENT_CAST( message->src ) );
9128
9129                 debug_error("-Msg src : [%s] Code : [%x] Error : [%s]  \n",
9130                         msg_src_element, msg_param.code, (char*)msg_param.data );
9131         }
9132
9133         /* post error to application */
9134         if ( ! player->posted_msg )
9135         {
9136                 MMPLAYER_POST_MSG( player, MM_MESSAGE_ERROR, &msg_param );
9137
9138                 /* don't post more if one was sent already */
9139                 player->posted_msg = TRUE;
9140         }
9141         else
9142         {
9143                 debug_log("skip error post because it's sent already.\n");
9144         }
9145
9146         debug_fleave();
9147
9148         return TRUE;
9149
9150 }
9151
9152 static gint
9153 __gst_handle_core_error( mm_player_t* player, int code )
9154 {
9155         gint trans_err = MM_ERROR_NONE;
9156
9157         debug_fenter();
9158
9159         return_val_if_fail( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
9160
9161         switch ( code )
9162         {
9163                 case GST_CORE_ERROR_STATE_CHANGE:
9164                 case GST_CORE_ERROR_MISSING_PLUGIN:
9165                 case GST_CORE_ERROR_SEEK:
9166                 case GST_CORE_ERROR_NOT_IMPLEMENTED:
9167                 case GST_CORE_ERROR_FAILED:
9168                 case GST_CORE_ERROR_TOO_LAZY:
9169                 case GST_CORE_ERROR_PAD:
9170                 case GST_CORE_ERROR_THREAD:
9171                 case GST_CORE_ERROR_NEGOTIATION:
9172                 case GST_CORE_ERROR_EVENT:
9173                 case GST_CORE_ERROR_CAPS:
9174                 case GST_CORE_ERROR_TAG:
9175                 case GST_CORE_ERROR_CLOCK:
9176                 case GST_CORE_ERROR_DISABLED:
9177                 default:
9178                         trans_err = MM_ERROR_PLAYER_INVALID_STREAM;
9179                 break;
9180         }
9181
9182         debug_fleave();
9183
9184         return trans_err;
9185 }
9186
9187 static gint
9188 __gst_handle_library_error( mm_player_t* player, int code )
9189 {
9190         gint trans_err = MM_ERROR_NONE;
9191
9192         debug_fenter();
9193
9194         return_val_if_fail( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
9195
9196         switch ( code )
9197         {
9198                 case GST_LIBRARY_ERROR_FAILED:
9199                 case GST_LIBRARY_ERROR_TOO_LAZY:
9200                 case GST_LIBRARY_ERROR_INIT:
9201                 case GST_LIBRARY_ERROR_SHUTDOWN:
9202                 case GST_LIBRARY_ERROR_SETTINGS:
9203                 case GST_LIBRARY_ERROR_ENCODE:
9204                 default:
9205                         trans_err =  MM_ERROR_PLAYER_INVALID_STREAM;
9206                 break;
9207         }
9208         
9209         debug_fleave();
9210
9211         return trans_err;
9212 }
9213
9214
9215 static gint
9216 __gst_handle_resource_error( mm_player_t* player, int code )
9217 {
9218         gint trans_err = MM_ERROR_NONE;
9219
9220         debug_fenter();
9221
9222         return_val_if_fail( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
9223
9224         switch ( code )
9225         {
9226                 case GST_RESOURCE_ERROR_NO_SPACE_LEFT:
9227                         trans_err = MM_ERROR_PLAYER_NO_FREE_SPACE;
9228                         break;
9229                 case GST_RESOURCE_ERROR_NOT_FOUND:
9230                 case GST_RESOURCE_ERROR_OPEN_READ:
9231                         if ( MMPLAYER_IS_HTTP_STREAMING(player) || MMPLAYER_IS_HTTP_LIVE_STREAMING ( player ) )
9232                         {
9233                                 trans_err = MM_ERROR_PLAYER_STREAMING_CONNECTION_FAIL;
9234                                 break;
9235                         }
9236                 case GST_RESOURCE_ERROR_READ:
9237                         if ( MMPLAYER_IS_HTTP_STREAMING(player) ||  MMPLAYER_IS_HTTP_LIVE_STREAMING ( player ))
9238                         {
9239                                 trans_err = MM_ERROR_PLAYER_STREAMING_FAIL;
9240                                 break;
9241                         }
9242                 case GST_RESOURCE_ERROR_SEEK:
9243                 case GST_RESOURCE_ERROR_FAILED:
9244                 case GST_RESOURCE_ERROR_TOO_LAZY:
9245                 case GST_RESOURCE_ERROR_BUSY:
9246                 case GST_RESOURCE_ERROR_OPEN_WRITE:
9247                 case GST_RESOURCE_ERROR_OPEN_READ_WRITE:
9248                 case GST_RESOURCE_ERROR_CLOSE:
9249                 case GST_RESOURCE_ERROR_WRITE:
9250                 case GST_RESOURCE_ERROR_SYNC:
9251                 case GST_RESOURCE_ERROR_SETTINGS:
9252                 default:
9253                         trans_err = MM_ERROR_PLAYER_FILE_NOT_FOUND;
9254                 break;
9255         }
9256
9257         debug_fleave();
9258
9259         return trans_err;
9260 }
9261
9262
9263 static gint
9264 __gst_handle_stream_error( mm_player_t* player, GError* error, GstMessage * message )
9265 {
9266         gint trans_err = MM_ERROR_NONE;
9267
9268         debug_fenter();
9269
9270         return_val_if_fail( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
9271         return_val_if_fail( error, MM_ERROR_INVALID_ARGUMENT );
9272         return_val_if_fail ( message, MM_ERROR_INVALID_ARGUMENT );
9273
9274         switch ( error->code )
9275         {
9276                 case GST_STREAM_ERROR_FAILED:
9277                 case GST_STREAM_ERROR_TYPE_NOT_FOUND:
9278                 case GST_STREAM_ERROR_DECODE:
9279                 case GST_STREAM_ERROR_WRONG_TYPE:
9280                 case GST_STREAM_ERROR_DECRYPT:
9281                          trans_err = __gst_transform_gsterror( player, message, error );
9282                 break;
9283
9284                 case GST_STREAM_ERROR_CODEC_NOT_FOUND:
9285                 case GST_STREAM_ERROR_NOT_IMPLEMENTED:
9286                 case GST_STREAM_ERROR_TOO_LAZY:
9287                 case GST_STREAM_ERROR_ENCODE:
9288                 case GST_STREAM_ERROR_DEMUX:
9289                 case GST_STREAM_ERROR_MUX:
9290                 case GST_STREAM_ERROR_FORMAT:
9291                 case GST_STREAM_ERROR_DECRYPT_NOKEY:
9292                 default:
9293                         trans_err = MM_ERROR_PLAYER_INVALID_STREAM;
9294                 break;
9295         }
9296
9297         debug_fleave();
9298
9299         return trans_err;
9300 }
9301
9302
9303 /* NOTE : decide gstreamer state whether there is some playable track or not. */
9304 static gint
9305 __gst_transform_gsterror( mm_player_t* player, GstMessage * message, GError* error )
9306 {
9307         gchar *src_element_name = NULL;
9308         GstElement *src_element = NULL;
9309         GstElementFactory *factory = NULL;
9310         const gchar* klass = NULL;
9311         
9312         debug_fenter();
9313
9314         /* FIXIT */
9315         return_val_if_fail ( message, MM_ERROR_INVALID_ARGUMENT );
9316         return_val_if_fail ( message->src, MM_ERROR_INVALID_ARGUMENT );
9317         return_val_if_fail ( error, MM_ERROR_INVALID_ARGUMENT );
9318
9319         src_element = GST_ELEMENT_CAST(message->src);
9320         if ( !src_element )
9321                 goto INTERNAL_ERROR;
9322         
9323         src_element_name = GST_ELEMENT_NAME(src_element);
9324         if ( !src_element_name )
9325                 goto INTERNAL_ERROR;
9326
9327         factory = gst_element_get_factory(src_element);
9328         if ( !factory )
9329                 goto INTERNAL_ERROR;
9330         
9331         klass = gst_element_factory_get_klass(factory);
9332         if ( !klass )
9333                 goto INTERNAL_ERROR;
9334
9335         debug_log("error code=%d, msg=%s, src element=%s, class=%s\n", 
9336                         error->code, error->message, src_element_name, klass);
9337
9338
9339         switch ( error->code )
9340         {
9341                 case GST_STREAM_ERROR_DECODE:
9342                 {
9343                         /* NOTE : Delay is needed because gst callback is sometime sent
9344                          * before completing autoplugging.
9345                          * Timer is more better than usleep.
9346                          * But, transformed msg value should be stored in player handle
9347                          * for function to call by timer.
9348                          */
9349                         if ( PLAYER_INI()->async_start )
9350                                 usleep(500000);
9351
9352                         /* Demuxer can't parse one track because it's corrupted.
9353                          * So, the decoder for it is not linked.
9354                          * But, it has one playable track.
9355                          */
9356                         if ( g_strrstr(klass, "Demux") )
9357                         {
9358                                 if ( player->can_support_codec == FOUND_PLUGIN_VIDEO )
9359                                 {
9360                                         return MM_ERROR_PLAYER_AUDIO_CODEC_NOT_FOUND;
9361                                 }
9362                                 else if ( player->can_support_codec == FOUND_PLUGIN_AUDIO )
9363                                 {
9364                                         return MM_ERROR_PLAYER_VIDEO_CODEC_NOT_FOUND;
9365                                 }
9366                                 else
9367                                 {
9368                                         if ( player->pipeline->audiobin ) // PCM
9369                                         {
9370                                                 return MM_ERROR_PLAYER_VIDEO_CODEC_NOT_FOUND;
9371                                         }
9372                                         else
9373                                         {
9374                                                 goto CODEC_NOT_FOUND;
9375                                         }
9376                                 }
9377                         }
9378                         return MM_ERROR_PLAYER_INVALID_STREAM;
9379                 }
9380                 break;
9381
9382                 case GST_STREAM_ERROR_WRONG_TYPE:
9383                 {
9384                         return MM_ERROR_PLAYER_NOT_SUPPORTED_FORMAT;
9385                 }
9386                 break;
9387
9388                 case GST_STREAM_ERROR_FAILED:
9389                 {
9390                         /* Decoder Custom Message */
9391                         if ( strstr(error->message, "ongoing") )
9392                         {
9393                                 if ( strcasestr(klass, "audio") )
9394                                 {
9395                                         if ( ( player->can_support_codec & FOUND_PLUGIN_VIDEO ) )
9396                                         {
9397                                                 debug_log("Video can keep playing.\n");
9398                                                 return MM_ERROR_PLAYER_AUDIO_CODEC_NOT_FOUND;
9399                                         }
9400                                         else
9401                                         {
9402                                                 goto CODEC_NOT_FOUND;
9403                                         }
9404
9405                                 }
9406                                 else if ( strcasestr(klass, "video") )
9407                                 {
9408                                         if ( ( player->can_support_codec & FOUND_PLUGIN_AUDIO ) )
9409                                         {
9410                                                 debug_log("Audio can keep playing.\n");
9411                                                 return MM_ERROR_PLAYER_VIDEO_CODEC_NOT_FOUND;
9412                                         }
9413                                         else
9414                                         {
9415                                                 goto CODEC_NOT_FOUND;
9416                                         }
9417                                 }
9418                         }
9419         return MM_ERROR_PLAYER_INVALID_STREAM;
9420                 }
9421                 break;
9422
9423                 case GST_STREAM_ERROR_TYPE_NOT_FOUND:
9424                 {                               
9425                         goto CODEC_NOT_FOUND;
9426                 }
9427                 break;
9428
9429                 case GST_STREAM_ERROR_DECRYPT:
9430                 {                               
9431                         debug_log("%s failed reason : %s\n", src_element_name, error->message);
9432                         return MM_MESSAGE_DRM_NOT_AUTHORIZED;
9433                 }
9434                 break;
9435
9436                 default:
9437                 break;
9438         }
9439
9440         debug_fleave();
9441
9442         return MM_ERROR_PLAYER_INVALID_STREAM;
9443
9444 INTERNAL_ERROR:
9445         return MM_ERROR_PLAYER_INTERNAL;
9446
9447 CODEC_NOT_FOUND:
9448         debug_log("not found any available codec. Player should be destroyed.\n");
9449         return MM_ERROR_PLAYER_CODEC_NOT_FOUND;
9450 }
9451
9452 static void
9453 __mmplayer_post_delayed_eos( mm_player_t* player, int delay_in_ms )
9454 {
9455         debug_fenter();
9456
9457         return_if_fail( player );
9458
9459         /* cancel if existing */
9460         __mmplayer_cancel_delayed_eos( player );
9461
9462
9463         /* post now if delay is zero */
9464         if ( delay_in_ms == 0 || player->is_sound_extraction)
9465         {
9466                 debug_log("eos delay is zero. posting EOS now\n");
9467                 MMPLAYER_POST_MSG( player, MM_MESSAGE_END_OF_STREAM, NULL );
9468
9469                 if ( player->is_sound_extraction )
9470                         __mmplayer_cancel_delayed_eos(player);
9471
9472                 return;
9473         }
9474
9475         /* init new timeout */
9476         /* NOTE : consider give high priority to this timer */
9477
9478         debug_log("posting EOS message after [%d] msec\n", delay_in_ms);
9479         player->eos_timer = g_timeout_add( delay_in_ms,
9480                 __mmplayer_eos_timer_cb, player );
9481
9482
9483         /* check timer is valid. if not, send EOS now */
9484         if ( player->eos_timer == 0 )
9485         {
9486                 debug_warning("creating timer for delayed EOS has failed. sending EOS now\n");
9487                 MMPLAYER_POST_MSG( player, MM_MESSAGE_END_OF_STREAM, NULL );
9488         }
9489
9490         debug_fleave();
9491 }
9492
9493 static void
9494 __mmplayer_cancel_delayed_eos( mm_player_t* player )
9495 {
9496         debug_fenter();
9497
9498         return_if_fail( player );
9499
9500         if ( player->eos_timer )
9501         {
9502                 g_source_remove( player->eos_timer );
9503         }
9504
9505         player->eos_timer = 0;
9506
9507         debug_fleave();
9508
9509         return;
9510 }
9511
9512 static gboolean
9513 __mmplayer_eos_timer_cb(gpointer u_data)
9514 {
9515         mm_player_t* player = NULL;
9516         player = (mm_player_t*) u_data;
9517
9518         debug_fenter();
9519
9520         return_val_if_fail( player, FALSE );
9521
9522         /* posting eos */
9523         MMPLAYER_POST_MSG( player, MM_MESSAGE_END_OF_STREAM, NULL );
9524
9525         /* cleare timer id */
9526         player->eos_timer = 0;
9527
9528         debug_fleave();
9529
9530         /* we are returning FALSE as we need only one posting */
9531         return FALSE;
9532 }
9533
9534 static void __mmplayer_set_antishock( mm_player_t* player, gboolean disable_by_force)
9535 {
9536         gint antishock = FALSE;
9537         MMHandleType attrs = 0;
9538
9539         debug_fenter();
9540
9541         return_if_fail ( player && player->pipeline );
9542
9543         /* It should be passed for video only clip */
9544         if ( ! player->pipeline->audiobin )
9545                 return;
9546
9547         if ( ( g_strrstr(PLAYER_INI()->name_of_audiosink, "avsysaudiosink")) )
9548         {
9549                 attrs = MMPLAYER_GET_ATTRS(player);
9550                 if ( ! attrs )
9551                 {
9552                         debug_error("fail to get attributes.\n");
9553                         return;
9554                 }
9555
9556                 mm_attrs_get_int_by_name(attrs, "sound_fadeup", &antishock);
9557
9558                 debug_log("setting antishock as (%d)\n", antishock);
9559
9560                 if ( disable_by_force )
9561                 {
9562                         debug_log("but, antishock is disabled by force when is seeked\n");
9563
9564                         antishock = FALSE;
9565                 }
9566
9567                 g_object_set(G_OBJECT(player->pipeline->audiobin[MMPLAYER_A_SINK].gst), "fadeup", antishock, NULL);
9568         }
9569
9570         debug_fleave();
9571
9572         return;
9573 }
9574
9575
9576 static gboolean
9577 __mmplayer_link_decoder( mm_player_t* player, GstPad *srcpad)
9578 {
9579         const gchar* name = NULL;
9580         GstStructure* str = NULL;
9581         GstCaps* srccaps = NULL;
9582
9583         debug_fenter();
9584
9585         return_val_if_fail( player, FALSE );
9586         return_val_if_fail ( srcpad, FALSE );
9587
9588         /* to check any of the decoder (video/audio) need to be linked  to parser*/
9589         srccaps = gst_pad_get_caps( srcpad );
9590         if ( !srccaps )
9591                 goto ERROR;
9592
9593         str = gst_caps_get_structure( srccaps, 0 );
9594         if ( ! str )
9595                 goto ERROR;
9596
9597         name = gst_structure_get_name(str);
9598         if ( ! name )
9599                 goto ERROR;
9600
9601         if (strstr(name, "video"))
9602         {
9603                 if(player->videodec_linked)
9604                 {
9605                     debug_msg("Video decoder already linked\n");
9606                         return FALSE;
9607                 }
9608         }
9609         if (strstr(name, "audio"))
9610         {
9611                 if(player->audiodec_linked)
9612                 {
9613                     debug_msg("Audio decoder already linked\n");
9614                         return FALSE;
9615                 }
9616         }
9617
9618         gst_caps_unref( srccaps );
9619
9620         debug_fleave();
9621
9622         return TRUE;
9623
9624 ERROR:
9625         if ( srccaps )
9626                 gst_caps_unref( srccaps );
9627
9628         return FALSE;
9629 }
9630
9631 static gboolean
9632 __mmplayer_link_sink( mm_player_t* player , GstPad *srcpad)
9633 {
9634         const gchar* name = NULL;
9635         GstStructure* str = NULL;
9636         GstCaps* srccaps = NULL;
9637
9638         debug_fenter();
9639
9640         return_val_if_fail ( player, FALSE );
9641         return_val_if_fail ( srcpad, FALSE );
9642
9643         /* to check any of the decoder (video/audio) need to be linked  to parser*/
9644         srccaps = gst_pad_get_caps( srcpad );
9645         if ( !srccaps )
9646                 goto ERROR;
9647
9648         str = gst_caps_get_structure( srccaps, 0 );
9649         if ( ! str )
9650                 goto ERROR;
9651
9652         name = gst_structure_get_name(str);
9653         if ( ! name )
9654                 goto ERROR;
9655
9656         if (strstr(name, "video"))
9657         {
9658                 if(player->videosink_linked)
9659                 {
9660                         debug_msg("Video Sink already linked\n");
9661                         return FALSE;
9662                 }
9663         }
9664         if (strstr(name, "audio"))
9665         {
9666                 if(player->audiosink_linked)
9667                 {
9668                         debug_msg("Audio Sink already linked\n");
9669                         return FALSE;
9670                 }
9671         }
9672         if (strstr(name, "text"))
9673         {
9674                 if(player->textsink_linked)
9675                 {
9676                         debug_msg("Text Sink already linked\n");
9677                         return FALSE;
9678                 }
9679         }
9680
9681         gst_caps_unref( srccaps );
9682
9683         debug_fleave();
9684
9685         return TRUE;
9686         //return (!player->videosink_linked || !player->audiosink_linked);
9687
9688 ERROR:
9689         if ( srccaps )
9690                 gst_caps_unref( srccaps );
9691
9692         return FALSE;
9693 }
9694
9695
9696 /* sending event to one of sinkelements */
9697 static gboolean
9698 __gst_send_event_to_sink( mm_player_t* player, GstEvent* event )
9699 {
9700         GList *sinks = NULL;
9701         gboolean res = FALSE;
9702
9703         debug_fenter();
9704         
9705         return_val_if_fail( player, FALSE );
9706         return_val_if_fail ( event, FALSE );
9707
9708         sinks = player->sink_elements;
9709         while (sinks)
9710         {
9711                 GstElement *sink = GST_ELEMENT_CAST (sinks->data);
9712
9713                 if (GST_IS_ELEMENT(sink))
9714                 {
9715                         /* keep ref to the event */
9716                         gst_event_ref (event);
9717
9718                         if ( (res = gst_element_send_event (sink, event)) )
9719                         {
9720                                 debug_log("sending event[%s] to sink element [%s] success!\n",
9721                                         GST_EVENT_TYPE_NAME(event), GST_ELEMENT_NAME(sink) );
9722                                 break;
9723                         }
9724
9725                         debug_log("sending event[%s] to sink element [%s] failed. try with next one.\n",
9726                                 GST_EVENT_TYPE_NAME(event), GST_ELEMENT_NAME(sink) );
9727                 }
9728
9729                 sinks = g_list_next (sinks);
9730         }
9731
9732         /* Note : Textbin is not linked to the video or audio bin.
9733          *              It needs to send the event to the text sink seperatelly.
9734          */
9735          if ( MMPLAYER_PLAY_SUBTITLE(player) )
9736          {
9737                 GstElement *subtitle_sink = GST_ELEMENT_CAST (player->pipeline->subtitlebin[MMPLAYER_SUB_SINK].gst);
9738
9739                 if ( (res != gst_element_send_event (subtitle_sink, event)) )
9740                 {
9741                         debug_error("sending event[%s] to subtitle sink element [%s] failed!\n",
9742                                 GST_EVENT_TYPE_NAME(event), GST_ELEMENT_NAME(subtitle_sink) );
9743                 }
9744                 else
9745                 {
9746                         debug_log("sending event[%s] to subtitle sink element [%s] success!\n",
9747                                 GST_EVENT_TYPE_NAME(event), GST_ELEMENT_NAME(subtitle_sink) );
9748                 }
9749          }
9750
9751         gst_event_unref (event);
9752
9753         debug_fleave();
9754
9755         return res;
9756 }
9757
9758 static void
9759 __mmplayer_add_sink( mm_player_t* player, GstElement* sink )
9760 {
9761         debug_fenter();
9762
9763         return_if_fail ( player );
9764         return_if_fail ( sink );
9765
9766         player->sink_elements =
9767                 g_list_append(player->sink_elements, sink);
9768
9769         debug_fleave();
9770 }
9771
9772 static void
9773 __mmplayer_del_sink( mm_player_t* player, GstElement* sink )
9774 {
9775         debug_fenter();
9776
9777         return_if_fail ( player );
9778         return_if_fail ( sink );
9779
9780         player->sink_elements =
9781                         g_list_remove(player->sink_elements, sink);
9782
9783         debug_fleave();
9784 }
9785
9786 static gboolean
9787 __gst_seek(mm_player_t* player, GstElement * element, gdouble rate,
9788                         GstFormat format, GstSeekFlags flags, GstSeekType cur_type,
9789                         gint64 cur, GstSeekType stop_type, gint64 stop )
9790 {
9791         GstEvent* event = NULL;
9792         gboolean result = FALSE;
9793
9794         debug_fenter();
9795         
9796         return_val_if_fail( player, FALSE );
9797
9798         event = gst_event_new_seek (rate, format, flags, cur_type,
9799                 cur, stop_type, stop);
9800
9801         result = __gst_send_event_to_sink( player, event );
9802
9803         debug_fleave();
9804
9805         return result;
9806 }
9807
9808 /* NOTE : be careful with calling this api. please refer to below glib comment
9809  * glib comment : Note that there is a bug in GObject that makes this function much
9810  * less useful than it might seem otherwise. Once gobject is disposed, the callback
9811  * will no longer be called, but, the signal handler is not currently disconnected.
9812  * If the instance is itself being freed at the same time than this doesn't matter,
9813  * since the signal will automatically be removed, but if instance persists,
9814  * then the signal handler will leak. You should not remove the signal yourself
9815  * because in a future versions of GObject, the handler will automatically be
9816  * disconnected.
9817  *
9818  * It's possible to work around this problem in a way that will continue to work
9819  * with future versions of GObject by checking that the signal handler is still
9820  * connected before disconnected it:
9821  *
9822  *  if (g_signal_handler_is_connected (instance, id))
9823  *    g_signal_handler_disconnect (instance, id);
9824  */
9825 static void
9826 __mmplayer_release_signal_connection(mm_player_t* player)
9827 {
9828         GList* sig_list = player->signals;
9829         MMPlayerSignalItem* item = NULL;
9830
9831         debug_fenter();
9832         
9833         return_if_fail( player );
9834
9835         for ( ; sig_list; sig_list = sig_list->next )
9836         {
9837                 item = sig_list->data;
9838
9839                 if ( item && item->obj && GST_IS_ELEMENT(item->obj) )
9840                 {
9841                         debug_log("checking signal connection : [%lud] from [%s]\n", item->sig, GST_OBJECT_NAME( item->obj ));
9842
9843                         if ( g_signal_handler_is_connected ( item->obj, item->sig ) )
9844                         {
9845                                 debug_log("signal disconnecting : [%lud] from [%s]\n", item->sig, GST_OBJECT_NAME( item->obj ));
9846                                 g_signal_handler_disconnect ( item->obj, item->sig );
9847                         }
9848                 }
9849
9850                 MMPLAYER_FREEIF( item );
9851
9852         }
9853         g_list_free ( player->signals );
9854         player->signals = NULL;
9855
9856         debug_fleave();
9857
9858         return;
9859 }
9860
9861
9862 /* Note : if silent is true, then subtitle would not be displayed. :*/
9863 int _mmplayer_set_subtitle_silent (MMHandleType hplayer, int silent)
9864 {
9865         mm_player_t* player = (mm_player_t*) hplayer;
9866
9867         debug_fenter();
9868
9869         /* check player handle */
9870         return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED );
9871         return_val_if_fail ( MMPLAYER_PLAY_SUBTITLE(player),    MM_ERROR_PLAYER_NOT_INITIALIZED );
9872
9873         player->is_subtitle_off = silent;
9874
9875         debug_log("subtitle is %s.\n", player->is_subtitle_off ? "ON" : "OFF");
9876
9877         debug_fleave();
9878
9879         return MM_ERROR_NONE;
9880 }
9881
9882
9883 int _mmplayer_get_subtitle_silent (MMHandleType hplayer, int* silent)
9884 {
9885         mm_player_t* player = (mm_player_t*) hplayer;
9886
9887         debug_fenter();
9888
9889         /* check player handle */
9890         return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED );
9891         return_val_if_fail ( MMPLAYER_PLAY_SUBTITLE(player),    MM_ERROR_PLAYER_NOT_INITIALIZED );
9892
9893         *silent = player->is_subtitle_off;
9894
9895         debug_log("subtitle is %s.\n", silent ? "ON" : "OFF");
9896
9897         debug_fleave();
9898
9899         return MM_ERROR_NONE;
9900 }
9901
9902 int _mmplayer_get_track_count(MMHandleType hplayer,  MMPlayerTrackType track_type, int *count)
9903 {
9904         mm_player_t* player = (mm_player_t*) hplayer;
9905         MMHandleType attrs = 0;
9906         int ret = MM_ERROR_NONE;
9907
9908         debug_fenter();
9909
9910         /* check player handle */
9911         return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
9912         return_val_if_fail(count, MM_ERROR_COMMON_INVALID_ARGUMENT);
9913         return_val_if_fail((MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PAUSED)
9914                  ||(MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PLAYING),
9915                 MM_ERROR_PLAYER_INVALID_STATE);
9916
9917         attrs = MMPLAYER_GET_ATTRS(player);
9918         if ( !attrs )
9919         {
9920                 debug_error("cannot get content attribute");
9921                 return MM_ERROR_PLAYER_INTERNAL;
9922         }
9923
9924         switch (track_type)
9925         {
9926                 case MM_PLAYER_TRACK_TYPE_AUDIO:
9927                         ret = mm_attrs_get_int_by_name(attrs, "content_audio_track_num", count);
9928                         break;
9929                 case MM_PLAYER_TRACK_TYPE_VIDEO:
9930                         ret = mm_attrs_get_int_by_name(attrs, "content_video_track_num", count);
9931                         break;
9932                 case MM_PLAYER_TRACK_TYPE_TEXT:
9933                         ret = mm_attrs_get_int_by_name(attrs, "content_text_track_num", count);
9934                         break;
9935                 default:
9936                         ret = MM_ERROR_COMMON_INVALID_ARGUMENT;
9937                         break;
9938         }
9939
9940         debug_log ("%d track num is %d\n", track_type, *count);
9941
9942         debug_fleave();
9943
9944         return ret;
9945 }
9946
9947
9948
9949 const gchar * 
9950 __get_state_name ( int state )
9951 {
9952         switch ( state )
9953         {
9954                 case MM_PLAYER_STATE_NULL:
9955                         return "NULL";
9956                 case MM_PLAYER_STATE_READY:
9957                         return "READY";
9958                 case MM_PLAYER_STATE_PAUSED:
9959                         return "PAUSED";
9960                 case MM_PLAYER_STATE_PLAYING:
9961                         return "PLAYING";
9962                 case MM_PLAYER_STATE_NONE:
9963                         return "NONE";
9964                 default:
9965                         return "INVAID";
9966         }
9967 }
9968 gboolean
9969 __is_rtsp_streaming ( mm_player_t* player )
9970 {
9971         return_val_if_fail ( player, FALSE );
9972
9973         return ( player->profile.uri_type == MM_PLAYER_URI_TYPE_URL_RTSP ) ? TRUE : FALSE;
9974 }
9975
9976 static gboolean
9977 __is_http_streaming ( mm_player_t* player )
9978 {
9979         return_val_if_fail ( player, FALSE );
9980
9981         return ( player->profile.uri_type == MM_PLAYER_URI_TYPE_URL_HTTP ) ? TRUE : FALSE;
9982 }
9983
9984 static gboolean
9985 __is_streaming ( mm_player_t* player )
9986 {
9987         return_val_if_fail ( player, FALSE );
9988
9989         return ( __is_rtsp_streaming ( player ) || __is_http_streaming ( player ) || __is_http_live_streaming ( player )) ? TRUE : FALSE;
9990 }
9991
9992 gboolean
9993 __is_live_streaming ( mm_player_t* player )
9994 {
9995         return_val_if_fail ( player, FALSE );
9996
9997         return ( __is_rtsp_streaming ( player ) && player->streaming_type == STREAMING_SERVICE_LIVE ) ? TRUE : FALSE;
9998 }
9999
10000 static gboolean
10001 __is_http_live_streaming( mm_player_t* player )
10002 {
10003         return_val_if_fail( player, FALSE );
10004
10005         return ( player->profile.uri_type == MM_PLAYER_URI_TYPE_HLS ) ? TRUE : FALSE;
10006 }
10007
10008 static gboolean
10009 __is_http_progressive_down(mm_player_t* player)
10010 {
10011         return_val_if_fail( player, FALSE );
10012
10013         return ((player->pd_mode) ? TRUE:FALSE);
10014 }