Add new API to get avail-mode(media/voice) of Bluetooth devices
[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_focus_set_requesting_behavior(sound_stream_info_h stream_info, int flags)
403 {
404         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
405
406         LOGI(">> enter");
407
408         SM_INSTANCE_CHECK(stream_h);
409         SM_RANGE_ARG_CHECK(flags,
410                                 SOUND_BEHAVIOR_NONE,
411                                 (SOUND_BEHAVIOR_NO_RESUME|SOUND_BEHAVIOR_FADING));
412
413         stream_h->requesting_flags = flags;
414
415         LOGI("the requesting sound behavior(0x%x) is set", stream_h->requesting_flags);
416
417         return SOUND_MANAGER_ERROR_NONE;
418 }
419
420 int sound_manager_focus_get_requesting_behavior(sound_stream_info_h stream_info, int *flags)
421 {
422         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
423
424         LOGI(">> enter");
425
426         SM_INSTANCE_CHECK(stream_h);
427         SM_NULL_ARG_CHECK(flags);
428
429         *flags = stream_h->requesting_flags;
430
431         LOGI("the requesting sound behavior is (0x%x)", stream_h->requesting_flags);
432
433         return SOUND_MANAGER_ERROR_NONE;
434 }
435
436 int sound_manager_focus_get_requested_behavior(sound_stream_info_h stream_info, int *flags)
437 {
438         int ret = MM_ERROR_NONE;
439         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
440         bool is_focus_cb_thread = false;
441
442         LOGI(">> enter");
443
444         SM_INSTANCE_CHECK(stream_h);
445         SM_NULL_ARG_CHECK(flags);
446
447         if ((ret = mm_sound_focus_is_cb_thread(&is_focus_cb_thread)))
448                 _convert_sound_manager_error_code(__func__, ret);
449
450         if (!is_focus_cb_thread) {
451                 LOGE("this API should be called in focus state changed callback");
452                 return SOUND_MANAGER_ERROR_INVALID_OPERATION;
453         }
454
455         *flags = stream_h->requested_flags;
456
457         LOGI("requested sound behavior is (0x%x)", stream_h->requested_flags);
458
459         return SOUND_MANAGER_ERROR_NONE;
460 }
461
462 int sound_manager_get_current_playback_focus(sound_stream_focus_change_reason_e *acquired_by, int *flags, char **extra_info)
463 {
464         int ret = MM_ERROR_NONE;
465         char *stream_type_str = NULL;
466         char *extra_info_str = NULL;
467         int option = 0;
468         bool is_focus_cb_thread = false;
469
470         LOGI(">> enter");
471
472         SM_NULL_ARG_CHECK(acquired_by);
473         SM_NULL_ARG_CHECK(flags);
474
475         if ((ret = mm_sound_focus_is_cb_thread(&is_focus_cb_thread)))
476                 _convert_sound_manager_error_code(__func__, ret);
477
478         if (is_focus_cb_thread) {
479                 LOGE("this API should not be called in focus callback");
480                 return SOUND_MANAGER_ERROR_INVALID_OPERATION;
481         }
482
483         ret = mm_sound_get_stream_type_of_acquired_focus((int)SOUND_STREAM_FOCUS_FOR_PLAYBACK, &stream_type_str, &option, &extra_info_str);
484         if (ret == MM_ERROR_NONE) {
485                 LOGI("current acquired PLAYBACK focus : stream_type[%s]", stream_type_str);
486                 ret = _convert_stream_type_to_change_reason(stream_type_str, acquired_by);
487                 if (ret == MM_ERROR_NONE) {
488                         LOGI("                                : reason[%d], flags[0x%x], extra_info[%s]", *acquired_by, option, extra_info_str);
489                         *flags = option;
490                         if (extra_info)
491                                 *extra_info = extra_info_str;
492                         else
493                                 free(extra_info_str);
494                 }
495         }
496
497         return _convert_sound_manager_error_code(__func__, ret);
498 }
499
500 int sound_manager_get_current_recording_focus(sound_stream_focus_change_reason_e *acquired_by, int *flags, char **extra_info)
501 {
502         int ret = MM_ERROR_NONE;
503         char *stream_type_str = NULL;
504         char *extra_info_str = NULL;
505         int option = 0;
506         bool is_focus_cb_thread = false;
507
508         LOGI(">> enter");
509
510         SM_NULL_ARG_CHECK(acquired_by);
511         SM_NULL_ARG_CHECK(flags);
512
513         if ((ret = mm_sound_focus_is_cb_thread(&is_focus_cb_thread)))
514                 _convert_sound_manager_error_code(__func__, ret);
515
516         if (is_focus_cb_thread) {
517                 LOGE("this API should not be called in focus callback");
518                 return SOUND_MANAGER_ERROR_INVALID_OPERATION;
519         }
520
521         ret = mm_sound_get_stream_type_of_acquired_focus((int)SOUND_STREAM_FOCUS_FOR_RECORDING, &stream_type_str, &option, &extra_info_str);
522         if (ret == MM_ERROR_NONE) {
523                 LOGI("current acquired RECORDING focus : stream_type[%s]", stream_type_str);
524                 ret = _convert_stream_type_to_change_reason(stream_type_str, acquired_by);
525                 if (ret == MM_ERROR_NONE) {
526                         LOGI("                                 : reason[%d], flags[0x%x], extra_info[%s]", *acquired_by, option, extra_info_str);
527                         *flags = option;
528                         if (extra_info)
529                                 *extra_info = extra_info_str;
530                         else
531                                 free(extra_info_str);
532                 }
533         }
534
535         return _convert_sound_manager_error_code(__func__, ret);
536 }
537
538 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)
539 {
540         int ret = MM_ERROR_NONE;
541         int i = 0;
542
543         LOGI(">> enter");
544
545         SM_NULL_ARG_CHECK(callback);
546         SM_NULL_ARG_CHECK(id);
547         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_stream_info_count_mutex, SOUND_MANAGER_ERROR_INTERNAL);
548
549         for (i = 0; i < SOUND_STREAM_INFO_ARR_MAX; i++)
550                 if (focus_watch_info_arr[i].id == 0)
551                         break;
552         if (i == SOUND_STREAM_INFO_ARR_MAX) {
553                 LOGE("focus watch info array is full");
554                 ret = MM_ERROR_SOUND_INTERNAL;
555                 goto LEAVE;
556         }
557
558         ret = mm_sound_set_focus_watch_callback((mm_sound_focus_type_e)focus_mask, _focus_watch_callback, user_data, id);
559         if (ret == MM_ERROR_NONE) {
560                 SM_REF_FOR_STREAM_INFO(g_stream_info_count, ret);
561                 focus_watch_info_arr[i].id = *id;
562                 focus_watch_info_arr[i].user_data = user_data;
563                 focus_watch_info_arr[i].user_cb = callback;
564         }
565
566 LEAVE:
567         SM_LEAVE_CRITICAL_SECTION(&g_stream_info_count_mutex);
568
569         LOGD("cnt(%d), id(%d)", g_stream_info_count, *id);
570
571         return _convert_sound_manager_error_code(__func__, ret);
572 }
573
574 int sound_manager_remove_focus_state_watch_cb(int id)
575 {
576         int ret = MM_ERROR_NONE;
577         int i = 0;
578
579         LOGI(">> enter");
580
581         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_stream_info_count_mutex, SOUND_MANAGER_ERROR_INTERNAL);
582
583         for (i = 0; i < SOUND_STREAM_INFO_ARR_MAX; i++)
584                 if (focus_watch_info_arr[i].id == id)
585                         break;
586         if (i == SOUND_STREAM_INFO_ARR_MAX) {
587                 LOGE("cound not find item in focus watch info array for this id(%d)", id);
588                 ret = MM_ERROR_INVALID_ARGUMENT;
589                 goto LEAVE;
590         }
591
592         ret = mm_sound_unset_focus_watch_callback(id);
593         if (ret == MM_ERROR_NONE) {
594                 SM_UNREF_FOR_STREAM_INFO(g_stream_info_count);
595                 focus_watch_info_arr[i].id = 0;
596                 focus_watch_info_arr[i].user_data = NULL;
597                 focus_watch_info_arr[i].user_cb = NULL;
598         }
599
600 LEAVE:
601         SM_LEAVE_CRITICAL_SECTION(&g_stream_info_count_mutex);
602
603         LOGD("cnt(%d)", g_stream_info_count);
604
605         return _convert_sound_manager_error_code(__func__, ret);
606 }
607
608 int sound_manager_set_session_type(sound_session_type_e type)
609 {
610         int ret = MM_ERROR_NONE;
611         int cur_session = -1;
612         int new_session = MM_SESSION_TYPE_MEDIA;
613         bool mic_enable = false;
614
615         LOGW("DEPRECATION WARNING: %s() is deprecated and will be removed from next release. Use sound_manager_create_stream_information() instead.", __func__);
616         LOGI(">> enter : type=%d", type);
617
618         if (type < SOUND_SESSION_TYPE_MEDIA || type >  SOUND_SESSION_TYPE_VOIP)
619                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
620
621         /* If session type is VOIP but MIC is not enabled, return false */
622         if (type == SOUND_SESSION_TYPE_VOIP) {
623                 ret = system_info_get_platform_bool(FEATURE_MICROPHONE, &mic_enable);
624                 LOGI("system_info_platform [%s]=[%d], ret[%d]", FEATURE_MICROPHONE, mic_enable, ret);
625                 if (ret != SYSTEM_INFO_ERROR_NONE || !mic_enable)
626                         return _convert_sound_manager_error_code(__func__, MM_ERROR_NOT_SUPPORT_API);
627         }
628
629         /* it is not supported both session and stream feature at the same time */
630         if (g_stream_info_count) {
631                 LOGE("Could not set this type(%d) because of being used stream feature", type);
632                 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
633         }
634
635         switch (type) {
636         case SOUND_SESSION_TYPE_MEDIA:
637                 new_session = MM_SESSION_TYPE_MEDIA;
638                 break;
639         case SOUND_SESSION_TYPE_ALARM:
640                 new_session = MM_SESSION_TYPE_ALARM;
641                 break;
642         case SOUND_SESSION_TYPE_NOTIFICATION:
643                 new_session = MM_SESSION_TYPE_NOTIFY;
644                 break;
645         case SOUND_SESSION_TYPE_EMERGENCY:
646                 new_session = MM_SESSION_TYPE_EMERGENCY;
647                 break;
648         case SOUND_SESSION_TYPE_VOIP:
649                 new_session = MM_SESSION_TYPE_VOIP;
650                 break;
651         }
652
653         /* valid session check */
654         ret = mm_session_get_current_type(&cur_session);
655         if (ret == MM_ERROR_NONE) {
656                 if (cur_session == MM_SESSION_TYPE_MEDIA_RECORD) {
657                         if (type > SOUND_SESSION_TYPE_MEDIA) {
658                                 LOGE("Could not set this type(%d) during camera/recorder/audio-io(in)/radio", type);
659                                 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
660                         }
661                 }
662         }
663
664         if (g_session_interrupt_cb_table.is_registered) {
665                 if (new_session == cur_session ||
666                         ((new_session == SOUND_SESSION_TYPE_MEDIA) && (cur_session == MM_SESSION_TYPE_MEDIA_RECORD))) {
667                         LOGI("already set type=%d, ret=0x%x", type, ret);
668                         return SOUND_MANAGER_ERROR_NONE;
669                 } else {
670                         ret = mm_session_finish();
671                         if (ret != MM_ERROR_NONE)
672                                 return _convert_sound_manager_error_code(__func__, ret);
673
674                         g_session_interrupt_cb_table.is_registered = 0;
675                         if (cur_session == MM_SESSION_TYPE_VOIP) {
676                                 g_cached_session_mode = -1;
677                                 g_cached_voip_device_id = -1;
678                                 if (g_voip_vstream_h) {
679                                         _stop_virtual_stream(g_voip_vstream_h);
680                                         _destroy_virtual_stream(g_voip_vstream_h);
681                                         g_voip_vstream_h = NULL;
682                                 }
683                                 /*voip stream destruction*/
684                                 if (g_voip_stream_info) {
685                                         ret = _destroy_pa_connection_and_unregister_focus(g_voip_stream_info);
686                                         free(g_voip_stream_info);
687                                         g_voip_stream_info = NULL;
688                                         if (ret != MM_ERROR_NONE)
689                                                 return _convert_sound_manager_error_code(__func__, ret);
690                                 }
691                         }
692                 }
693         }
694         ret = mm_session_init(new_session);
695         if (ret == MM_ERROR_NONE)
696                 g_session_interrupt_cb_table.is_registered = 1;
697
698         LOGI("type=%d", type);
699
700         return _convert_sound_manager_error_code(__func__, ret);
701 }
702
703 int sound_manager_get_session_type(sound_session_type_e *type)
704 {
705         int ret = MM_ERROR_NONE;
706         int cur_session;
707
708         LOGW("DEPRECATION WARNING: %s() is deprecated and will be removed from next release.", __func__);
709         if (type == NULL)
710                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
711
712         ret = mm_session_get_current_type(&cur_session);
713         if (ret != MM_ERROR_NONE) {
714                 LOGW("session hasn't been set, setting default session");
715                 cur_session = SOUND_SESSION_TYPE_DEFAULT;
716                 ret = mm_session_init(cur_session);
717                 if (ret == MM_ERROR_NONE)
718                         g_session_interrupt_cb_table.is_registered = 1;
719         }
720         if ((cur_session > MM_SESSION_TYPE_EMERGENCY) &&
721                         (cur_session != MM_SESSION_TYPE_VOIP)) {
722                 if (g_cached_session != -1)
723                         cur_session = g_cached_session;
724                 else /* will be never reached here. just prevent code */
725                         cur_session = SOUND_SESSION_TYPE_DEFAULT;
726         }
727
728         switch (cur_session) {
729         case MM_SESSION_TYPE_MEDIA:
730         case MM_SESSION_TYPE_MEDIA_RECORD:
731                 *type = SOUND_SESSION_TYPE_MEDIA;
732                 break;
733         case MM_SESSION_TYPE_ALARM:
734                 *type = SOUND_SESSION_TYPE_ALARM;
735                 break;
736         case MM_SESSION_TYPE_NOTIFY:
737                 *type = SOUND_SESSION_TYPE_NOTIFICATION;
738                 break;
739         case MM_SESSION_TYPE_EMERGENCY:
740                 *type = SOUND_SESSION_TYPE_EMERGENCY;
741                 break;
742         case MM_SESSION_TYPE_VOIP:
743                 *type = SOUND_SESSION_TYPE_VOIP;
744                 break;
745         default:
746                 *type = cur_session;
747                 break;
748         }
749
750         LOGI("type=%d", *type);
751
752         return SOUND_MANAGER_ERROR_NONE;
753 }
754
755 int sound_manager_set_media_session_option(sound_session_option_for_starting_e s_option, sound_session_option_for_during_play_e d_option)
756 {
757         int ret = MM_ERROR_NONE;
758         int session = 0;
759         int session_option = 0;
760         int updated = 0;
761
762         LOGW("DEPRECATION WARNING: %s() is deprecated and will be removed from next release. Use sound_manager_create_stream_information() instead.", __func__);
763         LOGI(">> enter : option for starting=%d, for during play=%d", s_option, d_option);
764
765         if (s_option < 0 || s_option >  SOUND_SESSION_OPTION_PAUSE_OTHERS_WHEN_START)
766                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
767         if (d_option < 0 || d_option >  SOUND_SESSION_OPTION_UNINTERRUPTIBLE_DURING_PLAY)
768                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
769
770         ret = mm_session_get_current_information(&session, &session_option);
771         if (ret != 0 || !g_session_interrupt_cb_table.is_registered) {
772                 LOGW("session hasn't been set, setting default session");
773                 ret = mm_session_init(MM_SESSION_TYPE_MEDIA);
774                 if (ret == 0)
775                         g_session_interrupt_cb_table.is_registered = 1;
776
777         } else if (ret == 0 && session > MM_SESSION_TYPE_MEDIA) {
778                 if (session == MM_SESSION_TYPE_MEDIA_RECORD) {
779                         if (!g_session_interrupt_cb_table.is_registered) {
780                                 LOGE("Already set by camera/recorder/audio-io(in)/radio API, but need to set session to Media first");
781                                 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
782                         }
783                 } else {
784                         return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
785                 }
786         }
787
788         switch (s_option) {
789         case SOUND_SESSION_OPTION_MIX_WITH_OTHERS_WHEN_START:
790                 if (session_option & MM_SESSION_OPTION_PAUSE_OTHERS) {
791                         ret = mm_session_update_option(MM_SESSION_UPDATE_TYPE_REMOVE, MM_SESSION_OPTION_PAUSE_OTHERS);
792                         if (ret)
793                                 return _convert_sound_manager_error_code(__func__, ret);
794
795                         updated = 1;
796                 }
797                 break;
798         case SOUND_SESSION_OPTION_PAUSE_OTHERS_WHEN_START:
799                 if (!(session_option & MM_SESSION_OPTION_PAUSE_OTHERS)) {
800                         ret = mm_session_update_option(MM_SESSION_UPDATE_TYPE_ADD, MM_SESSION_OPTION_PAUSE_OTHERS);
801                         if (ret)
802                                 return _convert_sound_manager_error_code(__func__, ret);
803
804                         updated = 1;
805                 }
806                 break;
807         }
808
809         switch (d_option) {
810         case SOUND_SESSION_OPTION_INTERRUPTIBLE_DURING_PLAY:
811                 if (session_option & MM_SESSION_OPTION_UNINTERRUPTIBLE) {
812                         ret = mm_session_update_option(MM_SESSION_UPDATE_TYPE_REMOVE, MM_SESSION_OPTION_UNINTERRUPTIBLE);
813                         if (ret)
814                                 return _convert_sound_manager_error_code(__func__, ret);
815
816                         updated = 1;
817                 }
818                 break;
819         case SOUND_SESSION_OPTION_UNINTERRUPTIBLE_DURING_PLAY:
820                 if (!(session_option & MM_SESSION_OPTION_UNINTERRUPTIBLE)) {
821                         ret = mm_session_update_option(MM_SESSION_UPDATE_TYPE_ADD, MM_SESSION_OPTION_UNINTERRUPTIBLE);
822                         if (ret)
823                                 return _convert_sound_manager_error_code(__func__, ret);
824
825                         updated = 1;
826                 }
827                 break;
828         }
829
830         if (updated)
831                 LOGI("updated");
832         else
833                 LOGI("already set same option(%x), skip it", session_option);
834
835         return _convert_sound_manager_error_code(__func__, ret);
836 }
837
838 int sound_manager_get_media_session_option(sound_session_option_for_starting_e *s_option, sound_session_option_for_during_play_e *d_option)
839 {
840         int ret = MM_ERROR_NONE;
841         int session = 0;
842         int session_options = 0;
843
844         LOGW("DEPRECATION WARNING: %s() is deprecated and will be removed from next release. Use sound_manager_create_stream_information() instead.", __func__);
845         LOGI(">> enter");
846
847         if (s_option == NULL || d_option == NULL)
848                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
849
850         ret = mm_session_get_current_information(&session, &session_options);
851         if (ret != 0) {
852                 ret = mm_session_init(MM_SESSION_TYPE_MEDIA);
853                 if (ret == 0)
854                         g_session_interrupt_cb_table.is_registered = 1;
855
856         } else if (session > SOUND_SESSION_TYPE_MEDIA) {
857                 if (session == MM_SESSION_TYPE_MEDIA_RECORD) {
858                         if (!g_session_interrupt_cb_table.is_registered) {
859                                 LOGE("Already set by camera/recorder/audio-io(in)/radio API, but need to set session to Media first");
860                                 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
861                         }
862                 } else
863                         return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
864         }
865         /* get option */
866         if (session_options & MM_SESSION_OPTION_PAUSE_OTHERS)
867                 *s_option = SOUND_SESSION_OPTION_PAUSE_OTHERS_WHEN_START;
868         else
869                 *s_option = SOUND_SESSION_OPTION_MIX_WITH_OTHERS_WHEN_START;
870
871         if (session_options & MM_SESSION_OPTION_UNINTERRUPTIBLE)
872                 *d_option = SOUND_SESSION_OPTION_UNINTERRUPTIBLE_DURING_PLAY;
873         else
874                 *d_option = SOUND_SESSION_OPTION_INTERRUPTIBLE_DURING_PLAY;
875
876         LOGI(" option for starting=%d, for during play=%d", *s_option, *d_option);
877
878         return SOUND_MANAGER_ERROR_NONE;
879 }
880
881 int sound_manager_set_media_session_resumption_option(sound_session_option_for_resumption_e option)
882 {
883         int ret = MM_ERROR_NONE;
884         int session = 0;
885         int session_option = 0;
886         int updated = 0;
887
888         LOGW("DEPRECATION WARNING: %s() is deprecated and will be removed from next release. Use sound_manager_create_stream_information() instead.", __func__);
889         LOGI(">> enter : option for resumption=%d (0:by system, 1:by system or media paused)", option);
890
891         if (option < SOUND_SESSION_OPTION_RESUMPTION_BY_SYSTEM || option > SOUND_SESSION_OPTION_RESUMPTION_BY_SYSTEM_OR_MEDIA_PAUSED)
892                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
893
894         ret = mm_session_get_current_information(&session, &session_option);
895         if (ret != 0 || !g_session_interrupt_cb_table.is_registered) {
896                 LOGW("session hasn't been set, setting default session");
897                 ret = mm_session_init(MM_SESSION_TYPE_MEDIA);
898                 if (ret == 0)
899                         g_session_interrupt_cb_table.is_registered = 1;
900
901         } else if (ret == 0 && session > MM_SESSION_TYPE_MEDIA) {
902                 if (session == MM_SESSION_TYPE_MEDIA_RECORD) {
903                         if (!g_session_interrupt_cb_table.is_registered) {
904                                 LOGE("Already set by camera/recorder/audio-io(in)/radio API, but need to set session to Media first");
905                                 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
906                         }
907                 } else
908                         return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
909
910         }
911
912         switch (option) {
913         case SOUND_SESSION_OPTION_RESUMPTION_BY_SYSTEM:
914                 if (session_option & MM_SESSION_OPTION_RESUME_BY_SYSTEM_OR_MEDIA_PAUSED) {
915                         ret = mm_session_update_option(MM_SESSION_UPDATE_TYPE_REMOVE, MM_SESSION_OPTION_RESUME_BY_SYSTEM_OR_MEDIA_PAUSED);
916                         if (ret)
917                                 return _convert_sound_manager_error_code(__func__, ret);
918
919                         updated = 1;
920                 }
921                 break;
922         case SOUND_SESSION_OPTION_RESUMPTION_BY_SYSTEM_OR_MEDIA_PAUSED:
923                 if (!(session_option & MM_SESSION_OPTION_RESUME_BY_SYSTEM_OR_MEDIA_PAUSED)) {
924                         ret = mm_session_update_option(MM_SESSION_UPDATE_TYPE_ADD, MM_SESSION_OPTION_RESUME_BY_SYSTEM_OR_MEDIA_PAUSED);
925                         if (ret)
926                                 return _convert_sound_manager_error_code(__func__, ret);
927
928                         updated = 1;
929                 }
930                 break;
931         }
932
933         if (updated)
934                 LOGI("updated");
935         else
936                 LOGI("already set same option(0x%x), skip it", session_option);
937
938         return _convert_sound_manager_error_code(__func__, ret);
939 }
940
941 int sound_manager_get_media_session_resumption_option(sound_session_option_for_resumption_e *option)
942 {
943         int ret = MM_ERROR_NONE;
944         int session = 0;
945         int session_options = 0;
946
947         LOGW("DEPRECATION WARNING: %s() is deprecated and will be removed from next release. Use sound_manager_create_stream_information() instead.", __func__);
948         LOGI(">> enter");
949
950         if (option == NULL)
951                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
952
953         ret = mm_session_get_current_information(&session, &session_options);
954         if (ret != 0) {
955                 LOGW("session hasn't been set, setting default session");
956                 ret = mm_session_init(MM_SESSION_TYPE_MEDIA);
957                 if (ret == 0)
958                         g_session_interrupt_cb_table.is_registered = 1;
959
960         } else if (session > SOUND_SESSION_TYPE_MEDIA) {
961                 if (session == MM_SESSION_TYPE_MEDIA_RECORD) {
962                         if (!g_session_interrupt_cb_table.is_registered) {
963                                 LOGE("Already set by camera/recorder/audio-io(in)/radio API, but need to set session to Media first");
964                                 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
965                         }
966                 } else
967                         return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
968         }
969         /* get option */
970         if (session_options & MM_SESSION_OPTION_RESUME_BY_SYSTEM_OR_MEDIA_PAUSED)
971                 *option = SOUND_SESSION_OPTION_RESUMPTION_BY_SYSTEM_OR_MEDIA_PAUSED;
972         else
973                 *option = SOUND_SESSION_OPTION_RESUMPTION_BY_SYSTEM;
974
975         LOGI("option for resumption=%d (0:by system, 1:by system or media paused)", *option);
976
977         return SOUND_MANAGER_ERROR_NONE;
978 }
979
980 int sound_manager_set_voip_session_mode(sound_session_voip_mode_e mode)
981 {
982         int ret = MM_ERROR_NONE;
983         int session = 0;
984         int session_options = 0;
985
986         LOGW("DEPRECATION WARNING: %s() is deprecated and will be removed from next release. Use sound_manager_create_stream_information() instead.", __func__);
987         LOGI(">> enter : mode=%d", mode);
988
989         ret = mm_session_get_current_information(&session, &session_options);
990         if (ret != MM_ERROR_NONE)
991                 goto LEAVE;
992
993         if (session != MM_SESSION_TYPE_VOIP) {
994                 ret = MM_ERROR_POLICY_INTERNAL;
995                 goto LEAVE;
996         }
997
998         if (mode < SOUND_SESSION_VOIP_MODE_RINGTONE || mode > SOUND_SESSION_VOIP_MODE_VOICE_WITH_BLUETOOTH) {
999                 ret = MM_ERROR_INVALID_ARGUMENT;
1000                 goto LEAVE;
1001         }
1002
1003         ret = _set_session_mode((_session_mode_e)mode);
1004
1005         LOGI("session=%d, mode=%d", session, mode);
1006
1007 LEAVE:
1008         return _convert_sound_manager_error_code(__func__, ret);
1009 }
1010
1011 int sound_manager_get_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         if (mode == NULL) {
1019                 LOGE("mode is null");
1020                 ret = MM_ERROR_INVALID_ARGUMENT;
1021                 goto LEAVE;
1022         }
1023
1024         ret = mm_session_get_current_information(&session, &session_options);
1025         if (ret != MM_ERROR_NONE) {
1026                 LOGI("session = %d, option = %d", session, session_options);
1027                 goto LEAVE;
1028         }
1029
1030         if (session != MM_SESSION_TYPE_VOIP || g_cached_session_mode == -1) {
1031                 ret = MM_ERROR_POLICY_INTERNAL;
1032                 goto LEAVE;
1033         }
1034
1035         *mode = (sound_session_voip_mode_e)g_cached_session_mode;
1036
1037         LOGI("session=%d, mode=%d", session, *mode);
1038
1039 LEAVE:
1040         return _convert_sound_manager_error_code(__func__, ret);
1041 }
1042
1043 int sound_manager_set_session_interrupted_cb(sound_session_interrupted_cb callback, void *user_data)
1044 {
1045         int ret = MM_ERROR_NONE;
1046         unsigned int subs_id = 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         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_interrupt_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
1050
1051         if (callback == NULL) {
1052                 ret = MM_ERROR_INVALID_ARGUMENT;
1053                 goto LEAVE;
1054         }
1055
1056         /* it is not supported both session and stream feature at the same time */
1057         if (g_stream_info_count) {
1058                 ret =  MM_ERROR_POLICY_INTERNAL;
1059                 goto LEAVE;
1060         }
1061
1062         if (g_session_interrupt_cb_table.user_cb == NULL) {
1063                 ret = mm_sound_add_device_connected_callback(SOUND_DEVICE_ALL_MASK, (mm_sound_device_connected_cb)_device_connected_cb, NULL, &subs_id);
1064                 if (ret)
1065                         goto LEAVE;
1066                 ret = mm_sound_focus_set_session_interrupt_callback((mm_sound_focus_session_interrupt_cb)_focus_session_interrupt_cb, NULL);
1067                 if (ret) {
1068                         if (mm_sound_remove_device_connected_callback(subs_id) != MM_ERROR_NONE)
1069                                 LOGW("mm_sound_remove_device_connected_callback failed");
1070                         goto LEAVE;
1071                 }
1072                 g_session_interrupt_cb_table.subs_id = subs_id;
1073         }
1074         g_session_interrupt_cb_table.user_cb = (sound_session_interrupted_cb)callback;
1075         g_session_interrupt_cb_table.user_data = user_data;
1076
1077 LEAVE:
1078         SM_LEAVE_CRITICAL_SECTION(&g_interrupt_cb_mutex);
1079
1080         return _convert_sound_manager_error_code(__func__, ret);
1081 }
1082
1083 int sound_manager_unset_session_interrupted_cb(void)
1084 {
1085         int ret = MM_ERROR_NONE;
1086
1087         LOGW("DEPRECATION WARNING: %s() is deprecated and will be removed from next release.", __func__);
1088         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_interrupt_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
1089
1090         if (!g_session_interrupt_cb_table.user_cb) {
1091                 ret = MM_ERROR_SOUND_INTERNAL;
1092                 goto LEAVE;
1093         }
1094
1095         ret = mm_sound_focus_unset_session_interrupt_callback();
1096         if (ret) {
1097                 if (mm_sound_remove_device_connected_callback(g_session_interrupt_cb_table.subs_id) != MM_ERROR_NONE)
1098                         LOGW("mm_sound_remove_device_connected_callback failed");
1099                 goto LEAVE;
1100         }
1101
1102         ret = mm_sound_remove_device_connected_callback(g_session_interrupt_cb_table.subs_id);
1103         if (ret)
1104                 goto LEAVE;
1105
1106         g_session_interrupt_cb_table.subs_id = 0;
1107         g_session_interrupt_cb_table.user_cb = NULL;
1108         g_session_interrupt_cb_table.user_data = NULL;
1109
1110 LEAVE:
1111         SM_LEAVE_CRITICAL_SECTION(&g_interrupt_cb_mutex);
1112
1113         return _convert_sound_manager_error_code(__func__, ret);
1114 }
1115
1116 int sound_manager_get_current_device_list(sound_device_mask_e device_mask, sound_device_list_h *device_list)
1117 {
1118         int ret = MM_ERROR_NONE;
1119
1120         ret = mm_sound_get_current_device_list((mm_sound_device_flags_e)device_mask, device_list);
1121
1122         return _convert_sound_manager_error_code(__func__, ret);
1123 }
1124
1125 int sound_manager_free_device_list(sound_device_list_h device_list)
1126 {
1127         int ret = MM_ERROR_NONE;
1128
1129         ret = mm_sound_free_device_list(device_list);
1130
1131         return _convert_sound_manager_error_code(__func__, ret);
1132 }
1133
1134 int sound_manager_get_next_device(sound_device_list_h device_list, sound_device_h *device)
1135 {
1136         int ret = MM_ERROR_NONE;
1137
1138         ret = mm_sound_get_next_device(device_list, device);
1139
1140         return _convert_sound_manager_error_code(__func__, ret);
1141 }
1142
1143 int sound_manager_get_prev_device(sound_device_list_h device_list, sound_device_h *device)
1144 {
1145         int ret = MM_ERROR_NONE;
1146
1147         ret = mm_sound_get_prev_device(device_list, device);
1148
1149         return _convert_sound_manager_error_code(__func__, ret);
1150 }
1151
1152 int sound_manager_get_device_type(sound_device_h device, sound_device_type_e *type)
1153 {
1154         int ret = MM_ERROR_NONE;
1155
1156         ret = mm_sound_get_device_type(device, (mm_sound_device_type_e*)type);
1157
1158         return _convert_sound_manager_error_code(__func__, ret);
1159 }
1160
1161 int sound_manager_get_device_io_direction(sound_device_h device, sound_device_io_direction_e *io_direction)
1162 {
1163         int ret = MM_ERROR_NONE;
1164         mm_sound_device_io_direction_e mm_sound_io_direction;
1165
1166         ret = mm_sound_get_device_io_direction(device, &mm_sound_io_direction);
1167         if (ret == MM_ERROR_NONE)
1168                 ret = _convert_device_io_direction(mm_sound_io_direction, io_direction);
1169
1170         return _convert_sound_manager_error_code(__func__, ret);
1171 }
1172
1173 int sound_manager_get_device_id(sound_device_h device, int *id)
1174 {
1175         int ret = MM_ERROR_NONE;
1176
1177         ret = mm_sound_get_device_id(device, id);
1178
1179         return _convert_sound_manager_error_code(__func__, ret);
1180 }
1181
1182 int sound_manager_get_device_name(sound_device_h device, char **name)
1183 {
1184         int ret = MM_ERROR_NONE;
1185
1186         ret = mm_sound_get_device_name(device, name);
1187
1188         return _convert_sound_manager_error_code(__func__, ret);
1189 }
1190
1191 int sound_manager_get_device_state(sound_device_h device, sound_device_state_e *state)
1192 {
1193         int ret = MM_ERROR_NONE;
1194
1195         ret = mm_sound_get_device_state(device, (mm_sound_device_state_e*)state);
1196
1197         return _convert_sound_manager_error_code(__func__, ret);
1198 }
1199
1200 int sound_manager_get_bt_device_avail_modes(sound_device_h device, int *modes)
1201 {
1202         int ret = MM_ERROR_NONE;
1203         int mm_avail_mode;
1204         int _avail_mode;
1205         sound_device_type_e device_type;
1206
1207         if (!device || !modes)
1208                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
1209
1210         ret = mm_sound_get_device_type(device, (mm_sound_device_type_e*)&device_type);
1211         if (ret != MM_ERROR_NONE)
1212                 goto LEAVE;
1213         if (device_type != SOUND_DEVICE_BLUETOOTH) {
1214                 ret = MM_ERROR_INVALID_ARGUMENT;
1215                 goto LEAVE;
1216         }
1217
1218         ret = mm_sound_get_device_bt_avail_mode(device, &mm_avail_mode);
1219         if (ret != MM_ERROR_NONE)
1220                 goto LEAVE;
1221
1222         if ((_avail_mode = _convert_avail_mode(mm_avail_mode)) < 0) {
1223                 LOGE("Invalid avail mode %d", mm_avail_mode);
1224                 ret = MM_ERROR_SOUND_INTERNAL;
1225                 goto LEAVE;
1226         }
1227
1228         *modes = _avail_mode;
1229
1230 LEAVE:
1231         return _convert_sound_manager_error_code(__func__, ret);
1232 }
1233
1234 int sound_manager_set_device_connected_cb(sound_device_mask_e device_mask, sound_device_connected_cb callback, void *user_data)
1235 {
1236         int ret = MM_ERROR_NONE;
1237         unsigned int subs_id = 0;
1238
1239         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_device_conn_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
1240
1241         ret = mm_sound_add_device_connected_callback((mm_sound_device_flags_e)device_mask, (mm_sound_device_connected_cb)callback, user_data, &subs_id);
1242         if (ret == MM_ERROR_NONE) {
1243                 g_device_connected_cb_table.subs_id = subs_id;
1244                 g_device_connected_cb_table.user_cb = (sound_device_connected_cb)callback;
1245                 g_device_connected_cb_table.user_data = user_data;
1246         }
1247
1248         SM_LEAVE_CRITICAL_SECTION(&g_device_conn_cb_mutex);
1249
1250         return _convert_sound_manager_error_code(__func__, ret);
1251 }
1252
1253 int sound_manager_unset_device_connected_cb(void)
1254 {
1255         int ret = MM_ERROR_NONE;
1256
1257         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_device_conn_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
1258
1259         if (g_device_connected_cb_table.subs_id == 0) {
1260                 ret = MM_ERROR_SOUND_INTERNAL;
1261                 goto LEAVE;
1262         }
1263
1264         ret = mm_sound_remove_device_connected_callback(g_device_connected_cb_table.subs_id);
1265         if (ret == MM_ERROR_NONE) {
1266                 g_device_connected_cb_table.subs_id = 0;
1267                 g_device_connected_cb_table.user_cb = NULL;
1268                 g_device_connected_cb_table.user_data = NULL;
1269         }
1270
1271 LEAVE:
1272         SM_LEAVE_CRITICAL_SECTION(&g_device_conn_cb_mutex);
1273
1274         return _convert_sound_manager_error_code(__func__, ret);
1275 }
1276
1277 int sound_manager_set_device_information_changed_cb(sound_device_mask_e device_mask, sound_device_information_changed_cb callback, void *user_data)
1278 {
1279         int ret = MM_ERROR_NONE;
1280         unsigned int subs_id = 0;
1281
1282         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_device_info_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
1283
1284         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);
1285         if (ret == MM_ERROR_NONE) {
1286                 g_device_info_changed_cb_table.subs_id = subs_id;
1287                 g_device_info_changed_cb_table.user_cb = (sound_device_information_changed_cb)callback;
1288                 g_device_info_changed_cb_table.user_data = user_data;
1289         }
1290
1291         SM_LEAVE_CRITICAL_SECTION(&g_device_info_cb_mutex);
1292
1293         return _convert_sound_manager_error_code(__func__, ret);
1294 }
1295
1296 int sound_manager_unset_device_information_changed_cb(void)
1297 {
1298         int ret = MM_ERROR_NONE;
1299
1300         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_device_info_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
1301
1302         if (g_device_info_changed_cb_table.subs_id == 0) {
1303                 ret = MM_ERROR_SOUND_INTERNAL;
1304                 goto LEAVE;
1305         }
1306
1307         ret = mm_sound_remove_device_information_changed_callback(g_device_info_changed_cb_table.subs_id);
1308         if (ret == MM_ERROR_NONE) {
1309                 g_device_info_changed_cb_table.subs_id = 0;
1310                 g_device_info_changed_cb_table.user_cb = NULL;
1311                 g_device_info_changed_cb_table.user_data = NULL;
1312         }
1313
1314 LEAVE:
1315         SM_LEAVE_CRITICAL_SECTION(&g_device_info_cb_mutex);
1316
1317         return _convert_sound_manager_error_code(__func__, ret);
1318 }
1319
1320 __attribute__ ((destructor))
1321 void __sound_manager_finalize(void)
1322 {
1323         int ret = MM_ERROR_NONE;
1324
1325         if (g_session_interrupt_cb_table.is_registered) {
1326                 LOGI("<ENTER>");
1327                 ret = mm_session_finish();
1328                 if (ret != MM_ERROR_NONE)
1329                         LOGE("[%s] failed to mm_session_finish(), ret(0x%x)", __func__, ret);
1330
1331                 g_session_interrupt_cb_table.is_registered = 0;
1332                 LOGI("<LEAVE>");
1333         }
1334 }
1335
1336 __attribute__ ((constructor))
1337 void __sound_manager_initialize(void)
1338 {
1339
1340 }