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"
22 _session_interrupt_info_s g_session_interrupt_cb_table = {0, 0, NULL, NULL};
23 _volume_changed_info_s g_volume_changed_cb_table = {0, NULL, NULL};
24 _focus_watch_info_s g_focus_watch_cb_table = {-1, 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};
28 sound_session_type_e g_cached_session = -1;
29 _session_mode_e g_cached_session_mode = -1;
31 /* These variables will be removed when session features are deprecated. */
32 extern int g_stream_info_count;
33 extern pthread_mutex_t g_stream_info_count_mutex;
34 pthread_mutex_t g_interrupt_cb_mutex, g_device_info_cb_mutex, g_device_conn_cb_mutex, g_volume_cb_mutex;
37 /*temporary variable for set/get voip session mode. When 2.4 feature for routing is fully implemented, it will be removed.*/
38 sound_session_voip_mode_e tmp_mode = -1;
41 int sound_manager_get_max_volume (sound_type_e type, int *max)
43 const char *volume_type = NULL;
44 unsigned int max_level = 0;
45 int ret = MM_ERROR_NONE;
48 return __convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
50 if (type >= SOUND_TYPE_NUM || type < 0)
51 return __convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
52 ret = __convert_sound_type (type, &volume_type);
53 if (ret == MM_ERROR_NONE) {
54 ret = __get_volume_max_level("out", volume_type, &max_level);
55 if (ret == MM_ERROR_NONE)
56 *max = (int)max_level -1; // actual volume step can be max step - 1
59 return __convert_sound_manager_error_code(__func__, ret);
62 int sound_manager_set_volume (sound_type_e type, int volume)
64 int ret = MM_ERROR_NONE;
66 if (type >= SOUND_TYPE_NUM || type < 0)
67 return __convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
69 return __convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
71 ret = mm_sound_volume_set_value(type, volume);
72 LOGI("returns : type=%d, volume=%d, ret=%p", type, volume, ret);
74 return __convert_sound_manager_error_code(__func__, ret);
77 int sound_manager_get_volume (sound_type_e type, int *volume)
79 int ret = MM_ERROR_NONE;
82 if (type >= SOUND_TYPE_NUM || type < 0)
83 return __convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
85 return __convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
87 ret = mm_sound_volume_get_value(type, &uvolume);
88 if (ret == MM_ERROR_NONE)
91 LOGI("returns : type=%d, volume=%d, ret=%p", type, *volume, ret);
93 return __convert_sound_manager_error_code(__func__, ret);
96 int sound_manager_set_current_sound_type (sound_type_e type)
98 int ret = MM_ERROR_NONE;
100 if (type >= SOUND_TYPE_NUM || type < 0)
101 return __convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
103 ret = mm_sound_volume_primary_type_set(type);
105 return __convert_sound_manager_error_code(__func__, ret);
108 int sound_manager_get_current_sound_type (sound_type_e *type)
110 int ret = MM_ERROR_NONE;
111 volume_type_t mm_sound_vol_type = VOLUME_TYPE_UNKNOWN;
112 char *volume_type = NULL;
115 return __convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
117 ret = mm_sound_volume_primary_type_get(&mm_sound_vol_type);
118 if (ret == MM_ERROR_NONE) {
119 if (mm_sound_vol_type == VOLUME_TYPE_UNKNOWN) {
120 /* get the volume type of the current playing stream */
121 ret = __get_current_volume_type ("out", &volume_type);
122 if (ret == MM_ERROR_NONE) {
123 ret = __convert_sound_type_to_enum (volume_type, type);
127 *type = mm_sound_vol_type;
130 LOGI("returns : type=%d, ret=%p", *type, ret);
132 return __convert_sound_manager_error_code(__func__, ret);
135 int sound_manager_unset_current_sound_type (void)
137 int ret = MM_ERROR_NONE;
139 ret = mm_sound_volume_primary_type_set(VOLUME_TYPE_UNKNOWN);
141 return __convert_sound_manager_error_code(__func__, ret);
144 int sound_manager_set_volume_changed_cb (sound_manager_volume_changed_cb callback, void* user_data)
146 int ret = MM_ERROR_NONE;
147 unsigned int subs_id = 0;
149 SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_volume_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
151 ret = mm_sound_add_volume_changed_callback((mm_sound_volume_changed_cb)callback, user_data, &subs_id);
152 if (ret == MM_ERROR_NONE) {
153 g_volume_changed_cb_table.subs_id = subs_id;
154 g_volume_changed_cb_table.user_cb = (sound_manager_volume_changed_cb)callback;
155 g_volume_changed_cb_table.user_data = user_data;
158 SM_LEAVE_CRITICAL_SECTION(&g_volume_cb_mutex);
160 return __convert_sound_manager_error_code(__func__, ret);
163 int sound_manager_unset_volume_changed_cb (void)
165 int ret = MM_ERROR_NONE;
167 SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_volume_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
169 if (g_volume_changed_cb_table.subs_id > 0) {
170 ret = mm_sound_remove_volume_changed_callback(g_volume_changed_cb_table.subs_id);
171 if (ret == MM_ERROR_NONE) {
172 g_volume_changed_cb_table.subs_id = 0;
173 g_volume_changed_cb_table.user_cb = NULL;
174 g_volume_changed_cb_table.user_data = NULL;
177 ret = MM_ERROR_SOUND_INTERNAL;
180 SM_LEAVE_CRITICAL_SECTION(&g_volume_cb_mutex);
182 return __convert_sound_manager_error_code(__func__, ret);
185 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)
187 int ret = MM_ERROR_NONE;
191 SM_NULL_ARG_CHECK(stream_info);
192 SM_NULL_ARG_CHECK(callback);
194 if (g_session_interrupt_cb_table.is_registered)
195 return __convert_sound_manager_error_code(__func__, MM_ERROR_SOUND_INTERNAL);
197 sound_stream_info_s *stream_h = malloc(sizeof(sound_stream_info_s));
199 ret = MM_ERROR_OUT_OF_MEMORY;
201 memset(stream_h, 0, sizeof(sound_stream_info_s));
202 ret = __convert_stream_type(stream_type, &stream_h->stream_type);
203 if (ret == MM_ERROR_NONE) {
204 ret = _make_pa_connection_and_register_focus(stream_h, callback, user_data);
205 if (ret == MM_ERROR_NONE) {
206 *stream_info = (sound_stream_info_h)stream_h;
207 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);
215 return __convert_sound_manager_error_code(__func__, ret);
218 int sound_manager_destroy_stream_information (sound_stream_info_h stream_info)
220 int ret = MM_ERROR_NONE;
221 sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
225 SM_INSTANCE_CHECK(stream_h);
227 ret = _destroy_pa_connection_and_unregister_focus(stream_h);
229 LOGI("<< leave : cnt(%d), ret(%p)", g_stream_info_count, ret);
231 return __convert_sound_manager_error_code(__func__, ret);
234 int sound_manager_add_device_for_stream_routing (sound_stream_info_h stream_info, sound_device_h device)
236 int ret = MM_ERROR_NONE;
239 bool added_successfully = false;
240 char *device_type_str = NULL;
242 mm_sound_device_type_e device_type;
243 mm_sound_device_io_direction_e device_direction;
244 sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
248 SM_INSTANCE_CHECK(stream_h);
249 SM_NULL_ARG_CHECK(device);
251 if (stream_h->stream_conf_info.route_type == STREAM_ROUTE_TYPE_MANUAL) {
252 ret = mm_sound_get_device_id(device, &device_id);
254 return __convert_sound_manager_error_code(__func__, ret);
256 ret = mm_sound_get_device_type(device, &device_type);
258 return __convert_sound_manager_error_code(__func__, ret);
260 ret = __convert_device_type(device_type, &device_type_str);
262 return __convert_sound_manager_error_code(__func__, ret);
264 ret = mm_sound_get_device_io_direction(device, &device_direction);
266 return __convert_sound_manager_error_code(__func__, ret);
268 if (device_direction == MM_SOUND_DEVICE_IO_DIRECTION_IN || device_direction == MM_SOUND_DEVICE_IO_DIRECTION_BOTH) {
269 for (i = 0; i < AVAIL_DEVICES_MAX; i++) {
270 if (stream_h->stream_conf_info.avail_in_devices[i]) {
271 if (!strncmp(stream_h->stream_conf_info.avail_in_devices[i], device_type_str, SOUND_DEVICE_TYPE_LEN)) {
272 for (j = 0; j < AVAIL_DEVICES_MAX; j++) {
273 if (!stream_h->manual_route_info.route_in_devices[j]) {
274 stream_h->manual_route_info.route_in_devices[j] = (unsigned int)device_id;
275 added_successfully = true;
278 if (stream_h->manual_route_info.route_in_devices[j] == (unsigned int)device_id) {
279 /* it was already set */
280 return __convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_DUPLICATED);
289 if (device_direction == MM_SOUND_DEVICE_IO_DIRECTION_OUT || device_direction == MM_SOUND_DEVICE_IO_DIRECTION_BOTH) {
290 for (i = 0; i < AVAIL_DEVICES_MAX; i++) {
291 if (stream_h->stream_conf_info.avail_out_devices[i]) {
292 if (!strncmp(stream_h->stream_conf_info.avail_out_devices[i], device_type_str, SOUND_DEVICE_TYPE_LEN)) {
293 for (j = 0; j < AVAIL_DEVICES_MAX; j++) {
294 if (!stream_h->manual_route_info.route_out_devices[j]) {
295 stream_h->manual_route_info.route_out_devices[j] = (unsigned int)device_id;
296 added_successfully = true;
299 if (stream_h->manual_route_info.route_out_devices[j] == (unsigned int)device_id) {
300 /* it was already set */
301 return __convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_DUPLICATED);
312 if (!added_successfully) {
313 ret = MM_ERROR_POLICY_INTERNAL;
316 LOGI("<< leave : ret(%p)", ret);
318 return __convert_sound_manager_error_code(__func__, ret);
321 int sound_manager_remove_device_for_stream_routing (sound_stream_info_h stream_info, sound_device_h device)
323 int ret = MM_ERROR_NONE;
326 bool removed_successfully = false;
327 char *device_type_str = NULL;
329 mm_sound_device_type_e device_type;
330 mm_sound_device_io_direction_e device_direction;
331 sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
335 SM_INSTANCE_CHECK(stream_h);
336 SM_NULL_ARG_CHECK(device);
338 if (stream_h->stream_conf_info.route_type == STREAM_ROUTE_TYPE_MANUAL) {
339 ret = mm_sound_get_device_id(device, &device_id);
341 return __convert_sound_manager_error_code(__func__, ret);
343 ret = mm_sound_get_device_type(device, &device_type);
345 return __convert_sound_manager_error_code(__func__, ret);
347 ret = __convert_device_type(device_type, &device_type_str);
348 ret = mm_sound_get_device_io_direction(device, &device_direction);
350 return __convert_sound_manager_error_code(__func__, ret);
352 if (device_direction == MM_SOUND_DEVICE_IO_DIRECTION_IN || device_direction == MM_SOUND_DEVICE_IO_DIRECTION_BOTH) {
353 for (i = 0; i < AVAIL_DEVICES_MAX; i++) {
354 if (stream_h->stream_conf_info.avail_in_devices[i]) {
355 if (!strncmp(stream_h->stream_conf_info.avail_in_devices[i], device_type_str, SOUND_DEVICE_TYPE_LEN)) {
356 for (j = 0; j < AVAIL_DEVICES_MAX; j++) {
357 if (stream_h->manual_route_info.route_in_devices[j] == (unsigned int)device_id) {
358 removed_successfully = true;
359 stream_h->manual_route_info.route_in_devices[j] = 0;
369 if (device_direction == MM_SOUND_DEVICE_IO_DIRECTION_OUT || device_direction == MM_SOUND_DEVICE_IO_DIRECTION_BOTH) {
370 for (i = 0; i < AVAIL_DEVICES_MAX; i++) {
371 if (stream_h->stream_conf_info.avail_out_devices[i]) {
372 if (!strncmp(stream_h->stream_conf_info.avail_out_devices[i], device_type_str, SOUND_DEVICE_TYPE_LEN)) {
373 for (j = 0; j < AVAIL_DEVICES_MAX; j++) {
374 if (stream_h->manual_route_info.route_out_devices[j] == (unsigned int)device_id) {
375 removed_successfully = true;
376 stream_h->manual_route_info.route_out_devices[j] = 0;
388 if (!removed_successfully) {
389 ret = MM_ERROR_INVALID_ARGUMENT;
392 LOGI("<< leave : ret(%p)", ret);
394 return __convert_sound_manager_error_code(__func__, ret);
397 int sound_manager_apply_stream_routing (sound_stream_info_h stream_info)
399 int ret = MM_ERROR_NONE;
401 bool need_to_apply = false;
402 sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
406 SM_INSTANCE_CHECK(stream_h);
408 if (stream_h->stream_conf_info.route_type == STREAM_ROUTE_TYPE_MANUAL) {
409 for (i = 0; i < AVAIL_DEVICES_MAX; i++) {
410 if (stream_h->manual_route_info.route_in_devices[i]) {
411 need_to_apply = true;
414 if (stream_h->manual_route_info.route_out_devices[i]) {
415 need_to_apply = true;
420 ret = __set_manual_route_info(stream_h->index, &stream_h->manual_route_info);
422 __convert_sound_manager_error_code(__func__, MM_ERROR_SOUND_INVALID_STATE);
425 ret = MM_ERROR_SOUND_INVALID_STATE;
428 LOGI("<< leave : ret(%p)", ret);
430 return __convert_sound_manager_error_code(__func__, ret);
433 int sound_manager_acquire_focus (sound_stream_info_h stream_info, sound_stream_focus_mask_e focus_mask, const char *additional_info)
435 int ret = MM_ERROR_NONE;
436 sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
440 SM_INSTANCE_CHECK(stream_h);
442 ret = mm_sound_acquire_focus(stream_h->index, (mm_sound_focus_type_e)focus_mask, additional_info);
443 if (ret == MM_ERROR_NONE) {
444 stream_h->acquired_focus |= focus_mask;
445 __update_focus_status(stream_h->index, (unsigned int)stream_h->acquired_focus);
448 LOGI("<< leave : ret(%p)", ret);
450 return __convert_sound_manager_error_code(__func__, ret);
453 int sound_manager_release_focus (sound_stream_info_h stream_info, sound_stream_focus_mask_e focus_mask, const char *additional_info)
455 int ret = MM_ERROR_NONE;
456 sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
460 SM_INSTANCE_CHECK(stream_h);
462 ret = mm_sound_release_focus(stream_h->index, (mm_sound_focus_type_e)focus_mask, additional_info);
463 if (ret == MM_ERROR_NONE) {
464 stream_h->acquired_focus &= ~focus_mask;
465 __update_focus_status(stream_h->index, (unsigned int)stream_h->acquired_focus);
468 LOGI("<< leave : ret(%p)", ret);
470 return __convert_sound_manager_error_code(__func__, ret);
473 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)
475 int ret = MM_ERROR_NONE;
476 sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
480 SM_INSTANCE_CHECK(stream_h);
481 if (!state_for_playback && !state_for_recording)
482 ret = MM_ERROR_INVALID_ARGUMENT;
484 if (state_for_playback)
485 *state_for_playback = (stream_h->acquired_focus & SOUND_STREAM_FOCUS_FOR_PLAYBACK)?SOUND_STREAM_FOCUS_STATE_ACQUIRED:SOUND_STREAM_FOCUS_STATE_RELEASED;
486 if (state_for_recording)
487 *state_for_recording = (stream_h->acquired_focus & SOUND_STREAM_FOCUS_FOR_RECORDING)?SOUND_STREAM_FOCUS_STATE_ACQUIRED:SOUND_STREAM_FOCUS_STATE_RELEASED;
489 LOGI("<< leave : acquired_focus(%p)", stream_h->acquired_focus);
491 return __convert_sound_manager_error_code(__func__, ret);
494 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)
496 int ret = MM_ERROR_NONE;
501 SM_NULL_ARG_CHECK(callback);
502 SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_stream_info_count_mutex, SOUND_MANAGER_ERROR_INTERNAL);
504 if (!g_focus_watch_cb_table.user_cb) {
505 SM_REF_FOR_STREAM_INFO(g_stream_info_count, ret);
506 ret = mm_sound_set_focus_watch_callback((mm_sound_focus_type_e)focus_mask, _focus_watch_callback, user_data, &id);
507 if (ret == MM_ERROR_NONE) {
508 g_focus_watch_cb_table.index = id;
509 g_focus_watch_cb_table.user_cb = callback;
510 g_focus_watch_cb_table.user_data = user_data;
513 ret = MM_ERROR_SOUND_INTERNAL;
516 SM_LEAVE_CRITICAL_SECTION(&g_stream_info_count_mutex);
518 LOGI("<< leave : cnt(%d), ret(%p)", g_stream_info_count, ret);
520 return __convert_sound_manager_error_code(__func__, ret);
523 int sound_manager_unset_focus_state_watch_cb (void)
525 int ret = MM_ERROR_NONE;
529 SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_stream_info_count_mutex, SOUND_MANAGER_ERROR_INTERNAL);
531 if (g_focus_watch_cb_table.user_cb) {
532 ret = mm_sound_unset_focus_watch_callback(g_focus_watch_cb_table.index);
533 if (ret == MM_ERROR_NONE) {
534 g_focus_watch_cb_table.index = -1;
535 g_focus_watch_cb_table.user_cb = NULL;
536 g_focus_watch_cb_table.user_data = NULL;
537 SM_UNREF_FOR_STREAM_INFO(g_stream_info_count, ret);
539 ret = MM_ERROR_SOUND_INTERNAL;
542 ret = MM_ERROR_SOUND_INTERNAL;
545 SM_LEAVE_CRITICAL_SECTION(&g_stream_info_count_mutex);
547 LOGI("<< leave : cnt(%d), ret(%p)", g_stream_info_count, ret);
549 return __convert_sound_manager_error_code(__func__, ret);
552 int sound_manager_set_session_type (sound_session_type_e type)
554 int ret = MM_ERROR_NONE;
555 int cur_session = -1;
556 int new_session = MM_SESSION_TYPE_MEDIA;
558 LOGI(">> enter : type=%d", type);
560 if (type < SOUND_SESSION_TYPE_MEDIA || type > SOUND_SESSION_TYPE_VOIP)
561 return __convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
563 /* it is not supported both session and stream feature at the same time */
564 if (g_stream_info_count)
565 return __convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
568 case SOUND_SESSION_TYPE_MEDIA:
569 new_session = MM_SESSION_TYPE_MEDIA;
571 case SOUND_SESSION_TYPE_ALARM:
572 new_session = MM_SESSION_TYPE_ALARM;
574 case SOUND_SESSION_TYPE_NOTIFICATION:
575 new_session = MM_SESSION_TYPE_NOTIFY;
577 case SOUND_SESSION_TYPE_EMERGENCY:
578 new_session = MM_SESSION_TYPE_EMERGENCY;
580 case SOUND_SESSION_TYPE_VOIP:
581 new_session = MM_SESSION_TYPE_VOIP;
585 /* valid session check */
586 ret = mm_session_get_current_type(&cur_session);
587 if (ret == MM_ERROR_NONE) {
588 if (cur_session == MM_SESSION_TYPE_MEDIA_RECORD) {
589 if (type > SOUND_SESSION_TYPE_MEDIA) {
590 LOGE("<< leave : Could not set this type(%d) during camera/recorder/audio-io(in)/radio", type);
591 return __convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
594 if (cur_session == MM_SESSION_TYPE_VIDEOCALL ||
595 cur_session >= MM_SESSION_TYPE_VOICE_RECOGNITION) {
596 return __convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
600 if (g_session_interrupt_cb_table.is_registered) {
601 if (new_session == cur_session ||
602 ((new_session == SOUND_SESSION_TYPE_MEDIA) && (cur_session == MM_SESSION_TYPE_MEDIA_RECORD))) {
603 LOGI("<< leave : already set type=%d, ret=%p", type, ret);
604 return SOUND_MANAGER_ERROR_NONE;
606 ret = mm_session_finish();
607 if (ret != MM_ERROR_NONE) {
608 return __convert_sound_manager_error_code(__func__, ret);
610 g_session_interrupt_cb_table.is_registered = 0;
611 g_cached_session_mode = -1;
614 ret = mm_session_init_ex(new_session , __session_interrupt_cb, NULL);
615 if (ret == MM_ERROR_NONE) {
616 g_session_interrupt_cb_table.is_registered = 1;
618 if (new_session == MM_SESSION_TYPE_VOIP || new_session == MM_SESSION_TYPE_CALL) {
619 /* set default sub-session for voip */
620 ret = mm_session_set_subsession (MM_SUBSESSION_TYPE_RINGTONE, MM_SUBSESSION_OPTION_NONE);
621 if (ret != MM_ERROR_NONE) {
622 return __convert_sound_manager_error_code(__func__, ret);
624 g_cached_session_mode = _SESSION_MODE_RINGTONE;
626 LOGI("<< leave : type=%d, ret=%p", type, ret);
628 return __convert_sound_manager_error_code(__func__, ret);
631 int sound_manager_get_session_type (sound_session_type_e *type)
633 int ret = MM_ERROR_NONE;
637 return __convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
638 ret = mm_session_get_current_type(&cur_session);
640 LOGW("session hasn't been set, setting default session");
641 cur_session = SOUND_SESSION_TYPE_DEFAULT;
642 ret = mm_session_init_ex(cur_session, __session_interrupt_cb, NULL);
644 g_session_interrupt_cb_table.is_registered = 1;
647 if ((cur_session > MM_SESSION_TYPE_EMERGENCY) &&
648 (cur_session != MM_SESSION_TYPE_VOIP)) {
649 if (g_cached_session != -1)
650 cur_session = g_cached_session;
651 else //will be never reach here. just prevent code
652 cur_session = SOUND_SESSION_TYPE_DEFAULT;
655 switch (cur_session) {
656 case MM_SESSION_TYPE_MEDIA:
657 case MM_SESSION_TYPE_MEDIA_RECORD:
658 *type = SOUND_SESSION_TYPE_MEDIA;
660 case MM_SESSION_TYPE_ALARM:
661 *type = SOUND_SESSION_TYPE_ALARM;
663 case MM_SESSION_TYPE_NOTIFY:
664 *type = SOUND_SESSION_TYPE_NOTIFICATION;
666 case MM_SESSION_TYPE_EMERGENCY:
667 *type = SOUND_SESSION_TYPE_EMERGENCY;
669 case MM_SESSION_TYPE_VOIP:
670 *type = SOUND_SESSION_TYPE_VOIP;
677 LOGI("returns : type=%d, ret=%p", *type, ret);
682 int sound_manager_set_media_session_option (sound_session_option_for_starting_e s_option, sound_session_option_for_during_play_e d_option)
684 int ret = MM_ERROR_NONE;
686 int session_option = 0;
689 LOGI(">> enter : option for starting=%d, for during play=%d", s_option, d_option);
691 if (s_option < 0 || s_option > SOUND_SESSION_OPTION_PAUSE_OTHERS_WHEN_START)
692 return __convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
693 if (d_option < 0 || d_option > SOUND_SESSION_OPTION_UNINTERRUPTIBLE_DURING_PLAY)
694 return __convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
696 ret = mm_session_get_current_information(&session, &session_option);
697 if (ret != 0 || !g_session_interrupt_cb_table.is_registered) {
698 LOGW("session hasn't been set, setting default session");
699 ret = mm_session_init_ex(MM_SESSION_TYPE_MEDIA, __session_interrupt_cb, NULL);
701 g_session_interrupt_cb_table.is_registered = 1;
703 } else if (ret == 0 && session > MM_SESSION_TYPE_MEDIA) {
704 if (session == MM_SESSION_TYPE_MEDIA_RECORD) {
705 if (!g_session_interrupt_cb_table.is_registered) {
706 LOGE("Already set by camera/recorder/audio-io(in)/radio API, but need to set session to Media first");
707 return __convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
710 return __convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
715 case SOUND_SESSION_OPTION_MIX_WITH_OTHERS_WHEN_START:
716 if (session_option & MM_SESSION_OPTION_PAUSE_OTHERS) {
717 ret = mm_session_update_option(MM_SESSION_UPDATE_TYPE_REMOVE, MM_SESSION_OPTION_PAUSE_OTHERS);
719 return __convert_sound_manager_error_code(__func__, ret);
724 case SOUND_SESSION_OPTION_PAUSE_OTHERS_WHEN_START:
725 if (!(session_option & MM_SESSION_OPTION_PAUSE_OTHERS)) {
726 ret = mm_session_update_option(MM_SESSION_UPDATE_TYPE_ADD, MM_SESSION_OPTION_PAUSE_OTHERS);
728 return __convert_sound_manager_error_code(__func__, ret);
736 case SOUND_SESSION_OPTION_INTERRUPTIBLE_DURING_PLAY:
737 if (session_option & MM_SESSION_OPTION_UNINTERRUPTIBLE) {
738 ret = mm_session_update_option(MM_SESSION_UPDATE_TYPE_REMOVE, MM_SESSION_OPTION_UNINTERRUPTIBLE);
740 return __convert_sound_manager_error_code(__func__, ret);
745 case SOUND_SESSION_OPTION_UNINTERRUPTIBLE_DURING_PLAY:
746 if (!(session_option & MM_SESSION_OPTION_UNINTERRUPTIBLE)) {
747 ret = mm_session_update_option(MM_SESSION_UPDATE_TYPE_ADD, MM_SESSION_OPTION_UNINTERRUPTIBLE);
749 return __convert_sound_manager_error_code(__func__, ret);
757 LOGI("<< leave : updated");
759 LOGI("<< leave : already set same option(%x), skip it", session_option);
762 return __convert_sound_manager_error_code(__func__, ret);
765 int sound_manager_get_media_session_option (sound_session_option_for_starting_e *s_option, sound_session_option_for_during_play_e *d_option)
767 int ret = MM_ERROR_NONE;
769 int session_options = 0;
773 if (s_option == NULL || d_option == NULL)
774 return __convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
776 ret = mm_session_get_current_information(&session, &session_options);
778 ret = mm_session_init_ex(MM_SESSION_TYPE_MEDIA, __session_interrupt_cb, NULL);
780 g_session_interrupt_cb_table.is_registered = 1;
782 } else if (session > SOUND_SESSION_TYPE_MEDIA) {
783 if (session == MM_SESSION_TYPE_MEDIA_RECORD) {
784 if (!g_session_interrupt_cb_table.is_registered) {
785 LOGE("Already set by camera/recorder/audio-io(in)/radio API, but need to set session to Media first");
786 return __convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
789 return __convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
793 if (session_options & MM_SESSION_OPTION_PAUSE_OTHERS) {
794 *s_option = SOUND_SESSION_OPTION_PAUSE_OTHERS_WHEN_START;
796 *s_option = SOUND_SESSION_OPTION_MIX_WITH_OTHERS_WHEN_START;
798 if (session_options & MM_SESSION_OPTION_UNINTERRUPTIBLE) {
799 *d_option = SOUND_SESSION_OPTION_UNINTERRUPTIBLE_DURING_PLAY;
801 *d_option = SOUND_SESSION_OPTION_INTERRUPTIBLE_DURING_PLAY;
804 LOGI("<< leave : option for starting=%d, for during play=%d", *s_option, *d_option);
806 return SOUND_MANAGER_ERROR_NONE;
809 int sound_manager_set_media_session_resumption_option (sound_session_option_for_resumption_e option)
811 int ret = MM_ERROR_NONE;
813 int session_option = 0;
816 LOGI(">> enter : option for resumption=%d (0:by system, 1:by system or media paused)", option);
818 if (option < SOUND_SESSION_OPTION_RESUMPTION_BY_SYSTEM || option > SOUND_SESSION_OPTION_RESUMPTION_BY_SYSTEM_OR_MEDIA_PAUSED)
819 return __convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
821 ret = mm_session_get_current_information(&session, &session_option);
822 if (ret != 0 || !g_session_interrupt_cb_table.is_registered) {
823 LOGW("session hasn't been set, setting default session");
824 ret = mm_session_init_ex(MM_SESSION_TYPE_MEDIA, __session_interrupt_cb, NULL);
826 g_session_interrupt_cb_table.is_registered = 1;
828 } else if (ret == 0 && session > MM_SESSION_TYPE_MEDIA) {
829 if (session == MM_SESSION_TYPE_MEDIA_RECORD) {
830 if (!g_session_interrupt_cb_table.is_registered) {
831 LOGE("Already set by camera/recorder/audio-io(in)/radio API, but need to set session to Media first");
832 return __convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
835 return __convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
840 case SOUND_SESSION_OPTION_RESUMPTION_BY_SYSTEM:
841 if (session_option & MM_SESSION_OPTION_RESUME_BY_SYSTEM_OR_MEDIA_PAUSED) {
842 ret = mm_session_update_option(MM_SESSION_UPDATE_TYPE_REMOVE, MM_SESSION_OPTION_RESUME_BY_SYSTEM_OR_MEDIA_PAUSED);
844 return __convert_sound_manager_error_code(__func__, ret);
849 case SOUND_SESSION_OPTION_RESUMPTION_BY_SYSTEM_OR_MEDIA_PAUSED:
850 if (!(session_option & MM_SESSION_OPTION_RESUME_BY_SYSTEM_OR_MEDIA_PAUSED)) {
851 ret = mm_session_update_option(MM_SESSION_UPDATE_TYPE_ADD, MM_SESSION_OPTION_RESUME_BY_SYSTEM_OR_MEDIA_PAUSED);
853 return __convert_sound_manager_error_code(__func__, ret);
861 LOGI("<< leave : updated");
863 LOGI("<< leave : already set same option(%x), skip it", session_option);
866 return __convert_sound_manager_error_code(__func__, ret);
869 int sound_manager_get_media_session_resumption_option (sound_session_option_for_resumption_e *option)
871 int ret = MM_ERROR_NONE;
873 int session_options = 0;
878 return __convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
879 ret = mm_session_get_current_information(&session, &session_options);
881 LOGW("session hasn't been set, setting default session");
882 ret = mm_session_init_ex(MM_SESSION_TYPE_MEDIA, __session_interrupt_cb, NULL);
884 g_session_interrupt_cb_table.is_registered = 1;
886 } else if (session > SOUND_SESSION_TYPE_MEDIA) {
887 if (session == MM_SESSION_TYPE_MEDIA_RECORD) {
888 if (!g_session_interrupt_cb_table.is_registered) {
889 LOGE("Already set by camera/recorder/audio-io(in)/radio API, but need to set session to Media first");
890 return __convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
893 return __convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
897 if (session_options & MM_SESSION_OPTION_RESUME_BY_SYSTEM_OR_MEDIA_PAUSED) {
898 *option = SOUND_SESSION_OPTION_RESUMPTION_BY_SYSTEM_OR_MEDIA_PAUSED;
900 *option = SOUND_SESSION_OPTION_RESUMPTION_BY_SYSTEM;
903 LOGI("<< leave : option for resumption=%d (0:by system, 1:by system or media paused)", *option);
905 return SOUND_MANAGER_ERROR_NONE;
908 int sound_manager_set_voip_session_mode (sound_session_voip_mode_e mode)
910 int ret = MM_ERROR_NONE;
912 int session_options = 0;
914 LOGI(">> enter : mode=%d", mode);
916 ret = mm_session_get_current_information(&session, &session_options);
917 if (ret != MM_ERROR_NONE) {
918 return __convert_sound_manager_error_code(__func__, ret);
919 } else if (session != MM_SESSION_TYPE_VOIP) {
920 return __convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
922 if (mode < SOUND_SESSION_VOIP_MODE_RINGTONE || mode > SOUND_SESSION_VOIP_MODE_VOICE_WITH_BLUETOOTH) {
923 ret = MM_ERROR_INVALID_ARGUMENT;
924 return __convert_sound_manager_error_code(__func__, ret);
926 ret = __set_session_mode ((_session_mode_e)mode);
929 /* temporary code. When 2.4 feature for routing is fully implemented, it will be removed. */
933 LOGI("<< leave : session=%p, mode=%d, ret=%p", session, mode, ret);
935 return __convert_sound_manager_error_code(__func__, ret);
938 int sound_manager_get_voip_session_mode (sound_session_voip_mode_e *mode)
940 int ret = MM_ERROR_NONE;
942 int session_options = 0;
944 _session_mode_e _mode = 0;
948 LOGI("mode is null");
949 return __convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT);
952 ret = mm_session_get_current_information(&session, &session_options);
953 if (ret != MM_ERROR_NONE) {
954 LOGI("session = %d, option = %d", session, session_options);
955 return __convert_sound_manager_error_code(__func__, ret);
956 } else if (session != MM_SESSION_TYPE_VOIP) {
957 return __convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
961 /* temporary code. When 2.4 feature for routing is fully implemented, it will be removed. */
964 ret = __get_session_mode(&_mode);
965 if (ret == MM_ERROR_NONE)
966 *mode = (sound_session_voip_mode_e)_mode;
969 LOGI("returns : session=%p, mode=%d, ret=%p", session, *mode, ret);
971 return __convert_sound_manager_error_code(__func__, ret);
974 int sound_manager_set_session_interrupted_cb (sound_session_interrupted_cb callback, void *user_data)
976 int ret = MM_ERROR_NONE;
977 unsigned int subs_id = 0;
979 SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_interrupt_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
981 if (callback == NULL) {
982 ret = MM_ERROR_INVALID_ARGUMENT;
986 /* it is not supported both session and stream feature at the same time */
987 if (g_stream_info_count) {
988 ret = MM_ERROR_POLICY_INTERNAL;
992 if (g_session_interrupt_cb_table.is_registered == 0) {
993 ret = mm_sound_add_device_connected_callback(SOUND_DEVICE_ALL_MASK, (mm_sound_device_connected_cb)_device_connected_cb, NULL, &subs_id);
996 ret = mm_sound_focus_set_session_interrupt_callback((mm_sound_focus_session_interrupt_cb)_focus_session_interrupt_cb, NULL);
998 if(mm_sound_remove_device_connected_callback(subs_id) != MM_ERROR_NONE)
999 LOGW("mm_sound_remove_device_connected_callback failed");
1002 g_session_interrupt_cb_table.is_registered = 1;
1003 g_session_interrupt_cb_table.subs_id = subs_id;
1006 g_session_interrupt_cb_table.user_cb = (sound_session_interrupted_cb)callback;
1007 g_session_interrupt_cb_table.user_data = user_data;
1010 SM_LEAVE_CRITICAL_SECTION(&g_interrupt_cb_mutex);
1011 return __convert_sound_manager_error_code(__func__, ret);
1014 int sound_manager_unset_session_interrupted_cb (void)
1016 int ret = MM_ERROR_NONE;
1018 SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_interrupt_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
1020 if (g_session_interrupt_cb_table.user_cb) {
1021 ret = mm_sound_focus_unset_session_interrupt_callback();
1023 if(mm_sound_remove_device_connected_callback(g_session_interrupt_cb_table.subs_id) != MM_ERROR_NONE)
1024 LOGW("mm_sound_remove_device_connected_callback failed");
1027 ret = mm_sound_remove_device_connected_callback(g_session_interrupt_cb_table.subs_id);
1030 g_session_interrupt_cb_table.subs_id = 0;
1031 g_session_interrupt_cb_table.user_cb = NULL;
1032 g_session_interrupt_cb_table.user_data = NULL;
1033 g_session_interrupt_cb_table.is_registered = 0;
1035 ret = MM_ERROR_SOUND_INTERNAL;
1039 SM_LEAVE_CRITICAL_SECTION(&g_interrupt_cb_mutex);
1040 return __convert_sound_manager_error_code(__func__, ret);
1043 int sound_manager_get_current_device_list (sound_device_mask_e device_mask, sound_device_list_h *device_list)
1045 int ret = MM_ERROR_NONE;
1046 ret = mm_sound_get_current_device_list((mm_sound_device_flags_e)device_mask, device_list);
1048 return __convert_sound_manager_error_code(__func__, ret);
1051 int sound_manager_get_next_device (sound_device_list_h device_list, sound_device_h *device)
1053 int ret = MM_ERROR_NONE;
1054 ret = mm_sound_get_next_device(device_list, device);
1056 return __convert_sound_manager_error_code(__func__, ret);
1059 int sound_manager_get_prev_device (sound_device_list_h device_list, sound_device_h *device)
1061 int ret = MM_ERROR_NONE;
1062 ret = mm_sound_get_prev_device(device_list, device);
1064 return __convert_sound_manager_error_code(__func__, ret);
1067 int sound_manager_get_device_type (sound_device_h device, sound_device_type_e *type)
1069 int ret = MM_ERROR_NONE;
1070 ret = mm_sound_get_device_type(device, (mm_sound_device_type_e*)type);
1072 return __convert_sound_manager_error_code(__func__, ret);
1075 int sound_manager_get_device_io_direction (sound_device_h device, sound_device_io_direction_e *io_direction)
1077 int ret = MM_ERROR_NONE;
1078 mm_sound_device_io_direction_e mm_sound_io_direction;
1079 ret = mm_sound_get_device_io_direction(device, &mm_sound_io_direction);
1080 if (ret == MM_ERROR_NONE) {
1081 ret = __convert_device_io_direction(mm_sound_io_direction, io_direction);
1084 return __convert_sound_manager_error_code(__func__, ret);
1087 int sound_manager_get_device_id (sound_device_h device, int *id)
1089 int ret = MM_ERROR_NONE;
1090 ret = mm_sound_get_device_id(device, id);
1092 return __convert_sound_manager_error_code(__func__, ret);
1095 int sound_manager_get_device_name (sound_device_h device, char **name)
1097 int ret = MM_ERROR_NONE;
1098 ret = mm_sound_get_device_name(device, name);
1100 return __convert_sound_manager_error_code(__func__, ret);
1103 int sound_manager_get_device_state (sound_device_h device, sound_device_state_e *state)
1105 int ret = MM_ERROR_NONE;
1106 ret = mm_sound_get_device_state(device, (mm_sound_device_state_e*)state);
1108 return __convert_sound_manager_error_code(__func__, ret);
1111 int sound_manager_set_device_connected_cb (sound_device_mask_e device_mask, sound_device_connected_cb callback, void *user_data)
1113 int ret = MM_ERROR_NONE;
1114 unsigned int subs_id = 0;
1116 SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_device_conn_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
1118 ret = mm_sound_add_device_connected_callback((mm_sound_device_flags_e)device_mask, (mm_sound_device_connected_cb)callback, user_data, &subs_id);
1119 if (ret == MM_ERROR_NONE) {
1120 g_device_connected_cb_table.subs_id = subs_id;
1121 g_device_connected_cb_table.user_cb = (sound_device_connected_cb)callback;
1122 g_device_connected_cb_table.user_data = user_data;
1125 SM_LEAVE_CRITICAL_SECTION(&g_device_conn_cb_mutex);
1127 return __convert_sound_manager_error_code(__func__, ret);
1130 int sound_manager_unset_device_connected_cb (void)
1132 int ret = MM_ERROR_NONE;
1134 SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_device_conn_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
1136 if (g_device_connected_cb_table.subs_id > 0) {
1137 ret = mm_sound_remove_device_connected_callback(g_device_connected_cb_table.subs_id);
1138 if (ret == MM_ERROR_NONE) {
1139 g_device_connected_cb_table.subs_id = 0;
1140 g_device_connected_cb_table.user_cb = NULL;
1141 g_device_connected_cb_table.user_data = NULL;
1144 ret = MM_ERROR_SOUND_INTERNAL;
1147 SM_LEAVE_CRITICAL_SECTION(&g_device_conn_cb_mutex);
1149 return __convert_sound_manager_error_code(__func__, ret);
1152 int sound_manager_set_device_information_changed_cb (sound_device_mask_e device_mask, sound_device_information_changed_cb callback, void *user_data)
1154 int ret = MM_ERROR_NONE;
1155 unsigned int subs_id = 0;
1157 SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_device_info_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
1159 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);
1160 if (ret == MM_ERROR_NONE) {
1161 g_device_info_changed_cb_table.subs_id = subs_id;
1162 g_device_info_changed_cb_table.user_cb = (sound_device_information_changed_cb)callback;
1163 g_device_info_changed_cb_table.user_data = user_data;
1166 SM_LEAVE_CRITICAL_SECTION(&g_device_info_cb_mutex);
1168 return __convert_sound_manager_error_code(__func__, ret);
1171 int sound_manager_unset_device_information_changed_cb (void)
1173 int ret = MM_ERROR_NONE;
1175 SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_device_info_cb_mutex, SOUND_MANAGER_ERROR_INTERNAL);
1177 if (g_device_info_changed_cb_table.subs_id) {
1178 ret = mm_sound_remove_device_information_changed_callback(g_device_info_changed_cb_table.subs_id);
1179 if (ret == MM_ERROR_NONE) {
1180 g_device_info_changed_cb_table.subs_id = 0;
1181 g_device_info_changed_cb_table.user_cb = NULL;
1182 g_device_info_changed_cb_table.user_data = NULL;
1185 ret = MM_ERROR_SOUND_INTERNAL;
1188 SM_LEAVE_CRITICAL_SECTION(&g_device_info_cb_mutex);
1190 return __convert_sound_manager_error_code(__func__, ret);
1193 __attribute__ ((destructor))
1194 void __sound_manager_finalize (void)
1196 int ret = MM_ERROR_NONE;
1198 if (g_session_interrupt_cb_table.is_registered) {
1200 ret = mm_session_finish();
1201 if (ret != MM_ERROR_NONE) {
1202 LOGE("[%s] failed to mm_session_finish(), ret(%p)", __func__, ret);
1204 g_session_interrupt_cb_table.is_registered = 0;
1209 __attribute__ ((constructor))
1210 void __sound_manager_initialize (void)