Check mic feature when setting session type to voip
[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         if (type >= SOUND_TYPE_NUM || type < 0)
99                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
100
101         ret = mm_sound_volume_primary_type_set(type);
102
103         return _convert_sound_manager_error_code(__func__, ret);
104 }
105
106 int sound_manager_get_current_sound_type(sound_type_e *type)
107 {
108         int ret = MM_ERROR_NONE;
109         volume_type_t mm_sound_vol_type = VOLUME_TYPE_UNKNOWN;
110         char *volume_type = NULL;
111
112         if (type == NULL)
113                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
114
115         ret  = mm_sound_volume_primary_type_get(&mm_sound_vol_type);
116         if (ret == MM_ERROR_NONE) {
117                 if (mm_sound_vol_type == VOLUME_TYPE_UNKNOWN) {
118                         /* get the volume type of the current playing stream */
119                         ret = _get_current_volume_type(DIRECTION_OUT_STR, &volume_type);
120                         if (ret == MM_ERROR_NONE)
121                                 ret = _convert_sound_type_to_enum((const char*)volume_type, type);
122                 } else {
123                         *type = mm_sound_vol_type;
124                 }
125         }
126         LOGI("type=%d", *type);
127
128         return _convert_sound_manager_error_code(__func__, ret);
129 }
130
131 int sound_manager_unset_current_sound_type(void)
132 {
133         int ret = MM_ERROR_NONE;
134
135         ret = mm_sound_volume_primary_type_set(VOLUME_TYPE_UNKNOWN);
136
137         return _convert_sound_manager_error_code(__func__, ret);
138 }
139
140 int sound_manager_set_volume_changed_cb(sound_manager_volume_changed_cb callback, void* user_data)
141 {
142         int ret = MM_ERROR_NONE;
143         unsigned int subs_id = 0;
144
145         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_volume_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
146
147         ret = mm_sound_add_volume_changed_callback((mm_sound_volume_changed_cb)callback, user_data, &subs_id);
148         if (ret == MM_ERROR_NONE) {
149                 g_volume_changed_cb_table.subs_id = subs_id;
150                 g_volume_changed_cb_table.user_cb = (sound_manager_volume_changed_cb)callback;
151                 g_volume_changed_cb_table.user_data = user_data;
152         }
153
154         SM_LEAVE_CRITICAL_SECTION(&g_volume_cb_mutex);
155
156         return _convert_sound_manager_error_code(__func__, ret);
157 }
158
159 int sound_manager_unset_volume_changed_cb(void)
160 {
161         int ret = MM_ERROR_NONE;
162
163         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_volume_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
164
165         if (g_volume_changed_cb_table.subs_id > 0) {
166                 ret = mm_sound_remove_volume_changed_callback(g_volume_changed_cb_table.subs_id);
167                 if (ret == MM_ERROR_NONE) {
168                         g_volume_changed_cb_table.subs_id = 0;
169                         g_volume_changed_cb_table.user_cb = NULL;
170                         g_volume_changed_cb_table.user_data = NULL;
171                 }
172         } else {
173                 ret = MM_ERROR_SOUND_INTERNAL;
174         }
175
176         SM_LEAVE_CRITICAL_SECTION(&g_volume_cb_mutex);
177
178         return _convert_sound_manager_error_code(__func__, ret);
179 }
180
181 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)
182 {
183         int ret = MM_ERROR_NONE;
184
185         LOGI(">> enter");
186
187         SM_NULL_ARG_CHECK(stream_info);
188
189         if (g_session_interrupt_cb_table.is_registered)
190                 return _convert_sound_manager_error_code(__func__, MM_ERROR_SOUND_INTERNAL);
191
192         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_stream_info_count_mutex, MM_ERROR_SOUND_INTERNAL);
193
194         sound_stream_info_s *stream_h = malloc(sizeof(sound_stream_info_s));
195         if (!stream_h) {
196                 ret = MM_ERROR_OUT_OF_MEMORY;
197                 goto LEAVE;
198         }
199
200         memset(stream_h, 0, sizeof(sound_stream_info_s));
201         ret = _convert_stream_type(stream_type, &stream_h->stream_type);
202         if (ret == MM_ERROR_NONE) {
203                 ret = _make_pa_connection_and_register_focus(stream_h, callback, user_data);
204                 if (ret == MM_ERROR_NONE) {
205                         *stream_info = (sound_stream_info_h)stream_h;
206                         SM_REF_FOR_STREAM_INFO(g_stream_info_count, ret);
207                         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);
208                 }
209         }
210
211 LEAVE:
212         if (ret && stream_h)
213                 free(stream_h);
214
215         SM_LEAVE_CRITICAL_SECTION(&g_stream_info_count_mutex);
216
217         return _convert_sound_manager_error_code(__func__, ret);
218 }
219
220 int sound_manager_destroy_stream_information(sound_stream_info_h stream_info)
221 {
222         int ret = MM_ERROR_NONE;
223         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
224
225         LOGI(">> enter");
226
227         SM_INSTANCE_CHECK(stream_h);
228
229         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_stream_info_count_mutex, MM_ERROR_SOUND_INTERNAL);
230         ret = _destroy_pa_connection_and_unregister_focus(stream_h);
231         if (ret == MM_ERROR_NONE) {
232                 free(stream_h);
233                 stream_h = NULL;
234                 SM_UNREF_FOR_STREAM_INFO(g_stream_info_count);
235         }
236         SM_LEAVE_CRITICAL_SECTION(&g_stream_info_count_mutex);
237
238         LOGD("cnt(%d)", g_stream_info_count);
239
240         return _convert_sound_manager_error_code(__func__, ret);
241 }
242
243 int sound_manager_add_device_for_stream_routing(sound_stream_info_h stream_info, sound_device_h device)
244 {
245         int ret = MM_ERROR_NONE;
246         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
247
248         LOGI(">> enter");
249
250         ret = _add_device_for_stream_routing(stream_h, device);
251
252         return _convert_sound_manager_error_code(__func__, ret);
253 }
254
255 int sound_manager_remove_device_for_stream_routing(sound_stream_info_h stream_info, sound_device_h device)
256 {
257         int ret = MM_ERROR_NONE;
258         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
259
260         LOGI(">> enter");
261
262         ret = _remove_device_for_stream_routing(stream_h, device);
263
264         return _convert_sound_manager_error_code(__func__, ret);
265 }
266
267 int sound_manager_apply_stream_routing(sound_stream_info_h stream_info)
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 = _apply_stream_routing(stream_h);
275
276         return _convert_sound_manager_error_code(__func__, ret);
277 }
278
279 int sound_manager_set_focus_reacquisition(sound_stream_info_h stream_info, bool enable)
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         SM_INSTANCE_CHECK(stream_h);
287
288         ret = mm_sound_set_focus_reacquisition(stream_h->index, enable);
289
290         return _convert_sound_manager_error_code(__func__, ret);
291 }
292
293 int sound_manager_get_focus_reacquisition(sound_stream_info_h stream_info, bool *enabled)
294 {
295         int ret = MM_ERROR_NONE;
296         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
297
298         LOGI(">> enter");
299
300         SM_INSTANCE_CHECK(stream_h);
301         SM_NULL_ARG_CHECK(enabled);
302
303         ret = mm_sound_get_focus_reacquisition(stream_h->index, enabled);
304
305         return _convert_sound_manager_error_code(__func__, ret);
306 }
307
308 int sound_manager_acquire_focus(sound_stream_info_h stream_info, sound_stream_focus_mask_e focus_mask, const char *extra_info)
309 {
310         int ret = MM_ERROR_NONE;
311         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
312
313         LOGI(">> enter");
314
315         SM_INSTANCE_CHECK(stream_h);
316
317         if (stream_h->is_focus_unavailable) {
318                 LOGE("acquiring focus is not allowed for this strema type(%s)", stream_h->stream_type);
319                 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
320         }
321
322         if (stream_h->user_cb == NULL) {
323                 LOGE("focus state changed callback should be set before acquiring focus");
324                 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
325         }
326
327         ret = mm_sound_acquire_focus(stream_h->index, (mm_sound_focus_type_e)focus_mask, extra_info);
328         if (ret == MM_ERROR_NONE) {
329                 stream_h->acquired_focus |= focus_mask;
330                 _update_focus_status(stream_h->index, (unsigned int)stream_h->acquired_focus);
331         }
332
333         return _convert_sound_manager_error_code(__func__, ret);
334 }
335
336 int sound_manager_release_focus(sound_stream_info_h stream_info, sound_stream_focus_mask_e focus_mask, const char *extra_info)
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_release_focus(stream_h->index, (mm_sound_focus_type_e)focus_mask, extra_info);
346         if (ret == MM_ERROR_NONE) {
347                 stream_h->acquired_focus &= ~focus_mask;
348                 _update_focus_status(stream_h->index, (unsigned int)stream_h->acquired_focus);
349         }
350
351         return _convert_sound_manager_error_code(__func__, ret);
352 }
353
354 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)
355 {
356         int ret = MM_ERROR_NONE;
357         sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
358
359         LOGI(">> enter");
360
361         SM_INSTANCE_CHECK(stream_h);
362         if (!state_for_playback && !state_for_recording) {
363                 ret = MM_ERROR_INVALID_ARGUMENT;
364                 goto LEAVE;
365         }
366
367         if (state_for_playback)
368                 *state_for_playback = ((stream_h->acquired_focus & SOUND_STREAM_FOCUS_FOR_PLAYBACK) ? (SOUND_STREAM_FOCUS_STATE_ACQUIRED) : (SOUND_STREAM_FOCUS_STATE_RELEASED));
369         if (state_for_recording)
370                 *state_for_recording = ((stream_h->acquired_focus & SOUND_STREAM_FOCUS_FOR_RECORDING) ? (SOUND_STREAM_FOCUS_STATE_ACQUIRED) : (SOUND_STREAM_FOCUS_STATE_RELEASED));
371
372         LOGI("acquired_focus(0x%x)", stream_h->acquired_focus);
373
374 LEAVE:
375         return _convert_sound_manager_error_code(__func__, ret);
376 }
377
378 int sound_manager_get_sound_type(sound_stream_info_h stream_info, sound_type_e *sound_type)
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         SM_NULL_ARG_CHECK(sound_type);
387
388         if (stream_h->stream_conf_info.volume_type == NULL) {
389                 ret = MM_ERROR_SOUND_NO_DATA;
390                 goto LEAVE;
391         }
392
393         ret = _convert_sound_type_to_enum(stream_h->stream_conf_info.volume_type, sound_type);
394         LOGI("sound type(%d)", *sound_type);
395
396 LEAVE:
397         return _convert_sound_manager_error_code(__func__, ret);
398 }
399
400 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)
401 {
402         int ret = MM_ERROR_NONE;
403         int i = 0;
404
405         LOGI(">> enter");
406
407         SM_NULL_ARG_CHECK(callback);
408         SM_NULL_ARG_CHECK(id);
409         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_stream_info_count_mutex, SOUND_MANAGER_ERROR_INTERNAL);
410
411         for (i = 0; i < SOUND_STREAM_INFO_ARR_MAX; i++)
412                 if (focus_watch_info_arr[i].id == 0)
413                         break;
414         if (i == SOUND_STREAM_INFO_ARR_MAX) {
415                 LOGE("focus watch info array is full");
416                 ret = MM_ERROR_SOUND_INTERNAL;
417                 goto LEAVE;
418         }
419
420         ret = mm_sound_set_focus_watch_callback((mm_sound_focus_type_e)focus_mask, _focus_watch_callback, user_data, id);
421         if (ret == MM_ERROR_NONE) {
422                 SM_REF_FOR_STREAM_INFO(g_stream_info_count, ret);
423                 focus_watch_info_arr[i].id = *id;
424                 focus_watch_info_arr[i].user_data = user_data;
425                 focus_watch_info_arr[i].user_cb = callback;
426         }
427
428 LEAVE:
429         SM_LEAVE_CRITICAL_SECTION(&g_stream_info_count_mutex);
430
431         LOGD("cnt(%d), id(%d)", g_stream_info_count, *id);
432
433         return _convert_sound_manager_error_code(__func__, ret);
434 }
435
436 int sound_manager_remove_focus_state_watch_cb(int id)
437 {
438         int ret = MM_ERROR_NONE;
439         int i = 0;
440
441         LOGI(">> enter");
442
443         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_stream_info_count_mutex, SOUND_MANAGER_ERROR_INTERNAL);
444
445         for (i = 0; i < SOUND_STREAM_INFO_ARR_MAX; i++)
446                 if (focus_watch_info_arr[i].id == id)
447                         break;
448         if (i == SOUND_STREAM_INFO_ARR_MAX) {
449                 LOGE("cound not find item in focus watch info array for this id(%d)", id);
450                 ret = MM_ERROR_INVALID_ARGUMENT;
451                 goto LEAVE;
452         }
453
454         ret = mm_sound_unset_focus_watch_callback(id);
455         if (ret == MM_ERROR_NONE) {
456                 SM_UNREF_FOR_STREAM_INFO(g_stream_info_count);
457                 focus_watch_info_arr[i].id = 0;
458                 focus_watch_info_arr[i].user_data = NULL;
459                 focus_watch_info_arr[i].user_cb = NULL;
460         }
461
462 LEAVE:
463         SM_LEAVE_CRITICAL_SECTION(&g_stream_info_count_mutex);
464
465         LOGD("cnt(%d)", g_stream_info_count);
466
467         return _convert_sound_manager_error_code(__func__, ret);
468 }
469
470 int sound_manager_set_session_type(sound_session_type_e type)
471 {
472         int ret = MM_ERROR_NONE;
473         int cur_session = -1;
474         int new_session = MM_SESSION_TYPE_MEDIA;
475         bool mic_enable = false;
476
477         LOGI(">> enter : type=%d", type);
478
479         if (type < SOUND_SESSION_TYPE_MEDIA || type >  SOUND_SESSION_TYPE_VOIP)
480                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
481
482         /* If session type is VOIP but MIC is not enabled, return false */
483         if (type == SOUND_SESSION_TYPE_VOIP) {
484                 ret = system_info_get_platform_bool(FEATURE_MICROPHONE, &mic_enable);
485                 LOGI("system_info_platform [%s]=[%d], ret[%d]", FEATURE_MICROPHONE, mic_enable, ret);
486                 if (ret != SYSTEM_INFO_ERROR_NONE || !mic_enable)
487                         return _convert_sound_manager_error_code(__func__, MM_ERROR_NOT_SUPPORT_API);
488         }
489
490         /* it is not supported both session and stream feature at the same time */
491         if (g_stream_info_count) {
492                 LOGE("Could not set this type(%d) because of being used stream feature", type);
493                 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
494         }
495
496         switch (type) {
497         case SOUND_SESSION_TYPE_MEDIA:
498                 new_session = MM_SESSION_TYPE_MEDIA;
499                 break;
500         case SOUND_SESSION_TYPE_ALARM:
501                 new_session = MM_SESSION_TYPE_ALARM;
502                 break;
503         case SOUND_SESSION_TYPE_NOTIFICATION:
504                 new_session = MM_SESSION_TYPE_NOTIFY;
505                 break;
506         case SOUND_SESSION_TYPE_EMERGENCY:
507                 new_session = MM_SESSION_TYPE_EMERGENCY;
508                 break;
509         case SOUND_SESSION_TYPE_VOIP:
510                 new_session = MM_SESSION_TYPE_VOIP;
511                 break;
512         }
513
514         /* valid session check */
515         ret = mm_session_get_current_type(&cur_session);
516         if (ret == MM_ERROR_NONE) {
517                 if (cur_session == MM_SESSION_TYPE_MEDIA_RECORD) {
518                         if (type > SOUND_SESSION_TYPE_MEDIA) {
519                                 LOGE("Could not set this type(%d) during camera/recorder/audio-io(in)/radio", type);
520                                 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
521                         }
522                 }
523         }
524
525         if (g_session_interrupt_cb_table.is_registered) {
526                 if (new_session == cur_session ||
527                         ((new_session == SOUND_SESSION_TYPE_MEDIA) && (cur_session == MM_SESSION_TYPE_MEDIA_RECORD))) {
528                         LOGI("already set type=%d, ret=0x%x", type, ret);
529                         return SOUND_MANAGER_ERROR_NONE;
530                 } else {
531                         ret = mm_session_finish();
532                         if (ret != MM_ERROR_NONE)
533                                 return _convert_sound_manager_error_code(__func__, ret);
534
535                         g_session_interrupt_cb_table.is_registered = 0;
536                         if (cur_session == MM_SESSION_TYPE_VOIP) {
537                                 g_cached_session_mode = -1;
538                                 g_cached_voip_device_id = -1;
539                                 if (g_voip_vstream_h) {
540                                         _stop_virtual_stream(g_voip_vstream_h);
541                                         _destroy_virtual_stream(g_voip_vstream_h);
542                                         g_voip_vstream_h = NULL;
543                                 }
544                                 /*voip stream destruction*/
545                                 if (g_voip_stream_info) {
546                                         ret = _destroy_pa_connection_and_unregister_focus(g_voip_stream_info);
547                                         free(g_voip_stream_info);
548                                         g_voip_stream_info = NULL;
549                                         if (ret != MM_ERROR_NONE)
550                                                 return _convert_sound_manager_error_code(__func__, ret);
551                                 }
552                         }
553                 }
554         }
555         ret = mm_session_init(new_session);
556         if (ret == MM_ERROR_NONE)
557                 g_session_interrupt_cb_table.is_registered = 1;
558
559         LOGI("type=%d", type);
560
561         return _convert_sound_manager_error_code(__func__, ret);
562 }
563
564 int sound_manager_get_session_type(sound_session_type_e *type)
565 {
566         int ret = MM_ERROR_NONE;
567         int cur_session;
568
569         if (type == NULL)
570                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
571
572         ret = mm_session_get_current_type(&cur_session);
573         if (ret != MM_ERROR_NONE) {
574                 LOGW("session hasn't been set, setting default session");
575                 cur_session = SOUND_SESSION_TYPE_DEFAULT;
576                 ret = mm_session_init(cur_session);
577                 if (ret == MM_ERROR_NONE)
578                         g_session_interrupt_cb_table.is_registered = 1;
579         }
580         if ((cur_session > MM_SESSION_TYPE_EMERGENCY) &&
581                         (cur_session != MM_SESSION_TYPE_VOIP)) {
582                 if (g_cached_session != -1)
583                         cur_session = g_cached_session;
584                 else /* will be never reached here. just prevent code */
585                         cur_session = SOUND_SESSION_TYPE_DEFAULT;
586         }
587
588         switch (cur_session) {
589         case MM_SESSION_TYPE_MEDIA:
590         case MM_SESSION_TYPE_MEDIA_RECORD:
591                 *type = SOUND_SESSION_TYPE_MEDIA;
592                 break;
593         case MM_SESSION_TYPE_ALARM:
594                 *type = SOUND_SESSION_TYPE_ALARM;
595                 break;
596         case MM_SESSION_TYPE_NOTIFY:
597                 *type = SOUND_SESSION_TYPE_NOTIFICATION;
598                 break;
599         case MM_SESSION_TYPE_EMERGENCY:
600                 *type = SOUND_SESSION_TYPE_EMERGENCY;
601                 break;
602         case MM_SESSION_TYPE_VOIP:
603                 *type = SOUND_SESSION_TYPE_VOIP;
604                 break;
605         default:
606                 *type = cur_session;
607                 break;
608         }
609
610         LOGI("type=%d", *type);
611
612         return SOUND_MANAGER_ERROR_NONE;
613 }
614
615 int sound_manager_set_media_session_option(sound_session_option_for_starting_e s_option, sound_session_option_for_during_play_e d_option)
616 {
617         int ret = MM_ERROR_NONE;
618         int session = 0;
619         int session_option = 0;
620         int updated = 0;
621
622         LOGI(">> enter : option for starting=%d, for during play=%d", s_option, d_option);
623
624         if (s_option < 0 || s_option >  SOUND_SESSION_OPTION_PAUSE_OTHERS_WHEN_START)
625                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
626         if (d_option < 0 || d_option >  SOUND_SESSION_OPTION_UNINTERRUPTIBLE_DURING_PLAY)
627                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
628
629         ret = mm_session_get_current_information(&session, &session_option);
630         if (ret != 0 || !g_session_interrupt_cb_table.is_registered) {
631                 LOGW("session hasn't been set, setting default session");
632                 ret = mm_session_init(MM_SESSION_TYPE_MEDIA);
633                 if (ret == 0)
634                         g_session_interrupt_cb_table.is_registered = 1;
635
636         } else if (ret == 0 && session > MM_SESSION_TYPE_MEDIA) {
637                 if (session == MM_SESSION_TYPE_MEDIA_RECORD) {
638                         if (!g_session_interrupt_cb_table.is_registered) {
639                                 LOGE("Already set by camera/recorder/audio-io(in)/radio API, but need to set session to Media first");
640                                 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
641                         }
642                 } else {
643                         return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
644                 }
645         }
646
647         switch (s_option) {
648         case SOUND_SESSION_OPTION_MIX_WITH_OTHERS_WHEN_START:
649                 if (session_option & MM_SESSION_OPTION_PAUSE_OTHERS) {
650                         ret = mm_session_update_option(MM_SESSION_UPDATE_TYPE_REMOVE, MM_SESSION_OPTION_PAUSE_OTHERS);
651                         if (ret)
652                                 return _convert_sound_manager_error_code(__func__, ret);
653
654                         updated = 1;
655                 }
656                 break;
657         case SOUND_SESSION_OPTION_PAUSE_OTHERS_WHEN_START:
658                 if (!(session_option & MM_SESSION_OPTION_PAUSE_OTHERS)) {
659                         ret = mm_session_update_option(MM_SESSION_UPDATE_TYPE_ADD, MM_SESSION_OPTION_PAUSE_OTHERS);
660                         if (ret)
661                                 return _convert_sound_manager_error_code(__func__, ret);
662
663                         updated = 1;
664                 }
665                 break;
666         }
667
668         switch (d_option) {
669         case SOUND_SESSION_OPTION_INTERRUPTIBLE_DURING_PLAY:
670                 if (session_option & MM_SESSION_OPTION_UNINTERRUPTIBLE) {
671                         ret = mm_session_update_option(MM_SESSION_UPDATE_TYPE_REMOVE, MM_SESSION_OPTION_UNINTERRUPTIBLE);
672                         if (ret)
673                                 return _convert_sound_manager_error_code(__func__, ret);
674
675                         updated = 1;
676                 }
677                 break;
678         case SOUND_SESSION_OPTION_UNINTERRUPTIBLE_DURING_PLAY:
679                 if (!(session_option & MM_SESSION_OPTION_UNINTERRUPTIBLE)) {
680                         ret = mm_session_update_option(MM_SESSION_UPDATE_TYPE_ADD, MM_SESSION_OPTION_UNINTERRUPTIBLE);
681                         if (ret)
682                                 return _convert_sound_manager_error_code(__func__, ret);
683
684                         updated = 1;
685                 }
686                 break;
687         }
688
689         if (updated)
690                 LOGI("updated");
691         else
692                 LOGI("already set same option(%x), skip it", session_option);
693
694         return _convert_sound_manager_error_code(__func__, ret);
695 }
696
697 int sound_manager_get_media_session_option(sound_session_option_for_starting_e *s_option, sound_session_option_for_during_play_e *d_option)
698 {
699         int ret = MM_ERROR_NONE;
700         int session = 0;
701         int session_options = 0;
702
703         LOGI(">> enter");
704
705         if (s_option == NULL || d_option == NULL)
706                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
707
708         ret = mm_session_get_current_information(&session, &session_options);
709         if (ret != 0) {
710                 ret = mm_session_init(MM_SESSION_TYPE_MEDIA);
711                 if (ret == 0)
712                         g_session_interrupt_cb_table.is_registered = 1;
713
714         } else if (session > SOUND_SESSION_TYPE_MEDIA) {
715                 if (session == MM_SESSION_TYPE_MEDIA_RECORD) {
716                         if (!g_session_interrupt_cb_table.is_registered) {
717                                 LOGE("Already set by camera/recorder/audio-io(in)/radio API, but need to set session to Media first");
718                                 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
719                         }
720                 } else
721                         return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
722         }
723         /* get option */
724         if (session_options & MM_SESSION_OPTION_PAUSE_OTHERS)
725                 *s_option = SOUND_SESSION_OPTION_PAUSE_OTHERS_WHEN_START;
726         else
727                 *s_option = SOUND_SESSION_OPTION_MIX_WITH_OTHERS_WHEN_START;
728
729         if (session_options & MM_SESSION_OPTION_UNINTERRUPTIBLE)
730                 *d_option = SOUND_SESSION_OPTION_UNINTERRUPTIBLE_DURING_PLAY;
731         else
732                 *d_option = SOUND_SESSION_OPTION_INTERRUPTIBLE_DURING_PLAY;
733
734         LOGI(" option for starting=%d, for during play=%d", *s_option, *d_option);
735
736         return SOUND_MANAGER_ERROR_NONE;
737 }
738
739 int sound_manager_set_media_session_resumption_option(sound_session_option_for_resumption_e option)
740 {
741         int ret = MM_ERROR_NONE;
742         int session = 0;
743         int session_option = 0;
744         int updated = 0;
745
746         LOGI(">> enter : option for resumption=%d (0:by system, 1:by system or media paused)", option);
747
748         if (option < SOUND_SESSION_OPTION_RESUMPTION_BY_SYSTEM || option > SOUND_SESSION_OPTION_RESUMPTION_BY_SYSTEM_OR_MEDIA_PAUSED)
749                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
750
751         ret = mm_session_get_current_information(&session, &session_option);
752         if (ret != 0 || !g_session_interrupt_cb_table.is_registered) {
753                 LOGW("session hasn't been set, setting default session");
754                 ret = mm_session_init(MM_SESSION_TYPE_MEDIA);
755                 if (ret == 0)
756                         g_session_interrupt_cb_table.is_registered = 1;
757
758         } else if (ret == 0 && session > MM_SESSION_TYPE_MEDIA) {
759                 if (session == MM_SESSION_TYPE_MEDIA_RECORD) {
760                         if (!g_session_interrupt_cb_table.is_registered) {
761                                 LOGE("Already set by camera/recorder/audio-io(in)/radio API, but need to set session to Media first");
762                                 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
763                         }
764                 } else
765                         return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
766
767         }
768
769         switch (option) {
770         case SOUND_SESSION_OPTION_RESUMPTION_BY_SYSTEM:
771                 if (session_option & MM_SESSION_OPTION_RESUME_BY_SYSTEM_OR_MEDIA_PAUSED) {
772                         ret = mm_session_update_option(MM_SESSION_UPDATE_TYPE_REMOVE, MM_SESSION_OPTION_RESUME_BY_SYSTEM_OR_MEDIA_PAUSED);
773                         if (ret)
774                                 return _convert_sound_manager_error_code(__func__, ret);
775
776                         updated = 1;
777                 }
778                 break;
779         case SOUND_SESSION_OPTION_RESUMPTION_BY_SYSTEM_OR_MEDIA_PAUSED:
780                 if (!(session_option & MM_SESSION_OPTION_RESUME_BY_SYSTEM_OR_MEDIA_PAUSED)) {
781                         ret = mm_session_update_option(MM_SESSION_UPDATE_TYPE_ADD, MM_SESSION_OPTION_RESUME_BY_SYSTEM_OR_MEDIA_PAUSED);
782                         if (ret)
783                                 return _convert_sound_manager_error_code(__func__, ret);
784
785                         updated = 1;
786                 }
787                 break;
788         }
789
790         if (updated)
791                 LOGI("updated");
792         else
793                 LOGI("already set same option(0x%x), skip it", session_option);
794
795         return _convert_sound_manager_error_code(__func__, ret);
796 }
797
798 int sound_manager_get_media_session_resumption_option(sound_session_option_for_resumption_e *option)
799 {
800         int ret = MM_ERROR_NONE;
801         int session = 0;
802         int session_options = 0;
803
804         LOGI(">> enter");
805
806         if (option == NULL)
807                 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
808
809         ret = mm_session_get_current_information(&session, &session_options);
810         if (ret != 0) {
811                 LOGW("session hasn't been set, setting default session");
812                 ret = mm_session_init(MM_SESSION_TYPE_MEDIA);
813                 if (ret == 0)
814                         g_session_interrupt_cb_table.is_registered = 1;
815
816         } else if (session > SOUND_SESSION_TYPE_MEDIA) {
817                 if (session == MM_SESSION_TYPE_MEDIA_RECORD) {
818                         if (!g_session_interrupt_cb_table.is_registered) {
819                                 LOGE("Already set by camera/recorder/audio-io(in)/radio API, but need to set session to Media first");
820                                 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
821                         }
822                 } else
823                         return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
824         }
825         /* get option */
826         if (session_options & MM_SESSION_OPTION_RESUME_BY_SYSTEM_OR_MEDIA_PAUSED)
827                 *option = SOUND_SESSION_OPTION_RESUMPTION_BY_SYSTEM_OR_MEDIA_PAUSED;
828         else
829                 *option = SOUND_SESSION_OPTION_RESUMPTION_BY_SYSTEM;
830
831         LOGI("option for resumption=%d (0:by system, 1:by system or media paused)", *option);
832
833         return SOUND_MANAGER_ERROR_NONE;
834 }
835
836 int sound_manager_set_voip_session_mode(sound_session_voip_mode_e mode)
837 {
838         int ret = MM_ERROR_NONE;
839         int session = 0;
840         int session_options = 0;
841
842         LOGI(">> enter : mode=%d", mode);
843
844         ret = mm_session_get_current_information(&session, &session_options);
845         if (ret != MM_ERROR_NONE)
846                 goto LEAVE;
847
848         if (session != MM_SESSION_TYPE_VOIP) {
849                 ret = MM_ERROR_POLICY_INTERNAL;
850                 goto LEAVE;
851         }
852
853         if (mode < SOUND_SESSION_VOIP_MODE_RINGTONE || mode > SOUND_SESSION_VOIP_MODE_VOICE_WITH_BLUETOOTH) {
854                 ret = MM_ERROR_INVALID_ARGUMENT;
855                 goto LEAVE;
856         }
857
858         ret = _set_session_mode((_session_mode_e)mode);
859
860         LOGI("session=%d, mode=%d", session, mode);
861
862 LEAVE:
863         return _convert_sound_manager_error_code(__func__, ret);
864 }
865
866 int sound_manager_get_voip_session_mode(sound_session_voip_mode_e *mode)
867 {
868         int ret = MM_ERROR_NONE;
869         int session = 0;
870         int session_options = 0;
871
872         if (mode == NULL) {
873                 LOGE("mode is null");
874                 ret = MM_ERROR_INVALID_ARGUMENT;
875                 goto LEAVE;
876         }
877
878         ret = mm_session_get_current_information(&session, &session_options);
879         if (ret != MM_ERROR_NONE) {
880                 LOGI("session = %d, option = %d", session, session_options);
881                 goto LEAVE;
882         }
883
884         if (session != MM_SESSION_TYPE_VOIP || g_cached_session_mode == -1) {
885                 ret = MM_ERROR_POLICY_INTERNAL;
886                 goto LEAVE;
887         }
888
889         *mode = (sound_session_voip_mode_e)g_cached_session_mode;
890
891         LOGI("session=%d, mode=%d", session, *mode);
892
893 LEAVE:
894         return _convert_sound_manager_error_code(__func__, ret);
895 }
896
897 int sound_manager_set_session_interrupted_cb(sound_session_interrupted_cb callback, void *user_data)
898 {
899         int ret = MM_ERROR_NONE;
900         unsigned int subs_id = 0;
901
902         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_interrupt_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
903
904         if (callback == NULL) {
905                 ret = MM_ERROR_INVALID_ARGUMENT;
906                 goto LEAVE;
907         }
908
909         /* it is not supported both session and stream feature at the same time */
910         if (g_stream_info_count) {
911                 ret =  MM_ERROR_POLICY_INTERNAL;
912                 goto LEAVE;
913         }
914
915         if (g_session_interrupt_cb_table.user_cb == NULL) {
916                 ret = mm_sound_add_device_connected_callback(SOUND_DEVICE_ALL_MASK, (mm_sound_device_connected_cb)_device_connected_cb, NULL, &subs_id);
917                 if (ret)
918                         goto LEAVE;
919                 ret = mm_sound_focus_set_session_interrupt_callback((mm_sound_focus_session_interrupt_cb)_focus_session_interrupt_cb, NULL);
920                 if (ret) {
921                         if (mm_sound_remove_device_connected_callback(subs_id) != MM_ERROR_NONE)
922                                 LOGW("mm_sound_remove_device_connected_callback failed");
923                         goto LEAVE;
924                 }
925                 g_session_interrupt_cb_table.subs_id = subs_id;
926         }
927         g_session_interrupt_cb_table.user_cb = (sound_session_interrupted_cb)callback;
928         g_session_interrupt_cb_table.user_data = user_data;
929
930 LEAVE:
931         SM_LEAVE_CRITICAL_SECTION(&g_interrupt_cb_mutex);
932
933         return _convert_sound_manager_error_code(__func__, ret);
934 }
935
936 int sound_manager_unset_session_interrupted_cb(void)
937 {
938         int ret = MM_ERROR_NONE;
939
940         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_interrupt_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
941
942         if (!g_session_interrupt_cb_table.user_cb) {
943                 ret = MM_ERROR_SOUND_INTERNAL;
944                 goto LEAVE;
945         }
946
947         ret = mm_sound_focus_unset_session_interrupt_callback();
948         if (ret) {
949                 if (mm_sound_remove_device_connected_callback(g_session_interrupt_cb_table.subs_id) != MM_ERROR_NONE)
950                         LOGW("mm_sound_remove_device_connected_callback failed");
951                 goto LEAVE;
952         }
953
954         ret = mm_sound_remove_device_connected_callback(g_session_interrupt_cb_table.subs_id);
955         if (ret)
956                 goto LEAVE;
957
958         g_session_interrupt_cb_table.subs_id = 0;
959         g_session_interrupt_cb_table.user_cb = NULL;
960         g_session_interrupt_cb_table.user_data = NULL;
961
962 LEAVE:
963         SM_LEAVE_CRITICAL_SECTION(&g_interrupt_cb_mutex);
964
965         return _convert_sound_manager_error_code(__func__, ret);
966 }
967
968 int sound_manager_get_current_device_list(sound_device_mask_e device_mask, sound_device_list_h *device_list)
969 {
970         int ret = MM_ERROR_NONE;
971
972         ret = mm_sound_get_current_device_list((mm_sound_device_flags_e)device_mask, device_list);
973
974         return _convert_sound_manager_error_code(__func__, ret);
975 }
976
977 int sound_manager_free_device_list(sound_device_list_h device_list)
978 {
979         int ret = MM_ERROR_NONE;
980
981         ret = mm_sound_free_device_list(device_list);
982
983         return _convert_sound_manager_error_code(__func__, ret);
984 }
985
986 int sound_manager_get_next_device(sound_device_list_h device_list, sound_device_h *device)
987 {
988         int ret = MM_ERROR_NONE;
989
990         ret = mm_sound_get_next_device(device_list, device);
991
992         return _convert_sound_manager_error_code(__func__, ret);
993 }
994
995 int sound_manager_get_prev_device(sound_device_list_h device_list, sound_device_h *device)
996 {
997         int ret = MM_ERROR_NONE;
998
999         ret = mm_sound_get_prev_device(device_list, device);
1000
1001         return _convert_sound_manager_error_code(__func__, ret);
1002 }
1003
1004 int sound_manager_get_device_type(sound_device_h device, sound_device_type_e *type)
1005 {
1006         int ret = MM_ERROR_NONE;
1007
1008         ret = mm_sound_get_device_type(device, (mm_sound_device_type_e*)type);
1009
1010         return _convert_sound_manager_error_code(__func__, ret);
1011 }
1012
1013 int sound_manager_get_device_io_direction(sound_device_h device, sound_device_io_direction_e *io_direction)
1014 {
1015         int ret = MM_ERROR_NONE;
1016         mm_sound_device_io_direction_e mm_sound_io_direction;
1017
1018         ret = mm_sound_get_device_io_direction(device, &mm_sound_io_direction);
1019         if (ret == MM_ERROR_NONE)
1020                 ret = _convert_device_io_direction(mm_sound_io_direction, io_direction);
1021
1022         return _convert_sound_manager_error_code(__func__, ret);
1023 }
1024
1025 int sound_manager_get_device_id(sound_device_h device, int *id)
1026 {
1027         int ret = MM_ERROR_NONE;
1028
1029         ret = mm_sound_get_device_id(device, id);
1030
1031         return _convert_sound_manager_error_code(__func__, ret);
1032 }
1033
1034 int sound_manager_get_device_name(sound_device_h device, char **name)
1035 {
1036         int ret = MM_ERROR_NONE;
1037
1038         ret = mm_sound_get_device_name(device, name);
1039
1040         return _convert_sound_manager_error_code(__func__, ret);
1041 }
1042
1043 int sound_manager_get_device_state(sound_device_h device, sound_device_state_e *state)
1044 {
1045         int ret = MM_ERROR_NONE;
1046
1047         ret = mm_sound_get_device_state(device, (mm_sound_device_state_e*)state);
1048
1049         return _convert_sound_manager_error_code(__func__, ret);
1050 }
1051
1052 int sound_manager_set_device_connected_cb(sound_device_mask_e device_mask, sound_device_connected_cb callback, void *user_data)
1053 {
1054         int ret = MM_ERROR_NONE;
1055         unsigned int subs_id = 0;
1056
1057         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_device_conn_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
1058
1059         ret = mm_sound_add_device_connected_callback((mm_sound_device_flags_e)device_mask, (mm_sound_device_connected_cb)callback, user_data, &subs_id);
1060         if (ret == MM_ERROR_NONE) {
1061                 g_device_connected_cb_table.subs_id = subs_id;
1062                 g_device_connected_cb_table.user_cb = (sound_device_connected_cb)callback;
1063                 g_device_connected_cb_table.user_data = user_data;
1064         }
1065
1066         SM_LEAVE_CRITICAL_SECTION(&g_device_conn_cb_mutex);
1067
1068         return _convert_sound_manager_error_code(__func__, ret);
1069 }
1070
1071 int sound_manager_unset_device_connected_cb(void)
1072 {
1073         int ret = MM_ERROR_NONE;
1074
1075         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_device_conn_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
1076
1077         if (g_device_connected_cb_table.subs_id == 0) {
1078                 ret = MM_ERROR_SOUND_INTERNAL;
1079                 goto LEAVE;
1080         }
1081
1082         ret = mm_sound_remove_device_connected_callback(g_device_connected_cb_table.subs_id);
1083         if (ret == MM_ERROR_NONE) {
1084                 g_device_connected_cb_table.subs_id = 0;
1085                 g_device_connected_cb_table.user_cb = NULL;
1086                 g_device_connected_cb_table.user_data = NULL;
1087         }
1088
1089 LEAVE:
1090         SM_LEAVE_CRITICAL_SECTION(&g_device_conn_cb_mutex);
1091
1092         return _convert_sound_manager_error_code(__func__, ret);
1093 }
1094
1095 int sound_manager_set_device_information_changed_cb(sound_device_mask_e device_mask, sound_device_information_changed_cb callback, void *user_data)
1096 {
1097         int ret = MM_ERROR_NONE;
1098         unsigned int subs_id = 0;
1099
1100         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_device_info_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
1101
1102         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);
1103         if (ret == MM_ERROR_NONE) {
1104                 g_device_info_changed_cb_table.subs_id = subs_id;
1105                 g_device_info_changed_cb_table.user_cb = (sound_device_information_changed_cb)callback;
1106                 g_device_info_changed_cb_table.user_data = user_data;
1107         }
1108
1109         SM_LEAVE_CRITICAL_SECTION(&g_device_info_cb_mutex);
1110
1111         return _convert_sound_manager_error_code(__func__, ret);
1112 }
1113
1114 int sound_manager_unset_device_information_changed_cb(void)
1115 {
1116         int ret = MM_ERROR_NONE;
1117
1118         SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_device_info_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
1119
1120         if (g_device_info_changed_cb_table.subs_id == 0) {
1121                 ret = MM_ERROR_SOUND_INTERNAL;
1122                 goto LEAVE;
1123         }
1124
1125         ret = mm_sound_remove_device_information_changed_callback(g_device_info_changed_cb_table.subs_id);
1126         if (ret == MM_ERROR_NONE) {
1127                 g_device_info_changed_cb_table.subs_id = 0;
1128                 g_device_info_changed_cb_table.user_cb = NULL;
1129                 g_device_info_changed_cb_table.user_data = NULL;
1130         }
1131
1132 LEAVE:
1133         SM_LEAVE_CRITICAL_SECTION(&g_device_info_cb_mutex);
1134
1135         return _convert_sound_manager_error_code(__func__, ret);
1136 }
1137
1138 __attribute__ ((destructor))
1139 void __sound_manager_finalize(void)
1140 {
1141         int ret = MM_ERROR_NONE;
1142
1143         if (g_session_interrupt_cb_table.is_registered) {
1144                 LOGI("<ENTER>");
1145                 ret = mm_session_finish();
1146                 if (ret != MM_ERROR_NONE)
1147                         LOGE("[%s] failed to mm_session_finish(), ret(0x%x)", __func__, ret);
1148
1149                 g_session_interrupt_cb_table.is_registered = 0;
1150                 LOGI("<LEAVE>");
1151         }
1152 }
1153
1154 __attribute__ ((constructor))
1155 void __sound_manager_initialize(void)
1156 {
1157
1158 }