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"
21 _session_interrupt_info_s g_session_interrupt_cb_table = {0, 0, NULL, NULL};
22 _volume_changed_info_s g_volume_changed_cb_table = {0, NULL, NULL};
23 _focus_watch_info_s g_focus_watch_cb_table = {-1, NULL, NULL};
24 _device_connected_info_s g_device_connected_cb_table = {0, NULL, NULL};
25 _device_changed_info_s g_device_info_changed_cb_table = {0, NULL, NULL};
27 sound_session_type_e g_cached_session = -1;
28 _session_mode_e g_cached_session_mode = -1;
29 int g_cached_voip_device_id = -1;
30 extern sound_stream_info_s *g_voip_stream_info;
31 extern virtual_sound_stream_info_s *g_voip_vstream_h;
33 /* These variables will be removed when session features are deprecated. */
34 extern int g_stream_info_count;
35 extern pthread_mutex_t g_stream_info_count_mutex;
36 pthread_mutex_t g_interrupt_cb_mutex, g_device_info_cb_mutex, g_device_conn_cb_mutex, g_volume_cb_mutex;
38 int sound_manager_get_max_volume(sound_type_e type, int *max)
40 const char *volume_type = NULL;
41 unsigned int max_level = 0;
42 int ret = MM_ERROR_NONE;
45 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
47 if (type >= SOUND_TYPE_NUM || type < 0)
48 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
49 ret = _convert_sound_type(type, &volume_type);
50 if (ret == MM_ERROR_NONE) {
51 ret = _get_volume_max_level("out", volume_type, &max_level);
52 if (ret == MM_ERROR_NONE)
53 *max = (int)max_level -1; /* actual volume step can be max step - 1 */
56 return _convert_sound_manager_error_code(__func__, ret);
59 int sound_manager_set_volume(sound_type_e type, int volume)
61 int ret = MM_ERROR_NONE;
63 if (type >= SOUND_TYPE_NUM || type < 0)
64 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
66 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
68 ret = mm_sound_volume_set_value(type, volume);
69 LOGI("returns : type=%d, volume=%d, ret=%p", type, volume, ret);
71 return _convert_sound_manager_error_code(__func__, ret);
74 int sound_manager_get_volume(sound_type_e type, int *volume)
76 int ret = MM_ERROR_NONE;
79 if (type >= SOUND_TYPE_NUM || type < 0)
80 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
82 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
84 ret = mm_sound_volume_get_value(type, &uvolume);
85 if (ret == MM_ERROR_NONE)
88 LOGI("returns : type=%d, volume=%d, ret=%p", type, *volume, ret);
90 return _convert_sound_manager_error_code(__func__, ret);
93 int sound_manager_set_current_sound_type(sound_type_e type)
95 int ret = MM_ERROR_NONE;
97 if (type >= SOUND_TYPE_NUM || type < 0)
98 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
100 ret = mm_sound_volume_primary_type_set(type);
102 return _convert_sound_manager_error_code(__func__, ret);
105 int sound_manager_get_current_sound_type(sound_type_e *type)
107 int ret = MM_ERROR_NONE;
108 volume_type_t mm_sound_vol_type = VOLUME_TYPE_UNKNOWN;
109 char *volume_type = NULL;
112 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
114 ret = mm_sound_volume_primary_type_get(&mm_sound_vol_type);
115 if (ret == MM_ERROR_NONE) {
116 if (mm_sound_vol_type == VOLUME_TYPE_UNKNOWN) {
117 /* get the volume type of the current playing stream */
118 ret = _get_current_volume_type("out", &volume_type);
119 if (ret == MM_ERROR_NONE)
120 ret = _convert_sound_type_to_enum((const char*)volume_type, type);
122 *type = mm_sound_vol_type;
125 LOGI("returns : type=%d, ret=%p", *type, ret);
127 return _convert_sound_manager_error_code(__func__, ret);
130 int sound_manager_unset_current_sound_type(void)
132 int ret = MM_ERROR_NONE;
134 ret = mm_sound_volume_primary_type_set(VOLUME_TYPE_UNKNOWN);
136 return _convert_sound_manager_error_code(__func__, ret);
139 int sound_manager_set_volume_changed_cb(sound_manager_volume_changed_cb callback, void* user_data)
141 int ret = MM_ERROR_NONE;
142 unsigned int subs_id = 0;
144 SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_volume_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
146 ret = mm_sound_add_volume_changed_callback((mm_sound_volume_changed_cb)callback, user_data, &subs_id);
147 if (ret == MM_ERROR_NONE) {
148 g_volume_changed_cb_table.subs_id = subs_id;
149 g_volume_changed_cb_table.user_cb = (sound_manager_volume_changed_cb)callback;
150 g_volume_changed_cb_table.user_data = user_data;
153 SM_LEAVE_CRITICAL_SECTION(&g_volume_cb_mutex);
155 return _convert_sound_manager_error_code(__func__, ret);
158 int sound_manager_unset_volume_changed_cb(void)
160 int ret = MM_ERROR_NONE;
162 SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_volume_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
164 if (g_volume_changed_cb_table.subs_id > 0) {
165 ret = mm_sound_remove_volume_changed_callback(g_volume_changed_cb_table.subs_id);
166 if (ret == MM_ERROR_NONE) {
167 g_volume_changed_cb_table.subs_id = 0;
168 g_volume_changed_cb_table.user_cb = NULL;
169 g_volume_changed_cb_table.user_data = NULL;
172 ret = MM_ERROR_SOUND_INTERNAL;
175 SM_LEAVE_CRITICAL_SECTION(&g_volume_cb_mutex);
177 return _convert_sound_manager_error_code(__func__, ret);
180 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 int ret = MM_ERROR_NONE;
186 SM_NULL_ARG_CHECK(stream_info);
187 SM_NULL_ARG_CHECK(callback);
189 if (g_session_interrupt_cb_table.is_registered)
190 return _convert_sound_manager_error_code(__func__, MM_ERROR_SOUND_INTERNAL);
192 sound_stream_info_s *stream_h = malloc(sizeof(sound_stream_info_s));
194 ret = MM_ERROR_OUT_OF_MEMORY;
196 memset(stream_h, 0, sizeof(sound_stream_info_s));
197 ret = _convert_stream_type(stream_type, &stream_h->stream_type);
198 if (ret == MM_ERROR_NONE) {
199 SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_stream_info_count_mutex, MM_ERROR_SOUND_INTERNAL);
200 ret = _make_pa_connection_and_register_focus(stream_h, callback, user_data);
201 if (ret == MM_ERROR_NONE) {
202 *stream_info = (sound_stream_info_h)stream_h;
203 SM_REF_FOR_STREAM_INFO(g_stream_info_count, ret);
204 LOGI("<< leave : stream_h(%p), index(%u), user_cb(%p), cnt(%d), ret(%p)", stream_h, stream_h->index, stream_h->user_cb, g_stream_info_count, ret);
206 SM_LEAVE_CRITICAL_SECTION(&g_stream_info_count_mutex);
212 return _convert_sound_manager_error_code(__func__, ret);
215 int sound_manager_destroy_stream_information(sound_stream_info_h stream_info)
217 int ret = MM_ERROR_NONE;
218 sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
222 SM_INSTANCE_CHECK(stream_h);
224 SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_stream_info_count_mutex, MM_ERROR_SOUND_INTERNAL);
225 ret = _destroy_pa_connection_and_unregister_focus(stream_h);
228 SM_UNREF_FOR_STREAM_INFO(g_stream_info_count, ret);
229 SM_LEAVE_CRITICAL_SECTION(&g_stream_info_count_mutex);
231 LOGI("<< leave : cnt(%d), ret(%p)", g_stream_info_count, ret);
233 return _convert_sound_manager_error_code(__func__, ret);
236 int sound_manager_add_device_for_stream_routing(sound_stream_info_h stream_info, sound_device_h device)
238 int ret = MM_ERROR_NONE;
239 sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
243 ret = _add_device_for_stream_routing(stream_h, device);
245 LOGI("<< leave : ret(%p)", ret);
247 return _convert_sound_manager_error_code(__func__, ret);
250 int sound_manager_remove_device_for_stream_routing(sound_stream_info_h stream_info, sound_device_h device)
252 int ret = MM_ERROR_NONE;
253 sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
257 ret = _remove_device_for_stream_routing(stream_h, device);
259 LOGI("<< leave : ret(%p)", ret);
261 return _convert_sound_manager_error_code(__func__, ret);
264 int sound_manager_apply_stream_routing(sound_stream_info_h stream_info)
266 int ret = MM_ERROR_NONE;
267 sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
271 ret = _apply_stream_routing(stream_h);
273 LOGI("<< leave : ret(%p)", ret);
275 return _convert_sound_manager_error_code(__func__, ret);
278 int sound_manager_acquire_focus(sound_stream_info_h stream_info, sound_stream_focus_mask_e focus_mask, const char *additional_info)
280 int ret = MM_ERROR_NONE;
281 sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
285 SM_INSTANCE_CHECK(stream_h);
287 ret = mm_sound_acquire_focus(stream_h->index, (mm_sound_focus_type_e)focus_mask, additional_info);
288 if (ret == MM_ERROR_NONE) {
289 stream_h->acquired_focus |= focus_mask;
290 _update_focus_status(stream_h->index, (unsigned int)stream_h->acquired_focus);
293 LOGI("<< leave : ret(%p)", ret);
295 return _convert_sound_manager_error_code(__func__, ret);
298 int sound_manager_release_focus(sound_stream_info_h stream_info, sound_stream_focus_mask_e focus_mask, const char *additional_info)
300 int ret = MM_ERROR_NONE;
301 sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
305 SM_INSTANCE_CHECK(stream_h);
307 ret = mm_sound_release_focus(stream_h->index, (mm_sound_focus_type_e)focus_mask, additional_info);
308 if (ret == MM_ERROR_NONE) {
309 stream_h->acquired_focus &= ~focus_mask;
310 _update_focus_status(stream_h->index, (unsigned int)stream_h->acquired_focus);
313 LOGI("<< leave : ret(%p)", ret);
315 return _convert_sound_manager_error_code(__func__, ret);
318 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)
320 int ret = MM_ERROR_NONE;
321 sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
325 SM_INSTANCE_CHECK(stream_h);
326 if (!state_for_playback && !state_for_recording)
327 ret = MM_ERROR_INVALID_ARGUMENT;
329 if (state_for_playback)
330 *state_for_playback = ((stream_h->acquired_focus & SOUND_STREAM_FOCUS_FOR_PLAYBACK) ? (SOUND_STREAM_FOCUS_STATE_ACQUIRED) : (SOUND_STREAM_FOCUS_STATE_RELEASED));
331 if (state_for_recording)
332 *state_for_recording = ((stream_h->acquired_focus & SOUND_STREAM_FOCUS_FOR_RECORDING) ? (SOUND_STREAM_FOCUS_STATE_ACQUIRED) : (SOUND_STREAM_FOCUS_STATE_RELEASED));
334 LOGI("<< leave : acquired_focus(%p)", stream_h->acquired_focus);
336 return _convert_sound_manager_error_code(__func__, ret);
339 int sound_manager_get_sound_type(sound_stream_info_h stream_info, sound_type_e *sound_type)
341 int ret = MM_ERROR_NONE;
342 sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
346 SM_INSTANCE_CHECK(stream_h);
347 SM_NULL_ARG_CHECK(sound_type);
349 ret = _convert_sound_type_to_enum(stream_h->stream_conf_info.volume_type, sound_type);
351 LOGI("<< leave : sound type(%d)", *sound_type);
353 return _convert_sound_manager_error_code(__func__, ret);
356 int sound_manager_set_focus_state_watch_cb(sound_stream_focus_mask_e focus_mask, sound_stream_focus_state_watch_cb callback, void *user_data)
358 int ret = MM_ERROR_NONE;
363 SM_NULL_ARG_CHECK(callback);
364 SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_stream_info_count_mutex, SOUND_MANAGER_ERROR_INTERNAL);
366 if (!g_focus_watch_cb_table.user_cb) {
367 SM_REF_FOR_STREAM_INFO(g_stream_info_count, ret);
368 ret = mm_sound_set_focus_watch_callback((mm_sound_focus_type_e)focus_mask, _focus_watch_callback, user_data, &id);
369 if (ret == MM_ERROR_NONE) {
370 g_focus_watch_cb_table.index = id;
371 g_focus_watch_cb_table.user_cb = callback;
372 g_focus_watch_cb_table.user_data = user_data;
375 ret = MM_ERROR_SOUND_INTERNAL;
378 SM_LEAVE_CRITICAL_SECTION(&g_stream_info_count_mutex);
380 LOGI("<< leave : cnt(%d), ret(%p)", g_stream_info_count, ret);
382 return _convert_sound_manager_error_code(__func__, ret);
385 int sound_manager_unset_focus_state_watch_cb(void)
387 int ret = MM_ERROR_NONE;
391 SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_stream_info_count_mutex, SOUND_MANAGER_ERROR_INTERNAL);
393 if (g_focus_watch_cb_table.user_cb) {
394 ret = mm_sound_unset_focus_watch_callback(g_focus_watch_cb_table.index);
395 if (ret == MM_ERROR_NONE) {
396 g_focus_watch_cb_table.index = -1;
397 g_focus_watch_cb_table.user_cb = NULL;
398 g_focus_watch_cb_table.user_data = NULL;
399 SM_UNREF_FOR_STREAM_INFO(g_stream_info_count, ret);
401 ret = MM_ERROR_SOUND_INTERNAL;
404 ret = MM_ERROR_SOUND_INTERNAL;
407 SM_LEAVE_CRITICAL_SECTION(&g_stream_info_count_mutex);
409 LOGI("<< leave : cnt(%d), ret(%p)", g_stream_info_count, ret);
411 return _convert_sound_manager_error_code(__func__, ret);
414 int sound_manager_set_session_type(sound_session_type_e type)
416 int ret = MM_ERROR_NONE;
417 int cur_session = -1;
418 int new_session = MM_SESSION_TYPE_MEDIA;
420 LOGI(">> enter : type=%d", type);
422 if (type < SOUND_SESSION_TYPE_MEDIA || type > SOUND_SESSION_TYPE_VOIP)
423 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
425 /* it is not supported both session and stream feature at the same time */
426 if (g_stream_info_count) {
427 LOGE("Could not set this type(%d) because of being used stream feature", type);
428 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
432 case SOUND_SESSION_TYPE_MEDIA:
433 new_session = MM_SESSION_TYPE_MEDIA;
435 case SOUND_SESSION_TYPE_ALARM:
436 new_session = MM_SESSION_TYPE_ALARM;
438 case SOUND_SESSION_TYPE_NOTIFICATION:
439 new_session = MM_SESSION_TYPE_NOTIFY;
441 case SOUND_SESSION_TYPE_EMERGENCY:
442 new_session = MM_SESSION_TYPE_EMERGENCY;
444 case SOUND_SESSION_TYPE_VOIP:
445 new_session = MM_SESSION_TYPE_VOIP;
449 /* valid session check */
450 ret = mm_session_get_current_type(&cur_session);
451 if (ret == MM_ERROR_NONE) {
452 if (cur_session == MM_SESSION_TYPE_MEDIA_RECORD) {
453 if (type > SOUND_SESSION_TYPE_MEDIA) {
454 LOGE("<< leave : Could not set this type(%d) during camera/recorder/audio-io(in)/radio", type);
455 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
460 if (g_session_interrupt_cb_table.is_registered) {
461 if (new_session == cur_session ||
462 ((new_session == SOUND_SESSION_TYPE_MEDIA) && (cur_session == MM_SESSION_TYPE_MEDIA_RECORD))) {
463 LOGI("<< leave : already set type=%d, ret=%p", type, ret);
464 return SOUND_MANAGER_ERROR_NONE;
466 ret = mm_session_finish();
467 if (ret != MM_ERROR_NONE)
468 return _convert_sound_manager_error_code(__func__, ret);
470 g_session_interrupt_cb_table.is_registered = 0;
471 if (cur_session == MM_SESSION_TYPE_VOIP) {
472 g_cached_session_mode = -1;
473 g_cached_voip_device_id = -1;
474 if (g_voip_vstream_h) {
475 _stop_virtual_stream(g_voip_vstream_h);
476 _destroy_virtual_stream(g_voip_vstream_h);
477 g_voip_vstream_h = NULL;
479 /*voip stream destruction*/
480 if (g_voip_stream_info) {
481 ret = _destroy_pa_connection_and_unregister_focus(g_voip_stream_info);
482 free(g_voip_stream_info);
483 g_voip_stream_info = NULL;
484 if (ret != MM_ERROR_NONE)
485 return _convert_sound_manager_error_code(__func__, ret);
490 ret = mm_session_init(new_session);
491 if (ret == MM_ERROR_NONE)
492 g_session_interrupt_cb_table.is_registered = 1;
494 LOGI("<< leave : type=%d, ret=%p", type, ret);
496 return _convert_sound_manager_error_code(__func__, ret);
499 int sound_manager_get_session_type(sound_session_type_e *type)
501 int ret = MM_ERROR_NONE;
505 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
506 ret = mm_session_get_current_type(&cur_session);
508 LOGW("session hasn't been set, setting default session");
509 cur_session = SOUND_SESSION_TYPE_DEFAULT;
510 ret = mm_session_init(cur_session);
512 g_session_interrupt_cb_table.is_registered = 1;
514 if ((cur_session > MM_SESSION_TYPE_EMERGENCY) &&
515 (cur_session != MM_SESSION_TYPE_VOIP)) {
516 if (g_cached_session != -1)
517 cur_session = g_cached_session;
518 else /* will be never reach here. just prevent code */
519 cur_session = SOUND_SESSION_TYPE_DEFAULT;
522 switch (cur_session) {
523 case MM_SESSION_TYPE_MEDIA:
524 case MM_SESSION_TYPE_MEDIA_RECORD:
525 *type = SOUND_SESSION_TYPE_MEDIA;
527 case MM_SESSION_TYPE_ALARM:
528 *type = SOUND_SESSION_TYPE_ALARM;
530 case MM_SESSION_TYPE_NOTIFY:
531 *type = SOUND_SESSION_TYPE_NOTIFICATION;
533 case MM_SESSION_TYPE_EMERGENCY:
534 *type = SOUND_SESSION_TYPE_EMERGENCY;
536 case MM_SESSION_TYPE_VOIP:
537 *type = SOUND_SESSION_TYPE_VOIP;
544 LOGI("returns : type=%d, ret=%p", *type, ret);
549 int sound_manager_set_media_session_option(sound_session_option_for_starting_e s_option, sound_session_option_for_during_play_e d_option)
551 int ret = MM_ERROR_NONE;
553 int session_option = 0;
556 LOGI(">> enter : option for starting=%d, for during play=%d", s_option, d_option);
558 if (s_option < 0 || s_option > SOUND_SESSION_OPTION_PAUSE_OTHERS_WHEN_START)
559 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
560 if (d_option < 0 || d_option > SOUND_SESSION_OPTION_UNINTERRUPTIBLE_DURING_PLAY)
561 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
563 ret = mm_session_get_current_information(&session, &session_option);
564 if (ret != 0 || !g_session_interrupt_cb_table.is_registered) {
565 LOGW("session hasn't been set, setting default session");
566 ret = mm_session_init(MM_SESSION_TYPE_MEDIA);
568 g_session_interrupt_cb_table.is_registered = 1;
570 } else if (ret == 0 && session > MM_SESSION_TYPE_MEDIA) {
571 if (session == MM_SESSION_TYPE_MEDIA_RECORD) {
572 if (!g_session_interrupt_cb_table.is_registered) {
573 LOGE("Already set by camera/recorder/audio-io(in)/radio API, but need to set session to Media first");
574 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
577 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
582 case SOUND_SESSION_OPTION_MIX_WITH_OTHERS_WHEN_START:
583 if (session_option & MM_SESSION_OPTION_PAUSE_OTHERS) {
584 ret = mm_session_update_option(MM_SESSION_UPDATE_TYPE_REMOVE, MM_SESSION_OPTION_PAUSE_OTHERS);
586 return _convert_sound_manager_error_code(__func__, ret);
591 case SOUND_SESSION_OPTION_PAUSE_OTHERS_WHEN_START:
592 if (!(session_option & MM_SESSION_OPTION_PAUSE_OTHERS)) {
593 ret = mm_session_update_option(MM_SESSION_UPDATE_TYPE_ADD, MM_SESSION_OPTION_PAUSE_OTHERS);
595 return _convert_sound_manager_error_code(__func__, ret);
603 case SOUND_SESSION_OPTION_INTERRUPTIBLE_DURING_PLAY:
604 if (session_option & MM_SESSION_OPTION_UNINTERRUPTIBLE) {
605 ret = mm_session_update_option(MM_SESSION_UPDATE_TYPE_REMOVE, MM_SESSION_OPTION_UNINTERRUPTIBLE);
607 return _convert_sound_manager_error_code(__func__, ret);
612 case SOUND_SESSION_OPTION_UNINTERRUPTIBLE_DURING_PLAY:
613 if (!(session_option & MM_SESSION_OPTION_UNINTERRUPTIBLE)) {
614 ret = mm_session_update_option(MM_SESSION_UPDATE_TYPE_ADD, MM_SESSION_OPTION_UNINTERRUPTIBLE);
616 return _convert_sound_manager_error_code(__func__, ret);
624 LOGI("<< leave : updated");
626 LOGI("<< leave : already set same option(%x), skip it", session_option);
628 return _convert_sound_manager_error_code(__func__, ret);
631 int sound_manager_get_media_session_option(sound_session_option_for_starting_e *s_option, sound_session_option_for_during_play_e *d_option)
633 int ret = MM_ERROR_NONE;
635 int session_options = 0;
639 if (s_option == NULL || d_option == NULL)
640 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
642 ret = mm_session_get_current_information(&session, &session_options);
644 ret = mm_session_init(MM_SESSION_TYPE_MEDIA);
646 g_session_interrupt_cb_table.is_registered = 1;
648 } else if (session > SOUND_SESSION_TYPE_MEDIA) {
649 if (session == MM_SESSION_TYPE_MEDIA_RECORD) {
650 if (!g_session_interrupt_cb_table.is_registered) {
651 LOGE("Already set by camera/recorder/audio-io(in)/radio API, but need to set session to Media first");
652 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
655 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
658 if (session_options & MM_SESSION_OPTION_PAUSE_OTHERS)
659 *s_option = SOUND_SESSION_OPTION_PAUSE_OTHERS_WHEN_START;
661 *s_option = SOUND_SESSION_OPTION_MIX_WITH_OTHERS_WHEN_START;
663 if (session_options & MM_SESSION_OPTION_UNINTERRUPTIBLE)
664 *d_option = SOUND_SESSION_OPTION_UNINTERRUPTIBLE_DURING_PLAY;
666 *d_option = SOUND_SESSION_OPTION_INTERRUPTIBLE_DURING_PLAY;
668 LOGI("<< leave : option for starting=%d, for during play=%d", *s_option, *d_option);
670 return SOUND_MANAGER_ERROR_NONE;
673 int sound_manager_set_media_session_resumption_option(sound_session_option_for_resumption_e option)
675 int ret = MM_ERROR_NONE;
677 int session_option = 0;
680 LOGI(">> enter : option for resumption=%d (0:by system, 1:by system or media paused)", option);
682 if (option < SOUND_SESSION_OPTION_RESUMPTION_BY_SYSTEM || option > SOUND_SESSION_OPTION_RESUMPTION_BY_SYSTEM_OR_MEDIA_PAUSED)
683 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
685 ret = mm_session_get_current_information(&session, &session_option);
686 if (ret != 0 || !g_session_interrupt_cb_table.is_registered) {
687 LOGW("session hasn't been set, setting default session");
688 ret = mm_session_init(MM_SESSION_TYPE_MEDIA);
690 g_session_interrupt_cb_table.is_registered = 1;
692 } else if (ret == 0 && session > MM_SESSION_TYPE_MEDIA) {
693 if (session == MM_SESSION_TYPE_MEDIA_RECORD) {
694 if (!g_session_interrupt_cb_table.is_registered) {
695 LOGE("Already set by camera/recorder/audio-io(in)/radio API, but need to set session to Media first");
696 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
699 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
704 case SOUND_SESSION_OPTION_RESUMPTION_BY_SYSTEM:
705 if (session_option & MM_SESSION_OPTION_RESUME_BY_SYSTEM_OR_MEDIA_PAUSED) {
706 ret = mm_session_update_option(MM_SESSION_UPDATE_TYPE_REMOVE, MM_SESSION_OPTION_RESUME_BY_SYSTEM_OR_MEDIA_PAUSED);
708 return _convert_sound_manager_error_code(__func__, ret);
713 case SOUND_SESSION_OPTION_RESUMPTION_BY_SYSTEM_OR_MEDIA_PAUSED:
714 if (!(session_option & MM_SESSION_OPTION_RESUME_BY_SYSTEM_OR_MEDIA_PAUSED)) {
715 ret = mm_session_update_option(MM_SESSION_UPDATE_TYPE_ADD, MM_SESSION_OPTION_RESUME_BY_SYSTEM_OR_MEDIA_PAUSED);
717 return _convert_sound_manager_error_code(__func__, ret);
725 LOGI("<< leave : updated");
727 LOGI("<< leave : already set same option(%x), skip it", session_option);
729 return _convert_sound_manager_error_code(__func__, ret);
732 int sound_manager_get_media_session_resumption_option(sound_session_option_for_resumption_e *option)
734 int ret = MM_ERROR_NONE;
736 int session_options = 0;
741 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
742 ret = mm_session_get_current_information(&session, &session_options);
744 LOGW("session hasn't been set, setting default session");
745 ret = mm_session_init(MM_SESSION_TYPE_MEDIA);
747 g_session_interrupt_cb_table.is_registered = 1;
749 } else if (session > SOUND_SESSION_TYPE_MEDIA) {
750 if (session == MM_SESSION_TYPE_MEDIA_RECORD) {
751 if (!g_session_interrupt_cb_table.is_registered) {
752 LOGE("Already set by camera/recorder/audio-io(in)/radio API, but need to set session to Media first");
753 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
756 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
759 if (session_options & MM_SESSION_OPTION_RESUME_BY_SYSTEM_OR_MEDIA_PAUSED)
760 *option = SOUND_SESSION_OPTION_RESUMPTION_BY_SYSTEM_OR_MEDIA_PAUSED;
762 *option = SOUND_SESSION_OPTION_RESUMPTION_BY_SYSTEM;
764 LOGI("<< leave : option for resumption=%d (0:by system, 1:by system or media paused)", *option);
766 return SOUND_MANAGER_ERROR_NONE;
769 int sound_manager_set_voip_session_mode(sound_session_voip_mode_e mode)
771 int ret = MM_ERROR_NONE;
773 int session_options = 0;
775 LOGI(">> enter : mode=%d", mode);
777 ret = mm_session_get_current_information(&session, &session_options);
778 if (ret != MM_ERROR_NONE)
779 return _convert_sound_manager_error_code(__func__, ret);
780 else if (session != MM_SESSION_TYPE_VOIP)
781 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
783 if (mode < SOUND_SESSION_VOIP_MODE_RINGTONE || mode > SOUND_SESSION_VOIP_MODE_VOICE_WITH_BLUETOOTH) {
784 ret = MM_ERROR_INVALID_ARGUMENT;
785 return _convert_sound_manager_error_code(__func__, ret);
787 ret = _set_session_mode((_session_mode_e)mode);
789 LOGI("<< leave : session=%p, mode=%d, ret=%p", session, mode, ret);
791 return _convert_sound_manager_error_code(__func__, ret);
794 int sound_manager_get_voip_session_mode(sound_session_voip_mode_e *mode)
796 int ret = MM_ERROR_NONE;
798 int session_options = 0;
801 LOGI("mode is null");
802 return _convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
805 ret = mm_session_get_current_information(&session, &session_options);
806 if (ret != MM_ERROR_NONE) {
807 LOGI("session = %d, option = %d", session, session_options);
808 return _convert_sound_manager_error_code(__func__, ret);
809 } else if (session != MM_SESSION_TYPE_VOIP || g_cached_session_mode == -1)
810 return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
812 *mode = (sound_session_voip_mode_e)g_cached_session_mode;
814 LOGI("returns : session=%p, mode=%d, ret=%p", session, *mode, ret);
816 return _convert_sound_manager_error_code(__func__, ret);
819 int sound_manager_set_session_interrupted_cb(sound_session_interrupted_cb callback, void *user_data)
821 int ret = MM_ERROR_NONE;
822 unsigned int subs_id = 0;
824 SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_interrupt_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
826 if (callback == NULL) {
827 ret = MM_ERROR_INVALID_ARGUMENT;
831 /* it is not supported both session and stream feature at the same time */
832 if (g_stream_info_count) {
833 ret = MM_ERROR_POLICY_INTERNAL;
837 if (g_session_interrupt_cb_table.user_cb == NULL) {
838 ret = mm_sound_add_device_connected_callback(SOUND_DEVICE_ALL_MASK, (mm_sound_device_connected_cb)_device_connected_cb, NULL, &subs_id);
841 ret = mm_sound_focus_set_session_interrupt_callback((mm_sound_focus_session_interrupt_cb)_focus_session_interrupt_cb, NULL);
843 if (mm_sound_remove_device_connected_callback(subs_id) != MM_ERROR_NONE)
844 LOGW("mm_sound_remove_device_connected_callback failed");
847 g_session_interrupt_cb_table.subs_id = subs_id;
849 g_session_interrupt_cb_table.user_cb = (sound_session_interrupted_cb)callback;
850 g_session_interrupt_cb_table.user_data = user_data;
853 SM_LEAVE_CRITICAL_SECTION(&g_interrupt_cb_mutex);
854 return _convert_sound_manager_error_code(__func__, ret);
857 int sound_manager_unset_session_interrupted_cb(void)
859 int ret = MM_ERROR_NONE;
861 SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_interrupt_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
863 if (g_session_interrupt_cb_table.user_cb) {
864 ret = mm_sound_focus_unset_session_interrupt_callback();
866 if (mm_sound_remove_device_connected_callback(g_session_interrupt_cb_table.subs_id) != MM_ERROR_NONE)
867 LOGW("mm_sound_remove_device_connected_callback failed");
870 ret = mm_sound_remove_device_connected_callback(g_session_interrupt_cb_table.subs_id);
873 g_session_interrupt_cb_table.subs_id = 0;
874 g_session_interrupt_cb_table.user_cb = NULL;
875 g_session_interrupt_cb_table.user_data = NULL;
877 ret = MM_ERROR_SOUND_INTERNAL;
881 SM_LEAVE_CRITICAL_SECTION(&g_interrupt_cb_mutex);
882 return _convert_sound_manager_error_code(__func__, ret);
885 int sound_manager_get_current_device_list(sound_device_mask_e device_mask, sound_device_list_h *device_list)
887 int ret = MM_ERROR_NONE;
888 ret = mm_sound_get_current_device_list((mm_sound_device_flags_e)device_mask, device_list);
890 return _convert_sound_manager_error_code(__func__, ret);
893 int sound_manager_get_next_device(sound_device_list_h device_list, sound_device_h *device)
895 int ret = MM_ERROR_NONE;
896 ret = mm_sound_get_next_device(device_list, device);
898 return _convert_sound_manager_error_code(__func__, ret);
901 int sound_manager_get_prev_device(sound_device_list_h device_list, sound_device_h *device)
903 int ret = MM_ERROR_NONE;
904 ret = mm_sound_get_prev_device(device_list, device);
906 return _convert_sound_manager_error_code(__func__, ret);
909 int sound_manager_get_device_type(sound_device_h device, sound_device_type_e *type)
911 int ret = MM_ERROR_NONE;
912 ret = mm_sound_get_device_type(device, (mm_sound_device_type_e*)type);
914 return _convert_sound_manager_error_code(__func__, ret);
917 int sound_manager_get_device_io_direction(sound_device_h device, sound_device_io_direction_e *io_direction)
919 int ret = MM_ERROR_NONE;
920 mm_sound_device_io_direction_e mm_sound_io_direction;
921 ret = mm_sound_get_device_io_direction(device, &mm_sound_io_direction);
922 if (ret == MM_ERROR_NONE)
923 ret = _convert_device_io_direction(mm_sound_io_direction, io_direction);
925 return _convert_sound_manager_error_code(__func__, ret);
928 int sound_manager_get_device_id(sound_device_h device, int *id)
930 int ret = MM_ERROR_NONE;
931 ret = mm_sound_get_device_id(device, id);
933 return _convert_sound_manager_error_code(__func__, ret);
936 int sound_manager_get_device_name(sound_device_h device, char **name)
938 int ret = MM_ERROR_NONE;
939 ret = mm_sound_get_device_name(device, name);
941 return _convert_sound_manager_error_code(__func__, ret);
944 int sound_manager_get_device_state(sound_device_h device, sound_device_state_e *state)
946 int ret = MM_ERROR_NONE;
947 ret = mm_sound_get_device_state(device, (mm_sound_device_state_e*)state);
949 return _convert_sound_manager_error_code(__func__, ret);
952 int sound_manager_set_device_connected_cb(sound_device_mask_e device_mask, sound_device_connected_cb callback, void *user_data)
954 int ret = MM_ERROR_NONE;
955 unsigned int subs_id = 0;
957 SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_device_conn_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
959 ret = mm_sound_add_device_connected_callback((mm_sound_device_flags_e)device_mask, (mm_sound_device_connected_cb)callback, user_data, &subs_id);
960 if (ret == MM_ERROR_NONE) {
961 g_device_connected_cb_table.subs_id = subs_id;
962 g_device_connected_cb_table.user_cb = (sound_device_connected_cb)callback;
963 g_device_connected_cb_table.user_data = user_data;
966 SM_LEAVE_CRITICAL_SECTION(&g_device_conn_cb_mutex);
968 return _convert_sound_manager_error_code(__func__, ret);
971 int sound_manager_unset_device_connected_cb(void)
973 int ret = MM_ERROR_NONE;
975 SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_device_conn_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
977 if (g_device_connected_cb_table.subs_id > 0) {
978 ret = mm_sound_remove_device_connected_callback(g_device_connected_cb_table.subs_id);
979 if (ret == MM_ERROR_NONE) {
980 g_device_connected_cb_table.subs_id = 0;
981 g_device_connected_cb_table.user_cb = NULL;
982 g_device_connected_cb_table.user_data = NULL;
985 ret = MM_ERROR_SOUND_INTERNAL;
987 SM_LEAVE_CRITICAL_SECTION(&g_device_conn_cb_mutex);
989 return _convert_sound_manager_error_code(__func__, ret);
992 int sound_manager_set_device_information_changed_cb(sound_device_mask_e device_mask, sound_device_information_changed_cb callback, void *user_data)
994 int ret = MM_ERROR_NONE;
995 unsigned int subs_id = 0;
997 SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_device_info_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
999 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);
1000 if (ret == MM_ERROR_NONE) {
1001 g_device_info_changed_cb_table.subs_id = subs_id;
1002 g_device_info_changed_cb_table.user_cb = (sound_device_information_changed_cb)callback;
1003 g_device_info_changed_cb_table.user_data = user_data;
1006 SM_LEAVE_CRITICAL_SECTION(&g_device_info_cb_mutex);
1008 return _convert_sound_manager_error_code(__func__, ret);
1011 int sound_manager_unset_device_information_changed_cb(void)
1013 int ret = MM_ERROR_NONE;
1015 SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_device_info_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
1017 if (g_device_info_changed_cb_table.subs_id) {
1018 ret = mm_sound_remove_device_information_changed_callback(g_device_info_changed_cb_table.subs_id);
1019 if (ret == MM_ERROR_NONE) {
1020 g_device_info_changed_cb_table.subs_id = 0;
1021 g_device_info_changed_cb_table.user_cb = NULL;
1022 g_device_info_changed_cb_table.user_data = NULL;
1025 ret = MM_ERROR_SOUND_INTERNAL;
1028 SM_LEAVE_CRITICAL_SECTION(&g_device_info_cb_mutex);
1030 return _convert_sound_manager_error_code(__func__, ret);
1033 __attribute__ ((destructor))
1034 void __sound_manager_finalize(void)
1036 int ret = MM_ERROR_NONE;
1038 if (g_session_interrupt_cb_table.is_registered) {
1040 ret = mm_session_finish();
1041 if (ret != MM_ERROR_NONE)
1042 LOGE("[%s] failed to mm_session_finish(), ret(%p)", __func__, ret);
1044 g_session_interrupt_cb_table.is_registered = 0;
1049 __attribute__ ((constructor))
1050 void __sound_manager_initialize(void)