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
-
+++ /dev/null
-/*
- * 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
--- /dev/null
+pulseaudio _ rwx--- ------
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])
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
BuildRequires: pkgconfig(vconf)
BuildRequires: pkgconfig(iniparser)
BuildRequires: pkgconfig(dlog)
+Provides: libtizen-audio.so
%description
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
%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}
%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}
*
* 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
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;
}
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(¶ms[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, ¶ms[0]);
+ } else {
+ am->cb_intf.open_device(am->platform_data, device_info, ¶ms[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
*
* 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
#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;
};
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
*
* 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;
}
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;
}
-
*
* 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"
-#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,
};
"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)
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;
{
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";
}
}
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";
}
}
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)
*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;
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);
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++;
}
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));
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);
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) {
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;
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);
}
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);
}
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)))) {
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)
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;
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;
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;
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;
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
}
}
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))
--- /dev/null
+/*
+ * 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;
+}
+
*
* 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);
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);
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) {
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);
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);
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:
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;
}
*
* 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
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;
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;
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;
_audio_session_deinit(am);
_audio_device_deinit(am);
_audio_stream_deinit(am);
+ _audio_ucm_deinit(am);
_audio_util_deinit(am);
free(am);
*userdata = NULL;
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;
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;
+ }
+}
*
* 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
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 ;
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 {
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 {
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;
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;
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;
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;
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