summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjk7744.park <jk7744.park@samsung.com>2015-09-08 21:29:19 +0900
committerjk7744.park <jk7744.park@samsung.com>2015-09-08 21:29:19 +0900
commit150956c658d39b46b86383f5bcc5d9af79f760d1 (patch)
tree0fecc994a3e11ac961aa1471de6d0d0f75092fce
parent15f9a36c03cdeb2987270680770f361c316ea0a6 (diff)
downloadaudio-hal-e3250-tizen_2.3.1.tar.gz
audio-hal-e3250-tizen_2.3.1.tar.bz2
audio-hal-e3250-tizen_2.3.1.zip
-rw-r--r--AUTHORS1
-rw-r--r--LICENSE.APLv2204
-rwxr-xr-xMakefile.am13
-rw-r--r--NOTICE3
-rwxr-xr-xautogen.sh10
-rwxr-xr-xconfigure.ac49
-rw-r--r--packaging/audio-hal-e3250.spec47
-rwxr-xr-xtizen-audio-device.c369
-rwxr-xr-xtizen-audio-internal.h235
-rwxr-xr-xtizen-audio-session.c162
-rwxr-xr-xtizen-audio-stream.c473
-rwxr-xr-xtizen-audio-ucm.c447
-rwxr-xr-xtizen-audio-util.c357
-rwxr-xr-xtizen-audio.c125
-rwxr-xr-xtizen-audio.h274
15 files changed, 2769 insertions, 0 deletions
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..76f4125
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1 @@
+Hyunseok Lee <hs7388.lee at samsung.com>
diff --git a/LICENSE.APLv2 b/LICENSE.APLv2
new file mode 100644
index 0000000..76f9119
--- /dev/null
+++ b/LICENSE.APLv2
@@ -0,0 +1,204 @@
+Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ 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.
+
diff --git a/Makefile.am b/Makefile.am
new file mode 100755
index 0000000..af5fec7
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,13 @@
+lib_LTLIBRARIES = libtizen-audio.la
+
+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/NOTICE b/NOTICE
new file mode 100644
index 0000000..ccdad52
--- /dev/null
+++ b/NOTICE
@@ -0,0 +1,3 @@
+Copyright (c) Samsung Electronics Co., Ltd. All rights reserved.
+Except as noted, this software is licensed under Apache License, Version 2.
+Please, see the LICENSE file for Apache License terms and conditions.
diff --git a/autogen.sh b/autogen.sh
new file mode 100755
index 0000000..8e229ef
--- /dev/null
+++ b/autogen.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+# autogen.sh -- Autotools bootstrapping
+#
+
+libtoolize --copy --force
+aclocal && \
+autoheader && \
+autoconf && \
+automake --add-missing --copy
diff --git a/configure.ac b/configure.ac
new file mode 100755
index 0000000..6d82f53
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,49 @@
+AC_PREREQ([2.67])
+
+AC_INIT([audio-hal-e3250], [0.1])
+AM_INIT_AUTOMAKE([-Wall -Werror foreign])
+AC_CONFIG_HEADERS([config.h])
+
+AC_CONFIG_MACRO_DIR([m4])
+
+# Checks for programs.
+AC_PROG_CC
+AM_PROG_CC_C_O
+AC_PROG_CXX
+AC_PROG_LIBTOOL
+AC_PROG_AWK
+AC_PROG_CPP
+AC_PROG_INSTALL
+AC_PROG_LN_S
+AC_PROG_MAKE_SET
+PKG_PROG_PKG_CONFIG
+
+# Checks for libraries.
+
+PKG_CHECK_MODULES(ASOUNDLIB, alsa >= 1.0.24)
+AC_SUBST(ASOUNDLIB_CFLAGS)
+AC_SUBST(ASOUNDLIB_LIBS)
+
+PKG_CHECK_MODULES(VCONF, vconf)
+AC_SUBST(VCONF_CFLAGS)
+AC_SUBST(VCONF_LIBS)
+
+PKG_CHECK_MODULES(INIPARSER, iniparser)
+AC_SUBST(INIPARSER_CFLAGS)
+AC_SUBST(INIPARSER_LIBS)
+
+PKG_CHECK_MODULES(DLOG, dlog)
+AC_SUBST(DLOG_CFLAGS)
+AC_SUBST(DLOG_LIBS)
+
+# Checks for header files.
+
+# Checks for typedefs, structures, and compiler characteristics.
+
+# Checks for library functions.
+
+
+AC_CONFIG_FILES([ \
+ Makefile
+ ])
+AC_OUTPUT
diff --git a/packaging/audio-hal-e3250.spec b/packaging/audio-hal-e3250.spec
new file mode 100644
index 0000000..c6b0075
--- /dev/null
+++ b/packaging/audio-hal-e3250.spec
@@ -0,0 +1,47 @@
+Name: audio-hal-e3250
+Summary: TIZEN Audio HAL for Exynos3250
+Version: 0.2.19
+Release: 0
+Group: System/Libraries
+License: Apache-2.0
+URL: http://tizen.org
+Source0: audio-hal-e3250-%{version}.tar.gz
+BuildRequires: pkgconfig(alsa)
+BuildRequires: pkgconfig(vconf)
+BuildRequires: pkgconfig(iniparser)
+BuildRequires: pkgconfig(dlog)
+Provides: libtizen-audio.so
+
+%description
+TIZEN Audio HAL for Exynos3250
+
+%prep
+%setup -q -n %{name}-%{version}
+
+%build
+export CFLAGS="$CFLAGS -DTIZEN_DEBUG_ENABLE"
+export CXXFLAGS="$CXXFLAGS ?DTIZEN_DEBUG_ENABLE"
+export FFLAGS="$FFLAGS -DTIZEN_DEBUG_ENABLE"
+
+%autogen
+%configure
+
+make %{?jobs:-j%jobs}
+
+%install
+rm -rf %{buildroot}
+mkdir -p %{buildroot}/usr/share/license
+cp LICENSE.APLv2 %{buildroot}/usr/share/license/%{name}
+
+%make_install
+
+%post
+/sbin/ldconfig
+
+%postun
+/sbin/ldconfig
+
+%files
+%defattr(-,root,root,-)
+/usr/lib/libtizen-audio.so
+%{_datadir}/license/%{name}
diff --git a/tizen-audio-device.c b/tizen-audio-device.c
new file mode 100755
index 0000000..c8a6d93
--- /dev/null
+++ b/tizen-audio-device.c
@@ -0,0 +1,369 @@
+/*
+ * 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>
+#include <stdbool.h>
+
+#include "tizen-audio-internal.h"
+
+audio_return_t _audio_device_init (audio_mgr_t *am)
+{
+ AUDIO_RETURN_VAL_IF_FAIL(am, AUDIO_ERR_PARAMETER);
+
+ 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;
+}
+
+audio_return_t _audio_device_deinit (audio_mgr_t *am)
+{
+ AUDIO_RETURN_VAL_IF_FAIL(am, AUDIO_ERR_PARAMETER);
+
+ 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) {
+ /* 6 = "hw: ,idx */
+ if ((device_info->name = malloc(strlen(device_info->alsa.card_name) + 6)) != NULL) {
+ 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;
+ 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 ((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);
+ }
+ }
+
+ 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);
+
+// 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;
+}
diff --git a/tizen-audio-internal.h b/tizen-audio-internal.h
new file mode 100755
index 0000000..33e67e1
--- /dev/null
+++ b/tizen-audio-internal.h
@@ -0,0 +1,235 @@
+#ifndef footizenaudiointernalfoo
+#define footizenaudiointernalfoo
+
+/*
+ * 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.
+ *
+ */
+
+#include <dlog.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 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
+#endif
+#define DLOG_TAG "AUDIO_HAL"
+#define AUDIO_LOG_ERROR(...) SLOG(LOG_ERROR, DLOG_TAG, __VA_ARGS__)
+#define AUDIO_LOG_WARN(...) SLOG(LOG_WARN, DLOG_TAG, __VA_ARGS__)
+#define AUDIO_LOG_INFO(...) SLOG(LOG_INFO, DLOG_TAG, __VA_ARGS__)
+#define AUDIO_LOG_DEBUG(...) SLOG(LOG_DEBUG, DLOG_TAG, __VA_ARGS__)
+#define AUDIO_LOG_VERBOSE(...) SLOG(LOG_DEBUG, DLOG_TAG, __VA_ARGS__)
+#else
+#define AUDIO_LOG_ERROR(...) fprintf(stderr, __VA_ARGS__)
+#define AUDIO_LOG_WARN(...) fprintf(stderr, __VA_ARGS__)
+#define AUDIO_LOG_INFO(...) fprintf(stdout, __VA_ARGS__)
+#define AUDIO_LOG_DEBUG(...) fprintf(stdout, __VA_ARGS__)
+#define AUDIO_LOG_VERBOSE(...) fprintf(stdout, __VA_ARGS__)
+#endif
+
+#define AUDIO_RETURN_IF_FAIL(expr) do { \
+ if (!expr) { \
+ AUDIO_LOG_ERROR("%s failed", #expr); \
+ return; \
+ } \
+} while (0)
+#define AUDIO_RETURN_VAL_IF_FAIL(expr, val) do { \
+ if (!expr) { \
+ AUDIO_LOG_ERROR("%s failed", #expr); \
+ return val; \
+ } \
+} 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;
+
+
+/* Stream */
+
+#define AUDIO_VOLUME_LEVEL_MAX 16
+
+typedef struct audio_volume_gain_table {
+ double volume[AUDIO_VOLUME_TYPE_MAX][AUDIO_VOLUME_LEVEL_MAX];
+ uint32_t volume_level_max[AUDIO_VOLUME_LEVEL_MAX];
+ double gain[AUDIO_GAIN_TYPE_MAX];
+} audio_volume_gain_table_t;
+
+enum {
+ AUDIO_VOLUME_DEVICE_SPEAKER,
+ AUDIO_VOLUME_DEVICE_RECEIVER,
+ AUDIO_VOLUME_DEVICE_EARJACK,
+ AUDIO_VOLUME_DEVICE_BT_SCO,
+ AUDIO_VOLUME_DEVICE_BT_A2DP,
+ AUDIO_VOLUME_DEVICE_DOCK,
+ AUDIO_VOLUME_DEVICE_HDMI,
+ AUDIO_VOLUME_DEVICE_MIRRORING,
+ AUDIO_VOLUME_DEVICE_USB,
+ AUDIO_VOLUME_DEVICE_MULTIMEDIA_DOCK,
+ AUDIO_VOLUME_DEVICE_MAX,
+};
+
+typedef struct audio_stream_mgr {
+ uint32_t volume_level[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_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_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_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_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
diff --git a/tizen-audio-session.c b/tizen-audio-session.c
new file mode 100755
index 0000000..d323daa
--- /dev/null
+++ b/tizen-audio-session.c
@@ -0,0 +1,162 @@
+/*
+ * 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>
+
+#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;
+}
+
+audio_return_t _audio_session_deinit (audio_mgr_t *am)
+{
+ AUDIO_RETURN_VAL_IF_FAIL(am, AUDIO_ERR_PARAMETER);
+
+ return AUDIO_RET_OK;
+}
+
+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 %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 (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;
+
+ 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 = 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;
+}
diff --git a/tizen-audio-stream.c b/tizen-audio-stream.c
new file mode 100755
index 0000000..754f1c5
--- /dev/null
+++ b/tizen-audio-stream.c
@@ -0,0 +1,473 @@
+/*
+ * 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 <stdbool.h>
+#include <string.h>
+#include <math.h>
+#include <vconf.h>
+#include <iniparser.h>
+
+#include "tizen-audio-internal.h"
+
+#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)
+#define GAIN_VALUE_MAX (1.0f)
+
+enum {
+ STREAM_DEVICE_SPEAKER,
+ STREAM_DEVICE_HEADSET,
+ STREAM_DEVICE_BLUETOOTH,
+ STREAM_DEVICE_HDMI,
+ STREAM_DEVICE_DOCK,
+ STREAM_DEVICE_MAX,
+};
+
+static const char *g_volume_vconf[AUDIO_VOLUME_TYPE_MAX] = {
+ "file/private/sound/volume/system", /* AUDIO_VOLUME_TYPE_SYSTEM */
+ "file/private/sound/volume/notification", /* AUDIO_VOLUME_TYPE_NOTIFICATION */
+ "file/private/sound/volume/alarm", /* AUDIO_VOLUME_TYPE_ALARM */
+ "file/private/sound/volume/ringtone", /* AUDIO_VOLUME_TYPE_RINGTONE */
+ "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/voice", /* AUDIO_VOLUME_TYPE_VOICE */
+ "file/private/sound/volume/fixed", /* AUDIO_VOLUME_TYPE_FIXED */
+};
+
+static inline uint8_t __get_volume_dev_index(audio_mgr_t *am, uint32_t volume_type)
+{
+
+ 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_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_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_DOCK;
+ default:
+ AUDIO_LOG_DEBUG("invalid device_out:%d", device_out);
+ break;
+ }
+
+ return STREAM_DEVICE_SPEAKER;
+}
+
+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";
+ case STREAM_DEVICE_HDMI: return "hdmi";
+ case STREAM_DEVICE_DOCK: return "dock";
+ default: return "invalid";
+ }
+}
+
+static const char *__get_volume_type_string_by_idx (uint32_t vol_type_idx)
+{
+ switch (vol_type_idx) {
+ case AUDIO_VOLUME_TYPE_SYSTEM: return "system";
+ case AUDIO_VOLUME_TYPE_NOTIFICATION: return "notification";
+ case AUDIO_VOLUME_TYPE_ALARM: return "alarm";
+ case AUDIO_VOLUME_TYPE_RINGTONE: return "ringtone";
+ 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_VOICE: return "voice";
+ case AUDIO_VOLUME_TYPE_FIXED: return "fixed";
+ default: return "invalid";
+ }
+}
+
+static const char *__get_gain_type_string_by_idx (uint32_t gain_type_idx)
+{
+ switch (gain_type_idx) {
+ case AUDIO_GAIN_TYPE_DEFAULT: return "default";
+ case AUDIO_GAIN_TYPE_DIALER: return "dialer";
+ case AUDIO_GAIN_TYPE_TOUCH: return "touch";
+ case AUDIO_GAIN_TYPE_AF: return "af";
+ case AUDIO_GAIN_TYPE_SHUTTER1: return "shutter1";
+ case AUDIO_GAIN_TYPE_SHUTTER2: return "shutter2";
+ case AUDIO_GAIN_TYPE_CAMCODING: return "camcording";
+ case AUDIO_GAIN_TYPE_MIDI: return "midi";
+ case AUDIO_GAIN_TYPE_BOOTING: return "booting";
+ case AUDIO_GAIN_TYPE_VIDEO: return "video";
+ case AUDIO_GAIN_TYPE_TTS: return "tts";
+ 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 = 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 = snprintf(dump, AUDIO_DUMP_STR_LEN, "device:bluez(%s,nrec:%d)", info->device.bluez.protocol, info->device.bluez.nrec);
+ } else {
+ len = snprintf(dump, AUDIO_DUMP_STR_LEN, "device:unknown");
+ }
+
+ if (len > 0)
+ dump += len;
+
+ 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 += len;
+
+ *dump = '\0';
+}
+
+static void __dump_tb (audio_mgr_t *am)
+{
+ audio_volume_gain_table_t *volume_gain_table = am->stream.volume_gain_table;
+ uint32_t dev_idx, vol_type_idx, vol_level_idx, gain_type_idx;
+ const char *gain_type_str[] = {
+ "def", /* AUDIO_GAIN_TYPE_DEFAULT */
+ "dial", /* AUDIO_GAIN_TYPE_DIALER */
+ "touch", /* AUDIO_GAIN_TYPE_TOUCH */
+ "af", /* AUDIO_GAIN_TYPE_AF */
+ "shut1", /* AUDIO_GAIN_TYPE_SHUTTER1 */
+ "shut2", /* AUDIO_GAIN_TYPE_SHUTTER2 */
+ "cam", /* AUDIO_GAIN_TYPE_CAMCODING */
+ "midi", /* AUDIO_GAIN_TYPE_MIDI */
+ "boot", /* AUDIO_GAIN_TYPE_BOOTING */
+ "video", /* AUDIO_GAIN_TYPE_VIDEO */
+ "tts", /* AUDIO_GAIN_TYPE_TTS */
+ };
+ char dump_str[AUDIO_DUMP_STR_LEN], *dump_str_ptr;
+
+ /* Dump volume table */
+ AUDIO_LOG_INFO("<<<<< volume table >>>>>");
+
+
+ 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);
+
+ dump_str_ptr = &dump_str[0];
+ memset(dump_str, 0x00, sizeof(char) * sizeof(dump_str));
+ snprintf(dump_str_ptr, 8, "%6s:", vol_type_str);
+ dump_str_ptr += strlen(dump_str_ptr);
+
+ for (vol_level_idx = 0; vol_level_idx < volume_gain_table->volume_level_max[vol_type_idx]; vol_level_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_INFO("%s", dump_str);
+ }
+
+
+ /* Dump 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, 11, "%10s", " ");
+ dump_str_ptr += strlen(dump_str_ptr);
+
+ for (gain_type_idx = 0; gain_type_idx < AUDIO_GAIN_TYPE_MAX; gain_type_idx++) {
+ snprintf(dump_str_ptr, 7, "%5s ", gain_type_str[gain_type_idx]);
+ dump_str_ptr += strlen(dump_str_ptr);
+ }
+ AUDIO_LOG_INFO("%s", dump_str);
+
+
+ dump_str_ptr = &dump_str[0];
+ memset(dump_str, 0x00, sizeof(char) * sizeof(dump_str));
+
+ dump_str_ptr += strlen(dump_str_ptr);
+
+ for (gain_type_idx = 0; gain_type_idx < AUDIO_GAIN_TYPE_MAX; gain_type_idx++) {
+ snprintf(dump_str_ptr, 7, "%01.3f ", volume_gain_table->gain[gain_type_idx]);
+ dump_str_ptr += strlen(dump_str_ptr);
+ }
+ AUDIO_LOG_INFO("%s", dump_str);
+
+}
+
+static audio_return_t __load_volume_gain_table_from_ini (audio_mgr_t *am)
+{
+ dictionary * dict = NULL;
+ uint32_t 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;
+ const char delimiter[] = ", ";
+ char *key, *list_str, *token, *ptr = NULL;
+ const char *section = "volumes";
+
+ dict = iniparser_load(VOLUME_INI_TEMP_PATH);
+ if (!dict) {
+ AUDIO_LOG_DEBUG("Use default volume&gain ini file");
+ dict = iniparser_load(VOLUME_INI_DEFAULT_PATH);
+ if (!dict) {
+ AUDIO_LOG_WARN("Loading volume&gain table from ini file failed");
+ return AUDIO_ERR_UNDEFINED;
+ }
+ }
+
+ /* Load volume table */
+ 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);
+
+ volume_gain_table->volume_level_max[vol_type_idx] = 0;
+ size = strlen(section) + strlen(vol_type_str) + 2;
+ key = malloc(size);
+ if (key) {
+ snprintf(key, size, "%s:%s", section, 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 */
+ 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 {
+ 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);
+ }
+ }
+
+ /* Load gain table */
+ volume_gain_table->gain[AUDIO_GAIN_TYPE_DEFAULT] = GAIN_VALUE_MAX;
+ 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);
+
+ size = strlen(section) + strlen("gain") + strlen(gain_type_str) + 3;
+ key = malloc(size);
+ if (key) {
+ snprintf(key, size, "%s:gain_%s", section, gain_type_str);
+ token = iniparser_getstr(dict, key);
+ if (token) {
+ volume_gain_table->gain[gain_type_idx] = atof(token);
+ } else {
+ volume_gain_table->gain[gain_type_idx] = GAIN_VALUE_MAX;
+ }
+ free(key);
+ } else {
+ volume_gain_table->gain[gain_type_idx] = GAIN_VALUE_MAX;
+ }
+ }
+
+ iniparser_freedict(dict);
+
+ __dump_tb(am);
+
+ return AUDIO_RET_OK;
+}
+
+audio_return_t _audio_stream_init (audio_mgr_t *am)
+{
+ int i, j, val;
+ 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++) {
+ am->stream.volume_level[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], &val) < 0) {
+ AUDIO_LOG_ERROR("vconf_get_int(%s) failed", g_volume_vconf[i]);
+ continue;
+ }
+
+ AUDIO_LOG_INFO("read vconf. %s = %d", g_volume_vconf[i], val);
+
+ am->stream.volume_level[i] = val;
+ }
+
+ if (!(am->stream.volume_gain_table = malloc(sizeof(audio_volume_gain_table_t)))) {
+ AUDIO_LOG_ERROR("volume_gain_table malloc failed");
+ return AUDIO_ERR_RESOURCE;
+ }
+
+ 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)
+{
+ AUDIO_RETURN_VAL_IF_FAIL(am, AUDIO_ERR_PARAMETER);
+
+ if (am->stream.volume_gain_table) {
+ free(am->stream.volume_gain_table);
+ am->stream.volume_gain_table = NULL;
+ }
+
+ return AUDIO_RET_OK;
+}
+
+audio_return_t audio_get_volume_level_max (void *userdata, uint32_t volume_type, uint32_t *level)
+{
+ audio_mgr_t *am = (audio_mgr_t *)userdata;
+ audio_volume_gain_table_t *volume_gain_table;
+
+ AUDIO_RETURN_VAL_IF_FAIL(am, AUDIO_ERR_PARAMETER);
+ AUDIO_RETURN_VAL_IF_FAIL(am->stream.volume_gain_table, AUDIO_ERR_PARAMETER);
+
+ /* Get max volume level by device & type */
+ volume_gain_table = am->stream.volume_gain_table;
+ *level = volume_gain_table->volume_level_max[volume_type];
+
+ AUDIO_LOG_DEBUG("get_volume_level_max:%s=>%d", __get_volume_type_string_by_idx(volume_type), *level);
+
+ return AUDIO_RET_OK;
+}
+
+audio_return_t audio_get_volume_level (void *userdata, uint32_t volume_type, uint32_t *level)
+{
+ audio_mgr_t *am = (audio_mgr_t *)userdata;
+
+ AUDIO_RETURN_VAL_IF_FAIL(am, AUDIO_ERR_PARAMETER);
+
+ *level = am->stream.volume_level[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)
+{
+ if (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;
+ 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]);
+ }
+
+ return AUDIO_RET_OK;
+}
+
+audio_return_t audio_set_volume_level (void *userdata, audio_info_t *info, uint32_t volume_type, uint32_t level)
+{
+ audio_return_t audio_ret = AUDIO_RET_OK;
+ audio_mgr_t *am = (audio_mgr_t *)userdata;
+
+ AUDIO_RETURN_VAL_IF_FAIL(am, AUDIO_ERR_PARAMETER);
+
+ if (info == NULL) {
+
+ /* Update volume level */
+ am->stream.volume_level[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_get_gain_value (void *userdata, audio_info_t *info, uint32_t volume_type, double *value)
+{
+ audio_mgr_t *am = (audio_mgr_t *)userdata;
+ audio_volume_gain_table_t *volume_gain_table;
+
+ 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;
+ *value = volume_gain_table->gain[info->stream.gain_type];
+ }
+
+ return AUDIO_RET_OK;
+}
+
+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_ret = AUDIO_RET_OK;
+ audio_mgr_t *am = (audio_mgr_t *)userdata;
+
+ AUDIO_RETURN_VAL_IF_FAIL(am, AUDIO_ERR_PARAMETER);
+
+ /* TODO. Not implemented */
+
+ return audio_ret;
+}
+
+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_ret = AUDIO_RET_OK;
+ audio_mgr_t *am = (audio_mgr_t *)userdata;
+
+ AUDIO_RETURN_VAL_IF_FAIL(am, AUDIO_ERR_PARAMETER);
+ /* TODO. Not implemented */
+
+ return audio_ret;
+}
diff --git a/tizen-audio-ucm.c b/tizen-audio-ucm.c
new file mode 100755
index 0000000..0d4f437
--- /dev/null
+++ b/tizen-audio-ucm.c
@@ -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;
+}
+
diff --git a/tizen-audio-util.c b/tizen-audio-util.c
new file mode 100755
index 0000000..d459f36
--- /dev/null
+++ b/tizen-audio-util.c
@@ -0,0 +1,357 @@
+/*
+ * 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>
+#include <pthread.h>
+
+#include "tizen-audio-internal.h"
+
+audio_return_t _audio_util_init (audio_mgr_t *am)
+{
+ 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;
+}
+
+#ifdef __MIXER_PARAM_DUMP
+
+static void __dump_mixer_param(char *dump, long *param, int size)
+{
+ 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)
+{
+ 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 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_value_alloca(&control);
+
+ snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_MIXER);
+ snd_ctl_elem_id_set_name(id, ctl_name);
+
+ snd_ctl_elem_info_set_id(info, id);
+ 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);
+
+ type = snd_ctl_elem_info_get_type(info);
+ count = snd_ctl_elem_info_get_count(info);
+
+ snd_ctl_elem_value_set_id(control, id);
+
+ if(snd_ctl_elem_read(handle, control) < 0) {
+ AUDIO_LOG_ERROR("snd_ctl_elem_read failed \n");
+ goto close;
+ }
+
+ switch (type) {
+ case SND_CTL_ELEM_TYPE_BOOLEAN:
+ *val = snd_ctl_elem_value_get_boolean(control, i);
+ break;
+ case SND_CTL_ELEM_TYPE_INTEGER:
+ 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");
+ goto close;
+ }
+
+ snd_ctl_close(handle);
+
+#ifdef AUDIO_DEBUG
+ AUDIO_LOG_INFO("get mixer(%s) = %d success", ctl_name, *val);
+#endif
+
+ pthread_mutex_unlock(&(am->mixer.mutex));
+ return AUDIO_RET_USE_HW_CONTROL;
+
+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)
+{
+ 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;
+
+ 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_value_alloca(&control);
+
+ snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_MIXER);
+ snd_ctl_elem_id_set_name(id, ctl_name);
+
+ snd_ctl_elem_info_set_id(info, id);
+ 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);
+
+ type = snd_ctl_elem_info_get_type(info);
+ count = snd_ctl_elem_info_get_count(info);
+
+ snd_ctl_elem_value_set_id(control, id);
+
+ 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_boolean(control, i, val);
+ break;
+ case SND_CTL_ELEM_TYPE_INTEGER:
+ 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");
+ 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;
+ }
+
+ /* 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;
+ }
+
+ 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));
+
+ snd_pcm_hw_params_get_channels(hwparams, &channels);
+ sample_spec->channels = (uint8_t)channels;
+ AUDIO_LOG_DEBUG("channels = %d\n", sample_spec->channels);
+
+ 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;
+}
diff --git a/tizen-audio.c b/tizen-audio.c
new file mode 100755
index 0000000..db1638a
--- /dev/null
+++ b/tizen-audio.c
@@ -0,0 +1,125 @@
+/*
+ * 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 "tizen-audio-internal.h"
+
+int audio_get_revision (void)
+{
+ return AUDIO_REVISION;
+}
+
+audio_return_t audio_init (void **userdata, void *platform_data)
+{
+ audio_mgr_t *am;
+ audio_return_t ret = AUDIO_RET_OK;
+
+ if (!(am = malloc(sizeof(audio_mgr_t)))) {
+ 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;
+ }
+ 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_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;
+ }
+
+ *userdata = (void *)am;
+ return AUDIO_RET_OK;
+
+error_exit:
+ if (am)
+ free(am);
+
+ return ret;
+}
+
+audio_return_t audio_deinit (void **userdata)
+{
+ audio_mgr_t *am = (audio_mgr_t *)*userdata;
+
+ if (am) {
+ _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_stream_deinit(am);
+
+ if (AUDIO_IS_ERROR((ret = _audio_stream_init(am)))) {
+ AUDIO_LOG_ERROR("stream init failed");
+ goto error_exit;
+ }
+ }
+
+ return AUDIO_RET_OK;
+
+error_exit:
+ if (am)
+ free(am);
+ *userdata = NULL;
+
+ 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;
+ }
+}
diff --git a/tizen-audio.h b/tizen-audio.h
new file mode 100755
index 0000000..e29a08c
--- /dev/null
+++ b/tizen-audio.h
@@ -0,0 +1,274 @@
+#ifndef footizenaudiofoo
+#define footizenaudiofoo
+
+/*
+ * 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.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+#define AUDIO_REVISION 1
+
+/* Error code */
+
+#define AUDIO_IS_ERROR(ret) (ret < 0)
+
+typedef enum audio_return {
+ AUDIO_RET_OK = 0,
+ AUDIO_RET_USE_HW_CONTROL = (int32_t)0x40001000,
+ AUDIO_ERR_UNDEFINED = (int32_t)0x80001000,
+ 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 ;
+
+
+/* Session */
+typedef enum audio_session {
+ AUDIO_SESSION_MEDIA,
+ AUDIO_SESSION_VOICECALL,
+ AUDIO_SESSION_VIDEOCALL,
+ AUDIO_SESSION_VOIP,
+ AUDIO_SESSION_FMRADIO,
+ AUDIO_SESSION_CAMCORDER,
+ AUDIO_SESSION_NOTIFICATION,
+ AUDIO_SESSION_ALARM,
+ AUDIO_SESSION_EMERGENCY,
+ AUDIO_SESSION_VOICE_RECOGNITION,
+ AUDIO_SESSION_MAX
+} audio_session_t;
+
+/* Sub session */
+typedef enum audio_subsession {
+ AUDIO_SUBSESSION_NONE,
+ AUDIO_SUBSESSION_VOICE,
+ AUDIO_SUBSESSION_RINGTONE,
+ AUDIO_SUBSESSION_MEDIA,
+ AUDIO_SUBSESSION_INIT,
+ AUDIO_SUBSESSION_VR_NORMAL,
+ AUDIO_SUBSESSION_VR_DRIVE,
+ AUDIO_SUBSESSION_STEREO_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 {
+ AUDIO_DIRECTION_NONE,
+ AUDIO_DIRECTION_IN, /**< Capture */
+ AUDIO_DIRECTION_OUT, /**< Playback */
+} audio_direction_t;
+
+
+/* Device */
+
+typedef enum audio_device_in {
+ AUDIO_DEVICE_IN_NONE,
+ AUDIO_DEVICE_IN_MIC, /**< Device builtin mic. */
+ AUDIO_DEVICE_IN_WIRED_ACCESSORY, /**< Wired input devices */
+ AUDIO_DEVICE_IN_BT_SCO, /**< Bluetooth SCO device */
+ AUDIO_DEVICE_IN_MAX,
+} audio_device_in_t;
+
+typedef enum audio_device_out {
+ AUDIO_DEVICE_OUT_NONE,
+ AUDIO_DEVICE_OUT_SPEAKER, /**< Device builtin speaker */
+ AUDIO_DEVICE_OUT_RECEIVER, /**< Device builtin receiver */
+ AUDIO_DEVICE_OUT_WIRED_ACCESSORY, /**< Wired output devices such as headphone, headset, and so on. */
+ AUDIO_DEVICE_OUT_BT_SCO, /**< Bluetooth SCO device */
+ AUDIO_DEVICE_OUT_BT_A2DP, /**< Bluetooth A2DP device */
+ AUDIO_DEVICE_OUT_DOCK, /**< DOCK device */
+ AUDIO_DEVICE_OUT_HDMI, /**< HDMI device */
+ AUDIO_DEVICE_OUT_MIRRORING, /**< MIRRORING device */
+ AUDIO_DEVICE_OUT_USB_AUDIO, /**< USB Audio device */
+ AUDIO_DEVICE_OUT_MULTIMEDIA_DOCK, /**< Multimedia DOCK device */
+ AUDIO_DEVICE_OUT_MAX,
+} audio_device_out_t;
+
+typedef enum audio_route_flag {
+ AUDIO_ROUTE_FLAG_NONE = 0,
+ 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_UNKNOWN,
+ AUDIO_DEVICE_API_ALSA,
+ 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_bluz_info {
+ char *protocol;
+ uint32_t nrec;
+} audio_device_bluez_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_device_info_t;
+
+
+/* Stream */
+
+typedef enum audio_volume {
+ AUDIO_VOLUME_TYPE_SYSTEM, /**< System volume type */
+ AUDIO_VOLUME_TYPE_NOTIFICATION, /**< Notification volume type */
+ AUDIO_VOLUME_TYPE_ALARM, /**< Alarm volume type */
+ AUDIO_VOLUME_TYPE_RINGTONE, /**< Ringtone volume type */
+ AUDIO_VOLUME_TYPE_MEDIA, /**< Media volume type */
+ AUDIO_VOLUME_TYPE_CALL, /**< Call volume type */
+ AUDIO_VOLUME_TYPE_VOIP, /**< VOIP volume type */
+ AUDIO_VOLUME_TYPE_VOICE, /**< Voice volume type */
+ AUDIO_VOLUME_TYPE_FIXED, /**< Volume type for fixed acoustic level */
+ AUDIO_VOLUME_TYPE_MAX, /**< Volume type count */
+} audio_volume_t;
+
+typedef enum audio_gain {
+ AUDIO_GAIN_TYPE_DEFAULT,
+ AUDIO_GAIN_TYPE_DIALER,
+ AUDIO_GAIN_TYPE_TOUCH,
+ AUDIO_GAIN_TYPE_AF,
+ AUDIO_GAIN_TYPE_SHUTTER1,
+ AUDIO_GAIN_TYPE_SHUTTER2,
+ AUDIO_GAIN_TYPE_CAMCODING,
+ AUDIO_GAIN_TYPE_MIDI,
+ AUDIO_GAIN_TYPE_BOOTING,
+ AUDIO_GAIN_TYPE_VIDEO,
+ AUDIO_GAIN_TYPE_TTS,
+ AUDIO_GAIN_TYPE_MAX,
+} audio_gain_t;
+
+typedef struct audio_stream_info {
+ char *name;
+ uint32_t samplerate;
+ uint8_t channels;
+ uint32_t volume_type;
+ uint32_t gain_type;
+} audio_stream_info_t ;
+
+
+/* Overall */
+
+typedef struct audio_info {
+ audio_device_info_t device;
+ 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, 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, 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_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