summaryrefslogtreecommitdiff
path: root/server/mm_sound_mgr_session.c
diff options
context:
space:
mode:
Diffstat (limited to 'server/mm_sound_mgr_session.c')
-rwxr-xr-xserver/mm_sound_mgr_session.c2903
1 files changed, 2903 insertions, 0 deletions
diff --git a/server/mm_sound_mgr_session.c b/server/mm_sound_mgr_session.c
new file mode 100755
index 0000000..5c01d54
--- /dev/null
+++ b/server/mm_sound_mgr_session.c
@@ -0,0 +1,2903 @@
+/*
+ * libmm-sound
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Seungbae Shin <seungbae.shin@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <pthread.h>
+#include <sys/shm.h>
+#include <sys/msg.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <errno.h>
+#ifdef TIZEN_MICRO
+#include <gio/gio.h>
+#endif
+#include <vconf.h>
+#include <mm_error.h>
+#include <mm_debug.h>
+#include <audio-session-manager.h>
+
+#include "../include/mm_sound_common.h"
+#include "../include/mm_sound_utils.h"
+#include "../include/mm_sound_device.h"
+#include "include/mm_sound_mgr_common.h"
+#include "include/mm_sound_mgr_session.h"
+#include "include/mm_sound_mgr_device.h"
+#include "include/mm_sound_mgr_device_headset.h"
+#include "include/mm_sound_mgr_device_dock.h"
+#include "include/mm_sound_mgr_pulse.h"
+#include "include/mm_sound_mgr_asm.h"
+
+#define EARJACK_UNPLUGGED 0
+#define EARJACK_WITH_MIC 3
+
+#define MAX_STRING_LEN 256
+
+#define VCONF_SOUND_BURSTSHOT "memory/private/sound/burstshot"
+
+#define DEVICE_API_BLUETOOTH "bluez"
+#define DEVICE_API_ALSA "alsa"
+#define DEVICE_BUS_BLUETOOTH "bluetooth"
+#define DEVICE_BUS_USB "usb"
+#define DEVICE_BUS_BUILTIN "builtin"
+
+#define MIRRORING_MONITOR_SOURCE "alsa_output.0.analog-stereo.monitor"
+#define ALSA_SINK_HDMI "alsa_output.1.analog-stereo"
+
+#ifdef TIZEN_MICRO
+/* Call pause resume scenario with D-bus */
+/* Call application send dbus dbus signal */
+#define DBUS_CALL_STATUS_PATH "/Org/Tizen/Call/Status"
+#define DBUS_CALL_STATUS_INTERFACE "org.tizen.call.status"
+#define DBUS_CALL_STATUS_CHANGED_SIGNAL "call_status"
+#endif
+
+#define MM_SOUND_DEVICE_OUT_ANY 0x000FFF00
+#define MM_SOUND_DEVICE_IN_ANY 0x000000FF
+
+#define MM_SOUND_DEVICE_OUT_FILTER 0x000000FF
+#define MM_SOUND_DEVICE_IN_FILTER 0x000FFF00
+
+#define MAX_BURST_CHECK_RETRY 10
+#define BURST_CHECK_INTERVAL 300000
+
+#define STR_LEN 128
+
+pthread_mutex_t g_mutex_session = PTHREAD_MUTEX_INITIALIZER;
+
+#define LOCK_SESSION() /* do { debug_log("(*)LOCKING\n"); pthread_mutex_lock(&g_mutex_session); debug_log("(+)LOCKED\n"); }while(0) */
+#define UNLOCK_SESSION() /* do { pthread_mutex_unlock(&g_mutex_session); debug_log("(-)UNLOCKED\n"); }while(0) */
+
+pthread_mutex_t g_mutex_path = PTHREAD_MUTEX_INITIALIZER;
+
+#define LOCK_PATH() do { debug_log("(*)LOCKING\n"); pthread_mutex_lock(&g_mutex_path); debug_log("(+)LOCKED\n"); }while(0)
+#define UNLOCK_PATH() do { pthread_mutex_unlock(&g_mutex_path); debug_log("(-)UNLOCKED\n"); }while(0)
+
+#define RESET_ACTIVE(x) (g_info.device_active &= x)
+#define RESET_AVAILABLE(x) (g_info.device_available &= x)
+
+#define SET_ACTIVE(x) (g_info.device_active |= x)
+#define SET_AVAILABLE(x) (g_info.device_available |= x)
+
+#define SET_PLAYBACK_ONLY_ACTIVE(x) do { RESET_ACTIVE(MM_SOUND_DEVICE_OUT_FILTER); SET_ACTIVE(x); }while(0)
+#define SET_CAPTURE_ONLY_ACTIVE(x) do { RESET_ACTIVE(MM_SOUND_DEVICE_IN_FILTER); SET_ACTIVE(x); }while(0)
+
+
+#define UNSET_ACTIVE(x) (g_info.device_active &= (~x))
+#define UNSET_AVAILABLE(x) (g_info.device_available &= (~x))
+
+#define TOGGLE_ACTIVE(x) (g_info.device_active ^= x)
+#define TOGGLE_AVAILABLE(x) (g_info.device_available ^= x)
+
+#define IS_ACTIVE(x) (g_info.device_active & x)
+#define IS_AVAILABLE(x) (g_info.device_available & x)
+
+#define GET_AVAILABLE_PLAYBACK() IS_AVAILABLE(MM_SOUND_DEVICE_OUT_ANY)
+#define GET_AVAILABLE_CAPTURE() IS_AVAILABLE(MM_SOUND_DEVICE_IN_ANY)
+
+#define GET_ACTIVE_PLAYBACK() IS_ACTIVE(MM_SOUND_DEVICE_OUT_ANY)
+#define GET_ACTIVE_CAPTURE() IS_ACTIVE(MM_SOUND_DEVICE_IN_ANY)
+
+#define IS_CALL_SESSION() ((g_info.session == SESSION_VOICECALL) || (g_info.session == SESSION_VIDEOCALL) || (g_info.session == SESSION_VOIP))
+#define IS_ALARM_SESSION() (g_info.session == SESSION_ALARM)
+#define IS_NOTIFICATION_SESSION() (g_info.session == SESSION_NOTIFICATION)
+#define IS_EMERGENCY_SESSION() (g_info.session == SESSION_EMERGENCY)
+#define IS_MEDIA_SESSION() (g_info.session == SESSION_MEDIA)
+
+
+typedef enum {
+ ROUTE_PARAM_NONE = 0x00000000,
+ ROUTE_PARAM_BROADCASTING = 0x00000001,
+ ROUTE_PARAM_CORK_DEVICE = 0x00000010,
+} mm_sound_route_param_t;
+
+#ifdef TIZEN_MICRO
+enum {
+ MM_SOUND_CALL_STATUS_RESUME = 0,
+ MM_SOUND_CALL_STATUS_PAUSE = 1,
+};
+#endif
+
+static int __set_route(bool need_broadcast, bool need_cork);
+static int __set_sound_path_for_current_active (bool need_broadcast, bool need_cork);
+static int __set_sound_path_to_dual ();
+static int __set_sound_path_to_earphone_only (void);
+static int __set_sound_path_to_speaker ();
+static int __set_sound_path_for_voicecontrol (void);
+static void __select_playback_active_device (void);
+static void __select_capture_active_device (void);
+
+static const char* __get_session_string(session_t session);
+static const char* __get_subsession_string(subsession_t session);
+#ifndef _TIZEN_PUBLIC_
+#ifndef TIZEN_MICRO
+static bool __is_noise_reduction_on (void);
+static bool __is_extra_volume_on (void);
+#endif
+static bool __is_upscaling_needed (void);
+static bool __is_right_hand_on (void);
+static bool __get_bt_nrec_status (void);
+static int __get_ag_wb_status(void);
+static int __get_hf_wb_status(void);
+static int __get_hf_connection_state(void);
+static const char* __get_bt_bandwidth_string(int bandwidth);
+#endif
+
+#define ENABLE_CALLBACK
+#ifndef ENABLE_CALLBACK
+#define _mm_sound_mgr_device_available_device_callback(a,b,c) MM_ERROR_NONE
+#define _mm_sound_mgr_device_active_device_callback(a,b) MM_ERROR_NONE
+#endif
+
+typedef struct _bt_info_struct
+{
+#ifdef TIZEN_MICRO
+ int ag_wb;
+ int hf_wb;
+ int hfp_conn_state;
+#endif
+ bool is_nrec;
+ bool is_wb;
+ char name[MAX_STRING_LEN];
+} BT_INFO_STRUCT;
+
+typedef struct _session_info_struct
+{
+ int asm_handle;
+ int device_available;
+ int device_active;
+ int headset_type;
+ bool is_noise_reduction;
+ bool is_extra_volume;
+ bool is_upscaling_needed;
+ bool is_voicecontrol;
+
+ session_t session;
+ subsession_t subsession;
+ mm_subsession_option_t option;
+
+ device_type_t previous_playback_device;
+ device_type_t previous_capture_device;
+ int previous_device_available;
+
+ BT_INFO_STRUCT bt_info;
+ char default_sink_name[MAX_STRING_LEN];
+
+} SESSION_INFO_STRUCT;
+
+
+SESSION_INFO_STRUCT g_info;
+#ifdef TIZEN_MICRO
+GDBusConnection *conn_callstatus;
+guint sig_id_callstatus;
+#endif
+
+static void dump_info ()
+{
+ int i = 0;
+
+ const char *playback_device_str[] = { "SPEAKER ", "RECEIVER ", "HEADSET ", "BTSCO ", "BTA2DP ", "DOCK ", "HDMI ", "MIRRORING ", "USB " };
+ const char *capture_device_str[] = { "MAINMIC ", "HEADSET ", "BTMIC " };
+
+ int playback_max = sizeof (playback_device_str) / sizeof (char*);
+ int capture_max = sizeof (capture_device_str) / sizeof (char*);
+
+ static char tmp_str[STR_LEN];
+ static char tmp_str2[STR_LEN];
+
+ debug_log ("<----------------------------------------------------->\n");
+
+
+ strcpy (tmp_str, "PLAYBACK = [ ");
+ for (i=0; i<playback_max; i++) {
+ if (((g_info.device_available & MM_SOUND_DEVICE_OUT_ANY) >> 8) & (0x01 << i)) {
+ strncat (tmp_str, playback_device_str[i], STR_LEN - strlen(tmp_str) -1);
+ }
+ }
+ strcat (tmp_str, "]");
+
+ strcpy (tmp_str2, "CAPTURE = [ ");
+ for (i=0; i<capture_max; i++) {
+ if ((g_info.device_available & MM_SOUND_DEVICE_IN_ANY) & (0x01 << i)) {
+ strncat (tmp_str2, capture_device_str[i], STR_LEN - strlen(tmp_str2) -1);
+ }
+ }
+ strcat (tmp_str2, "]");
+ debug_warning ("*** Available = [0x%08x], %s %s", g_info.device_available, tmp_str, tmp_str2);
+
+ strcpy (tmp_str, "PLAYBACK = [ ");
+ for (i=0; i<playback_max; i++) {
+ if (((g_info.device_active & MM_SOUND_DEVICE_OUT_ANY) >> 8) & (0x01 << i)) {
+ strncat (tmp_str, playback_device_str[i], STR_LEN - strlen(tmp_str) -1);
+ }
+ }
+ strcat (tmp_str, "]");
+
+ strcpy (tmp_str2, "CAPTURE = [ ");
+ for (i=0; i<capture_max; i++) {
+ if ((g_info.device_active & MM_SOUND_DEVICE_IN_ANY) & (0x01 << i)) {
+ strncat (tmp_str2, capture_device_str[i], STR_LEN - strlen(tmp_str2) -1);
+ }
+ }
+ strcat (tmp_str2, "]");
+ debug_warning ("*** Active = [0x%08x], %s %s", g_info.device_active, tmp_str, tmp_str2);
+
+
+ debug_warning ("*** Headset type = [%d], BT = [%s], default sink = [%s]\n", g_info.headset_type, g_info.bt_info.name, g_info.default_sink_name);
+ debug_warning ("*** Session = [%d], SubSession = [%d]\n", g_info.session, g_info.subsession);
+ debug_log ("<----------------------------------------------------->\n");
+}
+
+/* ------------------------- ASM ------------------------------------*/
+static pthread_mutex_t _asm_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+static bool _asm_register_for_headset (int * handle)
+{
+ int asm_error = 0;
+
+ if (handle == NULL) {
+ debug_error ("Handle is not valid!!!\n");
+ return false;
+ }
+
+ if (!ASM_register_sound_ex (-1, handle, ASM_EVENT_EARJACK_UNPLUG, ASM_STATE_NONE, NULL, NULL, ASM_RESOURCE_NONE, &asm_error, __asm_process_message)) {
+ debug_warning("earjack event register failed with 0x%x\n", asm_error);
+ return false;
+ }
+
+ return true;
+}
+
+static void _asm_pause_process(int handle)
+{
+ int asm_error = 0;
+
+ MMSOUND_ENTER_CRITICAL_SECTION( &_asm_mutex )
+
+ /* If no asm handle register here */
+ if (g_info.asm_handle == -1) {
+ debug_msg ("ASM handle is not valid, try to register once more\n");
+
+ /* This register should be success */
+ if (_asm_register_for_headset (&g_info.asm_handle)) {
+ debug_msg("_asm_register_for_headset() success\n");
+ } else {
+ debug_error("_asm_register_for_headset() failed\n");
+ }
+ }
+
+ //do pause
+ debug_warning("Send earphone unplug event to Audio Session Manager Server\n");
+
+ if (!ASM_set_sound_state_ex(handle, ASM_EVENT_EARJACK_UNPLUG, ASM_STATE_PLAYING, ASM_RESOURCE_NONE, &asm_error, __asm_process_message)) {
+ debug_error("earjack event set sound state to playing failed with 0x%x\n", asm_error);
+ }
+
+ if (!ASM_set_sound_state_ex(handle, ASM_EVENT_EARJACK_UNPLUG, ASM_STATE_STOP, ASM_RESOURCE_NONE, &asm_error, __asm_process_message)) {
+ debug_error("earjack event set sound state to stop failed with 0x%x\n", asm_error);
+ }
+
+ MMSOUND_LEAVE_CRITICAL_SECTION( &_asm_mutex )
+}
+
+static bool _asm_unregister_for_headset (int *handle)
+{
+ int asm_error = 0;
+
+ if (handle == NULL) {
+ debug_error ("Handle is not valid!!!\n");
+ return false;
+ }
+
+ if (!ASM_unregister_sound_ex(*handle, ASM_EVENT_EARJACK_UNPLUG, &asm_error, __asm_process_message)) {
+ debug_error("earjack event unregister failed with 0x%x\n", asm_error);
+ return false;
+ }
+
+ return true;
+}
+
+/* ------------------------- INTERNAL FUNCTIONS ------------------------------------*/
+
+static void __backup_current_active_device()
+{
+ g_info.previous_playback_device = GET_ACTIVE_PLAYBACK();
+ g_info.previous_capture_device = GET_ACTIVE_CAPTURE();
+ g_info.previous_device_available = g_info.device_available;
+}
+
+static void __restore_previous_active_device()
+{
+ RESET_ACTIVE(0);
+
+ debug_msg ("available device (0x%x => 0x%x)", g_info.previous_device_available, g_info.device_available);
+ if (g_info.previous_device_available == g_info.device_available) {
+ /* No Changes */
+ g_info.device_active |= g_info.previous_playback_device;
+ g_info.device_active |= g_info.previous_capture_device;
+ } else {
+ /* Changes happens */
+ __select_playback_active_device();
+ __select_capture_active_device();
+ }
+}
+
+
+static int __set_route(bool need_broadcast, bool need_cork)
+{
+ int ret = MM_ERROR_NONE;
+
+ debug_msg ("need_broadcast=%d, need_cork=%d\n", need_broadcast, need_cork);
+
+ LOCK_PATH();
+
+ /* Set path based on current active device */
+ ret = __set_sound_path_for_current_active(need_broadcast, need_cork);
+ if (ret != MM_ERROR_NONE) {
+ debug_error ("__set_sound_path_for_current_active() failed [%x]\n", ret);
+ UNLOCK_PATH();
+ return ret;
+ }
+
+ UNLOCK_PATH();
+ return ret;
+}
+
+static int __set_route_nolock(bool need_broadcast, bool need_cork)
+{
+ int ret = MM_ERROR_NONE;
+
+ debug_msg ("need_broadcast=%d, need_cork=%d\n", need_broadcast, need_cork);
+
+ /* Set path based on current active device */
+ ret = __set_sound_path_for_current_active(need_broadcast, need_cork);
+ if (ret != MM_ERROR_NONE) {
+ debug_error ("__set_sound_path_for_current_active() failed [%x]\n", ret);
+ UNLOCK_PATH();
+ return ret;
+ }
+
+ return ret;
+}
+
+static int __set_playback_route_media (session_state_t state)
+{
+ int ret = MM_ERROR_NONE;
+
+ debug_fenter();
+
+ if (state == SESSION_START) {
+ dump_info();
+ } else { /* SESSION_END */
+ __set_route(false, false);
+ dump_info();
+ }
+
+ debug_fleave();
+ return ret;
+}
+
+static int __set_playback_route_voip (session_state_t state)
+{
+ int ret = MM_ERROR_NONE;
+
+ debug_fenter();
+ if (state == SESSION_START) {
+ /* Enable Receiver Device */
+ debug_log ("voip call session started...");
+
+ /* Backup current active for future restore */
+ __backup_current_active_device();
+
+ /* Set default subsession as VOICE */
+#ifdef TIZEN_MICRO
+ g_info.subsession = SUBSESSION_MEDIA;
+#else
+ g_info.subsession = SUBSESSION_VOICE;
+#endif
+
+ /* OUT */
+#ifdef TIZEN_MICRO
+ SET_PLAYBACK_ONLY_ACTIVE(MM_SOUND_DEVICE_OUT_SPEAKER);
+ SET_CAPTURE_ONLY_ACTIVE(MM_SOUND_DEVICE_IN_MIC);
+#else
+ if (IS_ACTIVE(MM_SOUND_DEVICE_OUT_SPEAKER)) {
+ debug_log ("active out was SPEAKER => activate receiver!!\n");
+ SET_PLAYBACK_ONLY_ACTIVE(MM_SOUND_DEVICE_OUT_RECEIVER);
+ } else if (IS_ACTIVE(MM_SOUND_DEVICE_OUT_BT_A2DP)) {
+ debug_log ("active out was BT A2DP => activate BT SCO!!\n");
+ SET_PLAYBACK_ONLY_ACTIVE(MM_SOUND_DEVICE_OUT_BT_SCO);
+ SET_CAPTURE_ONLY_ACTIVE(MM_SOUND_DEVICE_IN_BT_SCO);
+ }
+ __set_route(true, false);
+#endif
+ dump_info();
+ } else { /* SESSION_END */
+ /* RESET */
+ if (g_info.session != SESSION_VOIP) {
+ debug_warning ("Must be VOIP session but current session is [%s]\n",
+ __get_session_string(g_info.session));
+ }
+ debug_log ("Reset ACTIVE, activate previous active device if still available, if not, set based on priority");
+ __restore_previous_active_device();
+
+ debug_log ("voip call session stopped...set path based on current active device");
+ __set_route(true, false);
+
+ dump_info();
+ }
+ debug_fleave();
+ return ret;
+}
+
+static int __set_playback_route_call (session_state_t state)
+{
+ int ret = MM_ERROR_NONE;
+
+ debug_fenter();
+
+ if (state == SESSION_START) {
+ debug_log ("voicecall session started...");
+
+ /* Backup current active for future restore */
+ __backup_current_active_device();
+
+ /* Set default subsession as MEDIA */
+ g_info.subsession = SUBSESSION_MEDIA;
+#ifndef TIZEN_MICRO
+ /* (speaker = receiver, headset = headset, bt a2dp = bt sco) */
+ /* OUT */
+ if (IS_ACTIVE(MM_SOUND_DEVICE_OUT_SPEAKER)) {
+ debug_log ("active out was SPEAKER => activate receiver!!\n");
+ SET_PLAYBACK_ONLY_ACTIVE(MM_SOUND_DEVICE_OUT_RECEIVER);
+ } else if (IS_ACTIVE(MM_SOUND_DEVICE_OUT_BT_A2DP)) {
+ debug_log ("active out was BT A2DP => activate BT SCO!!\n");
+ SET_PLAYBACK_ONLY_ACTIVE(MM_SOUND_DEVICE_OUT_BT_SCO);
+ SET_CAPTURE_ONLY_ACTIVE(MM_SOUND_DEVICE_IN_BT_SCO);
+ }
+ /* FIXME : Do we have to set IN device ??? */
+ /* __set_path_with_notification(DO_NOTI); */
+ /* For sharing device information with PulseAudio */
+ MMSoundMgrPulseSetActiveDevice(GET_ACTIVE_CAPTURE(), GET_ACTIVE_PLAYBACK());
+#endif
+ dump_info();
+ } else {
+ /* SESSION_END */
+ debug_log ("Reset ACTIVE, activate previous active device if still available, if not, set based on priority");
+ __restore_previous_active_device();
+
+ debug_log ("voicecall session stopped...set path based on current active device");
+ __set_route(true, false);
+
+ dump_info();
+ }
+ debug_fleave();
+
+ return ret;
+}
+
+static int __set_playback_route_fmradio (session_state_t state)
+{
+ int ret = MM_ERROR_NONE;
+ int out = MM_SOUND_DEVICE_OUT_NONE;
+
+ debug_fenter();
+
+ if (state == SESSION_START) {
+ if (IS_ACTIVE(MM_SOUND_DEVICE_OUT_SPEAKER))
+ out = MM_SOUND_DEVICE_OUT_SPEAKER;
+ else if (IS_ACTIVE(MM_SOUND_DEVICE_OUT_WIRED_ACCESSORY))
+ out = MM_SOUND_DEVICE_OUT_WIRED_ACCESSORY;
+ else if (IS_ACTIVE(MM_SOUND_DEVICE_OUT_BT_A2DP))
+ out = MM_SOUND_DEVICE_OUT_BT_A2DP;
+ /* Note : FM radio input is internal device, not exported */
+ } else {
+ /* SESSION_END */
+ /* Set as current active status */
+ /* FIXME : Need to release path on fm radio scenario */
+ __set_route(false, false);
+ }
+ /* FIXME : Need to update device status */
+ debug_fleave();
+ return ret;
+}
+
+static int __set_playback_route_notification (session_state_t state)
+{
+ int ret = MM_ERROR_NONE;
+
+ debug_fenter();
+
+ if (state == SESSION_START) {
+ /* FIXME : Need to check using vconf key with check status and policy */
+ if (_mm_sound_is_recording() || _mm_sound_is_mute_policy()) {
+ /* Force earphone path for mute case */
+ if ((ret = __set_sound_path_to_earphone_only ()) != MM_ERROR_NONE) {
+ debug_error ("__set_sound_path_to_earphone_only() failed [%x]\n", ret);
+ }
+ } else {
+ /* In case of B2s, lockup issue is occurred */
+ /* No HEADSET device */
+ /* No matter on YMU chipset */
+ if ((ret = __set_sound_path_to_dual ()) != MM_ERROR_NONE) {
+ debug_error ("__set_sound_path_to_dual() failed [%x]\n", ret);
+ }
+ }
+ } else {
+ /* SESSION_END */
+ __set_route(false, false);
+ }
+ debug_fleave();
+
+ return ret;
+}
+
+static int __set_playback_route_alarm (session_state_t state)
+{
+ int ret = MM_ERROR_NONE;
+
+ debug_fenter();
+
+ if (state == SESSION_START) {
+ if ((ret = __set_sound_path_to_dual ()) != MM_ERROR_NONE) {
+ debug_error ("__set_sound_path_to_dual() failed [%x]\n", ret);
+ }
+ } else { /* SESSION_END */
+ __set_route(false, false);
+ }
+
+ debug_fleave();
+
+ return ret;
+}
+
+static int __set_playback_route_emergency (session_state_t state)
+{
+ int ret = MM_ERROR_NONE;
+
+ debug_fenter();
+
+ if (state == SESSION_START) {
+ ret = __set_sound_path_to_speaker ();
+ if (ret != MM_ERROR_NONE) {
+ debug_error ("__set_sound_path_to_speaker() failed [%x]\n", ret);
+ }
+
+ } else { /* SESSION_END */
+ __set_route(false, false);
+ }
+
+ debug_fleave();
+
+ return ret;
+}
+
+static int __set_playback_route_voicerecognition (session_state_t state)
+{
+ int ret = MM_ERROR_NONE;
+
+ debug_fenter();
+
+ if (state == SESSION_START) {
+ g_info.subsession = SUBSESSION_INIT;
+ /* audio path is changed when subsession is set */
+ } else { /* SESSION_END */
+ /* FIXME : On MICRO profile, need to check release path here */
+ __set_route(true, false);
+ }
+
+ debug_fleave();
+
+ return ret;
+}
+
+#if 0
+/* FIXME : Need to check for private function */
+static int __set_playback_route_timer_shot_and_recorder (subsession_state_t state)
+{
+ int ret = MM_ERROR_NONE;
+ mm_sound_device_in device_in_after = MM_SOUND_DEVICE_IN_NONE;
+ mm_sound_device_out device_out_after = MM_SOUND_DEVICE_OUT_NONE;
+ bool is_available = 0;
+ debug_fenter();
+
+ LOCK_PATH();
+ if (state == SUBSESSION_START) {
+ MMSoundMgrSessionGetDeviceActive(&g_info.device_out_previous, &g_info.device_in_previous);
+ g_info.device_available_previous = g_info.device_available;
+ if(g_info.device_out_previous != MM_SOUND_DEVICE_OUT_SPEAKER) {
+ __set_sound_path_for_active_device_nolock(MM_SOUND_DEVICE_OUT_SPEAKER, MM_SOUND_DEVICE_IN_NONE);
+ }
+ /* audio path is changed when subsession is set */
+ } else { /* SESSION_END */
+ MMSoundMgrSessionGetDeviceActive(&device_out_after, &device_in_after);
+ if(device_out_after != MM_SOUND_DEVICE_OUT_SPEAKER) {
+ __set_sound_path_for_active_device_nolock(device_out_after, device_in_after);
+ } else if(device_out_after == MM_SOUND_DEVICE_OUT_SPEAKER && g_info.device_out_previous != MM_SOUND_DEVICE_OUT_SPEAKER) {
+ MMSoundMgrSessionIsDeviceAvailable(g_info.device_out_previous, g_info.device_in_previous, &is_available);
+ if(is_available) {
+ __set_sound_path_for_active_device_nolock(g_info.device_out_previous, g_info.device_in_previous);
+ } else {
+ __select_playback_active_device();
+ __select_capture_active_device();
+ MMSoundMgrSessionGetDeviceActive(&device_out_after, &device_in_after);
+ if(device_out_after != MM_SOUND_DEVICE_OUT_SPEAKER) {
+ __set_sound_path_for_active_device_nolock(device_out_after, device_in_after);
+ }
+ }
+ }
+ MMSoundMgrSessionGetDeviceActive(&g_info.device_out_previous, &g_info.device_in_previous);
+ g_info.device_available_previous = g_info.device_available;
+ }
+
+ UNLOCK_PATH();
+
+ debug_fleave();
+
+ return ret;
+}
+#endif
+
+static bool __is_forced_session ()
+{
+ return (IS_ALARM_SESSION() || IS_NOTIFICATION_SESSION() || IS_EMERGENCY_SESSION())? true : false;
+}
+
+static bool __is_recording_subsession ()
+{
+ /* FIXME : Need to check routing option flag */
+ /* On private, by record option routing flag is changed */
+ bool is_recording = true;
+ switch (g_info.subsession) {
+ case SUBSESSION_RECORD_STEREO:
+ case SUBSESSION_RECORD_MONO:
+ break;
+ default:
+ is_recording = false;
+ break;
+ }
+ return is_recording;
+}
+
+static void _wait_if_burstshot_exists(void)
+{
+ int retry = 0;
+ int is_burstshot = 0;
+
+ do {
+ if (retry > 0)
+ usleep (BURST_CHECK_INTERVAL);
+ if (vconf_get_int(VCONF_SOUND_BURSTSHOT, &is_burstshot) != 0) {
+ debug_warning ("Faided to get [%s], assume no burstshot....", VCONF_SOUND_BURSTSHOT);
+ is_burstshot = 0;
+ } else {
+ debug_warning ("Is Burstshot [%d], retry...[%d/%d], interval usec = %d",
+ is_burstshot, retry, MAX_BURST_CHECK_RETRY, BURST_CHECK_INTERVAL);
+ }
+ } while (is_burstshot && retry++ < MAX_BURST_CHECK_RETRY);
+}
+
+
+static int __set_sound_path_for_current_active (bool need_broadcast, bool need_cork)
+{
+ int ret = MM_ERROR_NONE;
+ int in = 0, out = 0;
+
+ debug_fenter();
+ debug_msg ("session:%s, subsession:%s, option:%d, active in:0x%x, out:0x%x, need_cork:%d",
+ __get_session_string(g_info.session), __get_subsession_string(g_info.subsession),
+ g_info.option, GET_ACTIVE_CAPTURE(), GET_ACTIVE_PLAYBACK(), need_cork);
+
+ if (__is_forced_session()) {
+ debug_warning ("Current session is ALARM/NOTI/EMER, pending path setting. path set will be done after session ends");
+ return MM_ERROR_SOUND_INVALID_STATE;
+ }
+
+ /* Wait if BurstShot is ongoing */
+ _wait_if_burstshot_exists();
+
+ if (need_cork)
+ MMSoundMgrPulseSetCorkAll (true);
+
+ in = GET_ACTIVE_CAPTURE();
+ out = GET_ACTIVE_PLAYBACK();
+
+#ifdef TIZEN_MICRO
+ /* Wearable BT SCO headset case. Should be check nrec, wb, hf does't use sco */
+ if (in == MM_SOUND_DEVICE_IN_BT_SCO && out == MM_SOUND_DEVICE_OUT_BT_SCO) {
+ bool nrec = 0;
+ int bandwidth = MM_SOUND_BANDWIDTH_UNKNOWN;
+
+ ret = MMSoundMgrPulseGetBluetoothInfo(&nrec, &bandwidth);
+ if(ret == MM_ERROR_NONE) {
+ g_info.bt_info.is_nrec = nrec;
+ g_info.bt_info.ag_wb = bandwidth;
+ debug_msg("get bt information successfully. nrec(%d), wb(%s)",
+ g_info.bt_info.is_nrec, __get_bt_bandwidth_string(g_info.bt_info.ag_wb));
+ } else {
+ g_info.bt_info.is_nrec = false;
+ g_info.bt_info.ag_wb = MM_SOUND_BANDWIDTH_NB;
+ debug_msg("failed to get bt information. use default setting. nrec(off), wb(off)");
+ }
+ /* FIXME : How to send status of nrec & ag wideband state with option flag, on MICRO profile */
+ }
+#else
+ if (in == MM_SOUND_DEVICE_IN_BT_SCO && out == MM_SOUND_DEVICE_OUT_BT_SCO) {
+ /* FIXME : How to send status of nrec & ag wideband state with option flag */
+ }
+#endif
+
+ /* prepare GAIN */
+ switch (g_info.session) {
+ case SESSION_MEDIA:
+ case SESSION_NOTIFICATION:
+ case SESSION_ALARM:
+ case SESSION_EMERGENCY:
+ if (IS_MEDIA_SESSION() && __is_recording_subsession()) {
+ /* gain & recording option */
+ } else {
+ /* gain option */
+ if (g_info.is_voicecontrol) {
+ debug_warning ("VoiceControl");
+ /* voice control option */
+ }
+ }
+ break;
+ case SESSION_VOIP:
+ if (g_info.subsession == SUBSESSION_RINGTONE) {
+ in = MM_SOUND_DEVICE_OUT_NONE;
+ /* gain option */
+ /* If active device was WFD(mirroring), set option */
+ if (out == MM_SOUND_DEVICE_OUT_MIRRORING) {
+ /* mirroring option */
+ }
+ if (_mm_sound_is_mute_policy ()) {
+ /* Mute Ringtone */
+ out = MM_SOUND_DEVICE_OUT_BT_A2DP;
+ } else {
+ /* Normal Ringtone */
+ out = MM_SOUND_DEVICE_OUT_SPEAKER;
+ /* dual out option */
+ }
+ } else if (g_info.subsession == SUBSESSION_VOICE) {
+ /* gain option */
+ } else {
+ debug_warning ("Unexpected SUBSESSION [%s]\n", __get_subsession_string(g_info.subsession));
+ /* gain voip option */
+ }
+ break;
+
+ case SESSION_VOICECALL:
+ case SESSION_VIDEOCALL:
+ if (g_info.subsession == SUBSESSION_RINGTONE) {
+#ifndef _TIZEN_PUBLIC_
+#ifndef TIZEN_MICRO
+ int vr_enabled = 0;
+#endif
+ int vr_ringtone_enabled = 0;
+#endif
+ in = MM_SOUND_DEVICE_IN_NONE;
+ /* If active device was WFD(mirroring), set option */
+ if (out == MM_SOUND_DEVICE_OUT_MIRRORING) {
+ /* mirroring option */
+ }
+
+#ifndef _TIZEN_PUBLIC_
+#ifdef TIZEN_MICRO
+ if (vconf_get_bool(VCONF_KEY_VR_RINGTONE_ENABLED, &vr_ringtone_enabled)) {
+ debug_warning("vconf_get_bool for %s failed\n", VCONF_KEY_VR_RINGTONE_ENABLED);
+ }
+
+ if (vr_ringtone_enabled) {
+ /* bargin option */
+ }
+#else
+ /* If voice control for incoming call is enabled, set capture path here for avoiding ringtone breaks */
+ if (vconf_get_bool(VCONF_KEY_VR_ENABLED, &vr_enabled)) {
+ debug_warning("vconf_get_bool for %s failed\n", VCONF_KEY_VR_ENABLED);
+ } else if (vconf_get_bool(VCONF_KEY_VR_RINGTONE_ENABLED, &vr_ringtone_enabled)) {
+ debug_warning("vconf_get_bool for %s failed\n", VCONF_KEY_VR_RINGTONE_ENABLED);
+ }
+
+ if (vr_enabled && vr_ringtone_enabled) {
+ /* bargin option */
+ }
+#endif /* TIZEN_MICRO */
+#endif /* #ifndef _TIZEN_PUBLIC_ */
+ if (_mm_sound_is_mute_policy ()) {
+ /* Mute Ringtone */
+#ifdef TIZEN_MICRO
+ out = MM_SOUND_DEVICE_OUT_SPEAKER;
+#else
+ out = MM_SOUND_DEVICE_OUT_BT_A2DP;
+#endif
+ } else {
+ out = MM_SOUND_DEVICE_OUT_SPEAKER;
+#ifdef TIZEN_MICRO
+ /* for inband ringtone. hfp call ringtone is not used sco */
+ int state = MM_SOUND_HFP_STATUS_UNKNOWN;
+ state = __get_hf_connection_state();
+
+ if(state == MM_SOUND_HFP_STATUS_INCOMMING_CALL) {
+ /* call by BT option */
+ }
+#endif
+ /* Normal Ringtone */
+ /* dual out option */
+ }
+ } else if (g_info.subsession == SUBSESSION_MEDIA) {
+ /* call gain option */
+ in = MM_SOUND_DEVICE_IN_NONE;
+ } else if (g_info.subsession == SUBSESSION_VOICE) {
+ /* gain for voicecall or videocall */
+#ifdef _TIZEN_PUBLIC_
+ if (out == MM_SOUND_DEVICE_OUT_WIRED_ACCESSORY) {
+ debug_log ("Fix in path to headsetmic when out path is headset\n");
+ in = MM_SOUND_DEVICE_IN_WIRED_ACCESSORY;
+ }
+ /* FIXME : Check to NB / WB option */
+#endif /* _TIZEN_PUBLIC_*/
+ } else {
+ debug_warning ("Unexpected SUBSESSION [%s]\n", __get_subsession_string(g_info.subsession));
+ }
+ break;
+
+ case SESSION_FMRADIO:
+ break;
+
+ case SESSION_VOICE_RECOGNITION:
+#ifdef TIZEN_MICRO
+ if (__is_right_hand_on()) {
+ }
+#endif
+ if (g_info.subsession == SUBSESSION_VR_NORMAL) {
+ /* NORMAL mode */
+ } else if (g_info.subsession == SUBSESSION_VR_DRIVE) {
+ /* DRIVE mode */
+ /* FIXME : Need to check private mode or not */
+ } else {
+ debug_warning ("Unexpected SUBSESSION [%s]\n", __get_subsession_string(g_info.subsession));
+ }
+ break;
+ default:
+ debug_warning ("session [%s] is not handled...\n", __get_session_string(g_info.session));
+ break;
+ }
+
+ debug_warning ("Trying to set device to pulseaudio : in[%d], out[%d]\n", in, out);
+
+ /* Update Pulseaudio Active Device */
+ if (IS_ACTIVE(MM_SOUND_DEVICE_OUT_BT_A2DP)) {
+ MMSoundMgrPulseSetActiveDevice(GET_ACTIVE_CAPTURE(), GET_ACTIVE_PLAYBACK());
+ } else if (IS_ACTIVE(MM_SOUND_DEVICE_OUT_USB_AUDIO)) {
+ MMSoundMgrPulseSetActiveDevice(GET_ACTIVE_CAPTURE(), GET_ACTIVE_PLAYBACK());
+ } else if (IS_ACTIVE(MM_SOUND_DEVICE_OUT_MULTIMEDIA_DOCK)) {
+ MMSoundMgrPulseSetActiveDevice(GET_ACTIVE_CAPTURE(), GET_ACTIVE_PLAYBACK());
+ } else {
+ /* ALSA route */
+ MMSoundMgrPulseSetActiveDevice(in, out);
+ }
+
+ /* Pulseaudio Default Sink route */
+ if (IS_ACTIVE(MM_SOUND_DEVICE_OUT_BT_A2DP)) {
+ MMSoundMgrPulseSetDefaultSink (DEVICE_API_BLUETOOTH, DEVICE_BUS_BLUETOOTH);
+ } else if (IS_ACTIVE(MM_SOUND_DEVICE_OUT_USB_AUDIO)) {
+ MMSoundMgrPulseSetUSBDefaultSink (MM_SOUND_DEVICE_OUT_USB_AUDIO);
+ } else if (IS_ACTIVE(MM_SOUND_DEVICE_OUT_MULTIMEDIA_DOCK)) {
+ MMSoundMgrPulseSetUSBDefaultSink (MM_SOUND_DEVICE_OUT_MULTIMEDIA_DOCK);
+ } else if (IS_ACTIVE(MM_SOUND_DEVICE_OUT_HDMI)) {
+ MMSoundMgrPulseSetDefaultSinkByName (ALSA_SINK_HDMI);
+ } else {
+ MMSoundMgrPulseSetDefaultSink (DEVICE_API_ALSA, DEVICE_BUS_BUILTIN);
+ }
+
+ /* Set Source Mute */
+ MMSoundMgrPulseSetSourcemutebyname(MIRRORING_MONITOR_SOURCE,
+ IS_ACTIVE(MM_SOUND_DEVICE_OUT_MIRRORING)? MM_SOUND_AUDIO_UNMUTE : MM_SOUND_AUDIO_MUTE);
+
+ if (need_broadcast) {
+ /* Notify current active device */
+ ret = _mm_sound_mgr_device_active_device_callback(GET_ACTIVE_CAPTURE(), GET_ACTIVE_PLAYBACK());
+ if (ret != MM_ERROR_NONE) {
+ debug_error ("_mm_sound_mgr_device_active_device_callback() failed [%x]\n", ret);
+ }
+ }
+
+ if (need_cork) {
+ /* FIXME : Private issues, workaround for earjack inserting scenario during media playback */
+ if (g_info.session == SESSION_MEDIA && (IS_ACTIVE(MM_SOUND_DEVICE_OUT_BT_A2DP) || IS_ACTIVE(MM_SOUND_DEVICE_OUT_WIRED_ACCESSORY))) {
+ usleep(20000);
+ }
+ MMSoundMgrPulseSetCorkAll (false);
+ }
+ MMSoundMgrPulseUpdateVolume();
+
+ /* clean up */
+ debug_fleave();
+ return ret;
+}
+
+static int __set_sound_path_for_voicecontrol (void)
+{
+ int ret = MM_ERROR_NONE;
+ int in = MM_SOUND_DEVICE_IN_NONE, out = MM_SOUND_DEVICE_OUT_NONE;
+
+ debug_fenter();
+
+ /* prepare IN */
+ if (IS_ACTIVE(MM_SOUND_DEVICE_IN_MIC)) {
+ in = MM_SOUND_DEVICE_IN_MIC;
+ } else if (IS_ACTIVE(MM_SOUND_DEVICE_IN_WIRED_ACCESSORY)) {
+ in = MM_SOUND_DEVICE_IN_WIRED_ACCESSORY;
+ } else if (IS_ACTIVE(MM_SOUND_DEVICE_IN_BT_SCO)) {
+ debug_warning ("[NOT EXPECTED CASE] BT SCO");
+ }
+
+ debug_warning ("g_info.session = %s ", __get_session_string(g_info.session));
+ /* prepare GAIN */
+ switch (g_info.session) {
+ case SESSION_MEDIA:
+ case SESSION_NOTIFICATION:
+ case SESSION_ALARM:
+ case SESSION_EMERGENCY:
+ case SESSION_VOICECALL:
+ case SESSION_VIDEOCALL:
+ case SESSION_VOIP:
+ if (IS_MEDIA_SESSION() && __is_recording_subsession(NULL)) {
+ debug_warning ("[NOT EXPECTED CASE] already RECORDING....return");
+ return MM_ERROR_NONE;
+ }
+ /* gain control KEYTONE */
+ if (g_info.is_voicecontrol) {
+#ifdef TIZEN_MICRO
+ /* For inband ringtone. hfp call ringtone is not used sco */
+ int state = MM_SOUND_HFP_STATUS_UNKNOWN;
+ state = __get_hf_connection_state();
+ if(state == MM_SOUND_HFP_STATUS_INCOMMING_CALL) {
+ /* Call by BT option */
+ }
+#endif
+ debug_warning ("VoiceControl\n");
+ /* Bargein option */
+ }
+ break;
+
+ case SESSION_FMRADIO:
+ case SESSION_VOICE_RECOGNITION:
+ debug_warning ("[NOT EXPECTED CASE] ");
+ break;
+
+ default:
+ debug_warning ("session [%s] is not handled...\n", __get_session_string(g_info.session));
+ break;
+ }
+
+ debug_warning ("Trying to set device to pulseaudio : in[%d], out[%d]\n", in, GET_ACTIVE_PLAYBACK());
+
+ /* Set Path (IN, OUT) */
+ MMSoundMgrPulseSetActiveDevice(in, GET_ACTIVE_PLAYBACK());
+
+ debug_fleave();
+ return ret;
+
+}
+
+
+static int __set_sound_path_to_dual (void)
+{
+ int ret = MM_ERROR_NONE;
+ int in = MM_SOUND_DEVICE_IN_NONE;
+
+ debug_fenter();
+
+ in = IS_ACTIVE(MM_SOUND_DEVICE_IN_WIRED_ACCESSORY)? MM_SOUND_DEVICE_IN_WIRED_ACCESSORY : MM_SOUND_DEVICE_IN_MIC;
+
+ /* If active device was WFD(mirroring), set option */
+ if (IS_ACTIVE(MM_SOUND_DEVICE_OUT_MIRRORING)) {
+ /* mirorring option */
+ }
+ if (g_info.is_voicecontrol) {
+ debug_msg ("VoiceControl\n");
+ /* bargein option */
+ }
+ /* Sound path for ALSA */
+ debug_msg ("not supported, set path to DUAL-OUT");
+ MMSoundMgrPulseSetActiveDevice(in, MM_SOUND_DEVICE_OUT_SPEAKER);
+
+ /* clean up */
+ debug_fleave();
+ return ret;
+}
+
+static int __set_sound_path_to_earphone_only (void)
+{
+ int ret = MM_ERROR_NONE;
+ int in = MM_SOUND_DEVICE_IN_NONE;
+
+ debug_fenter();
+
+ in = IS_ACTIVE(MM_SOUND_DEVICE_IN_WIRED_ACCESSORY)? MM_SOUND_DEVICE_IN_WIRED_ACCESSORY : MM_SOUND_DEVICE_IN_MIC;
+
+ if (g_info.is_voicecontrol) {
+ debug_msg ("VoiceControl\n");
+ /* bargein option */
+ }
+
+ /* Sound path for ALSA */
+ debug_msg ("Set path to EARPHONE only.\n");
+ MMSoundMgrPulseSetActiveDevice(in, MM_SOUND_DEVICE_OUT_WIRED_ACCESSORY);
+
+ /* clean up */
+ debug_fleave();
+ return ret;
+}
+
+int MMSoundMgrSessionSetSoundPathForActiveDevice (mm_sound_device_out playback, mm_sound_device_in capture)
+{
+ int ret = MM_ERROR_NONE;
+
+ debug_fenter();
+
+ /* Sound path for ALSA */
+ debug_log ("Set path for active device.playback:%x, capture:%x\n",playback,capture);
+ if ((playback && !IS_AVAILABLE(playback)) || (capture && !IS_AVAILABLE(capture))) {
+ debug_warning ("Failed to set active state to unavailable device!!!\n");
+ ret = MM_ERROR_INVALID_ARGUMENT;
+ goto END_SET_DEVICE;
+ }
+
+ LOCK_PATH();
+ /* Update active state */
+ debug_log ("Update active device as request\n");
+ if (playback) {
+ SET_PLAYBACK_ONLY_ACTIVE(playback);
+ }
+ if (capture) {
+ SET_CAPTURE_ONLY_ACTIVE(capture);
+ }
+ MMSoundMgrPulseSetActiveDevice(GET_ACTIVE_CAPTURE(), GET_ACTIVE_PLAYBACK());
+ UNLOCK_PATH();
+
+END_SET_DEVICE:
+ debug_fleave();
+ return ret;
+}
+
+static int __set_sound_path_for_active_device_nolock (mm_sound_device_out playback, mm_sound_device_in capture)
+{
+ int ret = MM_ERROR_NONE;
+
+ debug_fenter();
+
+ /* Sound path for ALSA */
+ debug_log ("Set path for active device.playback:%x, capture:%x\n",playback,capture);
+ if ((playback && !IS_AVAILABLE(playback)) || (capture && !IS_AVAILABLE(capture))) {
+ debug_warning ("Failed to set active state to unavailable device!!!\n");
+ ret = MM_ERROR_INVALID_ARGUMENT;
+ goto END_SET_DEVICE;
+ }
+
+ /* Update active state */
+ debug_log ("Update active device as request\n");
+ if (playback) {
+ SET_PLAYBACK_ONLY_ACTIVE(playback);
+ }
+ if (capture) {
+ SET_CAPTURE_ONLY_ACTIVE(capture);
+ }
+ MMSoundMgrPulseSetActiveDevice(GET_ACTIVE_CAPTURE(), GET_ACTIVE_PLAYBACK());
+
+END_SET_DEVICE:
+ debug_fleave();
+ return ret;
+}
+
+static int __set_sound_path_to_speaker (void)
+{
+ int ret = MM_ERROR_NONE;
+
+ debug_fenter();
+
+ /* Sound path for ALSA */
+ debug_log ("Set path to SPEAKER.\n");
+ MMSoundMgrPulseSetActiveDevice(GET_ACTIVE_CAPTURE(), MM_SOUND_DEVICE_OUT_SPEAKER);
+
+ /* clean up */
+ debug_fleave();
+ return ret;
+}
+
+static void __select_playback_active_device (void)
+{
+ if (IS_ACTIVE(MM_SOUND_DEVICE_OUT_ANY)) {
+ debug_log ("Active device exists. Nothing needed...\n");
+ return;
+ }
+
+ debug_warning ("No playback active device, set active based on priority!!\n");
+
+ /* set active device based on device priority (bt>ear>spk) */
+ if (IS_AVAILABLE(MM_SOUND_DEVICE_OUT_BT_A2DP)) {
+ debug_log ("BT A2DP available, set as active!!\n");
+ SET_ACTIVE(MM_SOUND_DEVICE_OUT_BT_A2DP);
+ MMSoundMgrDeviceUpdateStatus (DEVICE_UPDATE_STATUS_CHANGED_INFO_IO_DIRECTION, DEVICE_TYPE_BLUETOOTH, DEVICE_IO_DIRECTION_OUT, DEVICE_ID_AUTO, NULL, DEVICE_STATE_ACTIVATED, NULL);
+ MMSoundMgrDeviceUpdateStatus (DEVICE_UPDATE_STATUS_CHANGED_INFO_STATE, DEVICE_TYPE_BLUETOOTH, DEVICE_IO_DIRECTION_OUT, DEVICE_ID_AUTO, NULL, DEVICE_STATE_ACTIVATED, NULL);
+ } else if (IS_AVAILABLE(MM_SOUND_DEVICE_OUT_MIRRORING)) {
+ debug_log ("MIRRORING available, set as active!!\n");
+ SET_ACTIVE(MM_SOUND_DEVICE_OUT_MIRRORING);
+ MMSoundMgrDeviceUpdateStatus (DEVICE_UPDATE_STATUS_CHANGED_INFO_STATE, DEVICE_TYPE_MIRRORING, DEVICE_IO_DIRECTION_OUT, DEVICE_ID_AUTO, NULL, DEVICE_STATE_ACTIVATED, NULL);
+ } else if (IS_AVAILABLE(MM_SOUND_DEVICE_OUT_DOCK)) {
+ debug_log ("DOCK available, set as active!!\n");
+ SET_ACTIVE(MM_SOUND_DEVICE_OUT_DOCK);
+ } else if (IS_AVAILABLE(MM_SOUND_DEVICE_OUT_HDMI)) {
+ debug_log ("HDMI available, set as active!!\n");
+ SET_ACTIVE(MM_SOUND_DEVICE_OUT_HDMI);
+ MMSoundMgrDeviceUpdateStatus (DEVICE_UPDATE_STATUS_CHANGED_INFO_STATE, DEVICE_TYPE_HDMI, DEVICE_IO_DIRECTION_OUT, DEVICE_ID_AUTO, NULL, DEVICE_STATE_ACTIVATED, NULL);
+ } else if (IS_AVAILABLE(MM_SOUND_DEVICE_OUT_USB_AUDIO)) {
+ debug_log ("USB Audio available, set as active!!\n");
+ SET_ACTIVE(MM_SOUND_DEVICE_OUT_USB_AUDIO);
+ MMSoundMgrDeviceUpdateStatus (DEVICE_UPDATE_STATUS_CHANGED_INFO_STATE, DEVICE_TYPE_USB_AUDIO, DEVICE_IO_DIRECTION_OUT, DEVICE_ID_AUTO, NULL, DEVICE_STATE_ACTIVATED, NULL);
+ } else if (IS_AVAILABLE(MM_SOUND_DEVICE_OUT_MULTIMEDIA_DOCK)) {
+ debug_log ("Multimedia Dock available, set as active!!\n");
+ SET_ACTIVE(MM_SOUND_DEVICE_OUT_MULTIMEDIA_DOCK);
+ } else if (IS_AVAILABLE(MM_SOUND_DEVICE_OUT_WIRED_ACCESSORY)) {
+ debug_log ("WIRED available, set as active!!\n");
+ SET_ACTIVE(MM_SOUND_DEVICE_OUT_WIRED_ACCESSORY);
+ MMSoundMgrDeviceUpdateStatus (DEVICE_UPDATE_STATUS_CHANGED_INFO_STATE, DEVICE_TYPE_AUDIOJACK, 0, DEVICE_ID_AUTO, NULL, DEVICE_STATE_ACTIVATED, NULL);
+ } else {
+ debug_log ("SPEAKER/RECEIVER available, set SPEAKER as active!!\n");
+ SET_ACTIVE(MM_SOUND_DEVICE_OUT_SPEAKER);
+ MMSoundMgrDeviceUpdateStatus (DEVICE_UPDATE_STATUS_CHANGED_INFO_STATE, DEVICE_TYPE_BUILTIN_SPEAKER, DEVICE_IO_DIRECTION_OUT, DEVICE_ID_AUTO, NULL, DEVICE_STATE_ACTIVATED, NULL);
+ }
+}
+
+static void __select_capture_active_device (void)
+{
+ if (IS_ACTIVE(MM_SOUND_DEVICE_IN_ANY)) {
+ debug_log ("Active device exists. Nothing needed...\n");
+ return;
+ }
+
+ debug_warning ("No capture active device, set active based on priority!!\n");
+
+ /* set active device based on device priority (bt>ear>spk) */
+ if (IS_AVAILABLE(MM_SOUND_DEVICE_IN_BT_SCO) && IS_CALL_SESSION()) {
+ debug_log ("BT SCO available, set as active!!\n");
+ SET_ACTIVE(MM_SOUND_DEVICE_IN_BT_SCO);
+ MMSoundMgrDeviceUpdateStatus (DEVICE_UPDATE_STATUS_CHANGED_INFO_STATE, DEVICE_TYPE_BLUETOOTH, DEVICE_IO_DIRECTION_BOTH, DEVICE_ID_AUTO, NULL, DEVICE_STATE_ACTIVATED, NULL);
+ } else if (IS_AVAILABLE(MM_SOUND_DEVICE_IN_WIRED_ACCESSORY)) {
+ debug_log ("WIRED available, set as active!!\n");
+ SET_ACTIVE(MM_SOUND_DEVICE_IN_WIRED_ACCESSORY);
+ MMSoundMgrDeviceUpdateStatus (DEVICE_UPDATE_STATUS_CHANGED_INFO_STATE, DEVICE_TYPE_AUDIOJACK, DEVICE_IO_DIRECTION_BOTH, DEVICE_ID_AUTO, NULL, DEVICE_STATE_ACTIVATED, NULL);
+ } else {
+ debug_log ("MIC available, set as active!!\n");
+ SET_ACTIVE(MM_SOUND_DEVICE_IN_MIC);
+ MMSoundMgrDeviceUpdateStatus (DEVICE_UPDATE_STATUS_CHANGED_INFO_STATE, DEVICE_TYPE_BUILTIN_MIC, DEVICE_IO_DIRECTION_IN, DEVICE_ID_AUTO, NULL, DEVICE_STATE_ACTIVATED, NULL);
+ }
+}
+
+static int __get_device_type_from_old_device (int old_device_type, device_type_e *device_type)
+{
+ int ret = MM_ERROR_NONE;
+
+ switch(old_device_type) {
+ case MM_SOUND_DEVICE_IN_MIC:
+ *device_type = DEVICE_TYPE_BUILTIN_MIC;
+ break;
+ case MM_SOUND_DEVICE_IN_WIRED_ACCESSORY:
+ case MM_SOUND_DEVICE_OUT_WIRED_ACCESSORY:
+ *device_type = DEVICE_TYPE_AUDIOJACK;
+ break;
+ case MM_SOUND_DEVICE_IN_BT_SCO:
+ case MM_SOUND_DEVICE_OUT_BT_SCO:
+ case MM_SOUND_DEVICE_OUT_BT_A2DP:
+ *device_type = DEVICE_TYPE_BLUETOOTH;
+ break;
+ case MM_SOUND_DEVICE_OUT_SPEAKER:
+ *device_type = DEVICE_TYPE_BUILTIN_SPEAKER;
+ break;
+ case MM_SOUND_DEVICE_OUT_RECEIVER:
+ *device_type = DEVICE_TYPE_BUILTIN_RECEIVER;
+ break;
+ case MM_SOUND_DEVICE_OUT_HDMI:
+ *device_type = DEVICE_TYPE_HDMI;
+ break;
+ case MM_SOUND_DEVICE_OUT_MIRRORING:
+ *device_type = DEVICE_TYPE_MIRRORING;
+ break;
+ case MM_SOUND_DEVICE_OUT_USB_AUDIO:
+ *device_type = DEVICE_TYPE_USB_AUDIO;
+ break;
+ default:
+ ret = MM_ERROR_NOT_SUPPORT_API;
+ break;
+ }
+ return ret;
+}
+
+static void __set_deactivate_all_device_auto (mm_sound_device_in exception_in, mm_sound_device_out exception_out)
+{
+ /* DEACTIVATE OTHERS */
+ /* IN */
+ if (exception_in != MM_SOUND_DEVICE_IN_MIC) {
+ MMSoundMgrDeviceUpdateStatus (DEVICE_UPDATE_STATUS_CHANGED_INFO_STATE, DEVICE_TYPE_BUILTIN_MIC, 0, DEVICE_ID_AUTO, NULL, DEVICE_STATE_DEACTIVATED, NULL);
+ }
+ if ((exception_in != MM_SOUND_DEVICE_IN_WIRED_ACCESSORY) && (exception_out != MM_SOUND_DEVICE_OUT_WIRED_ACCESSORY)) {
+ MMSoundMgrDeviceUpdateStatus (DEVICE_UPDATE_STATUS_CHANGED_INFO_STATE, DEVICE_TYPE_AUDIOJACK, 0, DEVICE_ID_AUTO, NULL, DEVICE_STATE_DEACTIVATED, NULL);
+ }
+ if ((exception_in != MM_SOUND_DEVICE_IN_BT_SCO) && (exception_out != MM_SOUND_DEVICE_OUT_BT_A2DP) && (exception_out != MM_SOUND_DEVICE_OUT_BT_SCO)) {
+ MMSoundMgrDeviceUpdateStatus (DEVICE_UPDATE_STATUS_CHANGED_INFO_STATE, DEVICE_TYPE_BLUETOOTH, 0, DEVICE_ID_AUTO, NULL, DEVICE_STATE_DEACTIVATED, NULL);
+ }
+ /* OUT */
+ if (exception_out != MM_SOUND_DEVICE_OUT_SPEAKER) {
+ MMSoundMgrDeviceUpdateStatus (DEVICE_UPDATE_STATUS_CHANGED_INFO_STATE, DEVICE_TYPE_BUILTIN_SPEAKER, 0, DEVICE_ID_AUTO, NULL, DEVICE_STATE_DEACTIVATED, NULL);
+ }
+ if (exception_out != MM_SOUND_DEVICE_OUT_RECEIVER) {
+ MMSoundMgrDeviceUpdateStatus (DEVICE_UPDATE_STATUS_CHANGED_INFO_STATE, DEVICE_TYPE_BUILTIN_RECEIVER, 0, DEVICE_ID_AUTO, NULL, DEVICE_STATE_DEACTIVATED, NULL);
+ }
+ if ((exception_out != MM_SOUND_DEVICE_OUT_WIRED_ACCESSORY) && (exception_in != MM_SOUND_DEVICE_IN_WIRED_ACCESSORY)) {
+ MMSoundMgrDeviceUpdateStatus (DEVICE_UPDATE_STATUS_CHANGED_INFO_STATE, DEVICE_TYPE_AUDIOJACK, 0, DEVICE_ID_AUTO, NULL, DEVICE_STATE_DEACTIVATED, NULL);
+ }
+ if (exception_out != MM_SOUND_DEVICE_OUT_MIRRORING) {
+ MMSoundMgrDeviceUpdateStatus (DEVICE_UPDATE_STATUS_CHANGED_INFO_STATE, DEVICE_TYPE_MIRRORING, 0, DEVICE_ID_AUTO, NULL, DEVICE_STATE_DEACTIVATED, NULL);
+ }
+ if (exception_out != MM_SOUND_DEVICE_OUT_USB_AUDIO) {
+ MMSoundMgrDeviceUpdateStatus (DEVICE_UPDATE_STATUS_CHANGED_INFO_STATE, DEVICE_TYPE_USB_AUDIO, 0, DEVICE_ID_AUTO, NULL, DEVICE_STATE_DEACTIVATED, NULL);
+ }
+ if ((exception_out != MM_SOUND_DEVICE_OUT_BT_A2DP) && (exception_out != MM_SOUND_DEVICE_OUT_BT_SCO) && (exception_in != MM_SOUND_DEVICE_IN_BT_SCO)) {
+ MMSoundMgrDeviceUpdateStatus (DEVICE_UPDATE_STATUS_CHANGED_INFO_STATE, DEVICE_TYPE_BLUETOOTH, 0, DEVICE_ID_AUTO, NULL, DEVICE_STATE_DEACTIVATED, NULL);
+ }
+ if (exception_out != MM_SOUND_DEVICE_OUT_HDMI) {
+ MMSoundMgrDeviceUpdateStatus (DEVICE_UPDATE_STATUS_CHANGED_INFO_STATE, DEVICE_TYPE_HDMI, 0, DEVICE_ID_AUTO, NULL, DEVICE_STATE_DEACTIVATED, NULL);
+ }
+}
+
+static void __set_initial_active_device (void)
+{
+ int dock_type = 0;
+ bool a2dp = 0, sco = 0;
+
+ /* Set SPK/RECIEVER(for OUT) & MIC(for IN) as default available device */
+ /* FIXME : spk & mic can be always on??? */
+#ifdef TIZEN_MICRO
+ SET_AVAILABLE(MM_SOUND_DEVICE_OUT_SPEAKER);
+#else
+ SET_AVAILABLE(MM_SOUND_DEVICE_OUT_SPEAKER|MM_SOUND_DEVICE_OUT_RECEIVER);
+#endif
+ SET_AVAILABLE(MM_SOUND_DEVICE_IN_MIC);
+
+ /* Get wired status and set available status */
+ _mm_sound_get_earjack_type (&g_info.headset_type);
+ if (g_info.headset_type > EARJACK_UNPLUGGED) {
+ SET_AVAILABLE(MM_SOUND_DEVICE_OUT_WIRED_ACCESSORY);
+ if (g_info.headset_type == DEVICE_EARJACK_TYPE_SPK_WITH_MIC) {
+ SET_AVAILABLE(MM_SOUND_DEVICE_IN_WIRED_ACCESSORY);
+ MMSoundMgrDeviceUpdateStatus(DEVICE_UPDATE_STATUS_CONNECTED, DEVICE_TYPE_AUDIOJACK, DEVICE_IO_DIRECTION_BOTH, DEVICE_ID_AUTO, DEVICE_NAME_AUDIOJACK_4P, 0, NULL);
+ MMSoundMgrDeviceUpdateStatus(DEVICE_UPDATE_STATUS_CHANGED_INFO_STATE, DEVICE_TYPE_AUDIOJACK, DEVICE_IO_DIRECTION_BOTH, DEVICE_ID_AUTO, DEVICE_NAME_AUDIOJACK_4P, DEVICE_STATE_ACTIVATED, NULL);
+ } else {
+ MMSoundMgrDeviceUpdateStatus(DEVICE_UPDATE_STATUS_CONNECTED, DEVICE_TYPE_AUDIOJACK, DEVICE_IO_DIRECTION_BOTH, DEVICE_ID_AUTO, DEVICE_NAME_AUDIOJACK_3P, 0, NULL);
+ MMSoundMgrDeviceUpdateStatus(DEVICE_UPDATE_STATUS_CHANGED_INFO_STATE, DEVICE_TYPE_AUDIOJACK, DEVICE_IO_DIRECTION_BOTH, DEVICE_ID_AUTO, DEVICE_NAME_AUDIOJACK_3P, DEVICE_STATE_ACTIVATED, NULL);
+ }
+ }
+
+ /* Get Dock status and set available status */
+ _mm_sound_get_dock_type (&dock_type);
+ if (dock_type == DOCK_DESKDOCK) {
+ SET_AVAILABLE(MM_SOUND_DEVICE_OUT_DOCK);
+ }
+
+ /* Get BT status and set available status */
+ MMSoundMgrPulseGetInitialBTStatus (&a2dp, &sco);
+ if (a2dp) {
+ SET_AVAILABLE(MM_SOUND_DEVICE_OUT_BT_A2DP);
+ MMSoundMgrDeviceUpdateStatus(DEVICE_UPDATE_STATUS_CONNECTED, DEVICE_TYPE_BLUETOOTH, DEVICE_IO_DIRECTION_OUT, DEVICE_ID_AUTO, NULL, 0, NULL);
+ }
+ if (sco) {
+ SET_AVAILABLE(MM_SOUND_DEVICE_OUT_BT_SCO);
+ SET_AVAILABLE(MM_SOUND_DEVICE_IN_BT_SCO);
+ MMSoundMgrDeviceUpdateStatus(DEVICE_UPDATE_STATUS_CONNECTED, DEVICE_TYPE_BLUETOOTH, DEVICE_IO_DIRECTION_BOTH, DEVICE_ID_AUTO, NULL, 0, NULL);
+ }
+
+ /* Set Active device based on priority */
+ __select_playback_active_device ();
+ __select_capture_active_device ();
+
+ __set_route(true, false);
+ dump_info();
+}
+
+static void __handle_bt_a2dp_on (void)
+{
+ int ret = MM_ERROR_NONE;
+
+ /* at this time, pulseaudio default sink is bt sink */
+ if (IS_CALL_SESSION()) {
+ debug_warning ("Current session is VOICECALL or VIDEOCALL or VOIP, no auto-activation!!!\n");
+ return;
+ }
+
+ debug_log ("Activate BT_A2DP device\n");
+ SET_PLAYBACK_ONLY_ACTIVE(MM_SOUND_DEVICE_OUT_BT_A2DP);
+
+ /* ACTIVATE BLUETOOTH */
+ MMSoundMgrDeviceUpdateStatus (DEVICE_UPDATE_STATUS_CHANGED_INFO_STATE, DEVICE_TYPE_BLUETOOTH, 0, DEVICE_ID_AUTO, NULL, DEVICE_STATE_ACTIVATED, NULL);
+ /* DEACTIVATE OTHERS */
+ __set_deactivate_all_device_auto (GET_ACTIVE_CAPTURE(), GET_ACTIVE_PLAYBACK());
+
+ /* For sharing device information with PulseAudio */
+ MMSoundMgrPulseSetActiveDevice(MM_SOUND_DEVICE_IN_NONE, GET_ACTIVE_PLAYBACK());
+
+ ret = _mm_sound_mgr_device_active_device_callback(GET_ACTIVE_CAPTURE(), GET_ACTIVE_PLAYBACK());
+ if (ret != MM_ERROR_NONE) {
+ debug_error ("_mm_sound_mgr_device_active_device_callback() failed [%x]\n", ret);
+ }
+
+ dump_info ();
+}
+
+static void __handle_bt_a2dp_off (void)
+{
+ if (!IS_ACTIVE(MM_SOUND_DEVICE_OUT_BT_A2DP)) {
+ debug_warning("MM_SOUND_DEVICE_OUT_BT_A2DP was not active. nothing to do here.");
+ dump_info ();
+ return;
+ }
+
+ /* if bt was active, then do asm pause */
+ debug_msg("Do pause here");
+ _asm_pause_process (g_info.asm_handle);
+
+ /* set BT A2DP device to none */
+ debug_msg("Deactivate BT_A2DP device\n");
+ UNSET_ACTIVE(MM_SOUND_DEVICE_OUT_BT_A2DP);
+
+ /* DEACTIVATE BLUETOOTH */
+ MMSoundMgrDeviceUpdateStatus (DEVICE_UPDATE_STATUS_CHANGED_INFO_STATE, DEVICE_TYPE_BLUETOOTH, 0, DEVICE_ID_AUTO, NULL, DEVICE_STATE_DEACTIVATED, NULL);
+
+ /* activate current available device based on priority */
+ __select_playback_active_device();
+
+ /* Do set path and notify result */
+ __set_route_nolock(true, true);
+
+ dump_info ();
+}
+
+static void __handle_bt_sco_on ()
+{
+ /* if fmradio session, do nothing */
+
+ /* Skip when noti session */
+
+ /* ToDo : alarm/notification session ???? */
+ if (IS_CALL_SESSION()) {
+ debug_warning ("Current session is VOICECALL or VIDEOCALL or VOIP, no auto-activation!!!\n");
+ return;
+ }
+
+ debug_log ("Activate BT SCO IN/OUT device\n");
+ SET_PLAYBACK_ONLY_ACTIVE(MM_SOUND_DEVICE_OUT_BT_SCO);
+ SET_CAPTURE_ONLY_ACTIVE(MM_SOUND_DEVICE_IN_BT_SCO);
+
+ /* For wearable history */
+ /* __set_route_nolock(ROUTE_PARAM_BROADCASTING | ROUTE_PARAM_CORK_DEVICE); */
+ /* Do set path and notify result */
+ __set_route(true, true);
+
+ /* ACTIVATE BLUETOOTH */
+ MMSoundMgrDeviceUpdateStatus (DEVICE_UPDATE_STATUS_CHANGED_INFO_STATE, DEVICE_TYPE_BLUETOOTH, 0, DEVICE_ID_AUTO, NULL, DEVICE_STATE_ACTIVATED, NULL);
+ /* DEACTIVATE OTHERS */
+ __set_deactivate_all_device_auto (GET_ACTIVE_CAPTURE(), GET_ACTIVE_PLAYBACK());
+
+ dump_info ();
+}
+
+static void __handle_bt_sco_off (void)
+{
+ /* DEACTIVATE BLUETOOTH */
+ MMSoundMgrDeviceUpdateStatus (DEVICE_UPDATE_STATUS_CHANGED_INFO_STATE, DEVICE_TYPE_BLUETOOTH, 0, DEVICE_ID_AUTO, NULL, DEVICE_STATE_DEACTIVATED, NULL);
+
+ /* If sco is not activated, just return */
+ if (!IS_ACTIVE(MM_SOUND_DEVICE_OUT_BT_SCO) && !IS_ACTIVE(MM_SOUND_DEVICE_IN_BT_SCO)) {
+ debug_warning("BT SCO was not active. nothing to do here.");
+ dump_info ();
+ return;
+ }
+
+ /* set bt device to none */
+ debug_msg("Deactivate BT_SCO device\n");
+ UNSET_ACTIVE(MM_SOUND_DEVICE_OUT_BT_SCO);
+ UNSET_ACTIVE(MM_SOUND_DEVICE_IN_BT_SCO);
+
+ if (IS_CALL_SESSION()) {
+ debug_warning ("Current session is VOICECALL or VIDEOCALL or VOIP, no auto-activation!!!\n");
+ return;
+ }
+
+ /* activate current available device based on priority */
+ __select_playback_active_device();
+ __select_capture_active_device();
+
+ /* Do set path and notify result */
+ __set_route_nolock(true, true);
+
+ dump_info ();
+}
+
+static void __handle_headset_on (int type)
+{
+ /* at this time, pulseaudio default sink is bt sink */
+ /* if fmradio session, do nothing */
+
+ /* Skip when noti session */
+
+ /* ToDo : alarm/notification session ???? */
+ if (IS_CALL_SESSION()) {
+ debug_warning ("Current session is VOICECALL or VIDEOCALL or VOIP, no auto-activation!!!\n");
+ return;
+ }
+
+ debug_log ("Activate WIRED OUT device\n");
+ SET_PLAYBACK_ONLY_ACTIVE(MM_SOUND_DEVICE_OUT_WIRED_ACCESSORY);
+ if (type == DEVICE_EARJACK_TYPE_SPK_WITH_MIC) {
+ debug_log ("Activate WIRED IN device\n");
+ SET_CAPTURE_ONLY_ACTIVE(MM_SOUND_DEVICE_IN_WIRED_ACCESSORY);
+ }
+
+ /* Do set path and notify result */
+ __set_route(true, true);
+
+ /* ACTIVATE AUDIOJACK */
+ MMSoundMgrDeviceUpdateStatus (DEVICE_UPDATE_STATUS_CHANGED_INFO_STATE, DEVICE_TYPE_AUDIOJACK, 0, DEVICE_ID_AUTO, NULL, DEVICE_STATE_ACTIVATED, NULL);
+ /* DEACTIVATE OTHERS */
+ __set_deactivate_all_device_auto (GET_ACTIVE_CAPTURE(), GET_ACTIVE_PLAYBACK());
+ if (type == DEVICE_EARJACK_TYPE_SPK_WITH_MIC) {
+ MMSoundMgrDeviceUpdateStatus (DEVICE_UPDATE_STATUS_CHANGED_INFO_STATE, DEVICE_TYPE_BUILTIN_MIC, 0, DEVICE_ID_AUTO, NULL, DEVICE_STATE_DEACTIVATED, NULL);
+ }
+
+ dump_info ();
+}
+
+static void __handle_headset_off (void)
+{
+ /* FIXME : Need to be removed volume seperation on public */
+ if (!IS_ACTIVE(MM_SOUND_DEVICE_OUT_WIRED_ACCESSORY)) {
+ debug_warning("MM_SOUND_DEVICE_OUT_WIRED_ACCESSORY was not active. nothing to do here.");
+ return;
+ }
+
+ /* if Headset was active, then do asm pause */
+ debug_msg("Do pause here");
+ _asm_pause_process (g_info.asm_handle);
+
+ /* set Headset device to none */
+ debug_msg("Deactivate WIRED IN/OUT device\n");
+ UNSET_ACTIVE(MM_SOUND_DEVICE_OUT_WIRED_ACCESSORY);
+ UNSET_ACTIVE(MM_SOUND_DEVICE_IN_WIRED_ACCESSORY);
+
+ /* For call or voip session, activation device is up-to application policy */
+ if (IS_CALL_SESSION()) {
+ debug_warning ("Current session is VOICECALL or VIDEOCALL or VOIP, no auto-activation!!!\n");
+ return;
+ }
+
+ /* activate current available device based on priority */
+ __select_playback_active_device();
+ __select_capture_active_device();
+
+ /* Do set path and notify result */
+ __set_route(true, true);
+
+ /* DEACTIVATE AUDIOJACK */
+ MMSoundMgrDeviceUpdateStatus (DEVICE_UPDATE_STATUS_CHANGED_INFO_STATE, DEVICE_TYPE_AUDIOJACK, 0, DEVICE_ID_AUTO, NULL, DEVICE_STATE_DEACTIVATED, NULL);
+
+ dump_info ();
+}
+
+static void __handle_dock_on (void)
+{
+ /* ToDo : alarm/notification session ???? */
+ if (IS_CALL_SESSION()) {
+ debug_warning ("Current session is VOICECALL or VIDEOCALL or VOIP, no auto-activation!!!\n");
+ return;
+ }
+
+ debug_log ("Activate DOCK device\n");
+ SET_PLAYBACK_ONLY_ACTIVE(MM_SOUND_DEVICE_OUT_DOCK);
+
+ /* Do set path and notify result */
+ __set_route(true, true);
+
+ dump_info ();
+}
+
+static void __handle_dock_off (void)
+{
+ if (!IS_ACTIVE(MM_SOUND_DEVICE_OUT_DOCK)) {
+ debug_warning("MM_SOUND_DEVICE_OUT_DOCK was not active. nothing to do here.");
+ return;
+ }
+
+ /* if Dock was active, then do asm pause */
+ debug_msg("Do pause here");
+ _asm_pause_process (g_info.asm_handle);
+
+ /* set DOCK device to none */
+ debug_msg("Deactivate DOCK device\n");
+ UNSET_ACTIVE(MM_SOUND_DEVICE_OUT_DOCK);
+
+ /* activate current available device based on priority */
+ __select_playback_active_device();
+
+ /* Do set path and notify result */
+ __set_route(true, true);
+
+ dump_info ();
+}
+
+static void __handle_hdmi_on (void)
+{
+ /* ToDo : alarm/notification session ???? */
+ if (IS_CALL_SESSION()) {
+ debug_warning ("Current session is VOICECALL or VIDEOCALL or VOIP, no auto-activation!!!\n");
+ return;
+ }
+
+ debug_log ("Activate HDMI device\n");
+ SET_PLAYBACK_ONLY_ACTIVE(MM_SOUND_DEVICE_OUT_HDMI);
+
+ /* ACTIVATE HDMI */
+ MMSoundMgrDeviceUpdateStatus (DEVICE_UPDATE_STATUS_CHANGED_INFO_STATE, DEVICE_TYPE_HDMI, 0, DEVICE_ID_AUTO, NULL, DEVICE_STATE_ACTIVATED, NULL);
+ /* DEACTIVATE OTHERS */
+ __set_deactivate_all_device_auto (GET_ACTIVE_CAPTURE(), GET_ACTIVE_PLAYBACK());
+
+ /* Do set path and notify result */
+ __set_route(true, true);
+
+ dump_info ();
+}
+
+static void __handle_hdmi_off (void)
+{
+ if (!IS_ACTIVE(MM_SOUND_DEVICE_OUT_HDMI)) {
+ debug_warning("MM_SOUND_DEVICE_OUT_HDMI was not active. nothing to do here.");
+ return;
+ }
+
+ /* if HDMI was active, then do asm pause */
+ debug_msg("Do pause here");
+ _asm_pause_process (g_info.asm_handle);
+
+ MMSoundMgrPulseUnLoadHDMI();
+
+ /* set HDMI device to none */
+ debug_msg("Deactivate HDMI device\n");
+ UNSET_ACTIVE(MM_SOUND_DEVICE_OUT_HDMI);
+
+
+ /* DEACTIVATE HDMI */
+ MMSoundMgrDeviceUpdateStatus (DEVICE_UPDATE_STATUS_CHANGED_INFO_STATE, DEVICE_TYPE_HDMI, 0, DEVICE_ID_AUTO, NULL, DEVICE_STATE_DEACTIVATED, NULL);
+
+ /* activate current available device based on priority */
+ __select_playback_active_device();
+
+ /* Do set path and notify result */
+ __set_route(true, true);
+
+ dump_info ();
+}
+
+static void __handle_mirroring_on (void)
+{
+ /* ToDo : alarm/notification session ???? */
+ if (IS_CALL_SESSION()) {
+ debug_warning ("Current session is VOICECALL or VIDEOCALL or VOIP, no auto-activation!!!\n");
+ return;
+ }
+
+ debug_log ("Activate MIRRORING device\n");
+ SET_PLAYBACK_ONLY_ACTIVE(MM_SOUND_DEVICE_OUT_MIRRORING);
+
+ /* ACTIVATE MIRRORING */
+ MMSoundMgrDeviceUpdateStatus (DEVICE_UPDATE_STATUS_CHANGED_INFO_STATE, DEVICE_TYPE_MIRRORING, 0, DEVICE_ID_AUTO, NULL, DEVICE_STATE_ACTIVATED, NULL);
+ /* DEACTIVATE OTHERS */
+ __set_deactivate_all_device_auto (GET_ACTIVE_CAPTURE(), GET_ACTIVE_PLAYBACK());
+
+ /* Do set path and notify result */
+ __set_route(true, true);
+
+ dump_info ();
+}
+
+static void __handle_mirroring_off (void)
+{
+ if (!IS_ACTIVE(MM_SOUND_DEVICE_OUT_MIRRORING)) {
+ debug_warning("MM_SOUND_DEVICE_OUT_MIRRORING was not active. nothing to do here.");
+ return;
+ }
+
+ /* if MIRRORING was active, then do asm pause */
+ debug_msg("Do pause here");
+ _asm_pause_process (g_info.asm_handle);
+
+ /* set MIRRORING device to none */
+ debug_msg("Deactivate MIRRORING device\n");
+ UNSET_ACTIVE(MM_SOUND_DEVICE_OUT_MIRRORING);
+
+ /* DEACTIVATE MIRRORING */
+ MMSoundMgrDeviceUpdateStatus (DEVICE_UPDATE_STATUS_CHANGED_INFO_STATE, DEVICE_TYPE_MIRRORING, 0, DEVICE_ID_AUTO, NULL, DEVICE_STATE_DEACTIVATED, NULL);
+
+ /* activate current available device based on priority */
+ __select_playback_active_device();
+
+ /* Do set path and notify result */
+ __set_route(true, true);
+
+ dump_info ();
+}
+
+static void __handle_usb_audio_on (void)
+{
+ int ret = MM_ERROR_NONE;
+
+ if (IS_CALL_SESSION()) {
+ debug_warning ("Current session is VOICECALL or VIDEOCALL or VOIP, no auto-activation!!!\n");
+ return;
+ }
+
+ debug_log ("Activate USB Audio device\n");
+ SET_PLAYBACK_ONLY_ACTIVE(MM_SOUND_DEVICE_OUT_USB_AUDIO);
+
+ /* ACTIVATE USB_AUDIO */
+ MMSoundMgrDeviceUpdateStatus (DEVICE_UPDATE_STATUS_CHANGED_INFO_STATE, DEVICE_TYPE_USB_AUDIO, 0, DEVICE_ID_AUTO, NULL, DEVICE_STATE_ACTIVATED, NULL);
+ /* DEACTIVATE OTHERS */
+ __set_deactivate_all_device_auto (GET_ACTIVE_CAPTURE(), GET_ACTIVE_PLAYBACK());
+
+ /* For sharing device information with PulseAudio */
+ MMSoundMgrPulseSetActiveDevice(MM_SOUND_DEVICE_IN_NONE, GET_ACTIVE_PLAYBACK());
+
+ ret = _mm_sound_mgr_device_active_device_callback(GET_ACTIVE_CAPTURE(), GET_ACTIVE_PLAYBACK());
+ if (ret != MM_ERROR_NONE) {
+ debug_error ("_mm_sound_mgr_device_active_device_callback() failed [%x]\n", ret);
+ }
+
+ dump_info ();
+}
+
+static void __handle_usb_audio_off (void)
+{
+ if (!IS_ACTIVE(MM_SOUND_DEVICE_OUT_USB_AUDIO)) {
+ debug_warning("MM_SOUND_DEVICE_OUT_USB_AUDIO was not active. nothing to do here.");
+ dump_info ();
+ return;
+ }
+
+ /* if device was active, then do asm pause */
+ debug_msg("Do pause here");
+ _asm_pause_process (g_info.asm_handle);
+
+ /* set USB Audio device to none */
+ debug_msg("Deactivate USB Audio device\n");
+ UNSET_ACTIVE(MM_SOUND_DEVICE_OUT_USB_AUDIO);
+
+ /* DEACTIVATE USB_AUDIO */
+ MMSoundMgrDeviceUpdateStatus (DEVICE_UPDATE_STATUS_CHANGED_INFO_STATE, DEVICE_TYPE_USB_AUDIO, 0, DEVICE_ID_AUTO, NULL, DEVICE_STATE_DEACTIVATED, NULL);
+
+ /* activate current available device based on priority */
+ __select_playback_active_device();
+
+ /* Do set path and notify result */
+ __set_route(true, true);
+
+ dump_info ();
+}
+
+static void __handle_multimedia_dock_on (void)
+{
+ if (IS_CALL_SESSION()) {
+ debug_warning ("Current session is VOICECALL or VIDEOCALL or VOIP, no auto-activation!!!\n");
+ return;
+ }
+
+ /* If HDMI has already been actived, we just skip active. */
+ if (IS_ACTIVE(MM_SOUND_DEVICE_OUT_HDMI)) {
+ debug_warning ("HDMI device has been already actived. Just skip Multimedia Dock active action.\n");
+ return;
+ }
+
+ debug_log ("Activate Multimedia Dock device\n");
+ SET_PLAYBACK_ONLY_ACTIVE(MM_SOUND_DEVICE_OUT_MULTIMEDIA_DOCK);
+
+ /* Do set path and notify result */
+ __set_route(true, true);
+
+ dump_info ();
+}
+
+static void __handle_multimedia_dock_off (void)
+{
+ if (!IS_ACTIVE(MM_SOUND_DEVICE_OUT_MULTIMEDIA_DOCK)) {
+ debug_warning("MM_SOUND_DEVICE_OUT_MULTIMEDIA_DOCK was not active. nothing to do here.");
+ dump_info ();
+ return;
+ }
+
+ /* if device was active, then do asm pause */
+ debug_msg("Do pause here");
+ _asm_pause_process (g_info.asm_handle);
+
+ /* set MultimediaDock device to none */
+ debug_msg("Deactivate Multimedia Dock device\n");
+ UNSET_ACTIVE(MM_SOUND_DEVICE_OUT_MULTIMEDIA_DOCK);
+
+ /* activate current available device based on priority */
+ __select_playback_active_device();
+
+ /* Do set path and notify result */
+ __set_route(true, true);
+
+ dump_info ();
+}
+
+static const char* __get_session_string(session_t session)
+{
+ switch(session) {
+ case SESSION_MEDIA:
+ return "MEDIA";
+ case SESSION_VOICECALL:
+ return "VOICECALL";
+ case SESSION_VIDEOCALL:
+ return "VIDEOCALL";
+ case SESSION_VOIP:
+ return "VOIP";
+ case SESSION_FMRADIO:
+ return "FMRADIO";
+ case SESSION_NOTIFICATION:
+ return "NOTOFICATION";
+ case SESSION_ALARM:
+ return "ALARM";
+ case SESSION_EMERGENCY:
+ return "EMERGENCY";
+ case SESSION_VOICE_RECOGNITION:
+ return "VOICE_RECOGNITION";
+ default:
+ return "unknow session";
+ }
+}
+
+static const char* __get_subsession_string(subsession_t session)
+{
+ switch(session) {
+ case SUBSESSION_VOICE:
+ return "VOICECALL";
+ case SUBSESSION_RINGTONE:
+ return "RINGTONE";
+ case SUBSESSION_MEDIA:
+ return "MEDIA";
+ case SUBSESSION_INIT:
+ return "SUBSESSION_INIT";
+ case SUBSESSION_VR_NORMAL:
+ return "VR_NORMAL";
+ case SUBSESSION_VR_DRIVE:
+ return "VR_DRIVE";
+ case SUBSESSION_RECORD_STEREO:
+ return "RECORD_STEREO";
+ case SUBSESSION_RECORD_MONO:
+ return "RECORD_MONO";
+ default:
+ return "unknow subsession";
+ }
+}
+
+#ifdef TIZEN_MICRO
+static const char* __get_bt_bandwidth_string(int bandwidth)
+{
+ switch(bandwidth) {
+ case MM_SOUND_BANDWIDTH_UNKNOWN:
+ return "none. maybe bt is disconnected";
+ case MM_SOUND_BANDWIDTH_NB:
+ return "NB";
+ case MM_SOUND_BANDWIDTH_WB:
+ return "WB";
+ default:
+ return "unknow bandwidth";
+ }
+}
+
+static const char* __get_hfp_connection_state_string(int bandwidth)
+{
+ switch(bandwidth) {
+ case MM_SOUND_HFP_STATUS_UNKNOWN:
+ return "unknown";
+ case MM_SOUND_HFP_STATUS_INCOMMING_CALL:
+ return "HFP_INCOMMING_CALL:RINGTONE";
+ default:
+ return "unknow";
+ }
+}
+#endif
+
+static const char* __get_device_type_string(int device)
+{
+ switch(device) {
+ case DEVICE_BUILTIN:
+ return "builtin";
+ case DEVICE_WIRED:
+ return "wired";
+ case DEVICE_BT_A2DP:
+ return "bt-a2dp";
+ case DEVICE_BT_SCO:
+ return "bt-sco";
+ case DEVICE_DOCK:
+ return "dock";
+ case DEVICE_HDMI:
+ return "hdmi";
+ case DEVICE_MIRRORING:
+ return "mirroring";
+ case DEVICE_USB_AUDIO:
+ return "usb-audio";
+ case DEVICE_MULTIMEDIA_DOCK:
+ return "multimedia-dock";
+ default:
+ return "unknow device";
+ }
+}
+
+/* ------------------------- EXTERNAL FUNCTIONS ------------------------------------*/
+#ifdef TIZEN_MICRO
+int MMSoundMgrSessionMediaPause ()
+{
+ debug_msg ("[SESSION] Media pause requested...");
+ _asm_pause_process (g_info.asm_handle);
+
+ return MM_ERROR_NONE;
+}
+
+int MMSoundMgrSessionSetHFBandwidth (int bandwidth)
+{
+ debug_msg ("Set HF SCO bandwidth=(%s)", __get_bt_bandwidth_string(bandwidth));
+ g_info.bt_info.hf_wb = bandwidth;
+ return MM_ERROR_NONE;
+}
+
+int MMSoundMgrSessionSetHFPConnectionState (int stat)
+{
+ debug_msg ("Set HF SCO Stat=(%s)", __get_hfp_connection_state_string(stat));
+ g_info.bt_info.hfp_conn_state = stat;
+ return MM_ERROR_NONE;
+}
+#endif /* TIZEN_MICRO */
+
+int MMSoundMgrSessionEnableAgSCO (bool enable)
+{
+ debug_msg ("Set AG SCO enable=%d\n", enable);
+
+ if (enable) {
+ __handle_bt_sco_on();
+ } else {
+ __handle_bt_sco_off();
+ }
+ return MM_ERROR_NONE;
+}
+
+int MMSoundMgrSessionSetSCO (bool is_sco_on, bool is_bt_nrec, bool is_bt_wb)
+{
+ debug_msg ("[SESSION] Set SCO enable=%d, nrec=%d, wb=%d", is_sco_on, is_bt_nrec, is_bt_wb);
+ g_info.bt_info.is_nrec = (is_sco_on)? is_bt_nrec : false;
+ g_info.bt_info.is_wb = (is_sco_on)? is_bt_wb : false;
+
+ if (is_sco_on) {
+ __handle_bt_sco_on();
+ } else {
+ __handle_bt_sco_off();
+ }
+ return MM_ERROR_NONE;
+}
+
+/* DEVICE : Called by mgr_pulse for updating current default_sink_name */
+int MMSoundMgrSessionSetDefaultSink (const char * const default_sink_name)
+{
+ LOCK_SESSION();
+
+ MMSOUND_STRNCPY(g_info.default_sink_name, default_sink_name, MAX_STRING_LEN);
+
+ debug_msg ("[SESSION] default sink=[%s]\n", default_sink_name);
+
+ /* ToDo: do something */
+
+ UNLOCK_SESSION();
+
+ return MM_ERROR_NONE;
+}
+
+/* DEVICE : Called by mgr_pulse for bt and mgr_headset for headset */
+int MMSoundMgrSessionSetDeviceAvailable (device_type_t device, int available, int type, const char* name)
+{
+ LOCK_SESSION();
+
+ debug_warning ("[SESSION]set device available. device(%s), available(%d), type(%d), name(%s)\n",
+ __get_device_type_string(device), available, type, name != NULL ? name : "null");
+ switch (device) {
+ case DEVICE_WIRED:
+ if (available) {
+
+ if (!IS_AVAILABLE(MM_SOUND_DEVICE_OUT_WIRED_ACCESSORY)) {
+ SET_AVAILABLE(MM_SOUND_DEVICE_OUT_WIRED_ACCESSORY);
+ /* available device & send available callback */
+ if (type == DEVICE_EARJACK_TYPE_SPK_WITH_MIC) {
+ SET_AVAILABLE(MM_SOUND_DEVICE_IN_WIRED_ACCESSORY);
+ _mm_sound_mgr_device_available_device_callback(
+ MM_SOUND_DEVICE_IN_WIRED_ACCESSORY,
+ MM_SOUND_DEVICE_OUT_WIRED_ACCESSORY,
+ AVAILABLE);
+ } else {
+ _mm_sound_mgr_device_available_device_callback(
+ MM_SOUND_DEVICE_IN_NONE,
+ MM_SOUND_DEVICE_OUT_WIRED_ACCESSORY,
+ AVAILABLE);
+ }
+
+ /* Store earphone type */
+ g_info.headset_type = type;
+
+ /* activate device & send activated callback */
+ __handle_headset_on(type);
+ } else {
+ debug_log ("Already device [%d] is available...\n", device);
+ }
+
+ } else {
+ if (IS_AVAILABLE(MM_SOUND_DEVICE_OUT_WIRED_ACCESSORY)) {
+
+ /* unavailable earphone & earmic(if available)*/
+ UNSET_AVAILABLE(MM_SOUND_DEVICE_OUT_WIRED_ACCESSORY);
+ if (g_info.headset_type == DEVICE_EARJACK_TYPE_SPK_WITH_MIC) {
+ UNSET_AVAILABLE(MM_SOUND_DEVICE_IN_WIRED_ACCESSORY);
+ }
+ /* Clear earphone type */
+ g_info.headset_type = EARJACK_UNPLUGGED;
+
+ /* unactivate device & send callback */
+ __handle_headset_off();
+
+ /* Send unavailable callback */
+ if (g_info.headset_type == DEVICE_EARJACK_TYPE_SPK_WITH_MIC) {
+ _mm_sound_mgr_device_available_device_callback(
+ MM_SOUND_DEVICE_IN_WIRED_ACCESSORY,
+ MM_SOUND_DEVICE_OUT_WIRED_ACCESSORY,
+ NOT_AVAILABLE);
+ } else {
+ _mm_sound_mgr_device_available_device_callback(
+ MM_SOUND_DEVICE_IN_NONE,
+ MM_SOUND_DEVICE_OUT_WIRED_ACCESSORY,
+ NOT_AVAILABLE);
+ }
+
+ } else {
+ debug_log ("Already device [%d] is unavailable...\n", device);
+ }
+ }
+ break;
+
+ case DEVICE_BT_A2DP:
+ if (name)
+ MMSOUND_STRNCPY(g_info.bt_info.name, name, MAX_STRING_LEN);
+ else
+ memset(g_info.bt_info.name, 0, MAX_STRING_LEN);
+
+ if (available) {
+ if (!IS_AVAILABLE(MM_SOUND_DEVICE_OUT_BT_A2DP)) {
+ SET_AVAILABLE(MM_SOUND_DEVICE_OUT_BT_A2DP);
+ _mm_sound_mgr_device_available_device_callback(
+ MM_SOUND_DEVICE_IN_NONE,
+ MM_SOUND_DEVICE_OUT_BT_A2DP,
+ AVAILABLE);
+
+ __handle_bt_a2dp_on();
+ } else {
+ debug_log ("Already device [%d] is available...\n", device);
+ }
+ } else {
+ if (IS_AVAILABLE(MM_SOUND_DEVICE_OUT_BT_A2DP)) {
+ UNSET_AVAILABLE(MM_SOUND_DEVICE_OUT_BT_A2DP);
+ __handle_bt_a2dp_off();
+ _mm_sound_mgr_device_available_device_callback(
+ MM_SOUND_DEVICE_IN_NONE,
+ MM_SOUND_DEVICE_OUT_BT_A2DP,
+ NOT_AVAILABLE);
+
+
+ } else {
+ debug_log ("Already device [%d] is unavailable...\n", device);
+ }
+ }
+ break;
+
+ case DEVICE_BT_SCO:
+ if (available) {
+ if (!IS_AVAILABLE(MM_SOUND_DEVICE_OUT_BT_SCO)) {
+ SET_AVAILABLE(MM_SOUND_DEVICE_OUT_BT_SCO);
+ SET_AVAILABLE(MM_SOUND_DEVICE_IN_BT_SCO);
+ _mm_sound_mgr_device_available_device_callback(
+ MM_SOUND_DEVICE_IN_BT_SCO,
+ MM_SOUND_DEVICE_OUT_BT_SCO,
+ AVAILABLE);
+ } else {
+ debug_log ("Already device [%d] is available...\n", device);
+ }
+ } else {
+ if (IS_AVAILABLE(MM_SOUND_DEVICE_OUT_BT_SCO)) {
+ UNSET_AVAILABLE(MM_SOUND_DEVICE_OUT_BT_SCO);
+ UNSET_AVAILABLE(MM_SOUND_DEVICE_IN_BT_SCO);
+ __handle_bt_sco_off();
+ _mm_sound_mgr_device_available_device_callback(
+ MM_SOUND_DEVICE_IN_BT_SCO,
+ MM_SOUND_DEVICE_OUT_BT_SCO,
+ NOT_AVAILABLE);
+
+ } else {
+ debug_log ("Already device [%d] is unavailable...\n", device);
+ }
+ }
+ break;
+
+ case DEVICE_DOCK:
+ if (available) {
+ if (!IS_AVAILABLE(MM_SOUND_DEVICE_OUT_DOCK)) {
+ SET_AVAILABLE(MM_SOUND_DEVICE_OUT_DOCK);
+ _mm_sound_mgr_device_available_device_callback(
+ MM_SOUND_DEVICE_IN_NONE,
+ MM_SOUND_DEVICE_OUT_DOCK,
+ AVAILABLE);
+ __handle_dock_on();
+ } else {
+ debug_log ("Already device [%d] is available...\n", device);
+ }
+ } else {
+ if (IS_AVAILABLE(MM_SOUND_DEVICE_OUT_DOCK)) {
+ UNSET_AVAILABLE(MM_SOUND_DEVICE_OUT_DOCK);
+ __handle_dock_off();
+ _mm_sound_mgr_device_available_device_callback(
+ MM_SOUND_DEVICE_IN_NONE,
+ MM_SOUND_DEVICE_OUT_DOCK,
+ NOT_AVAILABLE);
+
+ } else {
+ debug_log ("Already device [%d] is unavailable...\n", device);
+ }
+ }
+ break;
+
+ case DEVICE_HDMI:
+ if (available) {
+ if (!IS_AVAILABLE(MM_SOUND_DEVICE_OUT_HDMI)) {
+ SET_AVAILABLE(MM_SOUND_DEVICE_OUT_HDMI);
+ _mm_sound_mgr_device_available_device_callback(
+ MM_SOUND_DEVICE_IN_NONE,
+ MM_SOUND_DEVICE_OUT_HDMI,
+ AVAILABLE);
+ __handle_hdmi_on();
+ } else {
+ debug_log ("Already device [%d] is available...\n", device);
+ }
+ } else {
+ if (IS_AVAILABLE(MM_SOUND_DEVICE_OUT_HDMI)) {
+ UNSET_AVAILABLE(MM_SOUND_DEVICE_OUT_HDMI);
+ __handle_hdmi_off();
+ _mm_sound_mgr_device_available_device_callback(
+ MM_SOUND_DEVICE_IN_NONE,
+ MM_SOUND_DEVICE_OUT_HDMI,
+ NOT_AVAILABLE);
+
+ } else {
+ debug_log ("Already device [%d] is unavailable...\n", device);
+ }
+ }
+ break;
+
+ case DEVICE_MIRRORING:
+ if (available) {
+ if (!IS_AVAILABLE(MM_SOUND_DEVICE_OUT_MIRRORING)) {
+ SET_AVAILABLE(MM_SOUND_DEVICE_OUT_MIRRORING);
+ _mm_sound_mgr_device_available_device_callback(
+ MM_SOUND_DEVICE_IN_NONE,
+ MM_SOUND_DEVICE_OUT_MIRRORING,
+ AVAILABLE);
+ __handle_mirroring_on();
+ } else {
+ debug_log ("Already device [%d] is available...\n", device);
+ }
+ } else {
+ if (IS_AVAILABLE(MM_SOUND_DEVICE_OUT_MIRRORING)) {
+ UNSET_AVAILABLE(MM_SOUND_DEVICE_OUT_MIRRORING);
+ __handle_mirroring_off();
+ _mm_sound_mgr_device_available_device_callback(
+ MM_SOUND_DEVICE_IN_NONE,
+ MM_SOUND_DEVICE_OUT_MIRRORING,
+ NOT_AVAILABLE);
+
+ } else {
+ debug_log ("Already device [%d] is unavailable...\n", device);
+ }
+ }
+ break;
+
+ case DEVICE_USB_AUDIO:
+ if (available) {
+ if (!IS_AVAILABLE(MM_SOUND_DEVICE_OUT_USB_AUDIO)) {
+ SET_AVAILABLE(MM_SOUND_DEVICE_OUT_USB_AUDIO);
+ _mm_sound_mgr_device_available_device_callback(
+ MM_SOUND_DEVICE_IN_NONE,
+ MM_SOUND_DEVICE_OUT_USB_AUDIO,
+ AVAILABLE);
+ __handle_usb_audio_on();
+ } else {
+ debug_log ("Already device [%d] is available...\n", device);
+ }
+ } else {
+ if (IS_AVAILABLE(MM_SOUND_DEVICE_OUT_USB_AUDIO)) {
+ UNSET_AVAILABLE(MM_SOUND_DEVICE_OUT_USB_AUDIO);
+ __handle_usb_audio_off();
+ _mm_sound_mgr_device_available_device_callback(
+ MM_SOUND_DEVICE_IN_NONE,
+ MM_SOUND_DEVICE_OUT_USB_AUDIO,
+ NOT_AVAILABLE);
+
+ } else {
+ debug_log ("Already device [%d] is unavailable...\n", device);
+ }
+ }
+ break;
+ case DEVICE_MULTIMEDIA_DOCK:
+ if (available) {
+ if (!IS_AVAILABLE(MM_SOUND_DEVICE_OUT_MULTIMEDIA_DOCK)) {
+ SET_AVAILABLE(MM_SOUND_DEVICE_OUT_MULTIMEDIA_DOCK);
+ _mm_sound_mgr_device_available_device_callback(
+ MM_SOUND_DEVICE_IN_NONE,
+ MM_SOUND_DEVICE_OUT_MULTIMEDIA_DOCK,
+ AVAILABLE);
+ __handle_multimedia_dock_on();
+ } else {
+ debug_log ("Already device [%d] is available...\n", device);
+ }
+ } else {
+ if (IS_AVAILABLE(MM_SOUND_DEVICE_OUT_MULTIMEDIA_DOCK)) {
+ UNSET_AVAILABLE(MM_SOUND_DEVICE_OUT_MULTIMEDIA_DOCK);
+ if (IS_AVAILABLE(MM_SOUND_DEVICE_OUT_USB_AUDIO)) {
+ UNSET_AVAILABLE(MM_SOUND_DEVICE_OUT_USB_AUDIO);
+ }
+ __handle_multimedia_dock_off();
+ _mm_sound_mgr_device_available_device_callback(
+ MM_SOUND_DEVICE_IN_NONE,
+ MM_SOUND_DEVICE_OUT_MULTIMEDIA_DOCK,
+ NOT_AVAILABLE);
+
+ } else {
+ debug_log ("Already device [%d] is unavailable...\n", device);
+ }
+ }
+ break;
+
+ default:
+ debug_warning ("device [%d] is not handled...\n", device);
+ break;
+ }
+
+ UNLOCK_SESSION();
+
+ return MM_ERROR_NONE;
+}
+
+int MMSoundMgrSessionIsDeviceAvailableNoLock (mm_sound_device_out playback, mm_sound_device_in capture, bool *available)
+{
+ int ret = MM_ERROR_NONE;
+ debug_log ("[SESSION] query playback=[0x%X] capture=[0x%X], current available = [0x%X]\n",
+ playback, capture, g_info.device_available);
+
+ if (available) {
+ if (playback == MM_SOUND_DEVICE_OUT_NONE) {
+ *available = IS_AVAILABLE(capture);
+ } else if (capture == MM_SOUND_DEVICE_IN_NONE) {
+ *available = IS_AVAILABLE(playback);
+ } else {
+ *available = (IS_AVAILABLE(playback) && IS_AVAILABLE(capture));
+ }
+ debug_log ("return available = [%d]\n", *available);
+ } else {
+ debug_warning ("Invalid argument!!!\n");
+ ret = MM_ERROR_INVALID_ARGUMENT;
+ }
+
+ return ret;
+}
+
+
+int MMSoundMgrSessionIsDeviceAvailable (mm_sound_device_out playback, mm_sound_device_in capture, bool *available)
+{
+ int ret = MM_ERROR_NONE;
+
+ LOCK_SESSION();
+ ret = MMSoundMgrSessionIsDeviceAvailableNoLock (playback, capture, available);
+ UNLOCK_SESSION();
+
+ return ret;
+}
+
+int MMSoundMgrSessionGetAvailableDevices (int *playback, int *capture)
+{
+ if (playback == NULL || capture == NULL) {
+ debug_error ("Invalid input parameter\n");
+ return MM_ERROR_INVALID_ARGUMENT;
+ }
+
+ LOCK_SESSION();
+
+ *playback = GET_AVAILABLE_PLAYBACK();
+ *capture = GET_AVAILABLE_CAPTURE();
+ debug_msg ("[SESSION] return available playback=[0x%X]/capture=[0x%X]\n", *playback, *capture);
+
+ UNLOCK_SESSION();
+
+ return MM_ERROR_NONE;
+}
+
+int MMSoundMgrSessionSetDeviceActive (mm_sound_device_out playback, mm_sound_device_in capture, bool need_broadcast)
+{
+ int ret = MM_ERROR_NONE;
+ int old_active = g_info.device_active;
+ bool need_update = false;
+ bool need_cork = true;
+ LOCK_SESSION();
+
+ debug_warning ("[SESSION] playback=[0x%X] capture=[0x%X]\n", playback, capture);
+
+ /* Check whether device is available */
+ if ((playback && !IS_AVAILABLE(playback)) || (capture && !IS_AVAILABLE(capture))) {
+ debug_warning ("Failed to set active state to unavailable device!!!\n");
+ ret = MM_ERROR_INVALID_ARGUMENT;
+ goto END_SET_DEVICE;
+ }
+
+ LOCK_PATH();
+ /* Update active state */
+ debug_log ("Update active device as request\n");
+ if (playback) {
+ int d_ret = MM_ERROR_NONE;
+ device_type_e device;
+
+ SET_PLAYBACK_ONLY_ACTIVE(playback);
+
+ d_ret = __get_device_type_from_old_device(playback, &device);
+ if(d_ret) {
+ debug_warning ("Failed to __get_device_type_from_old_device\n");
+ } else {
+ /* ACTIVATE device */
+ MMSoundMgrDeviceUpdateStatus (DEVICE_UPDATE_STATUS_CHANGED_INFO_STATE, device, 0, DEVICE_ID_AUTO, NULL, DEVICE_STATE_ACTIVATED, NULL);
+ }
+ }
+ if (capture) {
+ int d_ret = MM_ERROR_NONE;
+ device_type_e device;
+ SET_CAPTURE_ONLY_ACTIVE(capture);
+
+ d_ret = __get_device_type_from_old_device(capture, &device);
+ if(d_ret) {
+ debug_warning ("Failed to __get_device_type_from_old_device\n");
+ } else {
+ /* ACTIVATE device */
+ MMSoundMgrDeviceUpdateStatus (DEVICE_UPDATE_STATUS_CHANGED_INFO_STATE, device, 0, DEVICE_ID_AUTO, NULL, DEVICE_STATE_ACTIVATED, NULL);
+ }
+ }
+ /* DEACTIVATE OTHERS */
+ __set_deactivate_all_device_auto (GET_ACTIVE_CAPTURE(), GET_ACTIVE_PLAYBACK());
+
+ if (((g_info.session == SESSION_VOICECALL) || (g_info.session == SESSION_VIDEOCALL))) {
+ bool is_wb, is_nrec;
+#ifndef TIZEN_MICRO
+ bool is_noise_reduction, is_extra_volume, is_upscaling_needed;
+ is_noise_reduction = __is_noise_reduction_on();
+ is_extra_volume = __is_extra_volume_on();
+ is_upscaling_needed = __is_upscaling_needed();
+ if ((g_info.is_noise_reduction != is_noise_reduction)
+ || (g_info.is_extra_volume != is_extra_volume)
+ || (g_info.is_upscaling_needed != is_upscaling_needed)) {
+ need_update = true;
+ }
+ g_info.is_noise_reduction = is_noise_reduction;
+ g_info.is_extra_volume = is_extra_volume;
+ g_info.is_upscaling_needed = is_upscaling_needed;
+#endif /* TIZEN_MICRO */
+#ifdef SUPPORT_BT_SCO
+ /* FIXME : Check all BT SCO */
+ if (playback == MM_SOUND_DEVICE_OUT_BT_SCO && capture == MM_SOUND_DEVICE_IN_BT_SCO) {
+ is_wb = MMSoundMgrPulseBTSCOWBStatus();
+ is_nrec = MMSoundMgrPulseBTSCONRECStatus();
+ if ((g_info.bt_info.is_nrec != is_nrec) || (g_info.bt_info.is_wb != is_wb)) {
+ g_info.bt_info.is_wb = is_wb;
+ g_info.bt_info.is_nrec = is_nrec;
+ need_update = true;
+ }
+ }
+#endif /* SUPPORT_BT_SCO */
+ /* NOT need to cork during voice call */
+ need_cork = false;
+ }
+ UNLOCK_PATH();
+
+ /* If there's changes do path set and inform callback */
+ if (old_active != g_info.device_active || need_update == true) {
+ debug_msg ("Changes happens....set path based on current active device and inform callback(%d)!!!\n", need_broadcast);
+
+ /* Do set path based on current active state */
+ __set_route(need_broadcast, need_cork);
+ } else {
+ debug_msg ("No changes....nothing to do...\n");
+ }
+
+END_SET_DEVICE:
+ UNLOCK_SESSION();
+ return ret;
+}
+
+int MMSoundMgrSessionSetDeviceActiveAuto (void)
+{
+ int ret = MM_ERROR_NONE;
+
+ /* activate current available device based on priority */
+ __select_playback_active_device();
+ __select_capture_active_device();
+ /* Do set path and notify result */
+ ret = __set_route(true, true);
+ if (ret != MM_ERROR_NONE) {
+ debug_error("fail to MMSoundMgrSessionSetDeviceActiveAuto.\n");
+ } else {
+ debug_msg ("success : MMSoundMgrSessionSetDeviceActiveAuto\n");
+ }
+ return ret;
+}
+
+int MMSoundMgrSessionGetDeviceActive (mm_sound_device_out *playback, mm_sound_device_in *capture)
+{
+ if (playback == NULL || capture == NULL) {
+ debug_error ("Invalid input parameter\n");
+ return MM_ERROR_INVALID_ARGUMENT;
+ }
+
+ LOCK_SESSION();
+
+ *playback = GET_ACTIVE_PLAYBACK();
+ *capture = GET_ACTIVE_CAPTURE();
+ debug_msg ("[SESSION] return active playback=[0x%X]/capture=[0x%X]\n", *playback,*capture);
+
+ UNLOCK_SESSION();
+ return MM_ERROR_NONE;
+}
+
+int MMSoundMgrSessionGetAudioPath (mm_sound_device_out *playback, mm_sound_device_in *capture)
+{
+ if (playback == NULL || capture == NULL) {
+ debug_error ("Invalid input parameter\n");
+ return MM_ERROR_INVALID_ARGUMENT;
+ }
+
+ LOCK_SESSION();
+ MMSoundMgrPulseGetPathInfo(playback, capture);
+ debug_msg ("[SESSION] return current audio path which is set to ALSA . playback=[0x%X]/capture=[0x%X]\n", *playback,*capture);
+
+ UNLOCK_SESSION();
+ return MM_ERROR_NONE;
+}
+
+/* SUBSESSION */
+int MMSoundMgrSessionSetSession(session_t session, session_state_t state)
+{
+ LOCK_SESSION();
+
+ debug_warning ("[SESSION] session=[%s] state=[%s]\n", __get_session_string(session), state==SESSION_START ? "start" : "end");
+
+ /* Update Enable session */
+ if (state) {
+ g_info.session = session;
+ } else {
+ g_info.session = SESSION_MEDIA;
+ g_info.subsession = SUBSESSION_VOICE; /* initialize subsession */
+ }
+
+ MMSoundMgrPulseSetSession(session, state);
+
+ /* Do action based on new session */
+ switch (session) {
+ case SESSION_MEDIA:
+ __set_playback_route_media (state);
+ break;
+
+ case SESSION_VOICECALL:
+ case SESSION_VIDEOCALL:
+ __set_playback_route_call (state);
+ break;
+ case SESSION_VOIP:
+ __set_playback_route_voip (state);
+ break;
+
+ case SESSION_FMRADIO:
+ __set_playback_route_fmradio (state);
+ break;
+
+ case SESSION_NOTIFICATION:
+ __set_playback_route_notification (state);
+ break;
+
+ case SESSION_ALARM:
+ __set_playback_route_alarm (state);
+ break;
+
+ case SESSION_EMERGENCY:
+ __set_playback_route_emergency (state);
+ break;
+
+ case SESSION_VOICE_RECOGNITION:
+ __set_playback_route_voicerecognition (state);
+ break;
+
+ default:
+ debug_warning ("session [%s] is not handled...\n", __get_session_string(session));
+ break;
+ }
+
+ UNLOCK_SESSION();
+ return MM_ERROR_NONE;
+}
+
+int MMSoundMgrSessionGetSession(session_t *session)
+{
+ if (session == NULL) {
+ debug_error ("Invalid input parameter\n");
+ return MM_ERROR_INVALID_ARGUMENT;
+ }
+
+ /* LOCK_SESSION(); */
+ *session = g_info.session;
+ /* UNLOCK_SESSION(); */
+
+ return MM_ERROR_NONE;
+}
+
+const char* MMSoundMgrSessionGetSessionString(session_t session)
+{
+ return __get_session_string(session);
+}
+#ifdef TIZEN_MICRO
+int MMSoundMgrSessionSetDuplicateSubSession()
+{
+ /* This function is for set sub session duplicate
+ When BT wb/nb is changed, the call application cannot set
+ normal alsa scenario.
+ Because call app is set sub session before BT band is decided.
+ (Actually BT frw can know the band after SCO request
+ from phone)
+
+ Ref. mm_sound_mgr_pulse.c _bt_hf_cb function.
+ */
+
+ int ret = 0;
+ debug_msg ("Duplicated path control");
+
+ LOCK_SESSION();
+
+ ret = __set_route(false, false);
+ if(ret != MM_ERROR_NONE)
+ debug_warning("Fail to set route");
+
+ UNLOCK_SESSION();
+ return MM_ERROR_NONE;
+}
+#endif
+
+/* SUBSESSION */
+int MMSoundMgrSessionSetSubSession(subsession_t subsession, int subsession_opt)
+{
+ bool need_update = false;
+ bool need_cork = false;
+ static subsession_t prev_subsession = SUBSESSION_VOICE; /* Initialize subsession */
+ bool set_route_flag = true;
+ int sub_session_opt = 0;
+ LOCK_SESSION();
+
+ if (g_info.subsession == subsession) {
+ debug_warning ("[SESSION] already subsession is [%s]. skip this!!\n", __get_subsession_string(subsession));
+ } else {
+ MMSoundMgrPulseSetSubsession(subsession, subsession_opt);
+ g_info.subsession = subsession;
+ need_update = true;
+ }
+
+ /* FIXME : Need to check with private */
+ /* FIXME : Need to check with private */
+ /* FIXME : Need to check with private */
+ switch(subsession) {
+#ifdef TIZEN_MICRO
+ // FIXME: we got timing issue between music and player and sound_server
+ case SUBSESSION_VOICE:
+ case SUBSESSION_RINGTONE:
+ debug_msg("session(%s), subsession(%s). sound path will change to spk/mic",
+ __get_session_string(g_info.session), __get_subsession_string(subsession));
+ SET_PLAYBACK_ONLY_ACTIVE(MM_SOUND_DEVICE_OUT_SPEAKER);
+ SET_CAPTURE_ONLY_ACTIVE(MM_SOUND_DEVICE_IN_MIC);
+ need_update = true;
+ /* suspend ALSA devices when starting call */
+ if (subsession != SUBSESSION_RINGTONE) {
+ need_cork |= true;
+ }
+ dump_info();
+ break;
+#endif /* TIZEN_MICRO */
+ case SUBSESSION_VR_NORMAL:
+ case SUBSESSION_VR_DRIVE:
+ if(g_info.option != subsession_opt) {
+ g_info.option = subsession_opt;
+ need_update = true;
+ }
+ break;
+ default:
+ if (g_info.option != subsession_opt) {
+ g_info.option = MM_SUBSESSION_OPTION_NONE;
+ need_update = true;
+ }
+ break;
+ } if (g_info.subsession == SUBSESSION_VOICE) {
+ if (IS_ACTIVE(MM_SOUND_DEVICE_OUT_BT_SCO) && IS_ACTIVE(MM_SOUND_DEVICE_IN_BT_SCO)) {
+ /* Update BT info */
+ MMSoundMgrPulseUpdateBluetoothAGCodec();
+ }
+ }
+
+ if (g_info.subsession == SUBSESSION_VOICE) {
+ if (IS_ACTIVE(MM_SOUND_DEVICE_OUT_BT_SCO) && IS_ACTIVE(MM_SOUND_DEVICE_IN_BT_SCO)) {
+ /* Update BT info */
+ MMSoundMgrPulseUpdateBluetoothAGCodec();
+ }
+ }
+
+ if (need_update) {
+ debug_warning ("[SESSION] subsession=[%s], resource=[%d]\n", __get_subsession_string(g_info.subsession), g_info.option);
+ __set_route(true, need_cork);
+ }
+ UNLOCK_SESSION();
+
+ return MM_ERROR_NONE;
+}
+
+int MMSoundMgrSessionGetSubSession(subsession_t *subsession)
+{
+ if (subsession == NULL) {
+ debug_error ("Invalid input parameter\n");
+ return MM_ERROR_INVALID_ARGUMENT;
+ }
+
+ LOCK_SESSION();
+
+ *subsession = g_info.subsession;
+
+ UNLOCK_SESSION();
+
+ return MM_ERROR_NONE;
+}
+
+const char* MMSoundMgrSessionGetSubSessionString(subsession_t subsession)
+{
+ return __get_subsession_string(subsession);
+}
+
+
+char* MMSoundMgrSessionGetBtA2DPName ()
+{
+ return g_info.bt_info.name;
+}
+
+void MMSoundMgrSessionSetVoiceControlState (bool enable)
+{
+ int ret = MM_ERROR_NONE;
+ LOCK_SESSION();
+ g_info.is_voicecontrol = enable;
+ /* FIXME : Check whether need to set state to pulse, need to check with private */
+ /* MMSoundMgrPulseSetVoicecontrolState(enable); */
+
+ debug_warning("MMSoundMgrSessionSetVoiceControlState --------g_info.session = %s,g_info.subsession = %s ",
+ __get_session_string(g_info.session), __get_subsession_string(g_info.subsession));
+ if (IS_CALL_SESSION() && g_info.subsession == SUBSESSION_VOICE) {
+ debug_warning("already voice subsession in voice session");
+ return;
+ }
+
+ ret = __set_sound_path_for_voicecontrol();
+ UNLOCK_SESSION();
+ if (ret != MM_ERROR_NONE) {
+ debug_error ("__set_sound_path_for_voicecontrol() failed [%x]\n", ret);
+ return;
+ }
+
+}
+
+bool MMSoundMgrSessionGetVoiceControlState ()
+{
+ return g_info.is_voicecontrol;
+}
+
+#ifndef _TIZEN_PUBLIC_
+#ifndef TIZEN_MICRO
+/* -------------------------------- NOISE REDUCTION --------------------------------------------*/
+static bool __is_noise_reduction_on (void)
+{
+ int noise_reduction_on = 1;
+
+ if (vconf_get_bool(VCONF_KEY_NOISE_REDUCTION, &noise_reduction_on)) {
+ debug_warning("vconf_get_bool for VCONF_KEY_NOISE_REDUCTION failed\n");
+ }
+
+ return (noise_reduction_on == 1) ? true : false;
+}
+
+/* -------------------------------- EXTRA VOLUME --------------------------------------------*/
+static bool __is_extra_volume_on (void)
+{
+ int extra_volume_on = 1;
+
+ if (vconf_get_bool(VCONF_KEY_EXTRA_VOLUME, &extra_volume_on )) {
+ debug_warning("vconf_get_bool for VCONF_KEY_EXTRA_VOLUME failed\n");
+ }
+
+ return (extra_volume_on == 1) ? true : false;
+}
+#endif
+
+/* -------------------------------- UPSCALING --------------------------------------------*/
+static bool __is_upscaling_needed (void)
+{
+ int is_wbamr = 1;
+
+ if (vconf_get_bool(VCONF_KEY_WBAMR, &is_wbamr)) {
+ debug_warning("vconf_get_bool for VCONF_KEY_WBAMR failed\n");
+ }
+
+ return (is_wbamr == 0) ? true : false;
+}
+/* -------------------------------- BT NREC --------------------------------------------*/
+static bool __get_bt_nrec_status(void)
+{
+ debug_msg ("get bt nrec status.(%s)\n", g_info.bt_info.is_nrec==true ? "ON" : "OFF");
+ return g_info.bt_info.is_nrec;
+}
+
+#ifdef TIZEN_MICRO
+static int __get_ag_wb_status(void)
+{
+ debug_msg ("get ag wb status.(%s)\n", __get_bt_bandwidth_string(g_info.bt_info.ag_wb));
+ return g_info.bt_info.ag_wb;
+}
+
+static int __get_hf_wb_status(void)
+{
+ debug_msg ("get hf wb status.(%s)\n", __get_bt_bandwidth_string(g_info.bt_info.hf_wb));
+ return g_info.bt_info.hf_wb;
+}
+
+static int __get_hf_connection_state(void)
+{
+ debug_msg ("Set HF SCO connection state(%s)", __get_hfp_connection_state_string(g_info.bt_info.hfp_conn_state));
+ return g_info.bt_info.hfp_conn_state;
+}
+
+/* ------------------------------- RIGHT HAND ------------------------------------------*/
+static bool __is_right_hand_on (void)
+{
+ int is_right_hand = 0;
+ if (vconf_get_bool(VCONF_KEY_VR_LEFTHAND_ENABLED, &is_right_hand)) {
+ debug_warning("vconf_get_bool for %s failed\n", VCONF_KEY_VR_LEFTHAND_ENABLED);
+ }
+ debug_msg("is_right_hand : %d",is_right_hand);
+ return (is_right_hand == 0) ? true : false;
+}
+#endif /* TIZEN_MICRO */
+#endif /* _TIZEN_PUBLIC_ */
+#ifdef TIZEN_MICRO
+static void __media_pause_by_call (void)
+{
+ int asm_error = 0;
+ int asm_status = 0;
+ int handle = -1;
+
+ debug_msg ("[SESSION] Media pause requested by call dbus ...");
+ MMSOUND_ENTER_CRITICAL_SECTION( &_asm_mutex )
+
+ if (vconf_get_int(SOUND_STATUS_KEY, &asm_status)) {
+ debug_error(" vconf_set_int fail\n");
+ }
+
+ if ((asm_status & ~(ASM_STATUS_CALL|ASM_STATUS_NOTIFY|ASM_STATUS_ALARM|ASM_STATUS_EXCLUSIVE_RESOURCE))> 0) {
+ /* Do Pause for call dbus event */
+ debug_warning("Change state to pause by call dbus");
+
+ if (!ASM_register_sound_ex (-1, &handle, ASM_EVENT_CALL, ASM_STATE_NONE, NULL, NULL, ASM_RESOURCE_NONE, &asm_error, __asm_process_message)) {
+ debug_warning("Call event register failed with 0x%x", asm_error);
+ MMSOUND_LEAVE_CRITICAL_SECTION( &_asm_mutex )
+ return;
+ }
+
+ if (!ASM_set_sound_state_ex(handle, ASM_EVENT_CALL, ASM_STATE_PLAYING, ASM_RESOURCE_NONE, &asm_error, __asm_process_message)) {
+ debug_error("Call event set sound state to playing failed with 0x%x\n", asm_error);
+ }
+
+ if (!ASM_set_sound_state_ex(handle, ASM_EVENT_CALL, ASM_STATE_STOP, ASM_RESOURCE_NONE, &asm_error, __asm_process_message)) {
+ debug_error("Call event set sound state to stop failed with 0x%x", asm_error);
+ }
+
+ if (!ASM_unregister_sound_ex(handle, ASM_EVENT_CALL, &asm_error, __asm_process_message)) {
+ debug_error("Call event unregister failed with 0x%x\n", asm_error);
+ MMSOUND_LEAVE_CRITICAL_SECTION( &_asm_mutex )
+ return;
+ }
+
+ } else {
+ debug_msg("no need to pause others");
+ }
+
+ MMSOUND_LEAVE_CRITICAL_SECTION( &_asm_mutex )
+ /* End of change of session state */
+
+ return;
+}
+static void __call_status_changed(GDBusConnection *conn,
+ const gchar *sender_name,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *signal_name,
+ GVariant *parameters,
+ gpointer user_data)
+{
+ int value=0;
+ const GVariantType* value_type;
+
+ debug_msg ("sender : %s, object : %s, interface : %s, signal : %s",
+ sender_name, object_path, interface_name, signal_name);
+ if(g_variant_is_of_type(parameters, G_VARIANT_TYPE("(i)")))
+ {
+ g_variant_get(parameters, "(i)",&value);
+ debug_msg("singal[%s] = %X", signal_name, value);
+ if(value==MM_SOUND_CALL_STATUS_PAUSE)
+ {
+ __media_pause_by_call();
+ }
+ }
+ else
+ {
+ value_type = g_variant_get_type(parameters);
+ debug_warning("signal type is %s", value_type);
+ }
+
+}
+
+void _deinit_call_status_dbus(void)
+{
+ debug_fenter ();
+ g_dbus_connection_signal_unsubscribe(conn_callstatus, sig_id_callstatus);
+ g_object_unref(conn_callstatus);
+ debug_fleave ();
+}
+
+int _init_call_status_dbus(void)
+{
+ GError *err = NULL;
+ debug_fenter ();
+
+ g_type_init();
+
+ conn_callstatus = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
+ if (!conn_callstatus && err) {
+ debug_error ("g_bus_get_sync() error (%s) ", err->message);
+ g_error_free (err);
+ goto error;
+ }
+
+ sig_id_callstatus = g_dbus_connection_signal_subscribe(conn_callstatus,
+ NULL, DBUS_CALL_STATUS_INTERFACE, DBUS_CALL_STATUS_CHANGED_SIGNAL, DBUS_CALL_STATUS_PATH, NULL, 0,
+ __call_status_changed, NULL, NULL);
+ if (sig_id_callstatus < 0) {
+ debug_error ("g_dbus_connection_signal_subscribe() error (%d)", sig_id_callstatus);
+ goto sig_error;
+ }
+
+ debug_fleave ();
+ return 0;
+
+sig_error:
+ g_dbus_connection_signal_unsubscribe(conn_callstatus, sig_id_callstatus);
+ g_object_unref(conn_callstatus);
+
+error:
+ return -1;
+
+}
+#endif /* TIZEN_MICRO */
+int MMSoundMgrSessionInit(void)
+{
+ LOCK_SESSION();
+
+ debug_fenter();
+
+ memset (&g_info, 0, sizeof (SESSION_INFO_STRUCT));
+
+ /* FIXME: Initial status should be updated */
+ __set_initial_active_device ();
+
+ /* Register for headset unplug */
+ if (_asm_register_for_headset (&g_info.asm_handle) == false) {
+ debug_error ("Failed to register ASM for headset\n");
+ }
+#ifdef TIZEN_MICRO
+ if (_init_call_status_dbus() != 0) {
+ debug_error ("Registering call status signal handler failed\n");
+ }
+#endif
+
+ debug_fleave();
+
+ UNLOCK_SESSION();
+ return MM_ERROR_NONE;
+}
+
+int MMSoundMgrSessionFini(void)
+{
+ LOCK_SESSION();
+
+ debug_fenter();
+
+ /* Unregister for headset unplug */
+ _asm_unregister_for_headset (&g_info.asm_handle);
+
+ debug_fleave();
+
+ UNLOCK_SESSION();
+
+ return MM_ERROR_NONE;
+}
+