Revert "Add sound_manager_reserve_release_all_focus() function in sound_manager_inter...
[platform/core/api/sound-manager.git] / src / sound_manager.c
1 /*
2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "sound_manager.h"
18 #include "sound_manager_private.h"
19 #include <system_info.h>
20
21 #define FEATURE_MICROPHONE          "http://tizen.org/feature/microphone"
22
23 _session_interrupt_info_s g_session_interrupt_cb_table = {0, 0, NULL, NULL};
24 _volume_changed_info_s g_volume_changed_cb_table = {0, NULL, NULL};
25 _device_connected_info_s g_device_connected_cb_table = {0, NULL, NULL};
26 _device_changed_info_s g_device_info_changed_cb_table = {0, NULL, NULL};
27 _focus_watch_info_s focus_watch_info_arr[SOUND_STREAM_INFO_ARR_MAX];
28
29 sound_session_type_e g_cached_session = -1;
30 _session_mode_e g_cached_session_mode = -1;
31 int g_cached_voip_device_id = -1;
32 extern sound_stream_info_s *g_voip_stream_info;
33 extern virtual_sound_stream_info_s *g_voip_vstream_h;
34
35 /* These variables will be removed when session features are deprecated. */
36 extern int g_stream_info_count;
37 extern pthread_mutex_t g_stream_info_count_mutex;
38 pthread_mutex_t g_interrupt_cb_mutex, g_device_info_cb_mutex, g_device_conn_cb_mutex, g_volume_cb_mutex;
39
40 int sound_manager_get_max_volume(sound_type_e type, int *max)
41 {
42         const char *volume_type = NULL;
43         unsigned int max_level = 0;
44         int ret = MM_ERROR_NONE;
45
46         SM_NULL_ARG_CHECK(max);
47         if (type >= SOUND_TYPE_NUM || type < 0)
48                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
49
50         ret = _convert_sound_type(type, &volume_type);
51         if (ret == MM_ERROR_NONE) {
52                 ret = _get_volume_max_level(DIRECTION_OUT_STR, volume_type, &max_level);
53                 if (ret == MM_ERROR_NONE)
54                         *max = (int)max_level -1;       /* actual volume step can be max step - 1 */
55         }
56
57         return _convert_sound_manager_error_code(__func__, ret);
58 }
59
60 int sound_manager_set_volume(sound_type_e type, int volume)
61 {
62         int ret = MM_ERROR_NONE;
63
64         if (type >= SOUND_TYPE_NUM || type < 0)
65                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
66         if (volume < 0)
67                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
68
69         ret = mm_sound_volume_set_value(type, volume);
70         LOGI("type=%d, volume=%d", type, volume);
71
72         return _convert_sound_manager_error_code(__func__, ret);
73 }
74
75 int sound_manager_get_volume(sound_type_e type, int *volume)
76 {
77         int ret = MM_ERROR_NONE;
78         unsigned int uvolume;
79
80         if (type >= SOUND_TYPE_NUM || type < 0)
81                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
82         if (volume == NULL)
83                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
84
85         ret = mm_sound_volume_get_value(type, &uvolume);
86         if (ret == MM_ERROR_NONE)
87                 *volume = uvolume;
88
89         LOGI("type=%d, volume=%d", type, *volume);
90
91         return _convert_sound_manager_error_code(__func__, ret);
92 }
93
94 int sound_manager_set_current_sound_type(sound_type_e type)
95 {
96         int ret = MM_ERROR_NONE;
97
98         LOGW("DEPRECATION WARNING: %s() is deprecated and will be removed from next release.", __func__);
99         if (type >= SOUND_TYPE_NUM || type < 0)
100                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
101
102         ret = mm_sound_volume_primary_type_set(type);
103
104         return _convert_sound_manager_error_code(__func__, ret);
105 }
106
107 int sound_manager_get_current_sound_type(sound_type_e *type)
108 {
109         int ret = MM_ERROR_NONE;
110         volume_type_t mm_sound_vol_type = VOLUME_TYPE_UNKNOWN;
111         char *volume_type = NULL;
112
113         if (type == NULL)
114                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
115
116         ret  = mm_sound_volume_primary_type_get(&mm_sound_vol_type);
117         if (ret == MM_ERROR_NONE) {
118                 if (mm_sound_vol_type == VOLUME_TYPE_UNKNOWN) {
119                         /* get the volume type of the current playing stream */
120                         ret = _get_current_volume_type(DIRECTION_OUT_STR, &volume_type);
121                         if (ret == MM_ERROR_NONE)
122                                 ret = _convert_sound_type_to_enum((const char*)volume_type, type);
123                 } else {
124                         *type = mm_sound_vol_type;
125                 }
126         }
127         LOGI("type=%d", *type);
128
129         return _convert_sound_manager_error_code(__func__, ret);
130 }
131
132 int sound_manager_unset_current_sound_type(void)
133 {
134         int ret = MM_ERROR_NONE;
135
136         LOGW("DEPRECATION WARNING: %s() is deprecated and will be removed from next release.", __func__);
137         ret = mm_sound_volume_primary_type_set(VOLUME_TYPE_UNKNOWN);
138
139         return _convert_sound_manager_error_code(__func__, ret);
140 }
141
142 int sound_manager_set_volume_changed_cb(sound_manager_volume_changed_cb callback, void* user_data)
143 {
144         int ret = MM_ERROR_NONE;
145         unsigned int subs_id = 0;
146
147         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_volume_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
148
149         ret = mm_sound_add_volume_changed_callback((mm_sound_volume_changed_cb)callback, user_data, &subs_id);
150         if (ret == MM_ERROR_NONE) {
151                 g_volume_changed_cb_table.subs_id = subs_id;
152                 g_volume_changed_cb_table.user_cb = (sound_manager_volume_changed_cb)callback;
153                 g_volume_changed_cb_table.user_data = user_data;
154         }
155
156         SM_LEAVE_CRITICAL_SECTION(&g_volume_cb_mutex);
157
158         return _convert_sound_manager_error_code(__func__, ret);
159 }
160
161 int sound_manager_unset_volume_changed_cb(void)
162 {
163         int ret = MM_ERROR_NONE;
164
165         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_volume_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
166
167         if (g_volume_changed_cb_table.subs_id > 0) {
168                 ret = mm_sound_remove_volume_changed_callback(g_volume_changed_cb_table.subs_id);
169                 if (ret == MM_ERROR_NONE) {
170                         g_volume_changed_cb_table.subs_id = 0;
171                         g_volume_changed_cb_table.user_cb = NULL;
172                         g_volume_changed_cb_table.user_data = NULL;
173                 }
174         } else {
175                 ret = MM_ERROR_SOUND_INTERNAL;
176         }
177
178         SM_LEAVE_CRITICAL_SECTION(&g_volume_cb_mutex);
179
180         return _convert_sound_manager_error_code(__func__, ret);
181 }
182
183 int sound_manager_create_stream_information(sound_stream_type_e stream_type, sound_stream_focus_state_changed_cb callback, void *user_data, sound_stream_info_h *stream_info)
184 {
185         int ret = MM_ERROR_NONE;
186
187         LOGI(">> enter");
188
189         SM_NULL_ARG_CHECK(stream_info);
190
191         if (g_session_interrupt_cb_table.is_registered)
192                 return _convert_sound_manager_error_code(__func__, MM_ERROR_SOUND_INTERNAL);
193
194         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_stream_info_count_mutex, MM_ERROR_SOUND_INTERNAL);
195
196         sound_stream_info_s *stream_h = malloc(sizeof(sound_stream_info_s));
197         if (!stream_h) {
198                 ret = MM_ERROR_OUT_OF_MEMORY;
199                 goto LEAVE;
200         }
201
202         memset(stream_h, 0, sizeof(sound_stream_info_s));
203         ret = _convert_stream_type(stream_type, &stream_h->stream_type);
204         if (ret == MM_ERROR_NONE) {
205                 ret = _make_pa_connection_and_register_focus(stream_h, callback, user_data);
206                 if (ret == MM_ERROR_NONE) {
207                         *stream_info = (sound_stream_info_h)stream_h;
208                         SM_REF_FOR_STREAM_INFO(g_stream_info_count, ret);
209                         LOGI("stream_h(%p), index(%u), user_cb(%p), cnt(%d), ret(0x%x)", stream_h, stream_h->index, stream_h->user_cb, g_stream_info_count, ret);
210                 }
211         }
212
213 LEAVE:
214         if (ret && stream_h)
215                 free(stream_h);
216
217         SM_LEAVE_CRITICAL_SECTION(&g_stream_info_count_mutex);
218
219         return _convert_sound_manager_error_code(__func__, ret);
220 }
221
222 int sound_manager_destroy_stream_information(sound_stream_info_h stream_info)
223 {
224         int ret = MM_ERROR_NONE;
225         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
226
227         LOGI(">> enter");
228
229         SM_INSTANCE_CHECK(stream_h);
230
231         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_stream_info_count_mutex, MM_ERROR_SOUND_INTERNAL);
232         ret = _destroy_pa_connection_and_unregister_focus(stream_h);
233         if (ret == MM_ERROR_NONE) {
234                 free(stream_h);
235                 stream_h = NULL;
236                 SM_UNREF_FOR_STREAM_INFO(g_stream_info_count);
237         }
238         SM_LEAVE_CRITICAL_SECTION(&g_stream_info_count_mutex);
239
240         LOGD("cnt(%d)", g_stream_info_count);
241
242         return _convert_sound_manager_error_code(__func__, ret);
243 }
244
245 int sound_manager_get_sound_type(sound_stream_info_h stream_info, sound_type_e *sound_type)
246 {
247         int ret = MM_ERROR_NONE;
248         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
249
250         LOGI(">> enter");
251
252         SM_INSTANCE_CHECK(stream_h);
253         SM_NULL_ARG_CHECK(sound_type);
254
255         if (stream_h->stream_conf_info.volume_type == NULL) {
256                 ret = MM_ERROR_SOUND_NO_DATA;
257                 goto LEAVE;
258         }
259
260         ret = _convert_sound_type_to_enum(stream_h->stream_conf_info.volume_type, sound_type);
261         LOGI("sound type(%d)", *sound_type);
262
263 LEAVE:
264         return _convert_sound_manager_error_code(__func__, ret);
265 }
266
267 int sound_manager_add_device_for_stream_routing(sound_stream_info_h stream_info, sound_device_h device)
268 {
269         int ret = MM_ERROR_NONE;
270         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
271
272         LOGI(">> enter");
273
274         ret = _add_device_for_stream_routing(stream_h, device);
275
276         return _convert_sound_manager_error_code(__func__, ret);
277 }
278
279 int sound_manager_remove_device_for_stream_routing(sound_stream_info_h stream_info, sound_device_h device)
280 {
281         int ret = MM_ERROR_NONE;
282         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
283
284         LOGI(">> enter");
285
286         ret = _remove_device_for_stream_routing(stream_h, device);
287
288         return _convert_sound_manager_error_code(__func__, ret);
289 }
290
291 int sound_manager_apply_stream_routing(sound_stream_info_h stream_info)
292 {
293         int ret = MM_ERROR_NONE;
294         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
295
296         LOGI(">> enter");
297
298         ret = _apply_stream_routing(stream_h);
299
300         return _convert_sound_manager_error_code(__func__, ret);
301 }
302
303 int sound_manager_set_focus_reacquisition(sound_stream_info_h stream_info, bool enable)
304 {
305         int ret = MM_ERROR_NONE;
306         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
307
308         LOGI(">> enter");
309
310         SM_INSTANCE_CHECK(stream_h);
311
312         ret = mm_sound_set_focus_reacquisition(stream_h->index, enable);
313
314         return _convert_sound_manager_error_code(__func__, ret);
315 }
316
317 int sound_manager_get_focus_reacquisition(sound_stream_info_h stream_info, bool *enabled)
318 {
319         int ret = MM_ERROR_NONE;
320         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
321
322         LOGI(">> enter");
323
324         SM_INSTANCE_CHECK(stream_h);
325         SM_NULL_ARG_CHECK(enabled);
326
327         ret = mm_sound_get_focus_reacquisition(stream_h->index, enabled);
328
329         return _convert_sound_manager_error_code(__func__, ret);
330 }
331
332 int sound_manager_acquire_focus(sound_stream_info_h stream_info, sound_stream_focus_mask_e focus_mask, const char *extra_info)
333 {
334         int ret = MM_ERROR_NONE;
335         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
336
337         LOGI(">> enter");
338
339         SM_INSTANCE_CHECK(stream_h);
340
341         if (stream_h->is_focus_unavailable) {
342                 LOGE("acquiring focus is not allowed for this strema type(%s)", stream_h->stream_type);
343                 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
344         }
345
346         if (stream_h->user_cb == NULL) {
347                 LOGE("focus state changed callback should be set before acquiring focus");
348                 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
349         }
350
351         ret = mm_sound_acquire_focus_with_option(stream_h->index, (mm_sound_focus_type_e)focus_mask, stream_h->requesting_flags, extra_info);
352         if (ret == MM_ERROR_NONE) {
353                 stream_h->acquired_focus |= focus_mask;
354                 _update_focus_status(stream_h->index, (unsigned int)stream_h->acquired_focus);
355         }
356
357         return _convert_sound_manager_error_code(__func__, ret);
358 }
359
360 int sound_manager_release_focus(sound_stream_info_h stream_info, sound_stream_focus_mask_e focus_mask, const char *extra_info)
361 {
362         int ret = MM_ERROR_NONE;
363         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
364
365         LOGI(">> enter");
366
367         SM_INSTANCE_CHECK(stream_h);
368
369         ret = mm_sound_release_focus_with_option(stream_h->index, (mm_sound_focus_type_e)focus_mask, stream_h->requesting_flags, extra_info);
370         if (ret == MM_ERROR_NONE) {
371                 stream_h->acquired_focus &= ~focus_mask;
372                 _update_focus_status(stream_h->index, (unsigned int)stream_h->acquired_focus);
373         }
374
375         return _convert_sound_manager_error_code(__func__, ret);
376 }
377
378 int sound_manager_get_focus_state(sound_stream_info_h stream_info, sound_stream_focus_state_e *state_for_playback, sound_stream_focus_state_e *state_for_recording)
379 {
380         int ret = MM_ERROR_NONE;
381         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
382
383         LOGI(">> enter");
384
385         SM_INSTANCE_CHECK(stream_h);
386         if (!state_for_playback && !state_for_recording) {
387                 ret = MM_ERROR_INVALID_ARGUMENT;
388                 goto LEAVE;
389         }
390
391         if (state_for_playback)
392                 *state_for_playback = ((stream_h->acquired_focus & SOUND_STREAM_FOCUS_FOR_PLAYBACK) ? (SOUND_STREAM_FOCUS_STATE_ACQUIRED) : (SOUND_STREAM_FOCUS_STATE_RELEASED));
393         if (state_for_recording)
394                 *state_for_recording = ((stream_h->acquired_focus & SOUND_STREAM_FOCUS_FOR_RECORDING) ? (SOUND_STREAM_FOCUS_STATE_ACQUIRED) : (SOUND_STREAM_FOCUS_STATE_RELEASED));
395
396         LOGI("acquired_focus(0x%x)", stream_h->acquired_focus);
397
398 LEAVE:
399         return _convert_sound_manager_error_code(__func__, ret);
400 }
401
402 int sound_manager_get_changed_focus_state(sound_stream_info_h stream_info, sound_stream_focus_mask_e *focus_mask, sound_stream_focus_state_e *focus_state)
403 {
404         int ret = MM_ERROR_NONE;
405         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
406         bool is_focus_cb_thread = false;
407
408         LOGI(">> enter");
409
410         SM_INSTANCE_CHECK(stream_h);
411         SM_NULL_ARG_CHECK(focus_mask);
412         SM_NULL_ARG_CHECK(focus_state);
413
414         if ((ret = mm_sound_focus_is_cb_thread(&is_focus_cb_thread)))
415                 return _convert_sound_manager_error_code(__func__, ret);
416
417         if (!is_focus_cb_thread) {
418                 LOGE("this API should be called in focus state changed callback");
419                 return SOUND_MANAGER_ERROR_INVALID_OPERATION;
420         }
421
422         if (stream_h->changed_focus_type == FOCUS_NONE)
423                 return SOUND_MANAGER_ERROR_INVALID_OPERATION;
424
425         *focus_mask = (sound_stream_focus_mask_e)stream_h->changed_focus_type;
426         *focus_state = (sound_stream_focus_state_e)stream_h->changed_focus_state;
427
428         LOGI("changed focus(mask:0x%x, state:%d)", *focus_mask, *focus_state);
429
430         return _convert_sound_manager_error_code(__func__, ret);
431 }
432
433 int sound_manager_focus_set_requesting_behavior(sound_stream_info_h stream_info, int flags)
434 {
435         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
436
437         LOGI(">> enter");
438
439         SM_INSTANCE_CHECK(stream_h);
440         SM_RANGE_ARG_CHECK(flags,
441                                 SOUND_BEHAVIOR_NONE,
442                                 (SOUND_BEHAVIOR_NO_RESUME|SOUND_BEHAVIOR_FADING));
443
444         stream_h->requesting_flags = flags;
445
446         LOGI("the requesting sound behavior(0x%x) is set", stream_h->requesting_flags);
447
448         return SOUND_MANAGER_ERROR_NONE;
449 }
450
451 int sound_manager_focus_get_requesting_behavior(sound_stream_info_h stream_info, int *flags)
452 {
453         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
454
455         LOGI(">> enter");
456
457         SM_INSTANCE_CHECK(stream_h);
458         SM_NULL_ARG_CHECK(flags);
459
460         *flags = stream_h->requesting_flags;
461
462         LOGI("the requesting sound behavior is (0x%x)", stream_h->requesting_flags);
463
464         return SOUND_MANAGER_ERROR_NONE;
465 }
466
467 int sound_manager_focus_get_requested_behavior(sound_stream_info_h stream_info, int *flags)
468 {
469         int ret = MM_ERROR_NONE;
470         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
471         bool is_focus_cb_thread = false;
472
473         LOGI(">> enter");
474
475         SM_INSTANCE_CHECK(stream_h);
476         SM_NULL_ARG_CHECK(flags);
477
478         if ((ret = mm_sound_focus_is_cb_thread(&is_focus_cb_thread)))
479                 return _convert_sound_manager_error_code(__func__, ret);
480
481         if (!is_focus_cb_thread) {
482                 LOGE("this API should be called in focus state changed callback");
483                 return SOUND_MANAGER_ERROR_INVALID_OPERATION;
484         }
485
486         *flags = stream_h->requested_flags;
487
488         LOGI("requested sound behavior is (0x%x)", stream_h->requested_flags);
489
490         return SOUND_MANAGER_ERROR_NONE;
491 }
492
493 int sound_manager_get_current_playback_focus(sound_stream_focus_change_reason_e *acquired_by, int *flags, char **extra_info)
494 {
495         int ret = MM_ERROR_NONE;
496         char *stream_type_str = NULL;
497         char *extra_info_str = NULL;
498         int option = 0;
499         bool is_focus_cb_thread = false;
500
501         LOGI(">> enter");
502
503         SM_NULL_ARG_CHECK(acquired_by);
504         SM_NULL_ARG_CHECK(flags);
505
506         if ((ret = mm_sound_focus_is_cb_thread(&is_focus_cb_thread)))
507                 return _convert_sound_manager_error_code(__func__, ret);
508
509         if (is_focus_cb_thread) {
510                 LOGE("this API should not be called in focus callback");
511                 return SOUND_MANAGER_ERROR_INVALID_OPERATION;
512         }
513
514         ret = mm_sound_get_stream_type_of_acquired_focus((int)SOUND_STREAM_FOCUS_FOR_PLAYBACK, &stream_type_str, &option, &extra_info_str);
515         if (ret == MM_ERROR_NONE) {
516                 LOGI("current acquired PLAYBACK focus : stream_type[%s]", stream_type_str);
517                 ret = _convert_stream_type_to_change_reason(stream_type_str, acquired_by);
518                 if (ret == MM_ERROR_NONE) {
519                         LOGI("                                : reason[%d], flags[0x%x], extra_info[%s]", *acquired_by, option, extra_info_str);
520                         *flags = option;
521                         if (extra_info)
522                                 *extra_info = extra_info_str;
523                         else
524                                 free(extra_info_str);
525                 }
526         }
527
528         return _convert_sound_manager_error_code(__func__, ret);
529 }
530
531 int sound_manager_get_current_recording_focus(sound_stream_focus_change_reason_e *acquired_by, int *flags, char **extra_info)
532 {
533         int ret = MM_ERROR_NONE;
534         char *stream_type_str = NULL;
535         char *extra_info_str = NULL;
536         int option = 0;
537         bool is_focus_cb_thread = false;
538
539         LOGI(">> enter");
540
541         SM_NULL_ARG_CHECK(acquired_by);
542         SM_NULL_ARG_CHECK(flags);
543
544         if ((ret = mm_sound_focus_is_cb_thread(&is_focus_cb_thread)))
545                 return _convert_sound_manager_error_code(__func__, ret);
546
547         if (is_focus_cb_thread) {
548                 LOGE("this API should not be called in focus callback");
549                 return SOUND_MANAGER_ERROR_INVALID_OPERATION;
550         }
551
552         ret = mm_sound_get_stream_type_of_acquired_focus((int)SOUND_STREAM_FOCUS_FOR_RECORDING, &stream_type_str, &option, &extra_info_str);
553         if (ret == MM_ERROR_NONE) {
554                 LOGI("current acquired RECORDING focus : stream_type[%s]", stream_type_str);
555                 ret = _convert_stream_type_to_change_reason(stream_type_str, acquired_by);
556                 if (ret == MM_ERROR_NONE) {
557                         LOGI("                                 : reason[%d], flags[0x%x], extra_info[%s]", *acquired_by, option, extra_info_str);
558                         *flags = option;
559                         if (extra_info)
560                                 *extra_info = extra_info_str;
561                         else
562                                 free(extra_info_str);
563                 }
564         }
565
566         return _convert_sound_manager_error_code(__func__, ret);
567 }
568
569 int sound_manager_add_focus_state_watch_cb(sound_stream_focus_mask_e focus_mask, sound_stream_focus_state_watch_cb callback, void *user_data, int *id)
570 {
571         int ret = MM_ERROR_NONE;
572         int i = 0;
573
574         LOGI(">> enter");
575
576         SM_NULL_ARG_CHECK(callback);
577         SM_NULL_ARG_CHECK(id);
578         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_stream_info_count_mutex, SOUND_MANAGER_ERROR_INTERNAL);
579
580         for (i = 0; i < SOUND_STREAM_INFO_ARR_MAX; i++)
581                 if (focus_watch_info_arr[i].id == 0)
582                         break;
583         if (i == SOUND_STREAM_INFO_ARR_MAX) {
584                 LOGE("focus watch info array is full");
585                 ret = MM_ERROR_SOUND_INTERNAL;
586                 goto LEAVE;
587         }
588
589         ret = mm_sound_set_focus_watch_callback((mm_sound_focus_type_e)focus_mask, _focus_watch_callback, user_data, id);
590         if (ret == MM_ERROR_NONE) {
591                 SM_REF_FOR_STREAM_INFO(g_stream_info_count, ret);
592                 focus_watch_info_arr[i].id = *id;
593                 focus_watch_info_arr[i].user_data = user_data;
594                 focus_watch_info_arr[i].user_cb = callback;
595         }
596
597 LEAVE:
598         SM_LEAVE_CRITICAL_SECTION(&g_stream_info_count_mutex);
599
600         LOGD("cnt(%d), id(%d)", g_stream_info_count, *id);
601
602         return _convert_sound_manager_error_code(__func__, ret);
603 }
604
605 int sound_manager_remove_focus_state_watch_cb(int id)
606 {
607         int ret = MM_ERROR_NONE;
608         int i = 0;
609
610         LOGI(">> enter");
611
612         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_stream_info_count_mutex, SOUND_MANAGER_ERROR_INTERNAL);
613
614         for (i = 0; i < SOUND_STREAM_INFO_ARR_MAX; i++)
615                 if (focus_watch_info_arr[i].id == id)
616                         break;
617         if (i == SOUND_STREAM_INFO_ARR_MAX) {
618                 LOGE("cound not find item in focus watch info array for this id(%d)", id);
619                 ret = MM_ERROR_INVALID_ARGUMENT;
620                 goto LEAVE;
621         }
622
623         ret = mm_sound_unset_focus_watch_callback(id);
624         if (ret == MM_ERROR_NONE) {
625                 SM_UNREF_FOR_STREAM_INFO(g_stream_info_count);
626                 focus_watch_info_arr[i].id = 0;
627                 focus_watch_info_arr[i].user_data = NULL;
628                 focus_watch_info_arr[i].user_cb = NULL;
629         }
630
631 LEAVE:
632         SM_LEAVE_CRITICAL_SECTION(&g_stream_info_count_mutex);
633
634         LOGD("cnt(%d)", g_stream_info_count);
635
636         return _convert_sound_manager_error_code(__func__, ret);
637 }
638
639 int sound_manager_set_session_type(sound_session_type_e type)
640 {
641         int ret = MM_ERROR_NONE;
642         int cur_session = -1;
643         int new_session = MM_SESSION_TYPE_MEDIA;
644         bool mic_enable = false;
645
646         LOGW("DEPRECATION WARNING: %s() is deprecated and will be removed from next release. Use sound_manager_create_stream_information() instead.", __func__);
647         LOGI(">> enter : type=%d", type);
648
649         if (type < SOUND_SESSION_TYPE_MEDIA || type >  SOUND_SESSION_TYPE_VOIP)
650                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
651
652         /* If session type is VOIP but MIC is not enabled, return false */
653         if (type == SOUND_SESSION_TYPE_VOIP) {
654                 ret = system_info_get_platform_bool(FEATURE_MICROPHONE, &mic_enable);
655                 LOGI("system_info_platform [%s]=[%d], ret[%d]", FEATURE_MICROPHONE, mic_enable, ret);
656                 if (ret != SYSTEM_INFO_ERROR_NONE || !mic_enable)
657                         return _convert_sound_manager_error_code(__func__, MM_ERROR_NOT_SUPPORT_API);
658         }
659
660         /* it is not supported both session and stream feature at the same time */
661         if (g_stream_info_count) {
662                 LOGE("Could not set this type(%d) because of being used stream feature", type);
663                 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
664         }
665
666         switch (type) {
667         case SOUND_SESSION_TYPE_MEDIA:
668                 new_session = MM_SESSION_TYPE_MEDIA;
669                 break;
670         case SOUND_SESSION_TYPE_ALARM:
671                 new_session = MM_SESSION_TYPE_ALARM;
672                 break;
673         case SOUND_SESSION_TYPE_NOTIFICATION:
674                 new_session = MM_SESSION_TYPE_NOTIFY;
675                 break;
676         case SOUND_SESSION_TYPE_EMERGENCY:
677                 new_session = MM_SESSION_TYPE_EMERGENCY;
678                 break;
679         case SOUND_SESSION_TYPE_VOIP:
680                 new_session = MM_SESSION_TYPE_VOIP;
681                 break;
682         }
683
684         /* valid session check */
685         ret = mm_session_get_current_type(&cur_session);
686         if (ret == MM_ERROR_NONE) {
687                 if (cur_session == MM_SESSION_TYPE_MEDIA_RECORD) {
688                         if (type > SOUND_SESSION_TYPE_MEDIA) {
689                                 LOGE("Could not set this type(%d) during camera/recorder/audio-io(in)/radio", type);
690                                 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
691                         }
692                 }
693         }
694
695         if (g_session_interrupt_cb_table.is_registered) {
696                 if (new_session == cur_session ||
697                         ((new_session == SOUND_SESSION_TYPE_MEDIA) && (cur_session == MM_SESSION_TYPE_MEDIA_RECORD))) {
698                         LOGI("already set type=%d, ret=0x%x", type, ret);
699                         return SOUND_MANAGER_ERROR_NONE;
700                 } else {
701                         ret = mm_session_finish();
702                         if (ret != MM_ERROR_NONE)
703                                 return _convert_sound_manager_error_code(__func__, ret);
704
705                         g_session_interrupt_cb_table.is_registered = 0;
706                         if (cur_session == MM_SESSION_TYPE_VOIP) {
707                                 g_cached_session_mode = -1;
708                                 g_cached_voip_device_id = -1;
709                                 if (g_voip_vstream_h) {
710                                         _stop_virtual_stream(g_voip_vstream_h);
711                                         _destroy_virtual_stream(g_voip_vstream_h);
712                                         g_voip_vstream_h = NULL;
713                                 }
714                                 /*voip stream destruction*/
715                                 if (g_voip_stream_info) {
716                                         ret = _destroy_pa_connection_and_unregister_focus(g_voip_stream_info);
717                                         free(g_voip_stream_info);
718                                         g_voip_stream_info = NULL;
719                                         if (ret != MM_ERROR_NONE)
720                                                 return _convert_sound_manager_error_code(__func__, ret);
721                                 }
722                         }
723                 }
724         }
725         ret = mm_session_init(new_session);
726         if (ret == MM_ERROR_NONE)
727                 g_session_interrupt_cb_table.is_registered = 1;
728
729         LOGI("type=%d", type);
730
731         return _convert_sound_manager_error_code(__func__, ret);
732 }
733
734 int sound_manager_get_session_type(sound_session_type_e *type)
735 {
736         int ret = MM_ERROR_NONE;
737         int cur_session;
738
739         LOGW("DEPRECATION WARNING: %s() is deprecated and will be removed from next release.", __func__);
740         if (type == NULL)
741                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
742
743         ret = mm_session_get_current_type(&cur_session);
744         if (ret != MM_ERROR_NONE) {
745                 LOGW("session hasn't been set, setting default session");
746                 cur_session = SOUND_SESSION_TYPE_DEFAULT;
747                 ret = mm_session_init(cur_session);
748                 if (ret == MM_ERROR_NONE)
749                         g_session_interrupt_cb_table.is_registered = 1;
750         }
751         if ((cur_session > MM_SESSION_TYPE_EMERGENCY) &&
752                         (cur_session != MM_SESSION_TYPE_VOIP)) {
753                 if (g_cached_session != -1)
754                         cur_session = g_cached_session;
755                 else /* will be never reached here. just prevent code */
756                         cur_session = SOUND_SESSION_TYPE_DEFAULT;
757         }
758
759         switch (cur_session) {
760         case MM_SESSION_TYPE_MEDIA:
761         case MM_SESSION_TYPE_MEDIA_RECORD:
762                 *type = SOUND_SESSION_TYPE_MEDIA;
763                 break;
764         case MM_SESSION_TYPE_ALARM:
765                 *type = SOUND_SESSION_TYPE_ALARM;
766                 break;
767         case MM_SESSION_TYPE_NOTIFY:
768                 *type = SOUND_SESSION_TYPE_NOTIFICATION;
769                 break;
770         case MM_SESSION_TYPE_EMERGENCY:
771                 *type = SOUND_SESSION_TYPE_EMERGENCY;
772                 break;
773         case MM_SESSION_TYPE_VOIP:
774                 *type = SOUND_SESSION_TYPE_VOIP;
775                 break;
776         default:
777                 *type = cur_session;
778                 break;
779         }
780
781         LOGI("type=%d", *type);
782
783         return SOUND_MANAGER_ERROR_NONE;
784 }
785
786 int sound_manager_set_media_session_option(sound_session_option_for_starting_e s_option, sound_session_option_for_during_play_e d_option)
787 {
788         int ret = MM_ERROR_NONE;
789         int session = 0;
790         int session_option = 0;
791         int updated = 0;
792
793         LOGW("DEPRECATION WARNING: %s() is deprecated and will be removed from next release. Use sound_manager_create_stream_information() instead.", __func__);
794         LOGI(">> enter : option for starting=%d, for during play=%d", s_option, d_option);
795
796         if (s_option < 0 || s_option >  SOUND_SESSION_OPTION_PAUSE_OTHERS_WHEN_START)
797                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
798         if (d_option < 0 || d_option >  SOUND_SESSION_OPTION_UNINTERRUPTIBLE_DURING_PLAY)
799                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
800
801         ret = mm_session_get_current_information(&session, &session_option);
802         if (ret != 0 || !g_session_interrupt_cb_table.is_registered) {
803                 LOGW("session hasn't been set, setting default session");
804                 ret = mm_session_init(MM_SESSION_TYPE_MEDIA);
805                 if (ret == 0)
806                         g_session_interrupt_cb_table.is_registered = 1;
807
808         } else if (ret == 0 && session > MM_SESSION_TYPE_MEDIA) {
809                 if (session == MM_SESSION_TYPE_MEDIA_RECORD) {
810                         if (!g_session_interrupt_cb_table.is_registered) {
811                                 LOGE("Already set by camera/recorder/audio-io(in)/radio API, but need to set session to Media first");
812                                 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
813                         }
814                 } else {
815                         return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
816                 }
817         }
818
819         switch (s_option) {
820         case SOUND_SESSION_OPTION_MIX_WITH_OTHERS_WHEN_START:
821                 if (session_option & MM_SESSION_OPTION_PAUSE_OTHERS) {
822                         ret = mm_session_update_option(MM_SESSION_UPDATE_TYPE_REMOVE, MM_SESSION_OPTION_PAUSE_OTHERS);
823                         if (ret)
824                                 return _convert_sound_manager_error_code(__func__, ret);
825
826                         updated = 1;
827                 }
828                 break;
829         case SOUND_SESSION_OPTION_PAUSE_OTHERS_WHEN_START:
830                 if (!(session_option & MM_SESSION_OPTION_PAUSE_OTHERS)) {
831                         ret = mm_session_update_option(MM_SESSION_UPDATE_TYPE_ADD, MM_SESSION_OPTION_PAUSE_OTHERS);
832                         if (ret)
833                                 return _convert_sound_manager_error_code(__func__, ret);
834
835                         updated = 1;
836                 }
837                 break;
838         }
839
840         switch (d_option) {
841         case SOUND_SESSION_OPTION_INTERRUPTIBLE_DURING_PLAY:
842                 if (session_option & MM_SESSION_OPTION_UNINTERRUPTIBLE) {
843                         ret = mm_session_update_option(MM_SESSION_UPDATE_TYPE_REMOVE, MM_SESSION_OPTION_UNINTERRUPTIBLE);
844                         if (ret)
845                                 return _convert_sound_manager_error_code(__func__, ret);
846
847                         updated = 1;
848                 }
849                 break;
850         case SOUND_SESSION_OPTION_UNINTERRUPTIBLE_DURING_PLAY:
851                 if (!(session_option & MM_SESSION_OPTION_UNINTERRUPTIBLE)) {
852                         ret = mm_session_update_option(MM_SESSION_UPDATE_TYPE_ADD, MM_SESSION_OPTION_UNINTERRUPTIBLE);
853                         if (ret)
854                                 return _convert_sound_manager_error_code(__func__, ret);
855
856                         updated = 1;
857                 }
858                 break;
859         }
860
861         if (updated)
862                 LOGI("updated");
863         else
864                 LOGI("already set same option(%x), skip it", session_option);
865
866         return _convert_sound_manager_error_code(__func__, ret);
867 }
868
869 int sound_manager_get_media_session_option(sound_session_option_for_starting_e *s_option, sound_session_option_for_during_play_e *d_option)
870 {
871         int ret = MM_ERROR_NONE;
872         int session = 0;
873         int session_options = 0;
874
875         LOGW("DEPRECATION WARNING: %s() is deprecated and will be removed from next release. Use sound_manager_create_stream_information() instead.", __func__);
876         LOGI(">> enter");
877
878         if (s_option == NULL || d_option == NULL)
879                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
880
881         ret = mm_session_get_current_information(&session, &session_options);
882         if (ret != 0) {
883                 ret = mm_session_init(MM_SESSION_TYPE_MEDIA);
884                 if (ret == 0)
885                         g_session_interrupt_cb_table.is_registered = 1;
886
887         } else if (session > SOUND_SESSION_TYPE_MEDIA) {
888                 if (session == MM_SESSION_TYPE_MEDIA_RECORD) {
889                         if (!g_session_interrupt_cb_table.is_registered) {
890                                 LOGE("Already set by camera/recorder/audio-io(in)/radio API, but need to set session to Media first");
891                                 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
892                         }
893                 } else
894                         return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
895         }
896         /* get option */
897         if (session_options & MM_SESSION_OPTION_PAUSE_OTHERS)
898                 *s_option = SOUND_SESSION_OPTION_PAUSE_OTHERS_WHEN_START;
899         else
900                 *s_option = SOUND_SESSION_OPTION_MIX_WITH_OTHERS_WHEN_START;
901
902         if (session_options & MM_SESSION_OPTION_UNINTERRUPTIBLE)
903                 *d_option = SOUND_SESSION_OPTION_UNINTERRUPTIBLE_DURING_PLAY;
904         else
905                 *d_option = SOUND_SESSION_OPTION_INTERRUPTIBLE_DURING_PLAY;
906
907         LOGI(" option for starting=%d, for during play=%d", *s_option, *d_option);
908
909         return SOUND_MANAGER_ERROR_NONE;
910 }
911
912 int sound_manager_set_media_session_resumption_option(sound_session_option_for_resumption_e option)
913 {
914         int ret = MM_ERROR_NONE;
915         int session = 0;
916         int session_option = 0;
917         int updated = 0;
918
919         LOGW("DEPRECATION WARNING: %s() is deprecated and will be removed from next release. Use sound_manager_create_stream_information() instead.", __func__);
920         LOGI(">> enter : option for resumption=%d (0:by system, 1:by system or media paused)", option);
921
922         if (option < SOUND_SESSION_OPTION_RESUMPTION_BY_SYSTEM || option > SOUND_SESSION_OPTION_RESUMPTION_BY_SYSTEM_OR_MEDIA_PAUSED)
923                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
924
925         ret = mm_session_get_current_information(&session, &session_option);
926         if (ret != 0 || !g_session_interrupt_cb_table.is_registered) {
927                 LOGW("session hasn't been set, setting default session");
928                 ret = mm_session_init(MM_SESSION_TYPE_MEDIA);
929                 if (ret == 0)
930                         g_session_interrupt_cb_table.is_registered = 1;
931
932         } else if (ret == 0 && session > MM_SESSION_TYPE_MEDIA) {
933                 if (session == MM_SESSION_TYPE_MEDIA_RECORD) {
934                         if (!g_session_interrupt_cb_table.is_registered) {
935                                 LOGE("Already set by camera/recorder/audio-io(in)/radio API, but need to set session to Media first");
936                                 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
937                         }
938                 } else
939                         return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
940
941         }
942
943         switch (option) {
944         case SOUND_SESSION_OPTION_RESUMPTION_BY_SYSTEM:
945                 if (session_option & MM_SESSION_OPTION_RESUME_BY_SYSTEM_OR_MEDIA_PAUSED) {
946                         ret = mm_session_update_option(MM_SESSION_UPDATE_TYPE_REMOVE, MM_SESSION_OPTION_RESUME_BY_SYSTEM_OR_MEDIA_PAUSED);
947                         if (ret)
948                                 return _convert_sound_manager_error_code(__func__, ret);
949
950                         updated = 1;
951                 }
952                 break;
953         case SOUND_SESSION_OPTION_RESUMPTION_BY_SYSTEM_OR_MEDIA_PAUSED:
954                 if (!(session_option & MM_SESSION_OPTION_RESUME_BY_SYSTEM_OR_MEDIA_PAUSED)) {
955                         ret = mm_session_update_option(MM_SESSION_UPDATE_TYPE_ADD, MM_SESSION_OPTION_RESUME_BY_SYSTEM_OR_MEDIA_PAUSED);
956                         if (ret)
957                                 return _convert_sound_manager_error_code(__func__, ret);
958
959                         updated = 1;
960                 }
961                 break;
962         }
963
964         if (updated)
965                 LOGI("updated");
966         else
967                 LOGI("already set same option(0x%x), skip it", session_option);
968
969         return _convert_sound_manager_error_code(__func__, ret);
970 }
971
972 int sound_manager_get_media_session_resumption_option(sound_session_option_for_resumption_e *option)
973 {
974         int ret = MM_ERROR_NONE;
975         int session = 0;
976         int session_options = 0;
977
978         LOGW("DEPRECATION WARNING: %s() is deprecated and will be removed from next release. Use sound_manager_create_stream_information() instead.", __func__);
979         LOGI(">> enter");
980
981         if (option == NULL)
982                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
983
984         ret = mm_session_get_current_information(&session, &session_options);
985         if (ret != 0) {
986                 LOGW("session hasn't been set, setting default session");
987                 ret = mm_session_init(MM_SESSION_TYPE_MEDIA);
988                 if (ret == 0)
989                         g_session_interrupt_cb_table.is_registered = 1;
990
991         } else if (session > SOUND_SESSION_TYPE_MEDIA) {
992                 if (session == MM_SESSION_TYPE_MEDIA_RECORD) {
993                         if (!g_session_interrupt_cb_table.is_registered) {
994                                 LOGE("Already set by camera/recorder/audio-io(in)/radio API, but need to set session to Media first");
995                                 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
996                         }
997                 } else
998                         return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
999         }
1000         /* get option */
1001         if (session_options & MM_SESSION_OPTION_RESUME_BY_SYSTEM_OR_MEDIA_PAUSED)
1002                 *option = SOUND_SESSION_OPTION_RESUMPTION_BY_SYSTEM_OR_MEDIA_PAUSED;
1003         else
1004                 *option = SOUND_SESSION_OPTION_RESUMPTION_BY_SYSTEM;
1005
1006         LOGI("option for resumption=%d (0:by system, 1:by system or media paused)", *option);
1007
1008         return SOUND_MANAGER_ERROR_NONE;
1009 }
1010
1011 int sound_manager_set_voip_session_mode(sound_session_voip_mode_e mode)
1012 {
1013         int ret = MM_ERROR_NONE;
1014         int session = 0;
1015         int session_options = 0;
1016
1017         LOGW("DEPRECATION WARNING: %s() is deprecated and will be removed from next release. Use sound_manager_create_stream_information() instead.", __func__);
1018         LOGI(">> enter : mode=%d", mode);
1019
1020         ret = mm_session_get_current_information(&session, &session_options);
1021         if (ret != MM_ERROR_NONE)
1022                 goto LEAVE;
1023
1024         if (session != MM_SESSION_TYPE_VOIP) {
1025                 ret = MM_ERROR_POLICY_INTERNAL;
1026                 goto LEAVE;
1027         }
1028
1029         if (mode < SOUND_SESSION_VOIP_MODE_RINGTONE || mode > SOUND_SESSION_VOIP_MODE_VOICE_WITH_BLUETOOTH) {
1030                 ret = MM_ERROR_INVALID_ARGUMENT;
1031                 goto LEAVE;
1032         }
1033
1034         ret = _set_session_mode((_session_mode_e)mode);
1035
1036         LOGI("session=%d, mode=%d", session, mode);
1037
1038 LEAVE:
1039         return _convert_sound_manager_error_code(__func__, ret);
1040 }
1041
1042 int sound_manager_get_voip_session_mode(sound_session_voip_mode_e *mode)
1043 {
1044         int ret = MM_ERROR_NONE;
1045         int session = 0;
1046         int session_options = 0;
1047
1048         LOGW("DEPRECATION WARNING: %s() is deprecated and will be removed from next release. Use sound_manager_create_stream_information() instead.", __func__);
1049         if (mode == NULL) {
1050                 LOGE("mode is null");
1051                 ret = MM_ERROR_INVALID_ARGUMENT;
1052                 goto LEAVE;
1053         }
1054
1055         ret = mm_session_get_current_information(&session, &session_options);
1056         if (ret != MM_ERROR_NONE) {
1057                 LOGI("session = %d, option = %d", session, session_options);
1058                 goto LEAVE;
1059         }
1060
1061         if (session != MM_SESSION_TYPE_VOIP || g_cached_session_mode == -1) {
1062                 ret = MM_ERROR_POLICY_INTERNAL;
1063                 goto LEAVE;
1064         }
1065
1066         *mode = (sound_session_voip_mode_e)g_cached_session_mode;
1067
1068         LOGI("session=%d, mode=%d", session, *mode);
1069
1070 LEAVE:
1071         return _convert_sound_manager_error_code(__func__, ret);
1072 }
1073
1074 int sound_manager_set_session_interrupted_cb(sound_session_interrupted_cb callback, void *user_data)
1075 {
1076         int ret = MM_ERROR_NONE;
1077         unsigned int subs_id = 0;
1078
1079         LOGW("DEPRECATION WARNING: %s() is deprecated and will be removed from next release. Use sound_manager_create_stream_information() instead.", __func__);
1080         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_interrupt_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
1081
1082         if (callback == NULL) {
1083                 ret = MM_ERROR_INVALID_ARGUMENT;
1084                 goto LEAVE;
1085         }
1086
1087         /* it is not supported both session and stream feature at the same time */
1088         if (g_stream_info_count) {
1089                 ret =  MM_ERROR_POLICY_INTERNAL;
1090                 goto LEAVE;
1091         }
1092
1093         if (g_session_interrupt_cb_table.user_cb == NULL) {
1094                 ret = mm_sound_add_device_connected_callback(SOUND_DEVICE_ALL_MASK, (mm_sound_device_connected_cb)_device_connected_cb, NULL, &subs_id);
1095                 if (ret)
1096                         goto LEAVE;
1097                 ret = mm_sound_focus_set_session_interrupt_callback((mm_sound_focus_session_interrupt_cb)_focus_session_interrupt_cb, NULL);
1098                 if (ret) {
1099                         if (mm_sound_remove_device_connected_callback(subs_id) != MM_ERROR_NONE)
1100                                 LOGW("mm_sound_remove_device_connected_callback failed");
1101                         goto LEAVE;
1102                 }
1103                 g_session_interrupt_cb_table.subs_id = subs_id;
1104         }
1105         g_session_interrupt_cb_table.user_cb = (sound_session_interrupted_cb)callback;
1106         g_session_interrupt_cb_table.user_data = user_data;
1107
1108 LEAVE:
1109         SM_LEAVE_CRITICAL_SECTION(&g_interrupt_cb_mutex);
1110
1111         return _convert_sound_manager_error_code(__func__, ret);
1112 }
1113
1114 int sound_manager_unset_session_interrupted_cb(void)
1115 {
1116         int ret = MM_ERROR_NONE;
1117
1118         LOGW("DEPRECATION WARNING: %s() is deprecated and will be removed from next release.", __func__);
1119         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_interrupt_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
1120
1121         if (!g_session_interrupt_cb_table.user_cb) {
1122                 ret = MM_ERROR_SOUND_INTERNAL;
1123                 goto LEAVE;
1124         }
1125
1126         ret = mm_sound_focus_unset_session_interrupt_callback();
1127         if (ret) {
1128                 if (mm_sound_remove_device_connected_callback(g_session_interrupt_cb_table.subs_id) != MM_ERROR_NONE)
1129                         LOGW("mm_sound_remove_device_connected_callback failed");
1130                 goto LEAVE;
1131         }
1132
1133         ret = mm_sound_remove_device_connected_callback(g_session_interrupt_cb_table.subs_id);
1134         if (ret)
1135                 goto LEAVE;
1136
1137         g_session_interrupt_cb_table.subs_id = 0;
1138         g_session_interrupt_cb_table.user_cb = NULL;
1139         g_session_interrupt_cb_table.user_data = NULL;
1140
1141 LEAVE:
1142         SM_LEAVE_CRITICAL_SECTION(&g_interrupt_cb_mutex);
1143
1144         return _convert_sound_manager_error_code(__func__, ret);
1145 }
1146
1147 int sound_manager_get_current_device_list(sound_device_mask_e device_mask, sound_device_list_h *device_list)
1148 {
1149         int ret = MM_ERROR_NONE;
1150
1151         ret = mm_sound_get_current_device_list((mm_sound_device_flags_e)device_mask, device_list);
1152
1153         return _convert_sound_manager_error_code(__func__, ret);
1154 }
1155
1156 int sound_manager_free_device_list(sound_device_list_h device_list)
1157 {
1158         int ret = MM_ERROR_NONE;
1159
1160         ret = mm_sound_free_device_list(device_list);
1161
1162         return _convert_sound_manager_error_code(__func__, ret);
1163 }
1164
1165 int sound_manager_get_next_device(sound_device_list_h device_list, sound_device_h *device)
1166 {
1167         int ret = MM_ERROR_NONE;
1168
1169         ret = mm_sound_get_next_device(device_list, device);
1170
1171         return _convert_sound_manager_error_code(__func__, ret);
1172 }
1173
1174 int sound_manager_get_prev_device(sound_device_list_h device_list, sound_device_h *device)
1175 {
1176         int ret = MM_ERROR_NONE;
1177
1178         ret = mm_sound_get_prev_device(device_list, device);
1179
1180         return _convert_sound_manager_error_code(__func__, ret);
1181 }
1182
1183 int sound_manager_get_device_type(sound_device_h device, sound_device_type_e *type)
1184 {
1185         int ret = MM_ERROR_NONE;
1186
1187         ret = mm_sound_get_device_type(device, (mm_sound_device_type_e*)type);
1188
1189         return _convert_sound_manager_error_code(__func__, ret);
1190 }
1191
1192 int sound_manager_get_device_io_direction(sound_device_h device, sound_device_io_direction_e *io_direction)
1193 {
1194         int ret = MM_ERROR_NONE;
1195         mm_sound_device_io_direction_e mm_sound_io_direction;
1196
1197         ret = mm_sound_get_device_io_direction(device, &mm_sound_io_direction);
1198         if (ret == MM_ERROR_NONE)
1199                 ret = _convert_device_io_direction(mm_sound_io_direction, io_direction);
1200
1201         return _convert_sound_manager_error_code(__func__, ret);
1202 }
1203
1204 int sound_manager_get_device_id(sound_device_h device, int *id)
1205 {
1206         int ret = MM_ERROR_NONE;
1207
1208         ret = mm_sound_get_device_id(device, id);
1209
1210         return _convert_sound_manager_error_code(__func__, ret);
1211 }
1212
1213 int sound_manager_get_device_name(sound_device_h device, char **name)
1214 {
1215         int ret = MM_ERROR_NONE;
1216
1217         ret = mm_sound_get_device_name(device, name);
1218
1219         return _convert_sound_manager_error_code(__func__, ret);
1220 }
1221
1222 int sound_manager_get_device_state(sound_device_h device, sound_device_state_e *state)
1223 {
1224         int ret = MM_ERROR_NONE;
1225
1226         ret = mm_sound_get_device_state(device, (mm_sound_device_state_e*)state);
1227
1228         return _convert_sound_manager_error_code(__func__, ret);
1229 }
1230
1231 int sound_manager_get_bt_device_avail_modes(sound_device_h device, int *modes)
1232 {
1233         int ret = MM_ERROR_NONE;
1234         int mm_avail_mode;
1235         int _avail_mode;
1236         sound_device_type_e device_type;
1237
1238         if (!device || !modes)
1239                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
1240
1241         ret = mm_sound_get_device_type(device, (mm_sound_device_type_e*)&device_type);
1242         if (ret != MM_ERROR_NONE)
1243                 goto LEAVE;
1244         if (device_type != SOUND_DEVICE_BLUETOOTH) {
1245                 ret = MM_ERROR_INVALID_ARGUMENT;
1246                 goto LEAVE;
1247         }
1248
1249         ret = mm_sound_get_device_bt_avail_mode(device, &mm_avail_mode);
1250         if (ret != MM_ERROR_NONE)
1251                 goto LEAVE;
1252
1253         if ((_avail_mode = _convert_avail_mode(mm_avail_mode)) < 0) {
1254                 LOGE("Invalid avail mode %d", mm_avail_mode);
1255                 ret = MM_ERROR_SOUND_INTERNAL;
1256                 goto LEAVE;
1257         }
1258
1259         *modes = _avail_mode;
1260
1261 LEAVE:
1262         return _convert_sound_manager_error_code(__func__, ret);
1263 }
1264
1265 int sound_manager_set_device_connected_cb(sound_device_mask_e device_mask, sound_device_connected_cb callback, void *user_data)
1266 {
1267         int ret = MM_ERROR_NONE;
1268         unsigned int subs_id = 0;
1269
1270         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_device_conn_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
1271
1272         ret = mm_sound_add_device_connected_callback((mm_sound_device_flags_e)device_mask, (mm_sound_device_connected_cb)callback, user_data, &subs_id);
1273         if (ret == MM_ERROR_NONE) {
1274                 g_device_connected_cb_table.subs_id = subs_id;
1275                 g_device_connected_cb_table.user_cb = (sound_device_connected_cb)callback;
1276                 g_device_connected_cb_table.user_data = user_data;
1277         }
1278
1279         SM_LEAVE_CRITICAL_SECTION(&g_device_conn_cb_mutex);
1280
1281         return _convert_sound_manager_error_code(__func__, ret);
1282 }
1283
1284 int sound_manager_unset_device_connected_cb(void)
1285 {
1286         int ret = MM_ERROR_NONE;
1287
1288         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_device_conn_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
1289
1290         if (g_device_connected_cb_table.subs_id == 0) {
1291                 ret = MM_ERROR_SOUND_INTERNAL;
1292                 goto LEAVE;
1293         }
1294
1295         ret = mm_sound_remove_device_connected_callback(g_device_connected_cb_table.subs_id);
1296         if (ret == MM_ERROR_NONE) {
1297                 g_device_connected_cb_table.subs_id = 0;
1298                 g_device_connected_cb_table.user_cb = NULL;
1299                 g_device_connected_cb_table.user_data = NULL;
1300         }
1301
1302 LEAVE:
1303         SM_LEAVE_CRITICAL_SECTION(&g_device_conn_cb_mutex);
1304
1305         return _convert_sound_manager_error_code(__func__, ret);
1306 }
1307
1308 int sound_manager_set_device_information_changed_cb(sound_device_mask_e device_mask, sound_device_information_changed_cb callback, void *user_data)
1309 {
1310         int ret = MM_ERROR_NONE;
1311         unsigned int subs_id = 0;
1312
1313         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_device_info_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
1314
1315         ret = mm_sound_add_device_information_changed_callback((mm_sound_device_flags_e)device_mask, (mm_sound_device_info_changed_cb)callback, user_data, &subs_id);
1316         if (ret == MM_ERROR_NONE) {
1317                 g_device_info_changed_cb_table.subs_id = subs_id;
1318                 g_device_info_changed_cb_table.user_cb = (sound_device_information_changed_cb)callback;
1319                 g_device_info_changed_cb_table.user_data = user_data;
1320         }
1321
1322         SM_LEAVE_CRITICAL_SECTION(&g_device_info_cb_mutex);
1323
1324         return _convert_sound_manager_error_code(__func__, ret);
1325 }
1326
1327 int sound_manager_unset_device_information_changed_cb(void)
1328 {
1329         int ret = MM_ERROR_NONE;
1330
1331         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_device_info_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
1332
1333         if (g_device_info_changed_cb_table.subs_id == 0) {
1334                 ret = MM_ERROR_SOUND_INTERNAL;
1335                 goto LEAVE;
1336         }
1337
1338         ret = mm_sound_remove_device_information_changed_callback(g_device_info_changed_cb_table.subs_id);
1339         if (ret == MM_ERROR_NONE) {
1340                 g_device_info_changed_cb_table.subs_id = 0;
1341                 g_device_info_changed_cb_table.user_cb = NULL;
1342                 g_device_info_changed_cb_table.user_data = NULL;
1343         }
1344
1345 LEAVE:
1346         SM_LEAVE_CRITICAL_SECTION(&g_device_info_cb_mutex);
1347
1348         return _convert_sound_manager_error_code(__func__, ret);
1349 }
1350
1351 __attribute__ ((destructor))
1352 void __sound_manager_finalize(void)
1353 {
1354         int ret = MM_ERROR_NONE;
1355
1356         if (g_session_interrupt_cb_table.is_registered) {
1357                 LOGI("<ENTER>");
1358                 ret = mm_session_finish();
1359                 if (ret != MM_ERROR_NONE)
1360                         LOGE("[%s] failed to mm_session_finish(), ret(0x%x)", __func__, ret);
1361
1362                 g_session_interrupt_cb_table.is_registered = 0;
1363                 LOGI("<LEAVE>");
1364         }
1365 }
1366
1367 __attribute__ ((constructor))
1368 void __sound_manager_initialize(void)
1369 {
1370
1371 }