[0.6.231] Fix typo error
[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 #include "mm_player_attrs.h"
27
28 #define INVALID_TRACK_INDEX -1
29 #define LANGUAGE_CODE_SIZE (3 + 1) /* Size of ISO-639-1, and considering the nul-terminator */
30
31 /*---------------------------------------------------------------------------------------
32 |    LOCAL FUNCTION PROTOTYPES:                                                                               |
33 ---------------------------------------------------------------------------------------*/
34 static int __mmplayer_track_get_language(mmplayer_t *player, mmplayer_track_type_e type, gint stream_index, gchar **code);
35
36
37 /*=======================================================================================
38 |  FUNCTION DEFINITIONS                                                                                      |
39 =======================================================================================*/
40 int
41 _mmplayer_get_track_count(MMHandleType hplayer,  mmplayer_track_type_e type, int *count)
42 {
43         int ret = MM_ERROR_NONE;
44         mmplayer_t *player = (mmplayer_t *)hplayer;
45         MMHandleType attrs = 0;
46
47         MMPLAYER_FENTER();
48
49         /* check player handle */
50         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
51         MMPLAYER_RETURN_VAL_IF_FAIL(count, MM_ERROR_INVALID_ARGUMENT);
52         MMPLAYER_RETURN_VAL_IF_FAIL((MMPLAYER_CURRENT_STATE(player) == MM_PLAYER_STATE_PAUSED)
53                  || (MMPLAYER_CURRENT_STATE(player) == MM_PLAYER_STATE_PLAYING),
54                 MM_ERROR_PLAYER_INVALID_STATE);
55
56         attrs = MMPLAYER_GET_ATTRS(player);
57         if (!attrs) {
58                 LOGE("cannot get content attribute");
59                 return MM_ERROR_PLAYER_INTERNAL;
60         }
61
62         *count = 0;
63
64         switch (type) {
65         case MM_PLAYER_TRACK_TYPE_AUDIO:
66                 if (player->track[MM_PLAYER_TRACK_TYPE_AUDIO].total_track_num > 0)
67                         *count = player->track[MM_PLAYER_TRACK_TYPE_AUDIO].total_track_num;
68                 break;
69         case MM_PLAYER_TRACK_TYPE_TEXT: /* internal or external */
70                 ret = mm_attrs_get_int_by_name(attrs, "content_text_track_num", count);
71                 break;
72         default:
73                 ret = MM_ERROR_INVALID_ARGUMENT;
74                 break;
75         }
76
77         LOGD("type: %d, the num of track: %d", type, *count);
78
79         MMPLAYER_FLEAVE();
80
81         return ret;
82 }
83
84 int
85 _mmplayer_select_track(MMHandleType hplayer, mmplayer_track_type_e type, int index)
86 {
87         int ret = MM_ERROR_NONE;
88         mmplayer_t *player = (mmplayer_t *)hplayer;
89
90         MMPLAYER_FENTER();
91         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
92
93         LOGD("track type: %d, index: %d", type, index);
94
95         MMPLAYER_SUBTITLE_INFO_LOCK(player);
96
97         if (type == MM_PLAYER_TRACK_TYPE_TEXT && player->subtitle_language_list) { /* external subtitle */
98                 GstElement *subparse = NULL;
99                 mmplayer_lang_info_t *temp = NULL;
100                 guint num_of_list = 0;
101
102                 if (!player->pipeline || !player->pipeline->textbin[MMPLAYER_T_FAKE_SINK].gst) {
103                         ret = MM_ERROR_PLAYER_NOT_INITIALIZED;
104                         goto EXIT;
105                 }
106
107                 num_of_list = g_list_length(player->subtitle_language_list);
108                 if (index < 0 || index >= num_of_list) {
109                         LOGE("req track index is wrong");
110                         ret = MM_ERROR_INVALID_ARGUMENT;
111                         goto EXIT;
112                 }
113
114                 temp = g_list_nth_data(player->subtitle_language_list, index);
115                 if (!temp) {
116                         LOGE("fail to get lang from list");
117                         ret = MM_ERROR_PLAYER_INTERNAL;
118                         goto EXIT;
119                 }
120                 subparse = player->pipeline->mainbin[MMPLAYER_M_SUBPARSE].gst;
121                 LOGD("setting to language %s", temp->language_code);
122                 g_object_set(G_OBJECT(subparse), "current-language", temp->language_key, NULL);
123
124                 _mmplayer_sync_subtitle_pipeline(player);
125
126         } else { /* audio or internal subtitle */
127                 ret = _mmplayer_change_track_language(hplayer, type, index);
128                 if (ret != MM_ERROR_NONE) {
129                         LOGE("failed to change track");
130                         goto EXIT;
131                 }
132         }
133
134         if (type == MM_PLAYER_TRACK_TYPE_TEXT) {
135                 if (mm_player_set_attribute(hplayer, NULL,
136                                 "current_text_track_index", index, NULL) != MM_ERROR_NONE) {
137                         LOGE("failed to set text track index");
138                         ret = MM_ERROR_PLAYER_INTERNAL;
139                         goto EXIT;
140                 }
141         }
142
143         LOGD("current index is updated");
144
145 EXIT:
146         MMPLAYER_SUBTITLE_INFO_UNLOCK(player);
147         MMPLAYER_FLEAVE();
148         return ret;
149 }
150
151 int
152 _mmplayer_get_current_track(MMHandleType hplayer, mmplayer_track_type_e type, int *index)
153 {
154         int ret = MM_ERROR_NONE;
155         mmplayer_t *player = (mmplayer_t *)hplayer;
156         MMHandleType attrs = 0;
157         gint count = 0;
158
159         MMPLAYER_FENTER();
160         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
161         MMPLAYER_RETURN_VAL_IF_FAIL(index, MM_ERROR_INVALID_ARGUMENT);
162
163         attrs = MMPLAYER_GET_ATTRS(player);
164         MMPLAYER_RETURN_VAL_IF_FAIL(attrs, MM_ERROR_PLAYER_INTERNAL);
165
166         MMPLAYER_SUBTITLE_INFO_LOCK(player);
167
168         LOGD("track type: %d", type);
169
170         *index = INVALID_TRACK_INDEX;
171
172         switch (type) {
173         case MM_PLAYER_TRACK_TYPE_AUDIO:
174                 if (player->track[MM_PLAYER_TRACK_TYPE_AUDIO].total_track_num <= 0) {
175                         LOGW("there is no audio track");
176                         ret = MM_ERROR_PLAYER_NO_OP;
177                         goto EXIT;
178                 }
179
180                 *index = player->track[MM_PLAYER_TRACK_TYPE_AUDIO].active_track_index;
181                 break;
182         case MM_PLAYER_TRACK_TYPE_TEXT: /* internal or external */
183                 mm_attrs_get_int_by_name(attrs, "content_text_track_num", &count);
184                 if (count <= 0) {
185                         LOGD("there is no text track");
186                         ret = MM_ERROR_PLAYER_NO_OP;
187                         goto EXIT;
188                 }
189
190                 mm_attrs_get_int_by_name(attrs, "current_text_track_index", index);
191                 break;
192         default:
193                 LOGD("invalid input type");
194                 ret = MM_ERROR_INVALID_ARGUMENT;
195                 goto EXIT;
196         }
197
198         if (*index < 0) {
199                 LOGE("invalid track index");
200                 ret = MM_ERROR_PLAYER_INTERNAL;
201                 goto EXIT;
202         }
203
204         LOGD("current track index: %d", *index);
205
206 EXIT:
207         MMPLAYER_SUBTITLE_INFO_UNLOCK(player);
208         MMPLAYER_FLEAVE();
209         return ret;
210 }
211
212 int
213 _mmplayer_get_track_language_code(MMHandleType hplayer, mmplayer_track_type_e type, int index, char **code)
214 {
215         int ret = MM_ERROR_NONE;
216         mmplayer_t *player = (mmplayer_t *)hplayer;
217         gchar *lang_code = NULL;
218
219         MMPLAYER_FENTER();
220         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
221         MMPLAYER_RETURN_VAL_IF_FAIL(code, MM_ERROR_INVALID_ARGUMENT);
222
223         MMPLAYER_SUBTITLE_INFO_LOCK(player);
224
225         if (type == MM_PLAYER_TRACK_TYPE_TEXT && player->subtitle_language_list) { /* external subtitle */
226                 mmplayer_lang_info_t *language_list = NULL;
227
228                 lang_code = (gchar *)g_malloc0(LANGUAGE_CODE_SIZE * sizeof(char));
229
230                 language_list = g_list_nth_data(player->subtitle_language_list, index);
231                 if (language_list == NULL) {
232                         LOGE("invalid index %d", index);
233                         ret = MM_ERROR_INVALID_ARGUMENT;
234                         goto EXIT;
235                 }
236                 g_strlcpy(lang_code, language_list->language_code, LANGUAGE_CODE_SIZE);
237         } else { /* audio or internal subtitle */
238                 if (player->track[type].total_track_num <= 0) {
239                         LOGW("language list is not available. [type:%d]", type);
240                         ret = MM_ERROR_PLAYER_NO_OP;
241                         goto EXIT;
242                 }
243
244                 ret = __mmplayer_track_get_language(player, type, index, &lang_code);
245         }
246
247 EXIT:
248         MMPLAYER_SUBTITLE_INFO_UNLOCK(player);
249
250         *code = NULL;
251         if (ret == MM_ERROR_NONE) {
252                 if (g_strcmp0(lang_code, "und"))
253                         *code = strndup(lang_code, 2);
254                 else
255                         *code = strndup("und", 3);
256         }
257         MMPLAYER_FREEIF(lang_code);
258
259         MMPLAYER_FLEAVE();
260         return ret;
261 }
262
263 void
264 _mmplayer_track_initialize(mmplayer_t *player)
265 {
266         mmplayer_track_type_e type = MM_PLAYER_TRACK_TYPE_AUDIO;
267
268         MMPLAYER_FENTER();
269
270         for (; type < MM_PLAYER_TRACK_TYPE_MAX ; type++) {
271                 /* active_track_index is initialized when player is created or destroyed.
272                    and the value can be set by calling _mmplayer_change_track_language()
273                    before pipeline is created.*/
274                 player->track[type].total_track_num = 0;
275                 player->track[type].streams = g_ptr_array_new();
276         }
277 }
278
279 void
280 _mmplayer_track_destroy(mmplayer_t *player)
281 {
282         mmplayer_track_type_e type = MM_PLAYER_TRACK_TYPE_AUDIO;
283         MMPLAYER_FENTER();
284
285         if (mm_player_set_attribute((MMHandleType)player, NULL, "content_text_track_num", 0,
286                         "current_text_track_index", INVALID_TRACK_INDEX, NULL) != MM_ERROR_NONE)
287                 LOGE("failed to reset track attr");
288
289         for (; type < MM_PLAYER_TRACK_TYPE_MAX ; type++) {
290                 player->track[type].active_track_index = 0;
291                 player->track[type].total_track_num = 0;
292
293                 if (player->track[type].streams)
294                         g_ptr_array_free(player->track[type].streams, TRUE);
295                 player->track[type].streams = NULL;
296         }
297 }
298
299 void
300 _mmplayer_track_update_stream(mmplayer_t *player, mmplayer_track_type_e type, void *stream)
301 {
302         MMPLAYER_FENTER();
303
304         player->track[type].total_track_num++;
305         g_ptr_array_add(player->track[type].streams, stream);
306
307         LOGD("type: %d, track cnt: %d", type, player->track[type].total_track_num);
308 }
309
310 void
311 _mmplayer_track_update_text_attr_info(mmplayer_t *player, GstMessage *msg)
312 {
313          const GValue *lang_list = NULL;
314          mmplayer_lang_info_t *temp = NULL;
315          gchar *current_lang = NULL;
316          gint  track_index = INVALID_TRACK_INDEX;
317          guint track_count = 0, index = 0;
318
319          MMPLAYER_FENTER();
320          MMPLAYER_RETURN_IF_FAIL(player && msg);
321
322         if (!gst_message_get_structure(msg)) {
323                 LOGE("failed to get msg structure");
324                 return;
325         }
326
327         lang_list = gst_structure_get_value(gst_message_get_structure(msg), "lang_list");
328         if (!lang_list) {
329                 LOGW("language list is null");
330                 return;
331         }
332
333         track_count = g_list_length((GList *)g_value_get_pointer(lang_list));
334         if (track_count == 0) {
335                 LOGW("track count is zero");
336                 return;
337         }
338
339         MMPLAYER_SUBTITLE_INFO_LOCK(player);
340         player->subtitle_language_list = (GList *)g_value_get_pointer(lang_list);
341         mm_player_set_attribute((MMHandleType)player, NULL,
342                         "content_text_track_num", (gint)track_count, NULL);
343         g_object_get(G_OBJECT(msg->src), "current-language", &current_lang, NULL);
344
345         LOGI("track count: %d, current track lang: %s", track_count, current_lang);
346         if (!current_lang)
347                 goto EXIT;
348
349         for (index = 0 ; index < track_count ; index++) {
350                 temp = g_list_nth_data(player->subtitle_language_list, index);
351                 if (temp) {
352                         LOGI("[%d] lang_key: %s, lang_code: %s",
353                                 index, temp->language_key, temp->language_code);
354
355                         if (!g_strcmp0(temp->language_key, current_lang)) {
356                                 LOGD("current track index : %d", index);
357                                 track_index = index;
358                                 break;
359                         }
360                 }
361         }
362
363         if (track_index > INVALID_TRACK_INDEX)
364                 mm_player_set_attribute((MMHandleType)player, NULL,
365                                 "current_text_track_index", track_index, NULL);
366         else
367                 LOGE("failed to find current track index");
368
369 EXIT:
370         MMPLAYER_SUBTITLE_INFO_SIGNAL(player);
371         MMPLAYER_SUBTITLE_INFO_UNLOCK(player);
372
373         MMPLAYER_FLEAVE();
374 }
375
376 static int
377 __mmplayer_track_get_language(mmplayer_t *player, mmplayer_track_type_e type, gint stream_index, gchar **code)
378 {
379         GstTagList *tag_list = NULL;
380         gchar *tag = NULL;
381
382         MMPLAYER_FENTER();
383         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
384         MMPLAYER_RETURN_VAL_IF_FAIL((code && (stream_index >= 0) &&
385                 (stream_index < player->track[type].total_track_num)), MM_ERROR_INVALID_ARGUMENT);
386
387         LOGD("type: %d, track count: %d, input idx: %d", type, player->track[type].total_track_num, stream_index);
388
389         *code = (gchar *)g_malloc0(LANGUAGE_CODE_SIZE * sizeof(char));
390
391         if (MMPLAYER_USE_DECODEBIN(player)) {
392                 GstPad *sinkpad = g_ptr_array_index(player->track[type].streams, stream_index);
393                 g_object_get(sinkpad, "tags", &tag_list, NULL);
394         } else {
395                 GstStream *stream = g_ptr_array_index(player->track[type].streams, stream_index);
396                 tag_list = gst_stream_get_tags (stream);
397         }
398
399         if (tag_list)
400                 gst_tag_list_get_string(tag_list, GST_TAG_LANGUAGE_CODE, &tag);
401
402         if (tag) {
403                 LOGD("language code: %s, len: %zu", tag, strlen(tag));
404                 g_strlcpy(*code, tag, LANGUAGE_CODE_SIZE);
405                 MMPLAYER_FREEIF(tag);
406         } else {
407                 LOGD("no language code info - und");
408                 g_strlcpy(*code, "und", LANGUAGE_CODE_SIZE);
409         }
410
411         if (tag_list)
412                 gst_tag_list_unref(tag_list);
413
414         MMPLAYER_FLEAVE();
415         return MM_ERROR_NONE;
416 }