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