Fix to release internal focus of voip session when getting back to another session...
[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 int g_cached_voip_device_id2 = -1;
33 extern sound_stream_info_s *g_voip_stream_info;
34 extern sound_stream_info_s *g_voip_ringtone_stream_info;
35 extern virtual_sound_stream_info_s *g_voip_vstream_h;
36 extern virtual_sound_stream_info_s *g_voip_ringtone_vstream_h;
37
38 /* These variables will be removed when session features are deprecated. */
39 extern int g_stream_info_count;
40 extern pthread_mutex_t g_stream_info_count_mutex;
41 pthread_mutex_t g_session_mutex;
42 pthread_mutex_t g_interrupt_cb_mutex, g_device_info_cb_mutex, g_device_conn_cb_mutex, g_volume_cb_mutex;
43
44 int sound_manager_get_max_volume(sound_type_e type, int *max)
45 {
46         const char *volume_type = NULL;
47         unsigned int max_level = 0;
48         int ret = MM_ERROR_NONE;
49
50         SM_NULL_ARG_CHECK(max);
51         if (type >= SOUND_TYPE_NUM || type < 0)
52                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
53
54         ret = _convert_sound_type(type, &volume_type);
55         if (ret == MM_ERROR_NONE) {
56                 ret = _get_volume_max_level(DIRECTION_OUT_STR, volume_type, &max_level);
57                 if (ret == MM_ERROR_NONE)
58                         *max = (int)max_level -1;       /* actual volume step can be max step - 1 */
59         }
60
61         return _convert_sound_manager_error_code(__func__, ret);
62 }
63
64 int sound_manager_set_volume(sound_type_e type, int volume)
65 {
66         int ret = MM_ERROR_NONE;
67
68         if (type >= SOUND_TYPE_NUM || type < 0)
69                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
70         if (volume < 0)
71                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
72
73         ret = mm_sound_volume_set_value(type, volume);
74         LOGI("type=%d, volume=%d", type, volume);
75
76         return _convert_sound_manager_error_code(__func__, ret);
77 }
78
79 int sound_manager_get_volume(sound_type_e type, int *volume)
80 {
81         int ret = MM_ERROR_NONE;
82         unsigned int uvolume;
83
84         if (type >= SOUND_TYPE_NUM || type < 0)
85                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
86         if (volume == NULL)
87                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
88
89         ret = mm_sound_volume_get_value(type, &uvolume);
90         if (ret == MM_ERROR_NONE)
91                 *volume = uvolume;
92
93         LOGI("type=%d, volume=%d", type, *volume);
94
95         return _convert_sound_manager_error_code(__func__, ret);
96 }
97
98 int sound_manager_set_current_sound_type(sound_type_e type)
99 {
100         int ret = MM_ERROR_NONE;
101
102         LOGW("DEPRECATION WARNING: %s() is deprecated and will be removed from next release.", __func__);
103         if (type >= SOUND_TYPE_NUM || type < 0)
104                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
105
106         ret = mm_sound_volume_primary_type_set(type);
107
108         return _convert_sound_manager_error_code(__func__, ret);
109 }
110
111 int sound_manager_get_current_sound_type(sound_type_e *type)
112 {
113         int ret = MM_ERROR_NONE;
114         volume_type_t mm_sound_vol_type = VOLUME_TYPE_UNKNOWN;
115         char *volume_type = NULL;
116
117         if (type == NULL)
118                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
119
120         ret  = mm_sound_volume_primary_type_get(&mm_sound_vol_type);
121         if (ret == MM_ERROR_NONE) {
122                 if (mm_sound_vol_type == VOLUME_TYPE_UNKNOWN) {
123                         /* get the volume type of the current playing stream */
124                         ret = _get_current_volume_type(DIRECTION_OUT_STR, &volume_type);
125                         if (ret == MM_ERROR_NONE)
126                                 ret = _convert_sound_type_to_enum((const char*)volume_type, type);
127                 } else {
128                         *type = mm_sound_vol_type;
129                 }
130         }
131         LOGI("type=%d", *type);
132
133         return _convert_sound_manager_error_code(__func__, ret);
134 }
135
136 int sound_manager_unset_current_sound_type(void)
137 {
138         int ret = MM_ERROR_NONE;
139
140         LOGW("DEPRECATION WARNING: %s() is deprecated and will be removed from next release.", __func__);
141         ret = mm_sound_volume_primary_type_set(VOLUME_TYPE_UNKNOWN);
142
143         return _convert_sound_manager_error_code(__func__, ret);
144 }
145
146 int sound_manager_set_volume_changed_cb(sound_manager_volume_changed_cb callback, void* user_data)
147 {
148         int ret = MM_ERROR_NONE;
149         unsigned int subs_id = 0;
150
151         LOGW("DEPRECATION WARNING: %s() is deprecated and will be removed from next release. "
152                 "Use sound_manager_add_volume_changed_cb() instead.", __func__);
153
154         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_volume_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
155
156         ret = mm_sound_add_volume_changed_callback((mm_sound_volume_changed_cb)callback, user_data, &subs_id);
157         if (ret == MM_ERROR_NONE) {
158                 g_volume_changed_cb_table.subs_id = subs_id;
159                 g_volume_changed_cb_table.user_cb = (sound_manager_volume_changed_cb)callback;
160                 g_volume_changed_cb_table.user_data = user_data;
161         }
162
163         SM_LEAVE_CRITICAL_SECTION(&g_volume_cb_mutex);
164
165         return _convert_sound_manager_error_code(__func__, ret);
166 }
167
168 int sound_manager_unset_volume_changed_cb(void)
169 {
170         int ret = MM_ERROR_NONE;
171
172         LOGW("DEPRECATION WARNING: %s() is deprecated and will be removed from next release. "
173                 "Use sound_manager_remove_volume_changed_cb() instead.", __func__);
174
175         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_volume_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
176
177         if (g_volume_changed_cb_table.subs_id > 0) {
178                 ret = mm_sound_remove_volume_changed_callback(g_volume_changed_cb_table.subs_id);
179                 if (ret == MM_ERROR_NONE) {
180                         g_volume_changed_cb_table.subs_id = 0;
181                         g_volume_changed_cb_table.user_cb = NULL;
182                         g_volume_changed_cb_table.user_data = NULL;
183                 }
184         } else {
185                 ret = MM_ERROR_SOUND_INTERNAL;
186         }
187
188         SM_LEAVE_CRITICAL_SECTION(&g_volume_cb_mutex);
189
190         return _convert_sound_manager_error_code(__func__, ret);
191 }
192
193 int sound_manager_add_volume_changed_cb(sound_manager_volume_changed_cb callback, void *user_data, int *id)
194 {
195         int ret = MM_ERROR_NONE;
196
197         if (!callback || !id)
198                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
199
200         ret = mm_sound_add_volume_changed_callback((mm_sound_volume_changed_cb)callback, user_data, (unsigned int*)id);
201
202         return _convert_sound_manager_error_code(__func__, ret);
203 }
204
205 int sound_manager_remove_volume_changed_cb(int id)
206 {
207         int ret = MM_ERROR_NONE;
208
209         if (id < 0)
210                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
211
212         ret = mm_sound_remove_volume_changed_callback(id);
213
214         return _convert_sound_manager_error_code(__func__, ret);
215 }
216
217 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)
218 {
219         int ret = MM_ERROR_NONE;
220
221         LOGI(">> enter");
222
223         SM_NULL_ARG_CHECK(stream_info);
224
225         if (g_session_interrupt_cb_table.is_registered)
226                 return _convert_sound_manager_error_code(__func__, MM_ERROR_SOUND_INTERNAL);
227
228         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_stream_info_count_mutex, MM_ERROR_SOUND_INTERNAL);
229
230         sound_stream_info_s *stream_h = malloc(sizeof(sound_stream_info_s));
231         if (!stream_h) {
232                 ret = MM_ERROR_OUT_OF_MEMORY;
233                 goto LEAVE;
234         }
235
236         memset(stream_h, 0, sizeof(sound_stream_info_s));
237         ret = _convert_stream_type(stream_type, &stream_h->stream_type);
238         if (ret == MM_ERROR_NONE) {
239                 ret = _make_pa_connection_and_register_focus(stream_h, false, callback, user_data);
240                 if (ret == MM_ERROR_NONE) {
241                         *stream_info = (sound_stream_info_h)stream_h;
242                         SM_REF_FOR_STREAM_INFO(g_stream_info_count, ret);
243                         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);
244                 }
245         }
246
247 LEAVE:
248         if (ret)
249                 SM_SAFE_FREE(stream_h);
250
251         SM_LEAVE_CRITICAL_SECTION(&g_stream_info_count_mutex);
252
253         return _convert_sound_manager_error_code(__func__, ret);
254 }
255
256 int sound_manager_destroy_stream_information(sound_stream_info_h stream_info)
257 {
258         int ret = MM_ERROR_NONE;
259         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
260
261         LOGI(">> enter");
262
263         SM_INSTANCE_CHECK(stream_h);
264
265         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_stream_info_count_mutex, MM_ERROR_SOUND_INTERNAL);
266         ret = _destroy_pa_connection_and_unregister_focus(stream_h);
267         if (ret == MM_ERROR_NONE) {
268                 SM_SAFE_FREE(stream_h);
269                 SM_UNREF_FOR_STREAM_INFO(g_stream_info_count);
270         }
271         SM_LEAVE_CRITICAL_SECTION(&g_stream_info_count_mutex);
272
273         LOGD("cnt(%d)", g_stream_info_count);
274
275         return _convert_sound_manager_error_code(__func__, ret);
276 }
277
278 int sound_manager_get_sound_type(sound_stream_info_h stream_info, sound_type_e *sound_type)
279 {
280         int ret = MM_ERROR_NONE;
281         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
282
283         LOGI(">> enter");
284
285         SM_INSTANCE_CHECK(stream_h);
286         SM_NULL_ARG_CHECK(sound_type);
287
288         if (stream_h->stream_conf_info.volume_type == NULL) {
289                 ret = MM_ERROR_SOUND_NO_DATA;
290                 goto LEAVE;
291         }
292
293         ret = _convert_sound_type_to_enum(stream_h->stream_conf_info.volume_type, sound_type);
294         LOGI("sound type(%d)", *sound_type);
295
296 LEAVE:
297         return _convert_sound_manager_error_code(__func__, ret);
298 }
299
300 int sound_manager_add_device_for_stream_routing(sound_stream_info_h stream_info, sound_device_h device)
301 {
302         int ret = MM_ERROR_NONE;
303         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
304
305         LOGI(">> enter");
306
307         ret = _add_device_for_stream_routing(stream_h, device);
308
309         return _convert_sound_manager_error_code(__func__, ret);
310 }
311
312 int sound_manager_remove_device_for_stream_routing(sound_stream_info_h stream_info, sound_device_h device)
313 {
314         int ret = MM_ERROR_NONE;
315         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
316
317         LOGI(">> enter");
318
319         ret = _remove_device_for_stream_routing(stream_h, device);
320
321         return _convert_sound_manager_error_code(__func__, ret);
322 }
323
324 int sound_manager_apply_stream_routing(sound_stream_info_h stream_info)
325 {
326         int ret = MM_ERROR_NONE;
327         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
328
329         LOGI(">> enter");
330
331         ret = _apply_stream_routing(stream_h);
332
333         return _convert_sound_manager_error_code(__func__, ret);
334 }
335
336 int sound_manager_set_focus_reacquisition(sound_stream_info_h stream_info, bool enable)
337 {
338         int ret = MM_ERROR_NONE;
339         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
340
341         LOGI(">> enter");
342
343         SM_INSTANCE_CHECK(stream_h);
344
345         ret = mm_sound_set_focus_reacquisition(stream_h->index, enable);
346
347         LOGI("enable(%d)", enable);
348
349         return _convert_sound_manager_error_code(__func__, ret);
350 }
351
352 int sound_manager_get_focus_reacquisition(sound_stream_info_h stream_info, bool *enabled)
353 {
354         int ret = MM_ERROR_NONE;
355         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
356
357         LOGI(">> enter");
358
359         SM_INSTANCE_CHECK(stream_h);
360         SM_NULL_ARG_CHECK(enabled);
361
362         ret = mm_sound_get_focus_reacquisition(stream_h->index, enabled);
363
364         LOGI("enabled(%d)", *enabled);
365
366         return _convert_sound_manager_error_code(__func__, ret);
367 }
368
369 int sound_manager_acquire_focus(sound_stream_info_h stream_info, sound_stream_focus_mask_e focus_mask, int sound_behavior, const char *extra_info)
370 {
371         int ret = MM_ERROR_NONE;
372         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
373
374         LOGI(">> enter");
375
376         SM_INSTANCE_CHECK(stream_h);
377
378         if (stream_h->is_focus_unavailable) {
379                 LOGE("acquiring focus is not allowed for this strema type(%s)", stream_h->stream_type);
380                 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
381         }
382
383         if (stream_h->user_cb == NULL) {
384                 LOGE("focus state changed callback should be set before acquiring focus");
385                 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
386         }
387
388         ret = mm_sound_acquire_focus_with_option(stream_h->index, (mm_sound_focus_type_e)focus_mask, sound_behavior, extra_info);
389         if (ret == MM_ERROR_NONE) {
390                 stream_h->acquired_focus |= focus_mask;
391                 _update_focus_status(stream_h->index, (unsigned int)stream_h->acquired_focus);
392         }
393
394         return _convert_sound_manager_error_code(__func__, ret);
395 }
396
397 int sound_manager_release_focus(sound_stream_info_h stream_info, sound_stream_focus_mask_e focus_mask, int sound_behavior, const char *extra_info)
398 {
399         int ret = MM_ERROR_NONE;
400         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
401
402         LOGI(">> enter");
403
404         SM_INSTANCE_CHECK(stream_h);
405
406         ret = mm_sound_release_focus_with_option(stream_h->index, (mm_sound_focus_type_e)focus_mask, sound_behavior, extra_info);
407         if (ret == MM_ERROR_NONE) {
408                 stream_h->acquired_focus &= ~focus_mask;
409                 _update_focus_status(stream_h->index, (unsigned int)stream_h->acquired_focus);
410         }
411
412         return _convert_sound_manager_error_code(__func__, ret);
413 }
414
415 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)
416 {
417         int ret = MM_ERROR_NONE;
418         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
419
420         LOGI(">> enter");
421
422         SM_INSTANCE_CHECK(stream_h);
423         if (!state_for_playback && !state_for_recording) {
424                 ret = MM_ERROR_INVALID_ARGUMENT;
425                 goto LEAVE;
426         }
427
428         if (state_for_playback)
429                 *state_for_playback = ((stream_h->acquired_focus & SOUND_STREAM_FOCUS_FOR_PLAYBACK) ? (SOUND_STREAM_FOCUS_STATE_ACQUIRED) : (SOUND_STREAM_FOCUS_STATE_RELEASED));
430         if (state_for_recording)
431                 *state_for_recording = ((stream_h->acquired_focus & SOUND_STREAM_FOCUS_FOR_RECORDING) ? (SOUND_STREAM_FOCUS_STATE_ACQUIRED) : (SOUND_STREAM_FOCUS_STATE_RELEASED));
432
433         LOGI("acquired_focus(0x%x)", stream_h->acquired_focus);
434
435 LEAVE:
436         return _convert_sound_manager_error_code(__func__, ret);
437 }
438
439 int sound_manager_is_stream_on_device(sound_stream_info_h stream_info, sound_device_h device, bool *is_on)
440 {
441         int ret = MM_ERROR_NONE;
442         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
443
444         LOGI(">> enter");
445
446         SM_NULL_ARG_CHECK(stream_h);
447         SM_NULL_ARG_CHECK(device);
448         SM_NULL_ARG_CHECK(is_on);
449
450         ret = mm_sound_is_stream_on_device(stream_h->index, device, is_on);
451
452         return _convert_sound_manager_error_code(__func__, ret);
453 }
454
455 int sound_manager_get_current_media_playback_device_type(sound_device_type_e *device_type)
456 {
457         int ret = MM_ERROR_NONE;
458
459         LOGI(">> enter");
460
461         SM_NULL_ARG_CHECK(device_type);
462
463         ret = _get_current_media_routing_path("out", device_type);
464
465         return _convert_sound_manager_error_code(__func__, ret);
466 }
467
468 int sound_manager_get_current_playback_focus(sound_stream_focus_change_reason_e *acquired_by, int *flags, char **extra_info)
469 {
470         int ret = MM_ERROR_NONE;
471         char *stream_type_str = NULL;
472         char *extra_info_str = NULL;
473         int option = 0;
474         bool is_focus_cb_thread = false;
475
476         LOGI(">> enter");
477
478         SM_NULL_ARG_CHECK(acquired_by);
479         SM_NULL_ARG_CHECK(flags);
480
481         if ((ret = mm_sound_focus_is_cb_thread(&is_focus_cb_thread)))
482                 return _convert_sound_manager_error_code(__func__, ret);
483
484         if (is_focus_cb_thread) {
485                 LOGE("this API should not be called in focus callback");
486                 return SOUND_MANAGER_ERROR_INVALID_OPERATION;
487         }
488
489         ret = mm_sound_get_stream_type_of_acquired_focus((int)SOUND_STREAM_FOCUS_FOR_PLAYBACK, &stream_type_str, &option, &extra_info_str);
490         if (ret == MM_ERROR_NONE) {
491                 LOGI("current acquired PLAYBACK focus : stream_type[%s]", stream_type_str);
492                 ret = _convert_stream_type_to_change_reason(stream_type_str, acquired_by);
493                 if (ret == MM_ERROR_NONE) {
494                         LOGI("                                : reason[%d], flags[0x%x], extra_info[%s]", *acquired_by, option, extra_info_str);
495                         *flags = option;
496                         if (extra_info)
497                                 *extra_info = extra_info_str;
498                         else
499                                 SM_SAFE_FREE(extra_info_str);
500                 }
501         }
502
503         return _convert_sound_manager_error_code(__func__, ret);
504 }
505
506 int sound_manager_get_current_recording_focus(sound_stream_focus_change_reason_e *acquired_by, int *flags, char **extra_info)
507 {
508         int ret = MM_ERROR_NONE;
509         char *stream_type_str = NULL;
510         char *extra_info_str = NULL;
511         int option = 0;
512         bool is_focus_cb_thread = false;
513
514         LOGI(">> enter");
515
516         SM_NULL_ARG_CHECK(acquired_by);
517         SM_NULL_ARG_CHECK(flags);
518
519         if ((ret = mm_sound_focus_is_cb_thread(&is_focus_cb_thread)))
520                 return _convert_sound_manager_error_code(__func__, ret);
521
522         if (is_focus_cb_thread) {
523                 LOGE("this API should not be called in focus callback");
524                 return SOUND_MANAGER_ERROR_INVALID_OPERATION;
525         }
526
527         ret = mm_sound_get_stream_type_of_acquired_focus((int)SOUND_STREAM_FOCUS_FOR_RECORDING, &stream_type_str, &option, &extra_info_str);
528         if (ret == MM_ERROR_NONE) {
529                 LOGI("current acquired RECORDING focus : stream_type[%s]", stream_type_str);
530                 ret = _convert_stream_type_to_change_reason(stream_type_str, acquired_by);
531                 if (ret == MM_ERROR_NONE) {
532                         LOGI("                                 : reason[%d], flags[0x%x], extra_info[%s]", *acquired_by, option, extra_info_str);
533                         *flags = option;
534                         if (extra_info)
535                                 *extra_info = extra_info_str;
536                         else
537                                 SM_SAFE_FREE(extra_info_str);
538                 }
539         }
540
541         return _convert_sound_manager_error_code(__func__, ret);
542 }
543
544 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)
545 {
546         int ret = MM_ERROR_NONE;
547         int i = 0;
548
549         LOGI(">> enter");
550
551         SM_NULL_ARG_CHECK(callback);
552         SM_NULL_ARG_CHECK(id);
553         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_stream_info_count_mutex, SOUND_MANAGER_ERROR_INTERNAL);
554
555         for (i = 0; i < SOUND_STREAM_INFO_ARR_MAX; i++)
556                 if (focus_watch_info_arr[i].id == 0)
557                         break;
558         if (i == SOUND_STREAM_INFO_ARR_MAX) {
559                 LOGE("focus watch info array is full");
560                 ret = MM_ERROR_SOUND_INTERNAL;
561                 goto LEAVE;
562         }
563
564         ret = mm_sound_set_focus_watch_callback((mm_sound_focus_type_e)focus_mask, _focus_watch_callback, &focus_watch_info_arr[i], id);
565         if (ret == MM_ERROR_NONE) {
566                 SM_REF_FOR_STREAM_INFO(g_stream_info_count, ret);
567                 focus_watch_info_arr[i].id = *id;
568                 focus_watch_info_arr[i].user_data = user_data;
569                 focus_watch_info_arr[i].user_cb = callback;
570         }
571
572 LEAVE:
573         SM_LEAVE_CRITICAL_SECTION(&g_stream_info_count_mutex);
574
575         LOGD("cnt(%d), id(%d)", g_stream_info_count, *id);
576
577         return _convert_sound_manager_error_code(__func__, ret);
578 }
579
580 int sound_manager_remove_focus_state_watch_cb(int id)
581 {
582         int ret = MM_ERROR_NONE;
583         int i = 0;
584
585         LOGI(">> enter");
586
587         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_stream_info_count_mutex, SOUND_MANAGER_ERROR_INTERNAL);
588
589         for (i = 0; i < SOUND_STREAM_INFO_ARR_MAX; i++)
590                 if (focus_watch_info_arr[i].id == id)
591                         break;
592         if (i == SOUND_STREAM_INFO_ARR_MAX) {
593                 LOGE("cound not find item in focus watch info array for this id(%d)", id);
594                 ret = MM_ERROR_INVALID_ARGUMENT;
595                 goto LEAVE;
596         }
597
598         ret = mm_sound_unset_focus_watch_callback(id);
599         if (ret == MM_ERROR_NONE) {
600                 SM_UNREF_FOR_STREAM_INFO(g_stream_info_count);
601                 focus_watch_info_arr[i].id = 0;
602                 focus_watch_info_arr[i].user_data = NULL;
603                 focus_watch_info_arr[i].user_cb = NULL;
604         }
605
606 LEAVE:
607         SM_LEAVE_CRITICAL_SECTION(&g_stream_info_count_mutex);
608
609         LOGD("cnt(%d)", g_stream_info_count);
610
611         return _convert_sound_manager_error_code(__func__, ret);
612 }
613
614 int sound_manager_set_session_type(sound_session_type_e type)
615 {
616         int ret = MM_ERROR_NONE;
617         int cur_session = -1;
618         int new_session = MM_SESSION_TYPE_MEDIA;
619         bool mic_enable = false;
620
621         LOGW("DEPRECATION WARNING: %s() is deprecated and will be removed from next release. Use sound_manager_create_stream_information() instead.", __func__);
622         LOGI(">> enter : type=%d", type);
623
624         if (type < SOUND_SESSION_TYPE_MEDIA || type >  SOUND_SESSION_TYPE_VOIP)
625                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
626
627         /* If session type is VOIP but MIC is not enabled, return false */
628         if (type == SOUND_SESSION_TYPE_VOIP) {
629                 ret = system_info_get_platform_bool(FEATURE_MICROPHONE, &mic_enable);
630                 LOGI("system_info_platform [%s]=[%d], ret[%d]", FEATURE_MICROPHONE, mic_enable, ret);
631                 if (ret != SYSTEM_INFO_ERROR_NONE || !mic_enable)
632                         return _convert_sound_manager_error_code(__func__, MM_ERROR_NOT_SUPPORT_API);
633         }
634
635         /* it is not supported both session and stream feature at the same time */
636         if (g_stream_info_count) {
637                 LOGE("Could not set this type(%d) because of being used stream feature", type);
638                 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
639         }
640
641         switch (type) {
642         case SOUND_SESSION_TYPE_MEDIA:
643                 new_session = MM_SESSION_TYPE_MEDIA;
644                 break;
645         case SOUND_SESSION_TYPE_ALARM:
646                 new_session = MM_SESSION_TYPE_ALARM;
647                 break;
648         case SOUND_SESSION_TYPE_NOTIFICATION:
649                 new_session = MM_SESSION_TYPE_NOTIFY;
650                 break;
651         case SOUND_SESSION_TYPE_EMERGENCY:
652                 new_session = MM_SESSION_TYPE_EMERGENCY;
653                 break;
654         case SOUND_SESSION_TYPE_VOIP:
655                 new_session = MM_SESSION_TYPE_VOIP;
656                 break;
657         }
658
659         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_session_mutex, SOUND_MANAGER_ERROR_INTERNAL);
660
661         /* valid session check */
662         ret = mm_session_get_current_type(&cur_session);
663         if (ret == MM_ERROR_NONE) {
664                 if (cur_session == MM_SESSION_TYPE_MEDIA_RECORD) {
665                         if (type > SOUND_SESSION_TYPE_MEDIA) {
666                                 LOGE("Could not set this type(%d) during camera/recorder/audio-io(in)/radio", type);
667                                 ret = MM_ERROR_POLICY_INTERNAL;
668                                 goto LEAVE;
669                         }
670                 }
671         }
672
673         if (g_session_interrupt_cb_table.is_registered) {
674                 if (new_session == cur_session ||
675                         ((new_session == SOUND_SESSION_TYPE_MEDIA) && (cur_session == MM_SESSION_TYPE_MEDIA_RECORD))) {
676                         LOGI("already set type=%d, ret=0x%x", type, ret);
677                         goto LEAVE;
678                 }
679
680                 ret = mm_session_finish();
681                 if (ret != MM_ERROR_NONE)
682                         goto LEAVE;
683
684                 g_session_interrupt_cb_table.is_registered = 0;
685                 if (cur_session == MM_SESSION_TYPE_VOIP) {
686                         /* De-initialize regarding VoIP session */
687                         g_cached_session_mode = -1;
688                         g_cached_voip_device_id = -1;
689                         g_cached_voip_device_id2 = -1;
690                         if (g_voip_vstream_h) {
691                                 _stop_progress_virtual_stream(g_voip_vstream_h);
692                                 g_voip_vstream_h = NULL;
693                         }
694                         if (g_voip_ringtone_vstream_h) {
695                                 _stop_progress_virtual_stream(g_voip_ringtone_vstream_h);
696                                 g_voip_ringtone_vstream_h = NULL;
697                         }
698                         if (g_voip_ringtone_stream_info) {
699                                 if ((ret = mm_sound_release_focus(g_voip_ringtone_stream_info->index, g_voip_ringtone_stream_info->acquired_focus, EXT_INFO_VOIP_SESSION)))
700                                         LOGE("failed to release focus for ringtone-voip stream info, ret(0x%x)", ret);
701                         } else if (g_voip_stream_info) {
702                                 if ((ret = mm_sound_release_focus(g_voip_stream_info->index, g_voip_stream_info->acquired_focus, EXT_INFO_VOIP_SESSION)))
703                                         LOGE("failed to release focus for voip stream info, ret(0x%x)", ret);
704                         }
705                         if (g_voip_stream_info) {
706                                 ret = _destroy_pa_connection_and_unregister_focus(g_voip_stream_info);
707                                 SM_SAFE_FREE(g_voip_stream_info);
708                                 if (ret != MM_ERROR_NONE)
709                                         goto LEAVE;
710                         }
711                         if (g_voip_ringtone_stream_info) {
712                                 ret = _destroy_pa_connection_and_unregister_focus(g_voip_ringtone_stream_info);
713                                 SM_SAFE_FREE(g_voip_ringtone_stream_info);
714                                 if (ret != MM_ERROR_NONE)
715                                         goto LEAVE;
716                         }
717                 }
718         }
719         ret = mm_session_init(new_session);
720         if (ret == MM_ERROR_NONE)
721                 g_session_interrupt_cb_table.is_registered = 1;
722
723         LOGI("type=%d", type);
724 LEAVE:
725         SM_LEAVE_CRITICAL_SECTION(&g_session_mutex);
726
727         return _convert_sound_manager_error_code(__func__, ret);
728 }
729
730 int sound_manager_get_session_type(sound_session_type_e *type)
731 {
732         int ret = MM_ERROR_NONE;
733         int cur_session;
734
735         LOGW("DEPRECATION WARNING: %s() is deprecated and will be removed from next release.", __func__);
736         if (type == NULL)
737                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
738
739         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_session_mutex, SOUND_MANAGER_ERROR_INVALID_PARAMETER);
740
741         ret = mm_session_get_current_type(&cur_session);
742         if (ret != MM_ERROR_NONE) {
743                 LOGW("session hasn't been set, setting default session");
744                 cur_session = SOUND_SESSION_TYPE_DEFAULT;
745                 ret = mm_session_init(cur_session);
746                 if (ret == MM_ERROR_NONE)
747                         g_session_interrupt_cb_table.is_registered = 1;
748         }
749         if ((cur_session > MM_SESSION_TYPE_EMERGENCY) &&
750                         (cur_session != MM_SESSION_TYPE_VOIP)) {
751                 if (g_cached_session != -1)
752                         cur_session = g_cached_session;
753                 else /* will be never reached here. just prevent code */
754                         cur_session = SOUND_SESSION_TYPE_DEFAULT;
755         }
756
757         switch (cur_session) {
758         case MM_SESSION_TYPE_MEDIA:
759         case MM_SESSION_TYPE_MEDIA_RECORD:
760                 *type = SOUND_SESSION_TYPE_MEDIA;
761                 break;
762         case MM_SESSION_TYPE_ALARM:
763                 *type = SOUND_SESSION_TYPE_ALARM;
764                 break;
765         case MM_SESSION_TYPE_NOTIFY:
766                 *type = SOUND_SESSION_TYPE_NOTIFICATION;
767                 break;
768         case MM_SESSION_TYPE_EMERGENCY:
769                 *type = SOUND_SESSION_TYPE_EMERGENCY;
770                 break;
771         case MM_SESSION_TYPE_VOIP:
772                 *type = SOUND_SESSION_TYPE_VOIP;
773                 break;
774         default:
775                 *type = cur_session;
776                 break;
777         }
778
779         LOGI("type=%d", *type);
780
781         SM_LEAVE_CRITICAL_SECTION(&g_session_mutex);
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         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_session_mutex, SOUND_MANAGER_ERROR_INTERNAL);
1021
1022         ret = mm_session_get_current_information(&session, &session_options);
1023         if (ret != MM_ERROR_NONE)
1024                 goto LEAVE;
1025
1026         if (session != MM_SESSION_TYPE_VOIP) {
1027                 ret = MM_ERROR_POLICY_INTERNAL;
1028                 goto LEAVE;
1029         }
1030
1031         if (mode < SOUND_SESSION_VOIP_MODE_RINGTONE || mode > SOUND_SESSION_VOIP_MODE_VOICE_WITH_BLUETOOTH) {
1032                 ret = MM_ERROR_INVALID_ARGUMENT;
1033                 goto LEAVE;
1034         }
1035
1036         ret = _set_session_mode((_session_mode_e)mode);
1037
1038         LOGI("session=%d, mode=%d(0:RINGTONE 1:MIC_RCV 2:MIC_SPK 3:EAR 4:BT)", session, mode);
1039
1040 LEAVE:
1041         SM_LEAVE_CRITICAL_SECTION(&g_session_mutex);
1042
1043         return _convert_sound_manager_error_code(__func__, ret);
1044 }
1045
1046 int sound_manager_get_voip_session_mode(sound_session_voip_mode_e *mode)
1047 {
1048         int ret = MM_ERROR_NONE;
1049         int session = 0;
1050         int session_options = 0;
1051
1052         LOGW("DEPRECATION WARNING: %s() is deprecated and will be removed from next release. Use sound_manager_create_stream_information() instead.", __func__);
1053
1054         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_session_mutex, SOUND_MANAGER_ERROR_INTERNAL);
1055
1056         if (mode == NULL) {
1057                 LOGE("mode is null");
1058                 ret = MM_ERROR_INVALID_ARGUMENT;
1059                 goto LEAVE;
1060         }
1061
1062         ret = mm_session_get_current_information(&session, &session_options);
1063         if (ret != MM_ERROR_NONE) {
1064                 LOGI("session = %d, option = %d", session, session_options);
1065                 goto LEAVE;
1066         }
1067
1068         if (session != MM_SESSION_TYPE_VOIP || g_cached_session_mode == -1) {
1069                 ret = MM_ERROR_POLICY_INTERNAL;
1070                 goto LEAVE;
1071         }
1072
1073         *mode = (sound_session_voip_mode_e)g_cached_session_mode;
1074
1075         LOGI("session=%d, mode=%d", session, *mode);
1076
1077 LEAVE:
1078         SM_LEAVE_CRITICAL_SECTION(&g_session_mutex);
1079
1080         return _convert_sound_manager_error_code(__func__, ret);
1081 }
1082
1083 int sound_manager_set_session_interrupted_cb(sound_session_interrupted_cb callback, void *user_data)
1084 {
1085         int ret = MM_ERROR_NONE;
1086         unsigned int subs_id = 0;
1087
1088         LOGW("DEPRECATION WARNING: %s() is deprecated and will be removed from next release. Use sound_manager_create_stream_information() instead.", __func__);
1089         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_interrupt_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
1090
1091         if (callback == NULL) {
1092                 ret = MM_ERROR_INVALID_ARGUMENT;
1093                 goto LEAVE;
1094         }
1095
1096         /* it is not supported both session and stream feature at the same time */
1097         if (g_stream_info_count) {
1098                 ret =  MM_ERROR_POLICY_INTERNAL;
1099                 goto LEAVE;
1100         }
1101
1102         if (g_session_interrupt_cb_table.user_cb == NULL) {
1103                 if ((ret = mm_sound_add_device_connected_callback(SOUND_DEVICE_ALL_MASK, (mm_sound_device_connected_cb)_device_connected_cb, NULL, &subs_id))) {
1104                         ret = MM_ERROR_INVALID_ARGUMENT;
1105                         goto LEAVE;
1106                 }
1107                 if ((ret = mm_sound_focus_set_session_interrupt_callback((mm_sound_focus_session_interrupt_cb)_focus_session_interrupt_cb, NULL))) {
1108                         if (mm_sound_remove_device_connected_callback(subs_id) != MM_ERROR_NONE)
1109                                 LOGW("mm_sound_remove_device_connected_callback failed");
1110                         ret = MM_ERROR_INVALID_ARGUMENT;
1111                         goto LEAVE;
1112                 }
1113                 g_session_interrupt_cb_table.subs_id = subs_id;
1114         }
1115         g_session_interrupt_cb_table.user_cb = (sound_session_interrupted_cb)callback;
1116         g_session_interrupt_cb_table.user_data = user_data;
1117
1118 LEAVE:
1119         SM_LEAVE_CRITICAL_SECTION(&g_interrupt_cb_mutex);
1120
1121         return _convert_sound_manager_error_code(__func__, ret);
1122 }
1123
1124 int sound_manager_unset_session_interrupted_cb(void)
1125 {
1126         int ret = MM_ERROR_NONE;
1127
1128         LOGW("DEPRECATION WARNING: %s() is deprecated and will be removed from next release.", __func__);
1129         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_interrupt_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
1130
1131         if (!g_session_interrupt_cb_table.user_cb) {
1132                 ret = MM_ERROR_SOUND_INTERNAL;
1133                 goto LEAVE;
1134         }
1135
1136         if ((ret = mm_sound_focus_unset_session_interrupt_callback())) {
1137                 if (mm_sound_remove_device_connected_callback(g_session_interrupt_cb_table.subs_id) != MM_ERROR_NONE)
1138                         LOGW("mm_sound_remove_device_connected_callback failed");
1139                 ret = MM_ERROR_SOUND_INTERNAL;
1140                 goto LEAVE;
1141         }
1142
1143         if ((ret = mm_sound_remove_device_connected_callback(g_session_interrupt_cb_table.subs_id))) {
1144                 ret = MM_ERROR_SOUND_INTERNAL;
1145                 goto LEAVE;
1146         }
1147
1148         g_session_interrupt_cb_table.subs_id = 0;
1149         g_session_interrupt_cb_table.user_cb = NULL;
1150         g_session_interrupt_cb_table.user_data = NULL;
1151
1152 LEAVE:
1153         SM_LEAVE_CRITICAL_SECTION(&g_interrupt_cb_mutex);
1154
1155         return _convert_sound_manager_error_code(__func__, ret);
1156 }
1157
1158 int sound_manager_get_current_device_list(sound_device_mask_e device_mask, sound_device_list_h *device_list)
1159 {
1160         int ret = MM_ERROR_NONE;
1161
1162         LOGW("DEPRECATION WARNING: %s() is deprecated and will be removed from next release. Use sound_manager_get_device_list() instead.", __func__);
1163         ret = mm_sound_get_current_device_list(device_mask, device_list);
1164
1165         return _convert_sound_manager_error_code(__func__, ret);
1166 }
1167
1168 int sound_manager_get_device_list(int device_mask, sound_device_list_h *device_list)
1169 {
1170         int ret = MM_ERROR_NONE;
1171
1172         ret = mm_sound_get_device_list(device_mask, device_list);
1173
1174         return _convert_sound_manager_error_code(__func__, ret);
1175 }
1176
1177 int sound_manager_free_device_list(sound_device_list_h device_list)
1178 {
1179         int ret = MM_ERROR_NONE;
1180
1181         ret = mm_sound_free_device_list(device_list);
1182
1183         return _convert_sound_manager_error_code(__func__, ret);
1184 }
1185
1186 int sound_manager_get_next_device(sound_device_list_h device_list, sound_device_h *device)
1187 {
1188         int ret = MM_ERROR_NONE;
1189
1190         ret = mm_sound_get_next_device(device_list, device);
1191
1192         return _convert_sound_manager_error_code(__func__, ret);
1193 }
1194
1195 int sound_manager_get_prev_device(sound_device_list_h device_list, sound_device_h *device)
1196 {
1197         int ret = MM_ERROR_NONE;
1198
1199         ret = mm_sound_get_prev_device(device_list, device);
1200
1201         return _convert_sound_manager_error_code(__func__, ret);
1202 }
1203
1204 int sound_manager_get_device_type(sound_device_h device, sound_device_type_e *type)
1205 {
1206         int ret = MM_ERROR_NONE;
1207         mm_sound_device_type_e mm_sound_device_type;
1208
1209         ret = mm_sound_get_device_type(device, &mm_sound_device_type);
1210         if (ret == MM_ERROR_NONE)
1211                 ret = _convert_device_type(mm_sound_device_type, type);
1212
1213         return _convert_sound_manager_error_code(__func__, ret);
1214 }
1215
1216 int sound_manager_get_device_io_direction(sound_device_h device, sound_device_io_direction_e *io_direction)
1217 {
1218         int ret = MM_ERROR_NONE;
1219         mm_sound_device_io_direction_e mm_sound_io_direction;
1220
1221         ret = mm_sound_get_device_io_direction(device, &mm_sound_io_direction);
1222         if (ret == MM_ERROR_NONE)
1223                 ret = _convert_device_io_direction(mm_sound_io_direction, io_direction);
1224
1225         return _convert_sound_manager_error_code(__func__, ret);
1226 }
1227
1228 int sound_manager_get_device_id(sound_device_h device, int *id)
1229 {
1230         int ret = MM_ERROR_NONE;
1231
1232         ret = mm_sound_get_device_id(device, id);
1233
1234         return _convert_sound_manager_error_code(__func__, ret);
1235 }
1236
1237 int sound_manager_get_device_name(sound_device_h device, char **name)
1238 {
1239         int ret = MM_ERROR_NONE;
1240
1241         ret = mm_sound_get_device_name(device, name);
1242
1243         return _convert_sound_manager_error_code(__func__, ret);
1244 }
1245
1246 int sound_manager_get_device_state(sound_device_h device, sound_device_state_e *state)
1247 {
1248         int ret = MM_ERROR_NONE;
1249
1250         ret = mm_sound_get_device_state(device, (mm_sound_device_state_e*)state);
1251
1252         return _convert_sound_manager_error_code(__func__, ret);
1253 }
1254
1255 int sound_manager_set_device_connected_cb(sound_device_mask_e device_mask, sound_device_connected_cb callback, void *user_data)
1256 {
1257         int ret = MM_ERROR_NONE;
1258         unsigned int subs_id = 0;
1259
1260         LOGW("DEPRECATION WARNING: %s() is deprecated and will be removed from next release. "
1261                 "Use sound_manager_add_device_connection_changed_cb() instead.", __func__);
1262
1263         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_device_conn_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
1264
1265         ret = mm_sound_add_device_connected_callback((mm_sound_device_flags_e)device_mask, (mm_sound_device_connected_cb)callback, user_data, &subs_id);
1266         if (ret == MM_ERROR_NONE) {
1267                 g_device_connected_cb_table.subs_id = subs_id;
1268                 g_device_connected_cb_table.user_cb = (sound_device_connected_cb)callback;
1269                 g_device_connected_cb_table.user_data = user_data;
1270         }
1271
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_unset_device_connected_cb(void)
1278 {
1279         int ret = MM_ERROR_NONE;
1280
1281         LOGW("DEPRECATION WARNING: %s() is deprecated and will be removed from next release. "
1282                 "Use sound_manager_remove_device_connection_changed_cb() instead.", __func__);
1283
1284         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_device_conn_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
1285
1286         if (g_device_connected_cb_table.subs_id == 0) {
1287                 ret = MM_ERROR_SOUND_INTERNAL;
1288                 goto LEAVE;
1289         }
1290
1291         ret = mm_sound_remove_device_connected_callback(g_device_connected_cb_table.subs_id);
1292         if (ret == MM_ERROR_NONE) {
1293                 g_device_connected_cb_table.subs_id = 0;
1294                 g_device_connected_cb_table.user_cb = NULL;
1295                 g_device_connected_cb_table.user_data = NULL;
1296         }
1297
1298 LEAVE:
1299         SM_LEAVE_CRITICAL_SECTION(&g_device_conn_cb_mutex);
1300
1301         return _convert_sound_manager_error_code(__func__, ret);
1302 }
1303
1304 int sound_manager_add_device_connection_changed_cb(int device_mask, sound_device_connected_cb callback, void *user_data, int *id)
1305 {
1306         int ret = MM_ERROR_NONE;
1307
1308         if (!callback || !id)
1309                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
1310
1311         ret = mm_sound_add_device_connected_callback((mm_sound_device_flags_e)device_mask, (mm_sound_device_connected_cb)callback, user_data, (unsigned int*)id);
1312
1313         return _convert_sound_manager_error_code(__func__, ret);
1314 }
1315
1316 int sound_manager_remove_device_connection_changed_cb(int id)
1317 {
1318         int ret = MM_ERROR_NONE;
1319
1320         if (id < 0)
1321                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
1322
1323         ret = mm_sound_remove_device_connected_callback((unsigned int)id);
1324
1325         return _convert_sound_manager_error_code(__func__, ret);
1326 }
1327
1328 int sound_manager_set_device_information_changed_cb(sound_device_mask_e device_mask, sound_device_information_changed_cb callback, void *user_data)
1329 {
1330         int ret = MM_ERROR_NONE;
1331         unsigned int subs_id = 0;
1332
1333         LOGW("DEPRECATION WARNING: %s() is deprecated and will be removed from next release. "
1334                 "Use sound_manager_add_device_state_changed_cb() instead.", __func__);
1335         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_device_info_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
1336
1337         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);
1338         if (ret == MM_ERROR_NONE) {
1339                 g_device_info_changed_cb_table.subs_id = subs_id;
1340                 g_device_info_changed_cb_table.user_cb = (sound_device_information_changed_cb)callback;
1341                 g_device_info_changed_cb_table.user_data = user_data;
1342         }
1343
1344         SM_LEAVE_CRITICAL_SECTION(&g_device_info_cb_mutex);
1345
1346         return _convert_sound_manager_error_code(__func__, ret);
1347 }
1348
1349 int sound_manager_unset_device_information_changed_cb(void)
1350 {
1351         int ret = MM_ERROR_NONE;
1352
1353         LOGW("DEPRECATION WARNING: %s() is deprecated and will be removed from next release. "
1354                 "Use sound_manager_remove_device_state_changed_cb() instead.", __func__);
1355         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_device_info_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
1356
1357         if (g_device_info_changed_cb_table.subs_id == 0) {
1358                 ret = MM_ERROR_SOUND_INTERNAL;
1359                 goto LEAVE;
1360         }
1361
1362         ret = mm_sound_remove_device_information_changed_callback(g_device_info_changed_cb_table.subs_id);
1363         if (ret == MM_ERROR_NONE) {
1364                 g_device_info_changed_cb_table.subs_id = 0;
1365                 g_device_info_changed_cb_table.user_cb = NULL;
1366                 g_device_info_changed_cb_table.user_data = NULL;
1367         }
1368
1369 LEAVE:
1370         SM_LEAVE_CRITICAL_SECTION(&g_device_info_cb_mutex);
1371
1372         return _convert_sound_manager_error_code(__func__, ret);
1373 }
1374
1375 int sound_manager_add_device_state_changed_cb(int device_mask, sound_device_state_changed_cb callback, void *user_data, int *id)
1376 {
1377         int ret = MM_ERROR_NONE;
1378
1379         if (!callback || !id)
1380                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
1381
1382         ret = mm_sound_add_device_state_changed_callback(device_mask, (mm_sound_device_state_changed_cb)callback, user_data, (unsigned int*)id);
1383
1384         return _convert_sound_manager_error_code(__func__, ret);
1385 }
1386
1387 int sound_manager_remove_device_state_changed_cb(int id)
1388 {
1389         int ret = MM_ERROR_NONE;
1390
1391         if (id < 0)
1392                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
1393
1394         ret = mm_sound_remove_device_state_changed_callback((unsigned int)id);
1395
1396         return _convert_sound_manager_error_code(__func__, ret);
1397 }
1398
1399 __attribute__ ((destructor))
1400 void __sound_manager_finalize(void)
1401 {
1402         int ret = MM_ERROR_NONE;
1403
1404         if (g_session_interrupt_cb_table.is_registered) {
1405                 LOGI("<ENTER>");
1406                 ret = mm_session_finish();
1407                 if (ret != MM_ERROR_NONE)
1408                         LOGE("[%s] failed to mm_session_finish(), ret(0x%x)", __func__, ret);
1409
1410                 g_session_interrupt_cb_table.is_registered = 0;
1411                 LOGI("<LEAVE>");
1412         }
1413 }
1414
1415 __attribute__ ((constructor))
1416 void __sound_manager_initialize(void)
1417 {
1418
1419 }