[0.6.147] Apply new attribute API of libmm-common
[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_player_utils.h"
25 #include "mm_player_tracks.h"
26
27 /*---------------------------------------------------------------------------------------
28 |    LOCAL FUNCTION PROTOTYPES:                                                                               |
29 ---------------------------------------------------------------------------------------*/
30 static int __mmplayer_track_get_language(mm_player_t* player, MMPlayerTrackType type, gint stream_index, gchar **code);
31
32
33 /*=======================================================================================
34 |  FUNCTION DEFINITIONS                                                                                      |
35 =======================================================================================*/
36 int _mmplayer_get_track_count(MMHandleType hplayer,  MMPlayerTrackType type, int *count)
37 {
38         mm_player_t* player = (mm_player_t*) hplayer;
39         MMHandleType attrs = 0;
40         int ret = MM_ERROR_NONE;
41
42         MMPLAYER_FENTER();
43
44         /* check player handle */
45         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
46         MMPLAYER_RETURN_VAL_IF_FAIL(count, MM_ERROR_COMMON_INVALID_ARGUMENT);
47         MMPLAYER_RETURN_VAL_IF_FAIL((MMPLAYER_CURRENT_STATE(player) == MM_PLAYER_STATE_PAUSED)
48                  || (MMPLAYER_CURRENT_STATE(player) == MM_PLAYER_STATE_PLAYING),
49                 MM_ERROR_PLAYER_INVALID_STATE);
50
51         attrs = MMPLAYER_GET_ATTRS(player);
52         if (!attrs) {
53                 LOGE("cannot get content attribute");
54                 return MM_ERROR_PLAYER_INTERNAL;
55         }
56
57         switch (type) {
58         case MM_PLAYER_TRACK_TYPE_AUDIO:
59                         {
60                                 /*if function called for normal file [no multi audio] */
61                                 if (player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].total_track_num <= 0) {
62                                         *count = 0;
63                                         break;
64                                 }
65                                 ret = mm_attrs_get_int_by_name(attrs, "content_audio_track_num", count);
66                         }
67                 break;
68         case MM_PLAYER_TRACK_TYPE_TEXT:
69                         ret = mm_attrs_get_int_by_name(attrs, "content_text_track_num", count);
70                 break;
71         default:
72                         ret = MM_ERROR_COMMON_INVALID_ARGUMENT;
73                 break;
74         }
75
76         LOGD("%d track num : %d\n", type, *count);
77
78         MMPLAYER_FLEAVE();
79
80         return ret;
81 }
82
83 int _mmplayer_select_track(MMHandleType hplayer, MMPlayerTrackType type, int index)
84 {
85         int ret = MM_ERROR_NONE;
86         mm_player_t* player = (mm_player_t*) hplayer;
87         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
88         MMPLAYER_FENTER();
89
90         MMPLAYER_SUBTITLE_INFO_LOCK(player);
91
92         if (type == MM_PLAYER_TRACK_TYPE_TEXT && player->subtitle_language_list) {
93                 GstElement *subparse = NULL;
94                 MMPlayerLangStruct *temp = NULL;
95                 guint num_of_list = 0;
96
97                 if (!player->pipeline || !player->pipeline->textbin[MMPLAYER_T_FAKE_SINK].gst) {
98                         ret = MM_ERROR_PLAYER_NOT_INITIALIZED;
99                         goto EXIT;
100                 }
101
102                 num_of_list = g_list_length(player->subtitle_language_list);
103                 if (index < 0 || index >= num_of_list) {
104                         LOGE("req track index is wrong");
105                         ret = MM_ERROR_INVALID_ARGUMENT;
106                         goto EXIT;
107                 }
108
109                 temp = g_list_nth_data(player->subtitle_language_list, index);
110                 if (!temp) {
111                         LOGE("fail to get lang from list");
112                         ret = MM_ERROR_PLAYER_INTERNAL;
113                         goto EXIT;
114                 }
115                 subparse = player->pipeline->mainbin[MMPLAYER_M_SUBPARSE].gst;
116                 LOGD("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         } else {
122                 ret = _mmplayer_change_track_language(hplayer, type, index);
123         }
124
125 EXIT:
126         MMPLAYER_SUBTITLE_INFO_UNLOCK(player);
127         MMPLAYER_FLEAVE();
128         return ret;
129 }
130
131 #ifdef _MULTI_TRACK
132 int _mmplayer_track_add_subtitle_language(MMHandleType hplayer, int index)
133 {
134         int ret = MM_ERROR_NONE;
135         mm_player_t* player = (mm_player_t*) hplayer;
136         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
137         MMPLAYER_FENTER();
138
139         MMPLAYER_SUBTITLE_INFO_LOCK(player);
140         if (!player->pipeline || !player->pipeline->mainbin[MMPLAYER_M_T_SUBMUX_EXTERNAL].gst) {
141                 ret = MM_ERROR_PLAYER_NOT_INITIALIZED;
142                 goto EXIT;
143         }
144
145         if (player->subtitle_language_list) {
146                 GstElement *subparse = NULL;
147                 MMPlayerLangStruct *temp = NULL;
148
149                 temp = g_list_nth_data(player->subtitle_language_list, index);
150                 if (!temp) {
151                         LOGE("fail to get lang from list");
152                         ret = MM_ERROR_PLAYER_INTERNAL;
153                         goto EXIT;
154                 }
155                 temp->active = TRUE;
156
157                 subparse = player->pipeline->mainbin[MMPLAYER_M_T_SUBMUX_EXTERNAL].gst;
158                 LOGD("adding to language %s", temp->language_code);
159                 g_object_set(G_OBJECT(subparse), "current-language", temp->language_key, NULL);
160                 g_object_set(G_OBJECT(subparse), "lang-list", player->subtitle_language_list, NULL);
161
162                 _mmplayer_sync_subtitle_pipeline(player);
163         } else {
164                 LOGW("It is for just subtitle track");
165                 ret = MM_ERROR_PLAYER_NO_OP;
166                 goto EXIT;
167         }
168
169 EXIT:
170         MMPLAYER_SUBTITLE_INFO_UNLOCK(player);
171         MMPLAYER_FLEAVE();
172         return ret;
173 }
174
175 int _mmplayer_track_remove_subtitle_language(MMHandleType hplayer, int index)
176 {
177         int ret = MM_ERROR_NONE;
178         mm_player_t* player = (mm_player_t*) hplayer;
179         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
180         MMPLAYER_FENTER();
181
182         MMPLAYER_SUBTITLE_INFO_LOCK(player);
183         if (!player->pipeline || !player->pipeline->mainbin[MMPLAYER_M_T_SUBMUX_EXTERNAL].gst) {
184                 ret = MM_ERROR_PLAYER_NOT_INITIALIZED;
185                 goto EXIT;
186         }
187
188         if (player->subtitle_language_list) {
189                 GstElement *subparse = NULL;
190                 MMPlayerLangStruct *temp = NULL;
191
192                 temp = g_list_nth_data(player->subtitle_language_list, index);
193                 if (!temp) {
194                         LOGE("fail to get lang from list");
195                         ret = MM_ERROR_PLAYER_INTERNAL;
196                         goto EXIT;
197                 }
198                 temp->active = FALSE;
199
200                 subparse = player->pipeline->mainbin[MMPLAYER_M_T_SUBMUX_EXTERNAL].gst;
201                 LOGD("removing to language %s", temp->language_code);
202                 g_object_set(G_OBJECT(subparse), "current-language", temp->language_key, NULL);
203                 g_object_set(G_OBJECT(subparse), "lang-list", player->subtitle_language_list, NULL);
204
205                 _mmplayer_sync_subtitle_pipeline(player);
206         } else {
207                 LOGW("It is for just subtitle track");
208                 ret = MM_ERROR_PLAYER_NO_OP;
209                 goto EXIT;
210         }
211
212 EXIT:
213         MMPLAYER_SUBTITLE_INFO_UNLOCK(player);
214         MMPLAYER_FLEAVE();
215         return ret;
216 }
217 #endif
218 int _mmplayer_get_current_track(MMHandleType hplayer, MMPlayerTrackType type, int *index)
219 {
220         int ret = MM_ERROR_NONE;
221         mm_player_t* player = (mm_player_t*) hplayer;
222         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
223         MMPLAYER_FENTER();
224
225         MMPLAYER_SUBTITLE_INFO_LOCK(player);
226
227         if (type >= MM_PLAYER_TRACK_TYPE_MAX) {
228                 ret = MM_ERROR_INVALID_ARGUMENT;
229                 LOGD("Not a proper type [type:%d] \n", type);
230                 goto EXIT;
231         }
232
233         if (type == MM_PLAYER_TRACK_TYPE_TEXT && player->subtitle_language_list) {
234                 GstElement *subparse = NULL;
235                 int total_track_count = 0;
236                 gchar* current_language = NULL;
237                 MMPlayerLangStruct *temp = NULL;
238                 MMHandleType attrs = 0;
239
240                 attrs = MMPLAYER_GET_ATTRS(player);
241                 if (!attrs) {
242                         LOGE("cannot get content attribute");
243                         ret = MM_ERROR_PLAYER_INTERNAL;
244                         goto EXIT;
245                 }
246
247                 mm_attrs_get_int_by_name(attrs, "content_text_track_num", &total_track_count);
248
249                 subparse = player->pipeline->mainbin[MMPLAYER_M_SUBPARSE].gst;
250                 g_object_get(G_OBJECT(subparse), "current-language", &current_language, NULL);
251                 LOGD("current language is %s ", current_language);
252                 while (total_track_count) {
253                         temp = g_list_nth_data(player->subtitle_language_list, total_track_count - 1);
254                         if (temp && current_language) {
255                                 LOGD("find the list");
256                                 if (!strcmp(temp->language_key, current_language)) {
257                                         *index = total_track_count - 1;
258                                         LOGD("current lang index  is %d", *index);
259                                         break;
260                                 }
261                         }
262                         total_track_count--;
263                 }
264
265                 if (total_track_count == 0) {
266                         *index = 0;
267                         LOGE("failed to find current language index");
268                         ret = MM_ERROR_PLAYER_INTERNAL;
269                         goto EXIT;
270                 }
271         } else {
272                 if (player->selector[type].total_track_num <= 0) {
273                         ret = MM_ERROR_PLAYER_NO_OP;
274                         LOGD("there is no track information [type:%d] \n", type);
275                         goto EXIT;
276                 }
277                 *index = player->selector[type].active_pad_index;
278         }
279
280 EXIT:
281         MMPLAYER_SUBTITLE_INFO_UNLOCK(player);
282         MMPLAYER_FLEAVE();
283         return ret;
284 }
285
286 int _mmplayer_get_track_language_code(MMHandleType hplayer, MMPlayerTrackType type, int index, char **code)
287 {
288         int ret = MM_ERROR_NONE;
289
290         MMPLAYER_RETURN_VAL_IF_FAIL(hplayer, MM_ERROR_PLAYER_NOT_INITIALIZED);
291         mm_player_t* player = (mm_player_t*) hplayer;
292         MMPLAYER_FENTER();
293
294         MMPLAYER_SUBTITLE_INFO_LOCK(player);
295
296         if (type == MM_PLAYER_TRACK_TYPE_TEXT && player->subtitle_language_list) {
297                 int language_code_size = 3;/*Size of ISO-639-1*/
298                 MMPlayerLangStruct *language_list = NULL;
299
300                 *code = (char*)malloc(language_code_size * sizeof(char));
301                 if (*code == NULL) {
302                         ret = MM_ERROR_PLAYER_INTERNAL;
303                         goto EXIT;
304                 }
305                 memset(*code, 0, language_code_size * sizeof(char));
306
307                 language_list = g_list_nth_data(player->subtitle_language_list, index);
308                 if (language_list == NULL) {
309                         LOGD("%d is not a proper index \n", index);
310                         goto EXIT;
311                 }
312                 strncpy(*code, language_list->language_code, language_code_size);
313         } else {
314                 if (player->selector[type].total_track_num <= 0) {
315                         ret = MM_ERROR_PLAYER_NO_OP;
316                         LOGD("language list is not available. [type:%d] \n", type);
317                         goto EXIT;
318                 }
319
320                 if (index < 0 || index >= player->selector[type].total_track_num) {
321                         ret = MM_ERROR_INVALID_ARGUMENT;
322                         LOGD("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_SUBTITLE_INFO_UNLOCK(player);
331         MMPLAYER_FLEAVE();
332         return ret;
333 }
334
335 void __mmplayer_track_initialize(mm_player_t* player)
336 {
337         MMPlayerTrackType type = MM_PLAYER_TRACK_TYPE_AUDIO;
338
339         MMPLAYER_FENTER();
340
341         for (; type < MM_PLAYER_TRACK_TYPE_MAX ; type++) {
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                 mm_attrs_set_int_by_name(attrs, "content_audio_track_num", 0);
359                 mm_attrs_set_int_by_name(attrs, "content_text_track_num", 0);
360
361                 if (mm_attrs_commit_all(attrs))
362                         LOGE("failed to commit.\n");
363         }
364
365         for (; type < MM_PLAYER_TRACK_TYPE_MAX ; type++) {
366                 player->selector[type].active_pad_index = 0;
367                 player->selector[type].total_track_num = 0;
368
369                 if (player->selector[type].channels)
370                         g_ptr_array_free(player->selector[type].channels, TRUE);
371                 player->selector[type].channels = NULL;
372         }
373 }
374
375 void __mmplayer_track_update_info(mm_player_t* player, MMPlayerTrackType type, GstPad *sinkpad)
376 {
377         MMPLAYER_FENTER();
378
379         player->selector[type].total_track_num++;
380         g_ptr_array_add(player->selector[type].channels, sinkpad);
381
382         LOGD("type:%d, total track:%d\n", type, player->selector[type].total_track_num);
383 }
384
385 static int __mmplayer_track_get_language(mm_player_t* player, MMPlayerTrackType type, gint stream_index, gchar **code)
386 {
387         int ret = MM_ERROR_NONE;
388
389         GstTagList *tag_list = NULL;
390         gchar* tag = NULL;
391         GstPad *sinkpad = NULL;
392         gint language_code_size = 3; /*Size of ISO-639-1*/
393
394         MMPLAYER_FENTER();
395
396         *code = (char *)malloc(language_code_size*sizeof(char));
397         if (*code == NULL) {
398                 ret = MM_ERROR_PLAYER_INTERNAL;
399                 goto EXIT;
400         }
401         memset(*code, 0, language_code_size*sizeof(char));
402
403         LOGD("total track num : %d , req idx : %d\n", player->selector[type].total_track_num, stream_index);
404
405         if (stream_index < player->selector[type].total_track_num) {
406                 sinkpad = g_ptr_array_index(player->selector[type].channels, stream_index);
407         } else {
408                 ret = MM_ERROR_INVALID_ARGUMENT;
409                 goto EXIT;
410         }
411
412         g_object_get(sinkpad, "tags", &tag_list, NULL);
413         //SECURE_LOGD ("[%s]\n", gst_tag_list_to_string(tag_list));
414
415         gst_tag_list_get_string(tag_list, GST_TAG_LANGUAGE_CODE, &tag);
416
417         if (!tag) {
418                 LOGD("there is no lang info - und\n");
419                 strncpy(*code, "und", language_code_size);
420         } else {
421                 LOGD("language information[%d] code: %s, len: %d \n", type, tag, strlen(tag));
422                 strncpy(*code, tag, /*strlen(tag)*/language_code_size);
423                 g_free(tag);
424         }
425
426         if (tag_list)
427                 gst_tag_list_free(tag_list);
428
429 EXIT:
430         MMPLAYER_FLEAVE();
431         return ret;
432 }
433 #ifdef _MULTI_TRACK
434 int _mmplayer_track_foreach_selected_subtitle_language(MMHandleType hplayer, _mmplayer_track_selected_subtitle_language_cb foreach_cb, void *user_data)
435 {
436         int ret = MM_ERROR_NONE;
437         mm_player_t* player = (mm_player_t*) hplayer;
438         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
439         MMPLAYER_FENTER();
440
441         int index = -1;
442         MMPLAYER_SUBTITLE_INFO_LOCK(player);
443
444         if (player->subtitle_language_list) {
445                 int total_track_count = 0;
446                 MMPlayerLangStruct *temp = NULL;
447                 MMHandleType attrs = 0;
448
449                 attrs = MMPLAYER_GET_ATTRS(player);
450                 if (!attrs) {
451                         LOGE("cannot get content attribute");
452                         ret = MM_ERROR_PLAYER_INTERNAL;
453                         goto EXIT;
454                 }
455                 mm_attrs_get_int_by_name(attrs, "content_text_track_num", &total_track_count);
456
457                 if (!total_track_count) {
458                         LOGW("There are no subtitle track selected.");
459                         ret = MM_ERROR_PLAYER_NO_OP;
460                         goto EXIT;
461                 }
462
463                 while (total_track_count) {
464                         temp = g_list_nth_data(player->subtitle_language_list, total_track_count - 1);
465                         if (temp) {
466                                 LOGD("find the list");
467                                 if (temp->active) {
468                                         index = total_track_count - 1;
469                                         LOGD("active subtitle track index is %d", index);
470                                         if (!foreach_cb(index, user_data)) {
471                                                 ret = MM_ERROR_PLAYER_INTERNAL;
472                                                 goto CALLBACK_ERROR;
473                                         }
474                                 }
475                         }
476                         total_track_count--;
477                 }
478
479                 LOGD("we will return -1 for notifying the end to user");
480
481                 /* After returning all selected indexs, we will return -1 for notifying the end to user */
482                 if (!foreach_cb(-1, user_data)) {
483                         ret = MM_ERROR_PLAYER_INTERNAL;
484                         goto CALLBACK_ERROR;
485                 }
486         }
487
488 CALLBACK_ERROR:
489         LOGE("foreach callback returned error");
490
491 EXIT:
492         MMPLAYER_SUBTITLE_INFO_UNLOCK(player);
493         MMPLAYER_FLEAVE();
494         return ret;
495
496
497 }
498 #endif