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 if (type >= SOUND_TYPE_NUM || type < 0)
99 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
101 ret = mm_sound_volume_primary_type_set(type);
103 return _convert_sound_manager_error_code(__func__, ret);
106 int sound_manager_get_current_sound_type(sound_type_e *type)
108 int ret = MM_ERROR_NONE;
109 volume_type_t mm_sound_vol_type = VOLUME_TYPE_UNKNOWN;
110 char *volume_type = NULL;
113 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
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);
123 *type = mm_sound_vol_type;
126 LOGI("type=%d", *type);
128 return _convert_sound_manager_error_code(__func__, ret);
131 int sound_manager_unset_current_sound_type(void)
133 int ret = MM_ERROR_NONE;
135 ret = mm_sound_volume_primary_type_set(VOLUME_TYPE_UNKNOWN);
137 return _convert_sound_manager_error_code(__func__, ret);
140 int sound_manager_set_volume_changed_cb(sound_manager_volume_changed_cb callback, void* user_data)
142 int ret = MM_ERROR_NONE;
143 unsigned int subs_id = 0;
145 SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_volume_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
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;
154 SM_LEAVE_CRITICAL_SECTION(&g_volume_cb_mutex);
156 return _convert_sound_manager_error_code(__func__, ret);
159 int sound_manager_unset_volume_changed_cb(void)
161 int ret = MM_ERROR_NONE;
163 SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_volume_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
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;
173 ret = MM_ERROR_SOUND_INTERNAL;
176 SM_LEAVE_CRITICAL_SECTION(&g_volume_cb_mutex);
178 return _convert_sound_manager_error_code(__func__, ret);
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)
183 int ret = MM_ERROR_NONE;
187 SM_NULL_ARG_CHECK(stream_info);
189 if (g_session_interrupt_cb_table.is_registered)
190 return _convert_sound_manager_error_code(__func__, MM_ERROR_SOUND_INTERNAL);
192 SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_stream_info_count_mutex, MM_ERROR_SOUND_INTERNAL);
194 sound_stream_info_s *stream_h = malloc(sizeof(sound_stream_info_s));
196 ret = MM_ERROR_OUT_OF_MEMORY;
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);
215 SM_LEAVE_CRITICAL_SECTION(&g_stream_info_count_mutex);
217 return _convert_sound_manager_error_code(__func__, ret);
220 int sound_manager_destroy_stream_information(sound_stream_info_h stream_info)
222 int ret = MM_ERROR_NONE;
223 sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
227 SM_INSTANCE_CHECK(stream_h);
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) {
234 SM_UNREF_FOR_STREAM_INFO(g_stream_info_count);
236 SM_LEAVE_CRITICAL_SECTION(&g_stream_info_count_mutex);
238 LOGD("cnt(%d)", g_stream_info_count);
240 return _convert_sound_manager_error_code(__func__, ret);
243 int sound_manager_get_sound_type(sound_stream_info_h stream_info, sound_type_e *sound_type)
245 int ret = MM_ERROR_NONE;
246 sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
250 SM_INSTANCE_CHECK(stream_h);
251 SM_NULL_ARG_CHECK(sound_type);
253 if (stream_h->stream_conf_info.volume_type == NULL) {
254 ret = MM_ERROR_SOUND_NO_DATA;
258 ret = _convert_sound_type_to_enum(stream_h->stream_conf_info.volume_type, sound_type);
259 LOGI("sound type(%d)", *sound_type);
262 return _convert_sound_manager_error_code(__func__, ret);
265 int sound_manager_add_device_for_stream_routing(sound_stream_info_h stream_info, sound_device_h device)
267 int ret = MM_ERROR_NONE;
268 sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
272 ret = _add_device_for_stream_routing(stream_h, device);
274 return _convert_sound_manager_error_code(__func__, ret);
277 int sound_manager_remove_device_for_stream_routing(sound_stream_info_h stream_info, sound_device_h device)
279 int ret = MM_ERROR_NONE;
280 sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
284 ret = _remove_device_for_stream_routing(stream_h, device);
286 return _convert_sound_manager_error_code(__func__, ret);
289 int sound_manager_apply_stream_routing(sound_stream_info_h stream_info)
291 int ret = MM_ERROR_NONE;
292 sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
296 ret = _apply_stream_routing(stream_h);
298 return _convert_sound_manager_error_code(__func__, ret);
301 int sound_manager_set_focus_reacquisition(sound_stream_info_h stream_info, bool enable)
303 int ret = MM_ERROR_NONE;
304 sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
308 SM_INSTANCE_CHECK(stream_h);
310 ret = mm_sound_set_focus_reacquisition(stream_h->index, enable);
312 return _convert_sound_manager_error_code(__func__, ret);
315 int sound_manager_get_focus_reacquisition(sound_stream_info_h stream_info, bool *enabled)
317 int ret = MM_ERROR_NONE;
318 sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
322 SM_INSTANCE_CHECK(stream_h);
323 SM_NULL_ARG_CHECK(enabled);
325 ret = mm_sound_get_focus_reacquisition(stream_h->index, enabled);
327 return _convert_sound_manager_error_code(__func__, ret);
330 int sound_manager_acquire_focus(sound_stream_info_h stream_info, sound_stream_focus_mask_e focus_mask, const char *extra_info)
332 int ret = MM_ERROR_NONE;
333 sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
337 SM_INSTANCE_CHECK(stream_h);
339 if (stream_h->is_focus_unavailable) {
340 LOGE("acquiring focus is not allowed for this strema type(%s)", stream_h->stream_type);
341 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
344 if (stream_h->user_cb == NULL) {
345 LOGE("focus state changed callback should be set before acquiring focus");
346 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
349 ret = mm_sound_acquire_focus_with_option(stream_h->index, (mm_sound_focus_type_e)focus_mask, stream_h->requesting_flags, extra_info);
350 if (ret == MM_ERROR_NONE) {
351 stream_h->acquired_focus |= focus_mask;
352 _update_focus_status(stream_h->index, (unsigned int)stream_h->acquired_focus);
355 return _convert_sound_manager_error_code(__func__, ret);
358 int sound_manager_release_focus(sound_stream_info_h stream_info, sound_stream_focus_mask_e focus_mask, const char *extra_info)
360 int ret = MM_ERROR_NONE;
361 sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
365 SM_INSTANCE_CHECK(stream_h);
367 ret = mm_sound_release_focus_with_option(stream_h->index, (mm_sound_focus_type_e)focus_mask, stream_h->requesting_flags, extra_info);
368 if (ret == MM_ERROR_NONE) {
369 stream_h->acquired_focus &= ~focus_mask;
370 _update_focus_status(stream_h->index, (unsigned int)stream_h->acquired_focus);
373 return _convert_sound_manager_error_code(__func__, ret);
376 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)
378 int ret = MM_ERROR_NONE;
379 sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
383 SM_INSTANCE_CHECK(stream_h);
384 if (!state_for_playback && !state_for_recording) {
385 ret = MM_ERROR_INVALID_ARGUMENT;
389 if (state_for_playback)
390 *state_for_playback = ((stream_h->acquired_focus & SOUND_STREAM_FOCUS_FOR_PLAYBACK) ? (SOUND_STREAM_FOCUS_STATE_ACQUIRED) : (SOUND_STREAM_FOCUS_STATE_RELEASED));
391 if (state_for_recording)
392 *state_for_recording = ((stream_h->acquired_focus & SOUND_STREAM_FOCUS_FOR_RECORDING) ? (SOUND_STREAM_FOCUS_STATE_ACQUIRED) : (SOUND_STREAM_FOCUS_STATE_RELEASED));
394 LOGI("acquired_focus(0x%x)", stream_h->acquired_focus);
397 return _convert_sound_manager_error_code(__func__, ret);
400 int sound_manager_focus_set_requesting_behavior(sound_stream_info_h stream_info, int flags)
402 sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
406 SM_INSTANCE_CHECK(stream_h);
407 SM_RANGE_ARG_CHECK(flags,
409 (SOUND_BEHAVIOR_NO_RESUME|SOUND_BEHAVIOR_FADING));
411 stream_h->requesting_flags = flags;
413 LOGI("the requesting sound behavior(0x%x) is set", stream_h->requesting_flags);
415 return SOUND_MANAGER_ERROR_NONE;
418 int sound_manager_focus_get_requesting_behavior(sound_stream_info_h stream_info, int *flags)
420 sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
424 SM_INSTANCE_CHECK(stream_h);
425 SM_NULL_ARG_CHECK(flags);
427 *flags = stream_h->requesting_flags;
429 LOGI("the requesting sound behavior is (0x%x)", stream_h->requesting_flags);
431 return SOUND_MANAGER_ERROR_NONE;
434 int sound_manager_focus_get_requested_behavior(sound_stream_info_h stream_info, int *flags)
436 int ret = MM_ERROR_NONE;
437 sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
438 bool is_focus_cb_thread = false;
442 SM_INSTANCE_CHECK(stream_h);
443 SM_NULL_ARG_CHECK(flags);
445 if ((ret = mm_sound_focus_is_cb_thread(&is_focus_cb_thread)))
446 _convert_sound_manager_error_code(__func__, ret);
448 if (!is_focus_cb_thread) {
449 LOGE("this API should be called in focus state changed callback");
450 return SOUND_MANAGER_ERROR_INVALID_OPERATION;
453 *flags = stream_h->requested_flags;
455 LOGI("requested sound behavior is (0x%x)", stream_h->requested_flags);
457 return SOUND_MANAGER_ERROR_NONE;
460 int sound_manager_get_current_playback_focus(sound_stream_focus_change_reason_e *acquired_by, int *flags, char **extra_info)
462 int ret = MM_ERROR_NONE;
463 char *stream_type_str = NULL;
464 char *extra_info_str = NULL;
466 bool is_focus_cb_thread = false;
470 SM_NULL_ARG_CHECK(acquired_by);
471 SM_NULL_ARG_CHECK(flags);
473 if ((ret = mm_sound_focus_is_cb_thread(&is_focus_cb_thread)))
474 _convert_sound_manager_error_code(__func__, ret);
476 if (is_focus_cb_thread) {
477 LOGE("this API should not be called in focus callback");
478 return SOUND_MANAGER_ERROR_INVALID_OPERATION;
481 ret = mm_sound_get_stream_type_of_acquired_focus((int)SOUND_STREAM_FOCUS_FOR_PLAYBACK, &stream_type_str, &option, &extra_info_str);
482 if (ret == MM_ERROR_NONE) {
483 LOGI("current acquired PLAYBACK focus : stream_type[%s]", stream_type_str);
484 ret = _convert_stream_type_to_change_reason(stream_type_str, acquired_by);
485 if (ret == MM_ERROR_NONE) {
486 LOGI(" : reason[%d], flags[0x%x], extra_info[%s]", *acquired_by, option, extra_info_str);
489 *extra_info = extra_info_str;
491 free(extra_info_str);
495 return _convert_sound_manager_error_code(__func__, ret);
498 int sound_manager_get_current_recording_focus(sound_stream_focus_change_reason_e *acquired_by, int *flags, char **extra_info)
500 int ret = MM_ERROR_NONE;
501 char *stream_type_str = NULL;
502 char *extra_info_str = NULL;
504 bool is_focus_cb_thread = false;
508 SM_NULL_ARG_CHECK(acquired_by);
509 SM_NULL_ARG_CHECK(flags);
511 if ((ret = mm_sound_focus_is_cb_thread(&is_focus_cb_thread)))
512 _convert_sound_manager_error_code(__func__, ret);
514 if (is_focus_cb_thread) {
515 LOGE("this API should not be called in focus callback");
516 return SOUND_MANAGER_ERROR_INVALID_OPERATION;
519 ret = mm_sound_get_stream_type_of_acquired_focus((int)SOUND_STREAM_FOCUS_FOR_RECORDING, &stream_type_str, &option, &extra_info_str);
520 if (ret == MM_ERROR_NONE) {
521 LOGI("current acquired RECORDING focus : stream_type[%s]", stream_type_str);
522 ret = _convert_stream_type_to_change_reason(stream_type_str, acquired_by);
523 if (ret == MM_ERROR_NONE) {
524 LOGI(" : reason[%d], flags[0x%x], extra_info[%s]", *acquired_by, option, extra_info_str);
527 *extra_info = extra_info_str;
529 free(extra_info_str);
533 return _convert_sound_manager_error_code(__func__, ret);
536 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)
538 int ret = MM_ERROR_NONE;
543 SM_NULL_ARG_CHECK(callback);
544 SM_NULL_ARG_CHECK(id);
545 SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_stream_info_count_mutex, SOUND_MANAGER_ERROR_INTERNAL);
547 for (i = 0; i < SOUND_STREAM_INFO_ARR_MAX; i++)
548 if (focus_watch_info_arr[i].id == 0)
550 if (i == SOUND_STREAM_INFO_ARR_MAX) {
551 LOGE("focus watch info array is full");
552 ret = MM_ERROR_SOUND_INTERNAL;
556 ret = mm_sound_set_focus_watch_callback((mm_sound_focus_type_e)focus_mask, _focus_watch_callback, user_data, id);
557 if (ret == MM_ERROR_NONE) {
558 SM_REF_FOR_STREAM_INFO(g_stream_info_count, ret);
559 focus_watch_info_arr[i].id = *id;
560 focus_watch_info_arr[i].user_data = user_data;
561 focus_watch_info_arr[i].user_cb = callback;
565 SM_LEAVE_CRITICAL_SECTION(&g_stream_info_count_mutex);
567 LOGD("cnt(%d), id(%d)", g_stream_info_count, *id);
569 return _convert_sound_manager_error_code(__func__, ret);
572 int sound_manager_remove_focus_state_watch_cb(int id)
574 int ret = MM_ERROR_NONE;
579 SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_stream_info_count_mutex, SOUND_MANAGER_ERROR_INTERNAL);
581 for (i = 0; i < SOUND_STREAM_INFO_ARR_MAX; i++)
582 if (focus_watch_info_arr[i].id == id)
584 if (i == SOUND_STREAM_INFO_ARR_MAX) {
585 LOGE("cound not find item in focus watch info array for this id(%d)", id);
586 ret = MM_ERROR_INVALID_ARGUMENT;
590 ret = mm_sound_unset_focus_watch_callback(id);
591 if (ret == MM_ERROR_NONE) {
592 SM_UNREF_FOR_STREAM_INFO(g_stream_info_count);
593 focus_watch_info_arr[i].id = 0;
594 focus_watch_info_arr[i].user_data = NULL;
595 focus_watch_info_arr[i].user_cb = NULL;
599 SM_LEAVE_CRITICAL_SECTION(&g_stream_info_count_mutex);
601 LOGD("cnt(%d)", g_stream_info_count);
603 return _convert_sound_manager_error_code(__func__, ret);
606 int sound_manager_set_session_type(sound_session_type_e type)
608 int ret = MM_ERROR_NONE;
609 int cur_session = -1;
610 int new_session = MM_SESSION_TYPE_MEDIA;
611 bool mic_enable = false;
613 LOGI(">> enter : type=%d", type);
615 if (type < SOUND_SESSION_TYPE_MEDIA || type > SOUND_SESSION_TYPE_VOIP)
616 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
618 /* If session type is VOIP but MIC is not enabled, return false */
619 if (type == SOUND_SESSION_TYPE_VOIP) {
620 ret = system_info_get_platform_bool(FEATURE_MICROPHONE, &mic_enable);
621 LOGI("system_info_platform [%s]=[%d], ret[%d]", FEATURE_MICROPHONE, mic_enable, ret);
622 if (ret != SYSTEM_INFO_ERROR_NONE || !mic_enable)
623 return _convert_sound_manager_error_code(__func__, MM_ERROR_NOT_SUPPORT_API);
626 /* it is not supported both session and stream feature at the same time */
627 if (g_stream_info_count) {
628 LOGE("Could not set this type(%d) because of being used stream feature", type);
629 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
633 case SOUND_SESSION_TYPE_MEDIA:
634 new_session = MM_SESSION_TYPE_MEDIA;
636 case SOUND_SESSION_TYPE_ALARM:
637 new_session = MM_SESSION_TYPE_ALARM;
639 case SOUND_SESSION_TYPE_NOTIFICATION:
640 new_session = MM_SESSION_TYPE_NOTIFY;
642 case SOUND_SESSION_TYPE_EMERGENCY:
643 new_session = MM_SESSION_TYPE_EMERGENCY;
645 case SOUND_SESSION_TYPE_VOIP:
646 new_session = MM_SESSION_TYPE_VOIP;
650 /* valid session check */
651 ret = mm_session_get_current_type(&cur_session);
652 if (ret == MM_ERROR_NONE) {
653 if (cur_session == MM_SESSION_TYPE_MEDIA_RECORD) {
654 if (type > SOUND_SESSION_TYPE_MEDIA) {
655 LOGE("Could not set this type(%d) during camera/recorder/audio-io(in)/radio", type);
656 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
661 if (g_session_interrupt_cb_table.is_registered) {
662 if (new_session == cur_session ||
663 ((new_session == SOUND_SESSION_TYPE_MEDIA) && (cur_session == MM_SESSION_TYPE_MEDIA_RECORD))) {
664 LOGI("already set type=%d, ret=0x%x", type, ret);
665 return SOUND_MANAGER_ERROR_NONE;
667 ret = mm_session_finish();
668 if (ret != MM_ERROR_NONE)
669 return _convert_sound_manager_error_code(__func__, ret);
671 g_session_interrupt_cb_table.is_registered = 0;
672 if (cur_session == MM_SESSION_TYPE_VOIP) {
673 g_cached_session_mode = -1;
674 g_cached_voip_device_id = -1;
675 if (g_voip_vstream_h) {
676 _stop_virtual_stream(g_voip_vstream_h);
677 _destroy_virtual_stream(g_voip_vstream_h);
678 g_voip_vstream_h = NULL;
680 /*voip stream destruction*/
681 if (g_voip_stream_info) {
682 ret = _destroy_pa_connection_and_unregister_focus(g_voip_stream_info);
683 free(g_voip_stream_info);
684 g_voip_stream_info = NULL;
685 if (ret != MM_ERROR_NONE)
686 return _convert_sound_manager_error_code(__func__, ret);
691 ret = mm_session_init(new_session);
692 if (ret == MM_ERROR_NONE)
693 g_session_interrupt_cb_table.is_registered = 1;
695 LOGI("type=%d", type);
697 return _convert_sound_manager_error_code(__func__, ret);
700 int sound_manager_get_session_type(sound_session_type_e *type)
702 int ret = MM_ERROR_NONE;
706 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
708 ret = mm_session_get_current_type(&cur_session);
709 if (ret != MM_ERROR_NONE) {
710 LOGW("session hasn't been set, setting default session");
711 cur_session = SOUND_SESSION_TYPE_DEFAULT;
712 ret = mm_session_init(cur_session);
713 if (ret == MM_ERROR_NONE)
714 g_session_interrupt_cb_table.is_registered = 1;
716 if ((cur_session > MM_SESSION_TYPE_EMERGENCY) &&
717 (cur_session != MM_SESSION_TYPE_VOIP)) {
718 if (g_cached_session != -1)
719 cur_session = g_cached_session;
720 else /* will be never reached here. just prevent code */
721 cur_session = SOUND_SESSION_TYPE_DEFAULT;
724 switch (cur_session) {
725 case MM_SESSION_TYPE_MEDIA:
726 case MM_SESSION_TYPE_MEDIA_RECORD:
727 *type = SOUND_SESSION_TYPE_MEDIA;
729 case MM_SESSION_TYPE_ALARM:
730 *type = SOUND_SESSION_TYPE_ALARM;
732 case MM_SESSION_TYPE_NOTIFY:
733 *type = SOUND_SESSION_TYPE_NOTIFICATION;
735 case MM_SESSION_TYPE_EMERGENCY:
736 *type = SOUND_SESSION_TYPE_EMERGENCY;
738 case MM_SESSION_TYPE_VOIP:
739 *type = SOUND_SESSION_TYPE_VOIP;
746 LOGI("type=%d", *type);
748 return SOUND_MANAGER_ERROR_NONE;
751 int sound_manager_set_media_session_option(sound_session_option_for_starting_e s_option, sound_session_option_for_during_play_e d_option)
753 int ret = MM_ERROR_NONE;
755 int session_option = 0;
758 LOGI(">> enter : option for starting=%d, for during play=%d", s_option, d_option);
760 if (s_option < 0 || s_option > SOUND_SESSION_OPTION_PAUSE_OTHERS_WHEN_START)
761 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
762 if (d_option < 0 || d_option > SOUND_SESSION_OPTION_UNINTERRUPTIBLE_DURING_PLAY)
763 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
765 ret = mm_session_get_current_information(&session, &session_option);
766 if (ret != 0 || !g_session_interrupt_cb_table.is_registered) {
767 LOGW("session hasn't been set, setting default session");
768 ret = mm_session_init(MM_SESSION_TYPE_MEDIA);
770 g_session_interrupt_cb_table.is_registered = 1;
772 } else if (ret == 0 && session > MM_SESSION_TYPE_MEDIA) {
773 if (session == MM_SESSION_TYPE_MEDIA_RECORD) {
774 if (!g_session_interrupt_cb_table.is_registered) {
775 LOGE("Already set by camera/recorder/audio-io(in)/radio API, but need to set session to Media first");
776 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
779 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
784 case SOUND_SESSION_OPTION_MIX_WITH_OTHERS_WHEN_START:
785 if (session_option & MM_SESSION_OPTION_PAUSE_OTHERS) {
786 ret = mm_session_update_option(MM_SESSION_UPDATE_TYPE_REMOVE, MM_SESSION_OPTION_PAUSE_OTHERS);
788 return _convert_sound_manager_error_code(__func__, ret);
793 case SOUND_SESSION_OPTION_PAUSE_OTHERS_WHEN_START:
794 if (!(session_option & MM_SESSION_OPTION_PAUSE_OTHERS)) {
795 ret = mm_session_update_option(MM_SESSION_UPDATE_TYPE_ADD, MM_SESSION_OPTION_PAUSE_OTHERS);
797 return _convert_sound_manager_error_code(__func__, ret);
805 case SOUND_SESSION_OPTION_INTERRUPTIBLE_DURING_PLAY:
806 if (session_option & MM_SESSION_OPTION_UNINTERRUPTIBLE) {
807 ret = mm_session_update_option(MM_SESSION_UPDATE_TYPE_REMOVE, MM_SESSION_OPTION_UNINTERRUPTIBLE);
809 return _convert_sound_manager_error_code(__func__, ret);
814 case SOUND_SESSION_OPTION_UNINTERRUPTIBLE_DURING_PLAY:
815 if (!(session_option & MM_SESSION_OPTION_UNINTERRUPTIBLE)) {
816 ret = mm_session_update_option(MM_SESSION_UPDATE_TYPE_ADD, MM_SESSION_OPTION_UNINTERRUPTIBLE);
818 return _convert_sound_manager_error_code(__func__, ret);
828 LOGI("already set same option(%x), skip it", session_option);
830 return _convert_sound_manager_error_code(__func__, ret);
833 int sound_manager_get_media_session_option(sound_session_option_for_starting_e *s_option, sound_session_option_for_during_play_e *d_option)
835 int ret = MM_ERROR_NONE;
837 int session_options = 0;
841 if (s_option == NULL || d_option == NULL)
842 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
844 ret = mm_session_get_current_information(&session, &session_options);
846 ret = mm_session_init(MM_SESSION_TYPE_MEDIA);
848 g_session_interrupt_cb_table.is_registered = 1;
850 } else if (session > SOUND_SESSION_TYPE_MEDIA) {
851 if (session == MM_SESSION_TYPE_MEDIA_RECORD) {
852 if (!g_session_interrupt_cb_table.is_registered) {
853 LOGE("Already set by camera/recorder/audio-io(in)/radio API, but need to set session to Media first");
854 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
857 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
860 if (session_options & MM_SESSION_OPTION_PAUSE_OTHERS)
861 *s_option = SOUND_SESSION_OPTION_PAUSE_OTHERS_WHEN_START;
863 *s_option = SOUND_SESSION_OPTION_MIX_WITH_OTHERS_WHEN_START;
865 if (session_options & MM_SESSION_OPTION_UNINTERRUPTIBLE)
866 *d_option = SOUND_SESSION_OPTION_UNINTERRUPTIBLE_DURING_PLAY;
868 *d_option = SOUND_SESSION_OPTION_INTERRUPTIBLE_DURING_PLAY;
870 LOGI(" option for starting=%d, for during play=%d", *s_option, *d_option);
872 return SOUND_MANAGER_ERROR_NONE;
875 int sound_manager_set_media_session_resumption_option(sound_session_option_for_resumption_e option)
877 int ret = MM_ERROR_NONE;
879 int session_option = 0;
882 LOGI(">> enter : option for resumption=%d (0:by system, 1:by system or media paused)", option);
884 if (option < SOUND_SESSION_OPTION_RESUMPTION_BY_SYSTEM || option > SOUND_SESSION_OPTION_RESUMPTION_BY_SYSTEM_OR_MEDIA_PAUSED)
885 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
887 ret = mm_session_get_current_information(&session, &session_option);
888 if (ret != 0 || !g_session_interrupt_cb_table.is_registered) {
889 LOGW("session hasn't been set, setting default session");
890 ret = mm_session_init(MM_SESSION_TYPE_MEDIA);
892 g_session_interrupt_cb_table.is_registered = 1;
894 } else if (ret == 0 && session > MM_SESSION_TYPE_MEDIA) {
895 if (session == MM_SESSION_TYPE_MEDIA_RECORD) {
896 if (!g_session_interrupt_cb_table.is_registered) {
897 LOGE("Already set by camera/recorder/audio-io(in)/radio API, but need to set session to Media first");
898 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
901 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
906 case SOUND_SESSION_OPTION_RESUMPTION_BY_SYSTEM:
907 if (session_option & MM_SESSION_OPTION_RESUME_BY_SYSTEM_OR_MEDIA_PAUSED) {
908 ret = mm_session_update_option(MM_SESSION_UPDATE_TYPE_REMOVE, MM_SESSION_OPTION_RESUME_BY_SYSTEM_OR_MEDIA_PAUSED);
910 return _convert_sound_manager_error_code(__func__, ret);
915 case SOUND_SESSION_OPTION_RESUMPTION_BY_SYSTEM_OR_MEDIA_PAUSED:
916 if (!(session_option & MM_SESSION_OPTION_RESUME_BY_SYSTEM_OR_MEDIA_PAUSED)) {
917 ret = mm_session_update_option(MM_SESSION_UPDATE_TYPE_ADD, MM_SESSION_OPTION_RESUME_BY_SYSTEM_OR_MEDIA_PAUSED);
919 return _convert_sound_manager_error_code(__func__, ret);
929 LOGI("already set same option(0x%x), skip it", session_option);
931 return _convert_sound_manager_error_code(__func__, ret);
934 int sound_manager_get_media_session_resumption_option(sound_session_option_for_resumption_e *option)
936 int ret = MM_ERROR_NONE;
938 int session_options = 0;
943 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
945 ret = mm_session_get_current_information(&session, &session_options);
947 LOGW("session hasn't been set, setting default session");
948 ret = mm_session_init(MM_SESSION_TYPE_MEDIA);
950 g_session_interrupt_cb_table.is_registered = 1;
952 } else if (session > SOUND_SESSION_TYPE_MEDIA) {
953 if (session == MM_SESSION_TYPE_MEDIA_RECORD) {
954 if (!g_session_interrupt_cb_table.is_registered) {
955 LOGE("Already set by camera/recorder/audio-io(in)/radio API, but need to set session to Media first");
956 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
959 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
962 if (session_options & MM_SESSION_OPTION_RESUME_BY_SYSTEM_OR_MEDIA_PAUSED)
963 *option = SOUND_SESSION_OPTION_RESUMPTION_BY_SYSTEM_OR_MEDIA_PAUSED;
965 *option = SOUND_SESSION_OPTION_RESUMPTION_BY_SYSTEM;
967 LOGI("option for resumption=%d (0:by system, 1:by system or media paused)", *option);
969 return SOUND_MANAGER_ERROR_NONE;
972 int sound_manager_set_voip_session_mode(sound_session_voip_mode_e mode)
974 int ret = MM_ERROR_NONE;
976 int session_options = 0;
978 LOGI(">> enter : mode=%d", mode);
980 ret = mm_session_get_current_information(&session, &session_options);
981 if (ret != MM_ERROR_NONE)
984 if (session != MM_SESSION_TYPE_VOIP) {
985 ret = MM_ERROR_POLICY_INTERNAL;
989 if (mode < SOUND_SESSION_VOIP_MODE_RINGTONE || mode > SOUND_SESSION_VOIP_MODE_VOICE_WITH_BLUETOOTH) {
990 ret = MM_ERROR_INVALID_ARGUMENT;
994 ret = _set_session_mode((_session_mode_e)mode);
996 LOGI("session=%d, mode=%d", session, mode);
999 return _convert_sound_manager_error_code(__func__, ret);
1002 int sound_manager_get_voip_session_mode(sound_session_voip_mode_e *mode)
1004 int ret = MM_ERROR_NONE;
1006 int session_options = 0;
1009 LOGE("mode is null");
1010 ret = MM_ERROR_INVALID_ARGUMENT;
1014 ret = mm_session_get_current_information(&session, &session_options);
1015 if (ret != MM_ERROR_NONE) {
1016 LOGI("session = %d, option = %d", session, session_options);
1020 if (session != MM_SESSION_TYPE_VOIP || g_cached_session_mode == -1) {
1021 ret = MM_ERROR_POLICY_INTERNAL;
1025 *mode = (sound_session_voip_mode_e)g_cached_session_mode;
1027 LOGI("session=%d, mode=%d", session, *mode);
1030 return _convert_sound_manager_error_code(__func__, ret);
1033 int sound_manager_set_session_interrupted_cb(sound_session_interrupted_cb callback, void *user_data)
1035 int ret = MM_ERROR_NONE;
1036 unsigned int subs_id = 0;
1038 SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_interrupt_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
1040 if (callback == NULL) {
1041 ret = MM_ERROR_INVALID_ARGUMENT;
1045 /* it is not supported both session and stream feature at the same time */
1046 if (g_stream_info_count) {
1047 ret = MM_ERROR_POLICY_INTERNAL;
1051 if (g_session_interrupt_cb_table.user_cb == NULL) {
1052 ret = mm_sound_add_device_connected_callback(SOUND_DEVICE_ALL_MASK, (mm_sound_device_connected_cb)_device_connected_cb, NULL, &subs_id);
1055 ret = mm_sound_focus_set_session_interrupt_callback((mm_sound_focus_session_interrupt_cb)_focus_session_interrupt_cb, NULL);
1057 if (mm_sound_remove_device_connected_callback(subs_id) != MM_ERROR_NONE)
1058 LOGW("mm_sound_remove_device_connected_callback failed");
1061 g_session_interrupt_cb_table.subs_id = subs_id;
1063 g_session_interrupt_cb_table.user_cb = (sound_session_interrupted_cb)callback;
1064 g_session_interrupt_cb_table.user_data = user_data;
1067 SM_LEAVE_CRITICAL_SECTION(&g_interrupt_cb_mutex);
1069 return _convert_sound_manager_error_code(__func__, ret);
1072 int sound_manager_unset_session_interrupted_cb(void)
1074 int ret = MM_ERROR_NONE;
1076 SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_interrupt_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
1078 if (!g_session_interrupt_cb_table.user_cb) {
1079 ret = MM_ERROR_SOUND_INTERNAL;
1083 ret = mm_sound_focus_unset_session_interrupt_callback();
1085 if (mm_sound_remove_device_connected_callback(g_session_interrupt_cb_table.subs_id) != MM_ERROR_NONE)
1086 LOGW("mm_sound_remove_device_connected_callback failed");
1090 ret = mm_sound_remove_device_connected_callback(g_session_interrupt_cb_table.subs_id);
1094 g_session_interrupt_cb_table.subs_id = 0;
1095 g_session_interrupt_cb_table.user_cb = NULL;
1096 g_session_interrupt_cb_table.user_data = NULL;
1099 SM_LEAVE_CRITICAL_SECTION(&g_interrupt_cb_mutex);
1101 return _convert_sound_manager_error_code(__func__, ret);
1104 int sound_manager_get_current_device_list(sound_device_mask_e device_mask, sound_device_list_h *device_list)
1106 int ret = MM_ERROR_NONE;
1108 ret = mm_sound_get_current_device_list((mm_sound_device_flags_e)device_mask, device_list);
1110 return _convert_sound_manager_error_code(__func__, ret);
1113 int sound_manager_free_device_list(sound_device_list_h device_list)
1115 int ret = MM_ERROR_NONE;
1117 ret = mm_sound_free_device_list(device_list);
1119 return _convert_sound_manager_error_code(__func__, ret);
1122 int sound_manager_get_next_device(sound_device_list_h device_list, sound_device_h *device)
1124 int ret = MM_ERROR_NONE;
1126 ret = mm_sound_get_next_device(device_list, device);
1128 return _convert_sound_manager_error_code(__func__, ret);
1131 int sound_manager_get_prev_device(sound_device_list_h device_list, sound_device_h *device)
1133 int ret = MM_ERROR_NONE;
1135 ret = mm_sound_get_prev_device(device_list, device);
1137 return _convert_sound_manager_error_code(__func__, ret);
1140 int sound_manager_get_device_type(sound_device_h device, sound_device_type_e *type)
1142 int ret = MM_ERROR_NONE;
1144 ret = mm_sound_get_device_type(device, (mm_sound_device_type_e*)type);
1146 return _convert_sound_manager_error_code(__func__, ret);
1149 int sound_manager_get_device_io_direction(sound_device_h device, sound_device_io_direction_e *io_direction)
1151 int ret = MM_ERROR_NONE;
1152 mm_sound_device_io_direction_e mm_sound_io_direction;
1154 ret = mm_sound_get_device_io_direction(device, &mm_sound_io_direction);
1155 if (ret == MM_ERROR_NONE)
1156 ret = _convert_device_io_direction(mm_sound_io_direction, io_direction);
1158 return _convert_sound_manager_error_code(__func__, ret);
1161 int sound_manager_get_device_id(sound_device_h device, int *id)
1163 int ret = MM_ERROR_NONE;
1165 ret = mm_sound_get_device_id(device, id);
1167 return _convert_sound_manager_error_code(__func__, ret);
1170 int sound_manager_get_device_name(sound_device_h device, char **name)
1172 int ret = MM_ERROR_NONE;
1174 ret = mm_sound_get_device_name(device, name);
1176 return _convert_sound_manager_error_code(__func__, ret);
1179 int sound_manager_get_device_state(sound_device_h device, sound_device_state_e *state)
1181 int ret = MM_ERROR_NONE;
1183 ret = mm_sound_get_device_state(device, (mm_sound_device_state_e*)state);
1185 return _convert_sound_manager_error_code(__func__, ret);
1188 int sound_manager_set_device_connected_cb(sound_device_mask_e device_mask, sound_device_connected_cb callback, void *user_data)
1190 int ret = MM_ERROR_NONE;
1191 unsigned int subs_id = 0;
1193 SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_device_conn_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
1195 ret = mm_sound_add_device_connected_callback((mm_sound_device_flags_e)device_mask, (mm_sound_device_connected_cb)callback, user_data, &subs_id);
1196 if (ret == MM_ERROR_NONE) {
1197 g_device_connected_cb_table.subs_id = subs_id;
1198 g_device_connected_cb_table.user_cb = (sound_device_connected_cb)callback;
1199 g_device_connected_cb_table.user_data = user_data;
1202 SM_LEAVE_CRITICAL_SECTION(&g_device_conn_cb_mutex);
1204 return _convert_sound_manager_error_code(__func__, ret);
1207 int sound_manager_unset_device_connected_cb(void)
1209 int ret = MM_ERROR_NONE;
1211 SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_device_conn_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
1213 if (g_device_connected_cb_table.subs_id == 0) {
1214 ret = MM_ERROR_SOUND_INTERNAL;
1218 ret = mm_sound_remove_device_connected_callback(g_device_connected_cb_table.subs_id);
1219 if (ret == MM_ERROR_NONE) {
1220 g_device_connected_cb_table.subs_id = 0;
1221 g_device_connected_cb_table.user_cb = NULL;
1222 g_device_connected_cb_table.user_data = NULL;
1226 SM_LEAVE_CRITICAL_SECTION(&g_device_conn_cb_mutex);
1228 return _convert_sound_manager_error_code(__func__, ret);
1231 int sound_manager_set_device_information_changed_cb(sound_device_mask_e device_mask, sound_device_information_changed_cb callback, void *user_data)
1233 int ret = MM_ERROR_NONE;
1234 unsigned int subs_id = 0;
1236 SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_device_info_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
1238 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);
1239 if (ret == MM_ERROR_NONE) {
1240 g_device_info_changed_cb_table.subs_id = subs_id;
1241 g_device_info_changed_cb_table.user_cb = (sound_device_information_changed_cb)callback;
1242 g_device_info_changed_cb_table.user_data = user_data;
1245 SM_LEAVE_CRITICAL_SECTION(&g_device_info_cb_mutex);
1247 return _convert_sound_manager_error_code(__func__, ret);
1250 int sound_manager_unset_device_information_changed_cb(void)
1252 int ret = MM_ERROR_NONE;
1254 SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_device_info_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
1256 if (g_device_info_changed_cb_table.subs_id == 0) {
1257 ret = MM_ERROR_SOUND_INTERNAL;
1261 ret = mm_sound_remove_device_information_changed_callback(g_device_info_changed_cb_table.subs_id);
1262 if (ret == MM_ERROR_NONE) {
1263 g_device_info_changed_cb_table.subs_id = 0;
1264 g_device_info_changed_cb_table.user_cb = NULL;
1265 g_device_info_changed_cb_table.user_data = NULL;
1269 SM_LEAVE_CRITICAL_SECTION(&g_device_info_cb_mutex);
1271 return _convert_sound_manager_error_code(__func__, ret);
1274 __attribute__ ((destructor))
1275 void __sound_manager_finalize(void)
1277 int ret = MM_ERROR_NONE;
1279 if (g_session_interrupt_cb_table.is_registered) {
1281 ret = mm_session_finish();
1282 if (ret != MM_ERROR_NONE)
1283 LOGE("[%s] failed to mm_session_finish(), ret(0x%x)", __func__, ret);
1285 g_session_interrupt_cb_table.is_registered = 0;
1290 __attribute__ ((constructor))
1291 void __sound_manager_initialize(void)