2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include "sound_manager.h"
18 #include "sound_manager_private.h"
19 #include <system_info.h>
21 #define FEATURE_MICROPHONE "http://tizen.org/feature/microphone"
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];
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;
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;
40 int sound_manager_get_max_volume(sound_type_e type, int *max)
42 const char *volume_type = NULL;
43 unsigned int max_level = 0;
44 int ret = MM_ERROR_NONE;
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);
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 */
57 return _convert_sound_manager_error_code(__func__, ret);
60 int sound_manager_set_volume(sound_type_e type, int volume)
62 int ret = MM_ERROR_NONE;
64 if (type >= SOUND_TYPE_NUM || type < 0)
65 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
67 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
69 ret = mm_sound_volume_set_value(type, volume);
70 LOGI("type=%d, volume=%d", type, volume);
72 return _convert_sound_manager_error_code(__func__, ret);
75 int sound_manager_get_volume(sound_type_e type, int *volume)
77 int ret = MM_ERROR_NONE;
80 if (type >= SOUND_TYPE_NUM || type < 0)
81 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
83 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
85 ret = mm_sound_volume_get_value(type, &uvolume);
86 if (ret == MM_ERROR_NONE)
89 LOGI("type=%d, volume=%d", type, *volume);
91 return _convert_sound_manager_error_code(__func__, ret);
94 int sound_manager_set_current_sound_type(sound_type_e type)
96 int ret = MM_ERROR_NONE;
98 LOGW("DEPRECATION WARNING: %s() is deprecated and will be removed from next release.", __func__);
99 if (type >= SOUND_TYPE_NUM || type < 0)
100 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
102 ret = mm_sound_volume_primary_type_set(type);
104 return _convert_sound_manager_error_code(__func__, ret);
107 int sound_manager_get_current_sound_type(sound_type_e *type)
109 int ret = MM_ERROR_NONE;
110 volume_type_t mm_sound_vol_type = VOLUME_TYPE_UNKNOWN;
111 char *volume_type = NULL;
114 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
116 ret = mm_sound_volume_primary_type_get(&mm_sound_vol_type);
117 if (ret == MM_ERROR_NONE) {
118 if (mm_sound_vol_type == VOLUME_TYPE_UNKNOWN) {
119 /* get the volume type of the current playing stream */
120 ret = _get_current_volume_type(DIRECTION_OUT_STR, &volume_type);
121 if (ret == MM_ERROR_NONE)
122 ret = _convert_sound_type_to_enum((const char*)volume_type, type);
124 *type = mm_sound_vol_type;
127 LOGI("type=%d", *type);
129 return _convert_sound_manager_error_code(__func__, ret);
132 int sound_manager_unset_current_sound_type(void)
134 int ret = MM_ERROR_NONE;
136 LOGW("DEPRECATION WARNING: %s() is deprecated and will be removed from next release.", __func__);
137 ret = mm_sound_volume_primary_type_set(VOLUME_TYPE_UNKNOWN);
139 return _convert_sound_manager_error_code(__func__, ret);
142 int sound_manager_set_volume_changed_cb(sound_manager_volume_changed_cb callback, void* user_data)
144 int ret = MM_ERROR_NONE;
145 unsigned int subs_id = 0;
147 SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_volume_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
149 ret = mm_sound_add_volume_changed_callback((mm_sound_volume_changed_cb)callback, user_data, &subs_id);
150 if (ret == MM_ERROR_NONE) {
151 g_volume_changed_cb_table.subs_id = subs_id;
152 g_volume_changed_cb_table.user_cb = (sound_manager_volume_changed_cb)callback;
153 g_volume_changed_cb_table.user_data = user_data;
156 SM_LEAVE_CRITICAL_SECTION(&g_volume_cb_mutex);
158 return _convert_sound_manager_error_code(__func__, ret);
161 int sound_manager_unset_volume_changed_cb(void)
163 int ret = MM_ERROR_NONE;
165 SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_volume_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
167 if (g_volume_changed_cb_table.subs_id > 0) {
168 ret = mm_sound_remove_volume_changed_callback(g_volume_changed_cb_table.subs_id);
169 if (ret == MM_ERROR_NONE) {
170 g_volume_changed_cb_table.subs_id = 0;
171 g_volume_changed_cb_table.user_cb = NULL;
172 g_volume_changed_cb_table.user_data = NULL;
175 ret = MM_ERROR_SOUND_INTERNAL;
178 SM_LEAVE_CRITICAL_SECTION(&g_volume_cb_mutex);
180 return _convert_sound_manager_error_code(__func__, ret);
183 int sound_manager_create_stream_information(sound_stream_type_e stream_type, sound_stream_focus_state_changed_cb callback, void *user_data, sound_stream_info_h *stream_info)
185 int ret = MM_ERROR_NONE;
189 SM_NULL_ARG_CHECK(stream_info);
191 if (g_session_interrupt_cb_table.is_registered)
192 return _convert_sound_manager_error_code(__func__, MM_ERROR_SOUND_INTERNAL);
194 SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_stream_info_count_mutex, MM_ERROR_SOUND_INTERNAL);
196 sound_stream_info_s *stream_h = malloc(sizeof(sound_stream_info_s));
198 ret = MM_ERROR_OUT_OF_MEMORY;
202 memset(stream_h, 0, sizeof(sound_stream_info_s));
203 ret = _convert_stream_type(stream_type, &stream_h->stream_type);
204 if (ret == MM_ERROR_NONE) {
205 ret = _make_pa_connection_and_register_focus(stream_h, callback, user_data);
206 if (ret == MM_ERROR_NONE) {
207 *stream_info = (sound_stream_info_h)stream_h;
208 SM_REF_FOR_STREAM_INFO(g_stream_info_count, ret);
209 LOGI("stream_h(%p), index(%u), user_cb(%p), cnt(%d), ret(0x%x)", stream_h, stream_h->index, stream_h->user_cb, g_stream_info_count, ret);
217 SM_LEAVE_CRITICAL_SECTION(&g_stream_info_count_mutex);
219 return _convert_sound_manager_error_code(__func__, ret);
222 int sound_manager_destroy_stream_information(sound_stream_info_h stream_info)
224 int ret = MM_ERROR_NONE;
225 sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
229 SM_INSTANCE_CHECK(stream_h);
231 SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_stream_info_count_mutex, MM_ERROR_SOUND_INTERNAL);
232 ret = _destroy_pa_connection_and_unregister_focus(stream_h);
233 if (ret == MM_ERROR_NONE) {
236 SM_UNREF_FOR_STREAM_INFO(g_stream_info_count);
238 SM_LEAVE_CRITICAL_SECTION(&g_stream_info_count_mutex);
240 LOGD("cnt(%d)", g_stream_info_count);
242 return _convert_sound_manager_error_code(__func__, ret);
245 int sound_manager_get_sound_type(sound_stream_info_h stream_info, sound_type_e *sound_type)
247 int ret = MM_ERROR_NONE;
248 sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
252 SM_INSTANCE_CHECK(stream_h);
253 SM_NULL_ARG_CHECK(sound_type);
255 if (stream_h->stream_conf_info.volume_type == NULL) {
256 ret = MM_ERROR_SOUND_NO_DATA;
260 ret = _convert_sound_type_to_enum(stream_h->stream_conf_info.volume_type, sound_type);
261 LOGI("sound type(%d)", *sound_type);
264 return _convert_sound_manager_error_code(__func__, ret);
267 int sound_manager_add_device_for_stream_routing(sound_stream_info_h stream_info, sound_device_h device)
269 int ret = MM_ERROR_NONE;
270 sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
274 ret = _add_device_for_stream_routing(stream_h, device);
276 return _convert_sound_manager_error_code(__func__, ret);
279 int sound_manager_remove_device_for_stream_routing(sound_stream_info_h stream_info, sound_device_h device)
281 int ret = MM_ERROR_NONE;
282 sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
286 ret = _remove_device_for_stream_routing(stream_h, device);
288 return _convert_sound_manager_error_code(__func__, ret);
291 int sound_manager_apply_stream_routing(sound_stream_info_h stream_info)
293 int ret = MM_ERROR_NONE;
294 sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
298 ret = _apply_stream_routing(stream_h);
300 return _convert_sound_manager_error_code(__func__, ret);
303 int sound_manager_set_focus_reacquisition(sound_stream_info_h stream_info, bool enable)
305 int ret = MM_ERROR_NONE;
306 sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
310 SM_INSTANCE_CHECK(stream_h);
312 ret = mm_sound_set_focus_reacquisition(stream_h->index, enable);
314 return _convert_sound_manager_error_code(__func__, ret);
317 int sound_manager_get_focus_reacquisition(sound_stream_info_h stream_info, bool *enabled)
319 int ret = MM_ERROR_NONE;
320 sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
324 SM_INSTANCE_CHECK(stream_h);
325 SM_NULL_ARG_CHECK(enabled);
327 ret = mm_sound_get_focus_reacquisition(stream_h->index, enabled);
329 return _convert_sound_manager_error_code(__func__, ret);
332 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)
334 int ret = MM_ERROR_NONE;
335 sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
339 SM_INSTANCE_CHECK(stream_h);
341 if (stream_h->is_focus_unavailable) {
342 LOGE("acquiring focus is not allowed for this strema type(%s)", stream_h->stream_type);
343 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
346 if (stream_h->user_cb == NULL) {
347 LOGE("focus state changed callback should be set before acquiring focus");
348 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
351 ret = mm_sound_acquire_focus_with_option(stream_h->index, (mm_sound_focus_type_e)focus_mask, sound_behavior, extra_info);
352 if (ret == MM_ERROR_NONE) {
353 stream_h->acquired_focus |= focus_mask;
354 _update_focus_status(stream_h->index, (unsigned int)stream_h->acquired_focus);
357 return _convert_sound_manager_error_code(__func__, ret);
360 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)
362 int ret = MM_ERROR_NONE;
363 sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
367 SM_INSTANCE_CHECK(stream_h);
369 ret = mm_sound_release_focus_with_option(stream_h->index, (mm_sound_focus_type_e)focus_mask, sound_behavior, extra_info);
370 if (ret == MM_ERROR_NONE) {
371 stream_h->acquired_focus &= ~focus_mask;
372 _update_focus_status(stream_h->index, (unsigned int)stream_h->acquired_focus);
375 return _convert_sound_manager_error_code(__func__, ret);
378 int sound_manager_get_focus_state(sound_stream_info_h stream_info, sound_stream_focus_state_e *state_for_playback, sound_stream_focus_state_e *state_for_recording)
380 int ret = MM_ERROR_NONE;
381 sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
385 SM_INSTANCE_CHECK(stream_h);
386 if (!state_for_playback && !state_for_recording) {
387 ret = MM_ERROR_INVALID_ARGUMENT;
391 if (state_for_playback)
392 *state_for_playback = ((stream_h->acquired_focus & SOUND_STREAM_FOCUS_FOR_PLAYBACK) ? (SOUND_STREAM_FOCUS_STATE_ACQUIRED) : (SOUND_STREAM_FOCUS_STATE_RELEASED));
393 if (state_for_recording)
394 *state_for_recording = ((stream_h->acquired_focus & SOUND_STREAM_FOCUS_FOR_RECORDING) ? (SOUND_STREAM_FOCUS_STATE_ACQUIRED) : (SOUND_STREAM_FOCUS_STATE_RELEASED));
396 LOGI("acquired_focus(0x%x)", stream_h->acquired_focus);
399 return _convert_sound_manager_error_code(__func__, ret);
402 int sound_manager_get_current_playback_focus(sound_stream_focus_change_reason_e *acquired_by, int *flags, char **extra_info)
404 int ret = MM_ERROR_NONE;
405 char *stream_type_str = NULL;
406 char *extra_info_str = NULL;
408 bool is_focus_cb_thread = false;
412 SM_NULL_ARG_CHECK(acquired_by);
413 SM_NULL_ARG_CHECK(flags);
415 if ((ret = mm_sound_focus_is_cb_thread(&is_focus_cb_thread)))
416 return _convert_sound_manager_error_code(__func__, ret);
418 if (is_focus_cb_thread) {
419 LOGE("this API should not be called in focus callback");
420 return SOUND_MANAGER_ERROR_INVALID_OPERATION;
423 ret = mm_sound_get_stream_type_of_acquired_focus((int)SOUND_STREAM_FOCUS_FOR_PLAYBACK, &stream_type_str, &option, &extra_info_str);
424 if (ret == MM_ERROR_NONE) {
425 LOGI("current acquired PLAYBACK focus : stream_type[%s]", stream_type_str);
426 ret = _convert_stream_type_to_change_reason(stream_type_str, acquired_by);
427 if (ret == MM_ERROR_NONE) {
428 LOGI(" : reason[%d], flags[0x%x], extra_info[%s]", *acquired_by, option, extra_info_str);
431 *extra_info = extra_info_str;
433 free(extra_info_str);
437 return _convert_sound_manager_error_code(__func__, ret);
440 int sound_manager_get_current_recording_focus(sound_stream_focus_change_reason_e *acquired_by, int *flags, char **extra_info)
442 int ret = MM_ERROR_NONE;
443 char *stream_type_str = NULL;
444 char *extra_info_str = NULL;
446 bool is_focus_cb_thread = false;
450 SM_NULL_ARG_CHECK(acquired_by);
451 SM_NULL_ARG_CHECK(flags);
453 if ((ret = mm_sound_focus_is_cb_thread(&is_focus_cb_thread)))
454 return _convert_sound_manager_error_code(__func__, ret);
456 if (is_focus_cb_thread) {
457 LOGE("this API should not be called in focus callback");
458 return SOUND_MANAGER_ERROR_INVALID_OPERATION;
461 ret = mm_sound_get_stream_type_of_acquired_focus((int)SOUND_STREAM_FOCUS_FOR_RECORDING, &stream_type_str, &option, &extra_info_str);
462 if (ret == MM_ERROR_NONE) {
463 LOGI("current acquired RECORDING focus : stream_type[%s]", stream_type_str);
464 ret = _convert_stream_type_to_change_reason(stream_type_str, acquired_by);
465 if (ret == MM_ERROR_NONE) {
466 LOGI(" : reason[%d], flags[0x%x], extra_info[%s]", *acquired_by, option, extra_info_str);
469 *extra_info = extra_info_str;
471 free(extra_info_str);
475 return _convert_sound_manager_error_code(__func__, ret);
478 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)
480 int ret = MM_ERROR_NONE;
485 SM_NULL_ARG_CHECK(callback);
486 SM_NULL_ARG_CHECK(id);
487 SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_stream_info_count_mutex, SOUND_MANAGER_ERROR_INTERNAL);
489 for (i = 0; i < SOUND_STREAM_INFO_ARR_MAX; i++)
490 if (focus_watch_info_arr[i].id == 0)
492 if (i == SOUND_STREAM_INFO_ARR_MAX) {
493 LOGE("focus watch info array is full");
494 ret = MM_ERROR_SOUND_INTERNAL;
498 ret = mm_sound_set_focus_watch_callback((mm_sound_focus_type_e)focus_mask, _focus_watch_callback, user_data, id);
499 if (ret == MM_ERROR_NONE) {
500 SM_REF_FOR_STREAM_INFO(g_stream_info_count, ret);
501 focus_watch_info_arr[i].id = *id;
502 focus_watch_info_arr[i].user_data = user_data;
503 focus_watch_info_arr[i].user_cb = callback;
507 SM_LEAVE_CRITICAL_SECTION(&g_stream_info_count_mutex);
509 LOGD("cnt(%d), id(%d)", g_stream_info_count, *id);
511 return _convert_sound_manager_error_code(__func__, ret);
514 int sound_manager_remove_focus_state_watch_cb(int id)
516 int ret = MM_ERROR_NONE;
521 SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_stream_info_count_mutex, SOUND_MANAGER_ERROR_INTERNAL);
523 for (i = 0; i < SOUND_STREAM_INFO_ARR_MAX; i++)
524 if (focus_watch_info_arr[i].id == id)
526 if (i == SOUND_STREAM_INFO_ARR_MAX) {
527 LOGE("cound not find item in focus watch info array for this id(%d)", id);
528 ret = MM_ERROR_INVALID_ARGUMENT;
532 ret = mm_sound_unset_focus_watch_callback(id);
533 if (ret == MM_ERROR_NONE) {
534 SM_UNREF_FOR_STREAM_INFO(g_stream_info_count);
535 focus_watch_info_arr[i].id = 0;
536 focus_watch_info_arr[i].user_data = NULL;
537 focus_watch_info_arr[i].user_cb = NULL;
541 SM_LEAVE_CRITICAL_SECTION(&g_stream_info_count_mutex);
543 LOGD("cnt(%d)", g_stream_info_count);
545 return _convert_sound_manager_error_code(__func__, ret);
548 int sound_manager_set_session_type(sound_session_type_e type)
550 int ret = MM_ERROR_NONE;
551 int cur_session = -1;
552 int new_session = MM_SESSION_TYPE_MEDIA;
553 bool mic_enable = false;
555 LOGW("DEPRECATION WARNING: %s() is deprecated and will be removed from next release. Use sound_manager_create_stream_information() instead.", __func__);
556 LOGI(">> enter : type=%d", type);
558 if (type < SOUND_SESSION_TYPE_MEDIA || type > SOUND_SESSION_TYPE_VOIP)
559 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
561 /* If session type is VOIP but MIC is not enabled, return false */
562 if (type == SOUND_SESSION_TYPE_VOIP) {
563 ret = system_info_get_platform_bool(FEATURE_MICROPHONE, &mic_enable);
564 LOGI("system_info_platform [%s]=[%d], ret[%d]", FEATURE_MICROPHONE, mic_enable, ret);
565 if (ret != SYSTEM_INFO_ERROR_NONE || !mic_enable)
566 return _convert_sound_manager_error_code(__func__, MM_ERROR_NOT_SUPPORT_API);
569 /* it is not supported both session and stream feature at the same time */
570 if (g_stream_info_count) {
571 LOGE("Could not set this type(%d) because of being used stream feature", type);
572 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
576 case SOUND_SESSION_TYPE_MEDIA:
577 new_session = MM_SESSION_TYPE_MEDIA;
579 case SOUND_SESSION_TYPE_ALARM:
580 new_session = MM_SESSION_TYPE_ALARM;
582 case SOUND_SESSION_TYPE_NOTIFICATION:
583 new_session = MM_SESSION_TYPE_NOTIFY;
585 case SOUND_SESSION_TYPE_EMERGENCY:
586 new_session = MM_SESSION_TYPE_EMERGENCY;
588 case SOUND_SESSION_TYPE_VOIP:
589 new_session = MM_SESSION_TYPE_VOIP;
593 /* valid session check */
594 ret = mm_session_get_current_type(&cur_session);
595 if (ret == MM_ERROR_NONE) {
596 if (cur_session == MM_SESSION_TYPE_MEDIA_RECORD) {
597 if (type > SOUND_SESSION_TYPE_MEDIA) {
598 LOGE("Could not set this type(%d) during camera/recorder/audio-io(in)/radio", type);
599 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
604 if (g_session_interrupt_cb_table.is_registered) {
605 if (new_session == cur_session ||
606 ((new_session == SOUND_SESSION_TYPE_MEDIA) && (cur_session == MM_SESSION_TYPE_MEDIA_RECORD))) {
607 LOGI("already set type=%d, ret=0x%x", type, ret);
608 return SOUND_MANAGER_ERROR_NONE;
610 ret = mm_session_finish();
611 if (ret != MM_ERROR_NONE)
612 return _convert_sound_manager_error_code(__func__, ret);
614 g_session_interrupt_cb_table.is_registered = 0;
615 if (cur_session == MM_SESSION_TYPE_VOIP) {
616 g_cached_session_mode = -1;
617 g_cached_voip_device_id = -1;
618 if (g_voip_vstream_h) {
619 _stop_virtual_stream(g_voip_vstream_h);
620 _destroy_virtual_stream(g_voip_vstream_h);
621 g_voip_vstream_h = NULL;
623 /*voip stream destruction*/
624 if (g_voip_stream_info) {
625 ret = _destroy_pa_connection_and_unregister_focus(g_voip_stream_info);
626 free(g_voip_stream_info);
627 g_voip_stream_info = NULL;
628 if (ret != MM_ERROR_NONE)
629 return _convert_sound_manager_error_code(__func__, ret);
634 ret = mm_session_init(new_session);
635 if (ret == MM_ERROR_NONE)
636 g_session_interrupt_cb_table.is_registered = 1;
638 LOGI("type=%d", type);
640 return _convert_sound_manager_error_code(__func__, ret);
643 int sound_manager_get_session_type(sound_session_type_e *type)
645 int ret = MM_ERROR_NONE;
648 LOGW("DEPRECATION WARNING: %s() is deprecated and will be removed from next release.", __func__);
650 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
652 ret = mm_session_get_current_type(&cur_session);
653 if (ret != MM_ERROR_NONE) {
654 LOGW("session hasn't been set, setting default session");
655 cur_session = SOUND_SESSION_TYPE_DEFAULT;
656 ret = mm_session_init(cur_session);
657 if (ret == MM_ERROR_NONE)
658 g_session_interrupt_cb_table.is_registered = 1;
660 if ((cur_session > MM_SESSION_TYPE_EMERGENCY) &&
661 (cur_session != MM_SESSION_TYPE_VOIP)) {
662 if (g_cached_session != -1)
663 cur_session = g_cached_session;
664 else /* will be never reached here. just prevent code */
665 cur_session = SOUND_SESSION_TYPE_DEFAULT;
668 switch (cur_session) {
669 case MM_SESSION_TYPE_MEDIA:
670 case MM_SESSION_TYPE_MEDIA_RECORD:
671 *type = SOUND_SESSION_TYPE_MEDIA;
673 case MM_SESSION_TYPE_ALARM:
674 *type = SOUND_SESSION_TYPE_ALARM;
676 case MM_SESSION_TYPE_NOTIFY:
677 *type = SOUND_SESSION_TYPE_NOTIFICATION;
679 case MM_SESSION_TYPE_EMERGENCY:
680 *type = SOUND_SESSION_TYPE_EMERGENCY;
682 case MM_SESSION_TYPE_VOIP:
683 *type = SOUND_SESSION_TYPE_VOIP;
690 LOGI("type=%d", *type);
692 return SOUND_MANAGER_ERROR_NONE;
695 int sound_manager_set_media_session_option(sound_session_option_for_starting_e s_option, sound_session_option_for_during_play_e d_option)
697 int ret = MM_ERROR_NONE;
699 int session_option = 0;
702 LOGW("DEPRECATION WARNING: %s() is deprecated and will be removed from next release. Use sound_manager_create_stream_information() instead.", __func__);
703 LOGI(">> enter : option for starting=%d, for during play=%d", s_option, d_option);
705 if (s_option < 0 || s_option > SOUND_SESSION_OPTION_PAUSE_OTHERS_WHEN_START)
706 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
707 if (d_option < 0 || d_option > SOUND_SESSION_OPTION_UNINTERRUPTIBLE_DURING_PLAY)
708 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
710 ret = mm_session_get_current_information(&session, &session_option);
711 if (ret != 0 || !g_session_interrupt_cb_table.is_registered) {
712 LOGW("session hasn't been set, setting default session");
713 ret = mm_session_init(MM_SESSION_TYPE_MEDIA);
715 g_session_interrupt_cb_table.is_registered = 1;
717 } else if (ret == 0 && session > MM_SESSION_TYPE_MEDIA) {
718 if (session == MM_SESSION_TYPE_MEDIA_RECORD) {
719 if (!g_session_interrupt_cb_table.is_registered) {
720 LOGE("Already set by camera/recorder/audio-io(in)/radio API, but need to set session to Media first");
721 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
724 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
729 case SOUND_SESSION_OPTION_MIX_WITH_OTHERS_WHEN_START:
730 if (session_option & MM_SESSION_OPTION_PAUSE_OTHERS) {
731 ret = mm_session_update_option(MM_SESSION_UPDATE_TYPE_REMOVE, MM_SESSION_OPTION_PAUSE_OTHERS);
733 return _convert_sound_manager_error_code(__func__, ret);
738 case SOUND_SESSION_OPTION_PAUSE_OTHERS_WHEN_START:
739 if (!(session_option & MM_SESSION_OPTION_PAUSE_OTHERS)) {
740 ret = mm_session_update_option(MM_SESSION_UPDATE_TYPE_ADD, MM_SESSION_OPTION_PAUSE_OTHERS);
742 return _convert_sound_manager_error_code(__func__, ret);
750 case SOUND_SESSION_OPTION_INTERRUPTIBLE_DURING_PLAY:
751 if (session_option & MM_SESSION_OPTION_UNINTERRUPTIBLE) {
752 ret = mm_session_update_option(MM_SESSION_UPDATE_TYPE_REMOVE, MM_SESSION_OPTION_UNINTERRUPTIBLE);
754 return _convert_sound_manager_error_code(__func__, ret);
759 case SOUND_SESSION_OPTION_UNINTERRUPTIBLE_DURING_PLAY:
760 if (!(session_option & MM_SESSION_OPTION_UNINTERRUPTIBLE)) {
761 ret = mm_session_update_option(MM_SESSION_UPDATE_TYPE_ADD, MM_SESSION_OPTION_UNINTERRUPTIBLE);
763 return _convert_sound_manager_error_code(__func__, ret);
773 LOGI("already set same option(%x), skip it", session_option);
775 return _convert_sound_manager_error_code(__func__, ret);
778 int sound_manager_get_media_session_option(sound_session_option_for_starting_e *s_option, sound_session_option_for_during_play_e *d_option)
780 int ret = MM_ERROR_NONE;
782 int session_options = 0;
784 LOGW("DEPRECATION WARNING: %s() is deprecated and will be removed from next release. Use sound_manager_create_stream_information() instead.", __func__);
787 if (s_option == NULL || d_option == NULL)
788 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
790 ret = mm_session_get_current_information(&session, &session_options);
792 ret = mm_session_init(MM_SESSION_TYPE_MEDIA);
794 g_session_interrupt_cb_table.is_registered = 1;
796 } else if (session > SOUND_SESSION_TYPE_MEDIA) {
797 if (session == MM_SESSION_TYPE_MEDIA_RECORD) {
798 if (!g_session_interrupt_cb_table.is_registered) {
799 LOGE("Already set by camera/recorder/audio-io(in)/radio API, but need to set session to Media first");
800 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
803 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
806 if (session_options & MM_SESSION_OPTION_PAUSE_OTHERS)
807 *s_option = SOUND_SESSION_OPTION_PAUSE_OTHERS_WHEN_START;
809 *s_option = SOUND_SESSION_OPTION_MIX_WITH_OTHERS_WHEN_START;
811 if (session_options & MM_SESSION_OPTION_UNINTERRUPTIBLE)
812 *d_option = SOUND_SESSION_OPTION_UNINTERRUPTIBLE_DURING_PLAY;
814 *d_option = SOUND_SESSION_OPTION_INTERRUPTIBLE_DURING_PLAY;
816 LOGI(" option for starting=%d, for during play=%d", *s_option, *d_option);
818 return SOUND_MANAGER_ERROR_NONE;
821 int sound_manager_set_media_session_resumption_option(sound_session_option_for_resumption_e option)
823 int ret = MM_ERROR_NONE;
825 int session_option = 0;
828 LOGW("DEPRECATION WARNING: %s() is deprecated and will be removed from next release. Use sound_manager_create_stream_information() instead.", __func__);
829 LOGI(">> enter : option for resumption=%d (0:by system, 1:by system or media paused)", option);
831 if (option < SOUND_SESSION_OPTION_RESUMPTION_BY_SYSTEM || option > SOUND_SESSION_OPTION_RESUMPTION_BY_SYSTEM_OR_MEDIA_PAUSED)
832 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
834 ret = mm_session_get_current_information(&session, &session_option);
835 if (ret != 0 || !g_session_interrupt_cb_table.is_registered) {
836 LOGW("session hasn't been set, setting default session");
837 ret = mm_session_init(MM_SESSION_TYPE_MEDIA);
839 g_session_interrupt_cb_table.is_registered = 1;
841 } else if (ret == 0 && session > MM_SESSION_TYPE_MEDIA) {
842 if (session == MM_SESSION_TYPE_MEDIA_RECORD) {
843 if (!g_session_interrupt_cb_table.is_registered) {
844 LOGE("Already set by camera/recorder/audio-io(in)/radio API, but need to set session to Media first");
845 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
848 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
853 case SOUND_SESSION_OPTION_RESUMPTION_BY_SYSTEM:
854 if (session_option & MM_SESSION_OPTION_RESUME_BY_SYSTEM_OR_MEDIA_PAUSED) {
855 ret = mm_session_update_option(MM_SESSION_UPDATE_TYPE_REMOVE, MM_SESSION_OPTION_RESUME_BY_SYSTEM_OR_MEDIA_PAUSED);
857 return _convert_sound_manager_error_code(__func__, ret);
862 case SOUND_SESSION_OPTION_RESUMPTION_BY_SYSTEM_OR_MEDIA_PAUSED:
863 if (!(session_option & MM_SESSION_OPTION_RESUME_BY_SYSTEM_OR_MEDIA_PAUSED)) {
864 ret = mm_session_update_option(MM_SESSION_UPDATE_TYPE_ADD, MM_SESSION_OPTION_RESUME_BY_SYSTEM_OR_MEDIA_PAUSED);
866 return _convert_sound_manager_error_code(__func__, ret);
876 LOGI("already set same option(0x%x), skip it", session_option);
878 return _convert_sound_manager_error_code(__func__, ret);
881 int sound_manager_get_media_session_resumption_option(sound_session_option_for_resumption_e *option)
883 int ret = MM_ERROR_NONE;
885 int session_options = 0;
887 LOGW("DEPRECATION WARNING: %s() is deprecated and will be removed from next release. Use sound_manager_create_stream_information() instead.", __func__);
891 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
893 ret = mm_session_get_current_information(&session, &session_options);
895 LOGW("session hasn't been set, setting default session");
896 ret = mm_session_init(MM_SESSION_TYPE_MEDIA);
898 g_session_interrupt_cb_table.is_registered = 1;
900 } else if (session > SOUND_SESSION_TYPE_MEDIA) {
901 if (session == MM_SESSION_TYPE_MEDIA_RECORD) {
902 if (!g_session_interrupt_cb_table.is_registered) {
903 LOGE("Already set by camera/recorder/audio-io(in)/radio API, but need to set session to Media first");
904 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
907 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
910 if (session_options & MM_SESSION_OPTION_RESUME_BY_SYSTEM_OR_MEDIA_PAUSED)
911 *option = SOUND_SESSION_OPTION_RESUMPTION_BY_SYSTEM_OR_MEDIA_PAUSED;
913 *option = SOUND_SESSION_OPTION_RESUMPTION_BY_SYSTEM;
915 LOGI("option for resumption=%d (0:by system, 1:by system or media paused)", *option);
917 return SOUND_MANAGER_ERROR_NONE;
920 int sound_manager_set_voip_session_mode(sound_session_voip_mode_e mode)
922 int ret = MM_ERROR_NONE;
924 int session_options = 0;
926 LOGW("DEPRECATION WARNING: %s() is deprecated and will be removed from next release. Use sound_manager_create_stream_information() instead.", __func__);
927 LOGI(">> enter : mode=%d", mode);
929 ret = mm_session_get_current_information(&session, &session_options);
930 if (ret != MM_ERROR_NONE)
933 if (session != MM_SESSION_TYPE_VOIP) {
934 ret = MM_ERROR_POLICY_INTERNAL;
938 if (mode < SOUND_SESSION_VOIP_MODE_RINGTONE || mode > SOUND_SESSION_VOIP_MODE_VOICE_WITH_BLUETOOTH) {
939 ret = MM_ERROR_INVALID_ARGUMENT;
943 ret = _set_session_mode((_session_mode_e)mode);
945 LOGI("session=%d, mode=%d", session, mode);
948 return _convert_sound_manager_error_code(__func__, ret);
951 int sound_manager_get_voip_session_mode(sound_session_voip_mode_e *mode)
953 int ret = MM_ERROR_NONE;
955 int session_options = 0;
957 LOGW("DEPRECATION WARNING: %s() is deprecated and will be removed from next release. Use sound_manager_create_stream_information() instead.", __func__);
959 LOGE("mode is null");
960 ret = MM_ERROR_INVALID_ARGUMENT;
964 ret = mm_session_get_current_information(&session, &session_options);
965 if (ret != MM_ERROR_NONE) {
966 LOGI("session = %d, option = %d", session, session_options);
970 if (session != MM_SESSION_TYPE_VOIP || g_cached_session_mode == -1) {
971 ret = MM_ERROR_POLICY_INTERNAL;
975 *mode = (sound_session_voip_mode_e)g_cached_session_mode;
977 LOGI("session=%d, mode=%d", session, *mode);
980 return _convert_sound_manager_error_code(__func__, ret);
983 int sound_manager_set_session_interrupted_cb(sound_session_interrupted_cb callback, void *user_data)
985 int ret = MM_ERROR_NONE;
986 unsigned int subs_id = 0;
988 LOGW("DEPRECATION WARNING: %s() is deprecated and will be removed from next release. Use sound_manager_create_stream_information() instead.", __func__);
989 SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_interrupt_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
991 if (callback == NULL) {
992 ret = MM_ERROR_INVALID_ARGUMENT;
996 /* it is not supported both session and stream feature at the same time */
997 if (g_stream_info_count) {
998 ret = MM_ERROR_POLICY_INTERNAL;
1002 if (g_session_interrupt_cb_table.user_cb == NULL) {
1003 ret = mm_sound_add_device_connected_callback(SOUND_DEVICE_ALL_MASK, (mm_sound_device_connected_cb)_device_connected_cb, NULL, &subs_id);
1006 ret = mm_sound_focus_set_session_interrupt_callback((mm_sound_focus_session_interrupt_cb)_focus_session_interrupt_cb, NULL);
1008 if (mm_sound_remove_device_connected_callback(subs_id) != MM_ERROR_NONE)
1009 LOGW("mm_sound_remove_device_connected_callback failed");
1012 g_session_interrupt_cb_table.subs_id = subs_id;
1014 g_session_interrupt_cb_table.user_cb = (sound_session_interrupted_cb)callback;
1015 g_session_interrupt_cb_table.user_data = user_data;
1018 SM_LEAVE_CRITICAL_SECTION(&g_interrupt_cb_mutex);
1020 return _convert_sound_manager_error_code(__func__, ret);
1023 int sound_manager_unset_session_interrupted_cb(void)
1025 int ret = MM_ERROR_NONE;
1027 LOGW("DEPRECATION WARNING: %s() is deprecated and will be removed from next release.", __func__);
1028 SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_interrupt_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
1030 if (!g_session_interrupt_cb_table.user_cb) {
1031 ret = MM_ERROR_SOUND_INTERNAL;
1035 ret = mm_sound_focus_unset_session_interrupt_callback();
1037 if (mm_sound_remove_device_connected_callback(g_session_interrupt_cb_table.subs_id) != MM_ERROR_NONE)
1038 LOGW("mm_sound_remove_device_connected_callback failed");
1042 ret = mm_sound_remove_device_connected_callback(g_session_interrupt_cb_table.subs_id);
1046 g_session_interrupt_cb_table.subs_id = 0;
1047 g_session_interrupt_cb_table.user_cb = NULL;
1048 g_session_interrupt_cb_table.user_data = NULL;
1051 SM_LEAVE_CRITICAL_SECTION(&g_interrupt_cb_mutex);
1053 return _convert_sound_manager_error_code(__func__, ret);
1056 int sound_manager_get_current_device_list(sound_device_mask_e device_mask, sound_device_list_h *device_list)
1058 int ret = MM_ERROR_NONE;
1060 LOGW("DEPRECATION WARNING: %s() is deprecated and will be removed from next release. Use sound_manager_get_device_list() instead.", __func__);
1061 ret = mm_sound_get_device_list(device_mask, device_list);
1063 return _convert_sound_manager_error_code(__func__, ret);
1066 int sound_manager_get_device_list(int device_mask, sound_device_list_h *device_list)
1068 int ret = MM_ERROR_NONE;
1070 ret = mm_sound_get_device_list(device_mask, device_list);
1072 return _convert_sound_manager_error_code(__func__, ret);
1075 int sound_manager_free_device_list(sound_device_list_h device_list)
1077 int ret = MM_ERROR_NONE;
1079 ret = mm_sound_free_device_list(device_list);
1081 return _convert_sound_manager_error_code(__func__, ret);
1084 int sound_manager_get_next_device(sound_device_list_h device_list, sound_device_h *device)
1086 int ret = MM_ERROR_NONE;
1088 ret = mm_sound_get_next_device(device_list, device);
1090 return _convert_sound_manager_error_code(__func__, ret);
1093 int sound_manager_get_prev_device(sound_device_list_h device_list, sound_device_h *device)
1095 int ret = MM_ERROR_NONE;
1097 ret = mm_sound_get_prev_device(device_list, device);
1099 return _convert_sound_manager_error_code(__func__, ret);
1102 int sound_manager_get_device_type(sound_device_h device, sound_device_type_e *type)
1104 int ret = MM_ERROR_NONE;
1105 mm_sound_device_type_e mm_sound_device_type;
1107 ret = mm_sound_get_device_type(device, &mm_sound_device_type);
1108 if (ret == MM_ERROR_NONE)
1109 _convert_device_type(mm_sound_device_type, type);
1111 return _convert_sound_manager_error_code(__func__, ret);
1114 int sound_manager_get_device_io_direction(sound_device_h device, sound_device_io_direction_e *io_direction)
1116 int ret = MM_ERROR_NONE;
1117 mm_sound_device_io_direction_e mm_sound_io_direction;
1119 ret = mm_sound_get_device_io_direction(device, &mm_sound_io_direction);
1120 if (ret == MM_ERROR_NONE)
1121 ret = _convert_device_io_direction(mm_sound_io_direction, io_direction);
1123 return _convert_sound_manager_error_code(__func__, ret);
1126 int sound_manager_get_device_id(sound_device_h device, int *id)
1128 int ret = MM_ERROR_NONE;
1130 ret = mm_sound_get_device_id(device, id);
1132 return _convert_sound_manager_error_code(__func__, ret);
1135 int sound_manager_get_device_name(sound_device_h device, char **name)
1137 int ret = MM_ERROR_NONE;
1139 ret = mm_sound_get_device_name(device, name);
1141 return _convert_sound_manager_error_code(__func__, ret);
1144 int sound_manager_get_device_state(sound_device_h device, sound_device_state_e *state)
1146 int ret = MM_ERROR_NONE;
1148 ret = mm_sound_get_device_state(device, (mm_sound_device_state_e*)state);
1150 return _convert_sound_manager_error_code(__func__, ret);
1153 int sound_manager_get_bt_device_avail_modes(sound_device_h device, int *modes)
1155 int ret = MM_ERROR_NONE;
1156 sound_device_type_e device_type;
1157 mm_sound_device_type_e mm_sound_device_type;
1159 if (!device || !modes)
1160 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
1162 ret = mm_sound_get_device_type(device, (mm_sound_device_type_e*)&mm_sound_device_type);
1163 if (ret == MM_ERROR_NONE)
1164 _convert_device_type(mm_sound_device_type, &device_type);
1165 if (ret != MM_ERROR_NONE)
1167 if (device_type != SOUND_DEVICE_BLUETOOTH_MEDIA && device_type != SOUND_DEVICE_BLUETOOTH_VOICE) {
1168 ret = MM_ERROR_INVALID_ARGUMENT;
1172 /* temporary code, this API should be removed */
1173 *modes = SOUND_DEVICE_BLUETOOTH_MODE_MEDIA | SOUND_DEVICE_BLUETOOTH_MODE_VOICE;
1176 return _convert_sound_manager_error_code(__func__, ret);
1179 int sound_manager_set_device_connected_cb(sound_device_mask_e device_mask, sound_device_connected_cb callback, void *user_data)
1181 int ret = MM_ERROR_NONE;
1182 unsigned int subs_id = 0;
1184 SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_device_conn_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
1186 ret = mm_sound_add_device_connected_callback((mm_sound_device_flags_e)device_mask, (mm_sound_device_connected_cb)callback, user_data, &subs_id);
1187 if (ret == MM_ERROR_NONE) {
1188 g_device_connected_cb_table.subs_id = subs_id;
1189 g_device_connected_cb_table.user_cb = (sound_device_connected_cb)callback;
1190 g_device_connected_cb_table.user_data = user_data;
1193 SM_LEAVE_CRITICAL_SECTION(&g_device_conn_cb_mutex);
1195 return _convert_sound_manager_error_code(__func__, ret);
1198 int sound_manager_unset_device_connected_cb(void)
1200 int ret = MM_ERROR_NONE;
1202 SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_device_conn_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
1204 if (g_device_connected_cb_table.subs_id == 0) {
1205 ret = MM_ERROR_SOUND_INTERNAL;
1209 ret = mm_sound_remove_device_connected_callback(g_device_connected_cb_table.subs_id);
1210 if (ret == MM_ERROR_NONE) {
1211 g_device_connected_cb_table.subs_id = 0;
1212 g_device_connected_cb_table.user_cb = NULL;
1213 g_device_connected_cb_table.user_data = NULL;
1217 SM_LEAVE_CRITICAL_SECTION(&g_device_conn_cb_mutex);
1219 return _convert_sound_manager_error_code(__func__, ret);
1222 int sound_manager_set_device_information_changed_cb(sound_device_mask_e device_mask, sound_device_information_changed_cb callback, void *user_data)
1224 int ret = MM_ERROR_NONE;
1225 unsigned int subs_id = 0;
1227 SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_device_info_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
1229 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);
1230 if (ret == MM_ERROR_NONE) {
1231 g_device_info_changed_cb_table.subs_id = subs_id;
1232 g_device_info_changed_cb_table.user_cb = (sound_device_information_changed_cb)callback;
1233 g_device_info_changed_cb_table.user_data = user_data;
1236 SM_LEAVE_CRITICAL_SECTION(&g_device_info_cb_mutex);
1238 return _convert_sound_manager_error_code(__func__, ret);
1241 int sound_manager_unset_device_information_changed_cb(void)
1243 int ret = MM_ERROR_NONE;
1245 SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_device_info_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
1247 if (g_device_info_changed_cb_table.subs_id == 0) {
1248 ret = MM_ERROR_SOUND_INTERNAL;
1252 ret = mm_sound_remove_device_information_changed_callback(g_device_info_changed_cb_table.subs_id);
1253 if (ret == MM_ERROR_NONE) {
1254 g_device_info_changed_cb_table.subs_id = 0;
1255 g_device_info_changed_cb_table.user_cb = NULL;
1256 g_device_info_changed_cb_table.user_data = NULL;
1260 SM_LEAVE_CRITICAL_SECTION(&g_device_info_cb_mutex);
1262 return _convert_sound_manager_error_code(__func__, ret);
1265 __attribute__ ((destructor))
1266 void __sound_manager_finalize(void)
1268 int ret = MM_ERROR_NONE;
1270 if (g_session_interrupt_cb_table.is_registered) {
1272 ret = mm_session_finish();
1273 if (ret != MM_ERROR_NONE)
1274 LOGE("[%s] failed to mm_session_finish(), ret(0x%x)", __func__, ret);
1276 g_session_interrupt_cb_table.is_registered = 0;
1281 __attribute__ ((constructor))
1282 void __sound_manager_initialize(void)