Merge "Support using wl_surface for legacy_player_test" into tizen
[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 <dlog.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         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
47         MMPLAYER_RETURN_VAL_IF_FAIL(count, MM_ERROR_COMMON_INVALID_ARGUMENT);
48         MMPLAYER_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                 LOGE("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         LOGD ("%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         MMPLAYER_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                 guint num_of_list = 0;
101
102                 if(!player->pipeline || !player->pipeline->textbin[MMPLAYER_T_FAKE_SINK].gst)
103                 {
104                         ret = MM_ERROR_PLAYER_NOT_INITIALIZED;
105                         goto EXIT;
106                 }
107
108                 num_of_list = g_list_length(player->subtitle_language_list);
109                 if (index < 0 || index >= num_of_list)
110                 {
111                         LOGE("req track index is wrong");
112                         ret = MM_ERROR_INVALID_ARGUMENT;
113                         goto EXIT;
114                 }
115
116                 _mmplayer_get_position (hplayer, MM_PLAYER_POS_FORMAT_TIME, &cur_time);
117                 temp = g_list_nth_data (player->subtitle_language_list, index);
118                 if (!temp)
119                 {
120                         LOGE("fail to get lang from list");
121                         ret = MM_ERROR_PLAYER_INTERNAL;
122                         goto EXIT;
123                 }
124                 subparse = player->pipeline->mainbin[MMPLAYER_M_SUBPARSE].gst;
125                 LOGD("setting to language %s", temp->language_code);
126                 g_object_set (G_OBJECT (subparse), "current-language", temp->language_key, NULL);
127
128                 _mmplayer_sync_subtitle_pipeline(player);
129
130         }
131         else
132         {
133                 ret = _mmplayer_change_track_language (hplayer, type, index);
134         }
135
136 EXIT:
137         MMPLAYER_FLEAVE();
138         return ret;
139 }
140
141 #ifdef _MULTI_TRACK
142 int _mmplayer_track_add_subtitle_language(MMHandleType hplayer, int index)
143 {
144         int ret = MM_ERROR_NONE;
145         mm_player_t* player = (mm_player_t*) hplayer;
146         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
147         MMPLAYER_FENTER();
148
149         if(!player->pipeline || !player->pipeline->mainbin[MMPLAYER_M_T_SUBMUX_EXTERNAL].gst)
150         {
151                 ret = MM_ERROR_PLAYER_NOT_INITIALIZED;
152                 goto EXIT;
153         }
154
155         if (player->subtitle_language_list)
156         {
157                 GstElement *subparse = NULL;
158                 MMPlayerLangStruct *temp = NULL;
159
160                 temp = g_list_nth_data (player->subtitle_language_list, index);
161                 if (!temp)
162                 {
163                         LOGE("fail to get lang from list");
164                         ret = MM_ERROR_PLAYER_INTERNAL;
165                         goto EXIT;
166                 }
167                 temp->active = TRUE;
168
169                 subparse = player->pipeline->mainbin[MMPLAYER_M_T_SUBMUX_EXTERNAL].gst;
170                 LOGD("adding to language %s", temp->language_code);
171                 g_object_set (G_OBJECT (subparse), "current-language", temp->language_key, NULL);
172                 g_object_set (G_OBJECT (subparse), "lang-list", player->subtitle_language_list, NULL);
173
174                 _mmplayer_sync_subtitle_pipeline(player);
175         }
176         else
177         {
178                 LOGW("It is for just subtitle track");
179                 ret = MM_ERROR_PLAYER_NO_OP;
180                 goto EXIT;
181         }
182
183 EXIT:
184         MMPLAYER_FLEAVE();
185         return ret;
186 }
187
188 int _mmplayer_track_remove_subtitle_language(MMHandleType hplayer, int index)
189 {
190         int ret = MM_ERROR_NONE;
191         mm_player_t* player = (mm_player_t*) hplayer;
192         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
193         MMPLAYER_FENTER();
194
195         if(!player->pipeline || !player->pipeline->mainbin[MMPLAYER_M_T_SUBMUX_EXTERNAL].gst)
196         {
197                 ret = MM_ERROR_PLAYER_NOT_INITIALIZED;
198                 goto EXIT;
199         }
200
201         if (player->subtitle_language_list)
202         {
203                 GstElement *subparse = NULL;
204                 MMPlayerLangStruct *temp = NULL;
205
206                 temp = g_list_nth_data (player->subtitle_language_list, index);
207                 if (!temp)
208                 {
209                         LOGE("fail to get lang from list");
210                         ret = MM_ERROR_PLAYER_INTERNAL;
211                         goto EXIT;
212                 }
213                 temp->active = FALSE;
214
215                 subparse = player->pipeline->mainbin[MMPLAYER_M_T_SUBMUX_EXTERNAL].gst;
216                 LOGD("removing to language %s", temp->language_code);
217                 g_object_set (G_OBJECT (subparse), "current-language", temp->language_key, NULL);
218                 g_object_set (G_OBJECT (subparse), "lang-list", player->subtitle_language_list, NULL);
219
220                 _mmplayer_sync_subtitle_pipeline(player);
221         }
222         else
223         {
224                 LOGW("It is for just subtitle track");
225                 ret = MM_ERROR_PLAYER_NO_OP;
226                 goto EXIT;
227         }
228
229 EXIT:
230         MMPLAYER_FLEAVE();
231         return ret;
232 }
233 #endif
234 int _mmplayer_get_current_track(MMHandleType hplayer, MMPlayerTrackType type, int *index)
235 {
236         int ret = MM_ERROR_NONE;
237         mm_player_t* player = (mm_player_t*) hplayer;
238         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
239         MMPLAYER_FENTER();
240
241         if (type >= MM_PLAYER_TRACK_TYPE_MAX)
242         {
243                 ret = MM_ERROR_INVALID_ARGUMENT;
244                 LOGD("Not a proper type [type:%d] \n", type);
245                 goto EXIT;
246         }
247
248         if (type == MM_PLAYER_TRACK_TYPE_TEXT && player->subtitle_language_list)
249         {
250                 GstElement *subparse = NULL;
251                 int total_track_count = 0;
252                 gchar* current_language = NULL;
253                 MMPlayerLangStruct *temp = NULL;
254                 MMHandleType attrs = 0;
255
256                 attrs = MMPLAYER_GET_ATTRS(player);
257                 if (!attrs)
258                 {
259                         LOGE("cannot get content attribute");
260                         ret = MM_ERROR_PLAYER_INTERNAL;
261                         goto EXIT;
262                 }
263
264                 mm_attrs_get_int_by_name(attrs, "content_text_track_num", &total_track_count);
265
266                 subparse = player->pipeline->mainbin[MMPLAYER_M_SUBPARSE].gst;
267                 g_object_get (G_OBJECT (subparse), "current-language", &current_language, NULL);
268                 LOGD("current language is %s ",current_language);
269                 while (total_track_count)
270                 {
271                         temp = g_list_nth_data (player->subtitle_language_list, total_track_count - 1);
272                         if (temp)
273                         {
274                                 LOGD("find the list");
275                                 if (!strcmp(temp->language_key, current_language))
276                                 {
277                                         *index = total_track_count - 1;
278                                         LOGD("current lang index  is %d", *index);
279                                         break;
280                                 }
281                         }
282                         total_track_count--;
283                 }
284         }
285         else
286         {
287                 if (player->selector[type].total_track_num <= 0)
288                 {
289                         ret = MM_ERROR_PLAYER_NO_OP;
290                         LOGD("there is no track information [type:%d] \n", type);
291                         goto EXIT;
292                 }
293
294                 *index = player->selector[type].active_pad_index;
295         }
296
297 EXIT:
298         MMPLAYER_FLEAVE();
299         return ret;
300 }
301
302 int _mmplayer_get_track_language_code(MMHandleType hplayer, MMPlayerTrackType type, int index, char **code)
303 {
304         int ret = MM_ERROR_NONE;
305
306         MMPLAYER_RETURN_VAL_IF_FAIL(hplayer, MM_ERROR_PLAYER_NOT_INITIALIZED);
307         mm_player_t* player = (mm_player_t*) hplayer;
308         MMPLAYER_FENTER();
309
310         if (type == MM_PLAYER_TRACK_TYPE_TEXT && player->subtitle_language_list)
311         {
312                 int language_code_size = 3;/*Size of ISO-639-1*/
313                 MMPlayerLangStruct *language_list = NULL;
314
315                 *code = (char*)malloc(language_code_size * sizeof(char));
316                 if (*code == NULL)
317                 {
318                         ret = MM_ERROR_PLAYER_INTERNAL;
319                         goto EXIT;
320                 }
321                 memset(*code, 0, language_code_size * sizeof(char));
322
323                 language_list = g_list_nth_data (player->subtitle_language_list, index);
324                 if (language_list == NULL)
325                 {
326                         LOGD ("%d is not a proper index \n", index);
327                         goto EXIT;
328                 }
329                 strncpy(*code, language_list->language_code, language_code_size);
330         }
331         else
332         {
333                 if (player->selector[type].total_track_num <= 0)
334                 {
335                         ret = MM_ERROR_PLAYER_NO_OP;
336                         LOGD("language list is not available. [type:%d] \n", type);
337                         goto EXIT;
338                 }
339
340                 if(index < 0 || index >= player->selector[type].total_track_num)
341                 {
342                         ret = MM_ERROR_INVALID_ARGUMENT;
343                         LOGD("Not a proper index : %d \n", index);
344                         goto EXIT;
345                 }
346
347                 ret = __mmplayer_track_get_language(player, type, index, code);
348         }
349
350 EXIT:
351         MMPLAYER_FLEAVE();
352         return ret;
353 }
354
355 void _mmplayer_track_initialize(mm_player_t* player)
356 {
357         MMPlayerTrackType type = MM_PLAYER_TRACK_TYPE_AUDIO;
358
359         MMPLAYER_FENTER();
360
361         for (;type<MM_PLAYER_TRACK_TYPE_MAX ; type++)
362         {
363                 /* active_pad_index is initialized when player is created or destroyed.
364                    and the value can be set by calling _mmplayer_change_track_language()
365                    before pipeline is created.*/
366                 player->selector[type].total_track_num = 0;
367                 player->selector[type].channels = g_ptr_array_new();
368         }
369 }
370
371 void _mmplayer_track_destroy(mm_player_t* player)
372 {
373         MMPlayerTrackType type = MM_PLAYER_TRACK_TYPE_AUDIO;
374         MMHandleType attrs = 0;
375         MMPLAYER_FENTER();
376
377         attrs = MMPLAYER_GET_ATTRS(player);
378         if (attrs)
379         {
380                 mm_attrs_set_int_by_name(attrs, "content_audio_track_num", 0);
381                 mm_attrs_set_int_by_name(attrs, "content_video_track_num", 0);
382                 mm_attrs_set_int_by_name(attrs, "content_text_track_num", 0);
383
384                 if (mmf_attrs_commit (attrs))
385                         LOGE("failed to commit.\n");
386         }
387
388         for (;type<MM_PLAYER_TRACK_TYPE_MAX ; type++)
389         {
390                 player->selector[type].active_pad_index = 0;
391                 player->selector[type].total_track_num = 0;
392
393                 if (player->selector[type].channels)
394                         g_ptr_array_free (player->selector[type].channels, TRUE);
395                 player->selector[type].channels = NULL;
396         }
397 }
398
399 void _mmplayer_track_update_info(mm_player_t* player, MMPlayerTrackType type, GstPad *sinkpad)
400 {
401         MMPLAYER_FENTER();
402
403         player->selector[type].total_track_num++;
404         g_ptr_array_add (player->selector[type].channels, sinkpad);
405
406         LOGD ("type:%d, total track:%d\n", type, player->selector[type].total_track_num);
407 }
408
409 static int __mmplayer_track_get_language(mm_player_t* player, MMPlayerTrackType type, gint stream_index, gchar **code)
410 {
411         int ret = MM_ERROR_NONE;
412
413         GstTagList *tag_list = NULL;
414         gchar* tag = NULL;
415         GstPad *sinkpad = NULL;
416         gint language_code_size = 3; /*Size of ISO-639-1*/
417
418         MMPLAYER_FENTER();
419
420         *code = (char *)malloc(language_code_size*sizeof(char));
421         if(*code == NULL)
422         {
423                 ret = MM_ERROR_PLAYER_INTERNAL;
424                 goto EXIT;
425         }
426         memset(*code,0,language_code_size*sizeof(char));
427
428         LOGD ("total track num : %d , req idx : %d\n", player->selector[type].total_track_num, stream_index);
429
430         if (stream_index < player->selector[type].total_track_num)
431         {
432                 sinkpad = g_ptr_array_index (player->selector[type].channels, stream_index);
433         }
434         else
435         {
436                 ret = MM_ERROR_INVALID_ARGUMENT;
437                 goto EXIT;
438         }
439
440         g_object_get (sinkpad, "tags", &tag_list, NULL);
441         //SECURE_LOGD ("[%s]\n", gst_tag_list_to_string(tag_list));
442
443         gst_tag_list_get_string (tag_list, GST_TAG_LANGUAGE_CODE, &tag);
444
445         if(!tag)
446         {
447                 LOGD("there is no lang info - und\n");
448                 strncpy(*code, "und", language_code_size);
449         }
450         else
451         {
452                 LOGD("language information[%d] code: %s, len: %d \n", type, tag, strlen(tag));
453                 strncpy(*code, tag, /*strlen(tag)*/language_code_size);
454                 g_free (tag);
455         }
456
457         if (tag_list)
458                 gst_tag_list_free (tag_list);
459
460 EXIT:
461         MMPLAYER_FLEAVE();
462         return ret;
463 }
464 #ifdef _MULTI_TRACK
465 int _mmplayer_track_foreach_selected_subtitle_language(MMHandleType hplayer,_mmplayer_track_selected_subtitle_language_cb foreach_cb, void *user_data)
466 {
467         int ret = MM_ERROR_NONE;
468         mm_player_t* player = (mm_player_t*) hplayer;
469         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
470         MMPLAYER_FENTER();
471
472         int index = -1;
473
474         if (player->subtitle_language_list)
475         {
476                 int total_track_count = 0;
477                 MMPlayerLangStruct *temp = NULL;
478                 MMHandleType attrs = 0;
479
480                 attrs = MMPLAYER_GET_ATTRS(player);
481                 if (!attrs)
482                 {
483                         LOGE("cannot get content attribute");
484                         ret = MM_ERROR_PLAYER_INTERNAL;
485                         goto EXIT;
486                 }
487                 mm_attrs_get_int_by_name(attrs, "content_text_track_num", &total_track_count);
488
489                 if(!total_track_count)
490                 {
491                         LOGW("There are no subtitle track selected.");
492                         ret = MM_ERROR_PLAYER_NO_OP;
493                         goto EXIT;
494                 }
495
496                 while (total_track_count)
497                 {
498                         temp = g_list_nth_data (player->subtitle_language_list, total_track_count - 1);
499                         if (temp)
500                         {
501                                 LOGD("find the list");
502                                 if (temp->active)
503                                 {
504                                         index = total_track_count - 1;
505                                         LOGD("active subtitle track index is %d", index);
506                                         if (!foreach_cb(index, user_data))
507                                         {
508                                                 ret = MM_ERROR_PLAYER_INTERNAL;
509                                                 goto CALLBACK_ERROR;
510                                         }
511                                 }
512                         }
513                         total_track_count--;
514                 }
515
516                 LOGD("we will return -1 for notifying the end to user");
517
518                 /* After returning all selected indexs, we will return -1 for notifying the end to user */
519                 if (!foreach_cb(-1, user_data))
520                 {
521                         ret = MM_ERROR_PLAYER_INTERNAL;
522                         goto CALLBACK_ERROR;
523                 }
524         }
525
526 CALLBACK_ERROR:
527         LOGE("foreach callback returned error");
528
529 EXIT:
530         MMPLAYER_FLEAVE();
531         return ret;
532
533
534 }
535 #endif