4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
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>
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
13 * http://www.apache.org/licenses/LICENSE-2.0
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.
24 #include <mm_attrs_private.h>
25 #include "mm_player_utils.h"
26 #include "mm_player_tracks.h"
28 /*---------------------------------------------------------------------------------------
29 | LOCAL FUNCTION PROTOTYPES: |
30 ---------------------------------------------------------------------------------------*/
31 static int __mmplayer_track_get_language(mm_player_t* player, MMPlayerTrackType type, gint stream_index, gchar **code);
34 /*=======================================================================================
35 | FUNCTION DEFINITIONS |
36 =======================================================================================*/
37 int _mmplayer_get_track_count(MMHandleType hplayer, MMPlayerTrackType type, int *count)
39 mm_player_t* player = (mm_player_t*) hplayer;
40 MMHandleType attrs = 0;
41 int ret = MM_ERROR_NONE;
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);
52 attrs = MMPLAYER_GET_ATTRS(player);
54 LOGE("cannot get content attribute");
55 return MM_ERROR_PLAYER_INTERNAL;
59 case MM_PLAYER_TRACK_TYPE_AUDIO:
61 /*if function called for normal file [no multi audio] */
62 if (player->selector[MM_PLAYER_TRACK_TYPE_AUDIO].total_track_num <= 0) {
66 ret = mm_attrs_get_int_by_name(attrs, "content_audio_track_num", count);
69 case MM_PLAYER_TRACK_TYPE_TEXT:
70 ret = mm_attrs_get_int_by_name(attrs, "content_text_track_num", count);
73 ret = MM_ERROR_COMMON_INVALID_ARGUMENT;
77 LOGD("%d track num : %d\n", type, *count);
84 int _mmplayer_select_track(MMHandleType hplayer, MMPlayerTrackType type, int index)
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);
91 MMPLAYER_SUBTITLE_INFO_LOCK(player);
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;
99 if (!player->pipeline || !player->pipeline->textbin[MMPLAYER_T_FAKE_SINK].gst) {
100 ret = MM_ERROR_PLAYER_NOT_INITIALIZED;
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;
111 _mmplayer_get_position(hplayer, MM_PLAYER_POS_FORMAT_TIME, &cur_time);
112 temp = g_list_nth_data(player->subtitle_language_list, index);
114 LOGE("fail to get lang from list");
115 ret = MM_ERROR_PLAYER_INTERNAL;
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);
122 _mmplayer_sync_subtitle_pipeline(player);
125 ret = _mmplayer_change_track_language(hplayer, type, index);
129 MMPLAYER_SUBTITLE_INFO_UNLOCK(player);
135 int _mmplayer_track_add_subtitle_language(MMHandleType hplayer, int index)
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);
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;
148 if (player->subtitle_language_list) {
149 GstElement *subparse = NULL;
150 MMPlayerLangStruct *temp = NULL;
152 temp = g_list_nth_data(player->subtitle_language_list, index);
154 LOGE("fail to get lang from list");
155 ret = MM_ERROR_PLAYER_INTERNAL;
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);
165 _mmplayer_sync_subtitle_pipeline(player);
167 LOGW("It is for just subtitle track");
168 ret = MM_ERROR_PLAYER_NO_OP;
173 MMPLAYER_SUBTITLE_INFO_UNLOCK(player);
178 int _mmplayer_track_remove_subtitle_language(MMHandleType hplayer, int index)
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);
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;
191 if (player->subtitle_language_list) {
192 GstElement *subparse = NULL;
193 MMPlayerLangStruct *temp = NULL;
195 temp = g_list_nth_data(player->subtitle_language_list, index);
197 LOGE("fail to get lang from list");
198 ret = MM_ERROR_PLAYER_INTERNAL;
201 temp->active = FALSE;
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);
208 _mmplayer_sync_subtitle_pipeline(player);
210 LOGW("It is for just subtitle track");
211 ret = MM_ERROR_PLAYER_NO_OP;
216 MMPLAYER_SUBTITLE_INFO_UNLOCK(player);
221 int _mmplayer_get_current_track(MMHandleType hplayer, MMPlayerTrackType type, int *index)
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);
228 MMPLAYER_SUBTITLE_INFO_LOCK(player);
230 if (type >= MM_PLAYER_TRACK_TYPE_MAX) {
231 ret = MM_ERROR_INVALID_ARGUMENT;
232 LOGD("Not a proper type [type:%d] \n", type);
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;
243 attrs = MMPLAYER_GET_ATTRS(player);
245 LOGE("cannot get content attribute");
246 ret = MM_ERROR_PLAYER_INTERNAL;
250 mm_attrs_get_int_by_name(attrs, "content_text_track_num", &total_track_count);
252 subparse = player->pipeline->mainbin[MMPLAYER_M_SUBPARSE].gst;
253 g_object_get(G_OBJECT(subparse), "current-language", ¤t_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);
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);
273 *index = player->selector[type].active_pad_index;
277 MMPLAYER_SUBTITLE_INFO_UNLOCK(player);
282 int _mmplayer_get_track_language_code(MMHandleType hplayer, MMPlayerTrackType type, int index, char **code)
284 int ret = MM_ERROR_NONE;
286 MMPLAYER_RETURN_VAL_IF_FAIL(hplayer, MM_ERROR_PLAYER_NOT_INITIALIZED);
287 mm_player_t* player = (mm_player_t*) hplayer;
290 MMPLAYER_SUBTITLE_INFO_LOCK(player);
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;
296 *code = (char*)malloc(language_code_size * sizeof(char));
298 ret = MM_ERROR_PLAYER_INTERNAL;
301 memset(*code, 0, language_code_size * sizeof(char));
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);
308 strncpy(*code, language_list->language_code, language_code_size);
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);
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);
322 ret = __mmplayer_track_get_language(player, type, index, code);
326 MMPLAYER_SUBTITLE_INFO_UNLOCK(player);
331 void _mmplayer_track_initialize(mm_player_t* player)
333 MMPlayerTrackType type = MM_PLAYER_TRACK_TYPE_AUDIO;
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();
346 void _mmplayer_track_destroy(mm_player_t* player)
348 MMPlayerTrackType type = MM_PLAYER_TRACK_TYPE_AUDIO;
349 MMHandleType attrs = 0;
352 attrs = MMPLAYER_GET_ATTRS(player);
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);
358 if (mmf_attrs_commit(attrs))
359 LOGE("failed to commit.\n");
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;
366 if (player->selector[type].channels)
367 g_ptr_array_free(player->selector[type].channels, TRUE);
368 player->selector[type].channels = NULL;
372 void _mmplayer_track_update_info(mm_player_t* player, MMPlayerTrackType type, GstPad *sinkpad)
376 player->selector[type].total_track_num++;
377 g_ptr_array_add(player->selector[type].channels, sinkpad);
379 LOGD("type:%d, total track:%d\n", type, player->selector[type].total_track_num);
382 static int __mmplayer_track_get_language(mm_player_t* player, MMPlayerTrackType type, gint stream_index, gchar **code)
384 int ret = MM_ERROR_NONE;
386 GstTagList *tag_list = NULL;
388 GstPad *sinkpad = NULL;
389 gint language_code_size = 3; /*Size of ISO-639-1*/
393 *code = (char *)malloc(language_code_size*sizeof(char));
395 ret = MM_ERROR_PLAYER_INTERNAL;
398 memset(*code, 0, language_code_size*sizeof(char));
400 LOGD("total track num : %d , req idx : %d\n", player->selector[type].total_track_num, stream_index);
402 if (stream_index < player->selector[type].total_track_num) {
403 sinkpad = g_ptr_array_index(player->selector[type].channels, stream_index);
405 ret = MM_ERROR_INVALID_ARGUMENT;
409 g_object_get(sinkpad, "tags", &tag_list, NULL);
410 //SECURE_LOGD ("[%s]\n", gst_tag_list_to_string(tag_list));
412 gst_tag_list_get_string(tag_list, GST_TAG_LANGUAGE_CODE, &tag);
415 LOGD("there is no lang info - und\n");
416 strncpy(*code, "und", language_code_size);
418 LOGD("language information[%d] code: %s, len: %d \n", type, tag, strlen(tag));
419 strncpy(*code, tag, /*strlen(tag)*/language_code_size);
424 gst_tag_list_free(tag_list);
431 int _mmplayer_track_foreach_selected_subtitle_language(MMHandleType hplayer, _mmplayer_track_selected_subtitle_language_cb foreach_cb, void *user_data)
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);
439 MMPLAYER_SUBTITLE_INFO_LOCK(player);
441 if (player->subtitle_language_list) {
442 int total_track_count = 0;
443 MMPlayerLangStruct *temp = NULL;
444 MMHandleType attrs = 0;
446 attrs = MMPLAYER_GET_ATTRS(player);
448 LOGE("cannot get content attribute");
449 ret = MM_ERROR_PLAYER_INTERNAL;
452 mm_attrs_get_int_by_name(attrs, "content_text_track_num", &total_track_count);
454 if (!total_track_count) {
455 LOGW("There are no subtitle track selected.");
456 ret = MM_ERROR_PLAYER_NO_OP;
460 while (total_track_count) {
461 temp = g_list_nth_data(player->subtitle_language_list, total_track_count - 1);
463 LOGD("find the list");
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;
476 LOGD("we will return -1 for notifying the end to user");
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;
486 LOGE("foreach callback returned error");
489 MMPLAYER_SUBTITLE_INFO_UNLOCK(player);