fix prevent issue #453398
[platform/core/multimedia/libmm-player.git] / src / mm_player_tracks.c
1 /*
2  * libmm-player
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: JongHyuk Choi <jhchoi.choi@samsung.com>, naveen cherukuri <naveen.ch@samsung.com>,
7  * YeJin Cho <cho.yejin@samsung.com>, YoungHwan An <younghwan_.an@samsung.com>
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  * http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  */
22 #include <mm_debug.h>
23 #include <mm_error.h>
24 #include <mm_attrs_private.h>
25 #include "mm_player_utils.h"
26 #include "mm_player_tracks.h"
27
28 /*---------------------------------------------------------------------------------------
29 |    LOCAL FUNCTION PROTOTYPES:                                                                               |
30 ---------------------------------------------------------------------------------------*/
31 static int __mmplayer_track_get_language(mm_player_t* player, MMPlayerTrackType type, gint stream_index, gchar **code);
32
33
34 /*=======================================================================================
35 |  FUNCTION DEFINITIONS                                                                                      |
36 =======================================================================================*/
37 int _mmplayer_get_track_count(MMHandleType hplayer,  MMPlayerTrackType type, int *count)
38 {
39         mm_player_t* player = (mm_player_t*) hplayer;
40         MMHandleType attrs = 0;
41         int ret = MM_ERROR_NONE;
42
43         MMPLAYER_FENTER();
44
45         /* check player handle */
46         return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
47         return_val_if_fail(count, MM_ERROR_COMMON_INVALID_ARGUMENT);
48         return_val_if_fail((MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PAUSED)
49                  ||(MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PLAYING),
50                 MM_ERROR_PLAYER_INVALID_STATE);
51
52         attrs = MMPLAYER_GET_ATTRS(player);
53         if ( !attrs )
54         {
55                 debug_error("cannot get content attribute");
56                 return MM_ERROR_PLAYER_INTERNAL;
57         }
58
59         switch (type)
60         {
61                 case MM_PLAYER_TRACK_TYPE_AUDIO:
62                         {
63                                 /*if function called for normal file [no multi audio] */
64                                 if(player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].total_track_num <= 0)
65                                 {
66                                         *count = 0;
67                                         break;
68                                 }
69                                 ret = mm_attrs_get_int_by_name(attrs, "content_audio_track_num", count);
70                         }
71                         break;
72                 case MM_PLAYER_TRACK_TYPE_TEXT:
73                         ret = mm_attrs_get_int_by_name(attrs, "content_text_track_num", count);
74                         break;
75                 default:
76                         ret = MM_ERROR_COMMON_INVALID_ARGUMENT;
77                         break;
78         }
79
80         debug_log ("%d track num : %d\n", type, *count);
81
82         MMPLAYER_FLEAVE();
83
84         return ret;
85 }
86
87 int _mmplayer_select_track(MMHandleType hplayer, MMPlayerTrackType type, int index)
88 {
89         int ret = MM_ERROR_NONE;
90         mm_player_t* player = (mm_player_t*) hplayer;
91         return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
92         MMPLAYER_FENTER();
93
94
95         if (type == MM_PLAYER_TRACK_TYPE_TEXT && player->subtitle_language_list)
96         {
97                 GstElement *subparse = NULL;
98                 MMPlayerLangStruct *temp = NULL;
99                 unsigned long cur_time = 0;
100
101                 if(!player->pipeline || !player->pipeline->textbin[MMPLAYER_T_FAKE_SINK].gst)
102                 {
103                         ret = MM_ERROR_PLAYER_NOT_INITIALIZED;
104                         goto EXIT;
105                 }
106
107                 _mmplayer_get_position (hplayer, MM_PLAYER_POS_FORMAT_TIME, &cur_time);
108                 temp = g_list_nth_data (player->subtitle_language_list, index);
109
110                 subparse = player->pipeline->mainbin[MMPLAYER_M_SUBPARSE].gst;
111                 debug_log("setting to language %s", temp->language_code);
112                 g_object_set (G_OBJECT (subparse), "current-language", temp->language_key, NULL);
113
114                 _mmplayer_sync_subtitle_pipeline(player);
115
116         }
117         else
118         {
119                 ret = _mmplayer_change_track_language (hplayer, type, index);
120         }
121
122 EXIT:
123         MMPLAYER_FLEAVE();
124         return ret;
125 }
126
127 #ifdef _MULTI_TRACK
128 int _mmplayer_track_add_subtitle_language(MMHandleType hplayer, int index)
129 {
130         int ret = MM_ERROR_NONE;
131         mm_player_t* player = (mm_player_t*) hplayer;
132         return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
133         MMPLAYER_FENTER();
134
135         if(!player->pipeline || !player->pipeline->mainbin[MMPLAYER_M_T_SUBMUX_EXTERNAL].gst)
136         {
137                 ret = MM_ERROR_PLAYER_NOT_INITIALIZED;
138                 goto EXIT;
139         }
140
141         if (player->subtitle_language_list)
142         {
143                 GstElement *subparse = NULL;
144                 MMPlayerLangStruct *temp = NULL;
145
146                 temp = g_list_nth_data (player->subtitle_language_list, index);
147                 temp->active = TRUE;
148
149                 subparse = player->pipeline->mainbin[MMPLAYER_M_T_SUBMUX_EXTERNAL].gst;
150                 debug_log("adding to language %s", temp->language_code);
151                 g_object_set (G_OBJECT (subparse), "current-language", temp->language_key, NULL);
152                 g_object_set (G_OBJECT (subparse), "lang-list", player->subtitle_language_list, NULL);
153
154                 _mmplayer_sync_subtitle_pipeline(player);
155         }
156         else
157         {
158                 debug_warning("It is for just subtitle track");
159                 ret = MM_ERROR_PLAYER_NO_OP;
160                 goto EXIT;
161         }
162
163 EXIT:
164         MMPLAYER_FLEAVE();
165         return ret;
166 }
167
168 int _mmplayer_track_remove_subtitle_language(MMHandleType hplayer, int index)
169 {
170         int ret = MM_ERROR_NONE;
171         mm_player_t* player = (mm_player_t*) hplayer;
172         return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
173         MMPLAYER_FENTER();
174
175         if(!player->pipeline || !player->pipeline->mainbin[MMPLAYER_M_T_SUBMUX_EXTERNAL].gst)
176         {
177                 ret = MM_ERROR_PLAYER_NOT_INITIALIZED;
178                 goto EXIT;
179         }
180
181         if (player->subtitle_language_list)
182         {
183                 GstElement *subparse = NULL;
184                 MMPlayerLangStruct *temp = NULL;
185
186                 temp = g_list_nth_data (player->subtitle_language_list, index);
187                 temp->active = FALSE;
188
189                 subparse = player->pipeline->mainbin[MMPLAYER_M_T_SUBMUX_EXTERNAL].gst;
190                 debug_log("removing to language %s", temp->language_code);
191                 g_object_set (G_OBJECT (subparse), "current-language", temp->language_key, NULL);
192                 g_object_set (G_OBJECT (subparse), "lang-list", player->subtitle_language_list, NULL);
193
194                 _mmplayer_sync_subtitle_pipeline(player);
195         }
196         else
197         {
198                 debug_warning("It is for just subtitle track");
199                 ret = MM_ERROR_PLAYER_NO_OP;
200                 goto EXIT;
201         }
202
203 EXIT:
204         MMPLAYER_FLEAVE();
205         return ret;
206 }
207 #endif
208 int _mmplayer_get_current_track(MMHandleType hplayer, MMPlayerTrackType type, int *index)
209 {
210         int ret = MM_ERROR_NONE;
211         mm_player_t* player = (mm_player_t*) hplayer;
212         return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
213         MMPLAYER_FENTER();
214
215         if (type >= MM_PLAYER_TRACK_TYPE_MAX)
216         {
217                 ret = MM_ERROR_INVALID_ARGUMENT;
218                 debug_log("Not a proper type [type:%d] \n", type);
219                 goto EXIT;
220         }
221
222         if (type == MM_PLAYER_TRACK_TYPE_TEXT && player->subtitle_language_list)
223         {
224                 GstElement *subparse = NULL;
225                 int total_track_count = 0;
226                 gchar* current_language = NULL;
227                 MMPlayerLangStruct *temp = NULL;
228                 MMHandleType attrs = 0;
229
230                 attrs = MMPLAYER_GET_ATTRS(player);
231                 if (!attrs)
232                 {
233                         debug_error("cannot get content attribute");
234                         ret = MM_ERROR_PLAYER_INTERNAL;
235                         goto EXIT;
236                 }
237
238                 mm_attrs_get_int_by_name(attrs, "content_text_track_num", &total_track_count);
239
240                 subparse = player->pipeline->mainbin[MMPLAYER_M_SUBPARSE].gst;
241                 g_object_get (G_OBJECT (subparse), "current-language", &current_language, NULL);
242                 debug_log("current language is %s ",current_language);
243                 while (total_track_count)
244                 {
245                         temp = g_list_nth_data (player->subtitle_language_list, total_track_count - 1);
246                         if (temp)
247                         {
248                                 debug_log("find the list");
249                                 if (!strcmp(temp->language_key, current_language))
250                                 {
251                                         *index = total_track_count - 1;
252                                         debug_log("current lang index  is %d", *index);
253                                         break;
254                                 }
255                         }
256                         total_track_count--;
257                 }
258         }
259         else
260         {
261                 if (player->selector[type].total_track_num <= 0)
262                 {
263                         ret = MM_ERROR_PLAYER_NO_OP;
264                         debug_log("there is no track information [type:%d] \n", type);
265                         goto EXIT;
266                 }
267
268                 *index = player->selector[type].active_pad_index;
269         }
270
271 EXIT:
272         MMPLAYER_FLEAVE();
273         return ret;
274 }
275
276 int _mmplayer_get_track_language_code(MMHandleType hplayer, MMPlayerTrackType type, int index, char **code)
277 {
278         int ret = MM_ERROR_NONE;
279
280         return_val_if_fail(hplayer, MM_ERROR_PLAYER_NOT_INITIALIZED);
281         mm_player_t* player = (mm_player_t*) hplayer;
282         MMPLAYER_FENTER();
283
284         if (type == MM_PLAYER_TRACK_TYPE_TEXT && player->subtitle_language_list)
285         {
286                 int language_code_size = 3;/*Size of ISO-639-1*/
287                 MMPlayerLangStruct *language_list = NULL;
288
289                 *code = (char*)malloc(language_code_size * sizeof(char));
290                 if (*code == NULL)
291                 {
292                         ret = MM_ERROR_PLAYER_INTERNAL;
293                         goto EXIT;
294                 }
295                 memset(*code, 0, language_code_size * sizeof(char));
296
297                 language_list = g_list_nth_data (player->subtitle_language_list, index);
298                 if (language_list == NULL)
299                 {
300                         debug_log ("%d is not a proper index \n", index);
301                         goto EXIT;
302                 }
303                 strncpy(*code, language_list->language_code, language_code_size);
304         }
305         else
306         {
307                 if (player->selector[type].total_track_num <= 0)
308                 {
309                         ret = MM_ERROR_PLAYER_NO_OP;
310                         debug_log("language list is not available. [type:%d] \n", type);
311                         goto EXIT;
312                 }
313
314                 if(index < 0 || index >= player->selector[type].total_track_num)
315                 {
316                         ret = MM_ERROR_INVALID_ARGUMENT;
317                         debug_log("Not a proper index : %d \n", index);
318                         goto EXIT;
319                 }
320
321                 ret = __mmplayer_track_get_language(player, type, index, code);
322         }
323
324 EXIT:
325         MMPLAYER_FLEAVE();
326         return ret;
327 }
328
329 void _mmplayer_track_initialize(mm_player_t* player)
330 {
331         MMPlayerTrackType type = MM_PLAYER_TRACK_TYPE_AUDIO;
332
333         MMPLAYER_FENTER();
334
335         for (;type<MM_PLAYER_TRACK_TYPE_MAX ; type++)
336         {
337                 /* active_pad_index is initialized when player is created or destroyed.
338                    and the value can be set by calling _mmplayer_change_track_language()
339                    before pipeline is created.*/
340                 player->selector[type].total_track_num = 0;
341                 player->selector[type].channels = g_ptr_array_new();
342         }
343 }
344
345 void _mmplayer_track_destroy(mm_player_t* player)
346 {
347         MMPlayerTrackType type = MM_PLAYER_TRACK_TYPE_AUDIO;
348         MMHandleType attrs = 0;
349         MMPLAYER_FENTER();
350
351         attrs = MMPLAYER_GET_ATTRS(player);
352         if (attrs)
353         {
354                 mm_attrs_set_int_by_name(attrs, "content_audio_track_num", 0);
355                 mm_attrs_set_int_by_name(attrs, "content_video_track_num", 0);
356                 mm_attrs_set_int_by_name(attrs, "content_text_track_num", 0);
357
358                 if (mmf_attrs_commit (attrs))
359                         debug_error("failed to commit.\n");
360         }
361
362         for (;type<MM_PLAYER_TRACK_TYPE_MAX ; type++)
363         {
364                 player->selector[type].active_pad_index = 0;
365                 player->selector[type].total_track_num = 0;
366
367                 if (player->selector[type].channels)
368                         g_ptr_array_free (player->selector[type].channels, TRUE);
369                 player->selector[type].channels = NULL;
370         }
371 }
372
373 void _mmplayer_track_update_info(mm_player_t* player, MMPlayerTrackType type, GstPad *sinkpad)
374 {
375         MMPLAYER_FENTER();
376
377         player->selector[type].total_track_num++;
378         g_ptr_array_add (player->selector[type].channels, sinkpad);
379
380         debug_log ("type:%d, total track:%d\n", type, player->selector[type].total_track_num);
381 }
382
383 static int __mmplayer_track_get_language(mm_player_t* player, MMPlayerTrackType type, gint stream_index, gchar **code)
384 {
385         int ret = MM_ERROR_NONE;
386
387         GstTagList *tag_list = NULL;
388         gchar* tag = NULL;
389         GstPad *sinkpad = NULL;
390         gint language_code_size = 3; /*Size of ISO-639-1*/
391
392         MMPLAYER_FENTER();
393
394         *code = (char *)malloc(language_code_size*sizeof(char));
395         if(*code == NULL)
396         {
397                 ret = MM_ERROR_PLAYER_INTERNAL;
398                 goto EXIT;
399         }
400         memset(*code,0,language_code_size*sizeof(char));
401
402         debug_log ("total track num : %d , req idx : %d\n", player->selector[type].total_track_num, stream_index);
403
404         if (stream_index < player->selector[type].total_track_num)
405         {
406                 sinkpad = g_ptr_array_index (player->selector[type].channels, stream_index);
407         }
408         else
409         {
410                 ret = MM_ERROR_INVALID_ARGUMENT;
411                 goto EXIT;
412         }
413
414         g_object_get (sinkpad, "tags", &tag_list, NULL);
415         //secure_debug_log ("[%s]\n", gst_tag_list_to_string(tag_list));
416
417         gst_tag_list_get_string (tag_list, GST_TAG_LANGUAGE_CODE, &tag);
418
419         if(!tag)
420         {
421                 debug_log("there is no lang info - und\n");
422                 strncpy(*code, "und", language_code_size);
423         }
424         else
425         {
426                 debug_log("language information[%d] code: %s, len: %d \n", type, tag, strlen(tag));
427                 strncpy(*code, tag, /*strlen(tag)*/language_code_size);
428                 g_free (tag);
429         }
430
431         if (tag_list)
432                 gst_tag_list_free (tag_list);
433
434 EXIT:
435         MMPLAYER_FLEAVE();
436         return ret;
437 }
438 #ifdef _MULTI_TRACK
439 int _mmplayer_track_foreach_selected_subtitle_language(MMHandleType hplayer,_mmplayer_track_selected_subtitle_language_cb foreach_cb, void *user_data)
440 {
441         int ret = MM_ERROR_NONE;
442         mm_player_t* player = (mm_player_t*) hplayer;
443         return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
444         MMPLAYER_FENTER();
445
446         int index = -1;
447
448         if (player->subtitle_language_list)
449         {
450                 int total_track_count = 0;
451                 MMPlayerLangStruct *temp = NULL;
452                 MMHandleType attrs = 0;
453
454                 attrs = MMPLAYER_GET_ATTRS(player);
455                 if (!attrs)
456                 {
457                         debug_error("cannot get content attribute");
458                         ret = MM_ERROR_PLAYER_INTERNAL;
459                         goto EXIT;
460                 }
461                 mm_attrs_get_int_by_name(attrs, "content_text_track_num", &total_track_count);
462
463                 if(!total_track_count)
464                 {
465                         debug_warning("There are no subtitle track selected.");
466                         ret = MM_ERROR_PLAYER_NO_OP;
467                         goto EXIT;
468                 }
469
470                 while (total_track_count)
471                 {
472                         temp = g_list_nth_data (player->subtitle_language_list, total_track_count - 1);
473                         if (temp)
474                         {
475                                 debug_log("find the list");
476                                 if (temp->active)
477                                 {
478                                         index = total_track_count - 1;
479                                         debug_log("active subtitle track index is %d", index);
480                                         if (!foreach_cb(index, user_data))
481                                         {
482                                                 ret = MM_ERROR_PLAYER_INTERNAL;
483                                                 goto CALLBACK_ERROR;
484                                         }
485                                 }
486                         }
487                         total_track_count--;
488                 }
489
490                 debug_log("we will return -1 for notifying the end to user");
491
492                 /* After returning all selected indexs, we will return -1 for notifying the end to user */
493                 if (!foreach_cb(-1, user_data))
494                 {
495                         ret = MM_ERROR_PLAYER_INTERNAL;
496                         goto CALLBACK_ERROR;
497                 }
498         }
499
500 CALLBACK_ERROR:
501         debug_error("foreach callback returned error");
502
503 EXIT:
504         MMPLAYER_FLEAVE();
505         return ret;
506
507
508 }
509 #endif