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