From ae5fbd4017a6ea86320716ca35f366b403c63cb0 Mon Sep 17 00:00:00 2001 From: Hackseung Date: Fri, 23 Jun 2017 13:24:06 +0900 Subject: [PATCH 02/15] Initialization audio HAL for BCM2837 Target board is the Raspberry PI 3 Model B Codes are based on audio-hal-alc5658(0.2.24) Change-Id: I0e81a2e71e820a2a23eecb69a92cebfb6d28b8a1 --- LICENSE.Apache-2.0 | 202 ++++++++++ Makefile.am | 21 ++ NOTICE | 3 + audio-hal-bcm2837.manifest | 5 + autogen.sh | 10 + configure.ac | 60 +++ packaging/audio-hal-bcm2837.spec | 50 +++ tizen-audio-impl-ctrl.c | 251 +++++++++++++ tizen-audio-impl-pcm.c | 771 +++++++++++++++++++++++++++++++++++++++ tizen-audio-impl-ucm.c | 651 +++++++++++++++++++++++++++++++++ tizen-audio-impl.h | 57 +++ tizen-audio-internal.h | 276 ++++++++++++++ tizen-audio-pcm.c | 203 +++++++++++ tizen-audio-routing.c | 336 +++++++++++++++++ tizen-audio-stream.c | 54 +++ tizen-audio-util.c | 80 ++++ tizen-audio-volume.c | 403 ++++++++++++++++++++ tizen-audio.c | 78 ++++ tizen-audio.h | 483 ++++++++++++++++++++++++ 19 files changed, 3994 insertions(+) create mode 100644 LICENSE.Apache-2.0 create mode 100644 Makefile.am create mode 100644 NOTICE create mode 100644 audio-hal-bcm2837.manifest create mode 100755 autogen.sh create mode 100644 configure.ac create mode 100644 packaging/audio-hal-bcm2837.spec create mode 100644 tizen-audio-impl-ctrl.c create mode 100644 tizen-audio-impl-pcm.c create mode 100644 tizen-audio-impl-ucm.c create mode 100644 tizen-audio-impl.h create mode 100644 tizen-audio-internal.h create mode 100644 tizen-audio-pcm.c create mode 100644 tizen-audio-routing.c create mode 100644 tizen-audio-stream.c create mode 100644 tizen-audio-util.c create mode 100644 tizen-audio-volume.c create mode 100644 tizen-audio.c create mode 100644 tizen-audio.h diff --git a/LICENSE.Apache-2.0 b/LICENSE.Apache-2.0 new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/LICENSE.Apache-2.0 @@ -0,0 +1,202 @@ + + 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 100644 index 0000000..2543080 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,21 @@ +lib_LTLIBRARIES = libtizen-audio.la + +libtizen_audio_la_SOURCES = tizen-audio.c \ + tizen-audio-volume.c \ + tizen-audio-routing.c \ + tizen-audio-stream.c \ + tizen-audio-pcm.c \ + tizen-audio-util.c \ + tizen-audio-impl-pcm.c \ + tizen-audio-impl-ucm.c \ + tizen-audio-impl-ctrl.c +libtizen_audio_la_LDFLAGS = $(AM_LDFLAGS) -disable-static -avoid-version +if USE_TINYALSA +libtizen_audio_la_LIBADD = $(AM_LDADD) $(ASOUNDLIB_LIBS) $(TINYALSA_LIBS) $(VCONF_LIBS) $(DLOG_LIBS) $(INIPARSER_LIBS) +libtizen_audio_la_CFLAGS = $(AM_CFLAGS) $(ASOUNDLIB_CFLAGS) $(TINYALSA_CFLAGS) $(VCONF_CFLAGS) $(DLOG_CFLAGS) $(INIPARSER_CFLAGS) -D__USE_TINYALSA__ +else +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) +endif +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/audio-hal-bcm2837.manifest b/audio-hal-bcm2837.manifest new file mode 100644 index 0000000..86dbb26 --- /dev/null +++ b/audio-hal-bcm2837.manifest @@ -0,0 +1,5 @@ + + + + + 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 100644 index 0000000..5f221f2 --- /dev/null +++ b/configure.ac @@ -0,0 +1,60 @@ +AC_PREREQ([2.67]) + +AC_INIT([audio-hal-bcm2837], [0.1]) +AM_INIT_AUTOMAKE([-Wall -Werror foreign]) +AC_CONFIG_HEADERS([config.h]) + +AC_CONFIG_MACRO_DIR([m4]) + +# Checks for programs. +m4_pattern_allow([AM_PROG_AR]) +AM_PROG_AR +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) + +if test $USE_TINYALSA = "1"; then +PKG_CHECK_MODULES(TINYALSA, tinyalsa) +AC_SUBST(TINYALSA_CFLAGS) +AC_SUBST(TINYALSA_LIBS) +AM_CONDITIONAL(USE_TINYALSA, true) +else +AM_CONDITIONAL(USE_TINYALSA, false) +fi + +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-bcm2837.spec b/packaging/audio-hal-bcm2837.spec new file mode 100644 index 0000000..b011c08 --- /dev/null +++ b/packaging/audio-hal-bcm2837.spec @@ -0,0 +1,50 @@ +Name: audio-hal-bcm2837 +Summary: TIZEN Audio HAL for BCM2837 +Version: 0.1.0 +Release: 0 +Group: System/Libraries +License: Apache-2.0 +URL: http://tizen.org +Source0: audio-hal-bcm2837-%{version}.tar.gz +BuildRequires: pkgconfig(vconf) +BuildRequires: pkgconfig(iniparser) +BuildRequires: pkgconfig(dlog) +BuildRequires: pkgconfig(alsa) +#BuildRequires: pkgconfig(tinyalsa) +Provides: libtizen-audio.so + +%description +TIZEN Audio HAL for BCM2837 + +%prep +%setup -q -n %{name}-%{version} + +%build +export CFLAGS="$CFLAGS -DTIZEN_DEBUG_ENABLE -DSYSCONFDIR=\\\"%{_sysconfdir}\\\"" +export CXXFLAGS="$CXXFLAGS -DTIZEN_DEBUG_ENABLE" +export FFLAGS="$FFLAGS -DTIZEN_DEBUG_ENABLE" + +export USE_TINYALSA="0" + +%autogen +%configure + +make %{?jobs:-j%jobs} + +%install +rm -rf %{buildroot} +mkdir -p %{buildroot}%{_datadir}/license +cp LICENSE.Apache-2.0 %{buildroot}%{_datadir}/license/%{name} +%make_install + +%post +/sbin/ldconfig + +%postun +/sbin/ldconfig + +%files +%manifest audio-hal-bcm2837.manifest +%defattr(-,root,root,-) +%{_libdir}/libtizen-audio.so +%{_datadir}/license/%{name} diff --git a/tizen-audio-impl-ctrl.c b/tizen-audio-impl-ctrl.c new file mode 100644 index 0000000..253eaab --- /dev/null +++ b/tizen-audio-impl-ctrl.c @@ -0,0 +1,251 @@ +/* + * audio-hal + * + * Copyright (c) 2016 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 +#endif + +#include +#include +#include +#include + +#include "tizen-audio-internal.h" + +#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 _control_init(audio_hal_t *ah) +{ + AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); + + pthread_mutex_init(&(ah->mixer.mutex), NULL); + return AUDIO_RET_OK; +} + +audio_return_t _control_deinit(audio_hal_t *ah) +{ + AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); + + pthread_mutex_destroy(&(ah->mixer.mutex)); + return AUDIO_RET_OK; +} + +audio_return_t _mixer_control_set_param(audio_hal_t *ah, const char* ctl_name, snd_ctl_elem_value_t* param, int size) +{ + AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); + + /* TODO. */ + return AUDIO_RET_OK; +} + +audio_return_t _mixer_control_get_value(audio_hal_t *ah, 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; + + AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); + + pthread_mutex_lock(&(ah->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(&(ah->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(&(ah->mixer.mutex)); + return AUDIO_RET_OK; + +close: + AUDIO_LOG_ERROR("Error\n"); + snd_ctl_close(handle); + pthread_mutex_unlock(&(ah->mixer.mutex)); + return AUDIO_ERR_UNDEFINED; +} + +audio_return_t _mixer_control_set_value(audio_hal_t *ah, 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; + + AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(ctl_name, AUDIO_ERR_PARAMETER); + + pthread_mutex_lock(&(ah->mixer.mutex)); + + ret = snd_ctl_open(&handle, ALSA_DEFAULT_CARD, 0); + if (ret < 0) { + AUDIO_LOG_ERROR("snd_ctl_open error, card: %s: %s", ALSA_DEFAULT_CARD, snd_strerror(ret)); + pthread_mutex_unlock(&(ah->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(&(ah->mixer.mutex)); + return AUDIO_RET_OK; + +close: + AUDIO_LOG_ERROR("Error"); + snd_ctl_close(handle); + pthread_mutex_unlock(&(ah->mixer.mutex)); + return AUDIO_ERR_UNDEFINED; +} + +audio_return_t _mixer_control_set_value_string(audio_hal_t *ah, const char* ctl_name, const char* value) +{ + AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(ctl_name, AUDIO_ERR_PARAMETER); + + /* TODO. */ + return AUDIO_RET_OK; +} + + +audio_return_t _mixer_control_get_element(audio_hal_t *ah, const char *ctl_name, snd_hctl_elem_t **elem) +{ + AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(ctl_name, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(elem, AUDIO_ERR_PARAMETER); + + /* TODO. */ + return AUDIO_RET_OK; +} \ No newline at end of file diff --git a/tizen-audio-impl-pcm.c b/tizen-audio-impl-pcm.c new file mode 100644 index 0000000..e6327ea --- /dev/null +++ b/tizen-audio-impl-pcm.c @@ -0,0 +1,771 @@ +/* + * audio-hal + * + * Copyright (c) 2016 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 +#endif + +#include +#include +#include +#include + +#include "tizen-audio-internal.h" +#include "tizen-audio-impl.h" + +#ifdef __USE_TINYALSA__ +/* Convert pcm format from pulse to alsa */ +static const uint32_t g_format_convert_table[] = { + [AUDIO_SAMPLE_U8] = PCM_FORMAT_S8, + [AUDIO_SAMPLE_S16LE] = PCM_FORMAT_S16_LE, + [AUDIO_SAMPLE_S32LE] = PCM_FORMAT_S32_LE, + [AUDIO_SAMPLE_S24_32LE] = PCM_FORMAT_S24_LE +}; +#else /* alsa-lib */ +/* FIXME : To avoid build warning... */ +int _snd_pcm_poll_descriptor(snd_pcm_t *pcm); +/* Convert pcm format from pulse to alsa */ +static const uint32_t g_format_convert_table[] = { + [AUDIO_SAMPLE_U8] = SND_PCM_FORMAT_U8, + [AUDIO_SAMPLE_ALAW] = SND_PCM_FORMAT_A_LAW, + [AUDIO_SAMPLE_ULAW] = SND_PCM_FORMAT_MU_LAW, + [AUDIO_SAMPLE_S16LE] = SND_PCM_FORMAT_S16_LE, + [AUDIO_SAMPLE_S16BE] = SND_PCM_FORMAT_S16_BE, + [AUDIO_SAMPLE_FLOAT32LE] = SND_PCM_FORMAT_FLOAT_LE, + [AUDIO_SAMPLE_FLOAT32BE] = SND_PCM_FORMAT_FLOAT_BE, + [AUDIO_SAMPLE_S32LE] = SND_PCM_FORMAT_S32_LE, + [AUDIO_SAMPLE_S32BE] = SND_PCM_FORMAT_S32_BE, + [AUDIO_SAMPLE_S24LE] = SND_PCM_FORMAT_S24_3LE, + [AUDIO_SAMPLE_S24BE] = SND_PCM_FORMAT_S24_3BE, + [AUDIO_SAMPLE_S24_32LE] = SND_PCM_FORMAT_S24_LE, + [AUDIO_SAMPLE_S24_32BE] = SND_PCM_FORMAT_S24_BE +}; +#endif + +static uint32_t __convert_format(audio_sample_format_t format) +{ + return g_format_convert_table[format]; +} + +/* #define DEBUG_TIMING */ + +#ifdef __USE_TINYALSA__ +static struct pcm *__tinyalsa_open_device(audio_pcm_sample_spec_t *ss, size_t period_size, size_t period_count, uint32_t direction) +{ + struct pcm *pcm = NULL; + struct pcm_config config; + + AUDIO_RETURN_NULL_IF_FAIL(ss); + + config.channels = ss->channels; + config.rate = ss->rate; + config.period_size = period_size; + config.period_count = period_count; + config.format = ss->format; + config.start_threshold = period_size; + config.stop_threshold = 0xFFFFFFFF; + config.silence_threshold = 0; + + AUDIO_LOG_INFO("direction %d, channels %d, rate %d, format %d, period_size %d, period_count %d", direction, ss->channels, ss->rate, ss->format, period_size, period_count); + + pcm = pcm_open((direction == AUDIO_DIRECTION_OUT) ? PLAYBACK_CARD_ID : CAPTURE_CARD_ID, + (direction == AUDIO_DIRECTION_OUT) ? PLAYBACK_PCM_DEVICE_ID : CAPTURE_PCM_DEVICE_ID, + (direction == AUDIO_DIRECTION_OUT) ? PCM_OUT : PCM_IN, + &config); + if (!pcm || !pcm_is_ready(pcm)) { + AUDIO_LOG_ERROR("Unable to open device (%s)", pcm_get_error(pcm)); + pcm_close(pcm); + return NULL; + } + + return pcm; +} + +static int __tinyalsa_pcm_recover(struct pcm *pcm, int err) +{ + if (err > 0) + err = -err; + if (err == -EINTR) /* nothing to do, continue */ + return 0; + if (err == -EPIPE) { + AUDIO_LOG_INFO("XRUN occurred"); + err = pcm_prepare(pcm); + if (err < 0) { + AUDIO_LOG_ERROR("Could not recover from XRUN occurred, prepare failed : %d", err); + return err; + } + return 0; + } + if (err == -ESTRPIPE) { + /* tinyalsa does not support pcm resume, dont't care suspend case */ + AUDIO_LOG_ERROR("Could not recover from suspend : %d", err); + return err; + } + return err; +} +#endif + +audio_return_t _pcm_open(void **pcm_handle, uint32_t direction, void *sample_spec, uint32_t period_size, uint32_t periods) +{ +#ifdef __USE_TINYALSA__ + audio_pcm_sample_spec_t *ss; + int err; + + ss = (audio_pcm_sample_spec_t *)sample_spec; + ss->format = __convert_format((audio_sample_format_t)ss->format); + + *pcm_handle = __tinyalsa_open_device(ss, (size_t)period_size, (size_t)periods, direction); + if (*pcm_handle == NULL) { + AUDIO_LOG_ERROR("Error opening PCM device"); + return AUDIO_ERR_RESOURCE; + } + + if ((err = pcm_prepare((struct pcm *)*pcm_handle)) != 0) { + AUDIO_LOG_ERROR("Error prepare PCM device : %d", err); + } + +#else /* alsa-lib */ + int err, mode; + char *device_name = NULL; + + mode = SND_PCM_NONBLOCK | SND_PCM_NO_AUTO_RESAMPLE | SND_PCM_NO_AUTO_CHANNELS | SND_PCM_NO_AUTO_FORMAT; + + if (direction == AUDIO_DIRECTION_OUT) + device_name = PLAYBACK_PCM_DEVICE; + else if (direction == AUDIO_DIRECTION_IN) + device_name = CAPTURE_PCM_DEVICE; + else { + AUDIO_LOG_ERROR("Error get device_name, direction : %d", direction); + return AUDIO_ERR_RESOURCE; + } + + 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)); + return AUDIO_ERR_RESOURCE; + } + + if ((err = _pcm_set_params(*pcm_handle, direction, sample_spec, period_size, periods)) != AUDIO_RET_OK) { + AUDIO_LOG_ERROR("Failed to set pcm parameters : %d", err); + return err; + } + + AUDIO_LOG_INFO("PCM device %s", device_name); +#endif + + return AUDIO_RET_OK; +} + +audio_return_t _pcm_start(void *pcm_handle) +{ + int err; + +#ifdef __USE_TINYALSA__ + if ((err = pcm_start(pcm_handle)) < 0) { + AUDIO_LOG_ERROR("Error starting PCM handle : %d", err); + return AUDIO_ERR_RESOURCE; + } +#else /* alsa-lib */ + if ((err = snd_pcm_start(pcm_handle)) < 0) { + AUDIO_LOG_ERROR("Error starting PCM handle : %s", snd_strerror(err)); + return AUDIO_ERR_RESOURCE; + } +#endif + + AUDIO_LOG_INFO("PCM handle 0x%x start", pcm_handle); + return AUDIO_RET_OK; +} + +audio_return_t _pcm_stop(void *pcm_handle) +{ + int err; + +#ifdef __USE_TINYALSA__ + if ((err = pcm_stop(pcm_handle)) < 0) { + AUDIO_LOG_ERROR("Error stopping PCM handle : %d", err); + return AUDIO_ERR_RESOURCE; + } +#else /* alsa-lib */ + if ((err = snd_pcm_drop(pcm_handle)) < 0) { + AUDIO_LOG_ERROR("Error stopping PCM handle : %s", snd_strerror(err)); + return AUDIO_ERR_RESOURCE; + } +#endif + + AUDIO_LOG_INFO("PCM handle 0x%x stop", pcm_handle); + return AUDIO_RET_OK; +} + +audio_return_t _pcm_close(void *pcm_handle) +{ + int err; + + AUDIO_LOG_INFO("Try to close PCM handle 0x%x", pcm_handle); + +#ifdef __USE_TINYALSA__ + if ((err = pcm_close(pcm_handle)) < 0) { + AUDIO_LOG_ERROR("Error closing PCM handle : %d", err); + return AUDIO_ERR_RESOURCE; + } +#else /* alsa-lib */ + if ((err = snd_pcm_close(pcm_handle)) < 0) { + AUDIO_LOG_ERROR("Error closing PCM handle : %s", snd_strerror(err)); + return AUDIO_ERR_RESOURCE; + } +#endif + + return AUDIO_RET_OK; +} + +audio_return_t _pcm_avail(void *pcm_handle, uint32_t *avail) +{ +#ifdef __USE_TINYALSA__ + struct timespec tspec; + unsigned int frames_avail = 0; + int err; + + err = pcm_get_htimestamp(pcm_handle, &frames_avail, &tspec); + if (err < 0) { + AUDIO_LOG_ERROR("Could not get avail and timespec at PCM handle 0x%x : %d", pcm_handle, err); + return AUDIO_ERR_IOCTL; + } + +#ifdef DEBUG_TIMING + AUDIO_LOG_DEBUG("avail = %d", frames_avail); +#endif + + *avail = (uint32_t)frames_avail; +#else /* alsa-lib */ + snd_pcm_sframes_t frames_avail; + + if ((frames_avail = snd_pcm_avail(pcm_handle)) < 0) { + AUDIO_LOG_ERROR("Could not get avail at PCM handle 0x%x : %d", pcm_handle, frames_avail); + return AUDIO_ERR_IOCTL; + } + +#ifdef DEBUG_TIMING + AUDIO_LOG_DEBUG("avail = %d", frames_avail); +#endif + + *avail = (uint32_t)frames_avail; +#endif + + return AUDIO_RET_OK; +} + +audio_return_t _pcm_write(void *pcm_handle, const void *buffer, uint32_t frames) +{ +#ifdef __USE_TINYALSA__ + int err; + + err = pcm_write(pcm_handle, buffer, pcm_frames_to_bytes(pcm_handle, (unsigned int)frames)); + if (err < 0) { + AUDIO_LOG_ERROR("Failed to write pcm : %d", err); + return AUDIO_ERR_IOCTL; + } + +#ifdef DEBUG_TIMING + AUDIO_LOG_DEBUG("_pcm_write = %d", frames); +#endif +#else /* alsa-lib */ + snd_pcm_sframes_t frames_written; + + AUDIO_RETURN_VAL_IF_FAIL(pcm_handle, AUDIO_ERR_PARAMETER); + + frames_written = snd_pcm_writei(pcm_handle, buffer, (snd_pcm_uframes_t) frames); + if (frames_written < 0) { + AUDIO_LOG_ERROR("Failed to write pcm : %d", frames_written); + return AUDIO_ERR_IOCTL; + } + +#ifdef DEBUG_TIMING + AUDIO_LOG_DEBUG("_pcm_write = (%d / %d)", frames_written, frames); +#endif +#endif + + return AUDIO_RET_OK; +} + +audio_return_t _pcm_read(void *pcm_handle, void *buffer, uint32_t frames) +{ +#ifdef __USE_TINYALSA__ + int err; + + err = pcm_read(pcm_handle, buffer, pcm_frames_to_bytes(pcm_handle, (unsigned int)frames)); + if (err < 0) { + AUDIO_LOG_ERROR("Failed to read pcm : %d", err); + return AUDIO_ERR_IOCTL; + } + +#ifdef DEBUG_TIMING + AUDIO_LOG_DEBUG("audio_pcm_read = %d", frames); +#endif +#else /* alsa-lib */ + snd_pcm_sframes_t frames_read; + + frames_read = snd_pcm_readi(pcm_handle, buffer, (snd_pcm_uframes_t)frames); + if (frames_read < 0) { + AUDIO_LOG_ERROR("Failed to read pcm : %d", frames_read); + return AUDIO_ERR_IOCTL; + } + +#ifdef DEBUG_TIMING + AUDIO_LOG_DEBUG("_pcm_read = (%d / %d)", frames_read, frames); +#endif +#endif + + return AUDIO_RET_OK; +} + +audio_return_t _pcm_get_fd(void *pcm_handle, int *fd) +{ + /* we use an internal API of the (tiny)alsa library, so it causes warning message during compile */ +#ifdef __USE_TINYALSA__ + *fd = _pcm_poll_descriptor((struct pcm *)pcm_handle); +#else /* alsa-lib */ + *fd = _snd_pcm_poll_descriptor((snd_pcm_t *)pcm_handle); +#endif + return AUDIO_RET_OK; +} + +audio_return_t _pcm_recover(void *pcm_handle, int revents) +{ + int state, err; + + AUDIO_RETURN_VAL_IF_FAIL(pcm_handle, AUDIO_ERR_PARAMETER); + + if (revents & POLLERR) + AUDIO_LOG_DEBUG("Got POLLERR from ALSA"); + if (revents & POLLNVAL) + AUDIO_LOG_DEBUG("Got POLLNVAL from ALSA"); + if (revents & POLLHUP) + AUDIO_LOG_DEBUG("Got POLLHUP from ALSA"); + if (revents & POLLPRI) + AUDIO_LOG_DEBUG("Got POLLPRI from ALSA"); + if (revents & POLLIN) + AUDIO_LOG_DEBUG("Got POLLIN from ALSA"); + if (revents & POLLOUT) + AUDIO_LOG_DEBUG("Got POLLOUT from ALSA"); + +#ifdef __USE_TINYALSA__ + state = pcm_state(pcm_handle); + AUDIO_LOG_DEBUG("PCM state is %d", state); + + switch (state) { + case PCM_STATE_XRUN: + if ((err = __tinyalsa_pcm_recover(pcm_handle, -EPIPE)) != 0) { + AUDIO_LOG_ERROR("Could not recover from POLLERR|POLLNVAL|POLLHUP and XRUN : %d", err); + return AUDIO_ERR_IOCTL; + } + break; + + case PCM_STATE_SUSPENDED: + if ((err = __tinyalsa_pcm_recover(pcm_handle, -ESTRPIPE)) != 0) { + AUDIO_LOG_ERROR("Could not recover from POLLERR|POLLNVAL|POLLHUP and SUSPENDED : %d", err); + return AUDIO_ERR_IOCTL; + } + break; + + default: + pcm_stop(pcm_handle); + if ((err = pcm_prepare(pcm_handle)) < 0) { + AUDIO_LOG_ERROR("Could not recover from POLLERR|POLLNVAL|POLLHUP with pcm_prepare() : %d", err); + return AUDIO_ERR_IOCTL; + } + } +#else /* alsa-lib */ + state = snd_pcm_state(pcm_handle); + AUDIO_LOG_DEBUG("PCM state is %s", snd_pcm_state_name(state)); + + /* Try to recover from this error */ + + switch (state) { + case SND_PCM_STATE_XRUN: + if ((err = snd_pcm_recover(pcm_handle, -EPIPE, 1)) != 0) { + AUDIO_LOG_ERROR("Could not recover from POLLERR|POLLNVAL|POLLHUP and XRUN : %d", err); + return AUDIO_ERR_IOCTL; + } + break; + + case SND_PCM_STATE_SUSPENDED: + if ((err = snd_pcm_recover(pcm_handle, -ESTRPIPE, 1)) != 0) { + AUDIO_LOG_ERROR("Could not recover from POLLERR|POLLNVAL|POLLHUP and SUSPENDED : %d", err); + return AUDIO_ERR_IOCTL; + } + break; + + default: + snd_pcm_drop(pcm_handle); + if ((err = snd_pcm_prepare(pcm_handle)) < 0) { + AUDIO_LOG_ERROR("Could not recover from POLLERR|POLLNVAL|POLLHUP with snd_pcm_prepare() : %d", err); + return AUDIO_ERR_IOCTL; + } + break; + } +#endif + + AUDIO_LOG_DEBUG("_pcm_recover"); + return AUDIO_RET_OK; +} + +audio_return_t _pcm_get_params(void *pcm_handle, uint32_t direction, void **sample_spec, uint32_t *period_size, uint32_t *periods) +{ +#ifdef __USE_TINYALSA__ + audio_pcm_sample_spec_t *ss; + unsigned int _period_size, _buffer_size, _periods, _format, _rate, _channels; + unsigned int _start_threshold, _stop_threshold, _silence_threshold; + struct pcm_config *config; + + ss = (audio_pcm_sample_spec_t *)*sample_spec; + + /* we use an internal API of the tiny alsa library, so it causes warning message during compile */ + _pcm_config(pcm_handle, &config); + + *period_size = config->period_size; + *periods = config->period_count; + _buffer_size = config->period_size * config->period_count; + ss->format = config->format; + ss->rate = config->rate; + ss->channels = config->channels; + _start_threshold = config->start_threshold; + _stop_threshold = config->stop_threshold; + _silence_threshold = config->silence_threshold; + + AUDIO_LOG_DEBUG("_pcm_get_params (handle 0x%x, format %d, rate %d, channels %d, period_size %d, periods %d, buffer_size %d)", pcm_handle, config->format, config->rate, config->channels, config->period_size, config->period_count, _buffer_size); +#else /* alsa-lib */ + int err; + audio_pcm_sample_spec_t *ss; + int dir; + snd_pcm_uframes_t _period_size, _buffer_size; + snd_pcm_format_t _format; + unsigned int _rate, _channels; + snd_pcm_uframes_t _start_threshold, _stop_threshold, _silence_threshold, _avail_min; + unsigned int _periods; + snd_pcm_hw_params_t *hwparams; + snd_pcm_sw_params_t *swparams; + + ss = (audio_pcm_sample_spec_t *)*sample_spec; + + snd_pcm_hw_params_alloca(&hwparams); + snd_pcm_sw_params_alloca(&swparams); + + if ((err = snd_pcm_hw_params_current(pcm_handle, hwparams)) < 0) { + AUDIO_LOG_ERROR("snd_pcm_hw_params_current() failed : %d", err); + return AUDIO_ERR_PARAMETER; + } + + if ((err = snd_pcm_hw_params_get_period_size(hwparams, &_period_size, &dir)) < 0 || + (err = snd_pcm_hw_params_get_buffer_size(hwparams, &_buffer_size)) < 0 || + (err = snd_pcm_hw_params_get_periods(hwparams, &_periods, &dir)) < 0 || + (err = snd_pcm_hw_params_get_format(hwparams, &_format)) < 0 || + (err = snd_pcm_hw_params_get_rate(hwparams, &_rate, &dir)) < 0 || + (err = snd_pcm_hw_params_get_channels(hwparams, &_channels)) < 0) { + AUDIO_LOG_ERROR("snd_pcm_hw_params_get_{period_size|buffer_size|periods|format|rate|channels}() failed : %s", err); + return AUDIO_ERR_PARAMETER; + } + + *period_size = _period_size; + *periods = _periods; + ss->format = _format; + ss->rate = _rate; + ss->channels = _channels; + + if ((err = snd_pcm_sw_params_current(pcm_handle, swparams)) < 0) { + AUDIO_LOG_ERROR("snd_pcm_sw_params_current() failed : %d", err); + return AUDIO_ERR_PARAMETER; + } + + if ((err = snd_pcm_sw_params_get_start_threshold(swparams, &_start_threshold)) < 0 || + (err = snd_pcm_sw_params_get_stop_threshold(swparams, &_stop_threshold)) < 0 || + (err = snd_pcm_sw_params_get_silence_threshold(swparams, &_silence_threshold)) < 0 || + (err = snd_pcm_sw_params_get_avail_min(swparams, &_avail_min)) < 0) { + AUDIO_LOG_ERROR("snd_pcm_sw_params_get_{start_threshold|stop_threshold|silence_threshold|avail_min}() failed : %s", err); + } + + AUDIO_LOG_DEBUG("_pcm_get_params (handle 0x%x, format %d, rate %d, channels %d, period_size %d, periods %d, buffer_size %d)", pcm_handle, _format, _rate, _channels, _period_size, _periods, _buffer_size); +#endif + + return AUDIO_RET_OK; +} + +audio_return_t _pcm_set_params(void *pcm_handle, uint32_t direction, void *sample_spec, uint32_t period_size, uint32_t periods) +{ +#ifdef __USE_TINYALSA__ + /* Parameters are only acceptable in pcm_open() function */ + AUDIO_LOG_DEBUG("_pcm_set_params"); +#else /* alsa-lib */ + int err; + audio_pcm_sample_spec_t ss; + snd_pcm_uframes_t _buffer_size; + snd_pcm_hw_params_t *hwparams; + snd_pcm_sw_params_t *swparams; + + ss = *(audio_pcm_sample_spec_t *)sample_spec; + + snd_pcm_hw_params_alloca(&hwparams); + snd_pcm_sw_params_alloca(&swparams); + + /* Set hw params */ + if ((err = snd_pcm_hw_params_any(pcm_handle, hwparams)) < 0) { + AUDIO_LOG_ERROR("snd_pcm_hw_params_any() failed : %d", err); + return AUDIO_ERR_PARAMETER; + } + + if ((err = snd_pcm_hw_params_set_rate_resample(pcm_handle, hwparams, 0)) < 0) { + AUDIO_LOG_ERROR("snd_pcm_hw_params_set_rate_resample() failed : %d", err); + return AUDIO_ERR_PARAMETER; + } + + if ((err = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) { + AUDIO_LOG_ERROR("snd_pcm_hw_params_set_access() failed : %d", err); + return AUDIO_ERR_PARAMETER; + } + + ss.format = __convert_format((audio_sample_format_t)ss.format); + if ((err = snd_pcm_hw_params_set_format(pcm_handle, hwparams, ss.format)) < 0) { + AUDIO_LOG_ERROR("snd_pcm_hw_params_set_format() failed : %d", err); + return AUDIO_ERR_PARAMETER; + } + + if ((err = snd_pcm_hw_params_set_rate(pcm_handle, hwparams, ss.rate, 0)) < 0) { + AUDIO_LOG_ERROR("snd_pcm_hw_params_set_rate() failed : %d", err); + return AUDIO_ERR_PARAMETER; + } + + if ((err = snd_pcm_hw_params_set_channels(pcm_handle, hwparams, ss.channels)) < 0) { + AUDIO_LOG_ERROR("snd_pcm_hw_params_set_channels(%u) failed : %d", err); + return AUDIO_ERR_PARAMETER; + } + + if ((err = snd_pcm_hw_params_set_period_size(pcm_handle, hwparams, period_size, 0)) < 0) { + AUDIO_LOG_ERROR("snd_pcm_hw_params_set_period_size(%u) failed : %d", err); + return AUDIO_ERR_PARAMETER; + } + + if ((err = snd_pcm_hw_params_set_periods(pcm_handle, hwparams, periods, 0)) < 0) { + AUDIO_LOG_ERROR("snd_pcm_hw_params_set_periods(%u) failed : %d", periods, err); + return AUDIO_ERR_PARAMETER; + } + + _buffer_size = period_size * periods; + if ((err = snd_pcm_hw_params_set_buffer_size(pcm_handle, hwparams, _buffer_size)) < 0) { + AUDIO_LOG_ERROR("snd_pcm_hw_params_set_buffer_size(%u) failed : %d", periods * periods, err); + return AUDIO_ERR_PARAMETER; + } + + if ((err = snd_pcm_hw_params(pcm_handle, hwparams)) < 0) { + AUDIO_LOG_ERROR("snd_pcm_hw_params failed : %d", err); + return AUDIO_ERR_IOCTL; + } + + /* Set sw params */ + if ((err = snd_pcm_sw_params_current(pcm_handle, swparams)) < 0) { + AUDIO_LOG_ERROR("Unable to determine current swparams : %d", err); + return AUDIO_ERR_PARAMETER; + } + + if ((err = snd_pcm_sw_params_set_tstamp_mode(pcm_handle, swparams, SND_PCM_TSTAMP_ENABLE)) < 0) { + AUDIO_LOG_ERROR("Unable to enable time stamping : %d", err); + return AUDIO_ERR_PARAMETER; + } + + if ((err = snd_pcm_sw_params_set_stop_threshold(pcm_handle, swparams, 0xFFFFFFFF)) < 0) { + AUDIO_LOG_ERROR("Unable to set stop threshold : %d", err); + return AUDIO_ERR_PARAMETER; + } + + if ((err = snd_pcm_sw_params_set_start_threshold(pcm_handle, swparams, period_size / 2)) < 0) { + AUDIO_LOG_ERROR("Unable to set start threshold : %d", err); + return AUDIO_ERR_PARAMETER; + } + + if ((err = snd_pcm_sw_params_set_avail_min(pcm_handle, swparams, 1024)) < 0) { + AUDIO_LOG_ERROR("snd_pcm_sw_params_set_avail_min() failed : %d", err); + return AUDIO_ERR_PARAMETER; + } + + if ((err = snd_pcm_sw_params(pcm_handle, swparams)) < 0) { + AUDIO_LOG_ERROR("Unable to set sw params : %d", err); + return AUDIO_ERR_IOCTL; + } + + /* Prepare device */ + if ((err = snd_pcm_prepare(pcm_handle)) < 0) { + AUDIO_LOG_ERROR("snd_pcm_prepare() failed : %d", err); + return AUDIO_ERR_IOCTL; + } + + AUDIO_LOG_DEBUG("_pcm_set_params (handle 0x%x, format %d, rate %d, channels %d, period_size %d, periods %d, buffer_size %d)", pcm_handle, ss.format, ss.rate, ss.channels, period_size, periods, _buffer_size); +#endif + + return AUDIO_RET_OK; +} + +/* Generic snd pcm interface APIs */ +audio_return_t _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; + + AUDIO_RETURN_VAL_IF_FAIL(pcm, AUDIO_ERR_PARAMETER); + + 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_DEBUG("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 _pcm_set_sw_params(snd_pcm_t *pcm, snd_pcm_uframes_t avail_min, uint8_t period_event) +{ + snd_pcm_sw_params_t *swparams; + snd_pcm_uframes_t boundary; + int err; + + AUDIO_RETURN_VAL_IF_FAIL(pcm, AUDIO_ERR_PARAMETER); + + snd_pcm_sw_params_alloca(&swparams); + + if ((err = snd_pcm_sw_params_current(pcm, swparams)) < 0) { + AUDIO_LOG_WARN("Unable to determine current swparams: %s\n", snd_strerror(err)); + goto error; + } + if ((err = snd_pcm_sw_params_set_period_event(pcm, swparams, period_event)) < 0) { + AUDIO_LOG_WARN("Unable to disable period event: %s\n", snd_strerror(err)); + goto error; + } + if ((err = snd_pcm_sw_params_set_tstamp_mode(pcm, swparams, SND_PCM_TSTAMP_ENABLE)) < 0) { + AUDIO_LOG_WARN("Unable to enable time stamping: %s\n", snd_strerror(err)); + goto error; + } + if ((err = snd_pcm_sw_params_get_boundary(swparams, &boundary)) < 0) { + AUDIO_LOG_WARN("Unable to get boundary: %s\n", snd_strerror(err)); + goto error; + } + if ((err = snd_pcm_sw_params_set_stop_threshold(pcm, swparams, boundary)) < 0) { + AUDIO_LOG_WARN("Unable to set stop threshold: %s\n", snd_strerror(err)); + goto error; + } + if ((err = snd_pcm_sw_params_set_start_threshold(pcm, swparams, (snd_pcm_uframes_t) avail_min)) < 0) { + AUDIO_LOG_WARN("Unable to set start threshold: %s\n", snd_strerror(err)); + goto error; + } + if ((err = snd_pcm_sw_params_set_avail_min(pcm, swparams, avail_min)) < 0) { + AUDIO_LOG_WARN("snd_pcm_sw_params_set_avail_min() failed: %s", snd_strerror(err)); + goto error; + } + if ((err = snd_pcm_sw_params(pcm, swparams)) < 0) { + AUDIO_LOG_WARN("Unable to set sw params: %s\n", snd_strerror(err)); + goto error; + } + return AUDIO_RET_OK; +error: + return err; +} diff --git a/tizen-audio-impl-ucm.c b/tizen-audio-impl-ucm.c new file mode 100644 index 0000000..1dfe50a --- /dev/null +++ b/tizen-audio-impl-ucm.c @@ -0,0 +1,651 @@ +/* + * audio-hal + * + * Copyright (c) 2015 - 2016 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 +#endif + +#include +#include +#include +#ifdef ALSA_UCM_DEBUG_TIME +#include +#include +#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 + +#define UCM_PREFIX_CURRENT ">>> UCM current" +#define UCM_PREFIX_REQUESTED "> UCM requested" +#define UCM_PREFIX_CHANGED "<<< UCM changed" + +#define DUMP_LEN 512 + +static void __dump_use_case(const char* prefix, const char *verb, const char *devices[], int dev_count, const char *modifiers[], int mod_count) +{ + int i; + dump_data_t* dump = NULL; + + if (!(dump = _audio_dump_new(DUMP_LEN))) { + AUDIO_LOG_ERROR("Failed to create dump string..."); + return; + } + + /* Verb */ + _audio_dump_add_str(dump, "Verb [ %s ] Devices [ ", verb ? verb : AUDIO_USE_CASE_VERB_INACTIVE); + + /* Devices */ + if (devices) { + for (i = 0; i < dev_count; i++) { + _audio_dump_add_str(dump, (i != dev_count - 1) ? "%s, " : "%s", devices[i]); + } + } + _audio_dump_add_str(dump, " ] Modifier [ "); + + /* Modifiers */ + if (modifiers) { + for (i = 0; i < mod_count; i++) { + _audio_dump_add_str(dump, (i != mod_count - 1) ? "%s, " : "%s", modifiers[i]); + } + } + _audio_dump_add_str(dump, " ]"); + + AUDIO_LOG_INFO("TEST %s : %s", prefix, _audio_dump_get_str(dump)); + + _audio_dump_free(dump); +} + +#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 + +audio_return_t _ucm_init(audio_hal_t *ah) +{ + AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); + + snd_use_case_mgr_open(&ah->ucm.uc_mgr, ALSA_DEFAULT_CARD); + + if (!ah->ucm.uc_mgr) { + AUDIO_LOG_ERROR("uc_mgr open failed"); + return AUDIO_ERR_RESOURCE; + } + return AUDIO_RET_OK; +} + +audio_return_t _ucm_deinit(audio_hal_t *ah) +{ + AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(ah->ucm.uc_mgr, AUDIO_ERR_PARAMETER); + + if (ah->ucm.uc_mgr) { + snd_use_case_mgr_close(ah->ucm.uc_mgr); + ah->ucm.uc_mgr = NULL; + } + + return AUDIO_RET_OK; +} + +/* 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 _ucm_set_use_case(audio_hal_t *ah, 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; + + AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(ah->ucm.uc_mgr, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(verb, AUDIO_ERR_PARAMETER); + + snd_use_case_get(ah->ucm.uc_mgr, "_verb", &old_verb); + old_dev_count = snd_use_case_get_list(ah->ucm.uc_mgr, "_enadevs", &old_dev_list); + old_mod_count = snd_use_case_get_list(ah->ucm.uc_mgr, "_enamods", &old_mod_list); + __dump_use_case(UCM_PREFIX_CURRENT, old_verb, old_dev_list, old_dev_count, old_mod_list, old_mod_count); + + 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(UCM_PREFIX_REQUESTED, verb, devices, dev_count, modifiers, mod_count); + + 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(ah->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(ah->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(ah->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(ah->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(ah->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(ah->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(ah->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(ah->ucm.uc_mgr, "_verb", &new_verb); + new_dev_count = snd_use_case_get_list(ah->ucm.uc_mgr, "_enadevs", &new_dev_list); + new_mod_count = snd_use_case_get_list(ah->ucm.uc_mgr, "_enamods", &new_mod_list); + __dump_use_case(UCM_PREFIX_CHANGED, new_verb, new_dev_list, new_dev_count, new_mod_list, new_mod_count); + + 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 _ucm_set_devices(audio_hal_t *ah, const char *verb, const char *devices[]) +{ + audio_return_t audio_ret = AUDIO_RET_OK; + int is_verb_changed = 0, is_dev_changed = 0; + const char *old_verb = NULL, **old_dev_list = NULL; + int old_dev_count = 0, dev_count = 0; + const char **dis_dev_list = NULL, **ena_dev_list = NULL; + int dis_dev_count = 0, ena_dev_count = 0; + int i = 0, j = 0; + + AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(ah->ucm.uc_mgr, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(verb, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(devices, AUDIO_ERR_PARAMETER); + + snd_use_case_get(ah->ucm.uc_mgr, "_verb", &old_verb); + old_dev_count = snd_use_case_get_list(ah->ucm.uc_mgr, "_enadevs", &old_dev_list); + __dump_use_case(UCM_PREFIX_CURRENT, old_verb, old_dev_list, old_dev_count, NULL, 0); + + if (devices) { + for (dev_count = 0; devices[dev_count]; dev_count++); + } + + __dump_use_case(UCM_PREFIX_REQUESTED, verb, devices, dev_count, NULL, 0); + + 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; + } + } + + /* 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]; + } + } + + /* 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(ah->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(ah->ucm.uc_mgr, "_enadev", ena_dev_list[i]) < 0) + AUDIO_LOG_ERROR("enable %s device failed", ena_dev_list[i]); + } + + } else { + is_verb_changed = 1; + + AUDIO_LOG_INFO("Setting new verb: %s", verb); + /* set new verb */ + if (snd_use_case_set(ah->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_INFO("Enable device : %s", devices[i]); + if (snd_use_case_set(ah->ucm.uc_mgr, "_enadev", devices[i]) < 0) + AUDIO_LOG_ERROR("Enable %s device failed", devices[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 (dis_dev_list) + free((void *)dis_dev_list); + if (ena_dev_list) + free((void *)ena_dev_list); + + if (is_verb_changed == 1 || is_dev_changed == 1) { + const char *new_verb = NULL, **new_dev_list = NULL; + int new_dev_count = 0; + + snd_use_case_get(ah->ucm.uc_mgr, "_verb", &new_verb); + new_dev_count = snd_use_case_get_list(ah->ucm.uc_mgr, "_enadevs", &new_dev_list); + __dump_use_case(UCM_PREFIX_CHANGED, new_verb, new_dev_list, new_dev_count, NULL, 0); + + if (new_verb) + free((void *)new_verb); + if (new_dev_list) + snd_use_case_free_list(new_dev_list, new_dev_count); + } + + return audio_ret; + +} + +audio_return_t _ucm_set_modifiers(audio_hal_t *ah, const char *verb, const char *modifiers[]) +{ + audio_return_t audio_ret = AUDIO_RET_OK; + int is_verb_changed = 0, is_mod_changed = 0; + const char *old_verb = NULL, **old_mod_list = NULL; + int old_mod_count = 0, mod_count = 0; + const char **dis_mod_list = NULL, **ena_mod_list = NULL; + int dis_mod_count = 0, ena_mod_count = 0; + int i = 0, j = 0; + + AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(ah->ucm.uc_mgr, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(verb, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(modifiers, AUDIO_ERR_PARAMETER); + + snd_use_case_get(ah->ucm.uc_mgr, "_verb", &old_verb); + old_mod_count = snd_use_case_get_list(ah->ucm.uc_mgr, "_enamods", &old_mod_list); + __dump_use_case(UCM_PREFIX_CURRENT, old_verb, NULL, 0, old_mod_list, old_mod_count); + + if (modifiers) { + for (mod_count = 0; modifiers[mod_count]; mod_count++); + } + + __dump_use_case(UCM_PREFIX_REQUESTED, verb, NULL, 0, modifiers, mod_count); + + 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_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 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(ah->ucm.uc_mgr, "_dismod", dis_mod_list[i]) < 0) + AUDIO_LOG_ERROR("disable %s modifier failed", dis_mod_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(ah->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(ah->ucm.uc_mgr, "_verb", verb) < 0) { + AUDIO_LOG_ERROR("Setting verb %s failed", verb); + audio_ret = AUDIO_ERR_UNDEFINED; + goto exit; + } + /* enable modifiers */ + for (i = 0; i < mod_count; i++) { + AUDIO_LOG_DEBUG("Enable modifier : %s", modifiers[i]); + if (snd_use_case_set(ah->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_mod_list) + snd_use_case_free_list(old_mod_list, old_mod_count); + if (dis_mod_list) + free((void *)dis_mod_list); + if (ena_mod_list) + free((void *)ena_mod_list); + + if (is_verb_changed == 1 || is_mod_changed == 1) { + const char *new_verb = NULL, **new_mod_list = NULL; + int new_mod_count = 0; + + snd_use_case_get(ah->ucm.uc_mgr, "_verb", &new_verb); + new_mod_count = snd_use_case_get_list(ah->ucm.uc_mgr, "_enamods", &new_mod_list); + __dump_use_case(UCM_PREFIX_CHANGED, new_verb, NULL, 0, new_mod_list, new_mod_count); + + if (new_verb) + free((void *)new_verb); + if (new_mod_list) + snd_use_case_free_list(new_mod_list, new_mod_count); + } + + return audio_ret; +} + +audio_return_t _ucm_get_verb(audio_hal_t *ah, const char **value) +{ + audio_return_t ret = AUDIO_RET_OK; + + AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(ah->ucm.uc_mgr, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(value, AUDIO_ERR_PARAMETER); + + if ((ret = snd_use_case_get(ah->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 _ucm_reset_use_case(audio_hal_t *ah) +{ + audio_return_t ret = AUDIO_RET_OK; + + AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(ah->ucm.uc_mgr, AUDIO_ERR_PARAMETER); + + AUDIO_LOG_INFO(">>> UCM reset Verb [ %s ]", AUDIO_USE_CASE_VERB_INACTIVE); + + if ((ret = snd_use_case_set(ah->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; +} \ No newline at end of file diff --git a/tizen-audio-impl.h b/tizen-audio-impl.h new file mode 100644 index 0000000..4287ac8 --- /dev/null +++ b/tizen-audio-impl.h @@ -0,0 +1,57 @@ +#ifndef footizenaudioimplfoo +#define footizenaudioimplfoo + +/* + * audio-hal + * + * Copyright (c) 2016 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. + * + */ + +/* PCM */ +audio_return_t _pcm_open(void **pcm_handle, uint32_t direction, void *sample_spec, uint32_t period_size, uint32_t periods); +audio_return_t _pcm_start(void *pcm_handle); +audio_return_t _pcm_stop(void *pcm_handle); +audio_return_t _pcm_close(void *pcm_handle); +audio_return_t _pcm_avail(void *pcm_handle, uint32_t *avail); +audio_return_t _pcm_write(void *pcm_handle, const void *buffer, uint32_t frames); +audio_return_t _pcm_read(void *pcm_handle, void *buffer, uint32_t frames); +audio_return_t _pcm_get_fd(void *pcm_handle, int *fd); +audio_return_t _pcm_recover(void *pcm_handle, int revents); +audio_return_t _pcm_get_params(void *pcm_handle, uint32_t direction, void **sample_spec, uint32_t *period_size, uint32_t *periods); +audio_return_t _pcm_set_params(void *pcm_handle, uint32_t direction, void *sample_spec, uint32_t period_size, uint32_t periods); +audio_return_t _pcm_set_sw_params(snd_pcm_t *pcm, snd_pcm_uframes_t avail_min, uint8_t period_event); +audio_return_t _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); + +/* Control */ +audio_return_t _control_init(audio_hal_t *ah); +audio_return_t _control_deinit(audio_hal_t *ah); +audio_return_t _mixer_control_set_param(audio_hal_t *ah, const char* ctl_name, snd_ctl_elem_value_t* value, int size); +audio_return_t _mixer_control_set_value(audio_hal_t *ah, const char *ctl_name, int val); +audio_return_t _mixer_control_set_value_string(audio_hal_t *ah, const char* ctl_name, const char* value); +audio_return_t _mixer_control_get_value(audio_hal_t *ah, const char *ctl_name, int *val); +audio_return_t _mixer_control_get_element(audio_hal_t *ah, const char *ctl_name, snd_hctl_elem_t **elem); + +/* UCM */ +audio_return_t _ucm_init(audio_hal_t *ah); +audio_return_t _ucm_deinit(audio_hal_t *ah); +#define _ucm_update_use_case _ucm_set_use_case +audio_return_t _ucm_set_use_case(audio_hal_t *ah, const char *verb, const char *devices[], const char *modifiers[]); +audio_return_t _ucm_set_devices(audio_hal_t *ah, const char *verb, const char *devices[]); +audio_return_t _ucm_set_modifiers(audio_hal_t *ah, const char *verb, const char *modifiers[]); +audio_return_t _ucm_get_verb(audio_hal_t *ah, const char **value); +audio_return_t _ucm_reset_use_case(audio_hal_t *ah); + +#endif diff --git a/tizen-audio-internal.h b/tizen-audio-internal.h new file mode 100644 index 0000000..81d570b --- /dev/null +++ b/tizen-audio-internal.h @@ -0,0 +1,276 @@ +#ifndef footizenaudiointernalfoo +#define footizenaudiointernalfoo + +/* + * audio-hal + * + * Copyright (c) 2015 - 2016 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 +#include +#include +#include +#ifdef __USE_TINYALSA__ +#include +#endif +#include +#include +#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) +#define AUDIO_RETURN_NULL_IF_FAIL(expr) do { \ + if (!expr) { \ + AUDIO_LOG_ERROR("%s failed", #expr); \ + return NULL; \ + } \ +} while (0) + +/* Devices : Normal */ +#define AUDIO_DEVICE_OUT 0x00000000 +#define AUDIO_DEVICE_IN 0x80000000 +enum audio_device_type { + AUDIO_DEVICE_NONE = 0, + + /* output devices */ + AUDIO_DEVICE_OUT_SPEAKER = AUDIO_DEVICE_OUT | 0x00000001, + AUDIO_DEVICE_OUT_RECEIVER = AUDIO_DEVICE_OUT | 0x00000002, + AUDIO_DEVICE_OUT_JACK = AUDIO_DEVICE_OUT | 0x00000004, + AUDIO_DEVICE_OUT_BT_SCO = AUDIO_DEVICE_OUT | 0x00000008, + AUDIO_DEVICE_OUT_AUX = AUDIO_DEVICE_OUT | 0x00000010, + AUDIO_DEVICE_OUT_HDMI = AUDIO_DEVICE_OUT | 0x00000020, + AUDIO_DEVICE_OUT_ALL = (AUDIO_DEVICE_OUT_SPEAKER | + AUDIO_DEVICE_OUT_RECEIVER | + AUDIO_DEVICE_OUT_JACK | + AUDIO_DEVICE_OUT_BT_SCO | + AUDIO_DEVICE_OUT_AUX | + AUDIO_DEVICE_OUT_HDMI), + /* input devices */ + AUDIO_DEVICE_IN_MAIN_MIC = AUDIO_DEVICE_IN | 0x00000001, + AUDIO_DEVICE_IN_SUB_MIC = AUDIO_DEVICE_IN | 0x00000002, + AUDIO_DEVICE_IN_JACK = AUDIO_DEVICE_IN | 0x00000004, + AUDIO_DEVICE_IN_BT_SCO = AUDIO_DEVICE_IN | 0x00000008, + AUDIO_DEVICE_IN_ALL = (AUDIO_DEVICE_IN_MAIN_MIC | + AUDIO_DEVICE_IN_SUB_MIC | + AUDIO_DEVICE_IN_JACK | + AUDIO_DEVICE_IN_BT_SCO), +}; + +typedef struct device_type { + uint32_t type; + const char *name; +} device_type_t; + +/* Verbs */ +#define AUDIO_USE_CASE_VERB_INACTIVE "Inactive" +#define AUDIO_USE_CASE_VERB_HIFI "HiFi" + +/* Modifiers */ +#define AUDIO_USE_CASE_MODIFIER_VOICESEARCH "VoiceSearch" +#define AUDIO_USE_CASE_MODIFIER_CAMCORDING "Camcording" +#define AUDIO_USE_CASE_MODIFIER_MEDIA "Media" +#define AUDIO_USE_CASE_MODIFIER_DUAL_MEDIA "DualMedia" + +#define streq !strcmp +#define strneq strcmp + +#define ALSA_DEFAULT_CARD "bcm2835" +#define PLAYBACK_PCM_DEVICE "hw:0,0" +#define CAPTURE_PCM_DEVICE "hw:0,0" + +/* hw:0,0 */ +#define PLAYBACK_CARD_ID 0 +#define PLAYBACK_PCM_DEVICE_ID 0 + +/* hw:0,0 */ +#define CAPTURE_CARD_ID 0 +#define CAPTURE_PCM_DEVICE_ID 0 + +#define MAX_DEVICES 5 +#define MAX_MODIFIERS 5 +#define MAX_NAME_LEN 32 + +/* 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; + +/* Routing */ +typedef enum audio_route_mode { + VERB_NORMAL, +} audio_route_mode_t; + +typedef struct audio_hal_device { + uint32_t active_in; + uint32_t active_out; + snd_pcm_t *pcm_in; + snd_pcm_t *pcm_out; + pthread_mutex_t pcm_lock; + uint32_t pcm_count; + audio_route_mode_t mode; +} audio_hal_device_t; + +/* Volume */ +#define AUDIO_VOLUME_LEVEL_MAX 16 + +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_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_volume_value_table { + double volume[AUDIO_VOLUME_TYPE_MAX][AUDIO_VOLUME_LEVEL_MAX]; + double gain[AUDIO_GAIN_TYPE_MAX]; +} audio_volume_value_table_t; + +enum { + AUDIO_VOLUME_DEVICE_DEFAULT, + AUDIO_VOLUME_DEVICE_MAX, +}; + +typedef struct audio_hal_volume { + uint32_t volume_level_max[AUDIO_VOLUME_LEVEL_MAX]; + uint32_t volume_level[AUDIO_VOLUME_TYPE_MAX]; + audio_volume_value_table_t *volume_value_table; +} audio_hal_volume_t; + +/* UCM */ +typedef struct audio_hal_ucm { + snd_use_case_mgr_t* uc_mgr; +} audio_hal_ucm_t; + +/* Mixer */ +typedef struct audio_hal_mixer { + snd_mixer_t *mixer; + pthread_mutex_t mutex; + struct { + snd_ctl_elem_value_t *value; + snd_ctl_elem_id_t *id; + snd_ctl_elem_info_t *info; + } control; +} audio_hal_mixer_t; + +/* Audio format */ +typedef enum audio_sample_format { + AUDIO_SAMPLE_U8, + AUDIO_SAMPLE_ALAW, + AUDIO_SAMPLE_ULAW, + AUDIO_SAMPLE_S16LE, + AUDIO_SAMPLE_S16BE, + AUDIO_SAMPLE_FLOAT32LE, + AUDIO_SAMPLE_FLOAT32BE, + AUDIO_SAMPLE_S32LE, + AUDIO_SAMPLE_S32BE, + AUDIO_SAMPLE_S24LE, + AUDIO_SAMPLE_S24BE, + AUDIO_SAMPLE_S24_32LE, + AUDIO_SAMPLE_S24_32BE, + AUDIO_SAMPLE_MAX, + AUDIO_SAMPLE_INVALID = -1 +} audio_sample_format_t; + +/* Overall */ +typedef struct audio_hal { + audio_hal_device_t device; + audio_hal_volume_t volume; + audio_hal_ucm_t ucm; + audio_hal_mixer_t mixer; +} audio_hal_t; + +audio_return_t _audio_volume_init(audio_hal_t *ah); +audio_return_t _audio_volume_deinit(audio_hal_t *ah); +audio_return_t _audio_routing_init(audio_hal_t *ah); +audio_return_t _audio_routing_deinit(audio_hal_t *ah); +audio_return_t _audio_stream_init(audio_hal_t *ah); +audio_return_t _audio_stream_deinit(audio_hal_t *ah); +audio_return_t _audio_pcm_init(audio_hal_t *ah); +audio_return_t _audio_pcm_deinit(audio_hal_t *ah); + +typedef struct _dump_data { + char *strbuf; + int left; + char *p; +} dump_data_t; + +dump_data_t* _audio_dump_new(int length); +void _audio_dump_add_str(dump_data_t *dump, const char *fmt, ...); +char* _audio_dump_get_str(dump_data_t *dump); +void _audio_dump_free(dump_data_t *dump); + +#endif diff --git a/tizen-audio-pcm.c b/tizen-audio-pcm.c new file mode 100644 index 0000000..0a09cba --- /dev/null +++ b/tizen-audio-pcm.c @@ -0,0 +1,203 @@ +/* + * audio-hal + * + * Copyright (c) 2016 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 +#endif + +#include "tizen-audio-internal.h" +#include "tizen-audio-impl.h" + +audio_return_t _audio_pcm_init(audio_hal_t *ah) +{ + AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); + + ah->device.pcm_in = NULL; + ah->device.pcm_out = NULL; + pthread_mutex_init(&ah->device.pcm_lock, NULL); + ah->device.pcm_count = 0; + + return AUDIO_RET_OK; +} + +audio_return_t _audio_pcm_deinit(audio_hal_t *ah) +{ + AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); + + pthread_mutex_destroy(&ah->device.pcm_lock); + + return AUDIO_RET_OK; +} + +audio_return_t audio_pcm_open(void *audio_handle, void **pcm_handle, uint32_t direction, void *sample_spec, uint32_t period_size, uint32_t periods) +{ + audio_return_t audio_ret = AUDIO_RET_OK; + audio_hal_t *ah = NULL; + + AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(pcm_handle, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(sample_spec, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL((period_size > 0), AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL((periods > 0), AUDIO_ERR_PARAMETER); + + if ((audio_ret = _pcm_open(pcm_handle, direction, sample_spec, period_size, periods))) + return audio_ret; + + ah = (audio_hal_t*)audio_handle; + ah->device.pcm_count++; + AUDIO_LOG_INFO("Opening PCM handle 0x%x", *pcm_handle); + + return AUDIO_RET_OK; +} + +audio_return_t audio_pcm_start(void *audio_handle, void *pcm_handle) +{ + audio_return_t audio_ret = AUDIO_RET_OK; + + AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(pcm_handle, AUDIO_ERR_PARAMETER); + + audio_ret = _pcm_start(pcm_handle); + + return audio_ret; +} + +audio_return_t audio_pcm_stop(void *audio_handle, void *pcm_handle) +{ + audio_return_t audio_ret = AUDIO_RET_OK; + + AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(pcm_handle, AUDIO_ERR_PARAMETER); + + audio_ret = _pcm_stop(pcm_handle); + + return audio_ret; +} + +audio_return_t audio_pcm_close(void *audio_handle, void *pcm_handle) +{ + audio_return_t audio_ret = AUDIO_RET_OK; + audio_hal_t *ah = NULL; + + AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(pcm_handle, AUDIO_ERR_PARAMETER); + + if ((audio_ret = _pcm_close(pcm_handle))) + return audio_ret; + + pcm_handle = NULL; + ah = (audio_hal_t*)audio_handle; + ah->device.pcm_count--; + + AUDIO_LOG_INFO("PCM handle close success (count:%d)", ah->device.pcm_count); + + return audio_ret; +} + +audio_return_t audio_pcm_avail(void *audio_handle, void *pcm_handle, uint32_t *avail) +{ + audio_return_t audio_ret = AUDIO_RET_OK; + + AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(pcm_handle, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(avail, AUDIO_ERR_PARAMETER); + + audio_ret = _pcm_avail(pcm_handle, avail); + + return audio_ret; +} + +audio_return_t audio_pcm_write(void *audio_handle, void *pcm_handle, const void *buffer, uint32_t frames) +{ + audio_return_t audio_ret = AUDIO_RET_OK; + + AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(pcm_handle, AUDIO_ERR_PARAMETER); + + audio_ret = _pcm_write(pcm_handle, buffer, frames); + + return audio_ret; +} + +audio_return_t audio_pcm_read(void *audio_handle, void *pcm_handle, void *buffer, uint32_t frames) +{ + audio_return_t audio_ret = AUDIO_RET_OK; + + AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(pcm_handle, AUDIO_ERR_PARAMETER); + + audio_ret = _pcm_read(pcm_handle, buffer, frames); + + return audio_ret; +} + +audio_return_t audio_pcm_get_fd(void *audio_handle, void *pcm_handle, int *fd) +{ + audio_return_t audio_ret = AUDIO_RET_OK; + + AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(pcm_handle, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(fd, AUDIO_ERR_PARAMETER); + + audio_ret = _pcm_get_fd(pcm_handle, fd); + + return audio_ret; +} + +audio_return_t audio_pcm_recover(void *audio_handle, void *pcm_handle, int revents) +{ + audio_return_t audio_ret = AUDIO_RET_OK; + + AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(pcm_handle, AUDIO_ERR_PARAMETER); + + audio_ret = _pcm_recover(pcm_handle, revents); + + return audio_ret; +} + +audio_return_t audio_pcm_get_params(void *audio_handle, void *pcm_handle, uint32_t direction, void **sample_spec, uint32_t *period_size, uint32_t *periods) +{ + audio_return_t audio_ret = AUDIO_RET_OK; + + AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(pcm_handle, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(sample_spec, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(period_size, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(periods, AUDIO_ERR_PARAMETER); + + audio_ret = _pcm_get_params(pcm_handle, direction, sample_spec, period_size, periods); + + return audio_ret; +} + +audio_return_t audio_pcm_set_params(void *audio_handle, void *pcm_handle, uint32_t direction, void *sample_spec, uint32_t period_size, uint32_t periods) +{ + audio_return_t audio_ret = AUDIO_RET_OK; + + AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(pcm_handle, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(sample_spec, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(period_size, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(periods, AUDIO_ERR_PARAMETER); + + audio_ret = _pcm_set_params(pcm_handle, direction, sample_spec, period_size, periods); + + return audio_ret; +} \ No newline at end of file diff --git a/tizen-audio-routing.c b/tizen-audio-routing.c new file mode 100644 index 0000000..8be716b --- /dev/null +++ b/tizen-audio-routing.c @@ -0,0 +1,336 @@ +/* + * audio-hal + * + * Copyright (c) 2016 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 +#endif + +#include +#include +#include +#include + +#include "tizen-audio-internal.h" +#include "tizen-audio-impl.h" + +/* #define DEBUG_TIMING */ + +static device_type_t outDeviceTypes[] = { + { AUDIO_DEVICE_OUT_SPEAKER, "Speaker" }, + { AUDIO_DEVICE_OUT_JACK, "Headphones" }, + { AUDIO_DEVICE_OUT_BT_SCO, "Bluetooth" }, + { AUDIO_DEVICE_OUT_AUX, "Line" }, + { AUDIO_DEVICE_OUT_HDMI, "HDMI" }, + { 0, 0 }, +}; + +static device_type_t inDeviceTypes[] = { + { AUDIO_DEVICE_IN_MAIN_MIC, "MainMic" }, + { AUDIO_DEVICE_IN_JACK, "HeadsetMic" }, + { AUDIO_DEVICE_IN_BT_SCO, "BT Mic" }, + { 0, 0 }, +}; + +static const char* mode_to_verb_str[] = { + AUDIO_USE_CASE_VERB_HIFI, +}; + +static uint32_t __convert_device_string_to_enum(const char* device_str, uint32_t direction) +{ + uint32_t device = 0; + + if (!strncmp(device_str, "builtin-speaker", MAX_NAME_LEN)) { + device = AUDIO_DEVICE_OUT_SPEAKER; + } else if (!strncmp(device_str, "builtin-receiver", MAX_NAME_LEN)) { + device = AUDIO_DEVICE_OUT_RECEIVER; + } else if ((!strncmp(device_str, "audio-jack", MAX_NAME_LEN)) && (direction == AUDIO_DIRECTION_OUT)) { + device = AUDIO_DEVICE_OUT_JACK; + } else if ((!strncmp(device_str, "bt-sco", MAX_NAME_LEN)) && (direction == AUDIO_DIRECTION_OUT)) { + device = AUDIO_DEVICE_OUT_BT_SCO; + } else if (!strncmp(device_str, "aux", MAX_NAME_LEN)) { + device = AUDIO_DEVICE_OUT_AUX; + } else if (!strncmp(device_str, "hdmi", MAX_NAME_LEN)) { + device = AUDIO_DEVICE_OUT_HDMI; + } else if ((!strncmp(device_str, "builtin-mic", MAX_NAME_LEN))) { + device = AUDIO_DEVICE_IN_MAIN_MIC; + } else if ((!strncmp(device_str, "audio-jack", MAX_NAME_LEN)) && (direction == AUDIO_DIRECTION_IN)) { + device = AUDIO_DEVICE_IN_JACK; + } else if ((!strncmp(device_str, "bt-sco", MAX_NAME_LEN)) && (direction == AUDIO_DIRECTION_IN)) { + device = AUDIO_DEVICE_IN_BT_SCO; + } else { + device = AUDIO_DEVICE_NONE; + } + AUDIO_LOG_INFO("device type(%s), enum(0x%x)", device_str, device); + return device; +} + +static audio_return_t __set_devices(audio_hal_t *ah, const char *verb, device_info_t *devices, uint32_t num_of_devices) +{ + audio_return_t audio_ret = AUDIO_RET_OK; + uint32_t new_device = 0; + const char *active_devices[MAX_DEVICES] = {NULL,}; + int i = 0, j = 0, dev_idx = 0; + + AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(devices, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(num_of_devices, AUDIO_ERR_PARAMETER); + + if (num_of_devices > MAX_DEVICES) { + num_of_devices = MAX_DEVICES; + AUDIO_LOG_ERROR("error: num_of_devices"); + return AUDIO_ERR_PARAMETER; + } + + if (devices[0].direction == AUDIO_DIRECTION_OUT) { + ah->device.active_out &= 0x0; + if (ah->device.active_in) { + /* check the active in devices */ + for (j = 0; j < inDeviceTypes[j].type; j++) { + if (((ah->device.active_in & (~AUDIO_DEVICE_IN)) & inDeviceTypes[j].type)) + active_devices[dev_idx++] = inDeviceTypes[j].name; + } + } + } else if (devices[0].direction == AUDIO_DIRECTION_IN) { + ah->device.active_in &= 0x0; + if (ah->device.active_out) { + /* check the active out devices */ + for (j = 0; j < outDeviceTypes[j].type; j++) { + if (ah->device.active_out & outDeviceTypes[j].type) + active_devices[dev_idx++] = outDeviceTypes[j].name; + } + } + } + + for (i = 0; i < num_of_devices; i++) { + new_device = __convert_device_string_to_enum(devices[i].type, devices[i].direction); + if (new_device & AUDIO_DEVICE_IN) { + for (j = 0; j < inDeviceTypes[j].type; j++) { + if (new_device == inDeviceTypes[j].type) { + active_devices[dev_idx++] = inDeviceTypes[j].name; + ah->device.active_in |= new_device; + } + } + } else { + for (j = 0; j < outDeviceTypes[j].type; j++) { + if (new_device == outDeviceTypes[j].type) { + active_devices[dev_idx++] = outDeviceTypes[j].name; + ah->device.active_out |= new_device; + } + } + } + } + + if (active_devices[0] == NULL) { + AUDIO_LOG_ERROR("Failed to set device: active device is NULL"); + return AUDIO_ERR_PARAMETER; + } + + audio_ret = _ucm_set_devices(ah, verb, active_devices); + if (audio_ret) + AUDIO_LOG_ERROR("Failed to set device: error = %d", audio_ret); + + return audio_ret; +} + +static audio_return_t __update_route_ap_playback_capture(audio_hal_t *ah, audio_route_info_t *route_info) +{ + audio_return_t audio_ret = AUDIO_RET_OK; + device_info_t *devices = NULL; + const char *verb = mode_to_verb_str[VERB_NORMAL]; + + AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(route_info, AUDIO_ERR_PARAMETER); + + devices = route_info->device_infos; + + /* To Do: Set modifiers */ + /* int mod_idx = 0; */ + /* const char *modifiers[MAX_MODIFIERS] = {NULL,}; */ + + AUDIO_LOG_INFO("update_route_ap_playback_capture++ "); + + audio_ret = __set_devices(ah, verb, devices, route_info->num_of_devices); + if (audio_ret) { + AUDIO_LOG_ERROR("Failed to set devices: error = 0x%x", audio_ret); + return audio_ret; + } + ah->device.mode = VERB_NORMAL; + + /* To Do: Set modifiers */ + /* + if (!strncmp("voice_recognition", route_info->role, MAX_NAME_LEN)) { + modifiers[mod_idx++] = AUDIO_USE_CASE_MODIFIER_VOICESEARCH; + } else if ((!strncmp("alarm", route_info->role, MAX_NAME_LEN))||(!strncmp("notifiication", route_info->role, MAX_NAME_LEN))) { + if (ah->device.active_out &= AUDIO_DEVICE_OUT_JACK) + modifiers[mod_idx++] = AUDIO_USE_CASE_MODIFIER_DUAL_MEDIA; + else + modifiers[mod_idx++] = AUDIO_USE_CASE_MODIFIER_MEDIA; + } else { + if (ah->device.active_in) + modifiers[mod_idx++] = AUDIO_USE_CASE_MODIFIER_CAMCORDING; + else + modifiers[mod_idx++] = AUDIO_USE_CASE_MODIFIER_MEDIA; + } + audio_ret = _audio_ucm_set_modifiers (ah, verb, modifiers); + */ + + return audio_ret; +} + +static audio_return_t __update_route_voip(audio_hal_t *ah, device_info_t *devices, int32_t num_of_devices) +{ + audio_return_t audio_ret = AUDIO_RET_OK; + const char *verb = mode_to_verb_str[VERB_NORMAL]; + + AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(devices, AUDIO_ERR_PARAMETER); + + AUDIO_LOG_INFO("update_route_voip++"); + + audio_ret = __set_devices(ah, verb, devices, num_of_devices); + if (audio_ret) { + AUDIO_LOG_ERROR("Failed to set devices: error = 0x%x", audio_ret); + return audio_ret; + } + /* FIXME. If necessary, set VERB_VOIP */ + ah->device.mode = VERB_NORMAL; + + /* TO DO: Set modifiers */ + return audio_ret; +} + +static audio_return_t __update_route_reset(audio_hal_t *ah, uint32_t direction) +{ + audio_return_t audio_ret = AUDIO_RET_OK; + const char *active_devices[MAX_DEVICES] = {NULL,}; + int i = 0, dev_idx = 0; + + /* FIXME: If you need to reset, set verb inactive */ + /* const char *verb = NULL; */ + /* verb = AUDIO_USE_CASE_VERB_INACTIVE; */ + + AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); + + AUDIO_LOG_INFO("update_route_reset++, direction(0x%x)", direction); + + if (direction == AUDIO_DIRECTION_OUT) { + ah->device.active_out &= 0x0; + if (ah->device.active_in) { + /* check the active in devices */ + for (i = 0; i < inDeviceTypes[i].type; i++) { + if (((ah->device.active_in & (~AUDIO_DEVICE_IN)) & inDeviceTypes[i].type)) { + active_devices[dev_idx++] = inDeviceTypes[i].name; + AUDIO_LOG_INFO("added for in : %s", inDeviceTypes[i].name); + } + } + } + } else { + ah->device.active_in &= 0x0; + if (ah->device.active_out) { + /* check the active out devices */ + for (i = 0; i < outDeviceTypes[i].type; i++) { + if (ah->device.active_out & outDeviceTypes[i].type) { + active_devices[dev_idx++] = outDeviceTypes[i].name; + AUDIO_LOG_INFO("added for out : %s", outDeviceTypes[i].name); + } + } + } + } + + if (active_devices[0] == NULL) { + AUDIO_LOG_DEBUG("active device is NULL, no need to update."); + return AUDIO_RET_OK; + } + + if ((audio_ret = _ucm_set_devices(ah, mode_to_verb_str[ah->device.mode], active_devices))) + AUDIO_LOG_ERROR("failed to _ucm_set_devices(), ret(0x%x)", audio_ret); + + return audio_ret; +} + +audio_return_t _audio_routing_init(audio_hal_t *ah) +{ + audio_return_t audio_ret = AUDIO_RET_OK; + + AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); + + ah->device.active_in = 0x0; + ah->device.active_out = 0x0; + ah->device.mode = VERB_NORMAL; + + if ((audio_ret = _ucm_init(ah))) + AUDIO_LOG_ERROR("failed to _ucm_init(), ret(0x%x)", audio_ret); + + return audio_ret; +} + +audio_return_t _audio_routing_deinit(audio_hal_t *ah) +{ + audio_return_t audio_ret = AUDIO_RET_OK; + + AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); + + if ((audio_ret = _ucm_deinit(ah))) + AUDIO_LOG_ERROR("failed to _ucm_deinit(), ret(0x%x)", audio_ret); + + return audio_ret; +} + +audio_return_t audio_update_route(void *audio_handle, audio_route_info_t *info) +{ + audio_return_t audio_ret = AUDIO_RET_OK; + audio_hal_t *ah = (audio_hal_t *)audio_handle; + device_info_t *devices = NULL; + + AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(info, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(info->role, AUDIO_ERR_PARAMETER); + + AUDIO_LOG_INFO("role:%s", info->role); + + devices = info->device_infos; + + if (!strncmp("voip", info->role, MAX_NAME_LEN)) { + if ((audio_ret = __update_route_voip(ah, devices, info->num_of_devices))) + AUDIO_LOG_WARN("update voip route return 0x%x", audio_ret); + + } else if (!strncmp("reset", info->role, MAX_NAME_LEN)) { + if ((audio_ret = __update_route_reset(ah, devices->direction))) + AUDIO_LOG_WARN("update reset return 0x%x", audio_ret); + + } else { + /* need to prepare for "alarm","notification","emergency","voice-information","voice-recognition","ringtone" */ + if ((audio_ret = __update_route_ap_playback_capture(ah, info))) + AUDIO_LOG_WARN("update playback route return 0x%x", audio_ret); + } + return audio_ret; +} + +audio_return_t audio_update_route_option(void *audio_handle, audio_route_option_t *option) +{ + audio_return_t audio_ret = AUDIO_RET_OK; + audio_hal_t *ah = (audio_hal_t *)audio_handle; + + AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(option, AUDIO_ERR_PARAMETER); + + AUDIO_LOG_INFO("role:%s, name:%s, value:%d", option->role, option->name, option->value); + + return audio_ret; +} diff --git a/tizen-audio-stream.c b/tizen-audio-stream.c new file mode 100644 index 0000000..c60a443 --- /dev/null +++ b/tizen-audio-stream.c @@ -0,0 +1,54 @@ +/* + * audio-hal + * + * Copyright (c) 2016 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 +#endif + +#include "tizen-audio-internal.h" + +audio_return_t _audio_stream_init(audio_hal_t *ah) +{ + AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); + + return AUDIO_RET_OK; +} + +audio_return_t _audio_stream_deinit(audio_hal_t *ah) +{ + AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); + + return AUDIO_RET_OK; +} + +audio_return_t audio_notify_stream_connection_changed(void *audio_handle, audio_stream_info_t *info, uint32_t is_connected) +{ + audio_return_t audio_ret = AUDIO_RET_OK; + audio_hal_t *ah = (audio_hal_t *)audio_handle; + + AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(info, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(info->role, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL((info->direction <= AUDIO_DIRECTION_OUT), AUDIO_ERR_PARAMETER); + + AUDIO_LOG_INFO("role:%s, direction:%u, idx:%u, is_connected:%d", info->role, info->direction, info->idx, is_connected); + + return audio_ret; +} + diff --git a/tizen-audio-util.c b/tizen-audio-util.c new file mode 100644 index 0000000..6ab4aa0 --- /dev/null +++ b/tizen-audio-util.c @@ -0,0 +1,80 @@ +/* + * audio-hal + * + * Copyright (c) 2015 - 2016 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 +#endif + +#include +#include +#include + +#include "tizen-audio-internal.h" + +/* ------ dump helper -------- */ +#define MAX(a, b) ((a) > (b) ? (a) : (b)) + +dump_data_t* _audio_dump_new(int length) +{ + dump_data_t* dump = NULL; + + if ((dump = malloc(sizeof(dump_data_t)))) { + memset(dump, 0, sizeof(dump_data_t)); + if ((dump->strbuf = malloc(length))) { + dump->p = &dump->strbuf[0]; + dump->left = length; + } else { + free(dump); + dump = NULL; + } + } + + return dump; +} + +void _audio_dump_add_str(dump_data_t *dump, const char *fmt, ...) +{ + int len; + va_list ap; + + if (!dump) + return; + + va_start(ap, fmt); + len = vsnprintf(dump->p, dump->left, fmt, ap); + va_end(ap); + + dump->p += MAX(0, len); + dump->left -= MAX(0, len); +} + +char* _audio_dump_get_str(dump_data_t *dump) +{ + return (dump) ? dump->strbuf : NULL; +} + +void _audio_dump_free(dump_data_t *dump) +{ + if (dump) { + if (dump->strbuf) + free(dump->strbuf); + free(dump); + } +} +/* ------ dump helper -------- */ diff --git a/tizen-audio-volume.c b/tizen-audio-volume.c new file mode 100644 index 0000000..89d5124 --- /dev/null +++ b/tizen-audio-volume.c @@ -0,0 +1,403 @@ +/* + * audio-hal + * + * Copyright (c) 2015 - 2016 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 +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include "tizen-audio-internal.h" + +#define VOLUME_INI_DEFAULT_PATH SYSCONFDIR"/multimedia/mmfw_audio_volume.ini" /* SYSCONFDIR is defined at .spec */ +#define VOLUME_INI_TEMP_PATH "/opt/system/mmfw_audio_volume.ini" +#define VOLUME_VALUE_MAX (1.0f) +#define GAIN_VALUE_MAX (1.0f) + +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 */ +}; + +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"; + default: return "invalid"; + } +} + +static uint32_t __get_volume_idx_by_string_type(const char *vol_type) +{ + if (!strncmp(vol_type, "system", strlen(vol_type)) || !strncmp(vol_type, "0", strlen(vol_type))) + return AUDIO_VOLUME_TYPE_SYSTEM; + else if (!strncmp(vol_type, "notification", strlen(vol_type)) || !strncmp(vol_type, "1", strlen(vol_type))) + return AUDIO_VOLUME_TYPE_NOTIFICATION; + else if (!strncmp(vol_type, "alarm", strlen(vol_type)) || !strncmp(vol_type, "2", strlen(vol_type))) + return AUDIO_VOLUME_TYPE_ALARM; + else if (!strncmp(vol_type, "ringtone", strlen(vol_type)) || !strncmp(vol_type, "3", strlen(vol_type))) + return AUDIO_VOLUME_TYPE_RINGTONE; + else if (!strncmp(vol_type, "media", strlen(vol_type)) || !strncmp(vol_type, "4", strlen(vol_type))) + return AUDIO_VOLUME_TYPE_MEDIA; + else if (!strncmp(vol_type, "call", strlen(vol_type)) || !strncmp(vol_type, "5", strlen(vol_type))) + return AUDIO_VOLUME_TYPE_CALL; + else if (!strncmp(vol_type, "voip", strlen(vol_type)) || !strncmp(vol_type, "6", strlen(vol_type))) + return AUDIO_VOLUME_TYPE_VOIP; + else if (!strncmp(vol_type, "voice", strlen(vol_type)) || !strncmp(vol_type, "7", strlen(vol_type))) + return AUDIO_VOLUME_TYPE_VOICE; + else + return AUDIO_VOLUME_TYPE_MEDIA; +} + +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_tb(audio_hal_t *ah) +{ + audio_volume_value_table_t *volume_value_table = ah->volume.volume_value_table; + uint32_t 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 >>>>>"); + + const char *table_str = "volumes"; + + AUDIO_LOG_INFO("<< %s >>", table_str); + + for (vol_type_idx = 0; vol_type_idx < AUDIO_VOLUME_TYPE_MAX; vol_type_idx++) { + const char *vol_type_str = __get_volume_type_string_by_idx(vol_type_idx); + + 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 < ah->volume.volume_level_max[vol_type_idx]; vol_level_idx++) { + snprintf(dump_str_ptr, 6, "%01.2f ", volume_value_table->volume[vol_type_idx][vol_level_idx]); + dump_str_ptr += strlen(dump_str_ptr); + } + AUDIO_LOG_INFO("%s", dump_str); + } + + volume_value_table = ah->volume.volume_value_table; + + /* 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)); + + snprintf(dump_str_ptr, 11, "%9s:", table_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_value_table->gain[gain_type_idx]); + dump_str_ptr += strlen(dump_str_ptr); + } + AUDIO_LOG_INFO("%s", dump_str); + +} + +static audio_return_t __load_volume_value_table_from_ini(audio_hal_t *ah) +{ + dictionary * dict = NULL; + uint32_t vol_type_idx, vol_level_idx, gain_type_idx; + audio_volume_value_table_t *volume_value_table = ah->volume.volume_value_table; + int size = 0; + + 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; + } + } + + const char delimiter[] = ", "; + char *key, *list_str, *token, *ptr = NULL; + const char *table_str = "volumes"; + + /* 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); + + ah->volume.volume_level_max[vol_type_idx] = 0; + size = strlen(table_str) + strlen(vol_type_str) + 2; + key = malloc(size); + if (key) { + snprintf(key, size, "%s:%s", table_str, vol_type_str); + list_str = iniparser_getstring(dict, key, NULL); + 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_value_table->volume[vol_type_idx][ah->volume.volume_level_max[vol_type_idx]++] = vol_value; + token = strtok_r(NULL, delimiter, &ptr); + } + } else { + ah->volume.volume_level_max[vol_type_idx] = 1; + for (vol_level_idx = 0; vol_level_idx < AUDIO_VOLUME_LEVEL_MAX; vol_level_idx++) { + volume_value_table->volume[vol_type_idx][vol_level_idx] = VOLUME_VALUE_MAX; + } + } + free(key); + } + } + + /* Load gain table */ + volume_value_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(table_str) + strlen("gain") + strlen(gain_type_str) + 3; + key = malloc(size); + if (key) { + snprintf(key, size, "%s:gain_%s", table_str, gain_type_str); + token = iniparser_getstring(dict, key, NULL); + if (token) { + volume_value_table->gain[gain_type_idx] = atof(token); + } else { + volume_value_table->gain[gain_type_idx] = GAIN_VALUE_MAX; + } + free(key); + } else { + volume_value_table->gain[gain_type_idx] = GAIN_VALUE_MAX; + } + } + + iniparser_freedict(dict); + + __dump_tb(ah); + + return AUDIO_RET_OK; +} + +audio_return_t _audio_volume_init(audio_hal_t *ah) +{ + int i; + int val = 0; + audio_return_t audio_ret = AUDIO_RET_OK; + int init_value[AUDIO_VOLUME_TYPE_MAX] = { 9, 11, 7, 11, 7, 4, 4, 7 }; + + AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); + + for (i = 0; i < AUDIO_VOLUME_TYPE_MAX; i++) { + ah->volume.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); + ah->volume.volume_level[i] = val; + } + + if (!(ah->volume.volume_value_table = malloc(AUDIO_VOLUME_DEVICE_MAX * sizeof(audio_volume_value_table_t)))) { + AUDIO_LOG_ERROR("volume_value_table malloc failed"); + return AUDIO_ERR_RESOURCE; + } + + audio_ret = __load_volume_value_table_from_ini(ah); + if (audio_ret != AUDIO_RET_OK) { + AUDIO_LOG_ERROR("gain table load error"); + return AUDIO_ERR_UNDEFINED; + } + + return audio_ret; +} + +audio_return_t _audio_volume_deinit(audio_hal_t *ah) +{ + AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); + + if (ah->volume.volume_value_table) { + free(ah->volume.volume_value_table); + ah->volume.volume_value_table = NULL; + } + + return AUDIO_RET_OK; +} + +audio_return_t audio_get_volume_level_max(void *audio_handle, audio_volume_info_t *info, uint32_t *level) +{ + audio_hal_t *ah = (audio_hal_t *)audio_handle; + + AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(info, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(level, AUDIO_ERR_PARAMETER); + + /* Get max volume level by device & type */ + *level = ah->volume.volume_level_max[__get_volume_idx_by_string_type(info->type)]; + + AUDIO_LOG_DEBUG("get_[%s] volume_level_max: %d", info->type, *level); + + return AUDIO_RET_OK; +} + +audio_return_t audio_get_volume_level(void *audio_handle, audio_volume_info_t *info, uint32_t *level) +{ + audio_hal_t *ah = (audio_hal_t *)audio_handle; + + AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(info, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(level, AUDIO_ERR_PARAMETER); + + *level = ah->volume.volume_level[__get_volume_idx_by_string_type(info->type)]; + + AUDIO_LOG_INFO("get [%s] volume_level: %d, direction(%d)", info->type, *level, info->direction); + + return AUDIO_RET_OK; +} + +audio_return_t audio_get_volume_value(void *audio_handle, audio_volume_info_t *info, uint32_t level, double *value) +{ + audio_hal_t *ah = (audio_hal_t *)audio_handle; + audio_volume_value_table_t *volume_value_table; + char dump_str[AUDIO_DUMP_STR_LEN] = {0,}; + + AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(info, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(value, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(ah->volume.volume_value_table, AUDIO_ERR_PARAMETER); + + /* Get basic volume by device & type & level */ + volume_value_table = ah->volume.volume_value_table; + if (ah->volume.volume_level_max[__get_volume_idx_by_string_type(info->type)] < level) + *value = VOLUME_VALUE_MAX; + else + *value = volume_value_table->volume[__get_volume_idx_by_string_type(info->type)][level]; + *value *= volume_value_table->gain[AUDIO_GAIN_TYPE_DEFAULT]; /* need to fix getting gain via audio_info_t */ + + AUDIO_LOG_DEBUG("get_volume_value:%d(%s)=>%f %s", level, info->type, *value, &dump_str[0]); + + return AUDIO_RET_OK; +} + +audio_return_t audio_set_volume_level(void *audio_handle, audio_volume_info_t *info, uint32_t level) +{ + audio_return_t audio_ret = AUDIO_RET_OK; + audio_hal_t *ah = (audio_hal_t *)audio_handle; + + AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(info, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL((ah->volume.volume_level_max[__get_volume_idx_by_string_type(info->type)] >= level), AUDIO_ERR_PARAMETER); + + /* Update volume level */ + ah->volume.volume_level[__get_volume_idx_by_string_type(info->type)] = level; + AUDIO_LOG_INFO("set [%s] volume_level: %d, direction(%d)", info->type, level, info->direction); + + /* set mixer related to H/W volume if needed */ + + return audio_ret; +} + +audio_return_t audio_get_volume_mute(void *audio_handle, audio_volume_info_t *info, uint32_t *mute) +{ + audio_return_t audio_ret = AUDIO_RET_OK; + audio_hal_t *ah = (audio_hal_t *)audio_handle; + + AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(info, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(mute, AUDIO_ERR_PARAMETER); + + /* TODO. Not implemented */ + + return audio_ret; +} + +audio_return_t audio_set_volume_mute(void *audio_handle, audio_volume_info_t *info, uint32_t mute) +{ + audio_return_t audio_ret = AUDIO_RET_OK; + audio_hal_t *ah = (audio_hal_t *)audio_handle; + + AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(info, AUDIO_ERR_PARAMETER); + + /* TODO. Not implemented */ + + return audio_ret; +} diff --git a/tizen-audio.c b/tizen-audio.c new file mode 100644 index 0000000..b83397b --- /dev/null +++ b/tizen-audio.c @@ -0,0 +1,78 @@ +/* + * audio-hal + * + * Copyright (c) 2015 - 2016 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 +#endif + +#include "tizen-audio-internal.h" + +audio_return_t audio_init(void **audio_handle) +{ + audio_hal_t *ah; + audio_return_t ret = AUDIO_RET_OK; + + AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER); + + if (!(ah = malloc(sizeof(audio_hal_t)))) { + AUDIO_LOG_ERROR("failed to malloc()"); + return AUDIO_ERR_RESOURCE; + } + if ((ret = _audio_volume_init(ah))) { + AUDIO_LOG_ERROR("failed to _audio_volume_init(), ret(0x%x)", ret); + goto error_exit; + } + if ((ret = _audio_routing_init(ah))) { + AUDIO_LOG_ERROR("failed to _audio_routing_init(), ret(0x%x)", ret); + goto error_exit; + } + if ((ret = _audio_stream_init(ah))) { + AUDIO_LOG_ERROR("failed to _audio_stream_init(), ret(0x%x)", ret); + goto error_exit; + } + if ((ret = _audio_pcm_init(ah))) { + AUDIO_LOG_ERROR("failed to _audio_pcm_init(), ret(0x%x)", ret); + goto error_exit; + } + + *audio_handle = (void *)ah; + return AUDIO_RET_OK; + +error_exit: + if (ah) + free(ah); + + return ret; +} + +audio_return_t audio_deinit(void *audio_handle) +{ + audio_hal_t *ah = (audio_hal_t *)audio_handle; + + AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); + + _audio_volume_deinit(ah); + _audio_routing_deinit(ah); + _audio_stream_deinit(ah); + _audio_pcm_deinit(ah); + free(ah); + ah = NULL; + + return AUDIO_RET_OK; +} \ No newline at end of file diff --git a/tizen-audio.h b/tizen-audio.h new file mode 100644 index 0000000..282f7f0 --- /dev/null +++ b/tizen-audio.h @@ -0,0 +1,483 @@ +/* + * audio-hal + * + * Copyright (c) 2015 - 2016 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. + * + */ + +#ifndef footizenaudiofoo +#define footizenaudiofoo + +#include + +/** + * @file tizen-audio.h + * @brief This file contains the Audio Hardware Abstraction Layer Interfaces. + */ + +/** + * @addtogroup TIZEN_AUDIO_HAL_MODULE + * @{ + */ + +/** + * @brief Enumeration for return codes. + * @since_tizen 3.0 + */ +typedef enum audio_return { + AUDIO_RET_OK = 0, + 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_INVALID_STATE = (int32_t)0x80001004, + AUDIO_ERR_INTERNAL = (int32_t)0x80001005, + /* add new enemerator here */ + AUDIO_ERR_NOT_IMPLEMENTED = (int32_t)0x80001100, +} audio_return_t ; + +/** + * @brief Enumeration for audio direction. + * @since_tizen 3.0 + */ +typedef enum audio_direction { + AUDIO_DIRECTION_IN, /**< Capture */ + AUDIO_DIRECTION_OUT, /**< Playback */ +} audio_direction_t; + +/** + * @brief Device information including type, direction and id. + * @since_tizen 3.0 + */ +typedef struct device_info { + const char *type; + uint32_t direction; + uint32_t id; +} device_info_t; + +/** + * @brief Volume information including type, gain and direction. + * @since_tizen 3.0 + */ +typedef struct audio_volume_info { + const char *type; + const char *gain; + uint32_t direction; +} audio_volume_info_t ; + +/** + * @brief Route information including role and device. + * @since_tizen 3.0 + */ +typedef struct audio_route_info { + const char *role; + device_info_t *device_infos; + uint32_t num_of_devices; +} audio_route_info_t; + +/** + * @brief Route option including role, name and value. + * @since_tizen 3.0 + */ +typedef struct audio_route_option { + const char *role; + const char *name; + int32_t value; +} audio_route_option_t; + +/** + * @brief Stream information including role, direction and index. + * @since_tizen 3.0 + */ +typedef struct audio_stream_info { + const char *role; + uint32_t direction; + uint32_t idx; +} audio_stream_info_t ; + +/* Overall */ +typedef struct audio_interface { + /* Initialization & de-initialization */ + audio_return_t (*init)(void **audio_handle); + audio_return_t (*deinit)(void *audio_handle); + /* Volume */ + audio_return_t (*get_volume_level_max)(void *audio_handle, audio_volume_info_t *info, uint32_t *level); + audio_return_t (*get_volume_level)(void *audio_handle, audio_volume_info_t *info, uint32_t *level); + audio_return_t (*set_volume_level)(void *audio_handle, audio_volume_info_t *info, uint32_t level); + audio_return_t (*get_volume_value)(void *audio_handle, audio_volume_info_t *info, uint32_t level, double *value); + audio_return_t (*get_volume_mute)(void *audio_handle, audio_volume_info_t *info, uint32_t *mute); + audio_return_t (*set_volume_mute)(void *audio_handle, audio_volume_info_t *info, uint32_t mute); + /* Routing */ + audio_return_t (*update_route)(void *audio_handle, audio_route_info_t *info); + audio_return_t (*update_route_option)(void *audio_handle, audio_route_option_t *option); + /* Stream */ + audio_return_t (*notify_stream_connection_changed)(void *audio_handle, audio_stream_info_t *info, uint32_t is_connected); + /* PCM */ + audio_return_t (*pcm_open)(void *audio_handle, void **pcm_handle, uint32_t direction, void *sample_spec, uint32_t period_size, uint32_t periods); + audio_return_t (*pcm_start)(void *audio_handle, void *pcm_handle); + audio_return_t (*pcm_stop)(void *audio_handle, void *pcm_handle); + audio_return_t (*pcm_close)(void *audio_handle, void *pcm_handle); + audio_return_t (*pcm_avail)(void *audio_handle, void *pcm_handle, uint32_t *avail); + audio_return_t (*pcm_write)(void *audio_handle, void *pcm_handle, const void *buffer, uint32_t frames); + audio_return_t (*pcm_read)(void *audio_handle, void *pcm_handle, void *buffer, uint32_t frames); + audio_return_t (*pcm_get_fd)(void *audio_handle, void *pcm_handle, int *fd); + audio_return_t (*pcm_recover)(void *audio_handle, void *pcm_handle, int revents); + audio_return_t (*pcm_get_params)(void *audio_handle, void *pcm_handle, uint32_t direction, void **sample_spec, uint32_t *period_size, uint32_t *periods); + audio_return_t (*pcm_set_params)(void *audio_handle, void *pcm_handle, uint32_t direction, void *sample_spec, uint32_t period_size, uint32_t periods); +} audio_interface_t; + +/** + * @brief Initializes audio hal. + * @since_tizen 3.0 + * @param[out] audio_handle The audio hal handle + * + * @return @c 0 on success, + * otherwise a negative error value + * @retval #AUDIO_RET_OK Success + * @see audio_deinit() + */ +audio_return_t audio_init(void **audio_handle); + +/** + * @brief De-initializes audio hal. + * @since_tizen 3.0 + * @param[in] audio_handle The audio hal handle + * + * @return @c 0 on success, + * otherwise a negative error value + * @retval #AUDIO_RET_OK Success + * @see audio_init() + */ +audio_return_t audio_deinit(void *audio_handle); + +/** + * @brief Gets the maximum volume level supported for a particular volume information. + * @since_tizen 3.0 + * @param[in] audio_handle The audio hal handle + * @param[in] info The audio volume information + * @param[out] level The maximum volume level + * + * @return @c 0 on success, + * otherwise a negative error value + * @retval #AUDIO_RET_OK Success + * @see audio_set_volume_level() + * @see audio_get_volume_level() + * @see audio_get_volume_value() + */ +audio_return_t audio_get_volume_level_max(void *audio_handle, audio_volume_info_t *info, uint32_t *level); + +/** + * @brief Gets the volume level specified for a particular volume information. + * @since_tizen 3.0 + * @param[in] audio_handle The audio hal handle + * @param[in] info The audio volume information + * @param[out] level The current volume level + * + * @return @c 0 on success, + * otherwise a negative error value + * @retval #AUDIO_RET_OK Success + * @see audio_set_volume_level() + * @see audio_get_volume_level_max() + * @see audio_get_volume_value() + */ +audio_return_t audio_get_volume_level(void *audio_handle, audio_volume_info_t *info, uint32_t *level); + +/** + * @brief Sets the volume level specified for a particular volume information. + * @since_tizen 3.0 + * @param[in] audio_handle The audio hal handle + * @param[in] info The audio volume information + * @param[in] level The volume level to be set + * + * @return @c 0 on success, + * otherwise a negative error value + * @retval #AUDIO_RET_OK Success + * @see audio_get_volume_level() + * @see audio_get_volume_level_max() + * @see audio_get_volume_value() + */ +audio_return_t audio_set_volume_level(void *audio_handle, audio_volume_info_t *info, uint32_t level); + +/** + * @brief Gets the volume value specified for a particular volume information and level. + * @since_tizen 3.0 + * @param[in] audio_handle The audio hal handle + * @param[in] info The audio volume information + * @param[in] level The volume level + * @param[out] value The volume value (range is from 0.0 to 1.0 inclusive, 1.0 = 100%) + * + * @return @c 0 on success, + * otherwise a negative error value + * @retval #AUDIO_RET_OK Success + * @see audio_set_volume_level() + * @see audio_get_volume_level() + * @see audio_get_volume_level_max() + */ +audio_return_t audio_get_volume_value(void *audio_handle, audio_volume_info_t *info, uint32_t level, double *value); + +/** + * @brief Gets the volume mute specified for a particular volume information. + * @since_tizen 3.0 + * @param[in] audio_handle The audio hal handle + * @param[in] info The audio volume information + * @param[out] mute The volume mute state : (@c 0 = unmute, @c 1 = mute) + * + * @return @c 0 on success, + * otherwise a negative error value + * @retval #AUDIO_RET_OK Success + * @see audio_set_volume_mute() + */ +audio_return_t audio_get_volume_mute(void *audio_handle, audio_volume_info_t *info, uint32_t *mute); + +/** + * @brief Sets the volume mute specified for a particular volume information. + * @since_tizen 3.0 + * @param[in] audio_handle The audio hal handle + * @param[in] info The audio volume information + * @param[in] mute The volume mute state to be set : (@c 0 = unmute, @c 1 = mute) + * + * @return @c 0 on success, + * otherwise a negative error value + * @retval #AUDIO_RET_OK Success + * @see audio_get_volume_mute() + */ +audio_return_t audio_set_volume_mute(void *audio_handle, audio_volume_info_t *info, uint32_t mute); + +/** + * @brief Updates the audio routing according to audio route information. + * @since_tizen 3.0 + * @param[in] audio_handle The audio hal handle + * @param[in] info The audio route information including role and devices + * + * @return @c 0 on success, + * otherwise a negative error value + * @retval #AUDIO_RET_OK Success + * @see audio_update_route_option() + */ +audio_return_t audio_update_route(void *audio_handle, audio_route_info_t *info); + +/** + * @brief Updates audio routing option according to audio route option. + * @since_tizen 3.0 + * @param[in] audio_handle The audio hal handle + * @param[in] option The option that can be used for audio routing including role, name and value + * + * @remarks This option can be used for audio routing.\n + * It is recommended to apply this option for routing per each role. + * + * @return @c 0 on success, + * otherwise a negative error value + * @retval #AUDIO_RET_OK Success + * @see audio_update_route() + */ +audio_return_t audio_update_route_option(void *audio_handle, audio_route_option_t *option); + +/** + * @brief Gets notified when a stream is connected and disconnected. + * @since_tizen 3.0 + * @param[in] audio_handle The audio hal handle + * @param[in] info The stream information including role, direction, index + * @param[in] is_connected The connection state of this stream (@c true = connected, @c false = disconnected) + * + * @remarks This information can be used for audio routing, volume controls and so on. + * + * @return @c 0 on success, + * otherwise a negative error value + * @retval #AUDIO_RET_OK Success + */ +audio_return_t audio_notify_stream_connection_changed(void *audio_handle, audio_stream_info_t *info, uint32_t is_connected); + +/** + * @brief Opens a PCM device. + * @since_tizen 3.0 + * @param[in] audio_handle The audio hal handle + * @param[out] pcm_handle The PCM handle + * @param[in] direction The direction of PCM + * @param[in] sample_spec The sample specification + * @param[in] period_size The period size + * @param[in] periods The periods + * + * @return @c 0 on success, + * otherwise a negative error value + * @retval #AUDIO_RET_OK Success + * @see audio_pcm_close() + */ +audio_return_t audio_pcm_open(void *audio_handle, void **pcm_handle, uint32_t direction, void *sample_spec, uint32_t period_size, uint32_t periods); + +/** + * @brief Starts a PCM device. + * @since_tizen 3.0 + * @param[in] audio_handle The audio hal handle + * @param[in] pcm_handle The PCM handle to be started + * + * @return @c 0 on success, + * otherwise a negative error value + * @retval #AUDIO_RET_OK Success + * @see audio_pcm_avail() + * @see audio_pcm_write() + * @see audio_pcm_read() + * @see audio_pcm_stop() + * @see audio_pcm_recover() + */ +audio_return_t audio_pcm_start(void *audio_handle, void *pcm_handle); + +/** + * @brief Stops a PCM device. + * @since_tizen 3.0 + * @param[in] audio_handle The audio hal handle + * @param[in] pcm_handle The PCM handle to be stopped + * + * @return @c 0 on success, + * otherwise a negative error value + * @retval #AUDIO_RET_OK Success + * @see audio_pcm_start() + */ +audio_return_t audio_pcm_stop(void *audio_handle, void *pcm_handle); + +/** + * @brief Closes a PCM device. + * @since_tizen 3.0 + * @param[in] audio_handle The audio hal handle + * @param[in] pcm_handle The PCM handle to be closed + * + * @return @c 0 on success, + * otherwise a negative error value + * @retval #AUDIO_RET_OK Success + * @see audio_pcm_open() + */ +audio_return_t audio_pcm_close(void *audio_handle, void *pcm_handle); + +/** + * @brief Gets available number of frames. + * @since_tizen 3.0 + * @param[in] audio_handle The audio hal handle + * @param[in] pcm_handle The PCM handle + * @param[out] avail The available number of frames + * + * @return @c 0 on success, + * otherwise a negative error value + * @retval #AUDIO_RET_OK Success + * @see audio_pcm_write() + * @see audio_pcm_read() + */ +audio_return_t audio_pcm_avail(void *audio_handle, void *pcm_handle, uint32_t *avail); + +/** + * @brief Writes frames to a PCM device. + * @since_tizen 3.0 + * @param[in] audio_handle The audio hal handle + * @param[in] pcm_handle The PCM handle + * @param[in] buffer The buffer containing frames + * @param[in] frames The number of frames to be written + * + * @return @c 0 on success, + * otherwise a negative error value + * @retval #AUDIO_RET_OK Success + * @see audio_pcm_avail() + * @see audio_pcm_recover() + */ +audio_return_t audio_pcm_write(void *audio_handle, void *pcm_handle, const void *buffer, uint32_t frames); + +/** + * @brief Reads frames from a PCM device. + * @since_tizen 3.0 + * @param[in] audio_handle The audio hal handle + * @param[in] pcm_handle The PCM handle + * @param[out] buffer The buffer containing frames + * @param[in] frames The number of frames to be read + * + * @return @c 0 on success, + * otherwise a negative error value + * @retval #AUDIO_RET_OK Success + * @see audio_pcm_avail() + * @see audio_pcm_recover() + */ +audio_return_t audio_pcm_read(void *audio_handle, void *pcm_handle, void *buffer, uint32_t frames); + +/** + * @brief Gets poll descriptor for a PCM handle. + * @since_tizen 3.0 + * @param[in] audio_handle The audio hal handle + * @param[in] pcm_handle The PCM handle + * @param[out] fd The poll descriptor + * + * @return @c 0 on success, + * otherwise a negative error value + * @retval #AUDIO_RET_OK Success + * @see audio_pcm_open() + * @see audio_pcm_recover() + */ +audio_return_t audio_pcm_get_fd(void *audio_handle, void *pcm_handle, int *fd); + +/** + * @brief Recovers the PCM state. + * @since_tizen 3.0 + * @param[in] audio_handle The audio hal handle + * @param[in] pcm_handle The PCM handle + * @param[in] revents The returned event from pollfd + * + * @return @c 0 on success, + * otherwise a negative error value + * @retval #AUDIO_RET_OK Success + * @see audio_pcm_start() + * @see audio_pcm_write() + * @see audio_pcm_read() + * @see audio_pcm_get_fd() + */ +audio_return_t audio_pcm_recover(void *audio_handle, void *pcm_handle, int revents); + +/** + * @brief Gets parameters of a PCM device. + * @since_tizen 3.0 + * @param[in] audio_handle The audio hal handle + * @param[in] pcm_handle The PCM handle + * @param[in] direction The direction of PCM + * @param[out] sample_spec The sample specification + * @param[out] period_size The period size + * @param[out] periods The periods + * + * @return @c 0 on success, + * otherwise a negative error value + * @retval #AUDIO_RET_OK Success + * @see audio_pcm_set_params() + */ +audio_return_t audio_pcm_get_params(void *audio_handle, void *pcm_handle, uint32_t direction, void **sample_spec, uint32_t *period_size, uint32_t *periods); + +/** + * @brief Sets hardware and software parameters of a PCM device. + * @since_tizen 3.0 + * @param[in] audio_handle The audio hal handle + * @param[in] pcm_handle The PCM handle + * @param[in] direction The direction of PCM + * @param[in] sample_spec The sample specification + * @param[in] period_size The period size + * @param[in] periods The periods + * + * @return @c 0 on success, + * otherwise a negative error value + * @retval #AUDIO_RET_OK Success + * @see audio_pcm_set_params() + */ +audio_return_t audio_pcm_set_params(void *audio_handle, void *pcm_handle, uint32_t direction, void *sample_spec, uint32_t period_size, uint32_t periods); + +/** +* @} +*/ + +/** +* @} +*/ + +#endif -- 2.7.4 From 6f001fe9314a1aba1c957e5478cbc1d1c703b94f Mon Sep 17 00:00:00 2001 From: Lee Hackseung Date: Wed, 28 Jun 2017 11:53:52 +0900 Subject: [PATCH 03/15] Remove SPEAKER, MIC and JACK Does not support these devices. Change-Id: I9fd6ea8f95a2824de69e556cb557265b909e6148 --- tizen-audio-routing.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tizen-audio-routing.c b/tizen-audio-routing.c index 8be716b..0cdadb6 100644 --- a/tizen-audio-routing.c +++ b/tizen-audio-routing.c @@ -32,8 +32,6 @@ /* #define DEBUG_TIMING */ static device_type_t outDeviceTypes[] = { - { AUDIO_DEVICE_OUT_SPEAKER, "Speaker" }, - { AUDIO_DEVICE_OUT_JACK, "Headphones" }, { AUDIO_DEVICE_OUT_BT_SCO, "Bluetooth" }, { AUDIO_DEVICE_OUT_AUX, "Line" }, { AUDIO_DEVICE_OUT_HDMI, "HDMI" }, @@ -41,8 +39,6 @@ static device_type_t outDeviceTypes[] = { }; static device_type_t inDeviceTypes[] = { - { AUDIO_DEVICE_IN_MAIN_MIC, "MainMic" }, - { AUDIO_DEVICE_IN_JACK, "HeadsetMic" }, { AUDIO_DEVICE_IN_BT_SCO, "BT Mic" }, { 0, 0 }, }; -- 2.7.4 From 0f7f704a79b69ddf4d9733f6f883bf5168bc0d9e Mon Sep 17 00:00:00 2001 From: Lee Hackseung Date: Wed, 28 Jun 2017 17:30:57 +0900 Subject: [PATCH 04/15] Cleared all warnings when compiling tizen-audio-impl-pcm.c Change AUDIO_LOG_ERROR usage. Change-Id: I8cdafcf338ba8904d191d2fd32749747352b775d --- tizen-audio-impl-pcm.c | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/tizen-audio-impl-pcm.c b/tizen-audio-impl-pcm.c index e6327ea..273004d 100644 --- a/tizen-audio-impl-pcm.c +++ b/tizen-audio-impl-pcm.c @@ -186,8 +186,7 @@ audio_return_t _pcm_start(void *pcm_handle) return AUDIO_ERR_RESOURCE; } #endif - - AUDIO_LOG_INFO("PCM handle 0x%x start", pcm_handle); + AUDIO_LOG_INFO("PCM handle %p start", pcm_handle); return AUDIO_RET_OK; } @@ -207,15 +206,14 @@ audio_return_t _pcm_stop(void *pcm_handle) } #endif - AUDIO_LOG_INFO("PCM handle 0x%x stop", pcm_handle); + AUDIO_LOG_INFO("PCM handle %p stop", pcm_handle); return AUDIO_RET_OK; } audio_return_t _pcm_close(void *pcm_handle) { int err; - - AUDIO_LOG_INFO("Try to close PCM handle 0x%x", pcm_handle); + AUDIO_LOG_INFO("Try to close PCM handle %p", pcm_handle); #ifdef __USE_TINYALSA__ if ((err = pcm_close(pcm_handle)) < 0) { @@ -254,7 +252,7 @@ audio_return_t _pcm_avail(void *pcm_handle, uint32_t *avail) snd_pcm_sframes_t frames_avail; if ((frames_avail = snd_pcm_avail(pcm_handle)) < 0) { - AUDIO_LOG_ERROR("Could not get avail at PCM handle 0x%x : %d", pcm_handle, frames_avail); + AUDIO_LOG_ERROR("Could not get avail at PCM handle %p: %d", pcm_handle, (int)frames_avail); return AUDIO_ERR_IOCTL; } @@ -289,7 +287,7 @@ audio_return_t _pcm_write(void *pcm_handle, const void *buffer, uint32_t frames) frames_written = snd_pcm_writei(pcm_handle, buffer, (snd_pcm_uframes_t) frames); if (frames_written < 0) { - AUDIO_LOG_ERROR("Failed to write pcm : %d", frames_written); + AUDIO_LOG_ERROR("Failed to write pcm : %d", (int)frames_written); return AUDIO_ERR_IOCTL; } @@ -320,7 +318,7 @@ audio_return_t _pcm_read(void *pcm_handle, void *buffer, uint32_t frames) frames_read = snd_pcm_readi(pcm_handle, buffer, (snd_pcm_uframes_t)frames); if (frames_read < 0) { - AUDIO_LOG_ERROR("Failed to read pcm : %d", frames_read); + AUDIO_LOG_ERROR("Failed to read pcm : %d", (int)frames_read); return AUDIO_ERR_IOCTL; } @@ -475,7 +473,7 @@ audio_return_t _pcm_get_params(void *pcm_handle, uint32_t direction, void **samp (err = snd_pcm_hw_params_get_format(hwparams, &_format)) < 0 || (err = snd_pcm_hw_params_get_rate(hwparams, &_rate, &dir)) < 0 || (err = snd_pcm_hw_params_get_channels(hwparams, &_channels)) < 0) { - AUDIO_LOG_ERROR("snd_pcm_hw_params_get_{period_size|buffer_size|periods|format|rate|channels}() failed : %s", err); + AUDIO_LOG_ERROR("snd_pcm_hw_params_get_{period_size|buffer_size|periods|format|rate|channels}() failed : %d", err); return AUDIO_ERR_PARAMETER; } @@ -494,10 +492,10 @@ audio_return_t _pcm_get_params(void *pcm_handle, uint32_t direction, void **samp (err = snd_pcm_sw_params_get_stop_threshold(swparams, &_stop_threshold)) < 0 || (err = snd_pcm_sw_params_get_silence_threshold(swparams, &_silence_threshold)) < 0 || (err = snd_pcm_sw_params_get_avail_min(swparams, &_avail_min)) < 0) { - AUDIO_LOG_ERROR("snd_pcm_sw_params_get_{start_threshold|stop_threshold|silence_threshold|avail_min}() failed : %s", err); + AUDIO_LOG_ERROR("snd_pcm_sw_params_get_{start_threshold|stop_threshold|silence_threshold|avail_min}() failed : %d", err); } - AUDIO_LOG_DEBUG("_pcm_get_params (handle 0x%x, format %d, rate %d, channels %d, period_size %d, periods %d, buffer_size %d)", pcm_handle, _format, _rate, _channels, _period_size, _periods, _buffer_size); + AUDIO_LOG_DEBUG("_pcm_get_params (handle %p, format %d, rate %d, channels %d, period_size %d, periods %d, buffer_size %d)", pcm_handle, _format, _rate, _channels, (int)_period_size, _periods, (int)_buffer_size); #endif return AUDIO_RET_OK; @@ -548,12 +546,12 @@ audio_return_t _pcm_set_params(void *pcm_handle, uint32_t direction, void *sampl } if ((err = snd_pcm_hw_params_set_channels(pcm_handle, hwparams, ss.channels)) < 0) { - AUDIO_LOG_ERROR("snd_pcm_hw_params_set_channels(%u) failed : %d", err); + AUDIO_LOG_ERROR("snd_pcm_hw_params_set_channels(%u) failed : %d", ss.channels, err); return AUDIO_ERR_PARAMETER; } if ((err = snd_pcm_hw_params_set_period_size(pcm_handle, hwparams, period_size, 0)) < 0) { - AUDIO_LOG_ERROR("snd_pcm_hw_params_set_period_size(%u) failed : %d", err); + AUDIO_LOG_ERROR("snd_pcm_hw_params_set_period_size(%u) failed : %d", period_size,err); return AUDIO_ERR_PARAMETER; } @@ -610,7 +608,7 @@ audio_return_t _pcm_set_params(void *pcm_handle, uint32_t direction, void *sampl return AUDIO_ERR_IOCTL; } - AUDIO_LOG_DEBUG("_pcm_set_params (handle 0x%x, format %d, rate %d, channels %d, period_size %d, periods %d, buffer_size %d)", pcm_handle, ss.format, ss.rate, ss.channels, period_size, periods, _buffer_size); + AUDIO_LOG_DEBUG("_pcm_set_params (handle %p, format %d, rate %d, channels %d, period_size %d, periods %d, buffer_size %d)", pcm_handle, ss.format, ss.rate, ss.channels, period_size, periods,(int) _buffer_size); #endif return AUDIO_RET_OK; -- 2.7.4 From e7c2c32d942de45be4a2a1f02b217d42c971a4ec Mon Sep 17 00:00:00 2001 From: Youngjae Shin Date: Tue, 22 Aug 2017 10:54:07 +0900 Subject: [PATCH 05/15] revise installing a license file Change-Id: I03eeecb23c2cafb89433856bd1cf3d5858334688 --- packaging/audio-hal-bcm2837.spec | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packaging/audio-hal-bcm2837.spec b/packaging/audio-hal-bcm2837.spec index b011c08..dc25b07 100644 --- a/packaging/audio-hal-bcm2837.spec +++ b/packaging/audio-hal-bcm2837.spec @@ -33,8 +33,6 @@ make %{?jobs:-j%jobs} %install rm -rf %{buildroot} -mkdir -p %{buildroot}%{_datadir}/license -cp LICENSE.Apache-2.0 %{buildroot}%{_datadir}/license/%{name} %make_install %post @@ -47,4 +45,4 @@ cp LICENSE.Apache-2.0 %{buildroot}%{_datadir}/license/%{name} %manifest audio-hal-bcm2837.manifest %defattr(-,root,root,-) %{_libdir}/libtizen-audio.so -%{_datadir}/license/%{name} +%license LICENSE.Apache-2.0 -- 2.7.4 From 2b8a3e38fddf546b6aee93fa01b9ae1fda9be849 Mon Sep 17 00:00:00 2001 From: Lee Hackseung Date: Thu, 21 Sep 2017 10:39:18 +0900 Subject: [PATCH 06/15] alsa: change PLAYBACK_PCM_DEVICE value New PLAYBACK_PCM_DEVICE value is "hw:1,0". Starting with version 4.9.39 of the Tizen-rpi3 kernel, there are two playback devices. So the default playback device is second. tizen-audio-impl-pcm.c -> _pcm_open() -> snd_pcm_open(PLAYBACK_PCM_DEVICE) Please see below: **** List of PLAYBACK Hardware Devices **** card 0: vc4hdmi [vc4-hdmi], device 0: MAI PCM vc4-hdmi-hifi-0 [] Subdevices: 1/1 Subdevice #0: subdevice #0 card 1: ALSA [bcm2835 ALSA], device 0: bcm2835 ALSA [bcm2835 ALSA] Subdevices: 8/8 Subdevice #0: subdevice #0 Subdevice #1: subdevice #1 Subdevice #2: subdevice #2 Subdevice #3: subdevice #3 Subdevice #4: subdevice #4 Subdevice #5: subdevice #5 Subdevice #6: subdevice #6 Subdevice #7: subdevice #7 card 1: ALSA [bcm2835 ALSA], device 1: bcm2835 ALSA [bcm2835 IEC958/HDMI] Subdevices: 1/1 Subdevice #0: subdevice #0 Change-Id: I6142cb904ba9eb6ce4867d3cf325e41676eb4a9b Signed-off-by: Hackseung Lee --- tizen-audio-internal.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tizen-audio-internal.h b/tizen-audio-internal.h index 81d570b..7fa706c 100644 --- a/tizen-audio-internal.h +++ b/tizen-audio-internal.h @@ -124,7 +124,7 @@ typedef struct device_type { #define strneq strcmp #define ALSA_DEFAULT_CARD "bcm2835" -#define PLAYBACK_PCM_DEVICE "hw:0,0" +#define PLAYBACK_PCM_DEVICE "hw:1,0" #define CAPTURE_PCM_DEVICE "hw:0,0" /* hw:0,0 */ -- 2.7.4 From c37c9105f415bc8498fd0f793533fdb985466ed9 Mon Sep 17 00:00:00 2001 From: Jungsup Lee Date: Tue, 26 Jun 2018 14:38:32 +0900 Subject: [PATCH 07/15] Card and device arguments are added to pcm open API [Version] 0.1.1 [Issue Type] API Change-Id: Ia1ba2a63b3aa3212e756debf548611046ebb9495 Signed-off-by: Sangchul Lee --- packaging/audio-hal-bcm2837.spec | 2 +- tizen-audio-impl-pcm.c | 89 ++++++++++++++++++++++++++++------------ tizen-audio-impl.h | 2 +- tizen-audio-internal.h | 10 ----- tizen-audio-pcm.c | 9 ++-- tizen-audio.h | 8 ++-- 6 files changed, 75 insertions(+), 45 deletions(-) diff --git a/packaging/audio-hal-bcm2837.spec b/packaging/audio-hal-bcm2837.spec index dc25b07..c6090e4 100644 --- a/packaging/audio-hal-bcm2837.spec +++ b/packaging/audio-hal-bcm2837.spec @@ -1,6 +1,6 @@ Name: audio-hal-bcm2837 Summary: TIZEN Audio HAL for BCM2837 -Version: 0.1.0 +Version: 0.1.1 Release: 0 Group: System/Libraries License: Apache-2.0 diff --git a/tizen-audio-impl-pcm.c b/tizen-audio-impl-pcm.c index 273004d..6628e4e 100644 --- a/tizen-audio-impl-pcm.c +++ b/tizen-audio-impl-pcm.c @@ -29,6 +29,10 @@ #include "tizen-audio-internal.h" #include "tizen-audio-impl.h" +#ifndef __USE_TINYALSA__ +#define DEVICE_NAME_MAX 32 +#endif + #ifdef __USE_TINYALSA__ /* Convert pcm format from pulse to alsa */ static const uint32_t g_format_convert_table[] = { @@ -66,11 +70,27 @@ static uint32_t __convert_format(audio_sample_format_t format) /* #define DEBUG_TIMING */ #ifdef __USE_TINYALSA__ -static struct pcm *__tinyalsa_open_device(audio_pcm_sample_spec_t *ss, size_t period_size, size_t period_count, uint32_t direction) +static int __parse_card_device_number(const char *card, const char *device, unsigned int *card_u, unsigned int *device_u) { + AUDIO_RETURN_VAL_IF_FAIL(card, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(device, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(card_u, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(device_u, AUDIO_ERR_PARAMETER); + + AUDIO_LOG_DEBUG("card : %s, device : %s", card, device); + + *card_u = (unsigned int) strtol(card, NULL, 10); + *device_u = (unsigned int) strtol(device, NULL, 10); + + return 0; +} + +static struct pcm *__tinyalsa_open_device(const char *card, const char *device, audio_pcm_sample_spec_t *ss, size_t period_size, size_t period_count, uint32_t direction) { struct pcm *pcm = NULL; struct pcm_config config; + unsigned int card_u, device_u; + AUDIO_RETURN_NULL_IF_FAIL(device); AUDIO_RETURN_NULL_IF_FAIL(ss); config.channels = ss->channels; @@ -82,12 +102,15 @@ static struct pcm *__tinyalsa_open_device(audio_pcm_sample_spec_t *ss, size_t pe config.stop_threshold = 0xFFFFFFFF; config.silence_threshold = 0; - AUDIO_LOG_INFO("direction %d, channels %d, rate %d, format %d, period_size %d, period_count %d", direction, ss->channels, ss->rate, ss->format, period_size, period_count); + AUDIO_LOG_INFO("card %s, device %s, direction %d, channels %d, rate %d, format %d, period_size %d, period_count %d", + card, device, direction, ss->channels, ss->rate, ss->format, period_size, period_count); + + if (__parse_card_device_number(card, device, &card_u, &device_u) < 0) { + AUDIO_LOG_ERROR("Failed to get card device number from %s", device); + return NULL; + } - pcm = pcm_open((direction == AUDIO_DIRECTION_OUT) ? PLAYBACK_CARD_ID : CAPTURE_CARD_ID, - (direction == AUDIO_DIRECTION_OUT) ? PLAYBACK_PCM_DEVICE_ID : CAPTURE_PCM_DEVICE_ID, - (direction == AUDIO_DIRECTION_OUT) ? PCM_OUT : PCM_IN, - &config); + pcm = pcm_open(card_u, device_u, (direction == AUDIO_DIRECTION_OUT) ? PCM_OUT : PCM_IN, &config); if (!pcm || !pcm_is_ready(pcm)) { AUDIO_LOG_ERROR("Unable to open device (%s)", pcm_get_error(pcm)); pcm_close(pcm); @@ -121,16 +144,37 @@ static int __tinyalsa_pcm_recover(struct pcm *pcm, int err) } #endif -audio_return_t _pcm_open(void **pcm_handle, uint32_t direction, void *sample_spec, uint32_t period_size, uint32_t periods) +#ifndef __USE_TINYALSA__ +static int __make_alsa_device_name(const char *card, const char *device, char device_name[]) { + AUDIO_RETURN_VAL_IF_FAIL(card, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(device, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(device_name, AUDIO_ERR_PARAMETER); + + snprintf(device_name, DEVICE_NAME_MAX, "hw:%s,%s", card, device); + return 0; +} +#endif + +audio_return_t _pcm_open(const char *card, const char *device, uint32_t direction, void *sample_spec, + uint32_t period_size, uint32_t periods, void **pcm_handle) +{ + int err; + + AUDIO_RETURN_VAL_IF_FAIL(card, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(device, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL((direction == AUDIO_DIRECTION_OUT) || (direction == AUDIO_DIRECTION_IN), + AUDIO_ERR_PARAMETER); + + AUDIO_LOG_INFO("card(%s) device(%s) direction(%u) period_size(%u) periods(%u)", + card, device, direction, period_size, periods); #ifdef __USE_TINYALSA__ audio_pcm_sample_spec_t *ss; - int err; ss = (audio_pcm_sample_spec_t *)sample_spec; ss->format = __convert_format((audio_sample_format_t)ss->format); - *pcm_handle = __tinyalsa_open_device(ss, (size_t)period_size, (size_t)periods, direction); + *pcm_handle = __tinyalsa_open_device(card, device, ss, (size_t)period_size, (size_t)periods, direction); if (*pcm_handle == NULL) { AUDIO_LOG_ERROR("Error opening PCM device"); return AUDIO_ERR_RESOURCE; @@ -141,28 +185,21 @@ audio_return_t _pcm_open(void **pcm_handle, uint32_t direction, void *sample_spe } #else /* alsa-lib */ - int err, mode; - char *device_name = NULL; + int mode; + audio_return_t ret; + char device_name[DEVICE_NAME_MAX]; + __make_alsa_device_name(card, device, device_name); mode = SND_PCM_NONBLOCK | SND_PCM_NO_AUTO_RESAMPLE | SND_PCM_NO_AUTO_CHANNELS | SND_PCM_NO_AUTO_FORMAT; - if (direction == AUDIO_DIRECTION_OUT) - device_name = PLAYBACK_PCM_DEVICE; - else if (direction == AUDIO_DIRECTION_IN) - device_name = CAPTURE_PCM_DEVICE; - else { - AUDIO_LOG_ERROR("Error get device_name, direction : %d", direction); - return AUDIO_ERR_RESOURCE; - } - 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)); return AUDIO_ERR_RESOURCE; } - if ((err = _pcm_set_params(*pcm_handle, direction, sample_spec, period_size, periods)) != AUDIO_RET_OK) { - AUDIO_LOG_ERROR("Failed to set pcm parameters : %d", err); - return err; + if ((ret = _pcm_set_params(*pcm_handle, direction, sample_spec, period_size, periods)) != AUDIO_RET_OK) { + AUDIO_LOG_ERROR("Failed to set pcm parameters : %d", ret); + return ret; } AUDIO_LOG_INFO("PCM device %s", device_name); @@ -546,12 +583,12 @@ audio_return_t _pcm_set_params(void *pcm_handle, uint32_t direction, void *sampl } if ((err = snd_pcm_hw_params_set_channels(pcm_handle, hwparams, ss.channels)) < 0) { - AUDIO_LOG_ERROR("snd_pcm_hw_params_set_channels(%u) failed : %d", ss.channels, err); + AUDIO_LOG_ERROR("snd_pcm_hw_params_set_channels(%u) failed : %d", ss.channels, err); return AUDIO_ERR_PARAMETER; } if ((err = snd_pcm_hw_params_set_period_size(pcm_handle, hwparams, period_size, 0)) < 0) { - AUDIO_LOG_ERROR("snd_pcm_hw_params_set_period_size(%u) failed : %d", period_size,err); + AUDIO_LOG_ERROR("snd_pcm_hw_params_set_period_size(%u) failed : %d", period_size, err); return AUDIO_ERR_PARAMETER; } @@ -562,7 +599,7 @@ audio_return_t _pcm_set_params(void *pcm_handle, uint32_t direction, void *sampl _buffer_size = period_size * periods; if ((err = snd_pcm_hw_params_set_buffer_size(pcm_handle, hwparams, _buffer_size)) < 0) { - AUDIO_LOG_ERROR("snd_pcm_hw_params_set_buffer_size(%u) failed : %d", periods * periods, err); + AUDIO_LOG_ERROR("snd_pcm_hw_params_set_buffer_size(%u) failed : %d", _buffer_size, err); return AUDIO_ERR_PARAMETER; } diff --git a/tizen-audio-impl.h b/tizen-audio-impl.h index 4287ac8..b7ece02 100644 --- a/tizen-audio-impl.h +++ b/tizen-audio-impl.h @@ -21,7 +21,7 @@ */ /* PCM */ -audio_return_t _pcm_open(void **pcm_handle, uint32_t direction, void *sample_spec, uint32_t period_size, uint32_t periods); +audio_return_t _pcm_open(const char *card, const char *device, uint32_t direction, void *sample_spec, uint32_t period_size, uint32_t periods, void **pcm_handle); audio_return_t _pcm_start(void *pcm_handle); audio_return_t _pcm_stop(void *pcm_handle); audio_return_t _pcm_close(void *pcm_handle); diff --git a/tizen-audio-internal.h b/tizen-audio-internal.h index 7fa706c..8f2f2f9 100644 --- a/tizen-audio-internal.h +++ b/tizen-audio-internal.h @@ -124,16 +124,6 @@ typedef struct device_type { #define strneq strcmp #define ALSA_DEFAULT_CARD "bcm2835" -#define PLAYBACK_PCM_DEVICE "hw:1,0" -#define CAPTURE_PCM_DEVICE "hw:0,0" - -/* hw:0,0 */ -#define PLAYBACK_CARD_ID 0 -#define PLAYBACK_PCM_DEVICE_ID 0 - -/* hw:0,0 */ -#define CAPTURE_CARD_ID 0 -#define CAPTURE_PCM_DEVICE_ID 0 #define MAX_DEVICES 5 #define MAX_MODIFIERS 5 diff --git a/tizen-audio-pcm.c b/tizen-audio-pcm.c index 0a09cba..b18ad7e 100644 --- a/tizen-audio-pcm.c +++ b/tizen-audio-pcm.c @@ -45,7 +45,8 @@ audio_return_t _audio_pcm_deinit(audio_hal_t *ah) return AUDIO_RET_OK; } -audio_return_t audio_pcm_open(void *audio_handle, void **pcm_handle, uint32_t direction, void *sample_spec, uint32_t period_size, uint32_t periods) +audio_return_t audio_pcm_open(void *audio_handle, const char *card, const char *device, uint32_t direction, void *sample_spec, + uint32_t period_size, uint32_t periods, void **pcm_handle) { audio_return_t audio_ret = AUDIO_RET_OK; audio_hal_t *ah = NULL; @@ -56,12 +57,12 @@ audio_return_t audio_pcm_open(void *audio_handle, void **pcm_handle, uint32_t di AUDIO_RETURN_VAL_IF_FAIL((period_size > 0), AUDIO_ERR_PARAMETER); AUDIO_RETURN_VAL_IF_FAIL((periods > 0), AUDIO_ERR_PARAMETER); - if ((audio_ret = _pcm_open(pcm_handle, direction, sample_spec, period_size, periods))) + if ((audio_ret = _pcm_open(card, device, direction, sample_spec, period_size, periods, pcm_handle))) return audio_ret; ah = (audio_hal_t*)audio_handle; ah->device.pcm_count++; - AUDIO_LOG_INFO("Opening PCM handle 0x%x", *pcm_handle); + AUDIO_LOG_INFO("Opening PCM handle 0x%x", (unsigned int)*pcm_handle); return AUDIO_RET_OK; } @@ -200,4 +201,4 @@ audio_return_t audio_pcm_set_params(void *audio_handle, void *pcm_handle, uint32 audio_ret = _pcm_set_params(pcm_handle, direction, sample_spec, period_size, periods); return audio_ret; -} \ No newline at end of file +} diff --git a/tizen-audio.h b/tizen-audio.h index 282f7f0..d752d89 100644 --- a/tizen-audio.h +++ b/tizen-audio.h @@ -125,7 +125,7 @@ typedef struct audio_interface { /* Stream */ audio_return_t (*notify_stream_connection_changed)(void *audio_handle, audio_stream_info_t *info, uint32_t is_connected); /* PCM */ - audio_return_t (*pcm_open)(void *audio_handle, void **pcm_handle, uint32_t direction, void *sample_spec, uint32_t period_size, uint32_t periods); + audio_return_t (*pcm_open)(void *audio_handle, const char *card, const char *device, uint32_t direction, void *sample_spec, uint32_t period_size, uint32_t periods, void **pcm_handle); audio_return_t (*pcm_start)(void *audio_handle, void *pcm_handle); audio_return_t (*pcm_stop)(void *audio_handle, void *pcm_handle); audio_return_t (*pcm_close)(void *audio_handle, void *pcm_handle); @@ -303,18 +303,20 @@ audio_return_t audio_notify_stream_connection_changed(void *audio_handle, audio_ * @brief Opens a PCM device. * @since_tizen 3.0 * @param[in] audio_handle The audio hal handle - * @param[out] pcm_handle The PCM handle + * @param[in] card The card of PCM + * @param[in] device The device of PCM * @param[in] direction The direction of PCM * @param[in] sample_spec The sample specification * @param[in] period_size The period size * @param[in] periods The periods + * @param[out] pcm_handle The PCM handle * * @return @c 0 on success, * otherwise a negative error value * @retval #AUDIO_RET_OK Success * @see audio_pcm_close() */ -audio_return_t audio_pcm_open(void *audio_handle, void **pcm_handle, uint32_t direction, void *sample_spec, uint32_t period_size, uint32_t periods); +audio_return_t audio_pcm_open(void *audio_handle, const char *card, const char *device, uint32_t direction, void *sample_spec, uint32_t period_size, uint32_t periods, void **pcm_handle); /** * @brief Starts a PCM device. -- 2.7.4 From 0ba8563bb452f737b1dafcc78a2cf03463e2b35a Mon Sep 17 00:00:00 2001 From: Seungbae Shin Date: Fri, 14 Dec 2018 15:50:05 +0900 Subject: [PATCH 08/15] Fix invalid format string [Version] 0.1.2 [Issue Type] Build Change-Id: Ib469e12d1d1324e4a1bcbaa51afce9f42b7f1b88 --- packaging/audio-hal-bcm2837.spec | 2 +- tizen-audio-impl-pcm.c | 31 ++++++++++++++++++------------- tizen-audio-pcm.c | 2 +- 3 files changed, 20 insertions(+), 15 deletions(-) diff --git a/packaging/audio-hal-bcm2837.spec b/packaging/audio-hal-bcm2837.spec index c6090e4..5f1dfed 100644 --- a/packaging/audio-hal-bcm2837.spec +++ b/packaging/audio-hal-bcm2837.spec @@ -1,6 +1,6 @@ Name: audio-hal-bcm2837 Summary: TIZEN Audio HAL for BCM2837 -Version: 0.1.1 +Version: 0.1.2 Release: 0 Group: System/Libraries License: Apache-2.0 diff --git a/tizen-audio-impl-pcm.c b/tizen-audio-impl-pcm.c index 6628e4e..dc93a90 100644 --- a/tizen-audio-impl-pcm.c +++ b/tizen-audio-impl-pcm.c @@ -223,7 +223,8 @@ audio_return_t _pcm_start(void *pcm_handle) return AUDIO_ERR_RESOURCE; } #endif - AUDIO_LOG_INFO("PCM handle %p start", pcm_handle); + + AUDIO_LOG_INFO("PCM handle %p start", pcm_handle); return AUDIO_RET_OK; } @@ -243,14 +244,15 @@ audio_return_t _pcm_stop(void *pcm_handle) } #endif - AUDIO_LOG_INFO("PCM handle %p stop", pcm_handle); + AUDIO_LOG_INFO("PCM handle %p stop", pcm_handle); return AUDIO_RET_OK; } audio_return_t _pcm_close(void *pcm_handle) { int err; - AUDIO_LOG_INFO("Try to close PCM handle %p", pcm_handle); + + AUDIO_LOG_INFO("Try to close PCM handle %p", pcm_handle); #ifdef __USE_TINYALSA__ if ((err = pcm_close(pcm_handle)) < 0) { @@ -276,7 +278,7 @@ audio_return_t _pcm_avail(void *pcm_handle, uint32_t *avail) err = pcm_get_htimestamp(pcm_handle, &frames_avail, &tspec); if (err < 0) { - AUDIO_LOG_ERROR("Could not get avail and timespec at PCM handle 0x%x : %d", pcm_handle, err); + AUDIO_LOG_ERROR("Could not get avail and timespec at PCM handle %p : %d", pcm_handle, err); return AUDIO_ERR_IOCTL; } @@ -289,7 +291,7 @@ audio_return_t _pcm_avail(void *pcm_handle, uint32_t *avail) snd_pcm_sframes_t frames_avail; if ((frames_avail = snd_pcm_avail(pcm_handle)) < 0) { - AUDIO_LOG_ERROR("Could not get avail at PCM handle %p: %d", pcm_handle, (int)frames_avail); + AUDIO_LOG_ERROR("Could not get avail at PCM handle %p : %ld", pcm_handle, frames_avail); return AUDIO_ERR_IOCTL; } @@ -324,7 +326,7 @@ audio_return_t _pcm_write(void *pcm_handle, const void *buffer, uint32_t frames) frames_written = snd_pcm_writei(pcm_handle, buffer, (snd_pcm_uframes_t) frames); if (frames_written < 0) { - AUDIO_LOG_ERROR("Failed to write pcm : %d", (int)frames_written); + AUDIO_LOG_ERROR("Failed to write pcm : %ld", frames_written); return AUDIO_ERR_IOCTL; } @@ -355,7 +357,7 @@ audio_return_t _pcm_read(void *pcm_handle, void *buffer, uint32_t frames) frames_read = snd_pcm_readi(pcm_handle, buffer, (snd_pcm_uframes_t)frames); if (frames_read < 0) { - AUDIO_LOG_ERROR("Failed to read pcm : %d", (int)frames_read); + AUDIO_LOG_ERROR("Failed to read pcm : %ld", frames_read); return AUDIO_ERR_IOCTL; } @@ -481,7 +483,8 @@ audio_return_t _pcm_get_params(void *pcm_handle, uint32_t direction, void **samp _stop_threshold = config->stop_threshold; _silence_threshold = config->silence_threshold; - AUDIO_LOG_DEBUG("_pcm_get_params (handle 0x%x, format %d, rate %d, channels %d, period_size %d, periods %d, buffer_size %d)", pcm_handle, config->format, config->rate, config->channels, config->period_size, config->period_count, _buffer_size); + AUDIO_LOG_DEBUG("_pcm_get_params (handle %p, format %d, rate %u, channels %u, period_size %u, periods %u, buffer_size %u)", + pcm_handle, config->format, config->rate, config->channels, config->period_size, config->period_count, _buffer_size); #else /* alsa-lib */ int err; audio_pcm_sample_spec_t *ss; @@ -510,7 +513,7 @@ audio_return_t _pcm_get_params(void *pcm_handle, uint32_t direction, void **samp (err = snd_pcm_hw_params_get_format(hwparams, &_format)) < 0 || (err = snd_pcm_hw_params_get_rate(hwparams, &_rate, &dir)) < 0 || (err = snd_pcm_hw_params_get_channels(hwparams, &_channels)) < 0) { - AUDIO_LOG_ERROR("snd_pcm_hw_params_get_{period_size|buffer_size|periods|format|rate|channels}() failed : %d", err); + AUDIO_LOG_ERROR("snd_pcm_hw_params_get_{period_size|buffer_size|periods|format|rate|channels}() failed : %d", err); return AUDIO_ERR_PARAMETER; } @@ -529,10 +532,11 @@ audio_return_t _pcm_get_params(void *pcm_handle, uint32_t direction, void **samp (err = snd_pcm_sw_params_get_stop_threshold(swparams, &_stop_threshold)) < 0 || (err = snd_pcm_sw_params_get_silence_threshold(swparams, &_silence_threshold)) < 0 || (err = snd_pcm_sw_params_get_avail_min(swparams, &_avail_min)) < 0) { - AUDIO_LOG_ERROR("snd_pcm_sw_params_get_{start_threshold|stop_threshold|silence_threshold|avail_min}() failed : %d", err); + AUDIO_LOG_ERROR("snd_pcm_sw_params_get_{start_threshold|stop_threshold|silence_threshold|avail_min}() failed : %d", err); } - AUDIO_LOG_DEBUG("_pcm_get_params (handle %p, format %d, rate %d, channels %d, period_size %d, periods %d, buffer_size %d)", pcm_handle, _format, _rate, _channels, (int)_period_size, _periods, (int)_buffer_size); + AUDIO_LOG_DEBUG("_pcm_get_params (handle %p, format %d, rate %u, channels %u, period_size %lu, periods %u, buffer_size %lu)", + pcm_handle, _format, _rate, _channels, _period_size, _periods, _buffer_size); #endif return AUDIO_RET_OK; @@ -599,7 +603,7 @@ audio_return_t _pcm_set_params(void *pcm_handle, uint32_t direction, void *sampl _buffer_size = period_size * periods; if ((err = snd_pcm_hw_params_set_buffer_size(pcm_handle, hwparams, _buffer_size)) < 0) { - AUDIO_LOG_ERROR("snd_pcm_hw_params_set_buffer_size(%u) failed : %d", _buffer_size, err); + AUDIO_LOG_ERROR("snd_pcm_hw_params_set_buffer_size(%lu) failed : %d", _buffer_size, err); return AUDIO_ERR_PARAMETER; } @@ -645,7 +649,8 @@ audio_return_t _pcm_set_params(void *pcm_handle, uint32_t direction, void *sampl return AUDIO_ERR_IOCTL; } - AUDIO_LOG_DEBUG("_pcm_set_params (handle %p, format %d, rate %d, channels %d, period_size %d, periods %d, buffer_size %d)", pcm_handle, ss.format, ss.rate, ss.channels, period_size, periods,(int) _buffer_size); + AUDIO_LOG_DEBUG("_pcm_set_params (handle %p, format %d, rate %u, channels %u, period_size %u, periods %u, buffer_size %lu)", + pcm_handle, ss.format, ss.rate, ss.channels, period_size, periods, _buffer_size); #endif return AUDIO_RET_OK; diff --git a/tizen-audio-pcm.c b/tizen-audio-pcm.c index b18ad7e..c12c196 100644 --- a/tizen-audio-pcm.c +++ b/tizen-audio-pcm.c @@ -62,7 +62,7 @@ audio_return_t audio_pcm_open(void *audio_handle, const char *card, const char * ah = (audio_hal_t*)audio_handle; ah->device.pcm_count++; - AUDIO_LOG_INFO("Opening PCM handle 0x%x", (unsigned int)*pcm_handle); + AUDIO_LOG_INFO("Opening PCM handle %p", *pcm_handle); return AUDIO_RET_OK; } -- 2.7.4 From 2029d986506f9a9974aad29d2a20af4119755bb5 Mon Sep 17 00:00:00 2001 From: Seungbae Shin Date: Tue, 26 Mar 2019 15:25:37 +0900 Subject: [PATCH 09/15] Force to use earjack only for headless profile [Version] 0.1.3 [Issue Type] Add Change-Id: Ic4142c971ac9c8a623b78c285b7c97d1ab40929b --- Makefile.am | 11 +++++------ configure.ac | 4 ++++ packaging/audio-hal-bcm2837.spec | 3 ++- tizen-audio-routing.c | 23 +++++++++++++++++++++++ 4 files changed, 34 insertions(+), 7 deletions(-) diff --git a/Makefile.am b/Makefile.am index 2543080..b93a076 100644 --- a/Makefile.am +++ b/Makefile.am @@ -10,12 +10,11 @@ libtizen_audio_la_SOURCES = tizen-audio.c \ tizen-audio-impl-ucm.c \ tizen-audio-impl-ctrl.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) $(SYSTEM_INFO_LIBS) +libtizen_audio_la_CFLAGS = $(AM_CFLAGS) $(ASOUNDLIB_CFLAGS) $(VCONF_CFLAGS) $(DLOG_CFLAGS) $(INIPARSER_CFLAGS) $(SYSTEM_INFO_CFLAGS) -DUSE_DLOG + if USE_TINYALSA -libtizen_audio_la_LIBADD = $(AM_LDADD) $(ASOUNDLIB_LIBS) $(TINYALSA_LIBS) $(VCONF_LIBS) $(DLOG_LIBS) $(INIPARSER_LIBS) -libtizen_audio_la_CFLAGS = $(AM_CFLAGS) $(ASOUNDLIB_CFLAGS) $(TINYALSA_CFLAGS) $(VCONF_CFLAGS) $(DLOG_CFLAGS) $(INIPARSER_CFLAGS) -D__USE_TINYALSA__ -else -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_LIBADD += $(TINYALSA_LIBS) +libtizen_audio_la_CFLAGS += $(TINYALSA_CFLAGS) -D__USE_TINYALSA__ endif -libtizen_audio_la_CFLAGS += -DUSE_DLOG diff --git a/configure.ac b/configure.ac index 5f221f2..a8b820b 100644 --- a/configure.ac +++ b/configure.ac @@ -47,6 +47,10 @@ PKG_CHECK_MODULES(DLOG, dlog) AC_SUBST(DLOG_CFLAGS) AC_SUBST(DLOG_LIBS) +PKG_CHECK_MODULES(SYSTEM_INFO, capi-system-info) +AC_SUBST(SYSTEM_INFO_CFLAGS) +AC_SUBST(SYSTEM_INFO_LIBS) + # Checks for header files. # Checks for typedefs, structures, and compiler characteristics. diff --git a/packaging/audio-hal-bcm2837.spec b/packaging/audio-hal-bcm2837.spec index 5f1dfed..f4b77fb 100644 --- a/packaging/audio-hal-bcm2837.spec +++ b/packaging/audio-hal-bcm2837.spec @@ -1,6 +1,6 @@ Name: audio-hal-bcm2837 Summary: TIZEN Audio HAL for BCM2837 -Version: 0.1.2 +Version: 0.1.3 Release: 0 Group: System/Libraries License: Apache-2.0 @@ -10,6 +10,7 @@ BuildRequires: pkgconfig(vconf) BuildRequires: pkgconfig(iniparser) BuildRequires: pkgconfig(dlog) BuildRequires: pkgconfig(alsa) +BuildRequires: pkgconfig(capi-system-info) #BuildRequires: pkgconfig(tinyalsa) Provides: libtizen-audio.so diff --git a/tizen-audio-routing.c b/tizen-audio-routing.c index 0cdadb6..b78473f 100644 --- a/tizen-audio-routing.c +++ b/tizen-audio-routing.c @@ -29,6 +29,9 @@ #include "tizen-audio-internal.h" #include "tizen-audio-impl.h" +#include +#define FEATURE_DISPLAY_STATE "http://tizen.org/feature/display.state" + /* #define DEBUG_TIMING */ static device_type_t outDeviceTypes[] = { @@ -260,6 +263,23 @@ static audio_return_t __update_route_reset(audio_hal_t *ah, uint32_t direction) return audio_ret; } +static void __audio_routing_playback_rpi3(audio_hal_t *ah) +{ + bool display_enable = false; + int ret = SYSTEM_INFO_ERROR_NONE; + + ret = system_info_get_platform_bool(FEATURE_DISPLAY_STATE, &display_enable); + AUDIO_LOG_INFO("system_info_platform [%s]=[%d], ret[%d]", FEATURE_DISPLAY_STATE, display_enable, ret); + if (ret != SYSTEM_INFO_ERROR_NONE) + AUDIO_LOG_ERROR("Failed to get feature..."); + + if (!display_enable) { + /* no hdmi support means headless, force to use earjack(1) only. + supported value : (0)auto (1)earjack (2)hdmi */ + _mixer_control_set_value(ah, "PCM Playback Route", 1); + } +} + audio_return_t _audio_routing_init(audio_hal_t *ah) { audio_return_t audio_ret = AUDIO_RET_OK; @@ -273,6 +293,9 @@ audio_return_t _audio_routing_init(audio_hal_t *ah) if ((audio_ret = _ucm_init(ah))) AUDIO_LOG_ERROR("failed to _ucm_init(), ret(0x%x)", audio_ret); + /* additional setting for rpi3 playback route mixer control */ + __audio_routing_playback_rpi3(ah); + return audio_ret; } -- 2.7.4 From dab59363a5dfe311da583e2cb29f5c6c1d4ed763 Mon Sep 17 00:00:00 2001 From: Seungbae Shin Date: Tue, 14 May 2019 17:49:26 +0900 Subject: [PATCH 10/15] Sync with latest HAL codes [Version] 0.1.4 [Issue Type] Sync Change-Id: I7ab1b2bd783cc0cfeeae7dc104aa7c68006265fc --- Makefile.am | 1 + packaging/audio-hal-bcm2837.spec | 2 +- tizen-audio-ctrl.c | 46 ++++++++++++++++++++++++++++++++++++++++ tizen-audio-impl-ctrl.c | 6 +++--- tizen-audio-impl.h | 4 ++-- tizen-audio-internal.h | 8 ++++--- tizen-audio-routing.c | 1 + tizen-audio-volume.c | 27 ++++++++++++++++++++++- tizen-audio.c | 9 +++++++- tizen-audio.h | 1 + 10 files changed, 94 insertions(+), 11 deletions(-) create mode 100644 tizen-audio-ctrl.c diff --git a/Makefile.am b/Makefile.am index b93a076..9ed22c2 100644 --- a/Makefile.am +++ b/Makefile.am @@ -6,6 +6,7 @@ libtizen_audio_la_SOURCES = tizen-audio.c \ tizen-audio-stream.c \ tizen-audio-pcm.c \ tizen-audio-util.c \ + tizen-audio-ctrl.c \ tizen-audio-impl-pcm.c \ tizen-audio-impl-ucm.c \ tizen-audio-impl-ctrl.c diff --git a/packaging/audio-hal-bcm2837.spec b/packaging/audio-hal-bcm2837.spec index f4b77fb..28dac85 100644 --- a/packaging/audio-hal-bcm2837.spec +++ b/packaging/audio-hal-bcm2837.spec @@ -1,6 +1,6 @@ Name: audio-hal-bcm2837 Summary: TIZEN Audio HAL for BCM2837 -Version: 0.1.3 +Version: 0.1.4 Release: 0 Group: System/Libraries License: Apache-2.0 diff --git a/tizen-audio-ctrl.c b/tizen-audio-ctrl.c new file mode 100644 index 0000000..2b9bacd --- /dev/null +++ b/tizen-audio-ctrl.c @@ -0,0 +1,46 @@ +/* + * audio-hal + * + * Copyright (c) 2018 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 +#endif + +#include "tizen-audio-internal.h" +#include "tizen-audio-impl.h" + +audio_return_t _audio_ctrl_init(audio_hal_t *ah) +{ + audio_return_t audio_ret = AUDIO_RET_OK; + + AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); + + audio_ret = _mixer_control_init(ah); + + return audio_ret; +} + +audio_return_t _audio_ctrl_deinit(audio_hal_t *ah) +{ + audio_return_t audio_ret = AUDIO_RET_OK; + + AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); + + audio_ret = _mixer_control_deinit(ah); + + return audio_ret; +} diff --git a/tizen-audio-impl-ctrl.c b/tizen-audio-impl-ctrl.c index 253eaab..c52715a 100644 --- a/tizen-audio-impl-ctrl.c +++ b/tizen-audio-impl-ctrl.c @@ -47,7 +47,7 @@ static void __dump_mixer_param(char *dump, long *param, int size) } #endif -audio_return_t _control_init(audio_hal_t *ah) +audio_return_t _mixer_control_init(audio_hal_t *ah) { AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); @@ -55,7 +55,7 @@ audio_return_t _control_init(audio_hal_t *ah) return AUDIO_RET_OK; } -audio_return_t _control_deinit(audio_hal_t *ah) +audio_return_t _mixer_control_deinit(audio_hal_t *ah) { AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); @@ -248,4 +248,4 @@ audio_return_t _mixer_control_get_element(audio_hal_t *ah, const char *ctl_name, /* TODO. */ return AUDIO_RET_OK; -} \ No newline at end of file +} diff --git a/tizen-audio-impl.h b/tizen-audio-impl.h index b7ece02..11db856 100644 --- a/tizen-audio-impl.h +++ b/tizen-audio-impl.h @@ -36,8 +36,8 @@ audio_return_t _pcm_set_sw_params(snd_pcm_t *pcm, snd_pcm_uframes_t avail_min, u audio_return_t _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); /* Control */ -audio_return_t _control_init(audio_hal_t *ah); -audio_return_t _control_deinit(audio_hal_t *ah); +audio_return_t _mixer_control_init(audio_hal_t *ah); +audio_return_t _mixer_control_deinit(audio_hal_t *ah); audio_return_t _mixer_control_set_param(audio_hal_t *ah, const char* ctl_name, snd_ctl_elem_value_t* value, int size); audio_return_t _mixer_control_set_value(audio_hal_t *ah, const char *ctl_name, int val); audio_return_t _mixer_control_set_value_string(audio_hal_t *ah, const char* ctl_name, const char* value); diff --git a/tizen-audio-internal.h b/tizen-audio-internal.h index 8f2f2f9..5c93dd6 100644 --- a/tizen-audio-internal.h +++ b/tizen-audio-internal.h @@ -57,19 +57,19 @@ #endif #define AUDIO_RETURN_IF_FAIL(expr) do { \ - if (!expr) { \ + if (!(expr)) { \ AUDIO_LOG_ERROR("%s failed", #expr); \ return; \ } \ } while (0) #define AUDIO_RETURN_VAL_IF_FAIL(expr, val) do { \ - if (!expr) { \ + if (!(expr)) { \ AUDIO_LOG_ERROR("%s failed", #expr); \ return val; \ } \ } while (0) #define AUDIO_RETURN_NULL_IF_FAIL(expr) do { \ - if (!expr) { \ + if (!(expr)) { \ AUDIO_LOG_ERROR("%s failed", #expr); \ return NULL; \ } \ @@ -243,6 +243,8 @@ typedef struct audio_hal { audio_hal_mixer_t mixer; } audio_hal_t; +audio_return_t _audio_ctrl_init(audio_hal_t *ah); +audio_return_t _audio_ctrl_deinit(audio_hal_t *ah); audio_return_t _audio_volume_init(audio_hal_t *ah); audio_return_t _audio_volume_deinit(audio_hal_t *ah); audio_return_t _audio_routing_init(audio_hal_t *ah); diff --git a/tizen-audio-routing.c b/tizen-audio-routing.c index b78473f..1beaec1 100644 --- a/tizen-audio-routing.c +++ b/tizen-audio-routing.c @@ -35,6 +35,7 @@ /* #define DEBUG_TIMING */ static device_type_t outDeviceTypes[] = { + { AUDIO_DEVICE_OUT_SPEAKER, "Speaker" }, { AUDIO_DEVICE_OUT_BT_SCO, "Bluetooth" }, { AUDIO_DEVICE_OUT_AUX, "Line" }, { AUDIO_DEVICE_OUT_HDMI, "HDMI" }, diff --git a/tizen-audio-volume.c b/tizen-audio-volume.c index 89d5124..4ecf326 100644 --- a/tizen-audio-volume.c +++ b/tizen-audio-volume.c @@ -35,6 +35,8 @@ #define VOLUME_VALUE_MAX (1.0f) #define GAIN_VALUE_MAX (1.0f) +uint32_t g_master_volume_level = 100; + 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 */ @@ -180,7 +182,8 @@ static audio_return_t __load_volume_value_table_from_ini(audio_hal_t *ah) audio_volume_value_table_t *volume_value_table = ah->volume.volume_value_table; int size = 0; - dict = iniparser_load(VOLUME_INI_TEMP_PATH); + if (access(VOLUME_INI_TEMP_PATH, F_OK) == 0) + 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); @@ -326,6 +329,11 @@ audio_return_t audio_get_volume_level(void *audio_handle, audio_volume_info_t *i AUDIO_RETURN_VAL_IF_FAIL(info, AUDIO_ERR_PARAMETER); AUDIO_RETURN_VAL_IF_FAIL(level, AUDIO_ERR_PARAMETER); + if (!strncmp(info->type, "master", strlen("master"))) { + *level = g_master_volume_level; + return AUDIO_RET_OK; + } + *level = ah->volume.volume_level[__get_volume_idx_by_string_type(info->type)]; AUDIO_LOG_INFO("get [%s] volume_level: %d, direction(%d)", info->type, *level, info->direction); @@ -364,6 +372,10 @@ audio_return_t audio_set_volume_level(void *audio_handle, audio_volume_info_t *i AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); AUDIO_RETURN_VAL_IF_FAIL(info, AUDIO_ERR_PARAMETER); + if (!strncmp(info->type, "master", strlen("master"))) { + g_master_volume_level = level; + return AUDIO_RET_OK; + } AUDIO_RETURN_VAL_IF_FAIL((ah->volume.volume_level_max[__get_volume_idx_by_string_type(info->type)] >= level), AUDIO_ERR_PARAMETER); /* Update volume level */ @@ -401,3 +413,16 @@ audio_return_t audio_set_volume_mute(void *audio_handle, audio_volume_info_t *in return audio_ret; } + +audio_return_t audio_set_volume_ratio(void *audio_handle, audio_stream_info_t *info, double ratio) +{ + audio_return_t audio_ret = AUDIO_RET_OK; + audio_hal_t *ah = (audio_hal_t *)audio_handle; + + AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); + AUDIO_RETURN_VAL_IF_FAIL(info, AUDIO_ERR_PARAMETER); + + AUDIO_LOG_INFO("set [%s] volume_ratio: %f, direction(%u), index(%u)", info->role, ratio, info->direction, info->idx); + + return audio_ret; +} diff --git a/tizen-audio.c b/tizen-audio.c index b83397b..6128feb 100644 --- a/tizen-audio.c +++ b/tizen-audio.c @@ -34,6 +34,11 @@ audio_return_t audio_init(void **audio_handle) AUDIO_LOG_ERROR("failed to malloc()"); return AUDIO_ERR_RESOURCE; } + + if ((ret = _audio_ctrl_init(ah))) { + AUDIO_LOG_ERROR("failed to _audio_ctrl_init(), ret(0x%x)", ret); + goto error_exit; + } if ((ret = _audio_volume_init(ah))) { AUDIO_LOG_ERROR("failed to _audio_volume_init(), ret(0x%x)", ret); goto error_exit; @@ -71,8 +76,10 @@ audio_return_t audio_deinit(void *audio_handle) _audio_routing_deinit(ah); _audio_stream_deinit(ah); _audio_pcm_deinit(ah); + _audio_ctrl_deinit(ah); + free(ah); ah = NULL; return AUDIO_RET_OK; -} \ No newline at end of file +} diff --git a/tizen-audio.h b/tizen-audio.h index d752d89..9c893db 100644 --- a/tizen-audio.h +++ b/tizen-audio.h @@ -119,6 +119,7 @@ typedef struct audio_interface { audio_return_t (*get_volume_value)(void *audio_handle, audio_volume_info_t *info, uint32_t level, double *value); audio_return_t (*get_volume_mute)(void *audio_handle, audio_volume_info_t *info, uint32_t *mute); audio_return_t (*set_volume_mute)(void *audio_handle, audio_volume_info_t *info, uint32_t mute); + audio_return_t (*set_volume_ratio)(void *audio_handle, audio_stream_info_t *info, double ratio); /* Routing */ audio_return_t (*update_route)(void *audio_handle, audio_route_info_t *info); audio_return_t (*update_route_option)(void *audio_handle, audio_route_option_t *option); -- 2.7.4 From 4e8d759dd79b3b200e91f4efa874c6be7f4933ec Mon Sep 17 00:00:00 2001 From: Seungbae Shin Date: Thu, 1 Aug 2019 11:31:37 +0900 Subject: [PATCH 11/15] Update display feature key [Version] 0.1.5 [Issue Type] Feature update Change-Id: I4823c748e45a83f26f98ca6c44111153bb6dd783 --- packaging/audio-hal-bcm2837.spec | 2 +- tizen-audio-routing.c | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/packaging/audio-hal-bcm2837.spec b/packaging/audio-hal-bcm2837.spec index 28dac85..ffca005 100644 --- a/packaging/audio-hal-bcm2837.spec +++ b/packaging/audio-hal-bcm2837.spec @@ -1,6 +1,6 @@ Name: audio-hal-bcm2837 Summary: TIZEN Audio HAL for BCM2837 -Version: 0.1.4 +Version: 0.1.5 Release: 0 Group: System/Libraries License: Apache-2.0 diff --git a/tizen-audio-routing.c b/tizen-audio-routing.c index 1beaec1..dce56a6 100644 --- a/tizen-audio-routing.c +++ b/tizen-audio-routing.c @@ -30,7 +30,7 @@ #include "tizen-audio-impl.h" #include -#define FEATURE_DISPLAY_STATE "http://tizen.org/feature/display.state" +#define FEATURE_DISPLAY "http://tizen.org/feature/display" /* #define DEBUG_TIMING */ @@ -266,16 +266,16 @@ static audio_return_t __update_route_reset(audio_hal_t *ah, uint32_t direction) static void __audio_routing_playback_rpi3(audio_hal_t *ah) { - bool display_enable = false; + bool display_avail = false; int ret = SYSTEM_INFO_ERROR_NONE; - ret = system_info_get_platform_bool(FEATURE_DISPLAY_STATE, &display_enable); - AUDIO_LOG_INFO("system_info_platform [%s]=[%d], ret[%d]", FEATURE_DISPLAY_STATE, display_enable, ret); + ret = system_info_get_platform_bool(FEATURE_DISPLAY, &display_avail); + AUDIO_LOG_INFO("system_info_platform [%s]=[%d], ret[%d]", FEATURE_DISPLAY, display_avail, ret); if (ret != SYSTEM_INFO_ERROR_NONE) AUDIO_LOG_ERROR("Failed to get feature..."); - if (!display_enable) { - /* no hdmi support means headless, force to use earjack(1) only. + if (!display_avail) { + /* in case of headless (display is not available), force to use earjack(1) only. supported value : (0)auto (1)earjack (2)hdmi */ _mixer_control_set_value(ah, "PCM Playback Route", 1); } -- 2.7.4 From 2141974a6a7fffc6653bbff5a774dd619d65e6c3 Mon Sep 17 00:00:00 2001 From: Sangchul Lee Date: Mon, 14 Oct 2019 10:09:33 +0900 Subject: [PATCH 12/15] Remove codes related to UCM The HDMI audio device could not be detected from PulseAudio, it is impossible to set the HDMI device to UCM which leads to set "PCM Playback Route" mixer value to 2(HDMI). Hence, we decide to set the mixer value to 0(Auto) and leave it without any UCM setting. With the HDMI connected booting, sound will be played through the HDMI. Otherwise sound will be played through the audiojack. [Version] 0.1.6 [Issue Type] Bug fix Change-Id: I6f87eee5bd074f32763f2c4a99bc738fe547d266 Signed-off-by: Sangchul Lee --- Makefile.am | 1 - packaging/audio-hal-bcm2837.spec | 2 +- tizen-audio-impl-ucm.c | 651 --------------------------------------- tizen-audio-impl.h | 10 - tizen-audio-internal.h | 6 - tizen-audio-routing.c | 31 +- 6 files changed, 4 insertions(+), 697 deletions(-) delete mode 100644 tizen-audio-impl-ucm.c diff --git a/Makefile.am b/Makefile.am index 9ed22c2..ef960b6 100644 --- a/Makefile.am +++ b/Makefile.am @@ -8,7 +8,6 @@ libtizen_audio_la_SOURCES = tizen-audio.c \ tizen-audio-util.c \ tizen-audio-ctrl.c \ tizen-audio-impl-pcm.c \ - tizen-audio-impl-ucm.c \ tizen-audio-impl-ctrl.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) $(SYSTEM_INFO_LIBS) diff --git a/packaging/audio-hal-bcm2837.spec b/packaging/audio-hal-bcm2837.spec index ffca005..8d7d9c9 100644 --- a/packaging/audio-hal-bcm2837.spec +++ b/packaging/audio-hal-bcm2837.spec @@ -1,6 +1,6 @@ Name: audio-hal-bcm2837 Summary: TIZEN Audio HAL for BCM2837 -Version: 0.1.5 +Version: 0.1.6 Release: 0 Group: System/Libraries License: Apache-2.0 diff --git a/tizen-audio-impl-ucm.c b/tizen-audio-impl-ucm.c deleted file mode 100644 index 1dfe50a..0000000 --- a/tizen-audio-impl-ucm.c +++ /dev/null @@ -1,651 +0,0 @@ -/* - * audio-hal - * - * Copyright (c) 2015 - 2016 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 -#endif - -#include -#include -#include -#ifdef ALSA_UCM_DEBUG_TIME -#include -#include -#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 - -#define UCM_PREFIX_CURRENT ">>> UCM current" -#define UCM_PREFIX_REQUESTED "> UCM requested" -#define UCM_PREFIX_CHANGED "<<< UCM changed" - -#define DUMP_LEN 512 - -static void __dump_use_case(const char* prefix, const char *verb, const char *devices[], int dev_count, const char *modifiers[], int mod_count) -{ - int i; - dump_data_t* dump = NULL; - - if (!(dump = _audio_dump_new(DUMP_LEN))) { - AUDIO_LOG_ERROR("Failed to create dump string..."); - return; - } - - /* Verb */ - _audio_dump_add_str(dump, "Verb [ %s ] Devices [ ", verb ? verb : AUDIO_USE_CASE_VERB_INACTIVE); - - /* Devices */ - if (devices) { - for (i = 0; i < dev_count; i++) { - _audio_dump_add_str(dump, (i != dev_count - 1) ? "%s, " : "%s", devices[i]); - } - } - _audio_dump_add_str(dump, " ] Modifier [ "); - - /* Modifiers */ - if (modifiers) { - for (i = 0; i < mod_count; i++) { - _audio_dump_add_str(dump, (i != mod_count - 1) ? "%s, " : "%s", modifiers[i]); - } - } - _audio_dump_add_str(dump, " ]"); - - AUDIO_LOG_INFO("TEST %s : %s", prefix, _audio_dump_get_str(dump)); - - _audio_dump_free(dump); -} - -#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 - -audio_return_t _ucm_init(audio_hal_t *ah) -{ - AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); - - snd_use_case_mgr_open(&ah->ucm.uc_mgr, ALSA_DEFAULT_CARD); - - if (!ah->ucm.uc_mgr) { - AUDIO_LOG_ERROR("uc_mgr open failed"); - return AUDIO_ERR_RESOURCE; - } - return AUDIO_RET_OK; -} - -audio_return_t _ucm_deinit(audio_hal_t *ah) -{ - AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); - AUDIO_RETURN_VAL_IF_FAIL(ah->ucm.uc_mgr, AUDIO_ERR_PARAMETER); - - if (ah->ucm.uc_mgr) { - snd_use_case_mgr_close(ah->ucm.uc_mgr); - ah->ucm.uc_mgr = NULL; - } - - return AUDIO_RET_OK; -} - -/* 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 _ucm_set_use_case(audio_hal_t *ah, 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; - - AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); - AUDIO_RETURN_VAL_IF_FAIL(ah->ucm.uc_mgr, AUDIO_ERR_PARAMETER); - AUDIO_RETURN_VAL_IF_FAIL(verb, AUDIO_ERR_PARAMETER); - - snd_use_case_get(ah->ucm.uc_mgr, "_verb", &old_verb); - old_dev_count = snd_use_case_get_list(ah->ucm.uc_mgr, "_enadevs", &old_dev_list); - old_mod_count = snd_use_case_get_list(ah->ucm.uc_mgr, "_enamods", &old_mod_list); - __dump_use_case(UCM_PREFIX_CURRENT, old_verb, old_dev_list, old_dev_count, old_mod_list, old_mod_count); - - 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(UCM_PREFIX_REQUESTED, verb, devices, dev_count, modifiers, mod_count); - - 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(ah->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(ah->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(ah->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(ah->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(ah->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(ah->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(ah->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(ah->ucm.uc_mgr, "_verb", &new_verb); - new_dev_count = snd_use_case_get_list(ah->ucm.uc_mgr, "_enadevs", &new_dev_list); - new_mod_count = snd_use_case_get_list(ah->ucm.uc_mgr, "_enamods", &new_mod_list); - __dump_use_case(UCM_PREFIX_CHANGED, new_verb, new_dev_list, new_dev_count, new_mod_list, new_mod_count); - - 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 _ucm_set_devices(audio_hal_t *ah, const char *verb, const char *devices[]) -{ - audio_return_t audio_ret = AUDIO_RET_OK; - int is_verb_changed = 0, is_dev_changed = 0; - const char *old_verb = NULL, **old_dev_list = NULL; - int old_dev_count = 0, dev_count = 0; - const char **dis_dev_list = NULL, **ena_dev_list = NULL; - int dis_dev_count = 0, ena_dev_count = 0; - int i = 0, j = 0; - - AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); - AUDIO_RETURN_VAL_IF_FAIL(ah->ucm.uc_mgr, AUDIO_ERR_PARAMETER); - AUDIO_RETURN_VAL_IF_FAIL(verb, AUDIO_ERR_PARAMETER); - AUDIO_RETURN_VAL_IF_FAIL(devices, AUDIO_ERR_PARAMETER); - - snd_use_case_get(ah->ucm.uc_mgr, "_verb", &old_verb); - old_dev_count = snd_use_case_get_list(ah->ucm.uc_mgr, "_enadevs", &old_dev_list); - __dump_use_case(UCM_PREFIX_CURRENT, old_verb, old_dev_list, old_dev_count, NULL, 0); - - if (devices) { - for (dev_count = 0; devices[dev_count]; dev_count++); - } - - __dump_use_case(UCM_PREFIX_REQUESTED, verb, devices, dev_count, NULL, 0); - - 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; - } - } - - /* 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]; - } - } - - /* 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(ah->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(ah->ucm.uc_mgr, "_enadev", ena_dev_list[i]) < 0) - AUDIO_LOG_ERROR("enable %s device failed", ena_dev_list[i]); - } - - } else { - is_verb_changed = 1; - - AUDIO_LOG_INFO("Setting new verb: %s", verb); - /* set new verb */ - if (snd_use_case_set(ah->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_INFO("Enable device : %s", devices[i]); - if (snd_use_case_set(ah->ucm.uc_mgr, "_enadev", devices[i]) < 0) - AUDIO_LOG_ERROR("Enable %s device failed", devices[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 (dis_dev_list) - free((void *)dis_dev_list); - if (ena_dev_list) - free((void *)ena_dev_list); - - if (is_verb_changed == 1 || is_dev_changed == 1) { - const char *new_verb = NULL, **new_dev_list = NULL; - int new_dev_count = 0; - - snd_use_case_get(ah->ucm.uc_mgr, "_verb", &new_verb); - new_dev_count = snd_use_case_get_list(ah->ucm.uc_mgr, "_enadevs", &new_dev_list); - __dump_use_case(UCM_PREFIX_CHANGED, new_verb, new_dev_list, new_dev_count, NULL, 0); - - if (new_verb) - free((void *)new_verb); - if (new_dev_list) - snd_use_case_free_list(new_dev_list, new_dev_count); - } - - return audio_ret; - -} - -audio_return_t _ucm_set_modifiers(audio_hal_t *ah, const char *verb, const char *modifiers[]) -{ - audio_return_t audio_ret = AUDIO_RET_OK; - int is_verb_changed = 0, is_mod_changed = 0; - const char *old_verb = NULL, **old_mod_list = NULL; - int old_mod_count = 0, mod_count = 0; - const char **dis_mod_list = NULL, **ena_mod_list = NULL; - int dis_mod_count = 0, ena_mod_count = 0; - int i = 0, j = 0; - - AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); - AUDIO_RETURN_VAL_IF_FAIL(ah->ucm.uc_mgr, AUDIO_ERR_PARAMETER); - AUDIO_RETURN_VAL_IF_FAIL(verb, AUDIO_ERR_PARAMETER); - AUDIO_RETURN_VAL_IF_FAIL(modifiers, AUDIO_ERR_PARAMETER); - - snd_use_case_get(ah->ucm.uc_mgr, "_verb", &old_verb); - old_mod_count = snd_use_case_get_list(ah->ucm.uc_mgr, "_enamods", &old_mod_list); - __dump_use_case(UCM_PREFIX_CURRENT, old_verb, NULL, 0, old_mod_list, old_mod_count); - - if (modifiers) { - for (mod_count = 0; modifiers[mod_count]; mod_count++); - } - - __dump_use_case(UCM_PREFIX_REQUESTED, verb, NULL, 0, modifiers, mod_count); - - 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_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 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(ah->ucm.uc_mgr, "_dismod", dis_mod_list[i]) < 0) - AUDIO_LOG_ERROR("disable %s modifier failed", dis_mod_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(ah->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(ah->ucm.uc_mgr, "_verb", verb) < 0) { - AUDIO_LOG_ERROR("Setting verb %s failed", verb); - audio_ret = AUDIO_ERR_UNDEFINED; - goto exit; - } - /* enable modifiers */ - for (i = 0; i < mod_count; i++) { - AUDIO_LOG_DEBUG("Enable modifier : %s", modifiers[i]); - if (snd_use_case_set(ah->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_mod_list) - snd_use_case_free_list(old_mod_list, old_mod_count); - if (dis_mod_list) - free((void *)dis_mod_list); - if (ena_mod_list) - free((void *)ena_mod_list); - - if (is_verb_changed == 1 || is_mod_changed == 1) { - const char *new_verb = NULL, **new_mod_list = NULL; - int new_mod_count = 0; - - snd_use_case_get(ah->ucm.uc_mgr, "_verb", &new_verb); - new_mod_count = snd_use_case_get_list(ah->ucm.uc_mgr, "_enamods", &new_mod_list); - __dump_use_case(UCM_PREFIX_CHANGED, new_verb, NULL, 0, new_mod_list, new_mod_count); - - if (new_verb) - free((void *)new_verb); - if (new_mod_list) - snd_use_case_free_list(new_mod_list, new_mod_count); - } - - return audio_ret; -} - -audio_return_t _ucm_get_verb(audio_hal_t *ah, const char **value) -{ - audio_return_t ret = AUDIO_RET_OK; - - AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); - AUDIO_RETURN_VAL_IF_FAIL(ah->ucm.uc_mgr, AUDIO_ERR_PARAMETER); - AUDIO_RETURN_VAL_IF_FAIL(value, AUDIO_ERR_PARAMETER); - - if ((ret = snd_use_case_get(ah->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 _ucm_reset_use_case(audio_hal_t *ah) -{ - audio_return_t ret = AUDIO_RET_OK; - - AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); - AUDIO_RETURN_VAL_IF_FAIL(ah->ucm.uc_mgr, AUDIO_ERR_PARAMETER); - - AUDIO_LOG_INFO(">>> UCM reset Verb [ %s ]", AUDIO_USE_CASE_VERB_INACTIVE); - - if ((ret = snd_use_case_set(ah->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; -} \ No newline at end of file diff --git a/tizen-audio-impl.h b/tizen-audio-impl.h index 11db856..70b4993 100644 --- a/tizen-audio-impl.h +++ b/tizen-audio-impl.h @@ -44,14 +44,4 @@ audio_return_t _mixer_control_set_value_string(audio_hal_t *ah, const char* ctl_ audio_return_t _mixer_control_get_value(audio_hal_t *ah, const char *ctl_name, int *val); audio_return_t _mixer_control_get_element(audio_hal_t *ah, const char *ctl_name, snd_hctl_elem_t **elem); -/* UCM */ -audio_return_t _ucm_init(audio_hal_t *ah); -audio_return_t _ucm_deinit(audio_hal_t *ah); -#define _ucm_update_use_case _ucm_set_use_case -audio_return_t _ucm_set_use_case(audio_hal_t *ah, const char *verb, const char *devices[], const char *modifiers[]); -audio_return_t _ucm_set_devices(audio_hal_t *ah, const char *verb, const char *devices[]); -audio_return_t _ucm_set_modifiers(audio_hal_t *ah, const char *verb, const char *modifiers[]); -audio_return_t _ucm_get_verb(audio_hal_t *ah, const char **value); -audio_return_t _ucm_reset_use_case(audio_hal_t *ah); - #endif diff --git a/tizen-audio-internal.h b/tizen-audio-internal.h index 5c93dd6..485e0bb 100644 --- a/tizen-audio-internal.h +++ b/tizen-audio-internal.h @@ -200,11 +200,6 @@ typedef struct audio_hal_volume { audio_volume_value_table_t *volume_value_table; } audio_hal_volume_t; -/* UCM */ -typedef struct audio_hal_ucm { - snd_use_case_mgr_t* uc_mgr; -} audio_hal_ucm_t; - /* Mixer */ typedef struct audio_hal_mixer { snd_mixer_t *mixer; @@ -239,7 +234,6 @@ typedef enum audio_sample_format { typedef struct audio_hal { audio_hal_device_t device; audio_hal_volume_t volume; - audio_hal_ucm_t ucm; audio_hal_mixer_t mixer; } audio_hal_t; diff --git a/tizen-audio-routing.c b/tizen-audio-routing.c index dce56a6..ce7613c 100644 --- a/tizen-audio-routing.c +++ b/tizen-audio-routing.c @@ -141,9 +141,7 @@ static audio_return_t __set_devices(audio_hal_t *ah, const char *verb, device_in return AUDIO_ERR_PARAMETER; } - audio_ret = _ucm_set_devices(ah, verb, active_devices); - if (audio_ret) - AUDIO_LOG_ERROR("Failed to set device: error = %d", audio_ret); + /* Routing path is set only via __audio_routing_playback_rpi3() function, do nothing here. */ return audio_ret; } @@ -172,23 +170,7 @@ static audio_return_t __update_route_ap_playback_capture(audio_hal_t *ah, audio_ } ah->device.mode = VERB_NORMAL; - /* To Do: Set modifiers */ - /* - if (!strncmp("voice_recognition", route_info->role, MAX_NAME_LEN)) { - modifiers[mod_idx++] = AUDIO_USE_CASE_MODIFIER_VOICESEARCH; - } else if ((!strncmp("alarm", route_info->role, MAX_NAME_LEN))||(!strncmp("notifiication", route_info->role, MAX_NAME_LEN))) { - if (ah->device.active_out &= AUDIO_DEVICE_OUT_JACK) - modifiers[mod_idx++] = AUDIO_USE_CASE_MODIFIER_DUAL_MEDIA; - else - modifiers[mod_idx++] = AUDIO_USE_CASE_MODIFIER_MEDIA; - } else { - if (ah->device.active_in) - modifiers[mod_idx++] = AUDIO_USE_CASE_MODIFIER_CAMCORDING; - else - modifiers[mod_idx++] = AUDIO_USE_CASE_MODIFIER_MEDIA; - } - audio_ret = _audio_ucm_set_modifiers (ah, verb, modifiers); - */ + /* Routing path is set only via __audio_routing_playback_rpi3() function, do nothing here. */ return audio_ret; } @@ -258,8 +240,7 @@ static audio_return_t __update_route_reset(audio_hal_t *ah, uint32_t direction) return AUDIO_RET_OK; } - if ((audio_ret = _ucm_set_devices(ah, mode_to_verb_str[ah->device.mode], active_devices))) - AUDIO_LOG_ERROR("failed to _ucm_set_devices(), ret(0x%x)", audio_ret); + /* Routing path is set only via __audio_routing_playback_rpi3() function, do nothing here. */ return audio_ret; } @@ -291,9 +272,6 @@ audio_return_t _audio_routing_init(audio_hal_t *ah) ah->device.active_out = 0x0; ah->device.mode = VERB_NORMAL; - if ((audio_ret = _ucm_init(ah))) - AUDIO_LOG_ERROR("failed to _ucm_init(), ret(0x%x)", audio_ret); - /* additional setting for rpi3 playback route mixer control */ __audio_routing_playback_rpi3(ah); @@ -306,9 +284,6 @@ audio_return_t _audio_routing_deinit(audio_hal_t *ah) AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); - if ((audio_ret = _ucm_deinit(ah))) - AUDIO_LOG_ERROR("failed to _ucm_deinit(), ret(0x%x)", audio_ret); - return audio_ret; } -- 2.7.4 From 56a4d9b9830b5dfe0ccfc11bbcb9e272e8b1802c Mon Sep 17 00:00:00 2001 From: Sangchul Lee Date: Mon, 21 Oct 2019 12:58:43 +0900 Subject: [PATCH 13/15] Set volume mixer control value It had been set inside of UCM with a verb, but we removed the UCM codes in the previous patch, Now it is added to _audio_volume_init() and it is set with the previous value. [Version] 0.1.7 [Issue Type] Bug fix Change-Id: I383ea92485f450258f309a17bef16714dfc3579f Signed-off-by: Sangchul Lee --- packaging/audio-hal-bcm2837.spec | 2 +- tizen-audio-volume.c | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/packaging/audio-hal-bcm2837.spec b/packaging/audio-hal-bcm2837.spec index 8d7d9c9..7ca9559 100644 --- a/packaging/audio-hal-bcm2837.spec +++ b/packaging/audio-hal-bcm2837.spec @@ -1,6 +1,6 @@ Name: audio-hal-bcm2837 Summary: TIZEN Audio HAL for BCM2837 -Version: 0.1.6 +Version: 0.1.7 Release: 0 Group: System/Libraries License: Apache-2.0 diff --git a/tizen-audio-volume.c b/tizen-audio-volume.c index 4ecf326..7257b32 100644 --- a/tizen-audio-volume.c +++ b/tizen-audio-volume.c @@ -29,6 +29,7 @@ #include #include "tizen-audio-internal.h" +#include "tizen-audio-impl.h" #define VOLUME_INI_DEFAULT_PATH SYSCONFDIR"/multimedia/mmfw_audio_volume.ini" /* SYSCONFDIR is defined at .spec */ #define VOLUME_INI_TEMP_PATH "/opt/system/mmfw_audio_volume.ini" @@ -290,6 +291,8 @@ audio_return_t _audio_volume_init(audio_hal_t *ah) return AUDIO_ERR_UNDEFINED; } + _mixer_control_set_value(ah, "PCM Playback Volume", -663); /* value of 90% */ + return audio_ret; } -- 2.7.4 From a76b3e3738ee7d525c05312ab4049be609760713 Mon Sep 17 00:00:00 2001 From: Sangchul Lee Date: Mon, 21 Oct 2019 13:43:54 +0900 Subject: [PATCH 14/15] Change default volume value of volume mixer control It is revised from 90% to 100%. [Version] 0.1.8 [Issue Type] Tuning Change-Id: Id50fbcb556e40b080fb256d4dea87f0b7a4917f7 Signed-off-by: Sangchul Lee --- packaging/audio-hal-bcm2837.spec | 2 +- tizen-audio-volume.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packaging/audio-hal-bcm2837.spec b/packaging/audio-hal-bcm2837.spec index 7ca9559..aba5387 100644 --- a/packaging/audio-hal-bcm2837.spec +++ b/packaging/audio-hal-bcm2837.spec @@ -1,6 +1,6 @@ Name: audio-hal-bcm2837 Summary: TIZEN Audio HAL for BCM2837 -Version: 0.1.7 +Version: 0.1.8 Release: 0 Group: System/Libraries License: Apache-2.0 diff --git a/tizen-audio-volume.c b/tizen-audio-volume.c index 7257b32..20f701e 100644 --- a/tizen-audio-volume.c +++ b/tizen-audio-volume.c @@ -291,7 +291,7 @@ audio_return_t _audio_volume_init(audio_hal_t *ah) return AUDIO_ERR_UNDEFINED; } - _mixer_control_set_value(ah, "PCM Playback Volume", -663); /* value of 90% */ + _mixer_control_set_value(ah, "PCM Playback Volume", 400); /* value of 100% */ return audio_ret; } -- 2.7.4 From 019cebc7af363c8fc3e55d832e46b30acdeebf07 Mon Sep 17 00:00:00 2001 From: Jaechul Lee Date: Tue, 26 Jan 2021 13:50:39 +0900 Subject: [PATCH 15/15] Use hal interface hal interfaces were added. Besides, structure and enum names were changed for better readability. In case of enum, audio_return_t is changed to audio_return_'e', and device_info_t is changed to device_info_'s'. [Version] 0.1.9 [Issue Type] None Change-Id: I88005d26198d0453d07d08059f58e4cdf2206cb3 Signed-off-by: Jaechul Lee --- Makefile.am | 17 ++-- configure.ac | 4 + hal-backend-audio.c | 58 ++++++++++++++ packaging/audio-hal-bcm2837.spec | 10 ++- tizen-audio-ctrl.c | 8 +- tizen-audio-impl-ctrl.c | 14 ++-- tizen-audio-impl-pcm.c | 30 +++---- tizen-audio-impl.h | 40 +++++----- tizen-audio-internal.h | 20 ++--- tizen-audio-pcm.c | 48 ++++++------ tizen-audio-routing.c | 36 ++++----- tizen-audio-stream.c | 8 +- tizen-audio-volume.c | 30 +++---- tizen-audio.c | 6 +- tizen-audio.h | 165 +++++++++------------------------------ 15 files changed, 233 insertions(+), 261 deletions(-) create mode 100644 hal-backend-audio.c diff --git a/Makefile.am b/Makefile.am index ef960b6..ef9d5be 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,6 +1,6 @@ -lib_LTLIBRARIES = libtizen-audio.la +lib_LTLIBRARIES = libhal-backend-audio.la -libtizen_audio_la_SOURCES = tizen-audio.c \ +libhal_backend_audio_la_SOURCES = tizen-audio.c \ tizen-audio-volume.c \ tizen-audio-routing.c \ tizen-audio-stream.c \ @@ -8,13 +8,14 @@ libtizen_audio_la_SOURCES = tizen-audio.c \ tizen-audio-util.c \ tizen-audio-ctrl.c \ tizen-audio-impl-pcm.c \ - tizen-audio-impl-ctrl.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) $(SYSTEM_INFO_LIBS) -libtizen_audio_la_CFLAGS = $(AM_CFLAGS) $(ASOUNDLIB_CFLAGS) $(VCONF_CFLAGS) $(DLOG_CFLAGS) $(INIPARSER_CFLAGS) $(SYSTEM_INFO_CFLAGS) -DUSE_DLOG + tizen-audio-impl-ctrl.c \ + hal-backend-audio.c +libhal_backend_audio_la_LDFLAGS = $(AM_LDFLAGS) -disable-static -avoid-version +libhal_backend_audio_la_LIBADD = $(AM_LDADD) $(ASOUNDLIB_LIBS) $(VCONF_LIBS) $(DLOG_LIBS) $(INIPARSER_LIBS) $(SYSTEM_INFO_LIBS) +libhal_backend_audio_la_CFLAGS = $(AM_CFLAGS) $(ASOUNDLIB_CFLAGS) $(VCONF_CFLAGS) $(DLOG_CFLAGS) $(INIPARSER_CFLAGS) $(SYSTEM_INFO_CFLAGS) $(HALAPICOMMON) -DUSE_DLOG if USE_TINYALSA -libtizen_audio_la_LIBADD += $(TINYALSA_LIBS) -libtizen_audio_la_CFLAGS += $(TINYALSA_CFLAGS) -D__USE_TINYALSA__ +libhal_backend_audio_la_LIBADD += $(TINYALSA_LIBS) +libhal_backend_audio_la_CFLAGS += $(TINYALSA_CFLAGS) -D__USE_TINYALSA__ endif diff --git a/configure.ac b/configure.ac index a8b820b..199769c 100644 --- a/configure.ac +++ b/configure.ac @@ -51,6 +51,10 @@ PKG_CHECK_MODULES(SYSTEM_INFO, capi-system-info) AC_SUBST(SYSTEM_INFO_CFLAGS) AC_SUBST(SYSTEM_INFO_LIBS) +PKG_CHECK_MODULES(HALAPICOMMON, hal-api-common) +AC_SUBST(HALAPICOMMON_CFLAGS) +AC_SUBST(HALAPICOMMON_LIBS) + # Checks for header files. # Checks for typedefs, structures, and compiler characteristics. diff --git a/hal-backend-audio.c b/hal-backend-audio.c new file mode 100644 index 0000000..5b4c181 --- /dev/null +++ b/hal-backend-audio.c @@ -0,0 +1,58 @@ +#include +#include +#include +#include +#include +#include + +static int audio_rpi_init(void **data) +{ + hal_backend_audio_funcs *funcs; + + funcs = calloc(1, sizeof(hal_backend_audio_funcs)); + if (!funcs) + return -ENOMEM; + + funcs->init = audio_init; + funcs->deinit = audio_deinit; + funcs->get_volume_level_max = audio_get_volume_level_max; + funcs->set_volume_level = audio_set_volume_level; + funcs->get_volume_value = audio_get_volume_value; + funcs->get_volume_mute = audio_get_volume_mute; + funcs->set_volume_mute = audio_set_volume_mute; + funcs->set_volume_ratio = audio_set_volume_ratio; + funcs->update_route = audio_update_route; + funcs->update_route_option = audio_update_route_option; + funcs->notify_stream_connection_changed = audio_notify_stream_connection_changed; + funcs->pcm_open = audio_pcm_open; + funcs->pcm_start = audio_pcm_start; + funcs->pcm_stop = audio_pcm_stop; + funcs->pcm_close = audio_pcm_close; + funcs->pcm_avail = audio_pcm_avail; + funcs->pcm_write = audio_pcm_write; + funcs->pcm_read = audio_pcm_read; + funcs->pcm_get_fd = audio_pcm_get_fd; + funcs->pcm_recover = audio_pcm_recover; + funcs->pcm_get_params = audio_pcm_get_params; + funcs->pcm_set_params = audio_pcm_set_params; + + *data = (void *)funcs; + + return 0; +} + +static void audio_rpi_exit(void *data) +{ + if (!data) + return; + + free(data); +} + +hal_backend hal_backend_audio_data = { + .name = "audio-rpi", + .vendor = "Broadcom", + .abi_version = HAL_ABI_VERSION_TIZEN_6_5, + .init = audio_rpi_init, + .exit = audio_rpi_exit, +}; diff --git a/packaging/audio-hal-bcm2837.spec b/packaging/audio-hal-bcm2837.spec index aba5387..4b219ef 100644 --- a/packaging/audio-hal-bcm2837.spec +++ b/packaging/audio-hal-bcm2837.spec @@ -1,6 +1,6 @@ Name: audio-hal-bcm2837 Summary: TIZEN Audio HAL for BCM2837 -Version: 0.1.8 +Version: 0.1.9 Release: 0 Group: System/Libraries License: Apache-2.0 @@ -11,8 +11,10 @@ BuildRequires: pkgconfig(iniparser) BuildRequires: pkgconfig(dlog) BuildRequires: pkgconfig(alsa) BuildRequires: pkgconfig(capi-system-info) +BuildRequires: pkgconfig(hal-api-common) +BuildRequires: pkgconfig(hal-api-audio) #BuildRequires: pkgconfig(tinyalsa) -Provides: libtizen-audio.so +Provides: libhal-backend-audio.so %description TIZEN Audio HAL for BCM2837 @@ -28,7 +30,7 @@ export FFLAGS="$FFLAGS -DTIZEN_DEBUG_ENABLE" export USE_TINYALSA="0" %autogen -%configure +./configure --libdir=%{_hal_libdir} make %{?jobs:-j%jobs} @@ -45,5 +47,5 @@ rm -rf %{buildroot} %files %manifest audio-hal-bcm2837.manifest %defattr(-,root,root,-) -%{_libdir}/libtizen-audio.so +%{_hal_libdir}/libhal-backend-audio.so %license LICENSE.Apache-2.0 diff --git a/tizen-audio-ctrl.c b/tizen-audio-ctrl.c index 2b9bacd..40c5d6c 100644 --- a/tizen-audio-ctrl.c +++ b/tizen-audio-ctrl.c @@ -23,9 +23,9 @@ #include "tizen-audio-internal.h" #include "tizen-audio-impl.h" -audio_return_t _audio_ctrl_init(audio_hal_t *ah) +audio_return_e _audio_ctrl_init(audio_hal_t *ah) { - audio_return_t audio_ret = AUDIO_RET_OK; + audio_return_e audio_ret = AUDIO_RET_OK; AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); @@ -34,9 +34,9 @@ audio_return_t _audio_ctrl_init(audio_hal_t *ah) return audio_ret; } -audio_return_t _audio_ctrl_deinit(audio_hal_t *ah) +audio_return_e _audio_ctrl_deinit(audio_hal_t *ah) { - audio_return_t audio_ret = AUDIO_RET_OK; + audio_return_e audio_ret = AUDIO_RET_OK; AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); diff --git a/tizen-audio-impl-ctrl.c b/tizen-audio-impl-ctrl.c index c52715a..9f59871 100644 --- a/tizen-audio-impl-ctrl.c +++ b/tizen-audio-impl-ctrl.c @@ -47,7 +47,7 @@ static void __dump_mixer_param(char *dump, long *param, int size) } #endif -audio_return_t _mixer_control_init(audio_hal_t *ah) +audio_return_e _mixer_control_init(audio_hal_t *ah) { AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); @@ -55,7 +55,7 @@ audio_return_t _mixer_control_init(audio_hal_t *ah) return AUDIO_RET_OK; } -audio_return_t _mixer_control_deinit(audio_hal_t *ah) +audio_return_e _mixer_control_deinit(audio_hal_t *ah) { AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); @@ -63,7 +63,7 @@ audio_return_t _mixer_control_deinit(audio_hal_t *ah) return AUDIO_RET_OK; } -audio_return_t _mixer_control_set_param(audio_hal_t *ah, const char* ctl_name, snd_ctl_elem_value_t* param, int size) +audio_return_e _mixer_control_set_param(audio_hal_t *ah, const char* ctl_name, snd_ctl_elem_value_t* param, int size) { AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); @@ -71,7 +71,7 @@ audio_return_t _mixer_control_set_param(audio_hal_t *ah, const char* ctl_name, s return AUDIO_RET_OK; } -audio_return_t _mixer_control_get_value(audio_hal_t *ah, const char *ctl_name, int *val) +audio_return_e _mixer_control_get_value(audio_hal_t *ah, const char *ctl_name, int *val) { snd_ctl_t *handle; snd_ctl_elem_value_t *control; @@ -151,7 +151,7 @@ close: return AUDIO_ERR_UNDEFINED; } -audio_return_t _mixer_control_set_value(audio_hal_t *ah, const char *ctl_name, int val) +audio_return_e _mixer_control_set_value(audio_hal_t *ah, const char *ctl_name, int val) { snd_ctl_t *handle; snd_ctl_elem_value_t *control; @@ -230,7 +230,7 @@ close: return AUDIO_ERR_UNDEFINED; } -audio_return_t _mixer_control_set_value_string(audio_hal_t *ah, const char* ctl_name, const char* value) +audio_return_e _mixer_control_set_value_string(audio_hal_t *ah, const char* ctl_name, const char* value) { AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); AUDIO_RETURN_VAL_IF_FAIL(ctl_name, AUDIO_ERR_PARAMETER); @@ -240,7 +240,7 @@ audio_return_t _mixer_control_set_value_string(audio_hal_t *ah, const char* ctl_ } -audio_return_t _mixer_control_get_element(audio_hal_t *ah, const char *ctl_name, snd_hctl_elem_t **elem) +audio_return_e _mixer_control_get_element(audio_hal_t *ah, const char *ctl_name, snd_hctl_elem_t **elem) { AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); AUDIO_RETURN_VAL_IF_FAIL(ctl_name, AUDIO_ERR_PARAMETER); diff --git a/tizen-audio-impl-pcm.c b/tizen-audio-impl-pcm.c index dc93a90..093ad06 100644 --- a/tizen-audio-impl-pcm.c +++ b/tizen-audio-impl-pcm.c @@ -156,7 +156,7 @@ static int __make_alsa_device_name(const char *card, const char *device, char de } #endif -audio_return_t _pcm_open(const char *card, const char *device, uint32_t direction, void *sample_spec, +audio_return_e _pcm_open(const char *card, const char *device, uint32_t direction, void *sample_spec, uint32_t period_size, uint32_t periods, void **pcm_handle) { int err; @@ -186,7 +186,7 @@ audio_return_t _pcm_open(const char *card, const char *device, uint32_t directio #else /* alsa-lib */ int mode; - audio_return_t ret; + audio_return_e ret; char device_name[DEVICE_NAME_MAX]; __make_alsa_device_name(card, device, device_name); @@ -208,7 +208,7 @@ audio_return_t _pcm_open(const char *card, const char *device, uint32_t directio return AUDIO_RET_OK; } -audio_return_t _pcm_start(void *pcm_handle) +audio_return_e _pcm_start(void *pcm_handle) { int err; @@ -228,7 +228,7 @@ audio_return_t _pcm_start(void *pcm_handle) return AUDIO_RET_OK; } -audio_return_t _pcm_stop(void *pcm_handle) +audio_return_e _pcm_stop(void *pcm_handle) { int err; @@ -248,7 +248,7 @@ audio_return_t _pcm_stop(void *pcm_handle) return AUDIO_RET_OK; } -audio_return_t _pcm_close(void *pcm_handle) +audio_return_e _pcm_close(void *pcm_handle) { int err; @@ -269,7 +269,7 @@ audio_return_t _pcm_close(void *pcm_handle) return AUDIO_RET_OK; } -audio_return_t _pcm_avail(void *pcm_handle, uint32_t *avail) +audio_return_e _pcm_avail(void *pcm_handle, uint32_t *avail) { #ifdef __USE_TINYALSA__ struct timespec tspec; @@ -305,7 +305,7 @@ audio_return_t _pcm_avail(void *pcm_handle, uint32_t *avail) return AUDIO_RET_OK; } -audio_return_t _pcm_write(void *pcm_handle, const void *buffer, uint32_t frames) +audio_return_e _pcm_write(void *pcm_handle, const void *buffer, uint32_t frames) { #ifdef __USE_TINYALSA__ int err; @@ -338,7 +338,7 @@ audio_return_t _pcm_write(void *pcm_handle, const void *buffer, uint32_t frames) return AUDIO_RET_OK; } -audio_return_t _pcm_read(void *pcm_handle, void *buffer, uint32_t frames) +audio_return_e _pcm_read(void *pcm_handle, void *buffer, uint32_t frames) { #ifdef __USE_TINYALSA__ int err; @@ -369,7 +369,7 @@ audio_return_t _pcm_read(void *pcm_handle, void *buffer, uint32_t frames) return AUDIO_RET_OK; } -audio_return_t _pcm_get_fd(void *pcm_handle, int *fd) +audio_return_e _pcm_get_fd(void *pcm_handle, int *fd) { /* we use an internal API of the (tiny)alsa library, so it causes warning message during compile */ #ifdef __USE_TINYALSA__ @@ -380,7 +380,7 @@ audio_return_t _pcm_get_fd(void *pcm_handle, int *fd) return AUDIO_RET_OK; } -audio_return_t _pcm_recover(void *pcm_handle, int revents) +audio_return_e _pcm_recover(void *pcm_handle, int revents) { int state, err; @@ -460,7 +460,7 @@ audio_return_t _pcm_recover(void *pcm_handle, int revents) return AUDIO_RET_OK; } -audio_return_t _pcm_get_params(void *pcm_handle, uint32_t direction, void **sample_spec, uint32_t *period_size, uint32_t *periods) +audio_return_e _pcm_get_params(void *pcm_handle, uint32_t direction, void **sample_spec, uint32_t *period_size, uint32_t *periods) { #ifdef __USE_TINYALSA__ audio_pcm_sample_spec_t *ss; @@ -542,7 +542,7 @@ audio_return_t _pcm_get_params(void *pcm_handle, uint32_t direction, void **samp return AUDIO_RET_OK; } -audio_return_t _pcm_set_params(void *pcm_handle, uint32_t direction, void *sample_spec, uint32_t period_size, uint32_t periods) +audio_return_e _pcm_set_params(void *pcm_handle, uint32_t direction, void *sample_spec, uint32_t period_size, uint32_t periods) { #ifdef __USE_TINYALSA__ /* Parameters are only acceptable in pcm_open() function */ @@ -657,9 +657,9 @@ audio_return_t _pcm_set_params(void *pcm_handle, uint32_t direction, void *sampl } /* Generic snd pcm interface APIs */ -audio_return_t _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_e _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; + audio_return_e ret = AUDIO_RET_OK; snd_pcm_hw_params_t *hwparams; int err = 0; int dir; @@ -763,7 +763,7 @@ error: return AUDIO_ERR_RESOURCE; } -audio_return_t _pcm_set_sw_params(snd_pcm_t *pcm, snd_pcm_uframes_t avail_min, uint8_t period_event) +audio_return_e _pcm_set_sw_params(snd_pcm_t *pcm, snd_pcm_uframes_t avail_min, uint8_t period_event) { snd_pcm_sw_params_t *swparams; snd_pcm_uframes_t boundary; diff --git a/tizen-audio-impl.h b/tizen-audio-impl.h index 70b4993..ca1bc05 100644 --- a/tizen-audio-impl.h +++ b/tizen-audio-impl.h @@ -21,27 +21,27 @@ */ /* PCM */ -audio_return_t _pcm_open(const char *card, const char *device, uint32_t direction, void *sample_spec, uint32_t period_size, uint32_t periods, void **pcm_handle); -audio_return_t _pcm_start(void *pcm_handle); -audio_return_t _pcm_stop(void *pcm_handle); -audio_return_t _pcm_close(void *pcm_handle); -audio_return_t _pcm_avail(void *pcm_handle, uint32_t *avail); -audio_return_t _pcm_write(void *pcm_handle, const void *buffer, uint32_t frames); -audio_return_t _pcm_read(void *pcm_handle, void *buffer, uint32_t frames); -audio_return_t _pcm_get_fd(void *pcm_handle, int *fd); -audio_return_t _pcm_recover(void *pcm_handle, int revents); -audio_return_t _pcm_get_params(void *pcm_handle, uint32_t direction, void **sample_spec, uint32_t *period_size, uint32_t *periods); -audio_return_t _pcm_set_params(void *pcm_handle, uint32_t direction, void *sample_spec, uint32_t period_size, uint32_t periods); -audio_return_t _pcm_set_sw_params(snd_pcm_t *pcm, snd_pcm_uframes_t avail_min, uint8_t period_event); -audio_return_t _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_e _pcm_open(const char *card, const char *device, uint32_t direction, void *sample_spec, uint32_t period_size, uint32_t periods, void **pcm_handle); +audio_return_e _pcm_start(void *pcm_handle); +audio_return_e _pcm_stop(void *pcm_handle); +audio_return_e _pcm_close(void *pcm_handle); +audio_return_e _pcm_avail(void *pcm_handle, uint32_t *avail); +audio_return_e _pcm_write(void *pcm_handle, const void *buffer, uint32_t frames); +audio_return_e _pcm_read(void *pcm_handle, void *buffer, uint32_t frames); +audio_return_e _pcm_get_fd(void *pcm_handle, int *fd); +audio_return_e _pcm_recover(void *pcm_handle, int revents); +audio_return_e _pcm_get_params(void *pcm_handle, uint32_t direction, void **sample_spec, uint32_t *period_size, uint32_t *periods); +audio_return_e _pcm_set_params(void *pcm_handle, uint32_t direction, void *sample_spec, uint32_t period_size, uint32_t periods); +audio_return_e _pcm_set_sw_params(snd_pcm_t *pcm, snd_pcm_uframes_t avail_min, uint8_t period_event); +audio_return_e _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); /* Control */ -audio_return_t _mixer_control_init(audio_hal_t *ah); -audio_return_t _mixer_control_deinit(audio_hal_t *ah); -audio_return_t _mixer_control_set_param(audio_hal_t *ah, const char* ctl_name, snd_ctl_elem_value_t* value, int size); -audio_return_t _mixer_control_set_value(audio_hal_t *ah, const char *ctl_name, int val); -audio_return_t _mixer_control_set_value_string(audio_hal_t *ah, const char* ctl_name, const char* value); -audio_return_t _mixer_control_get_value(audio_hal_t *ah, const char *ctl_name, int *val); -audio_return_t _mixer_control_get_element(audio_hal_t *ah, const char *ctl_name, snd_hctl_elem_t **elem); +audio_return_e _mixer_control_init(audio_hal_t *ah); +audio_return_e _mixer_control_deinit(audio_hal_t *ah); +audio_return_e _mixer_control_set_param(audio_hal_t *ah, const char* ctl_name, snd_ctl_elem_value_t* value, int size); +audio_return_e _mixer_control_set_value(audio_hal_t *ah, const char *ctl_name, int val); +audio_return_e _mixer_control_set_value_string(audio_hal_t *ah, const char* ctl_name, const char* value); +audio_return_e _mixer_control_get_value(audio_hal_t *ah, const char *ctl_name, int *val); +audio_return_e _mixer_control_get_element(audio_hal_t *ah, const char *ctl_name, snd_hctl_elem_t **elem); #endif diff --git a/tizen-audio-internal.h b/tizen-audio-internal.h index 485e0bb..35dede3 100644 --- a/tizen-audio-internal.h +++ b/tizen-audio-internal.h @@ -237,16 +237,16 @@ typedef struct audio_hal { audio_hal_mixer_t mixer; } audio_hal_t; -audio_return_t _audio_ctrl_init(audio_hal_t *ah); -audio_return_t _audio_ctrl_deinit(audio_hal_t *ah); -audio_return_t _audio_volume_init(audio_hal_t *ah); -audio_return_t _audio_volume_deinit(audio_hal_t *ah); -audio_return_t _audio_routing_init(audio_hal_t *ah); -audio_return_t _audio_routing_deinit(audio_hal_t *ah); -audio_return_t _audio_stream_init(audio_hal_t *ah); -audio_return_t _audio_stream_deinit(audio_hal_t *ah); -audio_return_t _audio_pcm_init(audio_hal_t *ah); -audio_return_t _audio_pcm_deinit(audio_hal_t *ah); +audio_return_e _audio_ctrl_init(audio_hal_t *ah); +audio_return_e _audio_ctrl_deinit(audio_hal_t *ah); +audio_return_e _audio_volume_init(audio_hal_t *ah); +audio_return_e _audio_volume_deinit(audio_hal_t *ah); +audio_return_e _audio_routing_init(audio_hal_t *ah); +audio_return_e _audio_routing_deinit(audio_hal_t *ah); +audio_return_e _audio_stream_init(audio_hal_t *ah); +audio_return_e _audio_stream_deinit(audio_hal_t *ah); +audio_return_e _audio_pcm_init(audio_hal_t *ah); +audio_return_e _audio_pcm_deinit(audio_hal_t *ah); typedef struct _dump_data { char *strbuf; diff --git a/tizen-audio-pcm.c b/tizen-audio-pcm.c index c12c196..098e21e 100644 --- a/tizen-audio-pcm.c +++ b/tizen-audio-pcm.c @@ -24,7 +24,7 @@ #include "tizen-audio-internal.h" #include "tizen-audio-impl.h" -audio_return_t _audio_pcm_init(audio_hal_t *ah) +audio_return_e _audio_pcm_init(audio_hal_t *ah) { AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); @@ -36,7 +36,7 @@ audio_return_t _audio_pcm_init(audio_hal_t *ah) return AUDIO_RET_OK; } -audio_return_t _audio_pcm_deinit(audio_hal_t *ah) +audio_return_e _audio_pcm_deinit(audio_hal_t *ah) { AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); @@ -45,10 +45,10 @@ audio_return_t _audio_pcm_deinit(audio_hal_t *ah) return AUDIO_RET_OK; } -audio_return_t audio_pcm_open(void *audio_handle, const char *card, const char *device, uint32_t direction, void *sample_spec, +audio_return_e audio_pcm_open(void *audio_handle, const char *card, const char *device, uint32_t direction, void *sample_spec, uint32_t period_size, uint32_t periods, void **pcm_handle) { - audio_return_t audio_ret = AUDIO_RET_OK; + audio_return_e audio_ret = AUDIO_RET_OK; audio_hal_t *ah = NULL; AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER); @@ -67,9 +67,9 @@ audio_return_t audio_pcm_open(void *audio_handle, const char *card, const char * return AUDIO_RET_OK; } -audio_return_t audio_pcm_start(void *audio_handle, void *pcm_handle) +audio_return_e audio_pcm_start(void *audio_handle, void *pcm_handle) { - audio_return_t audio_ret = AUDIO_RET_OK; + audio_return_e audio_ret = AUDIO_RET_OK; AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER); AUDIO_RETURN_VAL_IF_FAIL(pcm_handle, AUDIO_ERR_PARAMETER); @@ -79,9 +79,9 @@ audio_return_t audio_pcm_start(void *audio_handle, void *pcm_handle) return audio_ret; } -audio_return_t audio_pcm_stop(void *audio_handle, void *pcm_handle) +audio_return_e audio_pcm_stop(void *audio_handle, void *pcm_handle) { - audio_return_t audio_ret = AUDIO_RET_OK; + audio_return_e audio_ret = AUDIO_RET_OK; AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER); AUDIO_RETURN_VAL_IF_FAIL(pcm_handle, AUDIO_ERR_PARAMETER); @@ -91,9 +91,9 @@ audio_return_t audio_pcm_stop(void *audio_handle, void *pcm_handle) return audio_ret; } -audio_return_t audio_pcm_close(void *audio_handle, void *pcm_handle) +audio_return_e audio_pcm_close(void *audio_handle, void *pcm_handle) { - audio_return_t audio_ret = AUDIO_RET_OK; + audio_return_e audio_ret = AUDIO_RET_OK; audio_hal_t *ah = NULL; AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER); @@ -111,9 +111,9 @@ audio_return_t audio_pcm_close(void *audio_handle, void *pcm_handle) return audio_ret; } -audio_return_t audio_pcm_avail(void *audio_handle, void *pcm_handle, uint32_t *avail) +audio_return_e audio_pcm_avail(void *audio_handle, void *pcm_handle, uint32_t *avail) { - audio_return_t audio_ret = AUDIO_RET_OK; + audio_return_e audio_ret = AUDIO_RET_OK; AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER); AUDIO_RETURN_VAL_IF_FAIL(pcm_handle, AUDIO_ERR_PARAMETER); @@ -124,9 +124,9 @@ audio_return_t audio_pcm_avail(void *audio_handle, void *pcm_handle, uint32_t *a return audio_ret; } -audio_return_t audio_pcm_write(void *audio_handle, void *pcm_handle, const void *buffer, uint32_t frames) +audio_return_e audio_pcm_write(void *audio_handle, void *pcm_handle, const void *buffer, uint32_t frames) { - audio_return_t audio_ret = AUDIO_RET_OK; + audio_return_e audio_ret = AUDIO_RET_OK; AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER); AUDIO_RETURN_VAL_IF_FAIL(pcm_handle, AUDIO_ERR_PARAMETER); @@ -136,9 +136,9 @@ audio_return_t audio_pcm_write(void *audio_handle, void *pcm_handle, const void return audio_ret; } -audio_return_t audio_pcm_read(void *audio_handle, void *pcm_handle, void *buffer, uint32_t frames) +audio_return_e audio_pcm_read(void *audio_handle, void *pcm_handle, void *buffer, uint32_t frames) { - audio_return_t audio_ret = AUDIO_RET_OK; + audio_return_e audio_ret = AUDIO_RET_OK; AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER); AUDIO_RETURN_VAL_IF_FAIL(pcm_handle, AUDIO_ERR_PARAMETER); @@ -148,9 +148,9 @@ audio_return_t audio_pcm_read(void *audio_handle, void *pcm_handle, void *buffer return audio_ret; } -audio_return_t audio_pcm_get_fd(void *audio_handle, void *pcm_handle, int *fd) +audio_return_e audio_pcm_get_fd(void *audio_handle, void *pcm_handle, int *fd) { - audio_return_t audio_ret = AUDIO_RET_OK; + audio_return_e audio_ret = AUDIO_RET_OK; AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER); AUDIO_RETURN_VAL_IF_FAIL(pcm_handle, AUDIO_ERR_PARAMETER); @@ -161,9 +161,9 @@ audio_return_t audio_pcm_get_fd(void *audio_handle, void *pcm_handle, int *fd) return audio_ret; } -audio_return_t audio_pcm_recover(void *audio_handle, void *pcm_handle, int revents) +audio_return_e audio_pcm_recover(void *audio_handle, void *pcm_handle, int revents) { - audio_return_t audio_ret = AUDIO_RET_OK; + audio_return_e audio_ret = AUDIO_RET_OK; AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER); AUDIO_RETURN_VAL_IF_FAIL(pcm_handle, AUDIO_ERR_PARAMETER); @@ -173,9 +173,9 @@ audio_return_t audio_pcm_recover(void *audio_handle, void *pcm_handle, int reven return audio_ret; } -audio_return_t audio_pcm_get_params(void *audio_handle, void *pcm_handle, uint32_t direction, void **sample_spec, uint32_t *period_size, uint32_t *periods) +audio_return_e audio_pcm_get_params(void *audio_handle, void *pcm_handle, uint32_t direction, void **sample_spec, uint32_t *period_size, uint32_t *periods) { - audio_return_t audio_ret = AUDIO_RET_OK; + audio_return_e audio_ret = AUDIO_RET_OK; AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER); AUDIO_RETURN_VAL_IF_FAIL(pcm_handle, AUDIO_ERR_PARAMETER); @@ -188,9 +188,9 @@ audio_return_t audio_pcm_get_params(void *audio_handle, void *pcm_handle, uint32 return audio_ret; } -audio_return_t audio_pcm_set_params(void *audio_handle, void *pcm_handle, uint32_t direction, void *sample_spec, uint32_t period_size, uint32_t periods) +audio_return_e audio_pcm_set_params(void *audio_handle, void *pcm_handle, uint32_t direction, void *sample_spec, uint32_t period_size, uint32_t periods) { - audio_return_t audio_ret = AUDIO_RET_OK; + audio_return_e audio_ret = AUDIO_RET_OK; AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER); AUDIO_RETURN_VAL_IF_FAIL(pcm_handle, AUDIO_ERR_PARAMETER); diff --git a/tizen-audio-routing.c b/tizen-audio-routing.c index ce7613c..feeed5d 100644 --- a/tizen-audio-routing.c +++ b/tizen-audio-routing.c @@ -80,9 +80,9 @@ static uint32_t __convert_device_string_to_enum(const char* device_str, uint32_t return device; } -static audio_return_t __set_devices(audio_hal_t *ah, const char *verb, device_info_t *devices, uint32_t num_of_devices) +static audio_return_e __set_devices(audio_hal_t *ah, const char *verb, device_info_s *devices, uint32_t num_of_devices) { - audio_return_t audio_ret = AUDIO_RET_OK; + audio_return_e audio_ret = AUDIO_RET_OK; uint32_t new_device = 0; const char *active_devices[MAX_DEVICES] = {NULL,}; int i = 0, j = 0, dev_idx = 0; @@ -146,10 +146,10 @@ static audio_return_t __set_devices(audio_hal_t *ah, const char *verb, device_in return audio_ret; } -static audio_return_t __update_route_ap_playback_capture(audio_hal_t *ah, audio_route_info_t *route_info) +static audio_return_e __update_route_ap_playback_capture(audio_hal_t *ah, audio_route_info_s *route_info) { - audio_return_t audio_ret = AUDIO_RET_OK; - device_info_t *devices = NULL; + audio_return_e audio_ret = AUDIO_RET_OK; + device_info_s *devices = NULL; const char *verb = mode_to_verb_str[VERB_NORMAL]; AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); @@ -175,9 +175,9 @@ static audio_return_t __update_route_ap_playback_capture(audio_hal_t *ah, audio_ return audio_ret; } -static audio_return_t __update_route_voip(audio_hal_t *ah, device_info_t *devices, int32_t num_of_devices) +static audio_return_e __update_route_voip(audio_hal_t *ah, device_info_s *devices, int32_t num_of_devices) { - audio_return_t audio_ret = AUDIO_RET_OK; + audio_return_e audio_ret = AUDIO_RET_OK; const char *verb = mode_to_verb_str[VERB_NORMAL]; AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); @@ -197,9 +197,9 @@ static audio_return_t __update_route_voip(audio_hal_t *ah, device_info_t *device return audio_ret; } -static audio_return_t __update_route_reset(audio_hal_t *ah, uint32_t direction) +static audio_return_e __update_route_reset(audio_hal_t *ah, uint32_t direction) { - audio_return_t audio_ret = AUDIO_RET_OK; + audio_return_e audio_ret = AUDIO_RET_OK; const char *active_devices[MAX_DEVICES] = {NULL,}; int i = 0, dev_idx = 0; @@ -262,9 +262,9 @@ static void __audio_routing_playback_rpi3(audio_hal_t *ah) } } -audio_return_t _audio_routing_init(audio_hal_t *ah) +audio_return_e _audio_routing_init(audio_hal_t *ah) { - audio_return_t audio_ret = AUDIO_RET_OK; + audio_return_e audio_ret = AUDIO_RET_OK; AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); @@ -278,20 +278,20 @@ audio_return_t _audio_routing_init(audio_hal_t *ah) return audio_ret; } -audio_return_t _audio_routing_deinit(audio_hal_t *ah) +audio_return_e _audio_routing_deinit(audio_hal_t *ah) { - audio_return_t audio_ret = AUDIO_RET_OK; + audio_return_e audio_ret = AUDIO_RET_OK; AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); return audio_ret; } -audio_return_t audio_update_route(void *audio_handle, audio_route_info_t *info) +audio_return_e audio_update_route(void *audio_handle, audio_route_info_s *info) { - audio_return_t audio_ret = AUDIO_RET_OK; + audio_return_e audio_ret = AUDIO_RET_OK; audio_hal_t *ah = (audio_hal_t *)audio_handle; - device_info_t *devices = NULL; + device_info_s *devices = NULL; AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); AUDIO_RETURN_VAL_IF_FAIL(info, AUDIO_ERR_PARAMETER); @@ -317,9 +317,9 @@ audio_return_t audio_update_route(void *audio_handle, audio_route_info_t *info) return audio_ret; } -audio_return_t audio_update_route_option(void *audio_handle, audio_route_option_t *option) +audio_return_e audio_update_route_option(void *audio_handle, audio_route_option_s *option) { - audio_return_t audio_ret = AUDIO_RET_OK; + audio_return_e audio_ret = AUDIO_RET_OK; audio_hal_t *ah = (audio_hal_t *)audio_handle; AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); diff --git a/tizen-audio-stream.c b/tizen-audio-stream.c index c60a443..918ea30 100644 --- a/tizen-audio-stream.c +++ b/tizen-audio-stream.c @@ -23,23 +23,23 @@ #include "tizen-audio-internal.h" -audio_return_t _audio_stream_init(audio_hal_t *ah) +audio_return_e _audio_stream_init(audio_hal_t *ah) { AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); return AUDIO_RET_OK; } -audio_return_t _audio_stream_deinit(audio_hal_t *ah) +audio_return_e _audio_stream_deinit(audio_hal_t *ah) { AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); return AUDIO_RET_OK; } -audio_return_t audio_notify_stream_connection_changed(void *audio_handle, audio_stream_info_t *info, uint32_t is_connected) +audio_return_e audio_notify_stream_connection_changed(void *audio_handle, audio_stream_info_s *info, uint32_t is_connected) { - audio_return_t audio_ret = AUDIO_RET_OK; + audio_return_e audio_ret = AUDIO_RET_OK; audio_hal_t *ah = (audio_hal_t *)audio_handle; AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); diff --git a/tizen-audio-volume.c b/tizen-audio-volume.c index 20f701e..8025b5f 100644 --- a/tizen-audio-volume.c +++ b/tizen-audio-volume.c @@ -176,7 +176,7 @@ static void __dump_tb(audio_hal_t *ah) } -static audio_return_t __load_volume_value_table_from_ini(audio_hal_t *ah) +static audio_return_e __load_volume_value_table_from_ini(audio_hal_t *ah) { dictionary * dict = NULL; uint32_t vol_type_idx, vol_level_idx, gain_type_idx; @@ -256,11 +256,11 @@ static audio_return_t __load_volume_value_table_from_ini(audio_hal_t *ah) return AUDIO_RET_OK; } -audio_return_t _audio_volume_init(audio_hal_t *ah) +audio_return_e _audio_volume_init(audio_hal_t *ah) { int i; int val = 0; - audio_return_t audio_ret = AUDIO_RET_OK; + audio_return_e audio_ret = AUDIO_RET_OK; int init_value[AUDIO_VOLUME_TYPE_MAX] = { 9, 11, 7, 11, 7, 4, 4, 7 }; AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); @@ -296,7 +296,7 @@ audio_return_t _audio_volume_init(audio_hal_t *ah) return audio_ret; } -audio_return_t _audio_volume_deinit(audio_hal_t *ah) +audio_return_e _audio_volume_deinit(audio_hal_t *ah) { AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); @@ -308,7 +308,7 @@ audio_return_t _audio_volume_deinit(audio_hal_t *ah) return AUDIO_RET_OK; } -audio_return_t audio_get_volume_level_max(void *audio_handle, audio_volume_info_t *info, uint32_t *level) +audio_return_e audio_get_volume_level_max(void *audio_handle, audio_volume_info_s *info, uint32_t *level) { audio_hal_t *ah = (audio_hal_t *)audio_handle; @@ -324,7 +324,7 @@ audio_return_t audio_get_volume_level_max(void *audio_handle, audio_volume_info_ return AUDIO_RET_OK; } -audio_return_t audio_get_volume_level(void *audio_handle, audio_volume_info_t *info, uint32_t *level) +audio_return_e audio_get_volume_level(void *audio_handle, audio_volume_info_s *info, uint32_t *level) { audio_hal_t *ah = (audio_hal_t *)audio_handle; @@ -344,7 +344,7 @@ audio_return_t audio_get_volume_level(void *audio_handle, audio_volume_info_t *i return AUDIO_RET_OK; } -audio_return_t audio_get_volume_value(void *audio_handle, audio_volume_info_t *info, uint32_t level, double *value) +audio_return_e audio_get_volume_value(void *audio_handle, audio_volume_info_s *info, uint32_t level, double *value) { audio_hal_t *ah = (audio_hal_t *)audio_handle; audio_volume_value_table_t *volume_value_table; @@ -368,9 +368,9 @@ audio_return_t audio_get_volume_value(void *audio_handle, audio_volume_info_t *i return AUDIO_RET_OK; } -audio_return_t audio_set_volume_level(void *audio_handle, audio_volume_info_t *info, uint32_t level) +audio_return_e audio_set_volume_level(void *audio_handle, audio_volume_info_s *info, uint32_t level) { - audio_return_t audio_ret = AUDIO_RET_OK; + audio_return_e audio_ret = AUDIO_RET_OK; audio_hal_t *ah = (audio_hal_t *)audio_handle; AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); @@ -390,9 +390,9 @@ audio_return_t audio_set_volume_level(void *audio_handle, audio_volume_info_t *i return audio_ret; } -audio_return_t audio_get_volume_mute(void *audio_handle, audio_volume_info_t *info, uint32_t *mute) +audio_return_e audio_get_volume_mute(void *audio_handle, audio_volume_info_s *info, uint32_t *mute) { - audio_return_t audio_ret = AUDIO_RET_OK; + audio_return_e audio_ret = AUDIO_RET_OK; audio_hal_t *ah = (audio_hal_t *)audio_handle; AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); @@ -404,9 +404,9 @@ audio_return_t audio_get_volume_mute(void *audio_handle, audio_volume_info_t *in return audio_ret; } -audio_return_t audio_set_volume_mute(void *audio_handle, audio_volume_info_t *info, uint32_t mute) +audio_return_e audio_set_volume_mute(void *audio_handle, audio_volume_info_s *info, uint32_t mute) { - audio_return_t audio_ret = AUDIO_RET_OK; + audio_return_e audio_ret = AUDIO_RET_OK; audio_hal_t *ah = (audio_hal_t *)audio_handle; AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); @@ -417,9 +417,9 @@ audio_return_t audio_set_volume_mute(void *audio_handle, audio_volume_info_t *in return audio_ret; } -audio_return_t audio_set_volume_ratio(void *audio_handle, audio_stream_info_t *info, double ratio) +audio_return_e audio_set_volume_ratio(void *audio_handle, audio_stream_info_s *info, double ratio) { - audio_return_t audio_ret = AUDIO_RET_OK; + audio_return_e audio_ret = AUDIO_RET_OK; audio_hal_t *ah = (audio_hal_t *)audio_handle; AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER); diff --git a/tizen-audio.c b/tizen-audio.c index 6128feb..7f3866d 100644 --- a/tizen-audio.c +++ b/tizen-audio.c @@ -23,10 +23,10 @@ #include "tizen-audio-internal.h" -audio_return_t audio_init(void **audio_handle) +audio_return_e audio_init(void **audio_handle) { audio_hal_t *ah; - audio_return_t ret = AUDIO_RET_OK; + audio_return_e ret = AUDIO_RET_OK; AUDIO_RETURN_VAL_IF_FAIL(audio_handle, AUDIO_ERR_PARAMETER); @@ -66,7 +66,7 @@ error_exit: return ret; } -audio_return_t audio_deinit(void *audio_handle) +audio_return_e audio_deinit(void *audio_handle) { audio_hal_t *ah = (audio_hal_t *)audio_handle; diff --git a/tizen-audio.h b/tizen-audio.h index 9c893db..1f2289f 100644 --- a/tizen-audio.h +++ b/tizen-audio.h @@ -21,6 +21,7 @@ #define footizenaudiofoo #include +#include /** * @file tizen-audio.h @@ -33,113 +34,6 @@ */ /** - * @brief Enumeration for return codes. - * @since_tizen 3.0 - */ -typedef enum audio_return { - AUDIO_RET_OK = 0, - 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_INVALID_STATE = (int32_t)0x80001004, - AUDIO_ERR_INTERNAL = (int32_t)0x80001005, - /* add new enemerator here */ - AUDIO_ERR_NOT_IMPLEMENTED = (int32_t)0x80001100, -} audio_return_t ; - -/** - * @brief Enumeration for audio direction. - * @since_tizen 3.0 - */ -typedef enum audio_direction { - AUDIO_DIRECTION_IN, /**< Capture */ - AUDIO_DIRECTION_OUT, /**< Playback */ -} audio_direction_t; - -/** - * @brief Device information including type, direction and id. - * @since_tizen 3.0 - */ -typedef struct device_info { - const char *type; - uint32_t direction; - uint32_t id; -} device_info_t; - -/** - * @brief Volume information including type, gain and direction. - * @since_tizen 3.0 - */ -typedef struct audio_volume_info { - const char *type; - const char *gain; - uint32_t direction; -} audio_volume_info_t ; - -/** - * @brief Route information including role and device. - * @since_tizen 3.0 - */ -typedef struct audio_route_info { - const char *role; - device_info_t *device_infos; - uint32_t num_of_devices; -} audio_route_info_t; - -/** - * @brief Route option including role, name and value. - * @since_tizen 3.0 - */ -typedef struct audio_route_option { - const char *role; - const char *name; - int32_t value; -} audio_route_option_t; - -/** - * @brief Stream information including role, direction and index. - * @since_tizen 3.0 - */ -typedef struct audio_stream_info { - const char *role; - uint32_t direction; - uint32_t idx; -} audio_stream_info_t ; - -/* Overall */ -typedef struct audio_interface { - /* Initialization & de-initialization */ - audio_return_t (*init)(void **audio_handle); - audio_return_t (*deinit)(void *audio_handle); - /* Volume */ - audio_return_t (*get_volume_level_max)(void *audio_handle, audio_volume_info_t *info, uint32_t *level); - audio_return_t (*get_volume_level)(void *audio_handle, audio_volume_info_t *info, uint32_t *level); - audio_return_t (*set_volume_level)(void *audio_handle, audio_volume_info_t *info, uint32_t level); - audio_return_t (*get_volume_value)(void *audio_handle, audio_volume_info_t *info, uint32_t level, double *value); - audio_return_t (*get_volume_mute)(void *audio_handle, audio_volume_info_t *info, uint32_t *mute); - audio_return_t (*set_volume_mute)(void *audio_handle, audio_volume_info_t *info, uint32_t mute); - audio_return_t (*set_volume_ratio)(void *audio_handle, audio_stream_info_t *info, double ratio); - /* Routing */ - audio_return_t (*update_route)(void *audio_handle, audio_route_info_t *info); - audio_return_t (*update_route_option)(void *audio_handle, audio_route_option_t *option); - /* Stream */ - audio_return_t (*notify_stream_connection_changed)(void *audio_handle, audio_stream_info_t *info, uint32_t is_connected); - /* PCM */ - audio_return_t (*pcm_open)(void *audio_handle, const char *card, const char *device, uint32_t direction, void *sample_spec, uint32_t period_size, uint32_t periods, void **pcm_handle); - audio_return_t (*pcm_start)(void *audio_handle, void *pcm_handle); - audio_return_t (*pcm_stop)(void *audio_handle, void *pcm_handle); - audio_return_t (*pcm_close)(void *audio_handle, void *pcm_handle); - audio_return_t (*pcm_avail)(void *audio_handle, void *pcm_handle, uint32_t *avail); - audio_return_t (*pcm_write)(void *audio_handle, void *pcm_handle, const void *buffer, uint32_t frames); - audio_return_t (*pcm_read)(void *audio_handle, void *pcm_handle, void *buffer, uint32_t frames); - audio_return_t (*pcm_get_fd)(void *audio_handle, void *pcm_handle, int *fd); - audio_return_t (*pcm_recover)(void *audio_handle, void *pcm_handle, int revents); - audio_return_t (*pcm_get_params)(void *audio_handle, void *pcm_handle, uint32_t direction, void **sample_spec, uint32_t *period_size, uint32_t *periods); - audio_return_t (*pcm_set_params)(void *audio_handle, void *pcm_handle, uint32_t direction, void *sample_spec, uint32_t period_size, uint32_t periods); -} audio_interface_t; - -/** * @brief Initializes audio hal. * @since_tizen 3.0 * @param[out] audio_handle The audio hal handle @@ -149,7 +43,7 @@ typedef struct audio_interface { * @retval #AUDIO_RET_OK Success * @see audio_deinit() */ -audio_return_t audio_init(void **audio_handle); +audio_return_e audio_init(void **audio_handle); /** * @brief De-initializes audio hal. @@ -161,7 +55,7 @@ audio_return_t audio_init(void **audio_handle); * @retval #AUDIO_RET_OK Success * @see audio_init() */ -audio_return_t audio_deinit(void *audio_handle); +audio_return_e audio_deinit(void *audio_handle); /** * @brief Gets the maximum volume level supported for a particular volume information. @@ -177,7 +71,7 @@ audio_return_t audio_deinit(void *audio_handle); * @see audio_get_volume_level() * @see audio_get_volume_value() */ -audio_return_t audio_get_volume_level_max(void *audio_handle, audio_volume_info_t *info, uint32_t *level); +audio_return_e audio_get_volume_level_max(void *audio_handle, audio_volume_info_s *info, uint32_t *level); /** * @brief Gets the volume level specified for a particular volume information. @@ -193,7 +87,7 @@ audio_return_t audio_get_volume_level_max(void *audio_handle, audio_volume_info_ * @see audio_get_volume_level_max() * @see audio_get_volume_value() */ -audio_return_t audio_get_volume_level(void *audio_handle, audio_volume_info_t *info, uint32_t *level); +audio_return_e audio_get_volume_level(void *audio_handle, audio_volume_info_s *info, uint32_t *level); /** * @brief Sets the volume level specified for a particular volume information. @@ -209,7 +103,7 @@ audio_return_t audio_get_volume_level(void *audio_handle, audio_volume_info_t *i * @see audio_get_volume_level_max() * @see audio_get_volume_value() */ -audio_return_t audio_set_volume_level(void *audio_handle, audio_volume_info_t *info, uint32_t level); +audio_return_e audio_set_volume_level(void *audio_handle, audio_volume_info_s *info, uint32_t level); /** * @brief Gets the volume value specified for a particular volume information and level. @@ -226,7 +120,7 @@ audio_return_t audio_set_volume_level(void *audio_handle, audio_volume_info_t *i * @see audio_get_volume_level() * @see audio_get_volume_level_max() */ -audio_return_t audio_get_volume_value(void *audio_handle, audio_volume_info_t *info, uint32_t level, double *value); +audio_return_e audio_get_volume_value(void *audio_handle, audio_volume_info_s *info, uint32_t level, double *value); /** * @brief Gets the volume mute specified for a particular volume information. @@ -240,7 +134,7 @@ audio_return_t audio_get_volume_value(void *audio_handle, audio_volume_info_t *i * @retval #AUDIO_RET_OK Success * @see audio_set_volume_mute() */ -audio_return_t audio_get_volume_mute(void *audio_handle, audio_volume_info_t *info, uint32_t *mute); +audio_return_e audio_get_volume_mute(void *audio_handle, audio_volume_info_s *info, uint32_t *mute); /** * @brief Sets the volume mute specified for a particular volume information. @@ -254,7 +148,20 @@ audio_return_t audio_get_volume_mute(void *audio_handle, audio_volume_info_t *in * @retval #AUDIO_RET_OK Success * @see audio_get_volume_mute() */ -audio_return_t audio_set_volume_mute(void *audio_handle, audio_volume_info_t *info, uint32_t mute); +audio_return_e audio_set_volume_mute(void *audio_handle, audio_volume_info_s *info, uint32_t mute); + +/** + * @brief Sets the volume ratio specified for a particular volume information. (optional) + * @since_tizen 5.5 + * @param[in] audio_handle The audio hal handle + * @param[in] info The audio volume information + * @param[in] ratio The volume ratio to be set (Min.:0.0 ~ Max.:1.0, default:1.0) + * + * @return @c 0 on success, + * otherwise a negative error value + * @retval #AUDIO_RET_OK Success + */ +audio_return_e audio_set_volume_ratio(void *audio_handle, audio_stream_info_s *info, double ratio); /** * @brief Updates the audio routing according to audio route information. @@ -267,7 +174,7 @@ audio_return_t audio_set_volume_mute(void *audio_handle, audio_volume_info_t *in * @retval #AUDIO_RET_OK Success * @see audio_update_route_option() */ -audio_return_t audio_update_route(void *audio_handle, audio_route_info_t *info); +audio_return_e audio_update_route(void *audio_handle, audio_route_info_s *info); /** * @brief Updates audio routing option according to audio route option. @@ -283,7 +190,7 @@ audio_return_t audio_update_route(void *audio_handle, audio_route_info_t *info); * @retval #AUDIO_RET_OK Success * @see audio_update_route() */ -audio_return_t audio_update_route_option(void *audio_handle, audio_route_option_t *option); +audio_return_e audio_update_route_option(void *audio_handle, audio_route_option_s *option); /** * @brief Gets notified when a stream is connected and disconnected. @@ -298,7 +205,7 @@ audio_return_t audio_update_route_option(void *audio_handle, audio_route_option_ * otherwise a negative error value * @retval #AUDIO_RET_OK Success */ -audio_return_t audio_notify_stream_connection_changed(void *audio_handle, audio_stream_info_t *info, uint32_t is_connected); +audio_return_e audio_notify_stream_connection_changed(void *audio_handle, audio_stream_info_s *info, uint32_t is_connected); /** * @brief Opens a PCM device. @@ -317,7 +224,7 @@ audio_return_t audio_notify_stream_connection_changed(void *audio_handle, audio_ * @retval #AUDIO_RET_OK Success * @see audio_pcm_close() */ -audio_return_t audio_pcm_open(void *audio_handle, const char *card, const char *device, uint32_t direction, void *sample_spec, uint32_t period_size, uint32_t periods, void **pcm_handle); +audio_return_e audio_pcm_open(void *audio_handle, const char *card, const char *device, uint32_t direction, void *sample_spec, uint32_t period_size, uint32_t periods, void **pcm_handle); /** * @brief Starts a PCM device. @@ -334,7 +241,7 @@ audio_return_t audio_pcm_open(void *audio_handle, const char *card, const char * * @see audio_pcm_stop() * @see audio_pcm_recover() */ -audio_return_t audio_pcm_start(void *audio_handle, void *pcm_handle); +audio_return_e audio_pcm_start(void *audio_handle, void *pcm_handle); /** * @brief Stops a PCM device. @@ -347,7 +254,7 @@ audio_return_t audio_pcm_start(void *audio_handle, void *pcm_handle); * @retval #AUDIO_RET_OK Success * @see audio_pcm_start() */ -audio_return_t audio_pcm_stop(void *audio_handle, void *pcm_handle); +audio_return_e audio_pcm_stop(void *audio_handle, void *pcm_handle); /** * @brief Closes a PCM device. @@ -360,7 +267,7 @@ audio_return_t audio_pcm_stop(void *audio_handle, void *pcm_handle); * @retval #AUDIO_RET_OK Success * @see audio_pcm_open() */ -audio_return_t audio_pcm_close(void *audio_handle, void *pcm_handle); +audio_return_e audio_pcm_close(void *audio_handle, void *pcm_handle); /** * @brief Gets available number of frames. @@ -375,7 +282,7 @@ audio_return_t audio_pcm_close(void *audio_handle, void *pcm_handle); * @see audio_pcm_write() * @see audio_pcm_read() */ -audio_return_t audio_pcm_avail(void *audio_handle, void *pcm_handle, uint32_t *avail); +audio_return_e audio_pcm_avail(void *audio_handle, void *pcm_handle, uint32_t *avail); /** * @brief Writes frames to a PCM device. @@ -391,7 +298,7 @@ audio_return_t audio_pcm_avail(void *audio_handle, void *pcm_handle, uint32_t *a * @see audio_pcm_avail() * @see audio_pcm_recover() */ -audio_return_t audio_pcm_write(void *audio_handle, void *pcm_handle, const void *buffer, uint32_t frames); +audio_return_e audio_pcm_write(void *audio_handle, void *pcm_handle, const void *buffer, uint32_t frames); /** * @brief Reads frames from a PCM device. @@ -407,7 +314,7 @@ audio_return_t audio_pcm_write(void *audio_handle, void *pcm_handle, const void * @see audio_pcm_avail() * @see audio_pcm_recover() */ -audio_return_t audio_pcm_read(void *audio_handle, void *pcm_handle, void *buffer, uint32_t frames); +audio_return_e audio_pcm_read(void *audio_handle, void *pcm_handle, void *buffer, uint32_t frames); /** * @brief Gets poll descriptor for a PCM handle. @@ -422,7 +329,7 @@ audio_return_t audio_pcm_read(void *audio_handle, void *pcm_handle, void *buffer * @see audio_pcm_open() * @see audio_pcm_recover() */ -audio_return_t audio_pcm_get_fd(void *audio_handle, void *pcm_handle, int *fd); +audio_return_e audio_pcm_get_fd(void *audio_handle, void *pcm_handle, int *fd); /** * @brief Recovers the PCM state. @@ -439,7 +346,7 @@ audio_return_t audio_pcm_get_fd(void *audio_handle, void *pcm_handle, int *fd); * @see audio_pcm_read() * @see audio_pcm_get_fd() */ -audio_return_t audio_pcm_recover(void *audio_handle, void *pcm_handle, int revents); +audio_return_e audio_pcm_recover(void *audio_handle, void *pcm_handle, int revents); /** * @brief Gets parameters of a PCM device. @@ -456,7 +363,7 @@ audio_return_t audio_pcm_recover(void *audio_handle, void *pcm_handle, int reven * @retval #AUDIO_RET_OK Success * @see audio_pcm_set_params() */ -audio_return_t audio_pcm_get_params(void *audio_handle, void *pcm_handle, uint32_t direction, void **sample_spec, uint32_t *period_size, uint32_t *periods); +audio_return_e audio_pcm_get_params(void *audio_handle, void *pcm_handle, uint32_t direction, void **sample_spec, uint32_t *period_size, uint32_t *periods); /** * @brief Sets hardware and software parameters of a PCM device. @@ -473,7 +380,7 @@ audio_return_t audio_pcm_get_params(void *audio_handle, void *pcm_handle, uint32 * @retval #AUDIO_RET_OK Success * @see audio_pcm_set_params() */ -audio_return_t audio_pcm_set_params(void *audio_handle, void *pcm_handle, uint32_t direction, void *sample_spec, uint32_t period_size, uint32_t periods); +audio_return_e audio_pcm_set_params(void *audio_handle, void *pcm_handle, uint32_t direction, void *sample_spec, uint32_t period_size, uint32_t periods); /** * @} -- 2.7.4