tizen 2.3 release tizen_2.3 submit/tizen_2.3/20150202.052533 tizen_2.3_release
authorjk7744.park <jk7744.park@samsung.com>
Sat, 31 Jan 2015 05:13:57 +0000 (14:13 +0900)
committerjk7744.park <jk7744.park@samsung.com>
Sat, 31 Jan 2015 05:13:57 +0000 (14:13 +0900)
13 files changed:
Makefile.am [changed mode: 0644->0755]
asoc.h [deleted file]
audio_hal_sys_file_access.efl [new file with mode: 0755]
configure.ac [changed mode: 0644->0755]
packaging/audio-hal-e3250.spec [changed mode: 0644->0755]
tizen-audio-device.c [changed mode: 0644->0755]
tizen-audio-internal.h [changed mode: 0644->0755]
tizen-audio-session.c [changed mode: 0644->0755]
tizen-audio-stream.c [changed mode: 0644->0755]
tizen-audio-ucm.c [new file with mode: 0755]
tizen-audio-util.c [changed mode: 0644->0755]
tizen-audio.c [changed mode: 0644->0755]
tizen-audio.h [changed mode: 0644->0755]

old mode 100644 (file)
new mode 100755 (executable)
index 7774281..af5fec7
@@ -4,10 +4,10 @@ libtizen_audio_la_SOURCES = tizen-audio.c \
                tizen-audio-session.c \
                tizen-audio-device.c \
                tizen-audio-stream.c \
+               tizen-audio-ucm.c \
                tizen-audio-util.c
 libtizen_audio_la_LDFLAGS = $(AM_LDFLAGS) -disable-static -avoid-version
 libtizen_audio_la_LIBADD = $(AM_LDADD) $(ASOUNDLIB_LIBS) $(VCONF_LIBS) $(DLOG_LIBS) $(INIPARSER_LIBS)
 libtizen_audio_la_CFLAGS = $(AM_CFLAGS) $(ASOUNDLIB_CFLAGS) $(VCONF_CFLAGS) $(DLOG_CFLAGS) $(INIPARSER_CFLAGS)
 libtizen_audio_la_CFLAGS += -DUSE_DLOG
 
-
diff --git a/asoc.h b/asoc.h
deleted file mode 100644 (file)
index 6302295..0000000
--- a/asoc.h
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * YMU831 ASoC codec driver
- *
- * Copyright (c) 2012 Yamaha Corporation
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.  In no event will the authors be held liable for any damages
- * arising from the use of this software.
- *
- * Permission is granted to anyone to use this software for any purpose,
- * including commercial applications, and to alter it and redistribute it
- * freely, subject to the following restrictions:
- *
- * 1. The origin of this software must not be misrepresented; you must not
- *    claim that you wrote the original software. If you use this software
- *    in a product, an acknowledgment in the product documentation would be
- *    appreciated but is not required.
- * 2. Altered source versions must be plainly marked as such, and must not be
- *    misrepresented as being the original software.
- * 3. This notice may not be removed or altered from any source distribution.
- */
-
-#ifndef ASOC_H
-#define ASOC_H
-
-#include <linux/ioctl.h>
-
-/*
- * dai: set_clkdiv
- */
-/* div_id */
-#define MC_ASOC_BCLK_MULT              5
-
-/* div for MC_ASOC_BCLK_MULT */
-#define MC_ASOC_LRCK_X64               (0)
-#define MC_ASOC_LRCK_X48               (1)
-#define MC_ASOC_LRCK_X32               (2)
-#define MC_ASOC_LRCK_X512              (3)
-#define MC_ASOC_LRCK_X256              (4)
-#define MC_ASOC_LRCK_X192              (5)
-#define MC_ASOC_LRCK_X128              (6)
-#define MC_ASOC_LRCK_X96               (7)
-#define MC_ASOC_LRCK_X24               (8)
-#define MC_ASOC_LRCK_X16               (9)
-
-/*
- * hwdep: ioctl
- */
-#define MC_ASOC_MAGIC                  'N'
-#define MC_ASOC_IOCTL_SET_CTRL         (1)
-#define MC_ASOC_IOCTL_READ_REG         (2)
-#define MC_ASOC_IOCTL_WRITE_REG                (3)
-#define MC_ASOC_IOCTL_NOTIFY_HOLD      (4)
-#define MC_ASOC_IOCTL_GET_DSP_DATA     (5)
-#define MC_ASOC_IOCTL_SET_DSP_DATA     (6)
-
-#define YMC_IOCTL_SET_CTRL \
-       _IOW(MC_ASOC_MAGIC, MC_ASOC_IOCTL_SET_CTRL, ymc_ctrl_args_t)
-
-#define YMC_IOCTL_READ_REG \
-       _IOWR(MC_ASOC_MAGIC, MC_ASOC_IOCTL_READ_REG, ymc_reg_args_t)
-
-#define YMC_IOCTL_WRITE_REG \
-       _IOWR(MC_ASOC_MAGIC, MC_ASOC_IOCTL_WRITE_REG, ymc_reg_args_t)
-
-#define YMC_IOCTL_NOTIFY_HOLD \
-       _IOWR(MC_ASOC_MAGIC, MC_ASOC_IOCTL_NOTIFY_HOLD, unsigned long)
-#define YMC_IOCTL_GET_DSP_DATA \
-       _IOWR(MC_ASOC_MAGIC, MC_ASOC_IOCTL_GET_DSP_DATA, \
-               ymc_dspdata_args_t)
-#define YMC_IOCTL_SET_DSP_DATA \
-       _IOWR(MC_ASOC_MAGIC, MC_ASOC_IOCTL_SET_DSP_DATA, \
-               ymc_dspdata_args_t)
-
-typedef struct _ymc_ctrl_args {
-       void            *param;
-       unsigned long   size;
-       unsigned long   option;
-} ymc_ctrl_args_t;
-
-typedef struct _ymc_reg_args {
-    unsigned char bRegType;
-    unsigned char bAddress;
-    unsigned char bData;
-} ymc_reg_args_t;
-
-typedef struct _ymc_dspdata_args {
-       unsigned char   *buf;
-       unsigned long   bufsize;
-       unsigned long   size;
-} ymc_dspdata_args_t;
-
-#define YMC_DSP_OUTPUT_BASE                        (0x00000000)
-#define YMC_DSP_OUTPUT_SP                          (0x00000001)
-#define YMC_DSP_OUTPUT_RC                          (0x00000002)
-#define YMC_DSP_OUTPUT_HP                          (0x00000003)
-#define YMC_DSP_OUTPUT_LO1                         (0x00000004)
-#define YMC_DSP_OUTPUT_LO2                         (0x00000005)
-#define YMC_DSP_OUTPUT_BT                          (0x00000006)
-        
-#define YMC_DSP_INPUT_BASE                         (0x00000010)
-#define YMC_DSP_INPUT_MAINMIC                  (0x00000020)
-#define YMC_DSP_INPUT_SUBMIC                   (0x00000030)
-#define YMC_DSP_INPUT_2MIC                         (0x00000040)
-#define YMC_DSP_INPUT_HEADSET_MIC              (0x00000050)
-#define YMC_DSP_INPUT_BLUETOOTH_MIC            (0x00000060)
-#define YMC_DSP_INPUT_LINEIN1                  (0x00000070)
-#define YMC_DSP_INPUT_LINEIN2                  (0x00000080)
-        
-#define YMC_DSP_VOICECALL_BASE_1MIC            (0x00000100)
-#define YMC_DSP_VOICECALL_BASE_2MIC            (0x00000200)
-#define YMC_DSP_VOICECALL_SP_1MIC              (0x00000300)
-#define YMC_DSP_VOICECALL_SP_2MIC              (0x00000400)
-#define YMC_DSP_VOICECALL_RC_1MIC              (0x00000500)
-#define YMC_DSP_VOICECALL_RC_2MIC              (0x00000600)
-#define YMC_DSP_VOICECALL_HP_1MIC              (0x00000700)
-#define YMC_DSP_VOICECALL_HP_2MIC              (0x00000800)
-#define YMC_DSP_VOICECALL_LO1_1MIC             (0x00000900)
-#define YMC_DSP_VOICECALL_LO1_2MIC             (0x00000A00)
-#define YMC_DSP_VOICECALL_LO2_1MIC             (0x00000B00)
-#define YMC_DSP_VOICECALL_LO2_2MIC             (0x00000C00)
-#define YMC_DSP_VOICECALL_HEADSET              (0x00000D00)
-#define YMC_DSP_VOICECALL_HEADBT               (0x00000E00)
-#define YMC_DSP_VOICECALL_BASE_COMMON       (0x00000F00)
-
-#define YMC_NOTITY_HOLD_OFF                        (0)
-#define YMC_NOTITY_HOLD_ON                         (1)
-
-#endif
diff --git a/audio_hal_sys_file_access.efl b/audio_hal_sys_file_access.efl
new file mode 100755 (executable)
index 0000000..7725046
--- /dev/null
@@ -0,0 +1 @@
+pulseaudio _ rwx--- ------
old mode 100644 (file)
new mode 100755 (executable)
index 7c2da00..6d82f53
@@ -1,6 +1,6 @@
 AC_PREREQ([2.67])
 
-AC_INIT([libaudiofilters-sec], [0.1])
+AC_INIT([audio-hal-e3250], [0.1])
 AM_INIT_AUTOMAKE([-Wall -Werror foreign])
 AC_CONFIG_HEADERS([config.h])
 
old mode 100644 (file)
new mode 100755 (executable)
index feca557..b005568
@@ -1,6 +1,6 @@
 Name:       audio-hal-e3250
 Summary:    TIZEN Audio HAL for Exynos3250
-Version:    0.2.13
+Version:    0.2.16
 Release:    0
 Group:      System/Libraries
 License:    Apache-2.0
@@ -10,6 +10,7 @@ BuildRequires: pkgconfig(alsa)
 BuildRequires: pkgconfig(vconf)
 BuildRequires: pkgconfig(iniparser)
 BuildRequires: pkgconfig(dlog)
+Provides: libtizen-audio.so
 
 %description
 TIZEN Audio HAL for Exynos3250
@@ -18,11 +19,9 @@ TIZEN Audio HAL for Exynos3250
 %setup -q -n %{name}-%{version}
 
 %build
-%if 0%{?sec_build_binary_debug_enable}
 export CFLAGS="$CFLAGS -DTIZEN_DEBUG_ENABLE"
-export CXXFLAGS="$CXXFLAGS DTIZEN_DEBUG_ENABLE"
+export CXXFLAGS="$CXXFLAGS ?DTIZEN_DEBUG_ENABLE"
 export FFLAGS="$FFLAGS -DTIZEN_DEBUG_ENABLE"
-%endif
 
 %autogen
 %configure
@@ -31,7 +30,8 @@ make %{?jobs:-j%jobs}
 
 %install
 rm -rf %{buildroot}
-
+mkdir -p %{buildroot}/etc/smack/accesses.d
+cp -arf audio_hal_sys_file_access.efl %{buildroot}/etc/smack/accesses.d
 mkdir -p %{buildroot}/usr/share/license
 cp LICENSE.APLv2 %{buildroot}/usr/share/license/%{name}
 
@@ -46,5 +46,6 @@ cp LICENSE.APLv2 %{buildroot}/usr/share/license/%{name}
 %files
 %manifest audio-hal-e3250.manifest
 %defattr(-,root,root,-)
+/etc/smack/accesses.d/audio_hal_sys_file_access.efl
 /usr/lib/libtizen-audio.so
 %{_datadir}/license/%{name}
old mode 100644 (file)
new mode 100755 (executable)
index 541285a..1f672c0
@@ -3,8 +3,6 @@
  *
  * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
  *
- * Contact: Hyunseok Lee <hs7388.lee@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
@@ -36,6 +34,11 @@ audio_return_t _audio_device_init (audio_mgr_t *am)
 
     am->device.active_in = AUDIO_DEVICE_IN_NONE;
     am->device.active_out = AUDIO_DEVICE_OUT_NONE;
+    am->device.route_flag = AUDIO_ROUTE_FLAG_NONE;
+    am->device.pcm_in = NULL;
+    am->device.pcm_out = NULL;
+    pthread_mutex_init(&am->device.pcm_lock, NULL);
+    am->device.pcm_count = 0;
 
     return AUDIO_RET_OK;
 }
@@ -47,25 +50,318 @@ audio_return_t _audio_device_deinit (audio_mgr_t *am)
     return AUDIO_RET_OK;
 }
 
+static void __load_n_open_device_with_params (audio_mgr_t *am, audio_device_info_t *device_info, int load_only)
+{
+    audio_device_param_info_t params[AUDIO_DEVICE_PARAM_MAX];
+    int dev_param_count = 0;
+
+    AUDIO_RETURN_IF_FAIL(am);
+    AUDIO_RETURN_IF_FAIL(device_info);
+    AUDIO_RETURN_IF_FAIL(am->cb_intf.load_device);
+    AUDIO_RETURN_IF_FAIL(am->cb_intf.open_device);
+
+    memset(&params[0], 0, sizeof(audio_device_param_info_t) * AUDIO_DEVICE_PARAM_MAX);
+
+    if (device_info->api == AUDIO_DEVICE_API_ALSA) {
+        device_info->name = malloc(strlen(device_info->alsa.card_name) + 6); /* 6 = "hw: ,idx */
+        sprintf(device_info->name, "hw:%s,%d", device_info->alsa.card_name, device_info->alsa.device_idx);
+        if (device_info->direction == AUDIO_DIRECTION_OUT) {
+            /* ALSA playback */
+            switch (device_info->alsa.device_idx) {
+                /* default device */
+                case 0:
+                case 3:
+                    device_info->is_default_device = 1;
+                    params[dev_param_count].param = AUDIO_DEVICE_PARAM_SUSPEND_TIMEOUT;
+                    params[dev_param_count++].u32_v = 1;
+                    params[dev_param_count].param = AUDIO_DEVICE_PARAM_TSCHED_BUF_SIZE;
+                    params[dev_param_count++].u32_v = 35280;
+                    AUDIO_LOG_INFO("HiFi Device");
+                    break;
+                /* HDMI device */
+                case 1:
+                    /* VOICE PCM. */
+                    break;
+                default:
+                    AUDIO_LOG_INFO("Unknown Playback Device");
+                    break;
+                }
+        } else if (device_info->direction == AUDIO_DIRECTION_IN) {
+            /* ALSA capture */
+            switch (device_info->alsa.device_idx) {
+                /* default device */
+                case 0:
+                    device_info->is_default_device = 1;
+                    /* use mmap */
+                    params[dev_param_count].param = AUDIO_DEVICE_PARAM_USE_MMAP;
+                    params[dev_param_count++].u32_v = 1;
+                    params[dev_param_count].param = AUDIO_DEVICE_PARAM_SAMPLERATE;
+                    params[dev_param_count++].u32_v = 48000;
+                    params[dev_param_count].param = AUDIO_DEVICE_PARAM_ALTERNATE_RATE;
+                    params[dev_param_count++].u32_v = 48000;
+                    break;
+                default:
+                    AUDIO_LOG_INFO("Unknown Capture Device");
+                    break;
+            }
+        }
+
+        AUDIO_LOG_INFO("open alsa %s device hw:%s,%d", (device_info->direction == AUDIO_DIRECTION_IN) ? "capture" : "playback",
+            device_info->alsa.card_name, device_info->alsa.device_idx);
+    }
+
+    if (load_only) {
+        am->cb_intf.load_device(am->platform_data, device_info, &params[0]);
+    } else {
+        am->cb_intf.open_device(am->platform_data, device_info, &params[0]);
+    }
+}
+
+static audio_return_t __set_route_ap_playback_capture (audio_mgr_t *am, uint32_t device_in, uint32_t device_out, uint32_t route_flag)
+{
+    audio_return_t audio_ret = AUDIO_RET_OK;
+    int dev_idx = 0;
+    const char *verb = NULL;
+    const char *devices[MAX_DEVICES] = {NULL,};
+    const char *modifiers[MAX_MODIFIERS] = {NULL,};
+
+    verb = AUDIO_USE_CASE_VERB_HIFI;
+
+    if (route_flag & AUDIO_ROUTE_FLAG_MUTE_POLICY) {
+        devices[dev_idx++] = AUDIO_USE_CASE_DEV_HEADSET;
+    } else if (route_flag & AUDIO_ROUTE_FLAG_DUAL_OUT) {
+        devices[dev_idx++] = AUDIO_USE_CASE_DEV_SPEAKER;
+        devices[dev_idx++] = AUDIO_USE_CASE_DEV_HEADSET;
+        if (device_out == AUDIO_DEVICE_OUT_MIRRORING) {
+            AUDIO_LOG_INFO("Skip WFD enable during DUAL path");
+        }
+    } else {
+        switch (device_out) {
+            case AUDIO_DEVICE_OUT_SPEAKER:
+                 devices[dev_idx++] = AUDIO_USE_CASE_DEV_SPEAKER;
+                 break;
+            case AUDIO_DEVICE_OUT_RECEIVER:
+                devices[dev_idx++] = AUDIO_USE_CASE_DEV_HANDSET;
+                break;
+            case AUDIO_DEVICE_OUT_WIRED_ACCESSORY:
+                devices[dev_idx++] = AUDIO_USE_CASE_DEV_HEADSET;
+                break;
+            /* even BT SCO is opened by call app, we cannot use BT SCO on HiFi verb */
+            case AUDIO_DEVICE_OUT_BT_SCO:
+                devices[dev_idx++] = AUDIO_USE_CASE_DEV_SPEAKER;
+                break;
+            default:
+                break;
+        }
+    }
+
+    if (am->session.is_radio_on == 0 || am->session.is_recording == 1) {
+        switch (device_in) {
+            case AUDIO_DEVICE_IN_MIC:
+                devices[dev_idx++] = AUDIO_USE_CASE_DEV_MAIN_MIC;
+                break;
+            case AUDIO_DEVICE_IN_WIRED_ACCESSORY:
+                devices[dev_idx++] = AUDIO_USE_CASE_DEV_HEADSET_MIC;
+                break;
+            /* even BT SCO is opened by call app, we cannot use BT SCO on HiFi verb */
+            case AUDIO_DEVICE_IN_BT_SCO:
+                devices[dev_idx++] = AUDIO_USE_CASE_DEV_MAIN_MIC;
+                break;
+            default:
+                break;
+        }
+    }
+
+    /* TODO. Handle voice recognition when seperate devices are available */
+    audio_ret = _audio_ucm_update_use_case(am, verb, devices, modifiers);
+    if (AUDIO_IS_ERROR(audio_ret)) {
+        return audio_ret;
+    }
+    return AUDIO_RET_OK;
+}
+
+audio_return_t _set_route_voicecall (audio_mgr_t *am, uint32_t device_in, uint32_t device_out, uint32_t route_flag)
+{
+    audio_return_t audio_ret = AUDIO_RET_OK;
+    int dev_idx = 0;
+    const char *verb = NULL;
+    const char *devices[MAX_DEVICES] = {NULL,};
+
+    verb = AUDIO_USE_CASE_VERB_VOICECALL;
+
+    switch (device_out) {
+        case AUDIO_DEVICE_OUT_SPEAKER:
+            /* FIXME: WB handling is needed */
+            devices[dev_idx++] = AUDIO_USE_CASE_DEV_SPEAKER;
+            break;
+        case AUDIO_DEVICE_OUT_RECEIVER:
+            /* FIXME: WB handling is needed */
+            devices[dev_idx++] = AUDIO_USE_CASE_DEV_HANDSET;
+            break;
+        case AUDIO_DEVICE_OUT_WIRED_ACCESSORY:
+            devices[dev_idx++] = AUDIO_USE_CASE_DEV_HEADSET;
+            break;
+        case AUDIO_DEVICE_OUT_BT_SCO:
+            devices[dev_idx++] = AUDIO_USE_CASE_DEV_BT_HEADSET;
+            break;
+        default:
+            break;
+    }
+
+    switch (device_in) {
+        case AUDIO_DEVICE_IN_MIC:
+            devices[dev_idx++] = AUDIO_USE_CASE_DEV_MAIN_MIC;
+            break;
+        case AUDIO_DEVICE_IN_WIRED_ACCESSORY:
+            devices[dev_idx++] = AUDIO_USE_CASE_DEV_HEADSET_MIC;
+            break;
+        default:
+            break;
+    }
+
+    /* FIXME. Get network info and configure rate in pcm device */
+    audio_ret = _audio_ucm_update_use_case(am, verb, devices, NULL);
+
+    return audio_ret;
+}
+
+static audio_return_t __set_route_voip (audio_mgr_t *am, uint32_t device_in, uint32_t device_out, uint32_t route_flag)
+{
+    int dev_idx = 0;
+    const char *verb = NULL;
+    const char *devices[MAX_DEVICES] = {NULL,};
+
+    verb = AUDIO_USE_CASE_VERB_HIFI; /* Modify later to use VIRTUALAUDIO to enable echo cancellation */
+
+    switch (device_out) {
+        case AUDIO_DEVICE_OUT_SPEAKER:
+            devices[dev_idx++] = AUDIO_USE_CASE_DEV_SPEAKER;
+            break;
+        case AUDIO_DEVICE_OUT_RECEIVER:
+            devices[dev_idx++] = AUDIO_USE_CASE_DEV_HANDSET;
+            break;
+        case AUDIO_DEVICE_OUT_WIRED_ACCESSORY:
+            devices[dev_idx++] = AUDIO_USE_CASE_DEV_HEADSET;
+            break;
+        case AUDIO_DEVICE_OUT_BT_SCO:
+            devices[dev_idx++] = AUDIO_USE_CASE_DEV_BT_HEADSET;
+            break;
+        default:
+            break;
+    }
+
+    switch (device_in) {
+        case AUDIO_DEVICE_IN_MIC:
+            devices[dev_idx++] = AUDIO_USE_CASE_DEV_MAIN_MIC;
+            break;
+        case AUDIO_DEVICE_IN_WIRED_ACCESSORY:
+            devices[dev_idx++] = AUDIO_USE_CASE_DEV_HEADSET_MIC;
+            break;
+        case AUDIO_DEVICE_IN_BT_SCO:
+            devices[dev_idx++] = AUDIO_USE_CASE_DEV_BT_MIC;
+            break;
+        default:
+            break;
+    }
+
+    return _audio_ucm_update_use_case(am, verb, devices, NULL);
+}
+
+audio_return_t _reset_route (audio_mgr_t *am, int need_inactive)
+{
+    const char *devices[MAX_DEVICES] = {NULL,};
+    const char *modifiers[MAX_MODIFIERS] = {NULL,};
+
+    if(need_inactive) {
+        _audio_ucm_update_use_case(am, AUDIO_USE_CASE_VERB_INACTIVE, devices, modifiers);
+    }
+    _audio_ucm_update_use_case(am, AUDIO_USE_CASE_VERB_HIFI, devices, modifiers);
+    __set_route_ap_playback_capture(am, am->device.active_in, am->device.active_out, 0);
+
+    return AUDIO_RET_OK;
+}
+
 audio_return_t audio_set_route (void *userdata, uint32_t session, uint32_t subsession, uint32_t device_in, uint32_t device_out, uint32_t route_flag)
 {
     audio_return_t audio_ret = AUDIO_RET_OK;
     audio_mgr_t *am = (audio_mgr_t *)userdata;
-    bool update_volume = false;
+    int i, dev_info_count = 0;
+    audio_device_info_t device_info_list[AUDIO_DEVICE_INFO_LIST_MAX];
+
+    am->device.active_in = device_in;
+    am->device.active_out = device_out;
+    am->device.route_flag = route_flag;
 
     AUDIO_RETURN_VAL_IF_FAIL(am, AUDIO_ERR_PARAMETER);
 
     AUDIO_LOG_INFO("session:%d,%d in:%d out:%d flag:0x%x", session, subsession, device_in, device_out, route_flag);
 
-    if (am->device.active_out != device_out)
-        update_volume = true;
+       if ((session == AUDIO_SESSION_VOICECALL) && (subsession == AUDIO_SUBSESSION_VOICE)) {
+        audio_ret = _set_route_voicecall(am, device_in, device_out, route_flag);
+        if (AUDIO_IS_ERROR(audio_ret)) {
+            AUDIO_LOG_WARN("set voicecall route return 0x%x", audio_ret);
+        }
+    } else if ((session == AUDIO_SESSION_VOIP) && (subsession == AUDIO_SUBSESSION_VOICE)) {
+        audio_ret = __set_route_voip(am, device_in, device_out, route_flag);
+        if (AUDIO_IS_ERROR(audio_ret)) {
+            AUDIO_LOG_WARN("set voip route return 0x%x", audio_ret);
+        }
+    } else {
+        audio_ret = __set_route_ap_playback_capture(am, device_in, device_out, route_flag);
+        if (AUDIO_IS_ERROR(audio_ret)) {
+            AUDIO_LOG_WARN("set playback route return 0x%x", audio_ret);
+        }
+    }
 
-    am->device.active_in = device_in;
-    am->device.active_out = device_out;
+    if (!AUDIO_IS_ERROR(audio_ret)) {
+        memset((void *)&device_info_list[0], 0, sizeof(audio_device_info_t) * AUDIO_DEVICE_INFO_LIST_MAX);
+        /* fill device params & open device */
+        dev_info_count = _audio_ucm_fill_device_info_list(am, &device_info_list[0], NULL);
+        for (i = 0; i < dev_info_count; i++) {
+            __load_n_open_device_with_params(am, &device_info_list[i], 0);
+            }
+        }
+    return AUDIO_RET_OK;
+}
+
+audio_return_t audio_alsa_pcm_open (void *userdata, void **pcm_handle, char *device_name, uint32_t direction, int mode)
+{
+    audio_return_t audio_ret = AUDIO_RET_OK;
+    audio_mgr_t *am = (audio_mgr_t *)userdata;
+    int err;
+
+    AUDIO_RETURN_VAL_IF_FAIL(am, AUDIO_ERR_PARAMETER);
 
-    /* Volume level should be updated if device changed */
-    if (update_volume)
-        audio_ret = _audio_update_volume_level(am);
+//    pthread_mutex_lock(&am->device.pcm_lock);
+   if ((err = snd_pcm_open((snd_pcm_t **)pcm_handle, device_name, (direction == AUDIO_DIRECTION_OUT) ? SND_PCM_STREAM_PLAYBACK : SND_PCM_STREAM_CAPTURE, mode)) < 0) {
+        AUDIO_LOG_ERROR("Error opening PCM device %s: %s", device_name, snd_strerror(err));
+        pthread_mutex_unlock(&am->device.pcm_lock);
+        return AUDIO_ERR_RESOURCE;
+    }
+    am->device.pcm_count++;
+    AUDIO_LOG_INFO("PCM handle 0x%x(%s,%s) opened(count:%d)", *pcm_handle, device_name, (direction == AUDIO_DIRECTION_OUT) ? "playback" : "capture", am->device.pcm_count);
+//    pthread_mutex_unlock(&am->device.pcm_lock);
 
     return audio_ret;
 }
+
+audio_return_t audio_alsa_pcm_close (void *userdata, void *pcm_handle)
+{
+    audio_return_t audio_ret = AUDIO_RET_OK;
+    audio_mgr_t *am = (audio_mgr_t *)userdata;
+    int err;
+
+    AUDIO_LOG_INFO("Try to close PCM handle 0x%x", pcm_handle);
+//    pthread_mutex_lock(&am->device.pcm_lock);
+    if ((err = snd_pcm_close(pcm_handle)) < 0) {
+        AUDIO_LOG_ERROR("Error closing PCM handle : %s", snd_strerror(err));
+        pthread_mutex_unlock(&am->device.pcm_lock);
+        return AUDIO_ERR_RESOURCE;
+    }
+
+    am->device.pcm_count--;
+    AUDIO_LOG_INFO("PCM handle close success (count:%d)", am->device.pcm_count);
+//    pthread_mutex_unlock(&am->device.pcm_lock);
+
+    return audio_ret;
+}
\ No newline at end of file
old mode 100644 (file)
new mode 100755 (executable)
index cdedf57..e32e601
@@ -6,8 +6,6 @@
  *
  * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
  *
- * Contact: Hyunseok Lee <hs7388.lee@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
  */
 
 #include <dlog.h>
-#include <alsa/asoundlib.h>
-
+#include <time.h>
+#include <sys/types.h>
+#include <asoundlib.h>
+#include <pthread.h>
+#include <use-case.h>
 #include "tizen-audio.h"
 
 /* Debug */
 
-#define AUDIO_DEBUG
+//#define AUDIO_DEBUG
+#define PROPERTY_VALUE_MAX 92
+#define BUF_SIZE 1024
 #define AUDIO_DUMP_STR_LEN              256
+#define AUDIO_DEVICE_INFO_LIST_MAX      16
 #ifdef USE_DLOG
 #ifdef DLOG_TAG
 #undef DLOG_TAG
@@ -49,7 +53,7 @@
 #define AUDIO_LOG_VERBOSE(...)          fprintf(stdout, __VA_ARGS__)
 #endif
 
-#define AUDIO_RETURN_IF_FAIL(expr, val) do { \
+#define AUDIO_RETURN_IF_FAIL(expr) do { \
     if (!expr) { \
         AUDIO_LOG_ERROR("%s failed", #expr); \
         return; \
     } \
 } while (0)
 
+/* Verbs */
+#define AUDIO_USE_CASE_VERB_INACTIVE                "Inactive"
+#define AUDIO_USE_CASE_VERB_HIFI                    "HiFi"
+#define AUDIO_USE_CASE_VERB_VOICECALL               "VoiceCall"
+#define AUDIO_USE_CASE_VERB_LOOPBACK                "Loopback"
+#define AUDIO_USE_CASE_VERB_FMRADIO                 "FM_Radio"
+
+/* Devices : Normal  */
+#define AUDIO_USE_CASE_DEV_SPEAKER                  "Speaker"
+#define AUDIO_USE_CASE_DEV_HANDSET                  "Earpiece"
+#define AUDIO_USE_CASE_DEV_HEADSET                  "Headphones"
+#define AUDIO_USE_CASE_DEV_HEADSET_3POLE            "Headphones"
+#define AUDIO_USE_CASE_DEV_BT_HEADSET               "Bluetooth"
+#define AUDIO_USE_CASE_DEV_LINEOUT                  "Line"
+#define AUDIO_USE_CASE_DEV_FMRADIO                  "FM"
+
+#define AUDIO_USE_CASE_DEV_MAIN_MIC                 "MainMic"
+#define AUDIO_USE_CASE_DEV_SUB_MIC                  "SubMic"
+#define AUDIO_USE_CASE_DEV_HEADSET_MIC              "HeadsetMic"
+#define AUDIO_USE_CASE_DEV_BT_MIC                   "BT Mic"
+
+/* Modifiers */
+#define AUDIO_USE_CASE_MODIFIER_VOICE                    "VoiceSearch"
+#define AUDIO_USE_CASE_MODIFIER_CAMCORDING               "Camcording"
+#define AUDIO_USE_CASE_MODIFIER_RINGTONE                 "Ringtone"
+
+
+#define streq !strcmp
+#define strneq strcmp
+
+#define ALSA_DEFAULT_CARD       "ymu831"
+
+#define MAX_DEVICES             5
+#define MAX_MODIFIERS           5
+
+/* type definitions */
+typedef signed char int8_t;
+
+/* pcm */
+typedef struct {
+    snd_pcm_format_t format;
+    uint32_t rate;
+    uint8_t channels;
+} audio_pcm_sample_spec_t;
+
 /* Session */
 typedef struct audio_session_mgr {
     audio_session_t session;
     audio_subsession_t subsession;
+    uint32_t is_recording;
+    uint32_t is_radio_on;
+    uint32_t is_call_session;
 } audio_session_mgr_t;
 
-
 /* Device */
 
 typedef struct audio_device_mgr {
     audio_device_in_t active_in;
     audio_device_out_t active_out;
+    uint32_t route_flag;
+    snd_pcm_t *pcm_in;
+    snd_pcm_t *pcm_out;
+    pthread_mutex_t pcm_lock;
+    uint32_t pcm_count;
 } audio_device_mgr_t;
 
 
@@ -102,42 +158,78 @@ enum {
 };
 
 typedef struct audio_stream_mgr {
-    uint32_t volume_level[AUDIO_VOLUME_TYPE_MAX];
+    uint32_t volume_level[AUDIO_VOLUME_DEVICE_MAX][AUDIO_VOLUME_TYPE_MAX];
     audio_volume_gain_table_t *volume_gain_table;
 } audio_stream_mgr_t;
 
+typedef struct audio_ucm_mgr {
+    snd_use_case_mgr_t* uc_mgr;
+} audio_ucm_mgr_t;
+
 typedef struct audio_mixer_mgr {
-    snd_ctl_t* mixer;
+    snd_mixer_t *mixer;
     pthread_mutex_t mutex;
+    struct {
+        snd_ctl_elem_value_t *value;
+        snd_ctl_elem_id_t *id;
+        snd_ctl_elem_info_t *info;
+    } control;
 } audio_mixer_mgr_t;
 
 /* Overall */
 
 typedef struct audio_mgr {
+    void *platform_data;
+    audio_cb_interface_t cb_intf;
+    audio_session_mgr_t session;
     audio_device_mgr_t device;
     audio_stream_mgr_t stream;
-    audio_session_mgr_t session;
+    audio_ucm_mgr_t ucm;
     audio_mixer_mgr_t mixer;
 } audio_mgr_t;
 
+typedef struct {
+    unsigned short      is_open; /* if is_open is true, open device; else close device.*/
+    unsigned short      is_headphone;
+    unsigned int        is_downlink_mute;
+    unsigned int        is_uplink_mute;
+} device_ctrl_t;
+
+typedef struct samplerate_ctrl {
+    unsigned int samplerate; /* change samplerate.*/
+} set_samplerate_t;
+
 audio_return_t _audio_stream_init (audio_mgr_t *am);
 audio_return_t _audio_stream_deinit (audio_mgr_t *am);
-audio_return_t _audio_update_volume_level (audio_mgr_t *am);
 
 audio_return_t _audio_device_init (audio_mgr_t *am);
 audio_return_t _audio_device_deinit (audio_mgr_t * am);
+audio_return_t _set_route_voicecall (audio_mgr_t *am, uint32_t device_in, uint32_t device_out, uint32_t route_flag);
+audio_return_t _reset_route (audio_mgr_t *am, int need_inactive);
 
 audio_return_t _audio_session_init (audio_mgr_t *am);
 audio_return_t _audio_session_deinit (audio_mgr_t *am);
 
-#define MIXER_SPK_VOLUME            "Speaker Volume"
-#define CDSP_VOLUME                 "CDSP Volume"
 #define MIXER_MIC1_SWITCH           "Mic1 Switch"
 #define MIXER_MIC2_SWITCH           "Mic2 Switch"
 
+audio_return_t _audio_ucm_init (audio_mgr_t *am);
+audio_return_t _audio_ucm_deinit (audio_mgr_t *am);
+void _audio_ucm_get_device_name (audio_mgr_t *am, const char *use_case, audio_direction_t direction, const char **value);
+#define _audio_ucm_update_use_case _audio_ucm_set_use_case
+audio_return_t _audio_ucm_set_use_case (audio_mgr_t *am, const char *verb, const char *devices[], const char *modifiers[]);
+int _audio_ucm_fill_device_info_list (audio_mgr_t *am, audio_device_info_t *device_info_list, const char *verb);
+audio_return_t _audio_ucm_get_verb (audio_mgr_t *am, const char **value);
+audio_return_t _audio_ucm_reset_use_case (audio_mgr_t *am);
+
 audio_return_t _audio_util_init (audio_mgr_t *am);
 audio_return_t _audio_util_deinit (audio_mgr_t *am);
+audio_return_t _audio_mixer_control_set_param(audio_mgr_t *am, const char* ctl_name, snd_ctl_elem_value_t* value, int size);
 audio_return_t _audio_mixer_control_set_value(audio_mgr_t *am, const char *ctl_name, int val);
+audio_return_t _audio_mixer_control_set_value_string(audio_mgr_t *am, const char* ctl_name, const char* value);
 audio_return_t _audio_mixer_control_get_value(audio_mgr_t *am, const char *ctl_name, int *val);
+audio_return_t _audio_mixer_control_get_element(audio_mgr_t *am, const char *ctl_name, snd_hctl_elem_t **elem);
 
+audio_return_t _audio_pcm_set_sw_params(snd_pcm_t *pcm, snd_pcm_uframes_t avail_min, uint8_t period_event, uint32_t start_threshold, uint32_t rate);
+audio_return_t _audio_pcm_set_hw_params(snd_pcm_t *pcm, audio_pcm_sample_spec_t *sample_spec, uint8_t *use_mmap, snd_pcm_uframes_t *period_size, snd_pcm_uframes_t *buffer_size);
 #endif
old mode 100644 (file)
new mode 100755 (executable)
index 9dd37de..d323daa
@@ -3,8 +3,6 @@
  *
  * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
  *
- * Contact: Hyunseok Lee <hs7388.lee@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
 
 #include "tizen-audio-internal.h"
 
+static const char *__get_session_string_by_idx (uint32_t session_idx)
+{
+    switch (session_idx) {
+    case AUDIO_SESSION_MEDIA:                       return "media";
+    case AUDIO_SESSION_VOICECALL:                   return "voicecall";
+    case AUDIO_SESSION_VIDEOCALL:                   return "videocall";
+    case AUDIO_SESSION_VOIP:                        return "voip";
+    case AUDIO_SESSION_FMRADIO:                     return "fmradio";
+    case AUDIO_SESSION_CAMCORDER:                   return "camcorder";
+    case AUDIO_SESSION_NOTIFICATION:                return "notification";
+    case AUDIO_SESSION_ALARM:                       return "alarm";
+    case AUDIO_SESSION_EMERGENCY:                   return "emergency";
+    case AUDIO_SESSION_VOICE_RECOGNITION:           return "voice_recognition";
+    default:                                        return "invalid";
+    }
+}
+
+static const char *__get_subsession_string_by_idx (uint32_t subsession_idx)
+{
+    switch (subsession_idx) {
+    case AUDIO_SUBSESSION_NONE:                     return "none";
+    case AUDIO_SUBSESSION_VOICE:                    return "voice";
+    case AUDIO_SUBSESSION_RINGTONE:                 return "ringtone";
+    case AUDIO_SUBSESSION_MEDIA:                    return "media";
+    case AUDIO_SUBSESSION_INIT:                     return "init";
+    case AUDIO_SUBSESSION_VR_NORMAL:                return "vr_normal";
+    case AUDIO_SUBSESSION_VR_DRIVE:                 return "vr_drive";
+    case AUDIO_SUBSESSION_STEREO_REC:               return "stereo_rec";
+    case AUDIO_SUBSESSION_MONO_REC:                 return "mono_rec";
+    default:                                        return "invalid";
+    }
+}
+
+static const char * __get_sessin_cmd_string (uint32_t cmd)
+{
+    switch (cmd) {
+    case AUDIO_SESSION_CMD_START:                   return "start";
+    case AUDIO_SESSION_CMD_SUBSESSION:              return "subsession";
+    case AUDIO_SESSION_CMD_END:                     return "end";
+    default:                                        return "invalid";
+    }
+}
+
 audio_return_t _audio_session_init (audio_mgr_t *am)
 {
     AUDIO_RETURN_VAL_IF_FAIL(am, AUDIO_ERR_PARAMETER);
 
     am->session.session = AUDIO_SESSION_MEDIA;
     am->session.subsession = AUDIO_SUBSESSION_NONE;
+    am->session.is_recording = 0;
+    am->session.is_radio_on = 0;
+    am->session.is_call_session = 0;
 
     return AUDIO_RET_OK;
 }
@@ -46,28 +90,73 @@ audio_return_t _audio_session_deinit (audio_mgr_t *am)
     return AUDIO_RET_OK;
 }
 
-audio_return_t audio_set_session (void *userdata, uint32_t session, uint32_t subsession)
+audio_return_t audio_set_session (void *userdata, uint32_t session, uint32_t subsession, uint32_t cmd)
 {
     audio_return_t audio_ret = AUDIO_RET_OK;
     audio_mgr_t *am = (audio_mgr_t *)userdata;
+    uint32_t prev_subsession = am->session.subsession;
 
     AUDIO_RETURN_VAL_IF_FAIL(am, AUDIO_ERR_PARAMETER);
 
-    AUDIO_LOG_INFO("session:%d,%d", session, subsession);
+    AUDIO_LOG_INFO("session %s:%s(%s)->%s(%s)", __get_sessin_cmd_string(cmd),
+        __get_session_string_by_idx(am->session.session), __get_subsession_string_by_idx(am->session.subsession),
+        __get_session_string_by_idx(session), __get_subsession_string_by_idx(subsession));
 
-    if (session == AUDIO_SESSION_VOICE_RECOGNITION && am->session.session != AUDIO_SESSION_VOICE_RECOGNITION) {
-        uint32_t volume_level = 0;
+    if (cmd == AUDIO_SESSION_CMD_START) {
+        if (am->session.is_call_session) {
+            AUDIO_LOG_ERROR("call active its not possible to have any other session start now");
+            return audio_ret;
+        }
+    am->session.session = session;
+    am->session.subsession = subsession;
 
-        /* voice recognition start */
-        audio_get_volume_level(userdata, AUDIO_VOLUME_TYPE_SVOICE, &volume_level);
-        audio_ret = audio_set_volume_level(userdata, NULL, AUDIO_VOLUME_TYPE_SVOICE, volume_level);
-    } else if  (session != AUDIO_SESSION_VOICE_RECOGNITION && am->session.session == AUDIO_SESSION_VOICE_RECOGNITION) {
-        /* voice recognition end */
+        if ((session == AUDIO_SESSION_VIDEOCALL) ||
+            (session == AUDIO_SESSION_VOICECALL) ||
+            (session == AUDIO_SESSION_VOIP)) {
+            AUDIO_LOG_INFO("set call session");
+            am->session.is_call_session = 1;
+        }
+
+    } else if (cmd == AUDIO_SESSION_CMD_END) {
+
+        if ((session == AUDIO_SESSION_VIDEOCALL) ||
+            (session == AUDIO_SESSION_VOICECALL) ||
+            (session == AUDIO_SESSION_VOIP)) {
+            AUDIO_LOG_INFO("unset call session");
+            am->session.is_call_session = 0;
+        }
+
+        if (am->session.is_call_session) {
+            AUDIO_LOG_ERROR("call active its not possible to have any other session end now");
+            return audio_ret;
+        }
+
+        if (session == AUDIO_SESSION_MEDIA && (prev_subsession == AUDIO_SUBSESSION_STEREO_REC || AUDIO_SUBSESSION_MONO_REC)) {
+            am->session.is_recording = 0;
     }
-
-    am->session.session = session;
+        am->session.session = AUDIO_SESSION_MEDIA;
+         am->session.subsession = AUDIO_SUBSESSION_NONE;
+    } else if (cmd == AUDIO_SESSION_CMD_SUBSESSION) {
+
+        if (am->session.is_call_session) {
+            if ((subsession != AUDIO_SUBSESSION_VOICE) &&
+                (subsession != AUDIO_SUBSESSION_MEDIA) &&
+                (subsession != AUDIO_SUBSESSION_RINGTONE)) {
+                AUDIO_LOG_ERROR("call active we can only have one of AUDIO_SUBSESSION_VOICE AUDIO_SUBSESSION_MEDIA AUDIO_SUBSESSION_RINGTONE as a sub-session");
+                return audio_ret;
+            }
+        }
     am->session.subsession = subsession;
+        if (prev_subsession != subsession && subsession == AUDIO_SUBSESSION_VOICE) {
+            am->session.is_recording = 0;
+        }
+
+        if (subsession == AUDIO_SUBSESSION_STEREO_REC || subsession == AUDIO_SUBSESSION_MONO_REC) {
+            am->session.is_recording = 1;
+        } else if (am->session.is_recording == 1 && subsession == AUDIO_SUBSESSION_INIT) {
+            am->session.is_recording = 0;
+        }
+    }
 
     return audio_ret;
 }
-
old mode 100644 (file)
new mode 100755 (executable)
index 73d8441..eb344da
@@ -3,8 +3,6 @@
  *
  * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
  *
- * Contact: Hyunseok Lee <hs7388.lee@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
@@ -32,7 +30,6 @@
 
 #include "tizen-audio-internal.h"
 
-#define VOLUME_INI_CSC_PATH         "/opt/system/csc-default/usr/tuning/mmfw_audio_volume.ini"
 #define VOLUME_INI_DEFAULT_PATH     "/usr/etc/mmfw_audio_volume.ini"
 #define VOLUME_INI_TEMP_PATH        "/opt/system/mmfw_audio_volume.ini"
 #define VOLUME_VALUE_MAX            (1.0f)
 
 enum {
     STREAM_DEVICE_SPEAKER,
+    STREAM_DEVICE_HEADSET,
     STREAM_DEVICE_BLUETOOTH,
+    STREAM_DEVICE_HDMI,
+    STREAM_DEVICE_DOCK,
     STREAM_DEVICE_MAX,
 };
 
@@ -52,14 +52,26 @@ static const char *g_volume_vconf[AUDIO_VOLUME_TYPE_MAX] = {
     "file/private/sound/volume/media",          /* AUDIO_VOLUME_TYPE_MEDIA */
     "file/private/sound/volume/call",           /* AUDIO_VOLUME_TYPE_CALL */
     "file/private/sound/volume/voip",           /* AUDIO_VOLUME_TYPE_VOIP */
-    "file/private/sound/volume/svoice",         /* AUDIO_VOLUME_TYPE_SVOICE */
+    "file/private/sound/volume/voice",          /* AUDIO_VOLUME_TYPE_VOICE */
     "file/private/sound/volume/fixed",          /* AUDIO_VOLUME_TYPE_FIXED */
-    "file/private/sound/volume/java"            /* AUDIO_VOLUME_TYPE_EXT_JAVA */
 };
 
 static inline uint8_t __get_volume_dev_index(audio_mgr_t *am, uint32_t volume_type)
 {
-    return 0;
+
+    switch (am->device.active_out) {
+        case AUDIO_DEVICE_OUT_SPEAKER:          return AUDIO_VOLUME_DEVICE_SPEAKER;
+        case AUDIO_DEVICE_OUT_RECEIVER:         return AUDIO_VOLUME_DEVICE_RECEIVER;
+        case AUDIO_DEVICE_OUT_WIRED_ACCESSORY:  return AUDIO_VOLUME_DEVICE_EARJACK;
+        case AUDIO_DEVICE_OUT_BT_SCO:           return AUDIO_VOLUME_DEVICE_BT_SCO;
+        case AUDIO_DEVICE_OUT_BT_A2DP:          return AUDIO_VOLUME_DEVICE_BT_A2DP;
+        case AUDIO_DEVICE_OUT_DOCK:             return AUDIO_VOLUME_DEVICE_DOCK;
+        case AUDIO_DEVICE_OUT_HDMI:             return AUDIO_VOLUME_DEVICE_HDMI;
+        case AUDIO_DEVICE_OUT_MIRRORING:        return AUDIO_VOLUME_DEVICE_MIRRORING;
+        case AUDIO_DEVICE_OUT_USB_AUDIO:        return AUDIO_VOLUME_DEVICE_USB;
+        case AUDIO_DEVICE_OUT_MULTIMEDIA_DOCK:  return AUDIO_VOLUME_DEVICE_MULTIMEDIA_DOCK;
+        default:                                return AUDIO_VOLUME_DEVICE_SPEAKER;
+    }
 }
 
 static const uint8_t __get_stream_dev_index (uint32_t device_out)
@@ -67,14 +79,14 @@ static const uint8_t __get_stream_dev_index (uint32_t device_out)
     switch (device_out) {
     case AUDIO_DEVICE_OUT_SPEAKER:          return STREAM_DEVICE_SPEAKER;
     case AUDIO_DEVICE_OUT_RECEIVER:         return STREAM_DEVICE_SPEAKER;
-    case AUDIO_DEVICE_OUT_WIRED_ACCESSORY:  return STREAM_DEVICE_SPEAKER;
+    case AUDIO_DEVICE_OUT_WIRED_ACCESSORY:  return STREAM_DEVICE_HEADSET;
     case AUDIO_DEVICE_OUT_BT_SCO:           return STREAM_DEVICE_BLUETOOTH;
     case AUDIO_DEVICE_OUT_BT_A2DP:          return STREAM_DEVICE_BLUETOOTH;
-    case AUDIO_DEVICE_OUT_DOCK:             return STREAM_DEVICE_SPEAKER;
-    case AUDIO_DEVICE_OUT_HDMI:             return STREAM_DEVICE_SPEAKER;
+    case AUDIO_DEVICE_OUT_DOCK:             return STREAM_DEVICE_DOCK;
+    case AUDIO_DEVICE_OUT_HDMI:             return STREAM_DEVICE_HDMI;
     case AUDIO_DEVICE_OUT_MIRRORING:        return STREAM_DEVICE_SPEAKER;
     case AUDIO_DEVICE_OUT_USB_AUDIO:        return STREAM_DEVICE_SPEAKER;
-    case AUDIO_DEVICE_OUT_MULTIMEDIA_DOCK:  return STREAM_DEVICE_SPEAKER;
+    case AUDIO_DEVICE_OUT_MULTIMEDIA_DOCK:  return STREAM_DEVICE_DOCK;
     default:
         AUDIO_LOG_DEBUG("invalid device_out:%d", device_out);
         break;
@@ -87,17 +99,10 @@ static const char *__get_device_string_by_idx (uint32_t dev_idx)
 {
     switch (dev_idx) {
     case STREAM_DEVICE_SPEAKER:             return "speaker";
+    case STREAM_DEVICE_HEADSET:             return "headset";
     case STREAM_DEVICE_BLUETOOTH:           return "btheadset";
-    default:                                return "invalid";
-    }
-}
-
-static const char *__get_direction_string_by_idx (uint32_t dir_idx)
-{
-    switch (dir_idx) {
-    case AUDIO_DIRECTION_NONE:              return "none";
-    case AUDIO_DIRECTION_IN:                return "in";
-    case AUDIO_DIRECTION_OUT:               return "out";
+    case STREAM_DEVICE_HDMI:                return "hdmi";
+    case STREAM_DEVICE_DOCK:                return "dock";
     default:                                return "invalid";
     }
 }
@@ -112,9 +117,8 @@ static const char *__get_volume_type_string_by_idx (uint32_t vol_type_idx)
     case AUDIO_VOLUME_TYPE_MEDIA:           return "media";
     case AUDIO_VOLUME_TYPE_CALL:            return "call";
     case AUDIO_VOLUME_TYPE_VOIP:            return "voip";
-    case AUDIO_VOLUME_TYPE_SVOICE:          return "svoice";
+    case AUDIO_VOLUME_TYPE_VOICE:           return "voice";
     case AUDIO_VOLUME_TYPE_FIXED:           return "fixed";
-    case AUDIO_VOLUME_TYPE_EXT_JAVA:        return "java";
     default:                                return "invalid";
     }
 }
@@ -140,20 +144,22 @@ static const char *__get_gain_type_string_by_idx (uint32_t gain_type_idx)
 static void __dump_info(char *dump, audio_info_t *info)
 {
     int len;
+    char name[64] = { '\0', };
 
     if (info->device.api == AUDIO_DEVICE_API_ALSA) {
-        len = sprintf(dump, "device:alsa(%d.%d)", info->device.alsa.card_idx, info->device.alsa.device_idx);
+        len = snprintf(dump, AUDIO_DUMP_STR_LEN, "device:alsa(%d.%d)", info->device.alsa.card_idx, info->device.alsa.device_idx);
     } else if (info->device.api == AUDIO_DEVICE_API_ALSA) {
-        len = sprintf(dump, "device:bluez(%s,nrec:%d)", info->device.bluez.protocol, info->device.bluez.nrec);
+        len = snprintf(dump, AUDIO_DUMP_STR_LEN, "device:bluez(%s,nrec:%d)", info->device.bluez.protocol, info->device.bluez.nrec);
     } else {
-        len = sprintf(dump, "device:unknown");
+        len = snprintf(dump, AUDIO_DUMP_STR_LEN, "device:unknown");
     }
 
     if (len > 0)
         dump += len;
 
-    len = sprintf(dump, "stream:%s(%dhz,%dch,vol:%s,gain:%s)",
-        info->stream.name ? info->stream.name : "null", info->stream.samplerate, info->stream.channels,
+    strncpy(name, info->stream.name ? info->stream.name : "null", sizeof(name)-1);
+    len = snprintf(dump, AUDIO_DUMP_STR_LEN, "stream:%s(%dhz,%dch,vol:%s,gain:%s)",
+        name, info->stream.samplerate, info->stream.channels,
         __get_volume_type_string_by_idx(info->stream.volume_type), __get_gain_type_string_by_idx(info->stream.gain_type));
 
     if (len > 0)
@@ -162,7 +168,6 @@ static void __dump_info(char *dump, audio_info_t *info)
     *dump = '\0';
 }
 
-#ifdef AUDIO_DEBUG
 static void __dump_tb (audio_mgr_t *am)
 {
     audio_volume_gain_table_t *volume_gain_table = am->stream.volume_gain_table;
@@ -183,12 +188,12 @@ static void __dump_tb (audio_mgr_t *am)
     char dump_str[AUDIO_DUMP_STR_LEN], *dump_str_ptr;
 
     /* Dump volume table */
-    AUDIO_LOG_DEBUG("<<<<< volume table >>>>>");
+    AUDIO_LOG_INFO("<<<<< volume table >>>>>");
 
     for (dev_idx = 0; dev_idx < STREAM_DEVICE_MAX; dev_idx++) {
         const char *dev_str = __get_device_string_by_idx(dev_idx);
 
-        AUDIO_LOG_DEBUG("<< %s >>", dev_str);
+        AUDIO_LOG_INFO("<< %s >>", dev_str);
 
         for (vol_type_idx = 0; vol_type_idx < AUDIO_VOLUME_TYPE_MAX; vol_type_idx++) {
             const char *vol_type_str = __get_volume_type_string_by_idx(vol_type_idx);
@@ -202,7 +207,7 @@ static void __dump_tb (audio_mgr_t *am)
                 snprintf(dump_str_ptr, 6, "%01.2f ", volume_gain_table->volume[vol_type_idx][vol_level_idx]);
                 dump_str_ptr += strlen(dump_str_ptr);
             }
-            AUDIO_LOG_DEBUG("%s", dump_str);
+            AUDIO_LOG_INFO("%s", dump_str);
         }
         volume_gain_table++;
     }
@@ -210,7 +215,7 @@ static void __dump_tb (audio_mgr_t *am)
     volume_gain_table = am->stream.volume_gain_table;
 
     /* Dump gain table */
-    AUDIO_LOG_DEBUG("<<<<< gain table >>>>>");
+    AUDIO_LOG_INFO("<<<<< gain table >>>>>");
 
     dump_str_ptr = &dump_str[0];
     memset(dump_str, 0x00, sizeof(char) * sizeof(dump_str));
@@ -222,7 +227,7 @@ static void __dump_tb (audio_mgr_t *am)
         snprintf(dump_str_ptr, 7, "%5s ", gain_type_str[gain_type_idx]);
         dump_str_ptr += strlen(dump_str_ptr);
     }
-    AUDIO_LOG_DEBUG("%s", dump_str);
+    AUDIO_LOG_INFO("%s", dump_str);
 
     for (dev_idx = 0; dev_idx < STREAM_DEVICE_MAX; dev_idx++) {
         const char *dev_str = __get_device_string_by_idx(dev_idx);
@@ -237,24 +242,21 @@ static void __dump_tb (audio_mgr_t *am)
             snprintf(dump_str_ptr, 7, "%01.3f ", volume_gain_table->gain[gain_type_idx]);
             dump_str_ptr += strlen(dump_str_ptr);
         }
-        AUDIO_LOG_DEBUG("%s", dump_str);
+        AUDIO_LOG_INFO("%s", dump_str);
 
         volume_gain_table++;
     }
 }
-#endif
 
 static audio_return_t __load_volume_gain_table_from_ini (audio_mgr_t *am)
 {
     dictionary * dict = NULL;
     uint32_t dev_idx, vol_type_idx, vol_level_idx, gain_type_idx;
     audio_volume_gain_table_t *volume_gain_table = am->stream.volume_gain_table;
+    int size = 0;
 
     dict = iniparser_load(VOLUME_INI_TEMP_PATH);
     if (!dict) {
-        AUDIO_LOG_DEBUG("Use csc & default volume&gain ini file");
-        dict = iniparser_load(VOLUME_INI_CSC_PATH);
-        if (!dict) {
             AUDIO_LOG_DEBUG("Use default volume&gain ini file");
             dict = iniparser_load(VOLUME_INI_DEFAULT_PATH);
             if (!dict) {
@@ -262,7 +264,7 @@ static audio_return_t __load_volume_gain_table_from_ini (audio_mgr_t *am)
                 return AUDIO_ERR_UNDEFINED;
             }
        }
-   }
+
     for (dev_idx = 0; dev_idx < STREAM_DEVICE_MAX; dev_idx++) {
         const char delimiter[] = ", ";
         char *key, *list_str, *token, *ptr = NULL;
@@ -273,23 +275,26 @@ static audio_return_t __load_volume_gain_table_from_ini (audio_mgr_t *am)
             const char *vol_type_str = __get_volume_type_string_by_idx(vol_type_idx);
 
             volume_gain_table->volume_level_max[vol_type_idx] = 0;
-
-            key = malloc(strlen(dev_str) + strlen(vol_type_str) + 2);
+            size = strlen(dev_str) + strlen(vol_type_str) + 2;
+            key = malloc(size);
             if (key) {
-                sprintf(key, "%s:%s", dev_str, vol_type_str);
+                snprintf(key, size, "%s:%s", dev_str, vol_type_str);
                 list_str = iniparser_getstr(dict, key);
                 if (list_str) {
                     token = strtok_r(list_str, delimiter, &ptr);
                     while (token) {
                         /* convert dB volume to linear volume */
-                        volume_gain_table->volume[vol_type_idx][volume_gain_table->volume_level_max[vol_type_idx]++] = pow(10.0, (atof(token) - 100) / 20.0);
+                        double vol_value = 0.0f;
+                        if(strncmp(token, "0", strlen(token)))
+                            vol_value = pow(10.0, (atof(token) - 100) / 20.0);
+                        volume_gain_table->volume[vol_type_idx][volume_gain_table->volume_level_max[vol_type_idx]++] = vol_value;
                         token = strtok_r(NULL, delimiter, &ptr);
                     }
                 } else {
-                    audio_volume_gain_table_t *volume_gain_table_spk = &am->stream.volume_gain_table[STREAM_DEVICE_SPEAKER];
-
-                    volume_gain_table->volume_level_max[vol_type_idx] = volume_gain_table_spk->volume_level_max[vol_type_idx];
-                    memcpy((double *)&volume_gain_table->volume[vol_type_idx][0], (double *)&volume_gain_table_spk->volume[vol_type_idx][0], AUDIO_VOLUME_LEVEL_MAX * sizeof(double));
+                     volume_gain_table->volume_level_max[vol_type_idx] = 1;
+                    for (vol_level_idx = 0; vol_level_idx < AUDIO_VOLUME_LEVEL_MAX; vol_level_idx++) {
+                        volume_gain_table->volume[vol_type_idx][vol_level_idx] = VOLUME_VALUE_MAX;
+                    }
                 }
                 free(key);
             }
@@ -300,9 +305,10 @@ static audio_return_t __load_volume_gain_table_from_ini (audio_mgr_t *am)
         for (gain_type_idx = AUDIO_GAIN_TYPE_DEFAULT + 1; gain_type_idx < AUDIO_GAIN_TYPE_MAX; gain_type_idx++) {
             const char *gain_type_str = __get_gain_type_string_by_idx(gain_type_idx);
 
-            key = malloc(strlen(dev_str) + strlen("gain") + strlen(gain_type_str) + 3);
+            size = strlen(dev_str) + strlen("gain") + strlen(gain_type_str) + 3;
+            key = malloc(size);
             if (key) {
-                sprintf(key, "%s:gain_%s", dev_str, gain_type_str);
+                snprintf(key, size, "%s:gain_%s", dev_str, gain_type_str);
                 token = iniparser_getstr(dict, key);
                 if (token) {
                     volume_gain_table->gain[gain_type_idx] = atof(token);
@@ -318,28 +324,48 @@ static audio_return_t __load_volume_gain_table_from_ini (audio_mgr_t *am)
     }
 
     iniparser_freedict(dict);
-#ifdef AUDIO_DEBUG
+
     __dump_tb(am);
-#endif
 
     return AUDIO_RET_OK;
 }
 
 audio_return_t _audio_stream_init (audio_mgr_t *am)
 {
-    int i, value;
+    int i, j;
+    char *str = NULL;
+    audio_return_t audio_ret = AUDIO_RET_OK;
+    int init_value[AUDIO_VOLUME_TYPE_MAX] = { 9, 11, 7, 11, 7, 4, 4, 7, 4, 0 };
 
     AUDIO_RETURN_VAL_IF_FAIL(am, AUDIO_ERR_PARAMETER);
 
     for (i = 0; i < AUDIO_VOLUME_TYPE_MAX; i++) {
+        for (j = 0; j < AUDIO_VOLUME_DEVICE_MAX; j++) {
+            am->stream.volume_level[j][i] = init_value[i];
+        }
+    }
+
+    for (i = 0; i < AUDIO_VOLUME_TYPE_MAX; i++) {
         /* Get volume value string from VCONF */
-        if (vconf_get_int(g_volume_vconf[i], &value) != 0) {
-            AUDIO_LOG_ERROR("vconf_get_int(%s) failed", g_volume_vconf[i]);
+        if((str = vconf_get_str(g_volume_vconf[i])) == NULL) {
+            AUDIO_LOG_ERROR("vconf_get_str(%s) failed", g_volume_vconf[i]);
             continue;
         }
-        AUDIO_LOG_INFO("read vconf. %s = %d", g_volume_vconf[i], value);
 
-        am->stream.volume_level[i] = value;
+        AUDIO_LOG_INFO("read vconf. %s = %s", g_volume_vconf[i], str);
+
+        /* Unified type uses only fisrt index of volume devices */
+
+        for (j = 0; j < AUDIO_VOLUME_DEVICE_MAX; j++) {
+            char val[3];
+            memset(val, 0, sizeof(val));
+            val[0] = str[j*2];
+            val[1] = str[j*2+1];
+            am->stream.volume_level[j][i] = atoi(val);
+        }
+
+       if (str)
+           free(str);
     }
 
     if (!(am->stream.volume_gain_table = malloc(STREAM_DEVICE_MAX * sizeof(audio_volume_gain_table_t)))) {
@@ -347,7 +373,13 @@ audio_return_t _audio_stream_init (audio_mgr_t *am)
         return AUDIO_ERR_RESOURCE;
     }
 
-    return __load_volume_gain_table_from_ini(am);
+    audio_ret = __load_volume_gain_table_from_ini(am);
+    if(audio_ret != AUDIO_RET_OK) {
+        AUDIO_LOG_ERROR("gain table load error");
+        return AUDIO_ERR_UNDEFINED;
+    }
+
+    return audio_ret;
 }
 
 audio_return_t _audio_stream_deinit (audio_mgr_t *am)
@@ -374,11 +406,6 @@ audio_return_t audio_get_volume_level_max (void *userdata, uint32_t volume_type,
     volume_gain_table = am->stream.volume_gain_table + __get_stream_dev_index(am->device.active_out);
     *level = volume_gain_table->volume_level_max[volume_type];
 
-    /* temporary fix for SVoice */
-    if (volume_type == AUDIO_VOLUME_TYPE_VOIP) {
-        *level = 7;
-    }
-
     AUDIO_LOG_DEBUG("get_volume_level_max:%s=>%d", __get_volume_type_string_by_idx(volume_type), *level);
 
     return AUDIO_RET_OK;
@@ -390,34 +417,30 @@ audio_return_t audio_get_volume_level (void *userdata, uint32_t volume_type, uin
 
     AUDIO_RETURN_VAL_IF_FAIL(am, AUDIO_ERR_PARAMETER);
 
-    *level = am->stream.volume_level[volume_type];
+    *level = am->stream.volume_level[__get_volume_dev_index(am, volume_type)][volume_type];
 
     return AUDIO_RET_OK;
 }
 
 audio_return_t audio_get_volume_value (void *userdata, audio_info_t *info, uint32_t volume_type, uint32_t level, double *value)
 {
-    audio_mgr_t *am = (audio_mgr_t *)userdata;
-    audio_volume_gain_table_t *volume_gain_table;
-    char dump_str[AUDIO_DUMP_STR_LEN];
-
-    AUDIO_RETURN_VAL_IF_FAIL(am, AUDIO_ERR_PARAMETER);
-    AUDIO_RETURN_VAL_IF_FAIL(am->stream.volume_gain_table, AUDIO_ERR_PARAMETER);
-
-    /* Get basic volume by device & type & level */
-    volume_gain_table = am->stream.volume_gain_table + __get_stream_dev_index(am->device.active_out);
-    if (volume_gain_table->volume_level_max[volume_type] < level)
-        *value = VOLUME_VALUE_MAX;
-    else
-        *value = volume_gain_table->volume[volume_type][level];
     if (info) {
-        __dump_info(&dump_str[0], info);
+        audio_mgr_t *am = (audio_mgr_t *)userdata;
+        audio_volume_gain_table_t *volume_gain_table;
+        char dump_str[AUDIO_DUMP_STR_LEN];
 
+        AUDIO_RETURN_VAL_IF_FAIL(am, AUDIO_ERR_PARAMETER);
+        AUDIO_RETURN_VAL_IF_FAIL(am->stream.volume_gain_table, AUDIO_ERR_PARAMETER);
+        __dump_info(&dump_str[0], info);
+        /* Get basic volume by device & type & level */
+        volume_gain_table = am->stream.volume_gain_table + __get_stream_dev_index(am->device.active_out);
+        if (volume_gain_table->volume_level_max[volume_type] < level)
+            *value = VOLUME_VALUE_MAX;
+        else
+            *value = volume_gain_table->volume[volume_type][level];
         *value *= volume_gain_table->gain[info->stream.gain_type];
 
         AUDIO_LOG_DEBUG("get_volume_value:%d(%s)=>%f %s", level, __get_volume_type_string_by_idx(volume_type), *value, &dump_str[0]);
-    } else {
-        AUDIO_LOG_DEBUG("get_volume_value:%d(%s)=>%f", level, __get_volume_type_string_by_idx(volume_type), *value);
     }
 
     return AUDIO_RET_OK;
@@ -431,56 +454,26 @@ audio_return_t audio_set_volume_level (void *userdata, audio_info_t *info, uint3
     AUDIO_RETURN_VAL_IF_FAIL(am, AUDIO_ERR_PARAMETER);
 
     if (info == NULL) {
-        double volume_linear = 1.0f, volume_db = 0.0f;
-        int volume_value = 0;
 
         /* Update volume level */
-        am->stream.volume_level[volume_type] = level;
-
-        if ((volume_type == AUDIO_VOLUME_TYPE_CALL && am->session.session == AUDIO_SESSION_VOICECALL)
-            || (volume_type == AUDIO_VOLUME_TYPE_VOIP && am->session.session == AUDIO_SESSION_VOIP)
-            || (volume_type == AUDIO_VOLUME_TYPE_SVOICE && am->session.session == AUDIO_SESSION_VOICE_RECOGNITION)) {
-#if 0   /* NOT NEED set for alsa lib */
-            audio_get_volume_value(userdata, info, volume_type, level, &volume_linear);
-            volume_db = 20.0 * log10(volume_linear);
-
-            /* 0x00~0x2E : min(-96dB) step(0dB)
-               0x2F~0x43 : min(-36dB) step(1dB)
-               0x44~0x57 : min(-15.5dB) step(0.5dB)
-               0x58~0x6F : min(-5.75dB) step(0.25dB) */
-            if (volume_db >= -5.75)
-                volume_value = 0x58 + (volume_db + 5.75) / 0.25;
-            else if (volume_db >= -15.5)
-                volume_value = 0x44 + (volume_db + 15.5) / 0.5;
-            else if (volume_db >= -36)
-                volume_value = 0x2F + (volume_db + 36) / 1;
-
-            audio_ret = _audio_mixer_control_set_value(am, MIXER_SPK_VOLUME, volume_value); */
-#endif
-            AUDIO_LOG_INFO("set_volume_level:%d(%s)", level, __get_volume_type_string_by_idx(volume_type));
-
-            /* cdsp volume range 0~5 */
-            audio_ret = _audio_mixer_control_set_value(am, CDSP_VOLUME, level-1);
-        } else {
-#ifdef AUDIO_DEBUG
-            AUDIO_LOG_DEBUG("skip set_volume_level:%d(%s)", level, __get_volume_type_string_by_idx(volume_type));
-#endif
-        }
+        am->stream.volume_level[__get_volume_dev_index(am, volume_type)][volume_type] = level;
+        AUDIO_LOG_INFO("set_volume_level:session(%d), %d(%s)", am->session.session, level, __get_volume_type_string_by_idx(volume_type));
     }
 
     return audio_ret;
 }
 
-audio_return_t _audio_update_volume_level (audio_mgr_t *am)
+audio_return_t audio_get_gain_value (void *userdata, audio_info_t *info, uint32_t volume_type, double *value)
 {
-    int i;
+    audio_mgr_t *am = (audio_mgr_t *)userdata;
+    audio_volume_gain_table_t *volume_gain_table;
 
-    for (i = 0; i < AUDIO_VOLUME_TYPE_MAX; i++) {
-        /* Update vconf */
-        if (vconf_set_int(g_volume_vconf[i], am->stream.volume_level[i]) != 0) {
-            AUDIO_LOG_ERROR("vconf_set_int(%s) failed", g_volume_vconf[i]);
-            continue;
-        }
+    AUDIO_RETURN_VAL_IF_FAIL(am, AUDIO_ERR_PARAMETER);
+    AUDIO_RETURN_VAL_IF_FAIL(am->stream.volume_gain_table, AUDIO_ERR_PARAMETER);
+
+    if (info != NULL) {
+        volume_gain_table = am->stream.volume_gain_table + __get_stream_dev_index(am->device.active_out);
+        *value = volume_gain_table->gain[info->stream.gain_type];
     }
 
     return AUDIO_RET_OK;
@@ -494,7 +487,6 @@ audio_return_t audio_get_mute (void *userdata, audio_info_t *info, uint32_t volu
     AUDIO_RETURN_VAL_IF_FAIL(am, AUDIO_ERR_PARAMETER);
 
     if (info == NULL) {
-        const char *ctl_name = NULL;
 
         if (volume_type == AUDIO_VOLUME_TYPE_CALL) {
             int mute_mic1 = 0, mute_mic2 = 0;
@@ -505,10 +497,10 @@ audio_return_t audio_get_mute (void *userdata, audio_info_t *info, uint32_t volu
             audio_ret = _audio_mixer_control_get_value(am, MIXER_MIC2_SWITCH, &mute_mic2);
             *mute = !(mute_mic1 & mute_mic2);
 
-            AUDIO_LOG_INFO("get_mute:%s,%s=>%d(ret:0x%x)", __get_volume_type_string_by_idx(volume_type), __get_direction_string_by_idx(direction), *mute, audio_ret);
+            AUDIO_LOG_INFO("get_mute:%s,%s=>%d(ret:0x%x)", __get_volume_type_string_by_idx(volume_type), direction, *mute, audio_ret);
         } else {
 #ifdef AUDIO_DEBUG
-            AUDIO_LOG_DEBUG("skip get_mute:%s,%s=>%d(ret:0x%x)", __get_volume_type_string_by_idx(volume_type), __get_direction_string_by_idx(direction), *mute, audio_ret);
+            AUDIO_LOG_DEBUG("skip get_mute:%s,%s=>%d(ret:0x%x)", __get_volume_type_string_by_idx(volume_type), direction, *mute, audio_ret);
 #endif
         }
     }
@@ -524,11 +516,8 @@ audio_return_t audio_set_mute (void *userdata, audio_info_t *info, uint32_t volu
     AUDIO_RETURN_VAL_IF_FAIL(am, AUDIO_ERR_PARAMETER);
 
     if (info == NULL) {
-        double volume_linear = 1.0f, volume_db = 0.0f;
-        int volume_value = 0;
-
         if (volume_type == AUDIO_VOLUME_TYPE_CALL) {
-            AUDIO_LOG_INFO("set_mute:%d(%s,%s)", mute, __get_volume_type_string_by_idx(volume_type), __get_direction_string_by_idx(direction));
+            AUDIO_LOG_INFO("set_mute:%d(%s,%s)", mute, __get_volume_type_string_by_idx(volume_type), direction);
 
             audio_ret = _audio_mixer_control_set_value(am, MIXER_MIC1_SWITCH, (int)!mute);
             if (AUDIO_IS_ERROR(audio_ret))
diff --git a/tizen-audio-ucm.c b/tizen-audio-ucm.c
new file mode 100755 (executable)
index 0000000..0d4f437
--- /dev/null
@@ -0,0 +1,447 @@
+/*
+ * audio-hal
+ *
+ * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * 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.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef ALSA_UCM_DEBUG_TIME
+#include <sys/time.h>
+#include <time.h>
+#endif
+
+#include "tizen-audio-internal.h"
+
+#ifdef ALSA_UCM_DEBUG_TIME
+#define SND_USE_CASE_SET __set_use_case_with_time
+#else
+#define SND_USE_CASE_SET snd_use_case_set
+#endif
+
+audio_return_t _audio_ucm_init (audio_mgr_t *am)
+{
+    snd_use_case_mgr_open(&am->ucm.uc_mgr, ALSA_DEFAULT_CARD);
+
+    if (!am->ucm.uc_mgr) {
+        AUDIO_LOG_ERROR("uc_mgr open failed");
+        return AUDIO_ERR_RESOURCE;
+    }
+    return AUDIO_RET_OK;
+}
+
+audio_return_t _audio_ucm_deinit (audio_mgr_t *am)
+{
+    if (am->ucm.uc_mgr != NULL) {
+        snd_use_case_mgr_close(am->ucm.uc_mgr);
+        am->ucm.uc_mgr = NULL;
+    }
+
+    return AUDIO_RET_OK;
+}
+
+void _audio_ucm_get_device_name (audio_mgr_t *am, const char *use_case, audio_direction_t direction, const char **value)
+{
+    char identifier[70] = {0};
+
+    if (direction == AUDIO_DIRECTION_IN) {
+        sprintf(identifier, "CapturePCM//%s", use_case);
+    } else {
+        sprintf(identifier, "PlaybackPCM//%s", use_case);
+    }
+    snd_use_case_get(am->ucm.uc_mgr, identifier, value);
+}
+
+static inline void __add_ucm_device_info (audio_mgr_t *am, const char *use_case, audio_direction_t direction, audio_device_info_t *device_info_list, int *device_info_count)
+{
+    audio_device_info_t *device_info;
+    const char *device_name = NULL;
+    char *needle = NULL;
+
+    _audio_ucm_get_device_name(am, use_case, direction, &device_name);
+    if (device_name) {
+        device_info = &device_info_list[(*device_info_count)++];
+
+        memset(device_info, 0x00, sizeof(audio_device_info_t));
+        device_info->api = AUDIO_DEVICE_API_ALSA;
+        device_info->direction = direction;
+        needle = strstr(&device_name[3], ",");
+        if (needle) {
+            device_info->alsa.device_idx = *(needle+1) - '0';
+            device_info->alsa.card_name = strndup(&device_name[3], needle - (device_name+3));
+            device_info->alsa.card_idx = snd_card_get_index(device_info->alsa.card_name);
+            AUDIO_LOG_DEBUG("Card name: %s", device_info->alsa.card_name);
+        }
+
+        free((void *)device_name);
+    }
+}
+
+int _audio_ucm_fill_device_info_list (audio_mgr_t *am, audio_device_info_t *device_info_list, const char *verb)
+{
+    int device_info_count = 0;
+    const char *curr_verb = NULL;
+
+    if (!verb) {
+        snd_use_case_get(am->ucm.uc_mgr, "_verb", &curr_verb);
+        verb = curr_verb;
+    }
+
+    /* prepare destination */
+    /*If the devices are VOICECALL LOOPBACK or FMRADIO then pulseaudio need not get the device notification*/
+    if (verb) {
+        if (strncmp(verb, AUDIO_USE_CASE_VERB_VOICECALL, strlen(AUDIO_USE_CASE_VERB_VOICECALL)) &&
+            strncmp(verb, AUDIO_USE_CASE_VERB_LOOPBACK, strlen(AUDIO_USE_CASE_VERB_LOOPBACK))) {
+            __add_ucm_device_info(am, verb, AUDIO_DIRECTION_IN, device_info_list, &device_info_count);
+            if(strncmp(verb, AUDIO_USE_CASE_VERB_FMRADIO, strlen(AUDIO_USE_CASE_VERB_FMRADIO))) {
+                __add_ucm_device_info(am, verb, AUDIO_DIRECTION_OUT, device_info_list, &device_info_count);
+            }
+        }
+
+        if (curr_verb)
+            free((void *)curr_verb);
+
+    }
+
+    return device_info_count;
+}
+
+static void __dump_use_case(const char *verb, const char *devices[], int dev_count, const char *modifiers[], int mod_count, char *dump)
+{
+    int i, len;
+
+    len = sprintf(dump, "Verb [ %s ] Devices [ ", verb ? verb : AUDIO_USE_CASE_VERB_INACTIVE);
+    if (len > 0)
+        dump += len;
+
+    for (i = 0; i < dev_count; i++) {
+        if (i != dev_count - 1) {
+            len = sprintf(dump, "%s, ", devices[i]);
+        } else {
+            len = sprintf(dump, "%s", devices[i]);
+        }
+        if (len > 0)
+            dump += len;
+    }
+
+    len = sprintf(dump, " ] Modifier [ ");
+    if (len > 0)
+        dump += len;
+
+    for (i = 0; i < mod_count; i++) {
+        if (i != mod_count - 1) {
+            len = sprintf(dump, "%s, ", modifiers[i]);
+        } else {
+            len = sprintf(dump, "%s", modifiers[i]);
+        }
+        if (len > 0)
+            dump += len;
+    }
+
+    len = sprintf(dump, " ]");
+    if (len > 0)
+        dump += len;
+
+    *dump = '\0';
+}
+
+#ifdef ALSA_UCM_DEBUG_TIME
+static inline int __set_use_case_with_time(snd_use_case_mgr_t *uc_mgr, const char *identifier, const char *value)
+{
+    int ret = 0;
+    struct timeval t_start, t_stop;
+    unsigned long long t_diff = 0;
+
+    gettimeofday(&t_start, NULL);
+    ret = snd_use_case_set(uc_mgr, identifier, value);
+    gettimeofday(&t_stop, NULL);
+    if (t_start.tv_sec < t_stop.tv_sec)
+        t_diff = (t_stop.tv_sec - t_start.tv_sec) * 1000000;
+    t_diff += (t_stop.tv_usec - t_start.tv_usec);
+    AUDIO_LOG_DEBUG("identifier %s value %s takes %lluusec", identifier, value, t_diff);
+
+    return ret;
+}
+#endif
+
+/* UCM sequence
+    1) If verb is null or verb is not changed
+    1-1) If device is changed
+         (If there is request for same device, it will be ignored)
+         -> Set "Inactive" verb, disable modifiers & devices, set current verb again, enable devices & modifiers
+            (playback/capture device will be enabled again if there is no request for playback/capture device)
+    1-2) If device is not changed
+     1-2-1) If modifier is changed
+            (If there is request for same modifier, it will be ignored)
+            -> Disable modifiers, enable modifiers
+   2) If verb is changed
+      -> Reset, set new verb, enable devices & modifiers
+ */
+audio_return_t _audio_ucm_set_use_case (audio_mgr_t *am, const char *verb, const char *devices[], const char *modifiers[])
+{
+    audio_return_t audio_ret = AUDIO_RET_OK;
+    int is_verb_changed = 0, is_dev_changed = 0, is_mod_changed = 0;
+    const char *old_verb = NULL, **old_dev_list = NULL, **old_mod_list = NULL;
+    int old_dev_count = 0, dev_count = 0;
+    int old_mod_count = 0, mod_count = 0;
+    const char **dis_dev_list = NULL, **ena_dev_list = NULL;
+    const char **dis_mod_list = NULL, **ena_mod_list = NULL;
+    int dis_dev_count = 0, ena_dev_count = 0;
+    int dis_mod_count = 0, ena_mod_count = 0;
+    int i = 0, j = 0;
+    char dump_str[512];
+
+    if (!am->ucm.uc_mgr || !verb)
+        return AUDIO_ERR_PARAMETER;
+
+    snd_use_case_get(am->ucm.uc_mgr, "_verb", &old_verb);
+    old_dev_count = snd_use_case_get_list(am->ucm.uc_mgr, "_enadevs", &old_dev_list);
+    old_mod_count = snd_use_case_get_list(am->ucm.uc_mgr, "_enamods", &old_mod_list);
+    __dump_use_case(old_verb, old_dev_list, old_dev_count, old_mod_list, old_mod_count, &dump_str[0]);
+    AUDIO_LOG_INFO(">>> UCM current %s", dump_str);
+
+    if (devices) {
+        for (dev_count = 0; devices[dev_count]; dev_count++);
+    }
+    if (modifiers) {
+        for (mod_count = 0; modifiers[mod_count]; mod_count++);
+    }
+
+    __dump_use_case(verb, devices, dev_count, modifiers, mod_count, &dump_str[0]);
+    AUDIO_LOG_INFO("> UCM requested %s", dump_str);
+
+    if (old_verb && streq(verb, old_verb)) {
+        AUDIO_LOG_DEBUG("current verb and new verb is same. No need to change verb, disable devices explicitely");
+
+        if (old_dev_count > 0) {
+            dis_dev_list = (const char **)malloc(sizeof(const char *) * old_dev_count);
+            for (i = 0; i < old_dev_count; i++) {
+                dis_dev_list[i] = NULL;
+            }
+        }
+        if (dev_count > 0) {
+            ena_dev_list = (const char **)malloc(sizeof(const char *) * dev_count);
+            for (i = 0; i < dev_count; i++) {
+                ena_dev_list[i] = NULL;
+            }
+        }
+        if (old_mod_count > 0) {
+            dis_mod_list = (const char **)malloc(sizeof(const char *) * old_mod_count);
+            for (i = 0; i < old_mod_count; i++) {
+                dis_mod_list[i] = NULL;
+            }
+        }
+        if (mod_count > 0) {
+            ena_mod_list = (const char **)malloc(sizeof(const char *) * mod_count);
+            for (i = 0; i < mod_count; i++) {
+                ena_mod_list[i] = NULL;
+            }
+        }
+
+        /* update disable modifiers list which are not present in new modifier list */
+        for (i = 0; i < old_mod_count; i++) {
+            int need_disable_mod = 1;
+
+            for (j = 0; j < mod_count; j++) {
+                if (streq(old_mod_list[i], modifiers[j])) {
+                    need_disable_mod = 0;
+                    break;
+                }
+            }
+            if (need_disable_mod) {
+                if (is_mod_changed == 0)
+                    is_mod_changed = 1;
+                dis_mod_list[dis_mod_count++] = old_mod_list[i];
+            }
+        }
+
+        /* update disable devices list which are not present in new device list */
+        for (i = 0; i < old_dev_count; i++) {
+            int need_disable_dev = 1;
+
+            for (j = 0; j < dev_count; j++) {
+                if (streq(old_dev_list[i], devices[j])) {
+                    need_disable_dev = 0;
+                    break;
+                }
+            }
+            if (need_disable_dev) {
+                if (is_dev_changed == 0)
+                    is_dev_changed = 1;
+                dis_dev_list[dis_dev_count++] = old_dev_list[i];
+            }
+        }
+
+        /* update enable devices list which are not present in old device list */
+        for (i = 0; i < dev_count; i++) {
+            int need_enable_dev = 1;
+
+            for (j = 0; j < old_dev_count; j++) {
+                if (streq(devices[i], old_dev_list[j])) {
+                    need_enable_dev = 0;
+                    break;
+                }
+            }
+            if (need_enable_dev) {
+                if (is_dev_changed == 0)
+                    is_dev_changed = 1;
+                ena_dev_list[ena_dev_count++] = devices[i];
+            }
+        }
+
+        /* update enable modifiers list which are not present in old modifier list */
+        for (i = 0; i < mod_count; i++) {
+            int need_enable_mod = 1;
+
+            for (j = 0; j < old_mod_count; j++) {
+                if (streq(modifiers[i], old_mod_list[j])) {
+                    need_enable_mod = 0;
+                    break;
+                }
+            }
+            if (need_enable_mod) {
+                if (is_mod_changed == 0)
+                    is_mod_changed = 1;
+                ena_mod_list[ena_mod_count++] = modifiers[i];
+            }
+        }
+
+        /* disable modifiers */
+        for (i = 0; i < dis_mod_count; i++) {
+            AUDIO_LOG_INFO("Disable modifier : %s", dis_mod_list[i]);
+            if (snd_use_case_set(am->ucm.uc_mgr, "_dismod", dis_mod_list[i]) < 0)
+                AUDIO_LOG_ERROR("disable %s modifier failed", dis_mod_list[i]);
+        }
+
+        /* disable devices */
+        for (i = 0; i < dis_dev_count; i++) {
+            AUDIO_LOG_INFO("Disable device : %s", dis_dev_list[i]);
+            if (snd_use_case_set(am->ucm.uc_mgr, "_disdev", dis_dev_list[i]) < 0)
+                AUDIO_LOG_ERROR("disable %s device failed", dis_dev_list[i]);
+        }
+
+        /* enable devices */
+        for (i = 0; i < ena_dev_count; i++) {
+            AUDIO_LOG_INFO("Enable device : %s", ena_dev_list[i]);
+            if (snd_use_case_set(am->ucm.uc_mgr, "_enadev", ena_dev_list[i]) < 0)
+                AUDIO_LOG_ERROR("enable %s device failed", ena_dev_list[i]);
+        }
+
+        /* enable modifiers */
+        for (i = 0; i < ena_mod_count; i++) {
+            AUDIO_LOG_INFO("Enable modifier : %s", ena_mod_list[i]);
+            if (snd_use_case_set(am->ucm.uc_mgr, "_enamod", ena_mod_list[i]) < 0)
+                AUDIO_LOG_ERROR("enable %s modifier failed", ena_mod_list[i]);
+        }
+    } else {
+        is_verb_changed = 1;
+
+        AUDIO_LOG_DEBUG("Setting new verb: %s", verb);
+        /* set new verb */
+        if (snd_use_case_set(am->ucm.uc_mgr, "_verb", verb) < 0) {
+            AUDIO_LOG_ERROR("Setting verb %s failed", verb);
+            audio_ret = AUDIO_ERR_UNDEFINED;
+            goto exit;
+        }
+        /* enable devices */
+        for (i = 0; i < dev_count; i++) {
+            AUDIO_LOG_DEBUG("Enable device : %s", devices[i]);
+            if(snd_use_case_set(am->ucm.uc_mgr, "_enadev", devices[i]) < 0)
+                AUDIO_LOG_ERROR("Enable %s device failed", devices[i]);
+        }
+        /* enable modifiers */
+        for (i = 0; i < mod_count; i++) {
+            AUDIO_LOG_DEBUG("Enable modifier : %s", modifiers[i]);
+            if(snd_use_case_set(am->ucm.uc_mgr, "_enamod", modifiers[i]) < 0)
+                AUDIO_LOG_ERROR("Enable %s modifier failed", modifiers[i]);
+        }
+    }
+
+exit:
+    if (old_verb)
+        free((void *)old_verb);
+    if (old_dev_list)
+        snd_use_case_free_list(old_dev_list, old_dev_count);
+    if (old_mod_list)
+        snd_use_case_free_list(old_mod_list, old_mod_count);
+    if (dis_dev_list)
+        free((void *)dis_dev_list);
+    if (ena_dev_list)
+        free((void *)ena_dev_list);
+    if (dis_mod_list)
+        free((void *)dis_mod_list);
+    if (ena_mod_list)
+        free((void *)ena_mod_list);
+
+    if (is_verb_changed == 1 || is_dev_changed == 1 || is_mod_changed == 1) {
+        const char *new_verb = NULL, **new_dev_list = NULL, **new_mod_list = NULL;
+        int new_dev_count = 0, new_mod_count = 0;
+
+        snd_use_case_get(am->ucm.uc_mgr, "_verb", &new_verb);
+        new_dev_count = snd_use_case_get_list(am->ucm.uc_mgr, "_enadevs", &new_dev_list);
+        new_mod_count = snd_use_case_get_list(am->ucm.uc_mgr, "_enamods", &new_mod_list);
+        __dump_use_case(new_verb, new_dev_list, new_dev_count, new_mod_list, new_mod_count, &dump_str[0]);
+        AUDIO_LOG_INFO("<<< UCM changed %s", dump_str);
+
+        if (new_verb)
+            free((void *)new_verb);
+        if (new_dev_list)
+            snd_use_case_free_list(new_dev_list, new_dev_count);
+        if (new_mod_list)
+            snd_use_case_free_list(new_mod_list, new_mod_count);
+    }
+
+    return audio_ret;
+}
+
+
+audio_return_t _audio_ucm_get_verb (audio_mgr_t *am, const char **value)
+{
+    audio_return_t ret = AUDIO_RET_OK;
+
+    AUDIO_RETURN_VAL_IF_FAIL(am, AUDIO_ERR_PARAMETER);
+    AUDIO_RETURN_VAL_IF_FAIL(value, AUDIO_ERR_PARAMETER);
+
+    if ((ret = snd_use_case_get(am->ucm.uc_mgr, "_verb", value)) < 0) {
+        AUDIO_LOG_ERROR("Getting current verb failed: Reason %d", ret);
+        ret = AUDIO_ERR_UNDEFINED;
+    }
+
+    return ret;
+}
+
+
+audio_return_t _audio_ucm_reset_use_case (audio_mgr_t *am)
+{
+    audio_return_t ret = AUDIO_RET_OK;
+
+    AUDIO_RETURN_VAL_IF_FAIL(am, AUDIO_ERR_PARAMETER);
+
+    AUDIO_LOG_INFO(">>> UCM reset Verb [ %s ]", AUDIO_USE_CASE_VERB_INACTIVE);
+
+    if ((ret = snd_use_case_set(am->ucm.uc_mgr, "_verb", AUDIO_USE_CASE_VERB_INACTIVE)) < 0) {
+        AUDIO_LOG_ERROR("Reset use case failed: Reason %d", ret);
+        ret = AUDIO_ERR_UNDEFINED;
+    }
+
+    return ret;
+}
+
old mode 100644 (file)
new mode 100755 (executable)
index c442595..d459f36
@@ -3,8 +3,6 @@
  *
  * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
  *
- * Contact: Hyunseok Lee <hs7388.lee@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
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 #include <pthread.h>
 
 #include "tizen-audio-internal.h"
 
 audio_return_t _audio_util_init (audio_mgr_t *am)
 {
-    char *card_name = 0;
-    int ret = 0;
-
-    pthread_mutex_init(&am->mixer.mutex, NULL);
-    snd_card_get_name(0, &card_name);
-    if (!card_name)
-        card_name = "default";
-    ret = snd_ctl_open(&am->mixer.mixer, card_name, 0);
-    if (ret < 0 || !am->mixer.mixer) {
-        AUDIO_LOG_ERROR("mixer_open failed");
-        return AUDIO_ERR_RESOURCE;
+    pthread_mutex_init(&(am->mixer.mutex), NULL);
+    return AUDIO_RET_OK;
     }
 
+audio_return_t _audio_util_deinit (audio_mgr_t *am)
+{
+    pthread_mutex_destroy(&(am->mixer.mutex));
     return AUDIO_RET_OK;
 }
 
-audio_return_t _audio_util_deinit (audio_mgr_t *am)
+#ifdef __MIXER_PARAM_DUMP
+
+static void __dump_mixer_param(char *dump, long *param, int size)
 {
-    pthread_mutex_destroy(&am->mixer.mutex);
-    snd_ctl_close(am->mixer.mixer);
-    am->mixer.mixer = NULL;
+    int i, len;
+
+    for (i = 0; i < size; i++) {
+        len = sprintf(dump, "%ld", *param);
+        if (len > 0)
+            dump += len;
+        if (i != size -1) {
+            *dump++ = ',';
+        }
+
+        param++;
+    }
+    *dump = '\0';
+}
 
+#endif
+
+audio_return_t _audio_mixer_control_set_param(audio_mgr_t *am, const char* ctl_name, snd_ctl_elem_value_t* param, int size)
+{
+    /* TODO. */
     return AUDIO_RET_OK;
 }
 
+audio_return_t audio_mixer_control_get_value (void *userdata, const char *ctl_name, int *val)
+{
+    audio_return_t audio_ret = AUDIO_RET_OK;
+    audio_mgr_t *am = (audio_mgr_t *)userdata;
+    audio_ret = _audio_mixer_control_get_value(am, ctl_name, val);
+    return audio_ret;
+}
+
 audio_return_t _audio_mixer_control_get_value(audio_mgr_t *am, const char *ctl_name, int *val)
 {
-    audio_return_t ret = AUDIO_RET_USE_HW_CONTROL;
+    snd_ctl_t *handle;
     snd_ctl_elem_value_t *control;
     snd_ctl_elem_id_t *id;
     snd_ctl_elem_info_t *info;
     snd_ctl_elem_type_t type;
-    int count = 0, i = 0;
 
-    pthread_mutex_lock(&am->mixer.mutex);
+    int ret = 0, count = 0, i = 0;
+
+    pthread_mutex_lock(&(am->mixer.mutex));
+
+    ret = snd_ctl_open(&handle, ALSA_DEFAULT_CARD, 0);
+    if (ret < 0) {
+        AUDIO_LOG_ERROR ("snd_ctl_open error, %s\n", snd_strerror(ret));
+        pthread_mutex_unlock(&(am->mixer.mutex));
+        return AUDIO_ERR_IOCTL;
+    }
+
+    // Get Element Info
 
     snd_ctl_elem_id_alloca(&id);
     snd_ctl_elem_info_alloca(&info);
@@ -75,10 +104,9 @@ audio_return_t _audio_mixer_control_get_value(audio_mgr_t *am, const char *ctl_n
     snd_ctl_elem_id_set_name(id, ctl_name);
 
     snd_ctl_elem_info_set_id(info, id);
-    if (snd_ctl_elem_info(am->mixer.mixer, info) < 0) {
-        AUDIO_LOG_ERROR("snd_ctl_elem_info %s failed", ctl_name);
-        ret = AUDIO_ERR_IOCTL;
-        goto exit;
+    if(snd_ctl_elem_info(handle, info) < 0 ) {
+        AUDIO_LOG_ERROR ("Cannot find control element: %s\n", ctl_name);
+        goto close;
     }
     snd_ctl_elem_info_get_id(info, id);
 
@@ -87,10 +115,9 @@ audio_return_t _audio_mixer_control_get_value(audio_mgr_t *am, const char *ctl_n
 
     snd_ctl_elem_value_set_id(control, id);
 
-    if(snd_ctl_elem_read(am->mixer.mixer, control) < 0) {
+    if(snd_ctl_elem_read(handle, control) < 0) {
         AUDIO_LOG_ERROR("snd_ctl_elem_read failed \n");
-        ret = AUDIO_ERR_IOCTL;
-        goto exit;
+        goto close;
     }
 
     switch (type) {
@@ -101,31 +128,52 @@ audio_return_t _audio_mixer_control_get_value(audio_mgr_t *am, const char *ctl_n
         for (i = 0; i < count; i++)
         *val = snd_ctl_elem_value_get_integer(control, i);
         break;
+    case SND_CTL_ELEM_TYPE_ENUMERATED:
+        for (i = 0; i < count; i++)
+        *val = snd_ctl_elem_value_get_enumerated(control, i);
+        break;
     default:
         AUDIO_LOG_WARN("unsupported control element type\n");
-        ret = AUDIO_ERR_IOCTL;
-        goto exit;
+        goto close;
     }
 
-    AUDIO_LOG_DEBUG("mixer_ctl_get %s=%d success", ctl_name, *val);
+    snd_ctl_close(handle);
+
+#ifdef AUDIO_DEBUG
+    AUDIO_LOG_INFO("get mixer(%s) = %d success", ctl_name, *val);
+#endif
 
-exit:
-    pthread_mutex_unlock(&am->mixer.mutex);
+    pthread_mutex_unlock(&(am->mixer.mutex));
+    return AUDIO_RET_USE_HW_CONTROL;
 
-    return ret;
+close:
+    AUDIO_LOG_ERROR ("Error\n");
+    snd_ctl_close(handle);
+    pthread_mutex_unlock(&(am->mixer.mutex));
+    return AUDIO_ERR_UNDEFINED;
 }
 
 audio_return_t _audio_mixer_control_set_value(audio_mgr_t *am, const char *ctl_name, int val)
 {
-    audio_return_t ret = AUDIO_RET_USE_HW_CONTROL;
-    int mixer_ret = -1;
+    snd_ctl_t *handle;
     snd_ctl_elem_value_t *control;
     snd_ctl_elem_id_t *id;
     snd_ctl_elem_info_t *info;
     snd_ctl_elem_type_t type;
-    int count = 0, i = 0;
 
-    pthread_mutex_lock(&am->mixer.mutex);
+    char *card_name = NULL;
+    int ret = 0, count = 0, i = 0;
+
+    pthread_mutex_lock(&(am->mixer.mutex));
+
+    ret = snd_ctl_open(&handle, ALSA_DEFAULT_CARD, 0);
+    if (ret < 0) {
+        AUDIO_LOG_ERROR("snd_ctl_open error, card: %s: %s", card_name, snd_strerror(ret));
+        pthread_mutex_unlock(&(am->mixer.mutex));
+        return AUDIO_ERR_IOCTL;
+    }
+
+    // Get Element Info
 
     snd_ctl_elem_id_alloca(&id);
     snd_ctl_elem_info_alloca(&info);
@@ -135,10 +183,9 @@ audio_return_t _audio_mixer_control_set_value(audio_mgr_t *am, const char *ctl_n
     snd_ctl_elem_id_set_name(id, ctl_name);
 
     snd_ctl_elem_info_set_id(info, id);
-    if (snd_ctl_elem_info(am->mixer.mixer, info) < 0) {
-        AUDIO_LOG_ERROR("snd_ctl_elem_info %s failed", ctl_name);
-        ret = AUDIO_ERR_IOCTL;
-        goto exit;
+    if(snd_ctl_elem_info(handle, info) < 0 ) {
+        AUDIO_LOG_ERROR("Cannot find control element: %s", ctl_name);
+        goto close;
     }
     snd_ctl_elem_info_get_id(info, id);
 
@@ -147,7 +194,7 @@ audio_return_t _audio_mixer_control_set_value(audio_mgr_t *am, const char *ctl_n
 
     snd_ctl_elem_value_set_id(control, id);
 
-    snd_ctl_elem_read(am->mixer.mixer, control);
+    snd_ctl_elem_read(handle, control);
 
     switch (type) {
     case SND_CTL_ELEM_TYPE_BOOLEAN:
@@ -158,22 +205,153 @@ audio_return_t _audio_mixer_control_set_value(audio_mgr_t *am, const char *ctl_n
         for (i = 0; i < count; i++)
             snd_ctl_elem_value_set_integer(control, i,val);
         break;
+    case SND_CTL_ELEM_TYPE_ENUMERATED:
+        for (i = 0; i < count; i++)
+            snd_ctl_elem_value_set_enumerated(control, i,val);
+        break;
+
     default:
-        AUDIO_LOG_WARN("unsupported control element type\n");
-        ret = AUDIO_ERR_IOCTL;
-        goto exit;
+        AUDIO_LOG_WARN("unsupported control element type");
+        goto close;
+    }
+
+    snd_ctl_elem_write(handle, control);
+
+    snd_ctl_close(handle);
+
+    AUDIO_LOG_INFO("set mixer(%s) = %d success", ctl_name, val);
+
+    pthread_mutex_unlock(&(am->mixer.mutex));
+    return AUDIO_RET_USE_HW_CONTROL;
+
+close:
+    AUDIO_LOG_ERROR("Error");
+    snd_ctl_close(handle);
+    pthread_mutex_unlock(&(am->mixer.mutex));
+    return -1;
+}
+
+audio_return_t _audio_mixer_control_set_value_string(audio_mgr_t *am, const char* ctl_name, const char* value)
+{
+    /* TODO. */
+    return AUDIO_RET_OK;
+}
+
+
+audio_return_t _audio_mixer_control_get_element(audio_mgr_t *am, const char *ctl_name, snd_hctl_elem_t **elem)
+{
+    /* TODO. */
+    return AUDIO_RET_OK;
+}
+
+
+/* Generic snd pcm interface APIs */
+audio_return_t _audio_pcm_set_hw_params(snd_pcm_t *pcm, audio_pcm_sample_spec_t *sample_spec, uint8_t *use_mmap, snd_pcm_uframes_t *period_size, snd_pcm_uframes_t *buffer_size)
+{
+    audio_return_t ret = AUDIO_RET_OK;
+    snd_pcm_hw_params_t *hwparams;
+    int err = 0;
+    int dir;
+    unsigned int val = 0;
+    snd_pcm_uframes_t _period_size = period_size ? *period_size : 0;
+    snd_pcm_uframes_t _buffer_size = buffer_size ? *buffer_size : 0;
+    uint8_t _use_mmap = use_mmap && *use_mmap;
+    uint32_t channels = 0;
+
+    snd_pcm_hw_params_alloca(&hwparams);
+
+    /* Skip parameter setting to null device. */
+    if (snd_pcm_type(pcm) == SND_PCM_TYPE_NULL)
+        return AUDIO_ERR_IOCTL;
+
+    /* Allocate a hardware parameters object. */
+    snd_pcm_hw_params_alloca(&hwparams);
+
+    /* Fill it in with default values. */
+    if(snd_pcm_hw_params_any(pcm, hwparams) < 0) {
+        AUDIO_LOG_ERROR("snd_pcm_hw_params_any() : failed! - %s\n", snd_strerror(err));
+        goto error;
+    }
+
+    /* Set the desired hardware parameters. */
+
+    if (_use_mmap) {
+
+        if (snd_pcm_hw_params_set_access(pcm, hwparams, SND_PCM_ACCESS_MMAP_INTERLEAVED) < 0) {
+
+            /* mmap() didn't work, fall back to interleaved */
+
+            if ((ret = snd_pcm_hw_params_set_access(pcm, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
+                AUDIO_LOG_DEBUG("snd_pcm_hw_params_set_access() failed: %s", snd_strerror(ret));
+                goto error;
+            }
+
+            _use_mmap = 0;
+        }
+
+    } else if ((ret = snd_pcm_hw_params_set_access(pcm, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
+        AUDIO_LOG_DEBUG("snd_pcm_hw_params_set_access() failed: %s", snd_strerror(ret));
+        goto error;
+    }
+    AUDIO_LOG_ERROR("setting rate - %d", sample_spec->rate);
+    err = snd_pcm_hw_params_set_rate(pcm, hwparams, sample_spec->rate, 0);
+    if (err < 0) {
+        AUDIO_LOG_ERROR("snd_pcm_hw_params_set_rate() : failed! - %s\n", snd_strerror(err));
+    }
+
+    err = snd_pcm_hw_params(pcm, hwparams);
+    if (err < 0) {
+        AUDIO_LOG_ERROR("snd_pcm_hw_params() : failed! - %s\n", snd_strerror(err));
+        goto error;
     }
 
-    if (snd_ctl_elem_write(am->mixer.mixer, control) < 0) {
-        AUDIO_LOG_ERROR("snd_ctl_elem_write failed \n");
-        ret = AUDIO_ERR_IOCTL;
-        goto exit;
+    /* Dump current param */
+
+    if ((ret = snd_pcm_hw_params_current(pcm, hwparams)) < 0) {
+        AUDIO_LOG_INFO("snd_pcm_hw_params_current() failed: %s", snd_strerror(ret));
+        goto error;
+    }
+
+    if ((ret = snd_pcm_hw_params_get_period_size(hwparams, &_period_size, &dir)) < 0 ||
+        (ret = snd_pcm_hw_params_get_buffer_size(hwparams, &_buffer_size)) < 0) {
+        AUDIO_LOG_INFO("snd_pcm_hw_params_get_{period|buffer}_size() failed: %s", snd_strerror(ret));
+        goto error;
     }
 
-    AUDIO_LOG_DEBUG("set_mixer %s=%d success", ctl_name, val);
+    snd_pcm_hw_params_get_access(hwparams, (snd_pcm_access_t *) &val);
+    AUDIO_LOG_DEBUG("access type = %s\n", snd_pcm_access_name((snd_pcm_access_t)val));
+
+    snd_pcm_hw_params_get_format(hwparams, &sample_spec->format);
+    AUDIO_LOG_DEBUG("format = '%s' (%s)\n",
+                    snd_pcm_format_name((snd_pcm_format_t)sample_spec->format),
+                    snd_pcm_format_description((snd_pcm_format_t)sample_spec->format));
+
+    snd_pcm_hw_params_get_subformat(hwparams, (snd_pcm_subformat_t *)&val);
+    AUDIO_LOG_DEBUG("subformat = '%s' (%s)\n",
+                    snd_pcm_subformat_name((snd_pcm_subformat_t)val),
+                    snd_pcm_subformat_description((snd_pcm_subformat_t)val));
 
-exit:
-    pthread_mutex_unlock(&am->mixer.mutex);
+    snd_pcm_hw_params_get_channels(hwparams, &channels);
+    sample_spec->channels = (uint8_t)channels;
+    AUDIO_LOG_DEBUG("channels = %d\n", sample_spec->channels);
 
-    return ret;
+    if (buffer_size)
+        *buffer_size = _buffer_size;
+
+    if (period_size)
+        *period_size = _period_size;
+
+    if (use_mmap)
+        *use_mmap = _use_mmap;
+
+    return AUDIO_RET_OK;
+
+error:
+    return AUDIO_ERR_RESOURCE;
+}
+
+
+audio_return_t _audio_pcm_set_sw_params(snd_pcm_t *pcm, snd_pcm_uframes_t avail_min, uint8_t period_event, uint32_t start_threshold, uint32_t rate)
+{
+    return AUDIO_ERR_NOT_IMPLEMENTED;
 }
old mode 100644 (file)
new mode 100755 (executable)
index 6e1c3ce..db1638a
@@ -3,8 +3,6 @@
  *
  * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
  *
- * Contact: Hyunseok Lee <hs7388.lee@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
@@ -30,7 +28,7 @@ int audio_get_revision (void)
     return AUDIO_REVISION;
 }
 
-audio_return_t audio_init (void **userdata)
+audio_return_t audio_init (void **userdata, void *platform_data)
 {
     audio_mgr_t *am;
     audio_return_t ret = AUDIO_RET_OK;
@@ -39,6 +37,8 @@ audio_return_t audio_init (void **userdata)
         AUDIO_LOG_ERROR("am malloc failed");
         return AUDIO_ERR_RESOURCE;
     }
+    am->platform_data = platform_data;
+    memset(&am->cb_intf, 0, sizeof(audio_cb_interface_t));
     if (AUDIO_IS_ERROR((ret = _audio_session_init(am)))) {
         AUDIO_LOG_ERROR("session init failed");
         goto error_exit;
@@ -51,6 +51,10 @@ audio_return_t audio_init (void **userdata)
         AUDIO_LOG_ERROR("stream init failed");
         goto error_exit;
     }
+    if (AUDIO_IS_ERROR((ret = _audio_ucm_init(am)))) {
+        AUDIO_LOG_ERROR("ucm init failed");
+        goto error_exit;
+    }
     if (AUDIO_IS_ERROR((ret = _audio_util_init(am)))) {
         AUDIO_LOG_ERROR("mixer init failed");
         goto error_exit;
@@ -74,6 +78,7 @@ audio_return_t audio_deinit (void **userdata)
         _audio_session_deinit(am);
         _audio_device_deinit(am);
         _audio_stream_deinit(am);
+        _audio_ucm_deinit(am);
         _audio_util_deinit(am);
         free(am);
         *userdata = NULL;
@@ -82,32 +87,19 @@ audio_return_t audio_deinit (void **userdata)
     return AUDIO_RET_OK;
 }
 
+/* this function is only called from audio tuning app for updating volume */
 audio_return_t audio_reset (void **userdata)
 {
     audio_mgr_t *am = (audio_mgr_t *)*userdata;
     audio_return_t ret = AUDIO_RET_OK;
 
     if (am) {
-        _audio_device_deinit(am);
         _audio_stream_deinit(am);
-        _audio_util_deinit(am);
 
-        if (AUDIO_IS_ERROR((ret = _audio_session_init(am)))) {
-            AUDIO_LOG_ERROR("session init failed");
-            goto error_exit;
-        }
-        if (AUDIO_IS_ERROR((ret = _audio_device_init(am)))) {
-            AUDIO_LOG_ERROR("device init failed");
-            goto error_exit;
-        }
         if (AUDIO_IS_ERROR((ret = _audio_stream_init(am)))) {
             AUDIO_LOG_ERROR("stream init failed");
             goto error_exit;
         }
-        if (AUDIO_IS_ERROR((ret = _audio_util_init(am)))) {
-            AUDIO_LOG_ERROR("mixer init failed");
-            goto error_exit;
-        }
     }
 
     return AUDIO_RET_OK;
@@ -119,3 +111,15 @@ error_exit:
 
     return ret;
 }
+
+audio_return_t audio_set_callback (void *userdata, audio_cb_interface_t *cb_interface)
+{
+    audio_mgr_t *am = (audio_mgr_t *)userdata;
+
+    if (am) {
+        memcpy(&am->cb_intf, cb_interface, sizeof(audio_cb_interface_t));
+        return AUDIO_RET_OK;
+    } else {
+        return AUDIO_ERR_PARAMETER;
+    }
+}
old mode 100644 (file)
new mode 100755 (executable)
index 328901a..e29a08c
@@ -6,8 +6,6 @@
  *
  * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
  *
- * Contact: Hyunseok Lee <hs7388.lee@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
@@ -39,6 +37,7 @@ typedef enum audio_return {
     AUDIO_ERR_RESOURCE                  = (int32_t)0x80001001,
     AUDIO_ERR_PARAMETER                 = (int32_t)0x80001002,
     AUDIO_ERR_IOCTL                     = (int32_t)0x80001003,
+    AUDIO_ERR_NOT_IMPLEMENTED           = (int32_t)0x80001004,
 } audio_return_t ;
 
 
@@ -63,15 +62,21 @@ typedef enum audio_subsession {
     AUDIO_SUBSESSION_VOICE,
     AUDIO_SUBSESSION_RINGTONE,
     AUDIO_SUBSESSION_MEDIA,
-    AUDIO_SUBSESSION_VR_INIT,
+    AUDIO_SUBSESSION_INIT,
     AUDIO_SUBSESSION_VR_NORMAL,
     AUDIO_SUBSESSION_VR_DRIVE,
     AUDIO_SUBSESSION_STEREO_REC,
-    AUDIO_SUBSESSION_AM_PLAY,
-    AUDIO_SUBSESSION_AM_REC,
+    AUDIO_SUBSESSION_MONO_REC,
     AUDIO_SUBSESSION_MAX
 } audio_subsession_t;
 
+/* Session command */
+typedef enum audio_session_command {
+    AUDIO_SESSION_CMD_START,
+    AUDIO_SESSION_CMD_SUBSESSION,
+    AUDIO_SESSION_CMD_END,
+} audio_session_command_t;
+
 
 /* Direction */
 typedef enum audio_direction {
@@ -108,12 +113,14 @@ typedef enum audio_device_out {
 
 typedef enum audio_route_flag {
     AUDIO_ROUTE_FLAG_NONE               = 0,
-    AUDIO_ROUTE_FLAG_DUAL_OUT           = 0x00000001,
-    AUDIO_ROUTE_FLAG_NOISE_REDUCTION    = 0x00000002,
-    AUDIO_ROUTE_FLAG_EXTRA_VOL          = 0x00000004,
-    AUDIO_ROUTE_FLAG_WB                 = 0x00000008,
-    AUDIO_ROUTE_FLAG_SVOICE_COMMAND     = 0x00010000,
-    AUDIO_ROUTE_FLAG_SVOICE_WAKEUP      = 0x00020000,
+    AUDIO_ROUTE_FLAG_MUTE_POLICY        = 0x00000001,
+    AUDIO_ROUTE_FLAG_DUAL_OUT           = 0x00000002,
+    AUDIO_ROUTE_FLAG_NOISE_REDUCTION    = 0x00000010,
+    AUDIO_ROUTE_FLAG_EXTRA_VOL          = 0x00000020,
+    AUDIO_ROUTE_FLAG_NETWORK_WB         = 0x00000040,
+    AUDIO_ROUTE_FLAG_BT_WB              = 0x00000100,
+    AUDIO_ROUTE_FLAG_BT_NREC            = 0x00000200,
+    AUDIO_ROUTE_FLAG_VOICE_COMMAND      = 0x00040000,
 } audio_route_flag_t;
 
 typedef enum audio_device_api {
@@ -122,7 +129,33 @@ typedef enum audio_device_api {
     AUDIO_DEVICE_API_BLUEZ,
 } audio_device_api_t;
 
+typedef enum audio_device_param {
+    AUDIO_DEVICE_PARAM_NONE,
+    AUDIO_DEVICE_PARAM_CHANNELS,
+    AUDIO_DEVICE_PARAM_SAMPLERATE,
+    AUDIO_DEVICE_PARAM_FRAGMENT_SIZE,
+    AUDIO_DEVICE_PARAM_FRAGMENT_NB,
+    AUDIO_DEVICE_PARAM_START_THRESHOLD,
+    AUDIO_DEVICE_PARAM_USE_MMAP,
+    AUDIO_DEVICE_PARAM_USE_TSCHED,
+    AUDIO_DEVICE_PARAM_TSCHED_BUF_SIZE,
+    AUDIO_DEVICE_PARAM_SUSPEND_TIMEOUT,
+    AUDIO_DEVICE_PARAM_ALTERNATE_RATE,
+    AUDIO_DEVICE_PARAM_MAX,
+} audio_device_param_t;
+
+typedef struct audio_device_param_info {
+    audio_device_param_t param;
+    union {
+        int64_t s64_v;
+        uint64_t u64_v;
+        int32_t s32_v;
+        uint32_t u32_v;
+    };
+} audio_device_param_info_t;
+
 typedef struct audio_device_alsa_info {
+    char *card_name;
     uint32_t card_idx;
     uint32_t device_idx;
 } audio_device_alsa_info_t;
@@ -134,6 +167,9 @@ typedef struct audio_device_bluz_info {
 
 typedef struct audio_device_info {
     audio_device_api_t api;
+    audio_direction_t direction;
+    char *name;
+    uint8_t is_default_device;
     union {
         audio_device_alsa_info_t alsa;
         audio_device_bluez_info_t bluez;
@@ -151,9 +187,8 @@ typedef enum audio_volume {
     AUDIO_VOLUME_TYPE_MEDIA,            /**< Media volume type */
     AUDIO_VOLUME_TYPE_CALL,             /**< Call volume type */
     AUDIO_VOLUME_TYPE_VOIP,             /**< VOIP volume type */
-    AUDIO_VOLUME_TYPE_SVOICE,           /**< SVOICE volume type */
+    AUDIO_VOLUME_TYPE_VOICE,            /**< Voice volume type */
     AUDIO_VOLUME_TYPE_FIXED,            /**< Volume type for fixed acoustic level */
-    AUDIO_VOLUME_TYPE_EXT_JAVA,         /**< External system volume for Java */
     AUDIO_VOLUME_TYPE_MAX,              /**< Volume type count */
 } audio_volume_t;
 
@@ -172,25 +207,8 @@ typedef enum audio_gain {
     AUDIO_GAIN_TYPE_MAX,
 } audio_gain_t;
 
-#if 0 // TODO : need to consider */
-typedef enum audio_volume_format {
-    AUDIO_VOLUME_FORMAT_LINEAR,     /**< Linear format (double) */
-    AUDIO_VOLUME_FORMAT_DECIBEL,    /**< Decibel format (double) */
-    AUDIO_VOLUME_FORMAT_PA,         /**< PulseAudio format (pa_volume_t) */
-} audio_volume_format_t;
-
-typedef struct audio_volume_value {
-    audio_volume_format format;
-    union {
-        double linear;
-        double decibel;
-        uint32_t pa;
-    } value;
-} audio_volume_value_t;
-#endif
-
 typedef struct audio_stream_info {
-    const char *name;
+    char *name;
     uint32_t samplerate;
     uint8_t channels;
     uint32_t volume_type;
@@ -205,19 +223,52 @@ typedef struct audio_info {
     audio_stream_info_t stream;
 } audio_info_t;
 
+typedef struct audio_cb_interface {
+    audio_return_t (*load_device)(void *platform_data, audio_device_info_t *device_info, audio_device_param_info_t *params);
+    audio_return_t (*open_device)(void *platform_data, audio_device_info_t *device_info, audio_device_param_info_t *params);
+    audio_return_t (*close_all_devices)(void *platform_data);
+    audio_return_t (*close_device)(void *platform_data, audio_device_info_t *device_info);
+    audio_return_t (*unload_device)(void *platform_data, audio_device_info_t *device_info);
+} audio_cb_interface_t;
+
+typedef struct audio_interface {
+    audio_return_t (*init)(void **userdata, void *platform_data);
+    audio_return_t (*deinit)(void **userdata);
+    audio_return_t (*reset)(void **userdata);
+    audio_return_t (*set_callback)(void *userdata, audio_cb_interface_t *cb_interface);
+    audio_return_t (*get_volume_level_max)(void *userdata, uint32_t volume_type, uint32_t *level);
+    audio_return_t (*get_volume_level)(void *userdata, uint32_t volume_type, uint32_t *level);
+    audio_return_t (*get_volume_value)(void *userdata, audio_info_t *info, uint32_t volume_type, uint32_t level, double *value);
+    audio_return_t (*set_volume_level)(void *userdata, audio_info_t *info, uint32_t volume_type, uint32_t level);
+    audio_return_t (*set_volume_value)(void *userdata, audio_info_t *info, uint32_t volume_type, double* value);
+    audio_return_t (*get_gain_value)(void *userdata, audio_info_t *info, uint32_t volume_type, double *value);
+    audio_return_t (*get_mute)(void *userdata, audio_info_t *info, uint32_t volume_type, uint32_t direction, uint32_t *mute);
+    audio_return_t (*set_mute)(void *userdata, audio_info_t *info, uint32_t volume_type, uint32_t direction, uint32_t mute);
+    audio_return_t (*set_session)(void *userdata, uint32_t session, uint32_t subsession, uint32_t cmd);
+    audio_return_t (*set_route)(void *userdata, uint32_t session, uint32_t subsession, uint32_t device_in, uint32_t device_out, uint32_t route_flag);
+    audio_return_t (*alsa_pcm_open)(void *userdata, void **pcm_handle, char *device_name, uint32_t direction, int mode);
+    audio_return_t (*alsa_pcm_close)(void *userdata, void *pcm_handle);
+    audio_return_t (*set_mixer_value_string)(void *userdata, const char* ctl, const char* value);
+
+} audio_interface_t;
+
 int audio_get_revision (void);
-audio_return_t audio_init (void **userdata);
+audio_return_t audio_init (void **userdata, void *platform_data);
 audio_return_t audio_deinit (void **userdata);
 audio_return_t audio_reset (void **userdata);
+audio_return_t audio_set_callback (void *userdata, audio_cb_interface_t *cb_interface);
 audio_return_t audio_get_volume_level_max (void *userdata, uint32_t volume_type, uint32_t *level);
 audio_return_t audio_get_volume_level (void *userdata, uint32_t volume_type, uint32_t *level);
 audio_return_t audio_get_volume_value (void *userdata, audio_info_t *info, uint32_t volume_type, uint32_t level, double *value);
 audio_return_t audio_set_volume_level (void *userdata, audio_info_t *info, uint32_t volume_type, uint32_t level);
+audio_return_t audio_set_volume_value (void *userdata, audio_info_t *info, uint32_t volume_type, double* value);
+audio_return_t audio_get_gain_value (void *userdata, audio_info_t *info, uint32_t volume_type, double *value);
 audio_return_t audio_get_mute (void *userdata, audio_info_t *info, uint32_t volume_type, uint32_t direction, uint32_t *mute);
 audio_return_t audio_set_mute (void *userdata, audio_info_t *info, uint32_t volume_type, uint32_t direction, uint32_t mute);
-audio_return_t audio_set_session (void *userdata, uint32_t session, uint32_t subsession);
+audio_return_t audio_set_session (void *userdata, uint32_t session, uint32_t subsession, uint32_t cmd);
+audio_return_t audio_alsa_pcm_open (void *userdata, void **pcm_handle, char *device_name, uint32_t direction, int mode);
+audio_return_t audio_alsa_pcm_close (void *userdata, void *pcm_handle);
 audio_return_t audio_set_route (void *userdata, uint32_t session, uint32_t subsession, uint32_t device_in, uint32_t device_out, uint32_t route_flag);
-audio_return_t audio_set_ecrx_device(void *userdata);
-
-
+audio_return_t audio_set_mixer_value_string(void *userdata, const char* ctl, const char* value);
+audio_return_t audio_mixer_control_get_value (void *userdata, const char *ctl_name, int *val);
 #endif