Merge "add resource limit return during player create" into tizen
[platform/core/multimedia/libmm-player.git] / src / mm_player.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>, YeJin Cho <cho.yejin@samsung.com>,
7  * Seungbae Shin <seungbae.shin@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
23 #include <gst/gst.h>
24 #include <string.h>
25
26 #include <dlog.h>
27 #include <mm_types.h>
28 #include <mm_message.h>
29
30 #include "mm_player.h"
31 #include "mm_player_priv.h"
32 #include "mm_player_attrs.h"
33 #include "mm_player_utils.h"
34 #include "mm_player_ini.h"
35 #include "mm_player_capture.h"
36 #include "mm_player_tracks.h"
37 #include "mm_player_es.h"
38
39 int mm_player_create(MMHandleType *player)
40 {
41         int result = MM_ERROR_PLAYER_INTERNAL;
42         mm_player_t* new_player = NULL;
43
44         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
45
46         /* alloc player structure */
47         new_player = g_malloc(sizeof(mm_player_t));
48         if (!new_player)
49         {
50                 LOGE("Cannot allocate memory for player\n");
51                 result = MM_ERROR_PLAYER_RESOURCE_LIMIT;
52                 goto ERROR;
53         }
54         memset(new_player, 0, sizeof(mm_player_t));
55
56         /* create player lock */
57         g_mutex_init(&new_player->cmd_lock);
58
59         /* create player lock */
60         g_mutex_init(&new_player->playback_lock);
61
62         /* load ini files */
63         if (MM_ERROR_NONE != mm_player_ini_load(&new_player->ini))
64         {
65                 LOGE("can't load ini");
66                 goto ERROR;
67         }
68
69         if (MM_ERROR_NONE != mm_player_audio_effect_ini_load(&new_player->ini))
70         {
71                 LOGE("can't load audio ini");
72                 goto ERROR;
73         }
74
75         /* create player */
76         result = _mmplayer_create_player((MMHandleType)new_player);
77         if(result != MM_ERROR_NONE)
78         {
79                 LOGE("failed to create player");
80                 if (result != MM_ERROR_PLAYER_RESOURCE_LIMIT)
81                         result = MM_ERROR_PLAYER_INTERNAL;
82                 goto ERROR;
83         }
84
85         *player = (MMHandleType)new_player;
86
87         return MM_ERROR_NONE;
88
89 ERROR:
90
91         if ( new_player )
92         {
93                 _mmplayer_destroy( (MMHandleType)new_player );
94                 g_mutex_clear(&new_player->cmd_lock);
95                 g_mutex_clear(&new_player->playback_lock);
96
97                 MMPLAYER_FREEIF( new_player );
98         }
99
100         *player = (MMHandleType)0;
101         return result; /* MM_ERROR_PLAYER_INTERNAL or MM_ERROR_PLAYER_RESOURCE_LIMIT */
102 }
103
104 int  mm_player_destroy(MMHandleType player)
105 {
106         int result = MM_ERROR_NONE;
107
108         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
109
110         MMPLAYER_CMD_LOCK( player );
111
112         result = _mmplayer_destroy(player);
113
114         MMPLAYER_CMD_UNLOCK( player );
115
116         g_mutex_clear(&((mm_player_t*)player)->cmd_lock);
117         g_mutex_clear(&((mm_player_t*)player)->playback_lock);
118
119         memset( (mm_player_t*)player, 0x00, sizeof(mm_player_t) );
120
121         /* free player */
122         g_free( (void*)player );
123
124         return result;
125 }
126
127 int mm_player_sound_register(MMHandleType player, int pid)
128 {
129         int result = MM_ERROR_NONE;
130
131         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
132
133         MMPLAYER_CMD_LOCK( player );
134
135         result = _mmplayer_sound_register_with_pid(player, pid);
136
137         MMPLAYER_CMD_UNLOCK( player );
138
139         return result;
140 }
141
142 int mm_player_get_client_pid (MMHandleType player, int* pid)
143 {
144         int result = MM_ERROR_NONE;
145
146         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
147         MMPLAYER_RETURN_VAL_IF_FAIL(pid, MM_ERROR_INVALID_ARGUMENT);
148
149         MMPLAYER_CMD_LOCK( player );
150
151         result = _mmplayer_get_client_pid(player, pid);
152
153         MMPLAYER_CMD_UNLOCK( player );
154
155         return result;
156 }
157
158 int mm_player_realize(MMHandleType player)
159 {
160         int result = MM_ERROR_NONE;
161
162         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
163
164         MMPLAYER_CMD_LOCK( player );
165
166         result = _mmplayer_realize(player);
167
168         MMPLAYER_CMD_UNLOCK( player );
169
170         return result;
171 }
172
173 int mm_player_unrealize(MMHandleType player)
174 {
175         int result = MM_ERROR_NONE;
176
177         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
178
179         MMPLAYER_CMD_LOCK( player );
180
181         result = _mmplayer_unrealize(player);
182
183         MMPLAYER_CMD_UNLOCK( player );
184
185         return result;
186 }
187
188 int mm_player_set_message_callback(MMHandleType player, MMMessageCallback callback, void *user_param)
189 {
190         int result = MM_ERROR_NONE;
191
192         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
193
194         MMPLAYER_CMD_LOCK( player );
195
196         result = _mmplayer_set_message_callback(player, callback, user_param);
197
198         MMPLAYER_CMD_UNLOCK( player );
199
200         return result;
201 }
202
203 int mm_player_set_pd_message_callback(MMHandleType player, MMMessageCallback callback, void *user_param)
204 {
205         int result = MM_ERROR_NONE;
206
207         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
208
209         result = _mm_player_set_pd_downloader_message_cb(player, callback, user_param);
210
211         return result;
212 }
213
214 int mm_player_set_audio_stream_callback(MMHandleType player, mm_player_audio_stream_callback callback, void *user_param)
215 {
216         int result = MM_ERROR_NONE;
217
218         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
219
220         MMPLAYER_CMD_LOCK( player );
221
222         result = _mmplayer_set_audiostream_cb(player, callback, user_param);
223
224         MMPLAYER_CMD_UNLOCK( player );
225
226         return result;
227 }
228
229 int mm_player_set_audio_stream_callback_ex(MMHandleType player, bool sync, mm_player_audio_stream_callback_ex callback, void *user_param)
230 {
231         int result = MM_ERROR_NONE;
232
233         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
234
235         MMPLAYER_CMD_LOCK( player );
236
237         result = _mmplayer_set_audiostream_cb_ex(player, sync, callback, user_param);
238
239         MMPLAYER_CMD_UNLOCK( player );
240
241         return result;
242 }
243
244 int mm_player_set_video_stream_callback(MMHandleType player, mm_player_video_stream_callback callback, void *user_param)
245 {
246         int result = MM_ERROR_NONE;
247
248         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
249
250         MMPLAYER_CMD_LOCK( player );
251
252         result = _mmplayer_set_videostream_cb(player, callback, user_param);
253
254         MMPLAYER_CMD_UNLOCK( player );
255
256         return result;
257 }
258
259 int mm_player_do_video_capture(MMHandleType player)
260 {
261         int result = MM_ERROR_NONE;
262
263         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
264
265         MMPLAYER_CMD_LOCK( player );
266
267         result = _mmplayer_do_video_capture(player);
268
269         MMPLAYER_CMD_UNLOCK( player );
270
271         return result;
272 }
273
274 int mm_player_set_prepare_buffering_time(MMHandleType player, int second)
275 {
276         int result = MM_ERROR_NONE;
277
278         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
279
280         MMPLAYER_CMD_LOCK( player );
281
282         result = _mmplayer_set_prepare_buffering_time(player, second);
283
284         MMPLAYER_CMD_UNLOCK( player );
285
286         return result;
287 }
288
289 int mm_player_set_runtime_buffering_mode(MMHandleType player, MMPlayerBufferingMode mode, int second)
290 {
291         int result = MM_ERROR_NONE;
292
293         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
294
295         MMPLAYER_CMD_LOCK( player );
296
297         result = _mmplayer_set_runtime_buffering_mode(player, mode, second);
298
299         MMPLAYER_CMD_UNLOCK( player );
300
301         return result;
302 }
303
304 int mm_player_set_volume(MMHandleType player, MMPlayerVolumeType *volume)
305 {
306         int result = MM_ERROR_NONE;
307
308         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
309         MMPLAYER_RETURN_VAL_IF_FAIL(volume, MM_ERROR_INVALID_ARGUMENT);
310
311         MMPLAYER_CMD_LOCK( player );
312
313         result = _mmplayer_set_volume(player, *volume);
314
315         MMPLAYER_CMD_UNLOCK( player );
316
317         return result;
318 }
319
320 int mm_player_get_volume(MMHandleType player, MMPlayerVolumeType *volume)
321 {
322         int result = MM_ERROR_NONE;
323
324         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
325         MMPLAYER_RETURN_VAL_IF_FAIL(volume, MM_ERROR_INVALID_ARGUMENT);
326
327         MMPLAYER_CMD_LOCK( player );
328
329         result = _mmplayer_get_volume(player, volume);
330
331         MMPLAYER_CMD_UNLOCK( player );
332
333         return result;
334 }
335
336 int mm_player_set_mute(MMHandleType player, int mute)
337 {
338         int result = MM_ERROR_NONE;
339
340         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
341
342         MMPLAYER_CMD_LOCK( player );
343
344         result = _mmplayer_set_mute(player, mute);
345
346         MMPLAYER_CMD_UNLOCK( player );
347
348         return result;
349 }
350
351 int mm_player_get_mute(MMHandleType player, int *mute)
352 {
353         int result = MM_ERROR_NONE;
354
355         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
356         MMPLAYER_RETURN_VAL_IF_FAIL(mute, MM_ERROR_INVALID_ARGUMENT);
357
358         MMPLAYER_CMD_LOCK( player );
359
360         result = _mmplayer_get_mute(player, mute);
361
362         MMPLAYER_CMD_UNLOCK( player );
363
364         return result;
365 }
366
367 int mm_player_get_state(MMHandleType player, MMPlayerStateType *state)
368 {
369         int result = MM_ERROR_NONE;
370
371         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
372         MMPLAYER_RETURN_VAL_IF_FAIL(state, MM_ERROR_COMMON_INVALID_ARGUMENT);
373
374         *state = MM_PLAYER_STATE_NULL;
375
376         result = _mmplayer_get_state(player, (int*)state);
377
378         return result;
379 }
380
381 /* NOTE : It does not support some use cases, eg using colorspace converter */
382 int mm_player_change_videosink(MMHandleType player, MMDisplaySurfaceType display_surface_type, void *display_overlay)
383 {
384         int result = MM_ERROR_NONE;
385
386         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
387
388         MMPLAYER_CMD_LOCK( player );
389
390         result = _mmplayer_change_videosink(player, display_surface_type, display_overlay);
391
392         MMPLAYER_CMD_UNLOCK( player );
393
394         return result;
395 }
396
397 int mm_player_push_buffer(MMHandleType player, unsigned char *buf, int size)
398 {
399         int result = MM_ERROR_NONE;
400
401         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
402
403         //MMPLAYER_CMD_LOCK( player );
404
405         result = _mmplayer_push_buffer(player, buf, size);
406
407         //MMPLAYER_CMD_UNLOCK( player );
408
409         return result;
410 }
411
412 int mm_player_start(MMHandleType player)
413 {
414         int result = MM_ERROR_NONE;
415
416         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
417
418         MMPLAYER_CMD_LOCK( player );
419
420         result = _mmplayer_start(player);
421
422         MMPLAYER_CMD_UNLOCK( player );
423
424         return result;
425 }
426
427 int  mm_player_stop(MMHandleType player)
428 {
429         int result = MM_ERROR_NONE;
430
431         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
432
433         MMPLAYER_CMD_LOCK( player );
434
435         result = _mmplayer_stop(player);
436
437         MMPLAYER_CMD_UNLOCK( player );
438
439         return result;
440 }
441
442 int mm_player_pause(MMHandleType player)
443 {
444         int result = MM_ERROR_NONE;
445
446         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
447
448         MMPLAYER_CMD_LOCK( player );
449
450         result = _mmplayer_pause(player);
451
452         MMPLAYER_CMD_UNLOCK( player );
453
454         return result;
455 }
456
457 int mm_player_resume(MMHandleType player)
458 {
459         int result = MM_ERROR_NONE;
460
461         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
462
463         MMPLAYER_CMD_LOCK( player );
464
465         result = _mmplayer_resume(player);
466
467         MMPLAYER_CMD_UNLOCK( player );
468
469         return result;
470 }
471
472 int mm_player_activate_section_repeat(MMHandleType player, int start_pos, int end_pos)
473 {
474         int result = MM_ERROR_NONE;
475
476         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
477
478         MMPLAYER_CMD_LOCK( player );
479
480         result = _mmplayer_activate_section_repeat(player, start_pos, end_pos);
481
482         MMPLAYER_CMD_UNLOCK( player );
483
484         return result;
485 }
486
487 int mm_player_deactivate_section_repeat(MMHandleType player)
488 {
489         int result = MM_ERROR_NONE;
490
491         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
492
493         MMPLAYER_CMD_LOCK( player );
494
495         result = _mmplayer_deactivate_section_repeat(player);
496
497         MMPLAYER_CMD_UNLOCK( player );
498
499         return result;
500 }
501
502 int mm_player_gst_set_audio_channel(MMHandleType player, MMPlayerAudioChannel ch)
503 {
504         int result = MM_ERROR_NONE;
505
506         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
507         MMPLAYER_CMD_LOCK( player );
508
509         result = _mmplayer_gst_set_audio_channel(player, ch);
510
511         MMPLAYER_CMD_UNLOCK( player );
512         return result;
513 }
514
515 int mm_player_set_play_speed(MMHandleType player, float rate, bool streaming)
516 {
517         int result = MM_ERROR_NONE;
518
519         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
520
521         MMPLAYER_CMD_LOCK( player );
522
523         result = _mmplayer_set_playspeed(player, rate, streaming);
524
525         MMPLAYER_CMD_UNLOCK( player );
526
527         return result;
528 }
529
530 int mm_player_set_position(MMHandleType player, MMPlayerPosFormatType format, int pos)
531 {
532         int result = MM_ERROR_NONE;
533
534         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
535
536         if (format >= MM_PLAYER_POS_FORMAT_NUM)
537         {
538                 LOGE("wrong format\n");
539                 return MM_ERROR_COMMON_INVALID_ARGUMENT;
540         }
541
542         MMPLAYER_CMD_LOCK( player );
543
544         result = _mmplayer_set_position(player, format, pos);
545
546         MMPLAYER_CMD_UNLOCK( player );
547
548         return result;
549 }
550
551 int mm_player_get_position(MMHandleType player, MMPlayerPosFormatType format, unsigned long *pos)
552 {
553         int result = MM_ERROR_NONE;
554
555         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
556         MMPLAYER_RETURN_VAL_IF_FAIL(pos, MM_ERROR_COMMON_INVALID_ARGUMENT);
557
558         if (format >= MM_PLAYER_POS_FORMAT_NUM)
559         {
560                 LOGE("wrong format\n");
561                 return MM_ERROR_COMMON_INVALID_ARGUMENT;
562         }
563
564         MMPLAYER_CMD_LOCK( player );
565
566         result = _mmplayer_get_position(player, (int)format, pos);
567
568         MMPLAYER_CMD_UNLOCK( player );
569
570         return result;
571 }
572
573 int mm_player_get_buffer_position(MMHandleType player, MMPlayerPosFormatType format, unsigned long *start_pos, unsigned long *stop_pos)
574 {
575         int result = MM_ERROR_NONE;
576
577         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
578         MMPLAYER_RETURN_VAL_IF_FAIL(start_pos && stop_pos, MM_ERROR_COMMON_INVALID_ARGUMENT);
579
580         MMPLAYER_CMD_LOCK( player );
581
582         result = _mmplayer_get_buffer_position(player, (int)format, start_pos, stop_pos );
583
584         MMPLAYER_CMD_UNLOCK( player );
585
586         return result;
587 }
588
589 int mm_player_set_external_subtitle_path(MMHandleType player, const char* path)
590 {
591         int result = MM_ERROR_NONE;
592
593         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
594
595         MMPLAYER_CMD_LOCK( player );
596
597         result = _mmplayer_set_external_subtitle_path(player, path);
598
599         MMPLAYER_CMD_UNLOCK( player );
600         return result;
601 }
602
603 int mm_player_adjust_subtitle_position(MMHandleType player, MMPlayerPosFormatType format, int pos)
604 {
605         int result = MM_ERROR_NONE;
606
607         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
608
609         if (format >= MM_PLAYER_POS_FORMAT_NUM)
610         {
611                 LOGE("wrong format(%d) \n", format);
612                 return MM_ERROR_INVALID_ARGUMENT;
613         }
614
615         MMPLAYER_CMD_LOCK( player );
616
617         result = _mmplayer_adjust_subtitle_postion(player, format, pos);
618
619         MMPLAYER_CMD_UNLOCK( player );
620
621         return result;
622 }
623
624 int mm_player_adjust_video_position(MMHandleType player, int offset)
625 {
626         int result = MM_ERROR_NONE;
627         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
628         MMPLAYER_CMD_LOCK( player );
629
630         result = _mmplayer_adjust_video_postion(player, offset);
631
632         MMPLAYER_CMD_UNLOCK( player );
633
634         return result;
635 }
636
637 int mm_player_set_subtitle_silent(MMHandleType player, int silent)
638 {
639         int result = MM_ERROR_NONE;
640
641         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
642
643         MMPLAYER_CMD_LOCK( player );
644
645         result = _mmplayer_set_subtitle_silent(player, silent);
646
647         MMPLAYER_CMD_UNLOCK( player );
648
649         return result;
650 }
651
652 int mm_player_get_subtitle_silent(MMHandleType player, int* silent)
653 {
654         int result = MM_ERROR_NONE;
655
656         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
657
658         MMPLAYER_CMD_LOCK( player );
659
660         result = _mmplayer_get_subtitle_silent(player, silent);
661
662         MMPLAYER_CMD_UNLOCK( player );
663
664         return result;
665 }
666
667 int mm_player_set_attribute(MMHandleType player,  char **err_attr_name, const char *first_attribute_name, ...)
668 {
669         int result = MM_ERROR_NONE;
670         va_list var_args;
671
672         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
673         MMPLAYER_RETURN_VAL_IF_FAIL(first_attribute_name, MM_ERROR_COMMON_INVALID_ARGUMENT);
674
675         va_start (var_args, first_attribute_name);
676         result = _mmplayer_set_attribute(player, err_attr_name, first_attribute_name, var_args);
677         va_end (var_args);
678
679         return result;
680 }
681
682 int mm_player_get_attribute(MMHandleType player,  char **err_attr_name, const char *first_attribute_name, ...)
683 {
684         int result = MM_ERROR_NONE;
685         va_list var_args;
686
687         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
688         MMPLAYER_RETURN_VAL_IF_FAIL(first_attribute_name, MM_ERROR_COMMON_INVALID_ARGUMENT);
689
690         va_start (var_args, first_attribute_name);
691         result = _mmplayer_get_attribute(player, err_attr_name, first_attribute_name, var_args);
692         va_end (var_args);
693
694         return result;
695 }
696
697 int mm_player_get_attribute_info(MMHandleType player,  const char *attribute_name, MMPlayerAttrsInfo *info)
698 {
699         int result = MM_ERROR_NONE;
700
701
702         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
703         MMPLAYER_RETURN_VAL_IF_FAIL(attribute_name, MM_ERROR_COMMON_INVALID_ARGUMENT);
704         MMPLAYER_RETURN_VAL_IF_FAIL(info, MM_ERROR_COMMON_INVALID_ARGUMENT);
705
706         result = _mmplayer_get_attributes_info((MMHandleType)player, attribute_name, info);
707
708         return result;
709 }
710
711 int mm_player_get_pd_status(MMHandleType player, guint64 *current_pos, guint64 *total_size)
712 {
713         int result = MM_ERROR_NONE;
714
715         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
716         MMPLAYER_RETURN_VAL_IF_FAIL(current_pos, MM_ERROR_COMMON_INVALID_ARGUMENT);
717         MMPLAYER_RETURN_VAL_IF_FAIL(total_size, MM_ERROR_COMMON_INVALID_ARGUMENT);
718
719         result = _mmplayer_get_pd_downloader_status(player, current_pos, total_size);
720
721         return result;
722 }
723
724 int mm_player_get_track_count(MMHandleType player, MMPlayerTrackType type, int *count)
725 {
726         int result = MM_ERROR_NONE;
727
728         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
729         MMPLAYER_RETURN_VAL_IF_FAIL(count, MM_ERROR_COMMON_INVALID_ARGUMENT);
730
731         MMPLAYER_CMD_LOCK( player );
732
733         result = _mmplayer_get_track_count(player, type, count);
734
735         MMPLAYER_CMD_UNLOCK( player );
736
737         return result;
738 }
739
740 int mm_player_select_track(MMHandleType player, MMPlayerTrackType type, int index)
741 {
742         int result = MM_ERROR_NONE;
743
744         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
745
746         MMPLAYER_CMD_LOCK( player );
747
748         result = _mmplayer_select_track(player, type, index);
749
750         MMPLAYER_CMD_UNLOCK( player );
751
752         return result;
753 }
754 #ifdef _MULTI_TRACK
755 int mm_player_track_add_subtitle_language(MMHandleType player, int index)
756 {
757         int result = MM_ERROR_NONE;
758
759         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
760
761         MMPLAYER_CMD_LOCK( player );
762
763         result = _mmplayer_track_add_subtitle_language(player, index);
764
765         MMPLAYER_CMD_UNLOCK( player );
766
767         return result;
768 }
769
770 int mm_player_track_remove_subtitle_language(MMHandleType player, int index)
771 {
772         int result = MM_ERROR_NONE;
773
774         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
775
776         MMPLAYER_CMD_LOCK( player );
777
778         result = _mmplayer_track_remove_subtitle_language(player, index);
779
780         MMPLAYER_CMD_UNLOCK( player );
781
782         return result;
783
784 }
785 #endif
786 int mm_player_get_current_track(MMHandleType player, MMPlayerTrackType type, int *index)
787 {
788         int result = MM_ERROR_NONE;
789
790         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
791         MMPLAYER_RETURN_VAL_IF_FAIL(index, MM_ERROR_COMMON_INVALID_ARGUMENT);
792
793         MMPLAYER_CMD_LOCK( player );
794
795         result = _mmplayer_get_current_track(player, type, index);
796
797         MMPLAYER_CMD_UNLOCK( player );
798
799         return result;
800 }
801
802 int mm_player_get_track_language_code(MMHandleType player,  MMPlayerTrackType type, int index, char **code)
803 {
804         int result = MM_ERROR_NONE;
805
806         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
807
808         MMPLAYER_CMD_LOCK( player );
809
810         result = _mmplayer_get_track_language_code(player, type, index, code);
811
812         MMPLAYER_CMD_UNLOCK( player );
813
814         return result;
815 }
816
817 int mm_player_set_display_zoom(MMHandleType player, float level, int x, int y)
818 {
819         int result = MM_ERROR_NONE;
820
821         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
822
823         MMPLAYER_CMD_LOCK( player );
824
825         result = _mmplayer_set_display_zoom(player, level, x, y);
826
827         MMPLAYER_CMD_UNLOCK( player );
828
829         return result;
830 }
831
832 int mm_player_get_display_zoom(MMHandleType player, float *level, int *x, int *y)
833 {
834         int result = MM_ERROR_NONE;
835
836         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
837         MMPLAYER_RETURN_VAL_IF_FAIL(level, MM_ERROR_COMMON_INVALID_ARGUMENT);
838
839         MMPLAYER_CMD_LOCK( player );
840
841         result = _mmplayer_get_display_zoom(player, level, x, y);
842
843         MMPLAYER_CMD_UNLOCK( player );
844
845         return result;
846 }
847
848 int mm_player_set_video_share_master_clock(MMHandleType player,
849                                                 long long clock,
850                                                 long long clock_delta,
851                                                 long long video_time,
852                                                 long long media_clock,
853                                                 long long audio_time)
854 {
855         int result = MM_ERROR_NONE;
856
857         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
858
859         MMPLAYER_CMD_LOCK( player );
860
861         result = _mmplayer_set_video_share_master_clock(player, clock, clock_delta, video_time, media_clock, audio_time);
862
863         MMPLAYER_CMD_UNLOCK( player );
864
865         return result;
866 }
867
868 int mm_player_get_video_share_master_clock(MMHandleType player,
869                                                 long long *video_time,
870                                                 long long *media_clock,
871                                                 long long *audio_time)
872 {
873         int result = MM_ERROR_NONE;
874
875         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
876         MMPLAYER_RETURN_VAL_IF_FAIL(video_time, MM_ERROR_COMMON_INVALID_ARGUMENT);
877         MMPLAYER_RETURN_VAL_IF_FAIL(media_clock, MM_ERROR_COMMON_INVALID_ARGUMENT);
878         MMPLAYER_RETURN_VAL_IF_FAIL(audio_time, MM_ERROR_COMMON_INVALID_ARGUMENT);
879
880         MMPLAYER_CMD_LOCK( player );
881
882         result = _mmplayer_get_video_share_master_clock(player, video_time, media_clock, audio_time);
883
884         MMPLAYER_CMD_UNLOCK( player );
885
886         return result;
887 }
888
889 int mm_player_get_video_rotate_angle(MMHandleType player, int *angle)
890 {
891         int result = MM_ERROR_NONE;
892
893         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
894         MMPLAYER_RETURN_VAL_IF_FAIL(angle, MM_ERROR_COMMON_INVALID_ARGUMENT);
895
896         MMPLAYER_CMD_LOCK( player );
897
898         result = _mmplayer_get_video_rotate_angle(player, angle);
899
900         MMPLAYER_CMD_UNLOCK( player );
901
902         return result;
903 }
904
905 int mm_player_set_video_hub_download_mode(MMHandleType player, bool mode)
906 {
907         int result = MM_ERROR_NONE;
908
909         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
910
911         MMPLAYER_CMD_LOCK( player );
912
913         result = _mmplayer_set_video_hub_download_mode(player, mode);
914
915         MMPLAYER_CMD_UNLOCK( player );
916
917         return result;
918 }
919
920 int mm_player_enable_sync_handler(MMHandleType player, bool enable)
921 {
922         int result = MM_ERROR_NONE;
923
924         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
925
926         MMPLAYER_CMD_LOCK( player );
927
928         result = _mmplayer_enable_sync_handler(player, enable);
929
930         MMPLAYER_CMD_UNLOCK( player );
931
932         return result;
933 }
934
935 int mm_player_set_uri(MMHandleType player, const char *uri)
936 {
937         int result = MM_ERROR_NONE;
938
939         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
940
941         MMPLAYER_CMD_LOCK( player );
942
943         result = _mmplayer_set_uri(player, uri);
944
945         MMPLAYER_CMD_UNLOCK( player );
946
947         return result;
948
949 }
950
951 int mm_player_set_next_uri(MMHandleType player, const char *uri)
952 {
953         int result = MM_ERROR_NONE;
954
955         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
956
957         MMPLAYER_CMD_LOCK( player );
958
959         result = _mmplayer_set_next_uri(player, uri, FALSE);
960
961         MMPLAYER_CMD_UNLOCK( player );
962
963         return result;
964
965 }
966
967 int mm_player_get_next_uri(MMHandleType player, char **uri)
968 {
969         int result = MM_ERROR_NONE;
970
971         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
972
973         MMPLAYER_CMD_LOCK( player );
974
975         result = _mmplayer_get_next_uri(player, uri);
976
977         MMPLAYER_CMD_UNLOCK( player );
978
979         return result;
980
981 }
982 #ifdef _MULTI_TRACK
983 int mm_player_track_foreach_selected_subtitle_language(MMHandleType player, mm_player_track_selected_subtitle_language_callback callback, void *user_param)
984 {
985         int result = MM_ERROR_NONE;
986
987         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
988
989         MMPLAYER_CMD_LOCK( player );
990
991         result = _mmplayer_track_foreach_selected_subtitle_language(player, callback, user_param);
992
993         MMPLAYER_CMD_UNLOCK( player );
994
995         return result;
996 }
997 #endif
998
999 int mm_player_has_closed_caption(MMHandleType player, bool *exist)
1000 {
1001         int result = MM_ERROR_NONE;
1002
1003         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
1004         MMPLAYER_RETURN_VAL_IF_FAIL(exist, MM_ERROR_INVALID_ARGUMENT);
1005
1006         MMPLAYER_CMD_LOCK( player );
1007
1008         result = _mmplayer_has_closed_caption(player, exist);
1009
1010         MMPLAYER_CMD_UNLOCK( player );
1011
1012         return result;
1013 }
1014
1015 int mm_player_enable_media_packet_video_stream(MMHandleType player, bool enable)
1016 {
1017         int result = MM_ERROR_NONE;
1018
1019         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
1020         MMPLAYER_RETURN_VAL_IF_FAIL(enable, MM_ERROR_INVALID_ARGUMENT);
1021
1022         MMPLAYER_CMD_LOCK( player );
1023
1024         result = _mmplayer_enable_media_packet_video_stream(player, enable);
1025
1026         MMPLAYER_CMD_UNLOCK( player );
1027
1028         return result;
1029 }
1030
1031 void * mm_player_media_packet_video_stream_internal_buffer_ref(void *buffer)
1032 {
1033         void * result;
1034         result = _mm_player_media_packet_video_stream_internal_buffer_ref(buffer);
1035
1036         return result;
1037 }
1038
1039 void mm_player_media_packet_video_stream_internal_buffer_unref(void *buffer)
1040 {
1041         _mm_player_media_packet_video_stream_internal_buffer_unref(buffer);
1042 }
1043
1044 int mm_player_submit_packet(MMHandleType player, media_packet_h packet)
1045 {
1046
1047         int result = MM_ERROR_NONE;
1048
1049         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
1050
1051         /* no lock here, otherwise callback for the "need-data" signal of appsrc will be blocking */
1052         //MMPLAYER_CMD_LOCK( player );
1053
1054         result = _mmplayer_submit_packet(player, packet);
1055
1056         //MMPLAYER_CMD_UNLOCK( player );
1057
1058         return result;
1059 }
1060
1061 int mm_player_set_video_info (MMHandleType player, media_format_h format)
1062 {
1063         int result = MM_ERROR_NONE;
1064
1065         LOGD("\n");
1066
1067         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
1068
1069         MMPLAYER_CMD_LOCK( player );
1070
1071         result = _mmplayer_set_video_info(player, format);
1072
1073         MMPLAYER_CMD_UNLOCK( player );
1074
1075         return result;
1076
1077 }
1078
1079 int mm_player_set_audio_info (MMHandleType player, media_format_h format)
1080 {
1081         int result = MM_ERROR_NONE;
1082
1083         LOGD("\n");
1084
1085         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
1086
1087         MMPLAYER_CMD_LOCK( player );
1088
1089         result = _mmplayer_set_audio_info(player, format);
1090
1091         MMPLAYER_CMD_UNLOCK( player );
1092
1093         return result;
1094 }
1095
1096 int mm_player_set_subtitle_info (MMHandleType player, MMPlayerSubtitleStreamInfo *subtitle_stream_info)
1097 {
1098         int result = MM_ERROR_NONE;
1099
1100         LOGD("\n");
1101
1102         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
1103
1104         MMPLAYER_CMD_LOCK( player );
1105
1106         result = _mmplayer_set_subtitle_info(player, subtitle_stream_info);
1107
1108         MMPLAYER_CMD_UNLOCK( player );
1109
1110         return result;
1111 }
1112
1113 int mm_player_set_media_stream_buffer_max_size(MMHandleType player, MMPlayerStreamType type, unsigned long long max_size)
1114 {
1115         int result = MM_ERROR_NONE;
1116
1117         LOGD("\n");
1118
1119         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
1120
1121         MMPLAYER_CMD_LOCK( player );
1122
1123         result = _mmplayer_set_media_stream_max_size(player, type, max_size);
1124
1125         MMPLAYER_CMD_UNLOCK( player );
1126
1127         return result;
1128 }
1129
1130 int mm_player_get_media_stream_buffer_max_size(MMHandleType player, MMPlayerStreamType type, unsigned long long *max_size)
1131 {
1132         int result = MM_ERROR_NONE;
1133         guint64 _max_size = 0;
1134
1135         LOGD("\n");
1136
1137         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
1138         MMPLAYER_RETURN_VAL_IF_FAIL(max_size, MM_ERROR_INVALID_ARGUMENT);
1139
1140         MMPLAYER_CMD_LOCK( player );
1141
1142         result = _mmplayer_get_media_stream_max_size(player, type, &_max_size);
1143         *max_size = _max_size;
1144
1145         MMPLAYER_CMD_UNLOCK( player );
1146
1147         return result;
1148 }
1149
1150 int mm_player_set_media_stream_buffer_min_percent(MMHandleType player, MMPlayerStreamType type, unsigned min_percent)
1151 {
1152         int result = MM_ERROR_NONE;
1153
1154         LOGD("\n");
1155
1156         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
1157
1158         MMPLAYER_CMD_LOCK( player );
1159
1160         result = _mmplayer_set_media_stream_min_percent(player, type, min_percent);
1161
1162         MMPLAYER_CMD_UNLOCK( player );
1163
1164         return result;
1165 }
1166
1167 int mm_player_get_media_stream_buffer_min_percent(MMHandleType player, MMPlayerStreamType type, unsigned int *min_percent)
1168 {
1169         int result = MM_ERROR_NONE;
1170
1171         LOGD("\n");
1172
1173         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
1174         MMPLAYER_RETURN_VAL_IF_FAIL(min_percent, MM_ERROR_INVALID_ARGUMENT);
1175
1176         MMPLAYER_CMD_LOCK( player );
1177
1178         result = _mmplayer_get_media_stream_min_percent(player, type, min_percent);
1179
1180         MMPLAYER_CMD_UNLOCK( player );
1181
1182         return result;
1183 }
1184
1185 int mm_player_set_media_stream_buffer_status_callback(MMHandleType player, MMPlayerStreamType type, mm_player_media_stream_buffer_status_callback callback, void * user_param)
1186 {
1187         int result = MM_ERROR_NONE;
1188
1189         LOGD("\n");
1190
1191         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
1192
1193         MMPLAYER_CMD_LOCK( player );
1194
1195         result = _mmplayer_set_media_stream_buffer_status_cb(player, type, callback, user_param);
1196
1197         MMPLAYER_CMD_UNLOCK( player );
1198
1199         return result;
1200 }
1201
1202 int mm_player_set_media_stream_seek_data_callback(MMHandleType player, MMPlayerStreamType type, mm_player_media_stream_seek_data_callback callback, void * user_param)
1203 {
1204         int result = MM_ERROR_NONE;
1205
1206         LOGD("\n");
1207
1208         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
1209
1210         MMPLAYER_CMD_LOCK( player );
1211
1212         result = _mmplayer_set_media_stream_seek_data_cb(player, type, callback, user_param);
1213
1214         MMPLAYER_CMD_UNLOCK( player );
1215
1216         return result;
1217 }
1218
1219 int mm_player_set_audio_stream_changed_callback(MMHandleType player, mm_player_stream_changed_callback callback, void *user_param)
1220 {
1221         int result = MM_ERROR_NONE;
1222
1223         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
1224
1225         MMPLAYER_CMD_LOCK( player );
1226
1227         result = _mmplayer_set_audiostream_changed_cb(player, callback, user_param);
1228
1229         MMPLAYER_CMD_UNLOCK( player );
1230
1231         return result;
1232 }
1233
1234 int mm_player_set_video_stream_changed_callback(MMHandleType player, mm_player_stream_changed_callback callback, void *user_param)
1235 {
1236         int result = MM_ERROR_NONE;
1237
1238         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
1239
1240         MMPLAYER_CMD_LOCK( player );
1241
1242         result = _mmplayer_set_videostream_changed_cb(player, callback, user_param);
1243
1244         MMPLAYER_CMD_UNLOCK( player );
1245
1246         return result;
1247 }
1248
1249 int mm_player_set_pcm_spec(MMHandleType player, int samplerate, int channel)
1250 {
1251         int result = MM_ERROR_NONE;
1252
1253         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
1254
1255         MMPLAYER_CMD_LOCK( player );
1256
1257         result = _mmplayer_set_pcm_spec(player, samplerate, channel);
1258
1259         MMPLAYER_CMD_UNLOCK( player );
1260
1261         return result;
1262 }
1263
1264 int mm_player_get_timeout(MMHandleType player, int *timeout)
1265 {
1266         int result = MM_ERROR_NONE;
1267
1268         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
1269         MMPLAYER_RETURN_VAL_IF_FAIL(timeout, MM_ERROR_COMMON_INVALID_ARGUMENT);
1270
1271         MMPLAYER_CMD_LOCK( player );
1272
1273         result = _mmplayer_get_timeout(player, timeout);
1274
1275         MMPLAYER_CMD_UNLOCK( player );
1276
1277         return result;
1278 }
1279
1280 int mm_player_get_num_of_video_out_buffers(MMHandleType player, int *num, int *extra_num)
1281 {
1282         int result = MM_ERROR_NONE;
1283
1284         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
1285         MMPLAYER_RETURN_VAL_IF_FAIL(num && extra_num, MM_ERROR_COMMON_INVALID_ARGUMENT);
1286
1287         MMPLAYER_CMD_LOCK( player );
1288
1289         result = _mmplayer_get_num_of_video_out_buffers(player, num, extra_num);
1290
1291         MMPLAYER_CMD_UNLOCK( player );
1292
1293         return result;
1294 }
1295
1296 int mm_player_set_media_stream_dynamic_resolution(MMHandleType player, bool drc)
1297 {
1298         int result = MM_ERROR_NONE;
1299
1300         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
1301
1302         MMPLAYER_CMD_LOCK( player );
1303
1304         result = _mmplayer_set_media_stream_dynamic_resolution(player, drc);
1305
1306         MMPLAYER_CMD_UNLOCK( player );
1307
1308         return result;
1309 }
1310
1311 int mm_player_release_video_stream_bo(MMHandleType player, void* bo)
1312 {
1313         int result = MM_ERROR_NONE;
1314
1315         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
1316         MMPLAYER_RETURN_VAL_IF_FAIL(bo, MM_ERROR_COMMON_INVALID_ARGUMENT);
1317 //      MMPLAYER_CMD_LOCK( player );
1318
1319         result = _mmplayer_video_stream_release_bo(player, bo);
1320
1321 //      MMPLAYER_CMD_UNLOCK( player );
1322         return result;
1323 }
1324
1325 int mm_player_set_file_buffering_path(MMHandleType player, const char *file_path)
1326 {
1327         int result = MM_ERROR_NONE;
1328
1329         MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
1330
1331         MMPLAYER_CMD_LOCK( player );
1332
1333         result = _mmplayer_set_file_buffering_path(player, file_path);
1334
1335         MMPLAYER_CMD_UNLOCK( player );
1336
1337         return result;
1338 }