From 7760bf0dc954e82d6fb3f5c67b34a4ecbde617dc Mon Sep 17 00:00:00 2001 From: Ievgen Vagin Date: Tue, 14 Jun 2016 14:00:54 +0300 Subject: [PATCH 02/14] Initial SoundPool package stub Change-Id: I9f9c4138355887a8dc15c14f1562ca1857fd9780 Signed-off-by: Ievgen Vagin --- AUTHORS | 4 + CMakeLists.txt | 102 +++++++++++++++++++++ LICENSE.APLv2 | 204 ++++++++++++++++++++++++++++++++++++++++++ NOTICE | 3 + doc/sound_pool_doc.h | 27 ++++++ include/sound_pool.h | 33 +++++++ packaging/sound-pool.manifest | 5 ++ packaging/sound-pool.spec | 59 ++++++++++++ sound-pool.pc.in | 11 +++ src/sound_pool.c | 21 +++++ 10 files changed, 469 insertions(+) create mode 100755 AUTHORS create mode 100755 CMakeLists.txt create mode 100644 LICENSE.APLv2 create mode 100644 NOTICE create mode 100644 doc/sound_pool_doc.h create mode 100644 include/sound_pool.h create mode 100644 packaging/sound-pool.manifest create mode 100644 packaging/sound-pool.spec create mode 100644 sound-pool.pc.in create mode 100644 src/sound_pool.c diff --git a/AUTHORS b/AUTHORS new file mode 100755 index 0000000..0bc26c3 --- /dev/null +++ b/AUTHORS @@ -0,0 +1,4 @@ +Oleksandr Danchenko +Ievgen Vagin +Seungbae Shin + diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100755 index 0000000..12706f9 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,102 @@ + +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +SET(fw_name "sound-pool") + +PROJECT(${fw_name}) + +SET(LIB_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/lib) +SET(PREFIX ${CMAKE_INSTALL_PREFIX}) + +SET(INC_DIR include) +INCLUDE_DIRECTORIES(${INC_DIR}) + +SET(dependents "dlog glib-2.0 openal freealut" ) +SET(pc_dependents "dlog glib-2.0 openal freealut" ) + +INCLUDE(FindPkgConfig) +pkg_check_modules(${fw_name} REQUIRED ${dependents}) +FOREACH(flag ${${fw_name}_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) + +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -fPIC -Wall") +SET(CMAKE_C_FLAGS_DEBUG "-O0 -g") + +IF("${ARCH}" STREQUAL "arm") + ADD_DEFINITIONS("-DTARGET") +ENDIF("${ARCH}" STREQUAL "arm") + +ADD_DEFINITIONS("-DPREFIX=\"${CMAKE_INSTALL_PREFIX}\"") + +SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed -Wl,--rpath=${LIB_INSTALL_DIR}") + +AUX_SOURCE_DIRECTORY (src MAIN_SRC) + +LIST (APPEND SOURCES + ${MAIN_SRC} + ) + +ADD_LIBRARY(${fw_name} SHARED ${SOURCES}) + +TARGET_LINK_LIBRARIES(${fw_name} ${${fw_name}_LDFLAGS}) + +SET_TARGET_PROPERTIES(${fw_name} + PROPERTIES + VERSION ${FULLVER} + SOVERSION ${MAJORVER} + CLEAN_DIRECT_OUTPUT 1 +) + +INSTALL(TARGETS ${fw_name} DESTINATION ${LIB_INSTALL_DIR}) +INSTALL( + DIRECTORY ${INC_DIR}/ DESTINATION ${INC_DIR}/media + FILES_MATCHING + PATTERN "mm_soundpool_private.h" EXCLUDE + PATTERN "${INC_DIR}/*.h" + ) + + +SET(PC_NAME ${fw_name}) +SET(PC_REQUIRED ${pc_dependents}) +SET(PC_INC_PREFIX ${INC_DIR}/media) +SET(PC_LDFLAGS -l${fw_name}) + +CONFIGURE_FILE( + ${fw_name}.pc.in + ${CMAKE_CURRENT_SOURCE_DIR}/${fw_name}.pc + @ONLY +) +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${fw_name}.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig) + +#ADD_SUBDIRECTORY(test) + +IF(UNIX) + +ADD_CUSTOM_TARGET (distclean @echo cleaning for source distribution) +ADD_CUSTOM_COMMAND( + DEPENDS clean + COMMENT "distribution clean" + COMMAND find + ARGS . + -not -name config.cmake -and \( + -name tester.c -or + -name Testing -or + -name CMakeFiles -or + -name cmake.depends -or + -name cmake.check_depends -or + -name CMakeCache.txt -or + -name cmake.check_cache -or + -name *.cmake -or + -name Makefile -or + -name core -or + -name core.* -or + -name gmon.out -or + -name install_manifest.txt -or + -name *.pc -or + -name *~ \) + | grep -v TC | xargs rm -rf + TARGET distclean + VERBATIM +) + +ENDIF(UNIX) diff --git a/LICENSE.APLv2 b/LICENSE.APLv2 new file mode 100644 index 0000000..d45e772 --- /dev/null +++ b/LICENSE.APLv2 @@ -0,0 +1,204 @@ +Copyright (c) 2000 - 2016 Samsung Electronics Co., Ltd. All rights reserved. + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + diff --git a/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/doc/sound_pool_doc.h b/doc/sound_pool_doc.h new file mode 100644 index 0000000..3b35e5c --- /dev/null +++ b/doc/sound_pool_doc.h @@ -0,0 +1,27 @@ +/* + * 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. + */ + + +#ifndef __TIZEN_SOUND_POOL_DOC_H__ +#define __TIZEN_SOUND_POOL_DOC_H__ + +/** + * @file sound_pool_doc.h + * @brief This file contains high level documentation for the Tizen Sound Pool API. + * + */ + +#endif /* __TIZEN_SOUND_POOL_DOC_H__ */ diff --git a/include/sound_pool.h b/include/sound_pool.h new file mode 100644 index 0000000..94d4b8c --- /dev/null +++ b/include/sound_pool.h @@ -0,0 +1,33 @@ +/* + * 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. + */ + +#ifndef __TIZEN_SOUND_POOL_H__ +#define __TIZEN_SOUND_POOL_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @file sound_pool.h + * @brief This file contains Tizen Sound Pool API. + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __TIZEN_SOUND_POOL_H__ */ diff --git a/packaging/sound-pool.manifest b/packaging/sound-pool.manifest new file mode 100644 index 0000000..a76fdba --- /dev/null +++ b/packaging/sound-pool.manifest @@ -0,0 +1,5 @@ + + + + + diff --git a/packaging/sound-pool.spec b/packaging/sound-pool.spec new file mode 100644 index 0000000..5d3ff1f --- /dev/null +++ b/packaging/sound-pool.spec @@ -0,0 +1,59 @@ +Name: sound-pool +Version: 0.0.1 +Summary: Tizen Sound Pool module +Release: 0 +Group: Multimedia/Framework +License: Apache-2.0 +URL: http://source.tizen.org +Source0: %{name}-%{version}.tar.gz +Source1001: sound-pool.manifest +BuildRequires: cmake +BuildRequires: pkgconfig(dlog) +BuildRequires: pkgconfig(glib-2.0) +BuildRequires: pkgconfig(openal) +BuildRequires: pkgconfig(freealut) + +%description +Tizen Sound Pool Module allowing sounds playing for audio resources. + +%package devel +Summary: Tizen Sound Pool Module allowing sounds playing for audio resources (Development). +Group: Multimedia/Framework +Requires: %{name} = %{version}-%{release} + +%description devel +SoundPool Library in Tizen Native API (DEV). + +%prep +%setup -q +cp %{SOURCE1001} . + +%build +export CFLAGS="$CFLAGS -fprofile-arcs -ftest-coverage" +export CXXFLAGS="$CXXFLAGS -fprofile-arcs -ftest-coverage" +export LDLAGS="$LDLAGS -lgcov" + +MAJORVER=`echo %{version} | awk 'BEGIN {FS="."}{print $1}'` +%cmake . -DCMAKE_INSTALL_PREFIX=%{_prefix} -DFULLVER=%{version} -DMAJORVER=${MAJORVER} + +make %{?jobs:-j%jobs} + +%install +rm -rf %{buildroot} +mkdir -p %{buildroot}%{_bindir} + +%make_install + +%post -p /sbin/ldconfig +%postun -p /sbin/ldconfig + +%files +%manifest %{name}.manifest +%license LICENSE.APLv2 +%{_libdir}/lib%{name}.so.* + +%files devel +%manifest %{name}.manifest +%{_includedir}/media/*.h +%{_libdir}/pkgconfig/*.pc +%{_libdir}/lib%{name}.so diff --git a/sound-pool.pc.in b/sound-pool.pc.in new file mode 100644 index 0000000..31f78b4 --- /dev/null +++ b/sound-pool.pc.in @@ -0,0 +1,11 @@ +prefix = @PREFIX@ +exec_prefix=${prefix} +libdir = ${prefix}/lib +includedir = ${prefix}/@PC_INC_PREFIX@ + +Name : @fw_name@ +Description : Multimedia Framework SoundPool Library +Requires : @pc_dependents@ +Version : @VERSION@ +Libs : -L${libdir} @PC_LDFLAGS@ +Cflags : -I${includedir} diff --git a/src/sound_pool.c b/src/sound_pool.c new file mode 100644 index 0000000..f720f45 --- /dev/null +++ b/src/sound_pool.c @@ -0,0 +1,21 @@ +/* + * 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. + */ + +#include "sound_pool.h" + +/* +* Public Implementation +*/ -- 2.7.4 From 121f288e7b6089ea604db56eac7d5f849d53f7b1 Mon Sep 17 00:00:00 2001 From: Ievgen Vagin Date: Tue, 14 Jun 2016 14:14:35 +0300 Subject: [PATCH 03/14] SoundPool API Change-Id: Ie254af065bf489eb47166d7169d55708240e3dd6 Signed-off-by: Ievgen Vagin --- AUTHORS | 6 +- doc/sound_pool_doc.h | 42 +++ include/sound_pool.h | 665 ++++++++++++++++++++++++++++++++++++++++++++++ include/sound_pool_type.h | 106 ++++++++ 4 files changed, 816 insertions(+), 3 deletions(-) create mode 100644 include/sound_pool_type.h diff --git a/AUTHORS b/AUTHORS index 0bc26c3..22ce42b 100755 --- a/AUTHORS +++ b/AUTHORS @@ -1,4 +1,4 @@ -Oleksandr Danchenko -Ievgen Vagin Seungbae Shin - +Ievgen Vagin +Oleksandr Danchenko +AravindKumar Gara diff --git a/doc/sound_pool_doc.h b/doc/sound_pool_doc.h index 3b35e5c..d063e3d 100644 --- a/doc/sound_pool_doc.h +++ b/doc/sound_pool_doc.h @@ -24,4 +24,46 @@ * */ +/** + * @defgroup CAPI_SOUND_POOL_MODULE Sound Pool + * @ingroup CAPI_MEDIA_FRAMEWORK + */ + +/** + * @ingroup CAPI_MEDIA_FRAMEWORK + * @addtogroup CAPI_SOUND_POOL_MODULE + * @brief The @ref CAPI_SOUND_POOL_MODULE API provides functions for easy sound + * management such as grouping sounds in pools, play, pause, resume, + * stop operations of sound streams and controlling stream/pool states. + * @section CAPI_SOUND_POOL_MODULE_HEADER Required Header + * \#include + * + * @section CAPI_SOUND_POOL_MODULE_OVERVIEW Overview + * The @ref CAPI_SOUND_POOL_MODULE module provides a set of functions to + * manipulate sounds in application. It allows easy loading, grouping, playing, + * and controlling the sound streams playback; changing parameters of sound + * streams such as volume, number of repeats (loops), and priorities also. Sound + * pool is aimed to control short sounds which can be grouped by some criteria + * (game level, or character, application audio theme, etc).\n + * Module includes three main entities: sound pool, sound source and sound + * stream.\n + * Sound pool is a collection of sounds. It can be defined as isolated + * environment where sound streams can be managed. When pool is created, it has + * to be filled by the sound sources. Sources can be defined as audio data + * which can be loaded from files. When you load the source from file + * to pool, audio data is loaded from this file and cached in the memory. + * After this it is possible to play sound streams using this cached data. + * Multiple sound streams can be played simultaneously using different or the + * same sources. Stream can be defined as an instance of sound source. Stream + * exists from the moment when play command is called till the end of until + * playback is finished or stop command is called.\n + * The @ref CAPI_SOUND_POOL_MODULE module supports multiple sound pools + * management. Pools can be activated/deactivated. When deactivation is + * performed, all playing streams corresponding to the pool gets suspended state. + * When pool is activated, then all suspended streams are resumed. Also, it is + * possible to change volume of the pool which affects all the streams in the + * pool. + * + */ + #endif /* __TIZEN_SOUND_POOL_DOC_H__ */ diff --git a/include/sound_pool.h b/include/sound_pool.h index 94d4b8c..67e9d41 100644 --- a/include/sound_pool.h +++ b/include/sound_pool.h @@ -17,6 +17,8 @@ #ifndef __TIZEN_SOUND_POOL_H__ #define __TIZEN_SOUND_POOL_H__ +#include "sound_pool_type.h" + #ifdef __cplusplus extern "C" { #endif @@ -26,6 +28,669 @@ extern "C" { * @brief This file contains Tizen Sound Pool API. */ +/** + * @addtogroup CAPI_SOUND_POOL_MODULE + * @{ + */ + +/** + * @brief Called when sound pool state is changed. + * + * @since_tizen 3.0 + * @param [in] pool The handle to the sound pool + * @param [in] prev_state Previous pool state + * @param [in] cur_state Current pool state + * @param [in] user_data The user data passed from the code where + * @ref sound_pool_set_state_change_callback() was + * called. + * + * @pre Create sound pool handler by calling @ref sound_pool_create() + * @pre Call @ref sound_pool_set_state_change_callback() + * + * @see sound_pool_create() + * @see sound_pool_set_state_change_callback() + * @see sound_pool_state_e + */ +typedef void (*sound_pool_state_change_cb) (sound_pool_h pool, + sound_pool_state_e prev_state, sound_pool_state_e cur_state, + void *user_data); + +/** + * @brief Called when sound pool stream state is changed. + * + * @since_tizen 3.0 + * @param [in] pool The handle to the sound pool + * @param [in] tag Unique string that identifies source which was used + * for stream creation + * @param [in] id Unique stream identifier + * @param [in] prev_state Previous stream state + * @param [in] cur_state Current stream state + * @param [in] data The user data passed from the code where + * @ref sound_pool_stream_set_state_change_callback() was + * called. + * + * @pre Create sound pool handler by calling @ref sound_pool_create() + * @pre Load source to pool by calling @ref sound_pool_load_source_from_file() + * @pre Start source playback by calling @ref sound_pool_stream_play() + * @pre Call @ref sound_pool_stream_set_state_change_callback() + * + * @see sound_pool_create() + * @see sound_pool_load_source_from_file() + * @see sound_pool_stream_play() + * @see sound_pool_stream_set_state_change_callback() + * @see sound_pool_stream_state_e + */ +typedef void (*sound_pool_stream_state_change_cb) (sound_pool_h pool, + const char *tag, unsigned id, sound_pool_stream_state_e prev_state, + sound_pool_stream_state_e cur_state, void *user_data); + +/** + * @brief Creates sound pool instance that can be used for sound sources + * loading/unloading. + * @details Up to 32 sound pools can be created. Several pools can be active + * at the same time. Streams can be in playing state only when pool is + * active. + * @remarks When pool has been created, pool state is + * SOUND_POOL_STATE_INACTIVE. To activate a pool use + * @ref sound_pool_activate() function. + * + * @since_tizen 3.0 + * @param [in] max_streams Maximum number of active streams + * @param [out] pool The handle to the pool that will be created + * @return @c 0 on success, otherwise a negative error value + * @retval #SOUND_POOL_ERROR_INVALID_PARAMETER + * Invalid parameter (@a pool is NULL or @ max_streams is 0) + * @retval #SOUND_POOL_ERROR_OUT_OF_MEMORY + * Not enough memory to create sound pool + * @retval #SOUND_POOL_ERROR_INVALID_OPERATION + * Maximal amount of sound pools is exceeded (usually, 32 pools allowed) + * + * @see sound_pool_destroy() + */ +int sound_pool_create(unsigned max_streams, sound_pool_h *pool); + +/** + * @brief Destroys sound pool and cleans allocated memory. + * @details Stops all streams and unloads all sources associated with pool. + * + * @since_tizen 3.0 + * @param [in] pool The handle to the pool that will be destroyed + * @return @c 0 on success, otherwise a negative error value + * @retval #SOUND_POOL_ERROR_INVALID_PARAMETER + * Invalid parameter (@a pool is NULL or corrupted) + * + * @pre Create sound pool handler by calling @ref sound_pool_create() + * + * @see sound_pool_create() + */ +int sound_pool_destroy(sound_pool_h pool); + +/** + * @brief Loads sound source data from file to pool. + * @details After calling this routine the source can be accessed by its @a tag. + * @remarks Input data can be either raw or encoded. + * Each of loaded sources must have unique @a tag + * It is synchronous operation. + * + * @since_tizen 3.0 + * @param [in] pool The handle to the sound pool + * @param [in] file_name The name of file that contains sound data + * @param [in] tag Unique string that will be used to identify source + * @return @c 0 on success, otherwise a negative error value + * @retval #SOUND_POOL_ERROR_INVALID_PARAMETER + * Invalid parameter (@a pool is NULL or corrupted, @a file_name is + * NULL, @a tag is NULL or @a tag/@a file_name length is too long) + * @retval #SOUND_POOL_ERROR_OUT_OF_MEMORY Not enough memory to allocate source + * @retval #SOUND_POOL_ERROR_NO_SUCH_FILE No file determined by @a file_name + * @retval #SOUND_POOL_ERROR_INVALID_OPERATION Invalid operation + * + * @pre Create sound @a pool handler by calling @ref sound_pool_create() + * @post Unload source from pool by calling @ref sound_pool_unload_source() + * + * @see sound_pool_create() + * @see sound_pool_destroy() + * @see sound_pool_unload_source() + */ +int sound_pool_load_source_from_file(sound_pool_h pool, const char *file_name, + const char *tag); + +/** + * @brief Unloads source from @a pool. + * @details Cleans memory. It is synchronous operation. + * @remarks The usage of @a tag name that was associated with unloaded source + * has no effect. It can be reused as well. + * + * @since_tizen 3.0 + * @param [in] pool The handle to the sound pool + * @param [in] tag Unique string that identifies source + * @return @c 0 on success, otherwise a negative error value + * @retval #SOUND_POOL_ERROR_INVALID_PARAMETER + * Invalid parameter (@a pool is NULL or corrupted, @a tag is NULL) + * @retval #SOUND_POOL_ERROR_KEY_NOT_AVAILABLE No sources tagged by @a tag exist + * in pool + * + * @pre Create sound @a pool handler by calling @ref sound_pool_create() + * @pre Load source to pool by calling @ref sound_pool_load_source_from_file() + * + * @see sound_pool_create() + * @see sound_pool_load_source_from_file() + */ +int sound_pool_unload_source(sound_pool_h pool, const char *tag); + +/** + * @brief Gets current @a state of @a pool. + * + * @since_tizen 3.0 + * @param [in] pool The handle to the sound pool + * @param [out] state Current state of @a pool + * @return @c 0 on success, otherwise a negative error value + * @retval #SOUND_POOL_ERROR_INVALID_PARAMETER + * Invalid parameter (@a pool is NULL or corrupted, @a tag is NULL) + * @retval #SOUND_POOL_ERROR_KEY_NOT_AVAILABLE No sources tagged by @a tag exist + * in pool + * + * @pre Create sound @a pool handler by calling @ref sound_pool_create() + * + * @see sound_pool_create() + * @see sound_pool_state_e + */ +int sound_pool_get_state(sound_pool_h pool, + sound_pool_state_e *state); + +/** + * @brief Changes current @a state of @a pool to SOUND_POOL_STATE_ACTIVE. + * + * @since_tizen 3.0 + * @param [in] pool The handle to the sound pool + * @return @c 0 on success, otherwise a negative error value + * @retval #SOUND_POOL_ERROR_INVALID_PARAMETER Invalid parameter + * (@a pool is NULL or corrupted) + * @retval #SOUND_POOL_ERROR_INVALID_OPERATION Invalid operation or sound pool + * is already in @c SOUND_POOL_STATE_ACTIVE state + * + * @pre Create sound @a pool handler by calling @ref sound_pool_create() + * + * @see sound_pool_create() + * @see sound_pool_get_state() + * @see sound_pool_deactivate() + * @see sound_pool_state_e + */ +int sound_pool_activate(sound_pool_h pool); + +/** + * @brief Changes current @a state of @a pool to SOUND_POOL_STATE_INACTIVE. + * + * @since_tizen 3.0 + * @param [in] pool The handle to the sound pool + * @return @c 0 on success, otherwise a negative error value + * @retval #SOUND_POOL_ERROR_INVALID_PARAMETER Invalid parameter + * (@a pool is NULL or corrupted) + * @retval #SOUND_POOL_ERROR_INVALID_OPERATION Invalid operation or sound pool + * is already in @c SOUND_POOL_STATE_INACTIVE state + * + * @pre Create sound @a pool handler by calling @ref sound_pool_create() + * @pre @a pool has to be in SOUND_POOL_STATE_ACTIVE state + * + * @see sound_pool_create() + * @see sound_pool_get_state() + * @see sound_pool_activate() + * @see sound_pool_state_e + */ +int sound_pool_deactivate(sound_pool_h pool); + +/** + * @brief Sets callback for handling sound @a pool state change. + * + * @since_tizen 3.0 + * @param [in] pool The handle to the sound pool + * @param [in] callback The callback that will be called after pool state + * will be changed. @a callback will be called + * synchronously + * @param [in] data The user data to be passed to the @a callback + * @return @c 0 on success, otherwise a negative error value + * @retval #SOUND_POOL_ERROR_INVALID_PARAMETER Invalid parameter + * (@a pool is NULL or corrupted, or @a callback is NULL) + * + * @pre Create sound @a pool handler by calling @ref sound_pool_create() + * @post Use @ref sound_pool_unset_state_change_callback() function to unset the + * @a callback + * + * @see sound_pool_create() + * @see sound_pool_pool_state_change_cb + */ +int sound_pool_set_state_change_callback(sound_pool_h pool, + sound_pool_state_change_cb callback, void *user_data); + +/** + * @brief Unsets callback for handling sound @a pool state change. + * + * @since_tizen 3.0 + * @param [in] pool The handle to the pool + * @return @c 0 on success, otherwise a negative error value + * @retval #SOUND_POOL_ERROR_INVALID_PARAMETER Invalid parameter + * (@a pool is NULL or corrupted) + * + * @pre Create sound @a pool handler by calling @ref sound_pool_create() + * @pre Set state change callback by calling @ref sound_pool_set_state_change_callback() + * + * @see sound_pool_create() + * @see sound_pool_set_state_change_callback() + */ +int sound_pool_unset_state_change_callback(sound_pool_h pool); + +/** + * @brief Plays source by @a tag. + * @details Creates stream with @a id that can be used to change parameters and + * get additional information. + * Sets stream state to SOUND_POOL_STREAM_STATE_PLAYING + * @remarks In case maximum active streams number after calling + * @ref sound_pool_stream_play() was exceeded the stream + * with lowest @a priority will be stopped. + * Resultant stream volume will depend on global pool volume. + * + * @since_tizen 3.0 + * @param [in] pool The handle to the sound pool + * @param [in] tag Unique string that identifies source + * @param [in] loop Number of times stream will be repeated + * (pass 0 if stream should be repeated continuously) + * @param [in] volume Stream volume in 0.0~1.0 range + * @param [in] priority Stream priority (0 = lowest priority) + * @param [in] callback The callback that will be called after stream state + * will be changed, or NULL if this callback call + * isn't needed. If @a callback is set, then it will + * be called asynchronously + * @param [in] user_data The user data to be passed to the @a callback + * @param [out] id Unique stream identifier that can be used to + * change parameters and get additional information + * @return @c 0 on success, otherwise a negative error value + * @retval #SOUND_POOL_ERROR_INVALID_PARAMETER Invalid parameter + * (@a pool is NULL or corrupted, @a tag is NULL, @a volume is out of + * 0.0~1.0 range, or @a id is NULL) + * @retval #SOUND_POOL_ERROR_KEY_NOT_AVAILABLE No sources tagged by @a tag exist + * in pool + * @retval #SOUND_POOL_ERROR_OUT_OF_MEMORY Not enough memory to allocate new + * sound stream + * @retval #SOUND_POOL_ERROR_INVALID_OPERATION Invalid operation + * + * @pre Create sound pool handler by calling @ref sound_pool_create() + * @pre Load source to @a pool by calling @ref sound_pool_load_source_from_file() + * @post When playback is finished normally (i.e. @ref sound_pool_stop_stream() + * will be not used for stream termination) state will be changed to + * SOUND_POOL_STREAM_STATE_FINISHED and memory will be cleared from the + * stream allocated resources automatically + * + * @see sound_pool_create() + * @see sound_pool_load_source_from_file() + * @see sound_pool_set_volume + * @see sound_pool_get_volume + */ +int sound_pool_stream_play(sound_pool_h pool, const char *tag, unsigned loop, + float volume, unsigned priority, + sound_pool_stream_state_change_cb callback, void *user_data, + unsigned *id); + +/** + * @brief Pauses stream by @a id. + * @details Sets stream state to SOUND_POOL_STREAM_STATE_PAUSED. + * @remarks Stream state has to be SOUND_POOL_STATE_PLAYING + * + * @since_tizen 3.0 + * @param [in] pool The handle to the sound pool + * @param [in] id Unique stream identifier + * @return @c 0 on success, otherwise a negative error value + * @retval #SOUND_POOL_ERROR_INVALID_PARAMETER Invalid parameter + * (@a pool is NULL or corrupted) + * @retval #SOUND_POOL_ERROR_KEY_NOT_AVAILABLE No streams identified by @a id + * exist in pool + * @retval #SOUND_POOL_ERROR_INVALID_OPERATION Invalid operation or stream is in + * the state which is not allowed for pause operation + * + * @pre Create sound @a pool handler by calling @ref sound_pool_create() + * @pre Load source to @a pool by calling @ref sound_pool_load_source_from_file() + * @pre Start stream playback by calling @ref sound_pool_stream_play() + * + * @see sound_pool_create() + * @see sound_pool_load_source_from_file() + * @see sound_pool_stream_play() + */ +int sound_pool_stream_pause(sound_pool_h pool, unsigned id); + +/** + * @brief Resumes stream by @a id. + * @details Sets stream state to SOUND_POOL_STREAM_STATE_PLAYING. + * @remarks Stream state has to be SOUND_POOL_STATE_PAUSED + * + * @since_tizen 3.0 + * @param [in] pool The handle to the sound pool + * @param [in] id Unique stream identifier + * @return @c 0 on success, otherwise a negative error value + * @retval #SOUND_POOL_ERROR_INVALID_PARAMETER Invalid parameter + * (@a pool is NULL or corrupted) + * @retval #SOUND_POOL_ERROR_KEY_NOT_AVAILABLE No streams identified by @a id + * exist in pool + * @retval #SOUND_POOL_ERROR_INVALID_OPERATION Invalid operation or stream is in + * the state which is not allowed for resume operation + * + * @pre Create sound @a pool handler by calling @ref sound_pool_create() + * @pre Load source to @a pool by calling @ref sound_pool_load_source_from_file() + * @pre Start stream playback by calling @ref sound_pool_stream_play() + * @pre Pause stream playback by calling @ref sound_pool_stream_pause() + * + * @see sound_pool_create() + * @see sound_pool_load_source_from_file() + * @see sound_pool_stream_play() + * @see sound_pool_stream_pause() + */ +int sound_pool_stream_resume(sound_pool_h pool, unsigned id); + +/** + * @brief Stops stream by @a id. + * @details Sets stream state to SOUND_POOL_STREAM_STATE_STOPPED. + * After stream was stopped it can not be resumed and @a id value + * becomes invalid. Moreover, stream will never gets + * @c SOUND_POOL_STREAM_STATE_FINISHED state as it will be terminated + * after this function call. + * + * @since_tizen 3.0 + * @param [in] pool The handle to the sound pool + * @param [in] id Unique stream identifier + * @return @c 0 on success, otherwise a negative error value + * @retval #SOUND_POOL_ERROR_INVALID_PARAMETER Invalid parameter + * (@a pool is NULL or corrupted) + * @retval #SOUND_POOL_ERROR_KEY_NOT_AVAILABLE No streams identified by @a id + * exist in pool + * @retval #SOUND_POOL_ERROR_INVALID_OPERATION Invalid operation or stream is in + * the state which is not allowed for stop operation + * + * @pre Create sound pool handler by calling @ref sound_pool_create() + * @pre Load source to @a pool by calling @ref sound_pool_load_source_from_file() + * @pre Start stream playback by calling @ref sound_pool_stream_play() + * + * @see sound_pool_create() + * @see sound_pool_load_source_from_file() + * @see sound_pool_stream_play() + */ +int sound_pool_stream_stop(sound_pool_h pool, unsigned id); + +/** + * @brief Sets pool global volume parameter. + * @details Volume of all streams related to @a pool will be scaled + * in accordance to global pool volume parameter + * (i.e. [stream real volume] = [global volume] * [stream volume], + * where [stream volume] is the volume parameter of arbitrary stream). + * + * @since_tizen 3.0 + * @param [in] pool The handle to the sound pool + * @param [in] volume Pool global volume in 0.0~1.0 range + * @return @c 0 on success, otherwise a negative error value + * @retval #SOUND_POOL_ERROR_INVALID_PARAMETER Invalid parameter + * (@a pool is NULL or corrupted, or @a volume isn't in 0.0~1.0 range) + * @retval #SOUND_POOL_ERROR_INVALID_OPERATION Invalid operation + * + * @pre Create sound @a pool handler by calling @ref sound_pool_create() + * + * @see sound_pool_create() + */ +int sound_pool_set_volume(sound_pool_h pool, float volume); + +/** + * @brief Gets pool global volume parameter. + * + * @since_tizen 3.0 + * @param [in] pool The handle to the sound pool + * @param [out] volume Pool global volume in 0.0~1.0 range + * @return @c 0 on success, otherwise a negative error value + * @retval #SOUND_POOL_ERROR_INVALID_PARAMETER Invalid parameter + * (@a pool is NULL or corrupted, or @a volume is NULL) + * @retval #SOUND_POOL_ERROR_INVALID_OPERATION Invalid operation + * + * @pre Create sound @a pool handler by calling @ref sound_pool_create() + * + * @see sound_pool_create() + */ +int sound_pool_get_volume(sound_pool_h pool, float *volume); + +/** + * @brief Gets current @a state of stream by @a id. + * + * @since_tizen 3.0 + * @param [in] pool The handle to the sound pool + * @param [in] id Unique stream identifier + * @param [out] state Current state of stream + * @return @c 0 on success, otherwise a negative error value + * @retval #SOUND_POOL_ERROR_INVALID_PARAMETER Invalid parameter + * (@a pool is NULL or corrupted, or @a state is NULL) + * @retval #SOUND_POOL_ERROR_KEY_NOT_AVAILABLE No streams identified by @a id + * exist in pool + * @retval #SOUND_POOL_ERROR_INVALID_OPERATION Invalid operation + * + * @pre Create sound pool handler by calling @ref sound_pool_create() + * @pre Load source to @a pool by calling @ref sound_pool_load_source_from_file() + * @pre Start stream playback by calling @ref sound_pool_stream_play() + * + * @see sound_pool_create() + * @see sound_pool_load_source_from_file() + * @see sound_pool_stream_play() + * @see sound_pool_stream_state_e + */ +int sound_pool_stream_get_state(sound_pool_h pool, unsigned id, + sound_pool_stream_state_e *state); + +/** + * @brief Sets stream @a loop parameter by stream @a id. + * + * @since_tizen 3.0 + * @param [in] pool The handle to the sound pool + * @param [in] id Unique stream identifier + * @param [in] loop Number of times stream will be repeated + * (pass 0 if stream should be repeated continuously) + * @return @c 0 on success, otherwise a negative error value + * @retval #SOUND_POOL_ERROR_INVALID_PARAMETER Invalid parameter + * (@a pool is NULL or corrupted) + * @retval #SOUND_POOL_ERROR_KEY_NOT_AVAILABLE No streams identified by @a id + * exist in pool + * @retval #SOUND_POOL_ERROR_INVALID_OPERATION Invalid operation + * + * @pre Create sound @a pool handler by calling @ref sound_pool_create() + * @pre Load source to @a pool by calling @ref sound_pool_load_source_from_file() + * @pre Start stream playback by calling @ref sound_pool_stream_play() + * + * @see sound_pool_create() + * @see sound_pool_load_source_from_file() + * @see sound_pool_stream_play() + */ +int sound_pool_stream_set_loop(sound_pool_h pool, unsigned id, unsigned loop); + +/** + * @brief Gets stream @a loop parameter by stream @a id. + * + * @since_tizen 3.0 + * @param [in] pool The handle to the sound pool + * @param [in] id Unique stream identifier + * @param [out] loop Number of times stream will be repeated before + * finishing (getting state SOUND_POOL_STREAM_STATE_FINISHED) + * and releasing of the memory and resources + * @return @c 0 on success, otherwise a negative error value + * @retval #SOUND_POOL_ERROR_INVALID_PARAMETER Invalid parameter + * (@a pool is NULL or corrupted, or @a loop is NULL) + * @retval #SOUND_POOL_ERROR_KEY_NOT_AVAILABLE No streams identified by @a id + * exist in pool + * @retval #SOUND_POOL_ERROR_INVALID_OPERATION Invalid operation + * + * @pre Create sound @a pool handler by calling @ref sound_pool_create() + * @pre Load source to @a pool by calling @ref sound_pool_load_source_from_file() + * @pre Start source playback by calling @ref sound_pool_stream_play() + * + * @see sound_pool_create() + * @see sound_pool_load_source_from_file() + * @see sound_pool_stream_play() + */ +int sound_pool_stream_get_loop(sound_pool_h pool, unsigned id, unsigned *loop); + +/** + * @brief Sets stream volume parameters by stream @a id. + * @remarks Resultant stream volume will depend on global pool volume. + * + * @since_tizen 3.0 + * @param [in] pool The handle to the sound pool + * @param [in] id Unique stream identifier + * @param [in] volume Stream volume in 0.0~1.0 range + * @return @c 0 on success, otherwise a negative error value + * @retval #SOUND_POOL_ERROR_INVALID_PARAMETER Invalid parameter + * (@a pool is NULL or corrupted, or @a volume isn't in 0.0~1.0 range) + * @retval #SOUND_POOL_ERROR_KEY_NOT_AVAILABLE No streams identified by @a id + * exist in pool + * @retval #SOUND_POOL_ERROR_INVALID_OPERATION Invalid operation + * + * @pre Create sound @a pool handler by calling @ref sound_pool_create() + * @pre Load source to @a pool by calling @ref sound_pool_load_source_from_file() + * @pre Start stream playback by calling @ref sound_pool_stream_play() + * + * @see sound_pool_create() + * @see sound_pool_load_source_from_file() + * @see sound_pool_stream_play() + * @see sound_pool_set_volume + * @see sound_pool_get_volume + */ +int sound_pool_stream_set_volume(sound_pool_h pool, unsigned id, + float volume); + +/** + * @brief Gets stream volume parameters by stream @a id. + * + * @since_tizen 3.0 + * @param [in] pool The handle to the sound pool + * @param [in] id Unique stream identifier + * @param [out] volume Stream volume in 0.0~1.0 range + * @return @c 0 on success, otherwise a negative error value + * @retval #SOUND_POOL_ERROR_INVALID_PARAMETER Invalid parameter + * (@a pool is NULL or corrupted, or @a volume is NULL) + * @retval #SOUND_POOL_ERROR_KEY_NOT_AVAILABLE No streams identified by @a id + * exist in pool + * @retval #SOUND_POOL_ERROR_INVALID_OPERATION Invalid operation + * + * @pre Create sound @a pool handler by calling @ref sound_pool_create() + * @pre Load source to @a pool by calling @ref sound_pool_load_source_from_file() + * @pre Start stream playback by calling @ref sound_pool_stream_play() + * + * @see sound_pool_create() + * @see sound_pool_load_source_from_file() + * @see sound_pool_stream_play() + */ +int sound_pool_stream_get_volume(sound_pool_h pool, unsigned id, + float *volume); + +/** + * @brief Sets stream priority parameter by stream @a id. + * + * @since_tizen 3.0 + * @param [in] pool The handle to the sound pool + * @param [in] id Unique stream identifier + * @param [in] priority Stream priority (0 = lowest priority) + * @return @c 0 on success, otherwise a negative error value + * @retval #SOUND_POOL_ERROR_INVALID_PARAMETER Invalid parameter + * (@a pool is NULL or corrupted) + * @retval #SOUND_POOL_ERROR_KEY_NOT_AVAILABLE No streams identified by @a id + * exist in pool + * @retval #SOUND_POOL_ERROR_INVALID_OPERATION Invalid operation + * + * @pre Create sound @a pool handler by calling @ref sound_pool_create() + * @pre Load source to @a pool by calling @ref sound_pool_load_source_from_file() + * @pre Start stream playback by calling @ref sound_pool_stream_play() + * + * @see sound_pool_create() + * @see sound_pool_load_source_from_file() + * @see sound_pool_stream_play() + */ +int sound_pool_stream_set_priority(sound_pool_h pool, unsigned id, + unsigned priority); + +/** + * @brief Gets stream priority parameter by stream @a id. + * + * @since_tizen 3.0 + * @param [in] pool The handle to the sound pool + * @param [in] id Unique stream identifier + * @param [in] priority Stream priority (0 = lowest priority) + * @return @c 0 on success, otherwise a negative error value + * @retval #SOUND_POOL_ERROR_INVALID_PARAMETER Invalid parameter + * (@a pool is NULL or corrupted, or @a priority is NULL) + * @retval #SOUND_POOL_ERROR_KEY_NOT_AVAILABLE No streams identified by @a id + * exist in pool + * @retval #SOUND_POOL_ERROR_INVALID_OPERATION Invalid operation + * + * @pre Create sound @a pool handler by calling @ref sound_pool_create() + * @pre Load source to @a pool by calling @ref sound_pool_load_source_from_file() + * @pre Start stream playback by calling @ref sound_pool_stream_play() + * + * @see sound_pool_create() + * @see sound_pool_load_source_from_file() + * @see sound_pool_stream_play() + */ +int sound_pool_stream_get_priority(sound_pool_h pool, unsigned id, + unsigned *priority); + +/** + * @brief Sets callback for handling stream state change events. + * + * @since_tizen 3.0 + * @param [in] pool The handle to the sound pool + * @param [in] id Unique stream identifier + * @param [in] callback The callback that will be called after stream state + * will be changed. @a callback will be called + * asynchronously + * @param [in] data The user data to be passed to the @a callback + * @return @c 0 on success, otherwise a negative error value + * @retval #SOUND_POOL_ERROR_INVALID_PARAMETER Invalid parameter + * (@a pool is NULL or corrupted, or @a callback is NULL) + * @retval #SOUND_POOL_ERROR_KEY_NOT_AVAILABLE No streams identified by @a id + * exist in pool + * @retval #SOUND_POOL_ERROR_INVALID_OPERATION Invalid operation + * + * @pre Create sound pool handler by calling @ref sound_pool_create() + * @pre Load source to pool by calling @ref sound_pool_load_source_from_file() + * @pre Start source playback by calling @ref sound_pool_stream_play() + * @post Use @ref sound_pool_stream_unset_state_change_callback() function to + * unset the @a callback + * + * @see sound_pool_create() + * @see sound_pool_load_source_from_file() + * @see sound_pool_stream_play() + * @see sound_pool_stream_state_change_cb + */ +int sound_pool_stream_set_state_change_callback(sound_pool_h pool, unsigned id, + sound_pool_stream_state_change_cb callback, void *user_data); + +/** + * @brief Unsets callback for handling stream state change events. + * + * @since_tizen 3.0 + * @param [in] pool The handle to the sound pool + * @param [in] id Unique stream identifier + * @return @c 0 on success, otherwise a negative error value + * @retval #SOUND_POOL_ERROR_INVALID_PARAMETER Invalid parameter + * (@a pool is NULL or corrupted) + * @retval #SOUND_POOL_ERROR_KEY_NOT_AVAILABLE No streams identified by @a id + * exist in pool + * + * @pre Create sound @a pool handler by calling @ref sound_pool_create() + * @pre Load source to @a pool by calling @ref sound_pool_load_source_from_file() + * @pre Start stream playback by calling @ref sound_pool_stream_play() + * @pre Set stream state change callback by calling @ref sound_pool_stream_set_state_change_callback() + * + * @see sound_pool_create() + * @see sound_pool_load_source_from_file() + * @see sound_pool_stream_play() + * @see sound_pool_stream_state_change_cb + */ +int sound_pool_stream_unset_state_change_callback(sound_pool_h pool, + unsigned id); + +/** + * @} + */ + + #ifdef __cplusplus } #endif diff --git a/include/sound_pool_type.h b/include/sound_pool_type.h new file mode 100644 index 0000000..d2cd0d2 --- /dev/null +++ b/include/sound_pool_type.h @@ -0,0 +1,106 @@ +/* + * 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. + */ + +#ifndef __TIZEN_SOUND_POOL_TYPE_H__ +#define __TIZEN_SOUND_POOL_TYPE_H__ + +#include "tizen.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @file sound_pool_type.h + * @brief This file contains handles, enumerations and callbacks types + * definitions required by Tizen SoundPool API. + */ + +/** + * @addtogroup CAPI_SOUND_POOL_MODULE + * @{ + */ + +/** + * @brief Enumeration for Tizen Sound Pool error. + * + * @since_tizen 3.0 + */ +typedef enum +{ + SOUND_POOL_ERROR_NONE + = TIZEN_ERROR_NONE, /**< Successful */ + SOUND_POOL_ERROR_NOT_SUPPORTED + = TIZEN_ERROR_NOT_SUPPORTED, /**< Not supported */ + SOUND_POOL_ERROR_MSG_TOO_LONG + = TIZEN_ERROR_MSG_TOO_LONG, /**< Message too long */ + SOUND_POOL_ERROR_NO_DATA + = TIZEN_ERROR_NO_DATA, /**< No data */ + SOUND_POOL_ERROR_KEY_NOT_AVAILABLE + = TIZEN_ERROR_KEY_NOT_AVAILABLE, /**< Key not available */ + SOUND_POOL_ERROR_OUT_OF_MEMORY + = TIZEN_ERROR_OUT_OF_MEMORY, /**< Out of memory */ + SOUND_POOL_ERROR_INVALID_PARAMETER + = TIZEN_ERROR_INVALID_PARAMETER, /**< Invalid parameter */ + SOUND_POOL_ERROR_INVALID_OPERATION + = TIZEN_ERROR_INVALID_OPERATION, /**< Invalid operation */ + SOUND_POOL_ERROR_PERMISSION_DENIED + = TIZEN_ERROR_NOT_PERMITTED, /**< Not permitted */ + SOUND_POOL_ERROR_NO_SUCH_FILE + = TIZEN_ERROR_NO_SUCH_FILE, /**< File not found */ + +} sound_pool_error_e; + +/** + * @brief Sound pool handle type. + * + * @since_tizen 3.0 + */ +typedef void *sound_pool_h; + +/** + * @brief Enumeration of sound pool stream state. + * + * @since_tizen 3.0 + */ +typedef enum { + SOUND_POOL_STREAM_STATE_NONE, /**< Stream state isn't determined */ + SOUND_POOL_STREAM_STATE_PLAYING, /**< Stream state is playing */ + SOUND_POOL_STREAM_STATE_PAUSED, /**< Stream state is paused */ + SOUND_POOL_STREAM_STATE_STOPPED, /**< Stream state is stopped */ + SOUND_POOL_STREAM_STATE_FINISHED, /**< Stream state is finished */ + SOUND_POOL_STREAM_STATE_SUSPENDED /**< Stream state is suspended */ +} sound_pool_stream_state_e; + +/** + * @brief Enumeration of sound pool state. + * + * @since_tizen 3.0 + */ +typedef enum { + SOUND_POOL_STATE_ACTIVE, /**< Sound pool active state: streams can be played */ + SOUND_POOL_STATE_INACTIVE /**< Sound pool inactive state: streams can't be played */ +} sound_pool_state_e; + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __TIZEN_SOUND_POOL_TYPE_H__ */ -- 2.7.4 From 015e69523ec3fba82b4984ca1ec5b6cf76a30243 Mon Sep 17 00:00:00 2001 From: "o.danchenko" Date: Tue, 14 Jun 2016 23:02:40 +0300 Subject: [PATCH 04/14] SoundPool implementation has been added. Change-Id: I232a8cc5af30a4b14135d5b75c8b1debd7b71f3e Signed-off-by: o.danchenko --- CMakeLists.txt | 2 +- include/internal/priority.h | 60 ++++ include/internal/soundpool.h | 85 ++++++ include/internal/source.h | 59 ++++ include/internal/stream.h | 93 ++++++ include/internal/stream_cb_manager.h | 64 +++++ include/sound_pool.h | 50 ++-- include/sound_pool_private.h | 128 +++++++++ packaging/sound-pool.spec | 4 +- src/priority.c | 189 ++++++++++++ src/sound_pool.c | 458 +++++++++++++++++++++++++++++ src/soundpool.c | 326 +++++++++++++++++++++ src/source.c | 218 ++++++++++++++ src/stream.c | 540 +++++++++++++++++++++++++++++++++++ src/stream_cb_manager.c | 218 ++++++++++++++ 15 files changed, 2466 insertions(+), 28 deletions(-) create mode 100644 include/internal/priority.h create mode 100644 include/internal/soundpool.h create mode 100644 include/internal/source.h create mode 100644 include/internal/stream.h create mode 100644 include/internal/stream_cb_manager.h create mode 100644 include/sound_pool_private.h create mode 100644 src/priority.c create mode 100644 src/soundpool.c create mode 100644 src/source.c create mode 100644 src/stream.c create mode 100644 src/stream_cb_manager.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 12706f9..d34c3c1 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -51,7 +51,7 @@ INSTALL(TARGETS ${fw_name} DESTINATION ${LIB_INSTALL_DIR}) INSTALL( DIRECTORY ${INC_DIR}/ DESTINATION ${INC_DIR}/media FILES_MATCHING - PATTERN "mm_soundpool_private.h" EXCLUDE + PATTERN "sound_pool_private.h" EXCLUDE PATTERN "${INC_DIR}/*.h" ) diff --git a/include/internal/priority.h b/include/internal/priority.h new file mode 100644 index 0000000..caf767b --- /dev/null +++ b/include/internal/priority.h @@ -0,0 +1,60 @@ +/* + * 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. + */ + +#ifndef __TIZEN_SOUNDPOOL_INTERNAL_PRIORITY_H_ +#define __TIZEN_SOUNDPOOL_INTERNAL_PRIORITY_H_ + +#include "sound_pool_private.h" +#include "internal/stream.h" + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Pool Priority Manager type. + * + * @since_tizen 3.0 + */ +struct stream_priority_manager_s { + sound_pool_t *pool; + GList *priority_queue; +}; + +sound_pool_error_e _sound_stream_priority_create(sound_pool_t *pool, + stream_priority_manager_t **mgr); + +sound_pool_error_e _sound_stream_priority_destroy( + stream_priority_manager_t *mgr); + +sound_pool_error_e _sound_stream_priority_add_stream( + stream_priority_manager_t *mgr, sound_stream_t *stream); + +sound_pool_error_e _sound_stream_priority_remove_stream( + stream_priority_manager_t *mgr, sound_stream_t *stream); + +sound_pool_error_e _sound_stream_priority_check(stream_priority_manager_t *mgr, + sound_stream_t *stream, gboolean *out); + +void _sound_stream_priority_update_playback(stream_priority_manager_t *mgr); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __TIZEN_SOUNDPOOL_INTERNAL_PRIORITY_H_ */ diff --git a/include/internal/soundpool.h b/include/internal/soundpool.h new file mode 100644 index 0000000..9b015d3 --- /dev/null +++ b/include/internal/soundpool.h @@ -0,0 +1,85 @@ +/* + * 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. + */ + +#ifndef __TIZEN_SOUNDPOOL_INTERNAL_SOUNDPOOL_H__ +#define __TIZEN_SOUNDPOOL_INTERNAL_SOUNDPOOL_H__ + +#include "sound_pool_type.h" +#include "sound_pool_private.h" + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct stream_cb_manager_s stream_cb_manager_t; +typedef struct stream_priority_manager_s stream_priority_manager_t; + +/** + * @brief Sound Pool pool type. + * + * @since_tizen 3.0 + */ +typedef struct sound_pool_s { + ALCcontext *al_context; + float volume; + + GHashTable *sources; + GHashTable *streams; + + guint max_streams; + guint max_stream_index; + sound_pool_state_e state; + + struct { + sound_pool_state_change_cb callback; + void *user_data; + } state_cb_info; + + stream_cb_manager_t *cbmgr; + stream_priority_manager_t *mgr_priority; +} sound_pool_t; + +/* Max amount of sound pools which could be created. */ +#define SOUND_POOL_MAX_POOLS_AMOUNT 32U + +sound_pool_error_e _sound_pool_create(size_t max_streams, sound_pool_t **pool); + +sound_pool_error_e _sound_pool_destroy(sound_pool_t *pool); + +sound_pool_error_e _sound_pool_activate(sound_pool_t *pool); + +sound_pool_error_e _sound_pool_deactivate(sound_pool_t *pool); + +sound_pool_error_e _sound_pool_get_state(sound_pool_t *pool, sound_pool_state_e *state); + +sound_pool_error_e _sound_pool_set_volume(sound_pool_t *pool, float volume); + +sound_pool_error_e _sound_pool_get_volume(sound_pool_t *pool, float *volume); + +sound_pool_error_e _sound_pool_set_callback(sound_pool_t *pool, + sound_pool_state_change_cb callback, void *data); + +sound_pool_error_e _sound_pool_unset_callback(sound_pool_t *pool); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __TIZEN_SOUNDPOOL_INTERNAL_SOUNDPOOL_H__ */ diff --git a/include/internal/source.h b/include/internal/source.h new file mode 100644 index 0000000..58117f9 --- /dev/null +++ b/include/internal/source.h @@ -0,0 +1,59 @@ +/* + * 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. + */ + +#ifndef __TIZEN_SOUNDPOOL_INTERNAL_SOURCE_H__ +#define __TIZEN_SOUNDPOOL_INTERNAL_SOURCE_H__ + +#include "sound_pool_private.h" +#include "internal/soundpool.h" + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Sound Pool source type. + * + * @since_tizen 3.0 + */ +typedef struct sound_source_s { + sound_pool_t *parent_pool; + gchar *tag_name; + ALuint al_buffer; +} sound_source_t; + +/* Max length of the tag can be used for source identification. */ +#define MAX_TAG_LEN 255U + +sound_pool_error_e _sound_source_create(sound_pool_t *pool, const char *tag, + sound_source_t **src); + +sound_pool_error_e _sound_source_destroy(sound_source_t *src); + +sound_pool_error_e _sound_source_load_from_file(sound_source_t *src, const char *fname); + +sound_pool_error_e _sound_pool_get_source_by_tag(sound_pool_t *pool, const char *tag, + sound_source_t **src); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __TIZEN_SOUNDPOOL_INTERNAL_SOURCE_H__ */ diff --git a/include/internal/stream.h b/include/internal/stream.h new file mode 100644 index 0000000..9d67b34 --- /dev/null +++ b/include/internal/stream.h @@ -0,0 +1,93 @@ +/* + * 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. + */ + +#ifndef __TIZEN_SOUNDPOOL_INTERNAL_STREAM_H__ +#define __TIZEN_SOUNDPOOL_INTERNAL_STREAM_H__ + + +#include "sound_pool_private.h" +#include "internal/source.h" + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Sound Pool stream type. + * + * @since_tizen 3.0 + */ +typedef struct sound_stream_s { + unsigned id; + sound_source_t *parent_source; + + unsigned priority; + unsigned loop; + float volume; + + sound_pool_stream_state_e state; + sound_pool_stream_state_e state_previous; + gboolean stopped; + + struct { + sound_pool_stream_state_change_cb callback; + void *user_data; + } state_cb_info; + + ALuint al_source; +} sound_stream_t; + +sound_pool_error_e _sound_stream_create(sound_source_t *src, sound_stream_t **stream); + +sound_pool_error_e _sound_stream_destroy(sound_stream_t *src); + +sound_pool_error_e _sound_stream_play(sound_stream_t *stream); + +sound_pool_error_e _sound_stream_pause(sound_stream_t *stream); + +sound_pool_error_e _sound_stream_resume(sound_stream_t *stream); + +sound_pool_error_e _sound_stream_stop(sound_stream_t *stream); + +sound_pool_error_e _sound_stream_set_loop(sound_stream_t *stream, unsigned loop); +sound_pool_error_e _sound_stream_get_loop(sound_stream_t *stream, unsigned *loop); + +sound_pool_error_e _sound_stream_set_volume(sound_stream_t *stream, float volume); +sound_pool_error_e _sound_stream_get_volume(sound_stream_t *stream, float *volume); + +sound_pool_error_e _sound_stream_set_priority(sound_stream_t *stream, unsigned rank); +sound_pool_error_e _sound_stream_get_priority(sound_stream_t *stream, unsigned *rank); + +sound_pool_error_e _sound_stream_get_state(sound_stream_t *stream, + sound_pool_stream_state_e *state); + +sound_pool_error_e _sound_stream_set_callback(sound_stream_t *stream, + sound_pool_stream_state_change_cb callback, void *data); + +sound_pool_error_e _sound_stream_unset_callback(sound_stream_t *stream); + +sound_pool_error_e _sound_pool_get_stream_by_id(sound_pool_t *pool, unsigned id, + sound_stream_t **stream); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __TIZEN_SOUNDPOOL_INTERNAL_STREAM_H__ */ diff --git a/include/internal/stream_cb_manager.h b/include/internal/stream_cb_manager.h new file mode 100644 index 0000000..60ef83a --- /dev/null +++ b/include/internal/stream_cb_manager.h @@ -0,0 +1,64 @@ +/* + * 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. + */ + +#ifndef __TIZEN_SOUNDPOOL_INTERNAL_STREAMCBMANAGER_H__ +#define __TIZEN_SOUNDPOOL_INTERNAL_STREAMCBMANAGER_H__ + +#include "internal/stream.h" + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Stream Callback Manager type. + * + * @since_tizen 3.0 + */ +struct stream_cb_manager_s { + sound_pool_t *pool; + GAsyncQueue *isolator_callback_queue; + + pthread_t isolator_thread; + pthread_mutex_t isolator_data_mutex; + pthread_cond_t isolator_data_cond; + gboolean isolator_state_changed; + gboolean isolator_loop_run; +}; + +typedef struct stream_cb_manager_event_data_s { + sound_stream_t *stream; + sound_pool_stream_state_e state; + sound_pool_stream_state_e state_previous; +} stream_cb_manager_event_data_t; + +sound_pool_error_e _stream_cb_manager_create(sound_pool_t *pool, stream_cb_manager_t **cbmgr); + +sound_pool_error_e _stream_cb_manager_destroy(stream_cb_manager_t *cbmgr); + +sound_pool_error_e _stream_cb_manager_register_event(stream_cb_manager_t *cbmgr, + sound_stream_t *stream); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __TIZEN_SOUNDPOOL_INTERNAL_STREAMCBMANAGER_H__ */ diff --git a/include/sound_pool.h b/include/sound_pool.h index 67e9d41..b862f0d 100644 --- a/include/sound_pool.h +++ b/include/sound_pool.h @@ -99,7 +99,7 @@ typedef void (*sound_pool_stream_state_change_cb) (sound_pool_h pool, * @param [out] pool The handle to the pool that will be created * @return @c 0 on success, otherwise a negative error value * @retval #SOUND_POOL_ERROR_INVALID_PARAMETER - * Invalid parameter (@a pool is NULL or @ max_streams is 0) + * Invalid parameter (@a pool is NULL or @a max_streams is 0) * @retval #SOUND_POOL_ERROR_OUT_OF_MEMORY * Not enough memory to create sound pool * @retval #SOUND_POOL_ERROR_INVALID_OPERATION @@ -107,7 +107,7 @@ typedef void (*sound_pool_stream_state_change_cb) (sound_pool_h pool, * * @see sound_pool_destroy() */ -int sound_pool_create(unsigned max_streams, sound_pool_h *pool); +sound_pool_error_e sound_pool_create(unsigned max_streams, sound_pool_h *pool); /** * @brief Destroys sound pool and cleans allocated memory. @@ -123,7 +123,7 @@ int sound_pool_create(unsigned max_streams, sound_pool_h *pool); * * @see sound_pool_create() */ -int sound_pool_destroy(sound_pool_h pool); +sound_pool_error_e sound_pool_destroy(sound_pool_h pool); /** * @brief Loads sound source data from file to pool. @@ -151,7 +151,7 @@ int sound_pool_destroy(sound_pool_h pool); * @see sound_pool_destroy() * @see sound_pool_unload_source() */ -int sound_pool_load_source_from_file(sound_pool_h pool, const char *file_name, +sound_pool_error_e sound_pool_load_source_from_file(sound_pool_h pool, const char *file_name, const char *tag); /** @@ -175,7 +175,7 @@ int sound_pool_load_source_from_file(sound_pool_h pool, const char *file_name, * @see sound_pool_create() * @see sound_pool_load_source_from_file() */ -int sound_pool_unload_source(sound_pool_h pool, const char *tag); +sound_pool_error_e sound_pool_unload_source(sound_pool_h pool, const char *tag); /** * @brief Gets current @a state of @a pool. @@ -194,7 +194,7 @@ int sound_pool_unload_source(sound_pool_h pool, const char *tag); * @see sound_pool_create() * @see sound_pool_state_e */ -int sound_pool_get_state(sound_pool_h pool, +sound_pool_error_e sound_pool_get_state(sound_pool_h pool, sound_pool_state_e *state); /** @@ -215,7 +215,7 @@ int sound_pool_get_state(sound_pool_h pool, * @see sound_pool_deactivate() * @see sound_pool_state_e */ -int sound_pool_activate(sound_pool_h pool); +sound_pool_error_e sound_pool_activate(sound_pool_h pool); /** * @brief Changes current @a state of @a pool to SOUND_POOL_STATE_INACTIVE. @@ -236,7 +236,7 @@ int sound_pool_activate(sound_pool_h pool); * @see sound_pool_activate() * @see sound_pool_state_e */ -int sound_pool_deactivate(sound_pool_h pool); +sound_pool_error_e sound_pool_deactivate(sound_pool_h pool); /** * @brief Sets callback for handling sound @a pool state change. @@ -258,7 +258,7 @@ int sound_pool_deactivate(sound_pool_h pool); * @see sound_pool_create() * @see sound_pool_pool_state_change_cb */ -int sound_pool_set_state_change_callback(sound_pool_h pool, +sound_pool_error_e sound_pool_set_state_change_callback(sound_pool_h pool, sound_pool_state_change_cb callback, void *user_data); /** @@ -276,7 +276,7 @@ int sound_pool_set_state_change_callback(sound_pool_h pool, * @see sound_pool_create() * @see sound_pool_set_state_change_callback() */ -int sound_pool_unset_state_change_callback(sound_pool_h pool); +sound_pool_error_e sound_pool_unset_state_change_callback(sound_pool_h pool); /** * @brief Plays source by @a tag. @@ -324,7 +324,7 @@ int sound_pool_unset_state_change_callback(sound_pool_h pool); * @see sound_pool_set_volume * @see sound_pool_get_volume */ -int sound_pool_stream_play(sound_pool_h pool, const char *tag, unsigned loop, +sound_pool_error_e sound_pool_stream_play(sound_pool_h pool, const char *tag, unsigned loop, float volume, unsigned priority, sound_pool_stream_state_change_cb callback, void *user_data, unsigned *id); @@ -353,7 +353,7 @@ int sound_pool_stream_play(sound_pool_h pool, const char *tag, unsigned loop, * @see sound_pool_load_source_from_file() * @see sound_pool_stream_play() */ -int sound_pool_stream_pause(sound_pool_h pool, unsigned id); +sound_pool_error_e sound_pool_stream_pause(sound_pool_h pool, unsigned id); /** * @brief Resumes stream by @a id. @@ -381,7 +381,7 @@ int sound_pool_stream_pause(sound_pool_h pool, unsigned id); * @see sound_pool_stream_play() * @see sound_pool_stream_pause() */ -int sound_pool_stream_resume(sound_pool_h pool, unsigned id); +sound_pool_error_e sound_pool_stream_resume(sound_pool_h pool, unsigned id); /** * @brief Stops stream by @a id. @@ -410,7 +410,7 @@ int sound_pool_stream_resume(sound_pool_h pool, unsigned id); * @see sound_pool_load_source_from_file() * @see sound_pool_stream_play() */ -int sound_pool_stream_stop(sound_pool_h pool, unsigned id); +sound_pool_error_e sound_pool_stream_stop(sound_pool_h pool, unsigned id); /** * @brief Sets pool global volume parameter. @@ -431,7 +431,7 @@ int sound_pool_stream_stop(sound_pool_h pool, unsigned id); * * @see sound_pool_create() */ -int sound_pool_set_volume(sound_pool_h pool, float volume); +sound_pool_error_e sound_pool_set_volume(sound_pool_h pool, float volume); /** * @brief Gets pool global volume parameter. @@ -448,7 +448,7 @@ int sound_pool_set_volume(sound_pool_h pool, float volume); * * @see sound_pool_create() */ -int sound_pool_get_volume(sound_pool_h pool, float *volume); +sound_pool_error_e sound_pool_get_volume(sound_pool_h pool, float *volume); /** * @brief Gets current @a state of stream by @a id. @@ -473,7 +473,7 @@ int sound_pool_get_volume(sound_pool_h pool, float *volume); * @see sound_pool_stream_play() * @see sound_pool_stream_state_e */ -int sound_pool_stream_get_state(sound_pool_h pool, unsigned id, +sound_pool_error_e sound_pool_stream_get_state(sound_pool_h pool, unsigned id, sound_pool_stream_state_e *state); /** @@ -499,7 +499,7 @@ int sound_pool_stream_get_state(sound_pool_h pool, unsigned id, * @see sound_pool_load_source_from_file() * @see sound_pool_stream_play() */ -int sound_pool_stream_set_loop(sound_pool_h pool, unsigned id, unsigned loop); +sound_pool_error_e sound_pool_stream_set_loop(sound_pool_h pool, unsigned id, unsigned loop); /** * @brief Gets stream @a loop parameter by stream @a id. @@ -525,7 +525,7 @@ int sound_pool_stream_set_loop(sound_pool_h pool, unsigned id, unsigned loop); * @see sound_pool_load_source_from_file() * @see sound_pool_stream_play() */ -int sound_pool_stream_get_loop(sound_pool_h pool, unsigned id, unsigned *loop); +sound_pool_error_e sound_pool_stream_get_loop(sound_pool_h pool, unsigned id, unsigned *loop); /** * @brief Sets stream volume parameters by stream @a id. @@ -552,7 +552,7 @@ int sound_pool_stream_get_loop(sound_pool_h pool, unsigned id, unsigned *loop); * @see sound_pool_set_volume * @see sound_pool_get_volume */ -int sound_pool_stream_set_volume(sound_pool_h pool, unsigned id, +sound_pool_error_e sound_pool_stream_set_volume(sound_pool_h pool, unsigned id, float volume); /** @@ -577,7 +577,7 @@ int sound_pool_stream_set_volume(sound_pool_h pool, unsigned id, * @see sound_pool_load_source_from_file() * @see sound_pool_stream_play() */ -int sound_pool_stream_get_volume(sound_pool_h pool, unsigned id, +sound_pool_error_e sound_pool_stream_get_volume(sound_pool_h pool, unsigned id, float *volume); /** @@ -602,7 +602,7 @@ int sound_pool_stream_get_volume(sound_pool_h pool, unsigned id, * @see sound_pool_load_source_from_file() * @see sound_pool_stream_play() */ -int sound_pool_stream_set_priority(sound_pool_h pool, unsigned id, +sound_pool_error_e sound_pool_stream_set_priority(sound_pool_h pool, unsigned id, unsigned priority); /** @@ -627,7 +627,7 @@ int sound_pool_stream_set_priority(sound_pool_h pool, unsigned id, * @see sound_pool_load_source_from_file() * @see sound_pool_stream_play() */ -int sound_pool_stream_get_priority(sound_pool_h pool, unsigned id, +sound_pool_error_e sound_pool_stream_get_priority(sound_pool_h pool, unsigned id, unsigned *priority); /** @@ -658,7 +658,7 @@ int sound_pool_stream_get_priority(sound_pool_h pool, unsigned id, * @see sound_pool_stream_play() * @see sound_pool_stream_state_change_cb */ -int sound_pool_stream_set_state_change_callback(sound_pool_h pool, unsigned id, +sound_pool_error_e sound_pool_stream_set_state_change_callback(sound_pool_h pool, unsigned id, sound_pool_stream_state_change_cb callback, void *user_data); /** @@ -683,7 +683,7 @@ int sound_pool_stream_set_state_change_callback(sound_pool_h pool, unsigned id, * @see sound_pool_stream_play() * @see sound_pool_stream_state_change_cb */ -int sound_pool_stream_unset_state_change_callback(sound_pool_h pool, +sound_pool_error_e sound_pool_stream_unset_state_change_callback(sound_pool_h pool, unsigned id); /** diff --git a/include/sound_pool_private.h b/include/sound_pool_private.h new file mode 100644 index 0000000..2b3af54 --- /dev/null +++ b/include/sound_pool_private.h @@ -0,0 +1,128 @@ +/* + * 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. + */ + +#ifndef __TIZEN_SOUNDPOOL_PRIVATE_H__ +#define __TIZEN_SOUNDPOOL_PRIVATE_H__ + +#include +#include +#include +#include + +#include "sound_pool.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef LOG_TAG +#undef LOG_TAG +#endif + +#define LOG_TAG "TIZEN_SOUND_POOL" + +#ifdef COLORED_LOG +#define FONT_COLOR_RESET "\033[0m" +#define FONT_COLOR_RED "\033[31m" +#define FONT_COLOR_GREEN "\033[32m" +#define FONT_COLOR_YELLOW "\033[33m" +#define FONT_COLOR_BLUE "\033[34m" +#define FONT_COLOR_PURPLE "\033[35m" +#define FONT_COLOR_CYAN "\033[36m" +#define FONT_COLOR_GRAY "\033[37m" +#else +#define FONT_COLOR_RESET +#define FONT_COLOR_RED +#define FONT_COLOR_GREEN +#define FONT_COLOR_YELLOW +#define FONT_COLOR_BLUE +#define FONT_COLOR_PURPLE +#define FONT_COLOR_CYAN +#define FONT_COLOR_GRAY +#endif + +/** + * @brief Max amount of sound pools which could be created. + * + * @since_tizen 3.0 + */ +#define SOUND_POOL_MAX_POOLS_AMOUNT 32U + +#define SP_DEBUG(fmt, arg...) \ + do { \ + LOGD(FONT_COLOR_RESET""fmt"", ##arg); \ + } while (0) + +#define SP_INFO(fmt, arg...) \ + do { \ + LOGI(FONT_COLOR_GREEN""fmt""FONT_COLOR_RESET, \ + ##arg); \ + } while (0) + +#define SP_ERROR(fmt, arg...) \ + do { \ + LOGE(FONT_COLOR_RED""fmt""FONT_COLOR_RESET, \ + ##arg); \ + } while (0) + +#define SP_DEBUF_FENTER() \ + do { \ + LOGD(FONT_COLOR_YELLOW""FONT_COLOR_RESET); \ + } while (0) + +#define SP_DEBUG_FLEAVE() \ + do { \ + LOGD(FONT_COLOR_PURPLE""FONT_COLOR_RESET); \ + } while (0) + +#define SP_INST_CHECK(expr, ret_code) \ + do { \ + SP_RETVM_IF(NULL == expr, ret_code, #ret_code); \ + } while (0) + +#define SP_RETM_IF(expr, fmt, arg...) \ + do { \ + if (expr) { \ + LOGE(FONT_COLOR_RED""fmt""FONT_COLOR_RESET, \ + ##arg); \ + SP_DEBUG_FLEAVE(); \ + return; \ + } \ + } while (0) + +#define SP_RETVM_IF(expr, val, fmt, arg...) \ + do { \ + if (expr) { \ + LOGE(FONT_COLOR_RED""fmt""FONT_COLOR_RESET, \ + ##arg); \ + SP_DEBUG_FLEAVE(); \ + return(val); \ + } \ + } while (0) + +#define GOTO_FAIL(msg, label) \ + do { \ + SP_ERROR(msg); \ + goto label; \ + } while (0) + +#define SP_SAFE_GFREE(src) { if (src) { g_free(src); src = NULL; } } + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __TIZEN_SOUNDPOOL_PRIVATE_H__ */ diff --git a/packaging/sound-pool.spec b/packaging/sound-pool.spec index 5d3ff1f..0f74e31 100644 --- a/packaging/sound-pool.spec +++ b/packaging/sound-pool.spec @@ -17,7 +17,7 @@ BuildRequires: pkgconfig(freealut) Tizen Sound Pool Module allowing sounds playing for audio resources. %package devel -Summary: Tizen Sound Pool Module allowing sounds playing for audio resources (Development). +Summary: Tizen Module allowing sounds playing for audio resources (Development) Group: Multimedia/Framework Requires: %{name} = %{version}-%{release} @@ -31,7 +31,7 @@ cp %{SOURCE1001} . %build export CFLAGS="$CFLAGS -fprofile-arcs -ftest-coverage" export CXXFLAGS="$CXXFLAGS -fprofile-arcs -ftest-coverage" -export LDLAGS="$LDLAGS -lgcov" +export LDFLAGS="$LDFLAGS -lgcov" MAJORVER=`echo %{version} | awk 'BEGIN {FS="."}{print $1}'` %cmake . -DCMAKE_INSTALL_PREFIX=%{_prefix} -DFULLVER=%{version} -DMAJORVER=${MAJORVER} diff --git a/src/priority.c b/src/priority.c new file mode 100644 index 0000000..9399567 --- /dev/null +++ b/src/priority.c @@ -0,0 +1,189 @@ +/* + * 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. + */ + +/** + * @file priority.c + * @brief This file include implementation of prioritization of streams in the + * SoundPool. + */ + +#include "internal/priority.h" + +static gint __stream_stream_proirity_cmp(gconstpointer a, gconstpointer b); + +static gint __stream_stream_proirity_cmp(gconstpointer a, gconstpointer b) +{ + SP_DEBUF_FENTER(); + SP_RETVM_IF(!a, 0, "Firs pointer is NULL."); + SP_RETVM_IF(!b, 0, "Second pointer is NULL."); + sound_stream_t *stream_a = (sound_stream_t *)a; + sound_stream_t *stream_b = (sound_stream_t *)b; + + SP_DEBUG_FLEAVE(); + if (stream_a->priority != stream_b->priority) + return (stream_b->priority - stream_a->priority); + return (stream_a->id - stream_b->id); +} + +sound_pool_error_e _sound_stream_priority_create(sound_pool_t *pool, + stream_priority_manager_t **mgr) +{ + SP_DEBUF_FENTER(); + SP_RETVM_IF(!pool, SOUND_POOL_ERROR_INVALID_PARAMETER, "Stream priority " + "manager can't be created for NULL sound pool"); + SP_RETVM_IF(!mgr, SOUND_POOL_ERROR_INVALID_PARAMETER, "Can't create " + "stream priority manager. Manager pointer is NULL"); + + stream_priority_manager_t *_mgr = NULL; + SP_RETVM_IF(!(_mgr = g_try_malloc0(sizeof(*_mgr))), + SOUND_POOL_ERROR_OUT_OF_MEMORY, + "Memory alloc failure. Can't create stream priority manager."); + + int ret = SOUND_POOL_ERROR_NONE; + + _mgr->priority_queue = NULL; + _mgr->pool = pool; + pool->mgr_priority = _mgr; + + *mgr = _mgr; + + SP_DEBUG_FLEAVE(); + return ret; +} + +sound_pool_error_e _sound_stream_priority_destroy(stream_priority_manager_t *mgr) +{ + SP_DEBUF_FENTER(); + SP_RETVM_IF(!mgr, SOUND_POOL_ERROR_INVALID_PARAMETER, "Can't handle priority " + "manager, it is NULL."); + + int ret = SOUND_POOL_ERROR_NONE; + + if (mgr->priority_queue) { + g_list_free(mgr->priority_queue); + mgr->priority_queue = NULL; + } + + mgr->pool = NULL; + + SP_SAFE_GFREE(mgr); + + SP_DEBUG_FLEAVE(); + return ret; +} + +sound_pool_error_e _sound_stream_priority_add_stream( + stream_priority_manager_t *mgr, sound_stream_t *stream) +{ + SP_DEBUF_FENTER(); + int ret = SOUND_POOL_ERROR_NONE; + SP_INST_CHECK(mgr, SOUND_POOL_ERROR_INVALID_PARAMETER); + SP_INST_CHECK(stream, SOUND_POOL_ERROR_INVALID_PARAMETER); + + mgr->priority_queue = g_list_append(mgr->priority_queue,(gpointer)stream); + _sound_stream_priority_update_playback(mgr); + + SP_DEBUG_FLEAVE(); + return ret; +} + +sound_pool_error_e _sound_stream_priority_remove_stream( + stream_priority_manager_t *mgr, sound_stream_t *stream) +{ + SP_DEBUF_FENTER(); + SP_INST_CHECK(mgr, SOUND_POOL_ERROR_INVALID_PARAMETER); + SP_INST_CHECK(stream, SOUND_POOL_ERROR_INVALID_PARAMETER); + int ret = SOUND_POOL_ERROR_NONE; + + GList* to_delete; + to_delete = g_list_find(mgr->priority_queue, (gpointer)stream); + SP_RETVM_IF(NULL == to_delete, SOUND_POOL_ERROR_INVALID_PARAMETER, + "Can't find to deleting link to stream [id:%d] from priority queue.", + stream->id); + + mgr->priority_queue = g_list_delete_link(mgr->priority_queue, to_delete); + _sound_stream_priority_update_playback(mgr); + + SP_DEBUG_FLEAVE(); + return ret; +} + +sound_pool_error_e _sound_stream_priority_check(stream_priority_manager_t *mgr, + sound_stream_t *stream, gboolean *out) +{ + SP_DEBUF_FENTER(); + SP_INST_CHECK(mgr, SOUND_POOL_ERROR_INVALID_PARAMETER); + SP_INST_CHECK(stream, SOUND_POOL_ERROR_INVALID_PARAMETER); + SP_INST_CHECK(out, SOUND_POOL_ERROR_INVALID_PARAMETER); + SP_INST_CHECK(stream->parent_source, SOUND_POOL_ERROR_INVALID_PARAMETER); + SP_INST_CHECK(mgr->pool, SOUND_POOL_ERROR_INVALID_PARAMETER); + SP_INST_CHECK(mgr->pool->sources, SOUND_POOL_ERROR_INVALID_PARAMETER); + SP_INST_CHECK(g_hash_table_lookup(mgr->pool->sources, + stream->parent_source->tag_name), SOUND_POOL_ERROR_KEY_NOT_AVAILABLE); + *out = FALSE; + int ret = SOUND_POOL_ERROR_NONE; + + int position = g_list_index(mgr->priority_queue, (gconstpointer)stream); + SP_RETVM_IF(-1 == position, SOUND_POOL_ERROR_INVALID_PARAMETER, + "Can't find stream in priority queue[%s]", stream->parent_source->tag_name); + + if (position < mgr->pool->max_streams) + *out = TRUE; + + SP_DEBUG_FLEAVE(); + return ret; +} + +void _sound_stream_priority_update_playback(stream_priority_manager_t *mgr) +{ + SP_DEBUF_FENTER(); + SP_RETM_IF(!mgr, "Priority manager pointer is NULL."); + SP_RETM_IF(!mgr->pool, "Pool pointer is NULL."); + SP_RETM_IF(!mgr->pool->cbmgr, "Callback manager pointer is NULL."); + gboolean can_run = FALSE; + + if (mgr->pool->state == SOUND_POOL_STATE_INACTIVE) { + SP_INFO("No need to update priority, Sound pool is INACTIVE."); + return; + } + + mgr->priority_queue = g_list_sort(mgr->priority_queue, + __stream_stream_proirity_cmp); + + GList *iter = mgr->priority_queue; + for (; iter != NULL; iter = iter->next) { + sound_stream_t *stream = (sound_stream_t *)iter->data; + + if (SOUND_POOL_ERROR_NONE != _sound_stream_priority_check(mgr, stream, + &can_run)) + continue; + if (TRUE == can_run) { + if (SOUND_POOL_STREAM_STATE_PLAYING != stream->state) + _sound_stream_play(stream); + } else { + if (SOUND_POOL_STREAM_STATE_PLAYING == stream->state) + _sound_stream_pause(stream); + stream->state_previous = stream->state; + stream->state = SOUND_POOL_STREAM_STATE_SUSPENDED; + if (_stream_cb_manager_register_event(mgr->pool->cbmgr, stream) != + SOUND_POOL_ERROR_NONE) + SP_DEBUG("State changing event wasn't registered." + "Callbacks will be not called"); + } + } + + SP_DEBUG_FLEAVE(); +} diff --git a/src/sound_pool.c b/src/sound_pool.c index f720f45..6236e6e 100644 --- a/src/sound_pool.c +++ b/src/sound_pool.c @@ -14,8 +14,466 @@ * limitations under the License. */ +/** + * @file sound_pool.c + * @brief This file include implementation of public API for the SoundPool. + */ + #include "sound_pool.h" +#include "sound_pool_private.h" + +#include "internal/soundpool.h" +#include "internal/source.h" +#include "internal/stream.h" /* * Public Implementation */ + +static unsigned int sound_pool_amount = 0; + +sound_pool_error_e sound_pool_create(unsigned max_streams, sound_pool_h *pool) +{ + SP_DEBUF_FENTER(); + SP_RETVM_IF(max_streams == 0, SOUND_POOL_ERROR_INVALID_PARAMETER, + "Max streams count should be greater then 0."); + SP_RETVM_IF(SOUND_POOL_MAX_POOLS_AMOUNT < (sound_pool_amount+1), + SOUND_POOL_ERROR_INVALID_OPERATION, + "Max pools count should be no more than %d.", + SOUND_POOL_MAX_POOLS_AMOUNT); + SP_INST_CHECK(pool, SOUND_POOL_ERROR_INVALID_PARAMETER); + + sound_pool_t *_pool = NULL; + const int ret = _sound_pool_create(max_streams, &_pool); + SP_RETVM_IF(ret != SOUND_POOL_ERROR_NONE, ret, + "Error while creating sound pool instance."); + SP_INST_CHECK(pool, SOUND_POOL_ERROR_INVALID_OPERATION); + + *pool = _pool; + ++sound_pool_amount; + SP_INFO("Number of created pools is [%u]", sound_pool_amount); + + SP_DEBUG_FLEAVE(); + return ret; +} + +sound_pool_error_e sound_pool_destroy(sound_pool_h pool) +{ + SP_DEBUF_FENTER(); + + const int ret = _sound_pool_destroy((sound_pool_t *)pool); + SP_RETVM_IF(ret != SOUND_POOL_ERROR_NONE, ret, + "Error occurred when destroying the sound pool"); + --sound_pool_amount; + SP_INFO("Number of pools is [%u]", sound_pool_amount); + + SP_DEBUG_FLEAVE(); + return ret; +} + +sound_pool_error_e sound_pool_load_source_from_file(sound_pool_h pool, + const char *file_name, const char *tag) +{ + SP_DEBUF_FENTER(); + + sound_pool_t *_pool = (sound_pool_t *)pool; + sound_source_t *_src = NULL; + int ret = _sound_source_create(_pool, tag, &_src); + SP_RETVM_IF(ret != SOUND_POOL_ERROR_NONE, ret, + "Error while creating sound source instance."); + + ret = _sound_source_load_from_file(_src, file_name); + if (ret != SOUND_POOL_ERROR_NONE) { + SP_ERROR("Error occurred when loading sound source from file"); + if (_sound_source_destroy(_src) != SOUND_POOL_ERROR_NONE) + SP_ERROR("Error occurred during removal of sound source[%s].", tag); + } + + SP_DEBUG_FLEAVE(); + return ret; +} + +sound_pool_error_e sound_pool_unload_source(sound_pool_h pool, const char *tag) +{ + SP_DEBUF_FENTER(); + + sound_pool_t *_pool = (sound_pool_t *)pool; + sound_source_t *_source = NULL; + int ret = _sound_pool_get_source_by_tag(_pool, tag, &_source); + SP_RETVM_IF(ret != SOUND_POOL_ERROR_NONE, ret, "Error occurred when " + "getting sound source [%s] from the sound pool", tag); + SP_INST_CHECK(_source, SOUND_POOL_ERROR_INVALID_OPERATION); + + ret = _sound_source_destroy(_source); + SP_RETVM_IF(ret != SOUND_POOL_ERROR_NONE, ret, "Error occurred when " + "destroying sound source [%s]", tag); + + SP_DEBUG_FLEAVE(); + return ret; +} + +sound_pool_error_e sound_pool_stream_play(sound_pool_h pool, const char *tag, + unsigned loop, float volume, unsigned priority, + sound_pool_stream_state_change_cb callback, void *data, unsigned *id) +{ + SP_DEBUF_FENTER(); + SP_INST_CHECK(id, SOUND_POOL_ERROR_INVALID_PARAMETER); + + sound_pool_t *_pool = (sound_pool_t *)pool; + sound_source_t *_source = NULL; + int ret = _sound_pool_get_source_by_tag(_pool, tag, &_source); + SP_RETVM_IF(ret != SOUND_POOL_ERROR_NONE, ret, "Error occurred when " + "getting sound source [%s] from the sound pool", tag); + SP_INST_CHECK(_source, SOUND_POOL_ERROR_INVALID_OPERATION); + + sound_stream_t *_stream = NULL; + ret = _sound_stream_create(_source, &_stream); + SP_RETVM_IF(ret != SOUND_POOL_ERROR_NONE, ret, + "Error while creating sound source instance."); + + ret = _sound_stream_set_loop(_stream, loop); + SP_RETVM_IF(ret != SOUND_POOL_ERROR_NONE, ret, "Error occurred when " + "setting sound stream loop parameter", tag); + + ret = _sound_stream_set_volume(_stream, volume); + SP_RETVM_IF(ret != SOUND_POOL_ERROR_NONE, ret, "Error occurred when " + "setting sound stream volume parameter", tag); + + if (callback) { + ret = _sound_stream_set_callback(_stream, callback, data); + SP_RETVM_IF(ret != SOUND_POOL_ERROR_NONE, ret, "Error occurred when " + "setting sound stream callback", tag); + } + + ret = _sound_stream_set_priority(_stream, priority); + SP_RETVM_IF(ret != SOUND_POOL_ERROR_NONE, ret, "Error occurred when " + "setting sound stream priority parameter", tag); + + *id = _stream->id; + + SP_DEBUG_FLEAVE(); + return ret; +} + +sound_pool_error_e sound_pool_stream_pause(sound_pool_h pool, unsigned id) +{ + SP_DEBUF_FENTER(); + + sound_pool_t *_pool = (sound_pool_t *)pool; + sound_stream_t *_stream = NULL; + int ret = _sound_pool_get_stream_by_id(_pool, id, &_stream); + SP_RETVM_IF(ret != SOUND_POOL_ERROR_NONE, ret, "Error occurred when " + "getting sound stream [%u] from the sound pool", id); + SP_INST_CHECK(_stream, SOUND_POOL_ERROR_INVALID_OPERATION); + + ret = _sound_stream_pause(_stream); + SP_RETVM_IF(ret != SOUND_POOL_ERROR_NONE, ret, "Error occurred when " + "pausing sound stream [%u]", id); + + SP_DEBUG_FLEAVE(); + return ret; +} + +sound_pool_error_e sound_pool_stream_resume(sound_pool_h pool, unsigned id) +{ + SP_DEBUF_FENTER(); + sound_pool_t *_pool = (sound_pool_t *)pool; + sound_stream_t *_stream = NULL; + int ret = _sound_pool_get_stream_by_id(_pool, id, &_stream); + SP_RETVM_IF(ret != SOUND_POOL_ERROR_NONE, ret, "Error occurred when " + "getting sound stream [%u] from the sound pool", id); + SP_INST_CHECK(_stream, SOUND_POOL_ERROR_INVALID_OPERATION); + + ret = _sound_stream_resume(_stream); + SP_RETVM_IF(ret != SOUND_POOL_ERROR_NONE, ret, "Error occurred when " + "resuming sound stream [%u]", id); + + SP_DEBUG_FLEAVE(); + return ret; +} + +sound_pool_error_e sound_pool_stream_stop(sound_pool_h pool, unsigned id) +{ + SP_DEBUF_FENTER(); + + sound_pool_t *_pool = (sound_pool_t *)pool; + sound_stream_t *_stream = NULL; + int ret = _sound_pool_get_stream_by_id(_pool, id, &_stream); + SP_RETVM_IF(ret != SOUND_POOL_ERROR_NONE, ret, "Error occurred when " + "getting sound stream [%u] from the sound pool", id); + SP_INST_CHECK(_stream, SOUND_POOL_ERROR_INVALID_OPERATION); + + ret = _sound_stream_stop(_stream); + SP_RETVM_IF(ret != SOUND_POOL_ERROR_NONE, ret, "Error occurred when " + "stopping sound stream [%u]", id); + + SP_DEBUG_FLEAVE(); + return ret; +} + +sound_pool_error_e sound_pool_get_state(sound_pool_h pool, sound_pool_state_e *state) +{ + SP_DEBUF_FENTER(); + + const int ret = _sound_pool_get_state(pool, state); + SP_RETVM_IF(ret != SOUND_POOL_ERROR_NONE, ret, "Error occurred when " + "getting state of the sound pool"); + + SP_DEBUG_FLEAVE(); + return ret; +} + +sound_pool_error_e sound_pool_activate(sound_pool_h pool) +{ + SP_DEBUF_FENTER(); + + const int ret = _sound_pool_activate((sound_pool_t *)pool); + SP_RETVM_IF(ret != SOUND_POOL_ERROR_NONE, ret, "Error occurred when " + "activating sound pool"); + + SP_DEBUG_FLEAVE(); + return ret; +} + +sound_pool_error_e sound_pool_deactivate(sound_pool_h pool) +{ + SP_DEBUF_FENTER(); + + const int ret = _sound_pool_deactivate((sound_pool_t *)pool); + SP_RETVM_IF(ret != SOUND_POOL_ERROR_NONE, ret, "Error occurred when " + "deactivating sound pool"); + + SP_DEBUG_FLEAVE(); + return ret; +} + +sound_pool_error_e sound_pool_set_volume(sound_pool_h pool, float volume) +{ + SP_DEBUF_FENTER(); + + const int ret = _sound_pool_set_volume((sound_pool_t *)pool, volume); + SP_RETVM_IF(ret != SOUND_POOL_ERROR_NONE, ret, "Error occurred when " + "setting volume for sound pool"); + + SP_DEBUG_FLEAVE(); + return ret; +} + +sound_pool_error_e sound_pool_get_volume(sound_pool_h pool, float *volume) +{ + SP_DEBUF_FENTER(); + + const int ret = _sound_pool_get_volume((sound_pool_t *)pool, volume); + SP_RETVM_IF(ret != SOUND_POOL_ERROR_NONE, ret, "Error occurred when " + "getting volume for sound pool"); + + SP_DEBUG_FLEAVE(); + return ret; +} + +sound_pool_error_e sound_pool_stream_get_state(sound_pool_h pool, unsigned id, + sound_pool_stream_state_e *state) +{ + SP_DEBUF_FENTER(); + + sound_pool_t *_pool = (sound_pool_t *)pool; + sound_stream_t *_stream = NULL; + int ret = _sound_pool_get_stream_by_id(_pool, id, &_stream); + SP_RETVM_IF(ret != SOUND_POOL_ERROR_NONE, ret, "Error occurred when " + "getting sound stream [%u] from the sound pool", id); + SP_INST_CHECK(_stream, SOUND_POOL_ERROR_INVALID_OPERATION); + + ret = _sound_stream_get_state(_stream, state); + SP_RETVM_IF(ret != SOUND_POOL_ERROR_NONE, ret, "Error occurred when " + "getting sound stream [%u] state", id); + + SP_DEBUG_FLEAVE(); + return ret; +} + +sound_pool_error_e sound_pool_stream_set_loop(sound_pool_h pool, unsigned id, + unsigned loop) +{ + SP_DEBUF_FENTER(); + + sound_pool_t *_pool = (sound_pool_t *)pool; + sound_stream_t *_stream = NULL; + int ret = _sound_pool_get_stream_by_id(_pool, id, &_stream); + SP_RETVM_IF(ret != SOUND_POOL_ERROR_NONE, ret, "Error occurred when " + "getting sound stream [%u] from the sound pool", id); + SP_INST_CHECK(_stream, SOUND_POOL_ERROR_INVALID_OPERATION); + + ret = _sound_stream_set_loop(_stream, loop); + SP_RETVM_IF(ret != SOUND_POOL_ERROR_NONE, ret, "Error occurred when " + "setting sound stream [%u] loop parameter", id); + + SP_DEBUG_FLEAVE(); + return ret; +} + +sound_pool_error_e sound_pool_stream_get_loop(sound_pool_h pool, unsigned id, + unsigned *loop) +{ + SP_DEBUF_FENTER(); + + sound_pool_t *_pool = (sound_pool_t *)pool; + sound_stream_t *_stream = NULL; + int ret = _sound_pool_get_stream_by_id(_pool, id, &_stream); + SP_RETVM_IF(ret != SOUND_POOL_ERROR_NONE, ret, "Error occurred when " + "getting sound stream [%u] from the sound pool", id); + SP_INST_CHECK(_stream, SOUND_POOL_ERROR_INVALID_OPERATION); + + ret = _sound_stream_get_loop(_stream, loop); + SP_RETVM_IF(ret != SOUND_POOL_ERROR_NONE, ret, "Error occurred when " + "getting sound stream [%u] loop parameter", id); + + SP_DEBUG_FLEAVE(); + return ret; +} + +sound_pool_error_e sound_pool_stream_set_volume(sound_pool_h pool, unsigned id, + float volume) +{ + SP_DEBUF_FENTER(); + + sound_pool_t *_pool = (sound_pool_t *)pool; + sound_stream_t *_stream = NULL; + int ret = _sound_pool_get_stream_by_id(_pool, id, &_stream); + SP_RETVM_IF(ret != SOUND_POOL_ERROR_NONE, ret, "Error occurred when " + "getting sound stream [%u] from the sound pool", id); + SP_INST_CHECK(_stream, SOUND_POOL_ERROR_INVALID_OPERATION); + + ret = _sound_stream_set_volume(_stream, volume); + SP_RETVM_IF(ret != SOUND_POOL_ERROR_NONE, ret, "Error occurred when " + "setting sound stream [%u] volume parameter", id); + + SP_DEBUG_FLEAVE(); + return ret; +} + +sound_pool_error_e sound_pool_stream_get_volume(sound_pool_h pool, unsigned id, + float *volume) +{ + SP_DEBUF_FENTER(); + + sound_pool_t *_pool = (sound_pool_t *)pool; + sound_stream_t *_stream = NULL; + int ret = _sound_pool_get_stream_by_id(_pool, id, &_stream); + SP_RETVM_IF(ret != SOUND_POOL_ERROR_NONE, ret, "Error occurred when " + "getting sound stream [%u] from the sound pool", id); + SP_INST_CHECK(_stream, SOUND_POOL_ERROR_INVALID_OPERATION); + + ret = _sound_stream_get_volume(_stream, volume); + SP_RETVM_IF(ret != SOUND_POOL_ERROR_NONE, ret, "Error occurred when " + "getting sound stream [%u] volume parameter", id); + + SP_DEBUG_FLEAVE(); + return ret; +} + +sound_pool_error_e sound_pool_stream_set_priority(sound_pool_h pool, + unsigned id, unsigned priority) +{ + SP_DEBUF_FENTER(); + + sound_pool_t *_pool = (sound_pool_t *)pool; + sound_stream_t *_stream = NULL; + int ret = _sound_pool_get_stream_by_id(_pool, id, &_stream); + SP_RETVM_IF(ret != SOUND_POOL_ERROR_NONE, ret, "Error occurred when " + "getting sound stream [%u] from the sound pool", id); + SP_INST_CHECK(_stream, SOUND_POOL_ERROR_INVALID_OPERATION); + + ret = _sound_stream_set_priority(_stream, priority); + SP_RETVM_IF(ret != SOUND_POOL_ERROR_NONE, ret, "Error occurred when " + "setting sound stream [%u] priority parameter", id); + + SP_DEBUG_FLEAVE(); + return ret; +} + +sound_pool_error_e sound_pool_stream_get_priority(sound_pool_h pool, + unsigned id, unsigned *priority) +{ + SP_DEBUF_FENTER(); + + sound_pool_t *_pool = (sound_pool_t *)pool; + sound_stream_t *_stream = NULL; + int ret = _sound_pool_get_stream_by_id(_pool, id, &_stream); + SP_RETVM_IF(ret != SOUND_POOL_ERROR_NONE, ret, "Error occurred when " + "getting sound stream [%u] from the sound pool", id); + SP_INST_CHECK(_stream, SOUND_POOL_ERROR_INVALID_OPERATION); + + ret = _sound_stream_get_priority(_stream, priority); + SP_RETVM_IF(ret != SOUND_POOL_ERROR_NONE, ret, "Error occurred when " + "getting sound stream [%u] priority parameter", id); + + SP_DEBUG_FLEAVE(); + return ret; +} + +sound_pool_error_e sound_pool_set_state_change_callback(sound_pool_h pool, + sound_pool_state_change_cb callback, void *data) +{ + SP_DEBUF_FENTER(); + + const int ret = + _sound_pool_set_callback((sound_pool_t *)pool, callback, data); + SP_RETVM_IF(ret != SOUND_POOL_ERROR_NONE, ret, "Error occurred when " + "setting state changing callback for sound pool"); + + SP_DEBUG_FLEAVE(); + return ret; +} + +sound_pool_error_e sound_pool_unset_state_change_callback(sound_pool_h pool) +{ + SP_DEBUF_FENTER(); + + const int ret = _sound_pool_unset_callback((sound_pool_t *)pool); + SP_RETVM_IF(ret != SOUND_POOL_ERROR_NONE, ret, "Error occurred when " + "unsetting state changing callback for sound pool"); + + SP_DEBUG_FLEAVE(); + return ret; +} + +sound_pool_error_e sound_pool_stream_set_state_change_callback( + sound_pool_h pool, unsigned id, + sound_pool_stream_state_change_cb callback, void *data) +{ + SP_DEBUF_FENTER(); + + sound_pool_t *_pool = (sound_pool_t *)pool; + sound_stream_t *_stream = NULL; + int ret = _sound_pool_get_stream_by_id(_pool, id, &_stream); + SP_RETVM_IF(ret != SOUND_POOL_ERROR_NONE, ret, "Error occurred when " + "getting sound stream [%u] from the sound pool", id); + SP_INST_CHECK(_stream, SOUND_POOL_ERROR_INVALID_OPERATION); + + ret = _sound_stream_set_callback(_stream, callback, data); + SP_RETVM_IF(ret != SOUND_POOL_ERROR_NONE, ret, "Error occurred when " + "setting sound stream [%u] state changing callback", id); + + SP_DEBUG_FLEAVE(); + return ret; +} + +sound_pool_error_e sound_pool_stream_unset_state_change_callback( + sound_pool_h pool, unsigned id) +{ + SP_DEBUF_FENTER(); + + sound_pool_t *_pool = (sound_pool_t *)pool; + sound_stream_t *_stream = NULL; + int ret = _sound_pool_get_stream_by_id(_pool, id, &_stream); + SP_RETVM_IF(ret != SOUND_POOL_ERROR_NONE, ret, "Error occurred when " + "getting sound stream [%u] from the sound pool", id); + SP_INST_CHECK(_stream, SOUND_POOL_ERROR_INVALID_OPERATION); + + ret = _sound_stream_unset_callback(_stream); + SP_RETVM_IF(ret != SOUND_POOL_ERROR_NONE, ret, "Error occurred when " + "unsetting sound stream [%u] state changing callback", id); + + SP_DEBUG_FLEAVE(); + return ret; +} diff --git a/src/soundpool.c b/src/soundpool.c new file mode 100644 index 0000000..631a3aa --- /dev/null +++ b/src/soundpool.c @@ -0,0 +1,326 @@ +/* + * 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. + */ + +/** + * @file soundpool.c + * @brief This file include implementation of protected API for the SoundPool. + */ + +#include "internal/soundpool.h" + +#include "internal/priority.h" +#include "internal/stream_cb_manager.h" + +#include "internal/source.h" +#include "internal/stream.h" + +#define DEFAULT_VOLUME_VALUE 1.0f + +static ALCdevice *device = NULL; +static void __stream_activate_iter(gpointer key, gpointer value, + gpointer user_data); +static void __stream_deactivate_iter(gpointer key, gpointer value, + gpointer user_data); + +static void __stream_activate_iter(gpointer key, gpointer value, + gpointer user_data) +{ + SP_DEBUF_FENTER(); + SP_RETM_IF(!user_data, "Empty user data."); + SP_RETM_IF(!value, "Empty sound stream data."); + guint *len = (guint*)user_data; + sound_stream_t *stream = (sound_stream_t *)value; + + gboolean can_run = TRUE; + if (SOUND_POOL_ERROR_NONE + == _sound_stream_priority_check(stream->parent_source->parent_pool->mgr_priority, + stream, &can_run)) + if (stream->state == SOUND_POOL_STREAM_STATE_SUSPENDED && TRUE == can_run) { + alSourcePlay(stream->al_source); + (*len)++; + } + + SP_DEBUG_FLEAVE(); +} + +static void __stream_deactivate_iter(gpointer key, gpointer value, + gpointer user_data) +{ + SP_DEBUF_FENTER(); + SP_RETM_IF(!user_data, "Empty user data."); + SP_RETM_IF(!value, "Empty sound stream data."); + guint *len = (guint*)user_data; + sound_stream_t *stream = (sound_stream_t *)value; + + if (stream->state == SOUND_POOL_STREAM_STATE_PLAYING) { + alSourcePause(stream->al_source); + (*len)++; + } + + SP_DEBUG_FLEAVE(); +} + +sound_pool_error_e _sound_pool_create(size_t max_streams, sound_pool_t **pool) +{ + SP_DEBUF_FENTER(); + SP_RETVM_IF(max_streams == 0, SOUND_POOL_ERROR_INVALID_PARAMETER, + "Max streams count should be greater than 0."); + + sound_pool_t *_pool = NULL; + SP_RETVM_IF(!(_pool = g_try_malloc0(sizeof(*_pool))), + SOUND_POOL_ERROR_OUT_OF_MEMORY, + "Memory alloc failure. Can't create sound pool"); + SP_RETVM_IF(!pool, SOUND_POOL_ERROR_INVALID_PARAMETER, "Can't create " + "sound pool. Pool pointer is NULL"); + + int ret = SOUND_POOL_ERROR_NONE; + _pool->al_context = NULL; + _pool->al_context = alcCreateContext(alcOpenDevice(NULL), NULL); + if (!_pool->al_context) { + ret = SOUND_POOL_ERROR_OUT_OF_MEMORY; + GOTO_FAIL("Memory alloc failure. Can't create OpenAL Context", cfail); + } + + _pool->sources = NULL; + _pool->streams = NULL; + + _pool->sources = g_hash_table_new(g_str_hash, g_str_equal); + if (!_pool->sources) { + ret = SOUND_POOL_ERROR_OUT_OF_MEMORY; + GOTO_FAIL("Memory alloc failure. Can't create internal sources hash " + "table in sound pool", cfail); + } + + _pool->streams = g_hash_table_new(g_int_hash, g_int_equal); + if (!_pool->streams) { + ret = SOUND_POOL_ERROR_OUT_OF_MEMORY; + GOTO_FAIL("Memory alloc failure. Can't create internal streams hash " + "table in sound pool", cfail); + } + + _pool->max_streams = max_streams; + _pool->volume = DEFAULT_VOLUME_VALUE; + _pool->max_stream_index = 0; + _pool->state = SOUND_POOL_STATE_INACTIVE; + _pool->state_cb_info.callback = NULL; + _pool->state_cb_info.user_data = NULL; + + _pool->cbmgr = NULL; + ret = _stream_cb_manager_create(_pool, &_pool->cbmgr); + if (ret != SOUND_POOL_ERROR_NONE) + GOTO_FAIL("Error occurred when trying to create stream state changing " + "callback manager instance", cfail); + + _pool->mgr_priority = NULL; + ret = _sound_stream_priority_create(_pool, &_pool->mgr_priority); + if (ret != SOUND_POOL_ERROR_NONE) + GOTO_FAIL("Error occurred initialising of priorities.", cfail); + + *pool = _pool; + SP_DEBUG_FLEAVE(); + return ret; + +cfail: + _sound_pool_destroy(_pool); + SP_DEBUG_FLEAVE(); + return ret; +} + +sound_pool_error_e _sound_pool_destroy(sound_pool_t *pool) +{ + SP_DEBUF_FENTER(); + SP_INST_CHECK(pool, SOUND_POOL_ERROR_INVALID_PARAMETER); + _sound_pool_deactivate(pool); + + if (pool->cbmgr) { + const int ret = _stream_cb_manager_destroy(pool->cbmgr); + SP_RETVM_IF(ret != SOUND_POOL_ERROR_NONE, ret, + "Error occurred when " "trying to destroy sound pool callback manager."); + pool->cbmgr = NULL; + } + + if (pool->sources) { + GHashTableIter iter; + gpointer key, value; + g_hash_table_iter_init(&iter, pool->sources); + while (g_hash_table_iter_next(&iter, &key, &value)) { + guint size_before = g_hash_table_size(pool->sources); + _sound_source_destroy((sound_source_t*)value); + guint size_after = g_hash_table_size(pool->sources); + if (size_before != size_after) + g_hash_table_iter_init(&iter, pool->sources); + } + g_hash_table_unref(pool->sources); + pool->sources = NULL; + } + + if (pool->streams) { + g_hash_table_unref(pool->streams); + pool->streams = NULL; + } + + if (pool->mgr_priority) { + const int ret = _sound_stream_priority_destroy(pool->mgr_priority); + SP_RETVM_IF(ret != SOUND_POOL_ERROR_NONE, ret, + "Error occurred when trying to destroy priority manager."); + pool->mgr_priority = NULL; + } + + if (pool->al_context) { + ALCdevice *device = alcGetContextsDevice(pool->al_context); + alcMakeContextCurrent(NULL); + alcDestroyContext(pool->al_context); + alcCloseDevice(device); + } + + SP_SAFE_GFREE(pool); + + SP_DEBUG_FLEAVE(); + return SOUND_POOL_ERROR_NONE; +} + +sound_pool_error_e _sound_pool_activate(sound_pool_t *pool) +{ + SP_DEBUF_FENTER(); + SP_INST_CHECK(pool, SOUND_POOL_ERROR_INVALID_PARAMETER); + + SP_RETVM_IF(pool->state == SOUND_POOL_STATE_ACTIVE, + SOUND_POOL_ERROR_INVALID_OPERATION, + "Already activated sound pool can't be activated again."); + + sound_pool_state_e old_state = pool->state; + pool->state = SOUND_POOL_STATE_ACTIVE; + + /* Generate array of all AlSources in pool */ + GPtrArray *streams = NULL; + if (g_hash_table_size(pool->streams) > 0) { + SP_RETVM_IF(!alcMakeContextCurrent(pool->al_context), + SOUND_POOL_ERROR_INVALID_OPERATION, "Can't set current context."); + guint len = 0; + g_hash_table_foreach(pool->streams, __stream_activate_iter, &len); + SP_INFO("Resuming [%d] number of streams.", len); + } + + if (streams) + g_ptr_array_free(streams, TRUE); + + SP_INFO("Sound pool has been activated"); + + if (pool->state_cb_info.callback) + pool->state_cb_info.callback(pool, old_state, pool->state, + pool->state_cb_info.user_data); + + SP_DEBUG_FLEAVE(); + return SOUND_POOL_ERROR_NONE; +} + +sound_pool_error_e _sound_pool_deactivate(sound_pool_t *pool) +{ + SP_DEBUF_FENTER(); + SP_INST_CHECK(pool, SOUND_POOL_ERROR_INVALID_PARAMETER); + SP_RETVM_IF(pool->state == SOUND_POOL_STATE_INACTIVE, + SOUND_POOL_ERROR_INVALID_OPERATION, + "Already deactivated sound pool can't be deactivated again."); + + sound_pool_state_e old_state = pool->state; + pool->state = SOUND_POOL_STATE_INACTIVE; + + /* Generate array of all AlSources in pool */ + GPtrArray *streams = NULL; + if (g_hash_table_size(pool->streams) > 0) { + SP_RETVM_IF(!alcMakeContextCurrent(pool->al_context), + SOUND_POOL_ERROR_INVALID_OPERATION, "Can't set current context."); + guint len = 0; + g_hash_table_foreach(pool->streams, __stream_deactivate_iter, &len); + SP_INFO("Suspending [%d] number of streams.", len); + } + + if (streams) + g_ptr_array_free(streams, TRUE); + + SP_INFO("Sound pool has been deactivated"); + + if (pool->state_cb_info.callback) + pool->state_cb_info.callback(pool, old_state, pool->state, + pool->state_cb_info.user_data); + + SP_DEBUG_FLEAVE(); + return SOUND_POOL_ERROR_NONE; +} + +sound_pool_error_e _sound_pool_get_state(sound_pool_t *pool, + sound_pool_state_e *state) +{ + SP_DEBUF_FENTER(); + SP_INST_CHECK(pool, SOUND_POOL_ERROR_INVALID_PARAMETER); + SP_INST_CHECK(state, SOUND_POOL_ERROR_INVALID_PARAMETER); + *state = pool->state; + SP_DEBUG_FLEAVE(); + return SOUND_POOL_ERROR_NONE; +} + +sound_pool_error_e _sound_pool_set_volume(sound_pool_t *pool, float volume) +{ + SP_DEBUF_FENTER(); + SP_INST_CHECK(pool, SOUND_POOL_ERROR_INVALID_PARAMETER); + SP_RETVM_IF((volume < 0.0f || volume > 1.0f), + SOUND_POOL_ERROR_INVALID_PARAMETER, + "Sound pool volume is not in [0.0..1.0] range."); + + SP_RETVM_IF(!alcMakeContextCurrent(pool->al_context), + SOUND_POOL_ERROR_INVALID_OPERATION, "Can't set current context."); + alListenerf(AL_GAIN, volume); + pool->volume = volume; + + SP_DEBUG_FLEAVE(); + return SOUND_POOL_ERROR_NONE; +} + +sound_pool_error_e _sound_pool_get_volume(sound_pool_t *pool, float *volume) +{ + SP_DEBUF_FENTER(); + SP_INST_CHECK(pool, SOUND_POOL_ERROR_INVALID_PARAMETER); + SP_INST_CHECK(volume, SOUND_POOL_ERROR_INVALID_PARAMETER); + *volume = pool->volume; + SP_DEBUG_FLEAVE(); + return SOUND_POOL_ERROR_NONE; +} + +sound_pool_error_e _sound_pool_set_callback(sound_pool_t *pool, + sound_pool_state_change_cb callback, void *data) +{ + SP_DEBUF_FENTER(); + SP_INST_CHECK(pool, SOUND_POOL_ERROR_INVALID_PARAMETER); + SP_INST_CHECK(callback, SOUND_POOL_ERROR_INVALID_PARAMETER); + + pool->state_cb_info.callback = callback; + pool->state_cb_info.user_data = data; + + SP_DEBUG_FLEAVE(); + return SOUND_POOL_ERROR_NONE; +} + +sound_pool_error_e _sound_pool_unset_callback(sound_pool_t *pool) +{ + SP_DEBUF_FENTER(); + SP_INST_CHECK(pool, SOUND_POOL_ERROR_INVALID_PARAMETER); + + pool->state_cb_info.callback = NULL; + pool->state_cb_info.user_data = NULL; + + SP_DEBUG_FLEAVE(); + return SOUND_POOL_ERROR_NONE; +} diff --git a/src/source.c b/src/source.c new file mode 100644 index 0000000..d9584dd --- /dev/null +++ b/src/source.c @@ -0,0 +1,218 @@ +/* + * 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. + */ + +/** + * @file source.c + * @brief This file include implementation of protected API + * for the sound sources(OpenAL buffers) as part of SoundPool. + */ + +#include "internal/source.h" +#include "internal/stream.h" + +#include + +static int __sound_pool_add_source(sound_pool_t *pool, sound_source_t *src); +static int __sound_pool_remove_source(sound_pool_t *pool, sound_source_t *src); + +static int __sound_pool_add_source(sound_pool_t *pool, sound_source_t *src) +{ + SP_DEBUF_FENTER(); + SP_INST_CHECK(pool, SOUND_POOL_ERROR_INVALID_PARAMETER); + SP_INST_CHECK(src, SOUND_POOL_ERROR_INVALID_PARAMETER); + SP_RETVM_IF(!pool->sources, SOUND_POOL_ERROR_INVALID_OPERATION, "Sound " + "pool to add the source is corrupted: NULL sources hash table"); + SP_RETVM_IF(!src->tag_name, SOUND_POOL_ERROR_INVALID_OPERATION, + "Source to be added to sound pool is corrupted: NULL tag name"); + SP_RETVM_IF(src->parent_pool != pool, SOUND_POOL_ERROR_INVALID_OPERATION, + "Sound source can't be added to the pool different to the pool for" + " which sound source was created"); + SP_RETVM_IF(g_hash_table_contains(pool->sources, src->tag_name), + SOUND_POOL_ERROR_INVALID_PARAMETER, + "Tag already exists in sources hash table."); + + SP_RETVM_IF(!g_hash_table_insert(pool->sources, src->tag_name, src), + SOUND_POOL_ERROR_INVALID_OPERATION, "Error occurred when adding " + "the source tagged [%s] to the sound pool", src->tag_name); + + SP_DEBUG_FLEAVE(); + return SOUND_POOL_ERROR_NONE; +} + +static int __sound_pool_remove_source(sound_pool_t *pool, sound_source_t *src) +{ + SP_DEBUF_FENTER(); + SP_INST_CHECK(pool, SOUND_POOL_ERROR_INVALID_PARAMETER); + SP_INST_CHECK(pool->sources, SOUND_POOL_ERROR_INVALID_PARAMETER); + SP_INST_CHECK(src, SOUND_POOL_ERROR_INVALID_PARAMETER); + + if (src->parent_pool == pool && src->tag_name) { + if (!g_hash_table_steal(pool->sources, src->tag_name)) { + SP_DEBUG("Tag [%s] doesn't exist in sources hash table", + src->tag_name); + SP_DEBUG_FLEAVE(); + return SOUND_POOL_ERROR_NONE; + } + GHashTableIter iter; + gpointer key, value; + g_hash_table_iter_init(&iter, pool->streams); + while (g_hash_table_iter_next(&iter, &key, &value)) { + guint size_before = g_hash_table_size(pool->streams); + gchar *tag = (gchar*)key; + sound_stream_t *stream = (sound_stream_t*)value; + SP_INFO("(%s)(%s)", src->tag_name, stream->parent_source->tag_name); + if (src == stream->parent_source) + _sound_stream_destroy((sound_stream_t*)value); + guint size_after = g_hash_table_size(pool->streams); + if (size_before != size_after) + g_hash_table_iter_init(&iter, pool->streams); + } + } else { + SP_DEBUG("Source wasn't removed from sound pool as it isn't known by " + "the pool for which operation is performed, or tag corrupted"); + } + + SP_DEBUG_FLEAVE(); + return SOUND_POOL_ERROR_NONE; +} + +sound_pool_error_e _sound_source_create(sound_pool_t *pool, const char *tag, + sound_source_t **src) +{ + SP_DEBUF_FENTER(); + SP_RETVM_IF(!pool, SOUND_POOL_ERROR_INVALID_PARAMETER, + "Can't create sound source in NULL sound pool"); + SP_RETVM_IF(!tag, SOUND_POOL_ERROR_INVALID_PARAMETER, + "Can't create sound source with NULL tag name"); + SP_RETVM_IF(!src, SOUND_POOL_ERROR_INVALID_PARAMETER, + "Can't create sound source. Source pointer is NULL"); + SP_RETVM_IF(strnlen(tag, MAX_TAG_LEN + 1) == MAX_TAG_LEN + 1, + SOUND_POOL_ERROR_INVALID_PARAMETER, "Can't create sound source " + "with tag name longer than %u", MAX_TAG_LEN); + SP_RETVM_IF(!pool->sources, SOUND_POOL_ERROR_INVALID_OPERATION, "Sound " + "pool to create source is corrupted: NULL sources hash table."); + SP_RETVM_IF(g_hash_table_contains(pool->sources, tag), + SOUND_POOL_ERROR_INVALID_PARAMETER, + "Tag already exists in sources hash table."); + + SP_RETVM_IF(!alcMakeContextCurrent(pool->al_context), + SOUND_POOL_ERROR_INVALID_OPERATION, + "Can't set current context."); + + sound_source_t *_src = NULL; + SP_RETVM_IF(!(_src = g_try_malloc0(sizeof(*_src))), + SOUND_POOL_ERROR_OUT_OF_MEMORY, + "Memory alloc failure. Can't create sound _src"); + + int ret = SOUND_POOL_ERROR_NONE; + alGenBuffers(1, &_src->al_buffer); + if (alGetError() != AL_NO_ERROR) { + ret = SOUND_POOL_ERROR_OUT_OF_MEMORY; + GOTO_FAIL("OpenAL error occurred when trying to generate Buffer id", cfail); + } + + _src->parent_pool = pool; + _src->tag_name = NULL; + _src->tag_name = g_strndup(tag, MAX_TAG_LEN); + + ret = __sound_pool_add_source(pool, _src); + if (ret != SOUND_POOL_ERROR_NONE) + GOTO_FAIL("Error occurred when trying to add source to pool", cfail); + + *src = _src; + SP_DEBUG_FLEAVE(); + return ret; + +cfail: + ret = _sound_source_destroy(_src); + SP_RETVM_IF(SOUND_POOL_ERROR_NONE != ret, ret, "Error occurred during removal " + "of sound source[%s].", tag); + SP_DEBUG_FLEAVE(); + return ret; +} + +sound_pool_error_e _sound_source_destroy(sound_source_t *src) +{ + SP_DEBUF_FENTER(); + SP_RETVM_IF(!src, SOUND_POOL_ERROR_INVALID_PARAMETER, + "Can't destroy NULL sound source"); + + /* If parent pool exists, then source has to be removed from the pool */ + if (src->parent_pool && __sound_pool_remove_source(src->parent_pool, src) + != SOUND_POOL_ERROR_NONE) + SP_DEBUG("Source wasn't removed from sound pool."); + + SP_DEBUG("Deleting OpenAL buffer with id [%u]", src->al_buffer); + alDeleteBuffers(1, &src->al_buffer); + + SP_SAFE_GFREE(src->tag_name); + SP_SAFE_GFREE(src); + + SP_DEBUG_FLEAVE(); + return SOUND_POOL_ERROR_NONE; +} + +sound_pool_error_e _sound_source_load_from_file(sound_source_t *src, + const char *fname) +{ + SP_DEBUF_FENTER(); + SP_INST_CHECK(src, SOUND_POOL_ERROR_INVALID_PARAMETER); + SP_INST_CHECK(fname, SOUND_POOL_ERROR_INVALID_PARAMETER); + SP_INST_CHECK(src->parent_pool, SOUND_POOL_ERROR_INVALID_OPERATION); + SP_RETVM_IF(!alcMakeContextCurrent(src->parent_pool->al_context), + SOUND_POOL_ERROR_INVALID_OPERATION, "Can't set current AL context."); + + int ret = SOUND_POOL_ERROR_NONE; + ALenum format; + ALsizei size; + ALvoid* data = NULL; + ALsizei freq; + ALboolean loop; + + alutLoadWAVFile((ALbyte*)fname, &format, &data, &size, &freq, &loop); + SP_RETVM_IF(alGetError() != AL_NO_ERROR || !data, + SOUND_POOL_ERROR_NO_SUCH_FILE, "Can't load audio file. No such " + "file [%s]", fname); + + alBufferData(src->al_buffer, format, data, size, freq); + if (alGetError() != AL_NO_ERROR) { + SP_ERROR("Can't create audio buffer from file [%s]", fname); + ret = SOUND_POOL_ERROR_INVALID_OPERATION; + } + + alutUnloadWAV(format, data, size, freq); + + SP_DEBUG_FLEAVE(); + return ret; +} + +sound_pool_error_e _sound_pool_get_source_by_tag(sound_pool_t *pool, + const char *tag, sound_source_t **src) +{ + SP_DEBUF_FENTER(); + SP_INST_CHECK(pool, SOUND_POOL_ERROR_INVALID_PARAMETER); + SP_INST_CHECK(tag, SOUND_POOL_ERROR_INVALID_PARAMETER); + SP_INST_CHECK(src, SOUND_POOL_ERROR_INVALID_PARAMETER); + SP_RETVM_IF(!pool->sources, SOUND_POOL_ERROR_INVALID_PARAMETER, "Corrupted " + "sound pool. Sources hash table is NULL"); + + *src = (sound_source_t *)g_hash_table_lookup(pool->sources, tag); + SP_RETVM_IF(!(*src), SOUND_POOL_ERROR_KEY_NOT_AVAILABLE, "Tag doesn't " + "exist in sources hash table"); + + SP_DEBUG_FLEAVE(); + return SOUND_POOL_ERROR_NONE; +} diff --git a/src/stream.c b/src/stream.c new file mode 100644 index 0000000..aa5fa68 --- /dev/null +++ b/src/stream.c @@ -0,0 +1,540 @@ +/* + * 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. + */ + +/** + * @file stream.c + * @brief This file include implementation of protected API + * for the sound streams(OpenAL sources) as part of SoundPool. + */ + +#include "internal/stream.h" +#include "internal/priority.h" + +#include "internal/stream_cb_manager.h" + +#define DEFAULT_STREAM_PRIORITY 255U +#define DEFAULT_STREAM_LOOP 1U +#define DEFAULT_STREAM_VOLUME 1.0f + +static const char *__stringify_stream_state(sound_pool_stream_state_e state); +static void __al_source_state_cb(ALuint source, ALenum state, ALvoid *data); +static int __sound_pool_add_stream(sound_pool_t *pool, sound_stream_t *stream); +static int __sound_pool_remove_stream(sound_pool_t *pool, sound_stream_t *stream); + +static const char *__stringify_stream_state(sound_pool_stream_state_e state) +{ + switch (state) { + case SOUND_POOL_STREAM_STATE_NONE: + return "SOUND_POOL_STREAM_STATE_NONE"; + case SOUND_POOL_STREAM_STATE_PLAYING: + return "SOUND_POOL_STREAM_STATE_PLAYING"; + case SOUND_POOL_STREAM_STATE_PAUSED: + return "SOUND_POOL_STREAM_STATE_PAUSED"; + case SOUND_POOL_STREAM_STATE_SUSPENDED: + return "SOUND_POOL_STREAM_STATE_SUSPENDED"; + case SOUND_POOL_STREAM_STATE_STOPPED: + return "SOUND_POOL_STREAM_STATE_STOPPED"; + case SOUND_POOL_STREAM_STATE_FINISHED: + return "SOUND_POOL_STREAM_STATE_FINISHED"; + default: + return ""; + } +} + +static void __al_source_state_cb(ALuint source, ALenum state, ALvoid *data) +{ + SP_DEBUF_FENTER(); + + sound_stream_t *stream = (sound_stream_t *)data; + SP_RETM_IF(!stream, "Can't handle stream in OpenAL callback, it is NULL"); + sound_pool_t *pool = stream->parent_source->parent_pool; + SP_RETM_IF(!pool, "Can't handle stream in OpenAL callback, stream's sound " + "pool is NULL"); + + stream->state_previous = stream->state; + + switch (state) { + case AL_INITIAL: + stream->state = SOUND_POOL_STREAM_STATE_NONE; + break; + case AL_PLAYING: + stream->state = SOUND_POOL_STREAM_STATE_PLAYING; + break; + case AL_PAUSED: + if (pool->state == SOUND_POOL_STATE_INACTIVE) + stream->state = SOUND_POOL_STREAM_STATE_SUSPENDED; + else if (pool->state == SOUND_POOL_STATE_ACTIVE) + stream->state = SOUND_POOL_STREAM_STATE_PAUSED; + break; + case AL_STOPPED: + if (stream->stopped) + stream->state = SOUND_POOL_STREAM_STATE_STOPPED; + else + stream->state = SOUND_POOL_STREAM_STATE_FINISHED; + break; + default: + SP_ERROR("Invalid OpenAl state value [%#04x]", state); + return; + } + + SP_INFO("Stream [%s:%d] state changed from [%s] to [%s]", + stream->parent_source->tag_name, stream->id, + __stringify_stream_state(stream->state_previous), + __stringify_stream_state(stream->state)); + + SP_RETM_IF(_stream_cb_manager_register_event(pool->cbmgr, stream) != + SOUND_POOL_ERROR_NONE, "State changing event wasn't registered." + "Callbacks will be not called"); + + SP_DEBUG_FLEAVE(); +} + +static int __sound_pool_add_stream(sound_pool_t *pool, sound_stream_t *stream) +{ + SP_DEBUF_FENTER(); + SP_INST_CHECK(pool, SOUND_POOL_ERROR_INVALID_PARAMETER); + SP_INST_CHECK(stream, SOUND_POOL_ERROR_INVALID_PARAMETER); + SP_RETVM_IF(!pool->streams, SOUND_POOL_ERROR_INVALID_OPERATION, "Sound " + "pool to add the stream is corrupted: NULL streams hash table"); + stream->id = ++(pool->max_stream_index); + SP_DEBUG("Id assigned to the stream is [%u]", stream->id); + SP_RETVM_IF(g_hash_table_contains(pool->streams, (gpointer)&stream->id), + SOUND_POOL_ERROR_INVALID_PARAMETER, + "Stream ID already exists in streams hash table."); + SP_RETVM_IF(stream->parent_source->parent_pool != pool, + SOUND_POOL_ERROR_INVALID_OPERATION, "Sound stream can't be added " + "to the pool different to the pool for which sound stream was created"); + + SP_RETVM_IF(!g_hash_table_insert(pool->streams, (gpointer)&stream->id, stream), + SOUND_POOL_ERROR_INVALID_OPERATION, "Error occurred when adding " + "the stream [%u] to the sound pool", stream->id); + + int ret = _sound_stream_priority_add_stream(pool->mgr_priority, stream); + SP_RETVM_IF(SOUND_POOL_ERROR_NONE != ret, ret, "Error occurred when adding " + "the stream [%u] to the priority queue.", stream->id); + + SP_DEBUG_FLEAVE(); + return SOUND_POOL_ERROR_NONE; +} + +static int __sound_pool_remove_stream(sound_pool_t *pool, sound_stream_t *stream) +{ + SP_DEBUF_FENTER(); + SP_INST_CHECK(pool, SOUND_POOL_ERROR_INVALID_PARAMETER); + SP_INST_CHECK(pool->mgr_priority, SOUND_POOL_ERROR_INVALID_PARAMETER); + SP_INST_CHECK(stream, SOUND_POOL_ERROR_INVALID_PARAMETER); + SP_INST_CHECK(stream->parent_source, SOUND_POOL_ERROR_INVALID_PARAMETER); + + if (stream->parent_source->parent_pool == pool) { + if (!g_hash_table_remove(pool->streams, &stream->id) + || SOUND_POOL_ERROR_NONE + != _sound_stream_priority_remove_stream(pool->mgr_priority, + stream)) + SP_DEBUG("Id [%u] doesn't exist in streams hash table", stream->id); + else + SP_INFO("[%u] sound stream was removed from pool", stream->id); + } else { + SP_DEBUG("Stream wasn't removed from sound pool as it isn't known by " + "the pool for which operation is performed"); + } + + SP_DEBUG_FLEAVE(); + return SOUND_POOL_ERROR_NONE; +} + +sound_pool_error_e _sound_stream_create(sound_source_t *src, + sound_stream_t **stream) +{ + SP_DEBUF_FENTER(); + SP_RETVM_IF(!src, SOUND_POOL_ERROR_INVALID_PARAMETER, + "Can't create sound stream in NULL sound source"); + SP_RETVM_IF(!stream, SOUND_POOL_ERROR_INVALID_PARAMETER, + "Can't create sound stream. Stream pointer is NULL"); + SP_RETVM_IF(!src->parent_pool, SOUND_POOL_ERROR_INVALID_PARAMETER, + "Can't create sound stream. Source's pool is NULL"); + + SP_RETVM_IF(!alcMakeContextCurrent(src->parent_pool->al_context), + SOUND_POOL_ERROR_INVALID_OPERATION, "Can't set current context."); + + sound_stream_t *_stream = NULL; + SP_RETVM_IF(!(_stream = g_try_malloc0(sizeof(*_stream))), + SOUND_POOL_ERROR_OUT_OF_MEMORY, + "Memory alloc failure. Can't create sound stream"); + + _stream->parent_source = src; + _stream->priority = DEFAULT_STREAM_PRIORITY; + _stream->loop = DEFAULT_STREAM_LOOP; + _stream->volume = DEFAULT_STREAM_VOLUME; + _stream->state_previous = SOUND_POOL_STREAM_STATE_NONE; + _stream->state = SOUND_POOL_STREAM_STATE_NONE; + _stream->stopped = FALSE; + _stream->state_cb_info.callback = NULL; + _stream->state_cb_info.user_data = NULL; + + int ret = SOUND_POOL_ERROR_NONE; + alGenSources((ALsizei)1, &_stream->al_source); + if (alGetError() != AL_NO_ERROR) { + ret = SOUND_POOL_ERROR_OUT_OF_MEMORY; + GOTO_FAIL("OpenAL error occurred when trying to generate OpenAL Source", + cfail); + } + + alSourcei(_stream->al_source, AL_BUFFER, src->al_buffer); + if (alGetError() != AL_NO_ERROR) { + ret = SOUND_POOL_ERROR_INVALID_OPERATION; + GOTO_FAIL("OpenAL error occurred when trying to assign OpenAL Buffer " + "to OpenAL Source", cfail); + } + + alSourcep(_stream->al_source, AL_SOURCE_STATE_CALLBACK, + (ALvoid *)__al_source_state_cb); + if (alGetError() != AL_NO_ERROR) { + ret = SOUND_POOL_ERROR_INVALID_OPERATION; + GOTO_FAIL("OpenAL error occurred when trying to assign OpenAL Callback " + "to OpenAL Source", cfail); + } + + alSourcep(_stream->al_source, AL_SOURCE_STATE_CALLBACK_DATA, (ALvoid *)_stream); + if (alGetError() != AL_NO_ERROR) { + ret = SOUND_POOL_ERROR_INVALID_OPERATION; + GOTO_FAIL("OpenAL error occurred when trying to assign OpenAL Callback " + "Data to OpenAL Source", cfail); + } + + ret = __sound_pool_add_stream(src->parent_pool, _stream); + if (ret != SOUND_POOL_ERROR_NONE) + GOTO_FAIL("Error occurred when trying to add source to pool", cfail); + + *stream = _stream; + SP_DEBUG_FLEAVE(); + return ret; + +cfail: + _sound_stream_destroy(_stream); + SP_DEBUG_FLEAVE(); + return ret; +} + +sound_pool_error_e _sound_stream_destroy(sound_stream_t *stream) +{ + SP_DEBUF_FENTER(); + SP_RETVM_IF(!stream, SOUND_POOL_ERROR_INVALID_PARAMETER, + "Can't destroy NULL sound stream"); + SP_RETVM_IF(!stream->parent_source->parent_pool, SOUND_POOL_ERROR_INVALID_PARAMETER, + "Empty parent pool pointer."); + + if (stream->parent_source) { + if (__sound_pool_remove_stream(stream->parent_source->parent_pool, + stream) != SOUND_POOL_ERROR_NONE) + SP_DEBUG("Stream[%s] wasn't removed from sound pool. Continue destroying", + stream->parent_source->tag_name); + if (alcMakeContextCurrent(stream->parent_source->parent_pool->al_context)) { + alSourcei(stream->al_source, AL_BUFFER, 0); + alDeleteSources(1, &stream->al_source); + SP_DEBUG("Deleting OpenAL source with id [%u]", stream->al_source); + } else { + SP_DEBUG("Can't set current context for deleting OpenAL source with id [%u]", + stream->al_source); + } + } + + SP_SAFE_GFREE(stream); + + SP_DEBUG_FLEAVE(); + return SOUND_POOL_ERROR_NONE; +} + +sound_pool_error_e _sound_stream_play(sound_stream_t *stream) +{ + SP_DEBUF_FENTER(); + SP_INST_CHECK(stream, SOUND_POOL_ERROR_INVALID_PARAMETER); + SP_INST_CHECK(stream->parent_source, SOUND_POOL_ERROR_INVALID_PARAMETER); + sound_pool_t *pool = stream->parent_source->parent_pool; + SP_INST_CHECK(pool, SOUND_POOL_ERROR_INVALID_PARAMETER); + SP_RETVM_IF(stream->state != SOUND_POOL_STREAM_STATE_SUSPENDED && + stream->state != SOUND_POOL_STREAM_STATE_PAUSED && + stream->state != SOUND_POOL_STREAM_STATE_NONE, + SOUND_POOL_ERROR_INVALID_OPERATION, "Can't play stream[%s] in [%s] " + "state", stream->parent_source->tag_name, __stringify_stream_state(stream->state)); + SP_RETVM_IF(stream->state == SOUND_POOL_STREAM_STATE_SUSPENDED && + pool->state == SOUND_POOL_STATE_INACTIVE, + SOUND_POOL_ERROR_INVALID_OPERATION, "Can't play suspended stream " + "in inactive sound pool"); + + SP_RETVM_IF(!alcMakeContextCurrent(pool->al_context), + SOUND_POOL_ERROR_INVALID_OPERATION, "Can't set current context."); + + if (pool->state == SOUND_POOL_STATE_INACTIVE && + stream->state == SOUND_POOL_STREAM_STATE_NONE) { + stream->state_previous = stream->state; + stream->state = SOUND_POOL_STREAM_STATE_SUSPENDED; + if (_stream_cb_manager_register_event(pool->cbmgr, stream) != + SOUND_POOL_ERROR_NONE) + SP_DEBUG("State changing event wasn't registered." + "Callbacks will be not called"); + SP_DEBUG("Don't play due to SoundPool is in inactive state."); + } else { + alSourcePlay(stream->al_source); + } + + SP_DEBUG_FLEAVE(); + return SOUND_POOL_ERROR_NONE; +} + +sound_pool_error_e _sound_stream_pause(sound_stream_t *stream) +{ + SP_DEBUF_FENTER(); + SP_INST_CHECK(stream, SOUND_POOL_ERROR_INVALID_PARAMETER); + SP_INST_CHECK(stream->parent_source, SOUND_POOL_ERROR_INVALID_PARAMETER); + sound_pool_t *pool = stream->parent_source->parent_pool; + SP_INST_CHECK(pool, SOUND_POOL_ERROR_INVALID_PARAMETER); + SP_RETVM_IF(stream->state != SOUND_POOL_STREAM_STATE_SUSPENDED && + stream->state != SOUND_POOL_STREAM_STATE_PLAYING, + SOUND_POOL_ERROR_INVALID_OPERATION, "Can't pause stream in [%s] " + "state", __stringify_stream_state(stream->state)); + + SP_RETVM_IF(!alcMakeContextCurrent(pool->al_context), + SOUND_POOL_ERROR_INVALID_OPERATION, "Can't set current context."); + + if (pool->state == SOUND_POOL_STATE_INACTIVE && + stream->state == SOUND_POOL_STREAM_STATE_SUSPENDED) { + stream->state_previous = stream->state; + stream->state = SOUND_POOL_STREAM_STATE_PAUSED; + if (_stream_cb_manager_register_event(pool->cbmgr, stream) != + SOUND_POOL_ERROR_NONE) + SP_DEBUG("State changing event wasn't registered." + "Callbacks will be not called"); + SP_DEBUG("Don't paused due to SoundPool is in inactive state."); + } else { + alSourcePause(stream->al_source); + } + + SP_DEBUG_FLEAVE(); + return SOUND_POOL_ERROR_NONE; +} + +sound_pool_error_e _sound_stream_resume(sound_stream_t *stream) +{ + SP_DEBUF_FENTER(); + SP_INST_CHECK(stream, SOUND_POOL_ERROR_INVALID_PARAMETER); + SP_INST_CHECK(stream->parent_source, SOUND_POOL_ERROR_INVALID_PARAMETER); + sound_pool_t *pool = stream->parent_source->parent_pool; + SP_INST_CHECK(pool, SOUND_POOL_ERROR_INVALID_PARAMETER); + SP_RETVM_IF(stream->state != SOUND_POOL_STREAM_STATE_PAUSED, + SOUND_POOL_ERROR_INVALID_OPERATION, "Can't resume stream in [%s] " + "state", __stringify_stream_state(stream->state)); + + SP_RETVM_IF(!alcMakeContextCurrent(pool->al_context), + SOUND_POOL_ERROR_INVALID_OPERATION, "Can't set current context."); + + if (pool->state == SOUND_POOL_STATE_INACTIVE && + stream->state == SOUND_POOL_STREAM_STATE_PAUSED) + { + stream->state_previous = stream->state; + stream->state = SOUND_POOL_STREAM_STATE_SUSPENDED; + if (_stream_cb_manager_register_event(pool->cbmgr, stream) != + SOUND_POOL_ERROR_NONE) + SP_DEBUG("State changing event wasn't registered." + "Callbacks will be not called"); + SP_DEBUG("Don't resumed due to SoundPool is in inactive state."); + } else { + alSourcePlay(stream->al_source); + } + + SP_DEBUG_FLEAVE(); + return SOUND_POOL_ERROR_NONE; +} + +sound_pool_error_e _sound_stream_stop(sound_stream_t *stream) +{ + SP_DEBUF_FENTER(); + SP_INST_CHECK(stream, SOUND_POOL_ERROR_INVALID_PARAMETER); + SP_INST_CHECK(stream->parent_source, SOUND_POOL_ERROR_INVALID_PARAMETER); + sound_pool_t *pool = stream->parent_source->parent_pool; + SP_INST_CHECK(pool, SOUND_POOL_ERROR_INVALID_PARAMETER); + SP_RETVM_IF(stream->state != SOUND_POOL_STREAM_STATE_PLAYING && + stream->state != SOUND_POOL_STREAM_STATE_SUSPENDED && + stream->state != SOUND_POOL_STREAM_STATE_PAUSED, + SOUND_POOL_ERROR_INVALID_OPERATION, "Can't stop stream in [%s] " + "state", __stringify_stream_state(stream->state)); + + SP_RETVM_IF(!alcMakeContextCurrent(pool->al_context), + SOUND_POOL_ERROR_INVALID_OPERATION, "Can't set current context."); + + stream->stopped = TRUE; + alSourceStop(stream->al_source); + + SP_DEBUG_FLEAVE(); + return SOUND_POOL_ERROR_NONE; +} + +sound_pool_error_e _sound_stream_set_loop(sound_stream_t *stream, unsigned loop) +{ + SP_DEBUF_FENTER(); + SP_INST_CHECK(stream, SOUND_POOL_ERROR_INVALID_PARAMETER); + sound_pool_t *pool = stream->parent_source->parent_pool; + SP_INST_CHECK(pool, SOUND_POOL_ERROR_INVALID_PARAMETER); + SP_RETVM_IF(!alcMakeContextCurrent(pool->al_context), + SOUND_POOL_ERROR_INVALID_OPERATION, "Can't set current context."); + + alSourcei(stream->al_source, AL_LOOP_COUNT, (ALint)loop); + stream->loop = loop; + + SP_DEBUG_FLEAVE(); + return SOUND_POOL_ERROR_NONE; +} + +sound_pool_error_e _sound_stream_get_loop(sound_stream_t *stream, unsigned *loop) +{ + SP_DEBUF_FENTER(); + SP_INST_CHECK(stream, SOUND_POOL_ERROR_INVALID_PARAMETER); + SP_INST_CHECK(loop, SOUND_POOL_ERROR_INVALID_PARAMETER); + + *loop = stream->loop; + + SP_DEBUG_FLEAVE(); + return SOUND_POOL_ERROR_NONE; +} + +sound_pool_error_e _sound_stream_set_volume(sound_stream_t *stream, float volume) +{ + SP_DEBUF_FENTER(); + SP_INST_CHECK(stream, SOUND_POOL_ERROR_INVALID_PARAMETER); + SP_RETVM_IF((volume < 0.0f || volume > 1.0f), + SOUND_POOL_ERROR_INVALID_PARAMETER, + "Volume for sound stream should be in range 0.0..1.0."); + sound_pool_t *pool = stream->parent_source->parent_pool; + SP_INST_CHECK(pool, SOUND_POOL_ERROR_INVALID_PARAMETER); + SP_RETVM_IF(!alcMakeContextCurrent(pool->al_context), + SOUND_POOL_ERROR_INVALID_OPERATION, "Can't set current context."); + + alSourcef(stream->al_source, AL_GAIN, volume); + + stream->volume = volume; + + SP_DEBUG_FLEAVE(); + return SOUND_POOL_ERROR_NONE; +} + +sound_pool_error_e _sound_stream_get_volume(sound_stream_t *stream, float *volume) +{ + SP_DEBUF_FENTER(); + SP_INST_CHECK(stream, SOUND_POOL_ERROR_INVALID_PARAMETER); + SP_INST_CHECK(volume, SOUND_POOL_ERROR_INVALID_PARAMETER); + + *volume = stream->volume; + + SP_DEBUG_FLEAVE(); + return SOUND_POOL_ERROR_NONE; +} + +sound_pool_error_e _sound_stream_get_state(sound_stream_t *stream, + sound_pool_stream_state_e *state) +{ + SP_DEBUF_FENTER(); + SP_INST_CHECK(stream, SOUND_POOL_ERROR_INVALID_PARAMETER); + SP_INST_CHECK(state, SOUND_POOL_ERROR_INVALID_PARAMETER); + + *state = stream->state; + + SP_DEBUG_FLEAVE(); + return SOUND_POOL_ERROR_NONE; +} + +sound_pool_error_e _sound_stream_set_priority(sound_stream_t *stream, unsigned rank) +{ + SP_DEBUF_FENTER(); + SP_INST_CHECK(stream, SOUND_POOL_ERROR_INVALID_PARAMETER); + SP_INST_CHECK(stream->parent_source->parent_pool, SOUND_POOL_ERROR_INVALID_PARAMETER); + SP_INST_CHECK(stream->parent_source->parent_pool->mgr_priority, SOUND_POOL_ERROR_INVALID_PARAMETER); + + stream->priority = rank; + if (stream->parent_source->parent_pool->state == SOUND_POOL_STATE_INACTIVE) { + if (stream->state == SOUND_POOL_STREAM_STATE_NONE) { + stream->state_previous = stream->state; + stream->state = SOUND_POOL_STREAM_STATE_SUSPENDED; + if (_stream_cb_manager_register_event( + stream->parent_source->parent_pool->cbmgr, stream) + != SOUND_POOL_ERROR_NONE) + SP_DEBUG( + "State changing event wasn't registered." "Callbacks" + " will be not called"); + } + SP_DEBUG("No need to update priority, Sound pool is INACTIVE."); + return SOUND_POOL_ERROR_NONE; + } + + _sound_stream_priority_update_playback(stream->parent_source->parent_pool->mgr_priority); + + SP_DEBUG_FLEAVE(); + return SOUND_POOL_ERROR_NONE; +} + +sound_pool_error_e _sound_stream_get_priority(sound_stream_t *stream, unsigned *rank) +{ + SP_DEBUF_FENTER(); + SP_INST_CHECK(stream, SOUND_POOL_ERROR_INVALID_PARAMETER); + SP_INST_CHECK(rank, SOUND_POOL_ERROR_INVALID_PARAMETER); + + *rank = stream->priority; + + SP_DEBUG_FLEAVE(); + return SOUND_POOL_ERROR_NONE; +} + +sound_pool_error_e _sound_stream_set_callback(sound_stream_t *stream, + sound_pool_stream_state_change_cb callback, void *data) +{ + SP_DEBUF_FENTER(); + SP_INST_CHECK(stream, SOUND_POOL_ERROR_INVALID_PARAMETER); + SP_INST_CHECK(callback, SOUND_POOL_ERROR_INVALID_PARAMETER); + + stream->state_cb_info.callback = callback; + stream->state_cb_info.user_data = data; + + SP_DEBUG_FLEAVE(); + return SOUND_POOL_ERROR_NONE; +} + +sound_pool_error_e _sound_stream_unset_callback(sound_stream_t *stream) +{ + SP_DEBUF_FENTER(); + SP_INST_CHECK(stream, SOUND_POOL_ERROR_INVALID_PARAMETER); + + stream->state_cb_info.callback = NULL; + stream->state_cb_info.user_data = NULL; + + SP_DEBUG_FLEAVE(); + return SOUND_POOL_ERROR_NONE; +} + +sound_pool_error_e _sound_pool_get_stream_by_id(sound_pool_t *pool, unsigned id, + sound_stream_t **stream) +{ + SP_DEBUF_FENTER(); + SP_INST_CHECK(pool, SOUND_POOL_ERROR_INVALID_PARAMETER); + SP_INST_CHECK(stream, SOUND_POOL_ERROR_INVALID_PARAMETER); + + SP_RETVM_IF(!pool->streams, SOUND_POOL_ERROR_INVALID_OPERATION, "Corrupted " + "sound pool. Sources hash table is NULL"); + + *stream = (sound_stream_t *)g_hash_table_lookup(pool->streams, &id); + SP_RETVM_IF(!(*stream), SOUND_POOL_ERROR_KEY_NOT_AVAILABLE, "Tag doesn't " + "exist in sources hash table"); + + SP_DEBUG_FLEAVE(); + return SOUND_POOL_ERROR_NONE; +} diff --git a/src/stream_cb_manager.c b/src/stream_cb_manager.c new file mode 100644 index 0000000..9e08c2b --- /dev/null +++ b/src/stream_cb_manager.c @@ -0,0 +1,218 @@ +/* + * 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. + */ + +/** + * @file stream_cb_manager.c + * @brief This file include implementation of protected API for the stream + * callback manager as part of SoundPool. + */ + +#include "internal/stream_cb_manager.h" + +static gpointer __sound_pool_callback_isolator(gpointer user_data); +static void __thread_cancel_cleanup(); +static void __queue_destroy_item(gpointer data); + +static void __queue_destroy_item(gpointer data) +{ + SP_DEBUF_FENTER(); + + SP_SAFE_GFREE(data); + + SP_DEBUG_FLEAVE(); +} + +static void __thread_cancel_cleanup(void *user_data) +{ + SP_DEBUF_FENTER(); + + stream_cb_manager_t *cbmgr = (stream_cb_manager_t *)user_data; + g_async_queue_unref(cbmgr->isolator_callback_queue); + pthread_mutex_destroy(&cbmgr->isolator_data_mutex); + pthread_cond_destroy(&cbmgr->isolator_data_cond); + + SP_SAFE_GFREE(cbmgr); + + SP_DEBUG_FLEAVE(); +} + +static gpointer __sound_pool_callback_isolator(gpointer user_data) +{ + SP_DEBUF_FENTER(); + int err = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); + if (err != 0) + SP_INFO("Can't setup cancel type for isolation thread with error [%d].", err); + err = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); + if (err != 0) + SP_INFO("Can't setup cancel state for isolation thread with error [%d].", err); + SP_RETVM_IF(!user_data, NULL, "User data is NULL. Terminate callback thread"); + + stream_cb_manager_t *cbmgr = (stream_cb_manager_t *)user_data; + pthread_cleanup_push(__thread_cancel_cleanup, user_data); + pthread_mutex_lock(&cbmgr->isolator_data_mutex); + gboolean runing = cbmgr->isolator_loop_run; + pthread_mutex_unlock(&cbmgr->isolator_data_mutex); + + while (runing) { + pthread_mutex_lock(&cbmgr->isolator_data_mutex); + while (!cbmgr->isolator_state_changed) + pthread_cond_wait(&cbmgr->isolator_data_cond, &cbmgr->isolator_data_mutex); + pthread_mutex_unlock(&cbmgr->isolator_data_mutex); + + /* Iterate streams have been pushed to the queue and call for each + state changed callback for each stream */ + stream_cb_manager_event_data_t *event_data = NULL; + while ((event_data = (stream_cb_manager_event_data_t *) + g_async_queue_try_pop(cbmgr->isolator_callback_queue))) { + + sound_pool_t* _pool = cbmgr->pool; + if (NULL != event_data->stream->state_cb_info.callback) { + event_data->stream->state_cb_info.callback(_pool, + event_data->stream->parent_source->tag_name, + event_data->stream->id, event_data->state_previous, + event_data->state, + event_data->stream->state_cb_info.user_data); + } + /* If SoundPool final state is FINISHED or STOPPED, then release item */ + if (event_data->state == SOUND_POOL_STREAM_STATE_FINISHED || + event_data->state == SOUND_POOL_STREAM_STATE_STOPPED) + _sound_stream_destroy(event_data->stream); + SP_SAFE_GFREE(event_data); + } + + pthread_mutex_lock(&cbmgr->isolator_data_mutex); + cbmgr->isolator_state_changed = FALSE; + pthread_mutex_unlock(&cbmgr->isolator_data_mutex); + + pthread_mutex_lock(&cbmgr->isolator_data_mutex); + runing = cbmgr->isolator_loop_run; + pthread_mutex_unlock(&cbmgr->isolator_data_mutex); + } + + pthread_cleanup_pop(0); + SP_DEBUG_FLEAVE(); + return NULL; +} + +sound_pool_error_e _stream_cb_manager_create(sound_pool_t *pool, + stream_cb_manager_t **cbmgr) +{ + SP_DEBUF_FENTER(); + SP_RETVM_IF(!pool, SOUND_POOL_ERROR_INVALID_PARAMETER, "Stream callback " + "manager can't be created for NULL sound pool"); + SP_RETVM_IF(!cbmgr, SOUND_POOL_ERROR_INVALID_PARAMETER, "Can't create " + "stream state changing callback manager. Manager pointer is NULL"); + + stream_cb_manager_t *_cbmgr = NULL; + SP_RETVM_IF(!(_cbmgr = g_try_malloc0(sizeof(*_cbmgr))), + SOUND_POOL_ERROR_OUT_OF_MEMORY, + "Memory alloc failure. Can't create stream callback manager"); + + _cbmgr->isolator_callback_queue = g_async_queue_new_full(__queue_destroy_item); + + int err = pthread_mutex_init(&_cbmgr->isolator_data_mutex, NULL); + SP_RETVM_IF(err != 0, SOUND_POOL_ERROR_INVALID_PARAMETER, + "Error while initialize mutex for isolation thread with error[%d]", err); + + _cbmgr->isolator_state_changed = FALSE; + _cbmgr->isolator_loop_run = TRUE; + + err = pthread_cond_init(&_cbmgr->isolator_data_cond, NULL); + SP_RETVM_IF(err != 0, SOUND_POOL_ERROR_INVALID_PARAMETER, + "Error while initialize condition for isolation thread with error[%d]", err); + + err = pthread_create(&_cbmgr->isolator_thread, NULL, &__sound_pool_callback_isolator, (void*)_cbmgr); + SP_RETVM_IF(err != 0, SOUND_POOL_ERROR_OUT_OF_MEMORY, + "Error while thread creating for isolation thread with error[%d]", err); + + _cbmgr->pool = pool; + pool->cbmgr = _cbmgr; + *cbmgr = _cbmgr; + + SP_DEBUG_FLEAVE(); + return SOUND_POOL_ERROR_NONE; +} + +sound_pool_error_e _stream_cb_manager_destroy(stream_cb_manager_t *cbmgr) +{ + SP_DEBUF_FENTER(); + SP_RETVM_IF(!cbmgr, SOUND_POOL_ERROR_INVALID_PARAMETER, "Can't handle callback " + "manager, it is NULL."); + + + pthread_t thread = cbmgr->isolator_thread; + + int err = pthread_kill(thread, 0); + if (0 == err) { + err = pthread_cancel(thread); + if (0 != err) { + SP_ERROR("Error while cancelling of isolation thread[%d].", err); + g_async_queue_unref(cbmgr->isolator_callback_queue); + pthread_mutex_destroy(&cbmgr->isolator_data_mutex); + pthread_cond_destroy(&cbmgr->isolator_data_cond); + SP_SAFE_GFREE(cbmgr); + SP_DEBUG_FLEAVE(); + return SOUND_POOL_ERROR_INVALID_OPERATION; + } + } else { + SP_ERROR("Invalid isolation thread[%d].", err); + g_async_queue_unref(cbmgr->isolator_callback_queue); + pthread_mutex_destroy(&cbmgr->isolator_data_mutex); + pthread_cond_destroy(&cbmgr->isolator_data_cond); + SP_SAFE_GFREE(cbmgr); + SP_DEBUG_FLEAVE(); + return SOUND_POOL_ERROR_INVALID_OPERATION; + } + + void *ret; + err = pthread_join(thread, &ret); + if (0 != err) + SP_ERROR("Error while joining of isolation thread[%d].", err); + if (ret == PTHREAD_CANCELED) + SP_INFO("Isolation thread canceled."); + else + SP_INFO("Routine joining of isolation thread."); + + SP_DEBUG_FLEAVE(); + return SOUND_POOL_ERROR_NONE; +} + +sound_pool_error_e _stream_cb_manager_register_event(stream_cb_manager_t *cbmgr, + sound_stream_t *stream) +{ + SP_DEBUF_FENTER(); + SP_RETVM_IF(!cbmgr, SOUND_POOL_ERROR_INVALID_PARAMETER, + "Can't handle callback manager, it is NULL."); + SP_RETVM_IF(!stream, SOUND_POOL_ERROR_INVALID_PARAMETER, + "Can't handle stream in callback manager, it is NULL."); + + stream_cb_manager_event_data_t *event_data = NULL; + SP_RETVM_IF(!(event_data = g_try_malloc0(sizeof(stream_cb_manager_event_data_t))), + SOUND_POOL_ERROR_OUT_OF_MEMORY, + "Memory alloc failure. Can't create stream callback event data structure."); + event_data->stream = stream; + event_data->state = stream->state; + event_data->state_previous = stream->state_previous; + + g_async_queue_push(cbmgr->isolator_callback_queue, (gpointer)(event_data)); + pthread_mutex_lock(&cbmgr->isolator_data_mutex); + cbmgr->isolator_state_changed = TRUE; + pthread_cond_signal(&cbmgr->isolator_data_cond); + pthread_mutex_unlock(&cbmgr->isolator_data_mutex); + + SP_DEBUG_FLEAVE(); + return SOUND_POOL_ERROR_NONE; +} -- 2.7.4 From b90ef888bff7a79f5efb399b23a151be566706f4 Mon Sep 17 00:00:00 2001 From: "o.danchenko" Date: Thu, 30 Jun 2016 18:59:06 +0300 Subject: [PATCH 05/14] ALURE support has been enabled. Change-Id: Ia708e95d7ec9d377d11959f2d99c9d9d17f770fd --- CMakeLists.txt | 7 ++++ include/sound_pool_private.h | 2 +- packaging/sound-pool.spec | 2 + src/priority.c | 31 ++++++-------- src/sound_pool.c | 99 ++++++++++++++++++++++---------------------- src/soundpool.c | 28 ++++++------- src/source.c | 33 +++++++++++---- src/stream.c | 50 +++++++++++----------- src/stream_cb_manager.c | 52 ++++++++++++----------- 9 files changed, 161 insertions(+), 143 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d34c3c1..f675d3a 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,6 +13,13 @@ INCLUDE_DIRECTORIES(${INC_DIR}) SET(dependents "dlog glib-2.0 openal freealut" ) SET(pc_dependents "dlog glib-2.0 openal freealut" ) +IF(DEFINED ENV{ENABLE_ALURE}) + SET(dependents "${dependents} alure" ) + SET(pc_dependents "${pc_dependents} alure" ) + SET(PKG_CONFIG_CFLAGS "${PKG_CONFIG_CFLAGS} -DENABLE_ALURE") + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -DENABLE_ALURE") +ENDIF() + INCLUDE(FindPkgConfig) pkg_check_modules(${fw_name} REQUIRED ${dependents}) FOREACH(flag ${${fw_name}_CFLAGS}) diff --git a/include/sound_pool_private.h b/include/sound_pool_private.h index 2b3af54..a170d6c 100644 --- a/include/sound_pool_private.h +++ b/include/sound_pool_private.h @@ -78,7 +78,7 @@ extern "C" { ##arg); \ } while (0) -#define SP_DEBUF_FENTER() \ +#define SP_DEBUG_FENTER() \ do { \ LOGD(FONT_COLOR_YELLOW""FONT_COLOR_RESET); \ } while (0) diff --git a/packaging/sound-pool.spec b/packaging/sound-pool.spec index 0f74e31..d4679e5 100644 --- a/packaging/sound-pool.spec +++ b/packaging/sound-pool.spec @@ -12,6 +12,7 @@ BuildRequires: pkgconfig(dlog) BuildRequires: pkgconfig(glib-2.0) BuildRequires: pkgconfig(openal) BuildRequires: pkgconfig(freealut) +#BuildRequires: pkgconfig(alure) %description Tizen Sound Pool Module allowing sounds playing for audio resources. @@ -32,6 +33,7 @@ cp %{SOURCE1001} . export CFLAGS="$CFLAGS -fprofile-arcs -ftest-coverage" export CXXFLAGS="$CXXFLAGS -fprofile-arcs -ftest-coverage" export LDFLAGS="$LDFLAGS -lgcov" +#export ENABLE_ALURE=1 MAJORVER=`echo %{version} | awk 'BEGIN {FS="."}{print $1}'` %cmake . -DCMAKE_INSTALL_PREFIX=%{_prefix} -DFULLVER=%{version} -DMAJORVER=${MAJORVER} diff --git a/src/priority.c b/src/priority.c index 9399567..d8ff7c1 100644 --- a/src/priority.c +++ b/src/priority.c @@ -26,7 +26,7 @@ static gint __stream_stream_proirity_cmp(gconstpointer a, gconstpointer b); static gint __stream_stream_proirity_cmp(gconstpointer a, gconstpointer b) { - SP_DEBUF_FENTER(); + SP_DEBUG_FENTER(); SP_RETVM_IF(!a, 0, "Firs pointer is NULL."); SP_RETVM_IF(!b, 0, "Second pointer is NULL."); sound_stream_t *stream_a = (sound_stream_t *)a; @@ -41,7 +41,7 @@ static gint __stream_stream_proirity_cmp(gconstpointer a, gconstpointer b) sound_pool_error_e _sound_stream_priority_create(sound_pool_t *pool, stream_priority_manager_t **mgr) { - SP_DEBUF_FENTER(); + SP_DEBUG_FENTER(); SP_RETVM_IF(!pool, SOUND_POOL_ERROR_INVALID_PARAMETER, "Stream priority " "manager can't be created for NULL sound pool"); SP_RETVM_IF(!mgr, SOUND_POOL_ERROR_INVALID_PARAMETER, "Can't create " @@ -52,8 +52,6 @@ sound_pool_error_e _sound_stream_priority_create(sound_pool_t *pool, SOUND_POOL_ERROR_OUT_OF_MEMORY, "Memory alloc failure. Can't create stream priority manager."); - int ret = SOUND_POOL_ERROR_NONE; - _mgr->priority_queue = NULL; _mgr->pool = pool; pool->mgr_priority = _mgr; @@ -61,17 +59,15 @@ sound_pool_error_e _sound_stream_priority_create(sound_pool_t *pool, *mgr = _mgr; SP_DEBUG_FLEAVE(); - return ret; + return SOUND_POOL_ERROR_NONE; } sound_pool_error_e _sound_stream_priority_destroy(stream_priority_manager_t *mgr) { - SP_DEBUF_FENTER(); + SP_DEBUG_FENTER(); SP_RETVM_IF(!mgr, SOUND_POOL_ERROR_INVALID_PARAMETER, "Can't handle priority " "manager, it is NULL."); - int ret = SOUND_POOL_ERROR_NONE; - if (mgr->priority_queue) { g_list_free(mgr->priority_queue); mgr->priority_queue = NULL; @@ -82,14 +78,13 @@ sound_pool_error_e _sound_stream_priority_destroy(stream_priority_manager_t *mgr SP_SAFE_GFREE(mgr); SP_DEBUG_FLEAVE(); - return ret; + return SOUND_POOL_ERROR_NONE; } sound_pool_error_e _sound_stream_priority_add_stream( stream_priority_manager_t *mgr, sound_stream_t *stream) { - SP_DEBUF_FENTER(); - int ret = SOUND_POOL_ERROR_NONE; + SP_DEBUG_FENTER(); SP_INST_CHECK(mgr, SOUND_POOL_ERROR_INVALID_PARAMETER); SP_INST_CHECK(stream, SOUND_POOL_ERROR_INVALID_PARAMETER); @@ -97,16 +92,15 @@ sound_pool_error_e _sound_stream_priority_add_stream( _sound_stream_priority_update_playback(mgr); SP_DEBUG_FLEAVE(); - return ret; + return SOUND_POOL_ERROR_NONE; } sound_pool_error_e _sound_stream_priority_remove_stream( stream_priority_manager_t *mgr, sound_stream_t *stream) { - SP_DEBUF_FENTER(); + SP_DEBUG_FENTER(); SP_INST_CHECK(mgr, SOUND_POOL_ERROR_INVALID_PARAMETER); SP_INST_CHECK(stream, SOUND_POOL_ERROR_INVALID_PARAMETER); - int ret = SOUND_POOL_ERROR_NONE; GList* to_delete; to_delete = g_list_find(mgr->priority_queue, (gpointer)stream); @@ -118,13 +112,13 @@ sound_pool_error_e _sound_stream_priority_remove_stream( _sound_stream_priority_update_playback(mgr); SP_DEBUG_FLEAVE(); - return ret; + return SOUND_POOL_ERROR_NONE; } sound_pool_error_e _sound_stream_priority_check(stream_priority_manager_t *mgr, sound_stream_t *stream, gboolean *out) { - SP_DEBUF_FENTER(); + SP_DEBUG_FENTER(); SP_INST_CHECK(mgr, SOUND_POOL_ERROR_INVALID_PARAMETER); SP_INST_CHECK(stream, SOUND_POOL_ERROR_INVALID_PARAMETER); SP_INST_CHECK(out, SOUND_POOL_ERROR_INVALID_PARAMETER); @@ -134,7 +128,6 @@ sound_pool_error_e _sound_stream_priority_check(stream_priority_manager_t *mgr, SP_INST_CHECK(g_hash_table_lookup(mgr->pool->sources, stream->parent_source->tag_name), SOUND_POOL_ERROR_KEY_NOT_AVAILABLE); *out = FALSE; - int ret = SOUND_POOL_ERROR_NONE; int position = g_list_index(mgr->priority_queue, (gconstpointer)stream); SP_RETVM_IF(-1 == position, SOUND_POOL_ERROR_INVALID_PARAMETER, @@ -144,12 +137,12 @@ sound_pool_error_e _sound_stream_priority_check(stream_priority_manager_t *mgr, *out = TRUE; SP_DEBUG_FLEAVE(); - return ret; + return SOUND_POOL_ERROR_NONE; } void _sound_stream_priority_update_playback(stream_priority_manager_t *mgr) { - SP_DEBUF_FENTER(); + SP_DEBUG_FENTER(); SP_RETM_IF(!mgr, "Priority manager pointer is NULL."); SP_RETM_IF(!mgr->pool, "Pool pointer is NULL."); SP_RETM_IF(!mgr->pool->cbmgr, "Callback manager pointer is NULL."); diff --git a/src/sound_pool.c b/src/sound_pool.c index 6236e6e..15a179f 100644 --- a/src/sound_pool.c +++ b/src/sound_pool.c @@ -34,17 +34,17 @@ static unsigned int sound_pool_amount = 0; sound_pool_error_e sound_pool_create(unsigned max_streams, sound_pool_h *pool) { - SP_DEBUF_FENTER(); + SP_DEBUG_FENTER(); SP_RETVM_IF(max_streams == 0, SOUND_POOL_ERROR_INVALID_PARAMETER, "Max streams count should be greater then 0."); - SP_RETVM_IF(SOUND_POOL_MAX_POOLS_AMOUNT < (sound_pool_amount+1), + SP_RETVM_IF(SOUND_POOL_MAX_POOLS_AMOUNT < (sound_pool_amount + 1), SOUND_POOL_ERROR_INVALID_OPERATION, "Max pools count should be no more than %d.", SOUND_POOL_MAX_POOLS_AMOUNT); SP_INST_CHECK(pool, SOUND_POOL_ERROR_INVALID_PARAMETER); sound_pool_t *_pool = NULL; - const int ret = _sound_pool_create(max_streams, &_pool); + sound_pool_error_e ret = _sound_pool_create(max_streams, &_pool); SP_RETVM_IF(ret != SOUND_POOL_ERROR_NONE, ret, "Error while creating sound pool instance."); SP_INST_CHECK(pool, SOUND_POOL_ERROR_INVALID_OPERATION); @@ -59,9 +59,9 @@ sound_pool_error_e sound_pool_create(unsigned max_streams, sound_pool_h *pool) sound_pool_error_e sound_pool_destroy(sound_pool_h pool) { - SP_DEBUF_FENTER(); + SP_DEBUG_FENTER(); - const int ret = _sound_pool_destroy((sound_pool_t *)pool); + sound_pool_error_e ret = _sound_pool_destroy((sound_pool_t *)pool); SP_RETVM_IF(ret != SOUND_POOL_ERROR_NONE, ret, "Error occurred when destroying the sound pool"); --sound_pool_amount; @@ -74,11 +74,11 @@ sound_pool_error_e sound_pool_destroy(sound_pool_h pool) sound_pool_error_e sound_pool_load_source_from_file(sound_pool_h pool, const char *file_name, const char *tag) { - SP_DEBUF_FENTER(); + SP_DEBUG_FENTER(); sound_pool_t *_pool = (sound_pool_t *)pool; sound_source_t *_src = NULL; - int ret = _sound_source_create(_pool, tag, &_src); + sound_pool_error_e ret = _sound_source_create(_pool, tag, &_src); SP_RETVM_IF(ret != SOUND_POOL_ERROR_NONE, ret, "Error while creating sound source instance."); @@ -95,11 +95,11 @@ sound_pool_error_e sound_pool_load_source_from_file(sound_pool_h pool, sound_pool_error_e sound_pool_unload_source(sound_pool_h pool, const char *tag) { - SP_DEBUF_FENTER(); + SP_DEBUG_FENTER(); sound_pool_t *_pool = (sound_pool_t *)pool; sound_source_t *_source = NULL; - int ret = _sound_pool_get_source_by_tag(_pool, tag, &_source); + sound_pool_error_e ret = _sound_pool_get_source_by_tag(_pool, tag, &_source); SP_RETVM_IF(ret != SOUND_POOL_ERROR_NONE, ret, "Error occurred when " "getting sound source [%s] from the sound pool", tag); SP_INST_CHECK(_source, SOUND_POOL_ERROR_INVALID_OPERATION); @@ -116,12 +116,12 @@ sound_pool_error_e sound_pool_stream_play(sound_pool_h pool, const char *tag, unsigned loop, float volume, unsigned priority, sound_pool_stream_state_change_cb callback, void *data, unsigned *id) { - SP_DEBUF_FENTER(); + SP_DEBUG_FENTER(); SP_INST_CHECK(id, SOUND_POOL_ERROR_INVALID_PARAMETER); sound_pool_t *_pool = (sound_pool_t *)pool; sound_source_t *_source = NULL; - int ret = _sound_pool_get_source_by_tag(_pool, tag, &_source); + sound_pool_error_e ret = _sound_pool_get_source_by_tag(_pool, tag, &_source); SP_RETVM_IF(ret != SOUND_POOL_ERROR_NONE, ret, "Error occurred when " "getting sound source [%s] from the sound pool", tag); SP_INST_CHECK(_source, SOUND_POOL_ERROR_INVALID_OPERATION); @@ -157,11 +157,11 @@ sound_pool_error_e sound_pool_stream_play(sound_pool_h pool, const char *tag, sound_pool_error_e sound_pool_stream_pause(sound_pool_h pool, unsigned id) { - SP_DEBUF_FENTER(); + SP_DEBUG_FENTER(); sound_pool_t *_pool = (sound_pool_t *)pool; sound_stream_t *_stream = NULL; - int ret = _sound_pool_get_stream_by_id(_pool, id, &_stream); + sound_pool_error_e ret = _sound_pool_get_stream_by_id(_pool, id, &_stream); SP_RETVM_IF(ret != SOUND_POOL_ERROR_NONE, ret, "Error occurred when " "getting sound stream [%u] from the sound pool", id); SP_INST_CHECK(_stream, SOUND_POOL_ERROR_INVALID_OPERATION); @@ -176,10 +176,10 @@ sound_pool_error_e sound_pool_stream_pause(sound_pool_h pool, unsigned id) sound_pool_error_e sound_pool_stream_resume(sound_pool_h pool, unsigned id) { - SP_DEBUF_FENTER(); + SP_DEBUG_FENTER(); sound_pool_t *_pool = (sound_pool_t *)pool; sound_stream_t *_stream = NULL; - int ret = _sound_pool_get_stream_by_id(_pool, id, &_stream); + sound_pool_error_e ret = _sound_pool_get_stream_by_id(_pool, id, &_stream); SP_RETVM_IF(ret != SOUND_POOL_ERROR_NONE, ret, "Error occurred when " "getting sound stream [%u] from the sound pool", id); SP_INST_CHECK(_stream, SOUND_POOL_ERROR_INVALID_OPERATION); @@ -194,11 +194,11 @@ sound_pool_error_e sound_pool_stream_resume(sound_pool_h pool, unsigned id) sound_pool_error_e sound_pool_stream_stop(sound_pool_h pool, unsigned id) { - SP_DEBUF_FENTER(); + SP_DEBUG_FENTER(); sound_pool_t *_pool = (sound_pool_t *)pool; sound_stream_t *_stream = NULL; - int ret = _sound_pool_get_stream_by_id(_pool, id, &_stream); + sound_pool_error_e ret = _sound_pool_get_stream_by_id(_pool, id, &_stream); SP_RETVM_IF(ret != SOUND_POOL_ERROR_NONE, ret, "Error occurred when " "getting sound stream [%u] from the sound pool", id); SP_INST_CHECK(_stream, SOUND_POOL_ERROR_INVALID_OPERATION); @@ -213,9 +213,9 @@ sound_pool_error_e sound_pool_stream_stop(sound_pool_h pool, unsigned id) sound_pool_error_e sound_pool_get_state(sound_pool_h pool, sound_pool_state_e *state) { - SP_DEBUF_FENTER(); + SP_DEBUG_FENTER(); - const int ret = _sound_pool_get_state(pool, state); + sound_pool_error_e ret = _sound_pool_get_state(pool, state); SP_RETVM_IF(ret != SOUND_POOL_ERROR_NONE, ret, "Error occurred when " "getting state of the sound pool"); @@ -225,9 +225,9 @@ sound_pool_error_e sound_pool_get_state(sound_pool_h pool, sound_pool_state_e *s sound_pool_error_e sound_pool_activate(sound_pool_h pool) { - SP_DEBUF_FENTER(); + SP_DEBUG_FENTER(); - const int ret = _sound_pool_activate((sound_pool_t *)pool); + sound_pool_error_e ret = _sound_pool_activate((sound_pool_t *)pool); SP_RETVM_IF(ret != SOUND_POOL_ERROR_NONE, ret, "Error occurred when " "activating sound pool"); @@ -237,9 +237,9 @@ sound_pool_error_e sound_pool_activate(sound_pool_h pool) sound_pool_error_e sound_pool_deactivate(sound_pool_h pool) { - SP_DEBUF_FENTER(); + SP_DEBUG_FENTER(); - const int ret = _sound_pool_deactivate((sound_pool_t *)pool); + sound_pool_error_e ret = _sound_pool_deactivate((sound_pool_t *)pool); SP_RETVM_IF(ret != SOUND_POOL_ERROR_NONE, ret, "Error occurred when " "deactivating sound pool"); @@ -249,9 +249,9 @@ sound_pool_error_e sound_pool_deactivate(sound_pool_h pool) sound_pool_error_e sound_pool_set_volume(sound_pool_h pool, float volume) { - SP_DEBUF_FENTER(); + SP_DEBUG_FENTER(); - const int ret = _sound_pool_set_volume((sound_pool_t *)pool, volume); + sound_pool_error_e ret = _sound_pool_set_volume((sound_pool_t *)pool, volume); SP_RETVM_IF(ret != SOUND_POOL_ERROR_NONE, ret, "Error occurred when " "setting volume for sound pool"); @@ -261,9 +261,9 @@ sound_pool_error_e sound_pool_set_volume(sound_pool_h pool, float volume) sound_pool_error_e sound_pool_get_volume(sound_pool_h pool, float *volume) { - SP_DEBUF_FENTER(); + SP_DEBUG_FENTER(); - const int ret = _sound_pool_get_volume((sound_pool_t *)pool, volume); + sound_pool_error_e ret = _sound_pool_get_volume((sound_pool_t *)pool, volume); SP_RETVM_IF(ret != SOUND_POOL_ERROR_NONE, ret, "Error occurred when " "getting volume for sound pool"); @@ -274,11 +274,11 @@ sound_pool_error_e sound_pool_get_volume(sound_pool_h pool, float *volume) sound_pool_error_e sound_pool_stream_get_state(sound_pool_h pool, unsigned id, sound_pool_stream_state_e *state) { - SP_DEBUF_FENTER(); + SP_DEBUG_FENTER(); sound_pool_t *_pool = (sound_pool_t *)pool; sound_stream_t *_stream = NULL; - int ret = _sound_pool_get_stream_by_id(_pool, id, &_stream); + sound_pool_error_e ret = _sound_pool_get_stream_by_id(_pool, id, &_stream); SP_RETVM_IF(ret != SOUND_POOL_ERROR_NONE, ret, "Error occurred when " "getting sound stream [%u] from the sound pool", id); SP_INST_CHECK(_stream, SOUND_POOL_ERROR_INVALID_OPERATION); @@ -294,11 +294,11 @@ sound_pool_error_e sound_pool_stream_get_state(sound_pool_h pool, unsigned id, sound_pool_error_e sound_pool_stream_set_loop(sound_pool_h pool, unsigned id, unsigned loop) { - SP_DEBUF_FENTER(); + SP_DEBUG_FENTER(); sound_pool_t *_pool = (sound_pool_t *)pool; sound_stream_t *_stream = NULL; - int ret = _sound_pool_get_stream_by_id(_pool, id, &_stream); + sound_pool_error_e ret = _sound_pool_get_stream_by_id(_pool, id, &_stream); SP_RETVM_IF(ret != SOUND_POOL_ERROR_NONE, ret, "Error occurred when " "getting sound stream [%u] from the sound pool", id); SP_INST_CHECK(_stream, SOUND_POOL_ERROR_INVALID_OPERATION); @@ -314,11 +314,11 @@ sound_pool_error_e sound_pool_stream_set_loop(sound_pool_h pool, unsigned id, sound_pool_error_e sound_pool_stream_get_loop(sound_pool_h pool, unsigned id, unsigned *loop) { - SP_DEBUF_FENTER(); + SP_DEBUG_FENTER(); sound_pool_t *_pool = (sound_pool_t *)pool; sound_stream_t *_stream = NULL; - int ret = _sound_pool_get_stream_by_id(_pool, id, &_stream); + sound_pool_error_e ret = _sound_pool_get_stream_by_id(_pool, id, &_stream); SP_RETVM_IF(ret != SOUND_POOL_ERROR_NONE, ret, "Error occurred when " "getting sound stream [%u] from the sound pool", id); SP_INST_CHECK(_stream, SOUND_POOL_ERROR_INVALID_OPERATION); @@ -334,11 +334,11 @@ sound_pool_error_e sound_pool_stream_get_loop(sound_pool_h pool, unsigned id, sound_pool_error_e sound_pool_stream_set_volume(sound_pool_h pool, unsigned id, float volume) { - SP_DEBUF_FENTER(); + SP_DEBUG_FENTER(); sound_pool_t *_pool = (sound_pool_t *)pool; sound_stream_t *_stream = NULL; - int ret = _sound_pool_get_stream_by_id(_pool, id, &_stream); + sound_pool_error_e ret = _sound_pool_get_stream_by_id(_pool, id, &_stream); SP_RETVM_IF(ret != SOUND_POOL_ERROR_NONE, ret, "Error occurred when " "getting sound stream [%u] from the sound pool", id); SP_INST_CHECK(_stream, SOUND_POOL_ERROR_INVALID_OPERATION); @@ -354,11 +354,11 @@ sound_pool_error_e sound_pool_stream_set_volume(sound_pool_h pool, unsigned id, sound_pool_error_e sound_pool_stream_get_volume(sound_pool_h pool, unsigned id, float *volume) { - SP_DEBUF_FENTER(); + SP_DEBUG_FENTER(); sound_pool_t *_pool = (sound_pool_t *)pool; sound_stream_t *_stream = NULL; - int ret = _sound_pool_get_stream_by_id(_pool, id, &_stream); + sound_pool_error_e ret = _sound_pool_get_stream_by_id(_pool, id, &_stream); SP_RETVM_IF(ret != SOUND_POOL_ERROR_NONE, ret, "Error occurred when " "getting sound stream [%u] from the sound pool", id); SP_INST_CHECK(_stream, SOUND_POOL_ERROR_INVALID_OPERATION); @@ -374,11 +374,11 @@ sound_pool_error_e sound_pool_stream_get_volume(sound_pool_h pool, unsigned id, sound_pool_error_e sound_pool_stream_set_priority(sound_pool_h pool, unsigned id, unsigned priority) { - SP_DEBUF_FENTER(); + SP_DEBUG_FENTER(); sound_pool_t *_pool = (sound_pool_t *)pool; sound_stream_t *_stream = NULL; - int ret = _sound_pool_get_stream_by_id(_pool, id, &_stream); + sound_pool_error_e ret = _sound_pool_get_stream_by_id(_pool, id, &_stream); SP_RETVM_IF(ret != SOUND_POOL_ERROR_NONE, ret, "Error occurred when " "getting sound stream [%u] from the sound pool", id); SP_INST_CHECK(_stream, SOUND_POOL_ERROR_INVALID_OPERATION); @@ -394,11 +394,11 @@ sound_pool_error_e sound_pool_stream_set_priority(sound_pool_h pool, sound_pool_error_e sound_pool_stream_get_priority(sound_pool_h pool, unsigned id, unsigned *priority) { - SP_DEBUF_FENTER(); + SP_DEBUG_FENTER(); sound_pool_t *_pool = (sound_pool_t *)pool; sound_stream_t *_stream = NULL; - int ret = _sound_pool_get_stream_by_id(_pool, id, &_stream); + sound_pool_error_e ret = _sound_pool_get_stream_by_id(_pool, id, &_stream); SP_RETVM_IF(ret != SOUND_POOL_ERROR_NONE, ret, "Error occurred when " "getting sound stream [%u] from the sound pool", id); SP_INST_CHECK(_stream, SOUND_POOL_ERROR_INVALID_OPERATION); @@ -414,10 +414,9 @@ sound_pool_error_e sound_pool_stream_get_priority(sound_pool_h pool, sound_pool_error_e sound_pool_set_state_change_callback(sound_pool_h pool, sound_pool_state_change_cb callback, void *data) { - SP_DEBUF_FENTER(); + SP_DEBUG_FENTER(); - const int ret = - _sound_pool_set_callback((sound_pool_t *)pool, callback, data); + sound_pool_error_e ret = _sound_pool_set_callback((sound_pool_t *)pool, callback, data); SP_RETVM_IF(ret != SOUND_POOL_ERROR_NONE, ret, "Error occurred when " "setting state changing callback for sound pool"); @@ -427,9 +426,9 @@ sound_pool_error_e sound_pool_set_state_change_callback(sound_pool_h pool, sound_pool_error_e sound_pool_unset_state_change_callback(sound_pool_h pool) { - SP_DEBUF_FENTER(); + SP_DEBUG_FENTER(); - const int ret = _sound_pool_unset_callback((sound_pool_t *)pool); + sound_pool_error_e ret = _sound_pool_unset_callback((sound_pool_t *)pool); SP_RETVM_IF(ret != SOUND_POOL_ERROR_NONE, ret, "Error occurred when " "unsetting state changing callback for sound pool"); @@ -441,11 +440,11 @@ sound_pool_error_e sound_pool_stream_set_state_change_callback( sound_pool_h pool, unsigned id, sound_pool_stream_state_change_cb callback, void *data) { - SP_DEBUF_FENTER(); + SP_DEBUG_FENTER(); sound_pool_t *_pool = (sound_pool_t *)pool; sound_stream_t *_stream = NULL; - int ret = _sound_pool_get_stream_by_id(_pool, id, &_stream); + sound_pool_error_e ret = _sound_pool_get_stream_by_id(_pool, id, &_stream); SP_RETVM_IF(ret != SOUND_POOL_ERROR_NONE, ret, "Error occurred when " "getting sound stream [%u] from the sound pool", id); SP_INST_CHECK(_stream, SOUND_POOL_ERROR_INVALID_OPERATION); @@ -461,11 +460,11 @@ sound_pool_error_e sound_pool_stream_set_state_change_callback( sound_pool_error_e sound_pool_stream_unset_state_change_callback( sound_pool_h pool, unsigned id) { - SP_DEBUF_FENTER(); + SP_DEBUG_FENTER(); sound_pool_t *_pool = (sound_pool_t *)pool; sound_stream_t *_stream = NULL; - int ret = _sound_pool_get_stream_by_id(_pool, id, &_stream); + sound_pool_error_e ret = _sound_pool_get_stream_by_id(_pool, id, &_stream); SP_RETVM_IF(ret != SOUND_POOL_ERROR_NONE, ret, "Error occurred when " "getting sound stream [%u] from the sound pool", id); SP_INST_CHECK(_stream, SOUND_POOL_ERROR_INVALID_OPERATION); diff --git a/src/soundpool.c b/src/soundpool.c index 631a3aa..faa6fcc 100644 --- a/src/soundpool.c +++ b/src/soundpool.c @@ -38,7 +38,7 @@ static void __stream_deactivate_iter(gpointer key, gpointer value, static void __stream_activate_iter(gpointer key, gpointer value, gpointer user_data) { - SP_DEBUF_FENTER(); + SP_DEBUG_FENTER(); SP_RETM_IF(!user_data, "Empty user data."); SP_RETM_IF(!value, "Empty sound stream data."); guint *len = (guint*)user_data; @@ -59,7 +59,7 @@ static void __stream_activate_iter(gpointer key, gpointer value, static void __stream_deactivate_iter(gpointer key, gpointer value, gpointer user_data) { - SP_DEBUF_FENTER(); + SP_DEBUG_FENTER(); SP_RETM_IF(!user_data, "Empty user data."); SP_RETM_IF(!value, "Empty sound stream data."); guint *len = (guint*)user_data; @@ -75,7 +75,7 @@ static void __stream_deactivate_iter(gpointer key, gpointer value, sound_pool_error_e _sound_pool_create(size_t max_streams, sound_pool_t **pool) { - SP_DEBUF_FENTER(); + SP_DEBUG_FENTER(); SP_RETVM_IF(max_streams == 0, SOUND_POOL_ERROR_INVALID_PARAMETER, "Max streams count should be greater than 0."); @@ -86,7 +86,7 @@ sound_pool_error_e _sound_pool_create(size_t max_streams, sound_pool_t **pool) SP_RETVM_IF(!pool, SOUND_POOL_ERROR_INVALID_PARAMETER, "Can't create " "sound pool. Pool pointer is NULL"); - int ret = SOUND_POOL_ERROR_NONE; + sound_pool_error_e ret = SOUND_POOL_ERROR_NONE; _pool->al_context = NULL; _pool->al_context = alcCreateContext(alcOpenDevice(NULL), NULL); if (!_pool->al_context) { @@ -141,12 +141,12 @@ cfail: sound_pool_error_e _sound_pool_destroy(sound_pool_t *pool) { - SP_DEBUF_FENTER(); + SP_DEBUG_FENTER(); SP_INST_CHECK(pool, SOUND_POOL_ERROR_INVALID_PARAMETER); _sound_pool_deactivate(pool); if (pool->cbmgr) { - const int ret = _stream_cb_manager_destroy(pool->cbmgr); + sound_pool_error_e ret = _stream_cb_manager_destroy(pool->cbmgr); SP_RETVM_IF(ret != SOUND_POOL_ERROR_NONE, ret, "Error occurred when " "trying to destroy sound pool callback manager."); pool->cbmgr = NULL; @@ -173,7 +173,7 @@ sound_pool_error_e _sound_pool_destroy(sound_pool_t *pool) } if (pool->mgr_priority) { - const int ret = _sound_stream_priority_destroy(pool->mgr_priority); + sound_pool_error_e ret = _sound_stream_priority_destroy(pool->mgr_priority); SP_RETVM_IF(ret != SOUND_POOL_ERROR_NONE, ret, "Error occurred when trying to destroy priority manager."); pool->mgr_priority = NULL; @@ -194,7 +194,7 @@ sound_pool_error_e _sound_pool_destroy(sound_pool_t *pool) sound_pool_error_e _sound_pool_activate(sound_pool_t *pool) { - SP_DEBUF_FENTER(); + SP_DEBUG_FENTER(); SP_INST_CHECK(pool, SOUND_POOL_ERROR_INVALID_PARAMETER); SP_RETVM_IF(pool->state == SOUND_POOL_STATE_ACTIVE, @@ -229,7 +229,7 @@ sound_pool_error_e _sound_pool_activate(sound_pool_t *pool) sound_pool_error_e _sound_pool_deactivate(sound_pool_t *pool) { - SP_DEBUF_FENTER(); + SP_DEBUG_FENTER(); SP_INST_CHECK(pool, SOUND_POOL_ERROR_INVALID_PARAMETER); SP_RETVM_IF(pool->state == SOUND_POOL_STATE_INACTIVE, SOUND_POOL_ERROR_INVALID_OPERATION, @@ -264,7 +264,7 @@ sound_pool_error_e _sound_pool_deactivate(sound_pool_t *pool) sound_pool_error_e _sound_pool_get_state(sound_pool_t *pool, sound_pool_state_e *state) { - SP_DEBUF_FENTER(); + SP_DEBUG_FENTER(); SP_INST_CHECK(pool, SOUND_POOL_ERROR_INVALID_PARAMETER); SP_INST_CHECK(state, SOUND_POOL_ERROR_INVALID_PARAMETER); *state = pool->state; @@ -274,7 +274,7 @@ sound_pool_error_e _sound_pool_get_state(sound_pool_t *pool, sound_pool_error_e _sound_pool_set_volume(sound_pool_t *pool, float volume) { - SP_DEBUF_FENTER(); + SP_DEBUG_FENTER(); SP_INST_CHECK(pool, SOUND_POOL_ERROR_INVALID_PARAMETER); SP_RETVM_IF((volume < 0.0f || volume > 1.0f), SOUND_POOL_ERROR_INVALID_PARAMETER, @@ -291,7 +291,7 @@ sound_pool_error_e _sound_pool_set_volume(sound_pool_t *pool, float volume) sound_pool_error_e _sound_pool_get_volume(sound_pool_t *pool, float *volume) { - SP_DEBUF_FENTER(); + SP_DEBUG_FENTER(); SP_INST_CHECK(pool, SOUND_POOL_ERROR_INVALID_PARAMETER); SP_INST_CHECK(volume, SOUND_POOL_ERROR_INVALID_PARAMETER); *volume = pool->volume; @@ -302,7 +302,7 @@ sound_pool_error_e _sound_pool_get_volume(sound_pool_t *pool, float *volume) sound_pool_error_e _sound_pool_set_callback(sound_pool_t *pool, sound_pool_state_change_cb callback, void *data) { - SP_DEBUF_FENTER(); + SP_DEBUG_FENTER(); SP_INST_CHECK(pool, SOUND_POOL_ERROR_INVALID_PARAMETER); SP_INST_CHECK(callback, SOUND_POOL_ERROR_INVALID_PARAMETER); @@ -315,7 +315,7 @@ sound_pool_error_e _sound_pool_set_callback(sound_pool_t *pool, sound_pool_error_e _sound_pool_unset_callback(sound_pool_t *pool) { - SP_DEBUF_FENTER(); + SP_DEBUG_FENTER(); SP_INST_CHECK(pool, SOUND_POOL_ERROR_INVALID_PARAMETER); pool->state_cb_info.callback = NULL; diff --git a/src/source.c b/src/source.c index d9584dd..c67c2a2 100644 --- a/src/source.c +++ b/src/source.c @@ -24,13 +24,16 @@ #include "internal/stream.h" #include +#ifdef ENABLE_ALURE +# include +#endif static int __sound_pool_add_source(sound_pool_t *pool, sound_source_t *src); static int __sound_pool_remove_source(sound_pool_t *pool, sound_source_t *src); static int __sound_pool_add_source(sound_pool_t *pool, sound_source_t *src) { - SP_DEBUF_FENTER(); + SP_DEBUG_FENTER(); SP_INST_CHECK(pool, SOUND_POOL_ERROR_INVALID_PARAMETER); SP_INST_CHECK(src, SOUND_POOL_ERROR_INVALID_PARAMETER); SP_RETVM_IF(!pool->sources, SOUND_POOL_ERROR_INVALID_OPERATION, "Sound " @@ -54,7 +57,7 @@ static int __sound_pool_add_source(sound_pool_t *pool, sound_source_t *src) static int __sound_pool_remove_source(sound_pool_t *pool, sound_source_t *src) { - SP_DEBUF_FENTER(); + SP_DEBUG_FENTER(); SP_INST_CHECK(pool, SOUND_POOL_ERROR_INVALID_PARAMETER); SP_INST_CHECK(pool->sources, SOUND_POOL_ERROR_INVALID_PARAMETER); SP_INST_CHECK(src, SOUND_POOL_ERROR_INVALID_PARAMETER); @@ -73,7 +76,6 @@ static int __sound_pool_remove_source(sound_pool_t *pool, sound_source_t *src) guint size_before = g_hash_table_size(pool->streams); gchar *tag = (gchar*)key; sound_stream_t *stream = (sound_stream_t*)value; - SP_INFO("(%s)(%s)", src->tag_name, stream->parent_source->tag_name); if (src == stream->parent_source) _sound_stream_destroy((sound_stream_t*)value); guint size_after = g_hash_table_size(pool->streams); @@ -92,7 +94,7 @@ static int __sound_pool_remove_source(sound_pool_t *pool, sound_source_t *src) sound_pool_error_e _sound_source_create(sound_pool_t *pool, const char *tag, sound_source_t **src) { - SP_DEBUF_FENTER(); + SP_DEBUG_FENTER(); SP_RETVM_IF(!pool, SOUND_POOL_ERROR_INVALID_PARAMETER, "Can't create sound source in NULL sound pool"); SP_RETVM_IF(!tag, SOUND_POOL_ERROR_INVALID_PARAMETER, @@ -117,7 +119,7 @@ sound_pool_error_e _sound_source_create(sound_pool_t *pool, const char *tag, SOUND_POOL_ERROR_OUT_OF_MEMORY, "Memory alloc failure. Can't create sound _src"); - int ret = SOUND_POOL_ERROR_NONE; + sound_pool_error_e ret = SOUND_POOL_ERROR_NONE; alGenBuffers(1, &_src->al_buffer); if (alGetError() != AL_NO_ERROR) { ret = SOUND_POOL_ERROR_OUT_OF_MEMORY; @@ -146,7 +148,7 @@ cfail: sound_pool_error_e _sound_source_destroy(sound_source_t *src) { - SP_DEBUF_FENTER(); + SP_DEBUG_FENTER(); SP_RETVM_IF(!src, SOUND_POOL_ERROR_INVALID_PARAMETER, "Can't destroy NULL sound source"); @@ -168,14 +170,14 @@ sound_pool_error_e _sound_source_destroy(sound_source_t *src) sound_pool_error_e _sound_source_load_from_file(sound_source_t *src, const char *fname) { - SP_DEBUF_FENTER(); + SP_DEBUG_FENTER(); SP_INST_CHECK(src, SOUND_POOL_ERROR_INVALID_PARAMETER); SP_INST_CHECK(fname, SOUND_POOL_ERROR_INVALID_PARAMETER); SP_INST_CHECK(src->parent_pool, SOUND_POOL_ERROR_INVALID_OPERATION); SP_RETVM_IF(!alcMakeContextCurrent(src->parent_pool->al_context), SOUND_POOL_ERROR_INVALID_OPERATION, "Can't set current AL context."); - int ret = SOUND_POOL_ERROR_NONE; + sound_pool_error_e ret = SOUND_POOL_ERROR_NONE; ALenum format; ALsizei size; ALvoid* data = NULL; @@ -183,9 +185,22 @@ sound_pool_error_e _sound_source_load_from_file(sound_source_t *src, ALboolean loop; alutLoadWAVFile((ALbyte*)fname, &format, &data, &size, &freq, &loop); + +#ifdef ENABLE_ALURE + if (alGetError() != AL_NO_ERROR || !data) { + if (alureBufferDataFromFile(fname, src->al_buffer) == AL_FALSE) { + src->al_buffer = AL_NONE; + SP_ERROR("Can't load audio file. No such file [%s]", fname); + ret = SOUND_POOL_ERROR_NO_SUCH_FILE; + } + SP_DEBUG_FLEAVE(); + return ret; + } +#else SP_RETVM_IF(alGetError() != AL_NO_ERROR || !data, SOUND_POOL_ERROR_NO_SUCH_FILE, "Can't load audio file. No such " "file [%s]", fname); +#endif alBufferData(src->al_buffer, format, data, size, freq); if (alGetError() != AL_NO_ERROR) { @@ -202,7 +217,7 @@ sound_pool_error_e _sound_source_load_from_file(sound_source_t *src, sound_pool_error_e _sound_pool_get_source_by_tag(sound_pool_t *pool, const char *tag, sound_source_t **src) { - SP_DEBUF_FENTER(); + SP_DEBUG_FENTER(); SP_INST_CHECK(pool, SOUND_POOL_ERROR_INVALID_PARAMETER); SP_INST_CHECK(tag, SOUND_POOL_ERROR_INVALID_PARAMETER); SP_INST_CHECK(src, SOUND_POOL_ERROR_INVALID_PARAMETER); diff --git a/src/stream.c b/src/stream.c index aa5fa68..d2bb663 100644 --- a/src/stream.c +++ b/src/stream.c @@ -31,8 +31,8 @@ static const char *__stringify_stream_state(sound_pool_stream_state_e state); static void __al_source_state_cb(ALuint source, ALenum state, ALvoid *data); -static int __sound_pool_add_stream(sound_pool_t *pool, sound_stream_t *stream); -static int __sound_pool_remove_stream(sound_pool_t *pool, sound_stream_t *stream); +static sound_pool_error_e __sound_pool_add_stream(sound_pool_t *pool, sound_stream_t *stream); +static sound_pool_error_e __sound_pool_remove_stream(sound_pool_t *pool, sound_stream_t *stream); static const char *__stringify_stream_state(sound_pool_stream_state_e state) { @@ -56,7 +56,7 @@ static const char *__stringify_stream_state(sound_pool_stream_state_e state) static void __al_source_state_cb(ALuint source, ALenum state, ALvoid *data) { - SP_DEBUF_FENTER(); + SP_DEBUG_FENTER(); sound_stream_t *stream = (sound_stream_t *)data; SP_RETM_IF(!stream, "Can't handle stream in OpenAL callback, it is NULL"); @@ -102,9 +102,9 @@ static void __al_source_state_cb(ALuint source, ALenum state, ALvoid *data) SP_DEBUG_FLEAVE(); } -static int __sound_pool_add_stream(sound_pool_t *pool, sound_stream_t *stream) +static sound_pool_error_e __sound_pool_add_stream(sound_pool_t *pool, sound_stream_t *stream) { - SP_DEBUF_FENTER(); + SP_DEBUG_FENTER(); SP_INST_CHECK(pool, SOUND_POOL_ERROR_INVALID_PARAMETER); SP_INST_CHECK(stream, SOUND_POOL_ERROR_INVALID_PARAMETER); SP_RETVM_IF(!pool->streams, SOUND_POOL_ERROR_INVALID_OPERATION, "Sound " @@ -122,7 +122,7 @@ static int __sound_pool_add_stream(sound_pool_t *pool, sound_stream_t *stream) SOUND_POOL_ERROR_INVALID_OPERATION, "Error occurred when adding " "the stream [%u] to the sound pool", stream->id); - int ret = _sound_stream_priority_add_stream(pool->mgr_priority, stream); + sound_pool_error_e ret = _sound_stream_priority_add_stream(pool->mgr_priority, stream); SP_RETVM_IF(SOUND_POOL_ERROR_NONE != ret, ret, "Error occurred when adding " "the stream [%u] to the priority queue.", stream->id); @@ -130,9 +130,9 @@ static int __sound_pool_add_stream(sound_pool_t *pool, sound_stream_t *stream) return SOUND_POOL_ERROR_NONE; } -static int __sound_pool_remove_stream(sound_pool_t *pool, sound_stream_t *stream) +static sound_pool_error_e __sound_pool_remove_stream(sound_pool_t *pool, sound_stream_t *stream) { - SP_DEBUF_FENTER(); + SP_DEBUG_FENTER(); SP_INST_CHECK(pool, SOUND_POOL_ERROR_INVALID_PARAMETER); SP_INST_CHECK(pool->mgr_priority, SOUND_POOL_ERROR_INVALID_PARAMETER); SP_INST_CHECK(stream, SOUND_POOL_ERROR_INVALID_PARAMETER); @@ -158,7 +158,7 @@ static int __sound_pool_remove_stream(sound_pool_t *pool, sound_stream_t *stream sound_pool_error_e _sound_stream_create(sound_source_t *src, sound_stream_t **stream) { - SP_DEBUF_FENTER(); + SP_DEBUG_FENTER(); SP_RETVM_IF(!src, SOUND_POOL_ERROR_INVALID_PARAMETER, "Can't create sound stream in NULL sound source"); SP_RETVM_IF(!stream, SOUND_POOL_ERROR_INVALID_PARAMETER, @@ -184,7 +184,7 @@ sound_pool_error_e _sound_stream_create(sound_source_t *src, _stream->state_cb_info.callback = NULL; _stream->state_cb_info.user_data = NULL; - int ret = SOUND_POOL_ERROR_NONE; + sound_pool_error_e ret = SOUND_POOL_ERROR_NONE; alGenSources((ALsizei)1, &_stream->al_source); if (alGetError() != AL_NO_ERROR) { ret = SOUND_POOL_ERROR_OUT_OF_MEMORY; @@ -230,7 +230,7 @@ cfail: sound_pool_error_e _sound_stream_destroy(sound_stream_t *stream) { - SP_DEBUF_FENTER(); + SP_DEBUG_FENTER(); SP_RETVM_IF(!stream, SOUND_POOL_ERROR_INVALID_PARAMETER, "Can't destroy NULL sound stream"); SP_RETVM_IF(!stream->parent_source->parent_pool, SOUND_POOL_ERROR_INVALID_PARAMETER, @@ -259,7 +259,7 @@ sound_pool_error_e _sound_stream_destroy(sound_stream_t *stream) sound_pool_error_e _sound_stream_play(sound_stream_t *stream) { - SP_DEBUF_FENTER(); + SP_DEBUG_FENTER(); SP_INST_CHECK(stream, SOUND_POOL_ERROR_INVALID_PARAMETER); SP_INST_CHECK(stream->parent_source, SOUND_POOL_ERROR_INVALID_PARAMETER); sound_pool_t *pool = stream->parent_source->parent_pool; @@ -296,7 +296,7 @@ sound_pool_error_e _sound_stream_play(sound_stream_t *stream) sound_pool_error_e _sound_stream_pause(sound_stream_t *stream) { - SP_DEBUF_FENTER(); + SP_DEBUG_FENTER(); SP_INST_CHECK(stream, SOUND_POOL_ERROR_INVALID_PARAMETER); SP_INST_CHECK(stream->parent_source, SOUND_POOL_ERROR_INVALID_PARAMETER); sound_pool_t *pool = stream->parent_source->parent_pool; @@ -328,7 +328,7 @@ sound_pool_error_e _sound_stream_pause(sound_stream_t *stream) sound_pool_error_e _sound_stream_resume(sound_stream_t *stream) { - SP_DEBUF_FENTER(); + SP_DEBUG_FENTER(); SP_INST_CHECK(stream, SOUND_POOL_ERROR_INVALID_PARAMETER); SP_INST_CHECK(stream->parent_source, SOUND_POOL_ERROR_INVALID_PARAMETER); sound_pool_t *pool = stream->parent_source->parent_pool; @@ -360,7 +360,7 @@ sound_pool_error_e _sound_stream_resume(sound_stream_t *stream) sound_pool_error_e _sound_stream_stop(sound_stream_t *stream) { - SP_DEBUF_FENTER(); + SP_DEBUG_FENTER(); SP_INST_CHECK(stream, SOUND_POOL_ERROR_INVALID_PARAMETER); SP_INST_CHECK(stream->parent_source, SOUND_POOL_ERROR_INVALID_PARAMETER); sound_pool_t *pool = stream->parent_source->parent_pool; @@ -383,7 +383,7 @@ sound_pool_error_e _sound_stream_stop(sound_stream_t *stream) sound_pool_error_e _sound_stream_set_loop(sound_stream_t *stream, unsigned loop) { - SP_DEBUF_FENTER(); + SP_DEBUG_FENTER(); SP_INST_CHECK(stream, SOUND_POOL_ERROR_INVALID_PARAMETER); sound_pool_t *pool = stream->parent_source->parent_pool; SP_INST_CHECK(pool, SOUND_POOL_ERROR_INVALID_PARAMETER); @@ -399,7 +399,7 @@ sound_pool_error_e _sound_stream_set_loop(sound_stream_t *stream, unsigned loop) sound_pool_error_e _sound_stream_get_loop(sound_stream_t *stream, unsigned *loop) { - SP_DEBUF_FENTER(); + SP_DEBUG_FENTER(); SP_INST_CHECK(stream, SOUND_POOL_ERROR_INVALID_PARAMETER); SP_INST_CHECK(loop, SOUND_POOL_ERROR_INVALID_PARAMETER); @@ -411,7 +411,7 @@ sound_pool_error_e _sound_stream_get_loop(sound_stream_t *stream, unsigned *loop sound_pool_error_e _sound_stream_set_volume(sound_stream_t *stream, float volume) { - SP_DEBUF_FENTER(); + SP_DEBUG_FENTER(); SP_INST_CHECK(stream, SOUND_POOL_ERROR_INVALID_PARAMETER); SP_RETVM_IF((volume < 0.0f || volume > 1.0f), SOUND_POOL_ERROR_INVALID_PARAMETER, @@ -431,7 +431,7 @@ sound_pool_error_e _sound_stream_set_volume(sound_stream_t *stream, float volume sound_pool_error_e _sound_stream_get_volume(sound_stream_t *stream, float *volume) { - SP_DEBUF_FENTER(); + SP_DEBUG_FENTER(); SP_INST_CHECK(stream, SOUND_POOL_ERROR_INVALID_PARAMETER); SP_INST_CHECK(volume, SOUND_POOL_ERROR_INVALID_PARAMETER); @@ -444,7 +444,7 @@ sound_pool_error_e _sound_stream_get_volume(sound_stream_t *stream, float *volum sound_pool_error_e _sound_stream_get_state(sound_stream_t *stream, sound_pool_stream_state_e *state) { - SP_DEBUF_FENTER(); + SP_DEBUG_FENTER(); SP_INST_CHECK(stream, SOUND_POOL_ERROR_INVALID_PARAMETER); SP_INST_CHECK(state, SOUND_POOL_ERROR_INVALID_PARAMETER); @@ -456,7 +456,7 @@ sound_pool_error_e _sound_stream_get_state(sound_stream_t *stream, sound_pool_error_e _sound_stream_set_priority(sound_stream_t *stream, unsigned rank) { - SP_DEBUF_FENTER(); + SP_DEBUG_FENTER(); SP_INST_CHECK(stream, SOUND_POOL_ERROR_INVALID_PARAMETER); SP_INST_CHECK(stream->parent_source->parent_pool, SOUND_POOL_ERROR_INVALID_PARAMETER); SP_INST_CHECK(stream->parent_source->parent_pool->mgr_priority, SOUND_POOL_ERROR_INVALID_PARAMETER); @@ -485,7 +485,7 @@ sound_pool_error_e _sound_stream_set_priority(sound_stream_t *stream, unsigned r sound_pool_error_e _sound_stream_get_priority(sound_stream_t *stream, unsigned *rank) { - SP_DEBUF_FENTER(); + SP_DEBUG_FENTER(); SP_INST_CHECK(stream, SOUND_POOL_ERROR_INVALID_PARAMETER); SP_INST_CHECK(rank, SOUND_POOL_ERROR_INVALID_PARAMETER); @@ -498,7 +498,7 @@ sound_pool_error_e _sound_stream_get_priority(sound_stream_t *stream, unsigned * sound_pool_error_e _sound_stream_set_callback(sound_stream_t *stream, sound_pool_stream_state_change_cb callback, void *data) { - SP_DEBUF_FENTER(); + SP_DEBUG_FENTER(); SP_INST_CHECK(stream, SOUND_POOL_ERROR_INVALID_PARAMETER); SP_INST_CHECK(callback, SOUND_POOL_ERROR_INVALID_PARAMETER); @@ -511,7 +511,7 @@ sound_pool_error_e _sound_stream_set_callback(sound_stream_t *stream, sound_pool_error_e _sound_stream_unset_callback(sound_stream_t *stream) { - SP_DEBUF_FENTER(); + SP_DEBUG_FENTER(); SP_INST_CHECK(stream, SOUND_POOL_ERROR_INVALID_PARAMETER); stream->state_cb_info.callback = NULL; @@ -524,7 +524,7 @@ sound_pool_error_e _sound_stream_unset_callback(sound_stream_t *stream) sound_pool_error_e _sound_pool_get_stream_by_id(sound_pool_t *pool, unsigned id, sound_stream_t **stream) { - SP_DEBUF_FENTER(); + SP_DEBUG_FENTER(); SP_INST_CHECK(pool, SOUND_POOL_ERROR_INVALID_PARAMETER); SP_INST_CHECK(stream, SOUND_POOL_ERROR_INVALID_PARAMETER); diff --git a/src/stream_cb_manager.c b/src/stream_cb_manager.c index 9e08c2b..329b022 100644 --- a/src/stream_cb_manager.c +++ b/src/stream_cb_manager.c @@ -28,7 +28,7 @@ static void __queue_destroy_item(gpointer data); static void __queue_destroy_item(gpointer data) { - SP_DEBUF_FENTER(); + SP_DEBUG_FENTER(); SP_SAFE_GFREE(data); @@ -37,7 +37,7 @@ static void __queue_destroy_item(gpointer data) static void __thread_cancel_cleanup(void *user_data) { - SP_DEBUF_FENTER(); + SP_DEBUG_FENTER(); stream_cb_manager_t *cbmgr = (stream_cb_manager_t *)user_data; g_async_queue_unref(cbmgr->isolator_callback_queue); @@ -51,7 +51,7 @@ static void __thread_cancel_cleanup(void *user_data) static gpointer __sound_pool_callback_isolator(gpointer user_data) { - SP_DEBUF_FENTER(); + SP_DEBUG_FENTER(); int err = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); if (err != 0) SP_INFO("Can't setup cancel type for isolation thread with error [%d].", err); @@ -110,7 +110,7 @@ static gpointer __sound_pool_callback_isolator(gpointer user_data) sound_pool_error_e _stream_cb_manager_create(sound_pool_t *pool, stream_cb_manager_t **cbmgr) { - SP_DEBUF_FENTER(); + SP_DEBUG_FENTER(); SP_RETVM_IF(!pool, SOUND_POOL_ERROR_INVALID_PARAMETER, "Stream callback " "manager can't be created for NULL sound pool"); SP_RETVM_IF(!cbmgr, SOUND_POOL_ERROR_INVALID_PARAMETER, "Can't create " @@ -148,10 +148,10 @@ sound_pool_error_e _stream_cb_manager_create(sound_pool_t *pool, sound_pool_error_e _stream_cb_manager_destroy(stream_cb_manager_t *cbmgr) { - SP_DEBUF_FENTER(); + SP_DEBUG_FENTER(); SP_RETVM_IF(!cbmgr, SOUND_POOL_ERROR_INVALID_PARAMETER, "Can't handle callback " "manager, it is NULL."); - + sound_pool_error_e ret = SOUND_POOL_ERROR_NONE; pthread_t thread = cbmgr->isolator_thread; @@ -160,40 +160,42 @@ sound_pool_error_e _stream_cb_manager_destroy(stream_cb_manager_t *cbmgr) err = pthread_cancel(thread); if (0 != err) { SP_ERROR("Error while cancelling of isolation thread[%d].", err); - g_async_queue_unref(cbmgr->isolator_callback_queue); - pthread_mutex_destroy(&cbmgr->isolator_data_mutex); - pthread_cond_destroy(&cbmgr->isolator_data_cond); - SP_SAFE_GFREE(cbmgr); - SP_DEBUG_FLEAVE(); - return SOUND_POOL_ERROR_INVALID_OPERATION; + ret = SOUND_POOL_ERROR_INVALID_OPERATION; + GOTO_FAIL("", creturn); } } else { SP_ERROR("Invalid isolation thread[%d].", err); - g_async_queue_unref(cbmgr->isolator_callback_queue); - pthread_mutex_destroy(&cbmgr->isolator_data_mutex); - pthread_cond_destroy(&cbmgr->isolator_data_cond); - SP_SAFE_GFREE(cbmgr); - SP_DEBUG_FLEAVE(); - return SOUND_POOL_ERROR_INVALID_OPERATION; + ret = SOUND_POOL_ERROR_INVALID_OPERATION; + GOTO_FAIL("", creturn); } - void *ret; - err = pthread_join(thread, &ret); + void *return_val; + err = pthread_join(thread, &return_val); if (0 != err) SP_ERROR("Error while joining of isolation thread[%d].", err); - if (ret == PTHREAD_CANCELED) + if (return_val == PTHREAD_CANCELED) SP_INFO("Isolation thread canceled."); - else - SP_INFO("Routine joining of isolation thread."); + else { + ret = SOUND_POOL_ERROR_NONE; + GOTO_FAIL("Routine joining of isolation thread.", creturn); + } SP_DEBUG_FLEAVE(); - return SOUND_POOL_ERROR_NONE; + return ret; + +creturn: + g_async_queue_unref(cbmgr->isolator_callback_queue); + pthread_mutex_destroy(&cbmgr->isolator_data_mutex); + pthread_cond_destroy(&cbmgr->isolator_data_cond); + SP_SAFE_GFREE(cbmgr); + SP_DEBUG_FLEAVE(); + return ret; } sound_pool_error_e _stream_cb_manager_register_event(stream_cb_manager_t *cbmgr, sound_stream_t *stream) { - SP_DEBUF_FENTER(); + SP_DEBUG_FENTER(); SP_RETVM_IF(!cbmgr, SOUND_POOL_ERROR_INVALID_PARAMETER, "Can't handle callback manager, it is NULL."); SP_RETVM_IF(!stream, SOUND_POOL_ERROR_INVALID_PARAMETER, -- 2.7.4 From 248f1ad9ac18d331e36db17ec37177e2bb7b012e Mon Sep 17 00:00:00 2001 From: Ievgen Vagin Date: Wed, 15 Jun 2016 14:53:54 +0300 Subject: [PATCH 06/14] Implementation of the test suite for API testing Change-Id: Ia9681a2cc28ef65fee2e491a3624614a0e5daf0f Signed-off-by: Ievgen Vagin --- CMakeLists.txt | 2 +- packaging/sound-pool.spec | 4 +- test/CMakeLists.txt | 34 + test/logger/logger.h | 62 ++ test/logger/src/logger.c | 257 ++++++++ test/proxy/proxy.h | 79 +++ test/proxy/src/proxy.c | 1584 +++++++++++++++++++++++++++++++++++++++++++++ test/sound_pool_test.c | 344 ++++++++++ 8 files changed, 2363 insertions(+), 3 deletions(-) create mode 100644 test/CMakeLists.txt create mode 100644 test/logger/logger.h create mode 100644 test/logger/src/logger.c create mode 100644 test/proxy/proxy.h create mode 100644 test/proxy/src/proxy.c create mode 100644 test/sound_pool_test.c diff --git a/CMakeLists.txt b/CMakeLists.txt index d34c3c1..ef95ddd 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -68,7 +68,7 @@ CONFIGURE_FILE( ) INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${fw_name}.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig) -#ADD_SUBDIRECTORY(test) +ADD_SUBDIRECTORY(test) IF(UNIX) diff --git a/packaging/sound-pool.spec b/packaging/sound-pool.spec index 0f74e31..f4bece1 100644 --- a/packaging/sound-pool.spec +++ b/packaging/sound-pool.spec @@ -1,5 +1,5 @@ Name: sound-pool -Version: 0.0.1 +Version: 0.0.2 Summary: Tizen Sound Pool module Release: 0 Group: Multimedia/Framework @@ -40,7 +40,6 @@ make %{?jobs:-j%jobs} %install rm -rf %{buildroot} -mkdir -p %{buildroot}%{_bindir} %make_install @@ -51,6 +50,7 @@ mkdir -p %{buildroot}%{_bindir} %manifest %{name}.manifest %license LICENSE.APLv2 %{_libdir}/lib%{name}.so.* +%{_bindir}/* %files devel %manifest %{name}.manifest diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 0000000..a27573a --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,34 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +SET(fw_test "${fw_name}-test") + +INCLUDE(FindPkgConfig) +pkg_check_modules(${fw_test} REQUIRED glib-2.0) +FOREACH(flag ${${fw_test}_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}") + +SET(modules "") +SET(srcs "") +FILE(GLOB children *) +FOREACH(child ${children}) + IF(IS_DIRECTORY ${child}) + aux_source_directory(${child}/src mod_srcs) + LIST(APPEND srcs ${mod_srcs}) + GET_FILENAME_COMPONENT(child_name ${child} NAME_WE) + LIST(APPEND modules ${child_name}) + ENDIF() +ENDFOREACH() + +INCLUDE_DIRECTORIES(../include) +INCLUDE_DIRECTORIES(${modules}) + +aux_source_directory(. sources) + +FOREACH(src ${sources}) + GET_FILENAME_COMPONENT(src_name ${src} NAME_WE) + SET(srcs ${src} ${mod_srcs}) + ADD_EXECUTABLE(${src_name} ${srcs}) + TARGET_LINK_LIBRARIES(${src_name} ${${fw_test}_LDFLAGS} ${fw_name}) + INSTALL(TARGETS ${src_name} DESTINATION bin) +ENDFOREACH() diff --git a/test/logger/logger.h b/test/logger/logger.h new file mode 100644 index 0000000..572459b --- /dev/null +++ b/test/logger/logger.h @@ -0,0 +1,62 @@ +/* + * 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. + */ + +#define MAX_PATH_LEN 1024 +#define MAX_MSG_LEN 1024 + +#define _STRINGIFY(x) #x +#define STRINGIFY(x) _STRINGIFY(x) + +#define MAX_PATH_LEN_STR STRINGIFY(MAX_PATH_LEN) +#define MAX_MSG_LEN_STR STRINGIFY(MAX_MSG_LEN) + +#define LOG_MODE_NONE 0 +#define LOG_MODE_FILE 1 +#ifdef LOG_MODE_FILE +# define LOG_MODE_STDERR (LOG_MODE_FILE << 1) +# define LOG_MODE_DLOG (LOG_MODE_FILE << 2) +#endif + +/* Enumeration for terminal colors. Used in internal _printf() function */ +typedef enum { + CMD_COLOR_RED, + CMD_COLOR_YELLOW, + CMD_COLOR_GREEN +} _cmd_color_e; + +/* Sets globally the mode of logging. mode has to be specified as a single or + combination of the following defines: + LOG_MODE_NONE - no logging; + LOG_MODE_FILE - logging to the file; + LOG_MODE_STDERR - logging to the standart error stream; + LOG_MODE_DLOG - logging to the dlog. + For example, set_logging_mode(LOG_MODE_FILE | LOG_MODE_DLOG) call will + direct all following logging to both file and dlog daemon */ +void _logger_set_logging_mode(int mode); + +/* Sets globally the name of the file for LOG_MODE_FILE logging mode */ +int _logger_set_file(const char *fname); + +/* Sets globally the log tag will be used in logging journals like Tizen dlog */ +int _logger_set_log_tag(const char *tag); + +/* Functions for corresponding logging: */ +int _logger_log_info(const char *fmt, ...); +int _logger_log_warn(const char *fmt, ...); +int _logger_log_err(const char *fmt, ...); + +/* Function for using instead of standard printf() if coloring is needed */ +int _printf(_cmd_color_e color, const char *fmt, ...); diff --git a/test/logger/src/logger.c b/test/logger/src/logger.c new file mode 100644 index 0000000..d3932ab --- /dev/null +++ b/test/logger/src/logger.c @@ -0,0 +1,257 @@ +/* + * 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. + */ + +#include "logger.h" + +#include +#include +#include +#include +#include + +#define INFO_TAG "[ INFO ]" +#define WARNING_TAG "[ WARN ]" +#define ERROR_TAG "[ ERROR ]" + +#ifndef COLORED_LOG + #define COLORED_LOG +#endif +#ifdef COLORED_LOG +#define FONT_COLOR_RESET "\033[0m" +#define FONT_COLOR_RED "\033[31m" +#define FONT_COLOR_GREEN "\033[32m" +#define FONT_COLOR_YELLOW "\033[33m" +#else +#define FONT_COLOR_RESET +#define FONT_COLOR_RED +#define FONT_COLOR_GREEN +#define FONT_COLOR_YELLOW +#endif + +#ifdef LOG_TAG +#undef LOG_TAG +#endif + +#define MAX_LOG_TAG_LEN 32 +#define LOG_TAG "TIZEN_SOUND_POOL_TEST_SUITE" + +static struct { + int inited; + int mode; + char fname[MAX_PATH_LEN]; + pthread_mutex_t mutex; + time_t timer; +} __logger = { 0, LOG_MODE_NONE, {'\0'}, PTHREAD_MUTEX_INITIALIZER, 0 }; + +static char LOGGER_LOG_TAG[MAX_LOG_TAG_LEN] = LOG_TAG; + +#define MAX_DATETIME_STR_LEN 26 +static char str_time[MAX_DATETIME_STR_LEN]; + +void _logger_set_logging_mode(int mode) +{ + pthread_mutex_lock(&__logger.mutex); + __logger.mode = mode; + pthread_mutex_unlock(&__logger.mutex); +} + +int _logger_set_file(const char *fname) +{ + if (!fname) + return -1; + + FILE *fd = fopen(fname, "w+"); + if (!fd) + return -1; + + fclose(fd); + + pthread_mutex_lock(&__logger.mutex); + strncpy(__logger.fname, fname, MAX_PATH_LEN - 1); + __logger.fname[MAX_PATH_LEN - 1] = '\0'; + pthread_mutex_unlock(&__logger.mutex); + + return 0; +} + +int _logger_set_log_tag(const char *tag) +{ + if (!tag) + return -1; + + pthread_mutex_lock(&__logger.mutex); + strncpy(LOGGER_LOG_TAG, tag, MAX_LOG_TAG_LEN - 1); + LOGGER_LOG_TAG[MAX_LOG_TAG_LEN - 1] = '\0'; + pthread_mutex_unlock(&__logger.mutex); + return 0; +} + +# define __LOGGER_PREPARE() \ + do { \ + pthread_mutex_lock(&__logger.mutex); \ + time(&__logger.timer); \ + strftime(str_time, MAX_DATETIME_STR_LEN, "%Y:%m:%d %H:%M:%S", \ + localtime(&__logger.timer)); \ + } while (0) + +# define __LOGGER_UNPREPARE() \ + do { \ + pthread_mutex_unlock(&__logger.mutex); \ + } while (0) + +int _logger_log_info(const char *fmt, ...) +{ + int res = 0; + va_list args; + __LOGGER_PREPARE(); + + if ((__logger.mode & LOG_MODE_FILE) == LOG_MODE_FILE) { + FILE *fd = fopen(__logger.fname, "a"); + if (!fd) { + __LOGGER_UNPREPARE(); + return -1; + } + fprintf(fd, "[%s]", str_time); + fprintf(fd, INFO_TAG); + va_start(args, fmt); + res = vfprintf(fd, fmt, args); + fprintf(fd, "\n"); + fclose(fd); + } + if ((__logger.mode & LOG_MODE_STDERR) == LOG_MODE_STDERR) { + fprintf(stderr, "[%s]", str_time); + fprintf(stderr, FONT_COLOR_GREEN INFO_TAG); + va_start(args, fmt); + res = vfprintf(stderr, fmt, args); + fprintf(stderr, FONT_COLOR_RESET); + fprintf(stderr, "\n"); + } + if ((__logger.mode & LOG_MODE_DLOG) == LOG_MODE_DLOG) { + char msg[MAX_MSG_LEN] = { '\0' }; + snprintf(msg, MAX_MSG_LEN, "[%s]%s", str_time, fmt); + va_start(args, fmt); + dlog_vprint(DLOG_INFO, LOGGER_LOG_TAG, msg, args); + } + + va_end(args); + __LOGGER_UNPREPARE(); + return res; +} + +int _logger_log_warn(const char *fmt, ...) +{ + int res = 0; + va_list args; + __LOGGER_PREPARE(); + + if ((__logger.mode & LOG_MODE_FILE) == LOG_MODE_FILE) { + FILE *fd = fopen(__logger.fname, "a"); + if (!fd) { + __LOGGER_UNPREPARE(); + return -1; + } + fprintf(fd, "[%s]", str_time); + fprintf(fd, WARNING_TAG); + va_start(args, fmt); + res = vfprintf(fd, fmt, args); + fprintf(fd, "\n"); + fclose(fd); + } + if ((__logger.mode & LOG_MODE_STDERR) == LOG_MODE_STDERR) { + fprintf(stderr, "[%s]", str_time); + fprintf(stderr, FONT_COLOR_YELLOW WARNING_TAG); + va_start(args, fmt); + res = vfprintf(stderr, fmt, args); + fprintf(stderr, FONT_COLOR_RESET); + fprintf(stderr, "\n"); + } + if ((__logger.mode & LOG_MODE_DLOG) == LOG_MODE_DLOG) { + char msg[MAX_MSG_LEN] = { '\0' }; + snprintf(msg, MAX_MSG_LEN, "[%s]%s", str_time, fmt); + va_start(args, fmt); + dlog_vprint(DLOG_WARN, LOGGER_LOG_TAG, msg, args); + } + + va_end(args); + __LOGGER_UNPREPARE(); + return res; +} + +int _logger_log_err(const char *fmt, ...) +{ + int res = 0; + va_list args; + __LOGGER_PREPARE(); + + if ((__logger.mode & LOG_MODE_FILE) == LOG_MODE_FILE) { + FILE *fd = fopen(__logger.fname, "a"); + if (!fd) { + __LOGGER_UNPREPARE(); + return -1; + } + fprintf(fd, "[%s]", str_time); + fprintf(fd, ERROR_TAG); + va_start(args, fmt); + res = vfprintf(fd, fmt, args); + fprintf(fd, "\n"); + fclose(fd); + } + if ((__logger.mode & LOG_MODE_STDERR) == LOG_MODE_STDERR) { + fprintf(stderr, "[%s]", str_time); + fprintf(stderr, FONT_COLOR_RED ERROR_TAG); + va_start(args, fmt); + res = vfprintf(stderr, fmt, args); + fprintf(stderr, FONT_COLOR_RESET); + fprintf(stderr, "\n"); + } + if ((__logger.mode & LOG_MODE_DLOG) == LOG_MODE_DLOG) { + char msg[MAX_MSG_LEN] = { '\0' }; + snprintf(msg, MAX_MSG_LEN, "[%s]%s", str_time, fmt); + va_start(args, fmt); + dlog_vprint(DLOG_ERROR, LOGGER_LOG_TAG, msg, args); + } + + va_end(args); + __LOGGER_UNPREPARE(); + return res; +} + +int _printf(_cmd_color_e color, const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + + switch (color) { + case CMD_COLOR_RED: + vprintf(FONT_COLOR_RED, args); + break; + case CMD_COLOR_YELLOW: + vprintf(FONT_COLOR_YELLOW, args); + break; + case CMD_COLOR_GREEN: + vprintf(FONT_COLOR_GREEN, args); + break; + default: + break; + } + + int res = vprintf(fmt, args); + printf(FONT_COLOR_RESET); + + va_end(args); + + return res; +} diff --git a/test/proxy/proxy.h b/test/proxy/proxy.h new file mode 100644 index 0000000..3cdc86e --- /dev/null +++ b/test/proxy/proxy.h @@ -0,0 +1,79 @@ +/* + * 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. + */ + +#include "sound_pool.h" + +#define MAX_COMMAND_LINE_LEN 1024 + +/* Test suite command list */ +#define CMD_EXIT "exit" /* 0 */ +#define CMD_HELP "help" /* 1 */ +#define CMD_CREATE_POOL "pool create" /* 2 */ +#define CMD_DESTROY_POOL "pool destroy" /* 3 */ +#define CMD_ACTIVATE_POOL "pool activate" /* 4 */ +#define CMD_DEACTIVATE_POOL "pool deactivate" /* 5 */ +#define CMD_GET_POOL_STATE "pool get state" /* 6 */ +#define CMD_SET_POOL_VOLUME "pool set volume" /* 7 */ +#define CMD_GET_POOL_VOLUME "pool get volume" /* 8 */ +#define CMD_SET_POOL_CB_MSG "pool set callback message" /* 9 */ +#define CMD_SET_POOL_CB_SCRIPT "pool set callback script" /* 10 */ +#define CMD_UNSET_POOL_CB "pool unset callback" /* 11 */ +#define CMD_LIST_POOL "pool list" /* 12 */ +#define CMD_LOAD_SOURCE "source load" /* 13 */ +#define CMD_LOAD_MEDIA_PACKAGE "source load mic" /* 14 */ +#define CMD_UNLOAD_SOURCE "source unload" /* 15 */ +#define CMD_PLAY_STREAM "stream play" /* 16 */ +#define CMD_STOP_STREAM "stream stop" /* 17 */ +#define CMD_PAUSE_STREAM "stream pause" /* 18 */ +#define CMD_RESUME_STREAM "stream resume" /* 19 */ +#define CMD_SET_STREAM_VOLUME "stream set volume" /* 20 */ +#define CMD_GET_STREAM_VOLUME "stream get volume" /* 21 */ +#define CMD_SET_STREAM_LOOP "stream set loop" /* 22 */ +#define CMD_GET_STREAM_LOOP "stream get loop" /* 23 */ +#define CMD_SET_STREAM_PRIORITY "stream set priority" /* 24 */ +#define CMD_GET_STREAM_PRIORITY "stream get priority" /* 25 */ +#define CMD_GET_STREAM_STATE "stream get state" /* 26 */ +#define CMD_SET_STREAM_CB_MSG "stream set callback message" /* 27 */ +#define CMD_SET_STREAM_CB_SCRIPT "stream set callback script" /* 28 */ +#define CMD_UNSET_STREAM_CB "stream unset callback" /* 29 */ +#define CMD_EXECUTE_SCRIPT "script execute" /* 30 */ +#define CMD_SLEEP "sleep" /* 31 */ + +#define CMD_COUNT 32 + +/* Command execution results list */ +#define OK +1 +#define FAIL -1 +#define UCMD -2 +#define EXIT 0 + +static char *cmd_list[MAX_COMMAND_LINE_LEN] = { CMD_EXIT, CMD_HELP, + CMD_CREATE_POOL, CMD_DESTROY_POOL, CMD_ACTIVATE_POOL, + CMD_DEACTIVATE_POOL, CMD_GET_POOL_STATE, CMD_SET_POOL_VOLUME, + CMD_GET_POOL_VOLUME, CMD_SET_POOL_CB_MSG, CMD_SET_POOL_CB_SCRIPT, + CMD_UNSET_POOL_CB, CMD_LIST_POOL, CMD_LOAD_SOURCE, + CMD_LOAD_MEDIA_PACKAGE, CMD_UNLOAD_SOURCE, CMD_PLAY_STREAM, + CMD_STOP_STREAM, CMD_PAUSE_STREAM, CMD_RESUME_STREAM, + CMD_SET_STREAM_VOLUME, CMD_GET_STREAM_VOLUME, CMD_SET_STREAM_LOOP, + CMD_GET_STREAM_LOOP, CMD_SET_STREAM_PRIORITY, CMD_GET_STREAM_PRIORITY, + CMD_GET_STREAM_STATE, CMD_SET_STREAM_CB_MSG, CMD_SET_STREAM_CB_SCRIPT, + CMD_UNSET_STREAM_CB, CMD_EXECUTE_SCRIPT, CMD_SLEEP }; + +void print_cmd_help_msg(); + +void print_async_msg(); + +int _exec_cmd(const char *cmd_line); diff --git a/test/proxy/src/proxy.c b/test/proxy/src/proxy.c new file mode 100644 index 0000000..deaa36b --- /dev/null +++ b/test/proxy/src/proxy.c @@ -0,0 +1,1584 @@ +/* + * 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. + */ + +#include "proxy.h" +#include "logger.h" + +#include +#include +#include +#include + +#define DEFAULT_MAX_STREAMS_PER_POOL_CNT 25 +#define MICROSECS_PER_MILLISEC 1000 + +#define MAX_POOL_CNT 100 +static sound_pool_h pools[MAX_POOL_CNT] = { NULL }; + +/* Messages to be used for callbacks output (for pool state changing) */ +static char *messages[MAX_POOL_CNT] = { NULL }; +/* Scripts will be launched from callbacks (for stream state changing) */ +static char *scripts[MAX_POOL_CNT] = { NULL }; + +#define MAX_STREAM_CNT 1000 +/* Messages to be used for callbacks output (for pool state changing) */ +static char *stream_messages[MAX_POOL_CNT][MAX_STREAM_CNT] = { NULL }; +/* Messages to be used for callbacks output (for stream state changing) */ +static char *stream_scripts[MAX_POOL_CNT][MAX_STREAM_CNT] = { NULL }; + +static int __proxy_sound_pool_execute_script(const char *pars); + +const char *__stringify_sound_pool_error(sound_pool_error_e error) +{ + switch (error) { + case SOUND_POOL_ERROR_NONE: + return "SOUND_POOL_ERROR_NONE"; + break; + case SOUND_POOL_ERROR_NOT_SUPPORTED: + return "SOUND_POOL_ERROR_NOT_SUPPORTED"; + break; + case SOUND_POOL_ERROR_MSG_TOO_LONG: + return "SOUND_POOL_ERROR_MSG_TOO_LONG"; + break; + case SOUND_POOL_ERROR_NO_DATA: + return "SOUND_POOL_ERROR_NO_DATA"; + break; + case SOUND_POOL_ERROR_KEY_NOT_AVAILABLE: + return "SOUND_POOL_ERROR_KEY_NOT_AVAILABLE"; + break; + case SOUND_POOL_ERROR_OUT_OF_MEMORY: + return "SOUND_POOL_ERROR_OUT_OF_MEMORY"; + break; + case SOUND_POOL_ERROR_INVALID_PARAMETER: + return "SOUND_POOL_ERROR_INVALID_PARAMETER"; + break; + case SOUND_POOL_ERROR_INVALID_OPERATION: + return "SOUND_POOL_ERROR_INVALID_OPERATION"; + break; + case SOUND_POOL_ERROR_PERMISSION_DENIED: + return "SOUND_POOL_ERROR_PERMISSION_DENIED"; + break; + default: + return ""; + break; + } + + return NULL; +} + +const char *__stringify_stream_state(sound_pool_stream_state_e state) +{ + switch (state) { + case SOUND_POOL_STREAM_STATE_NONE: + return "SOUND_POOL_STREAM_STATE_NONE"; + break; + case SOUND_POOL_STREAM_STATE_PLAYING: + return "SOUND_POOL_STREAM_STATE_PLAYING"; + break; + case SOUND_POOL_STREAM_STATE_PAUSED: + return "SOUND_POOL_STREAM_STATE_PAUSED"; + break; + case SOUND_POOL_STREAM_STATE_SUSPENDED: + return "SOUND_POOL_STREAM_STATE_SUSPENDED"; + break; + case SOUND_POOL_STREAM_STATE_STOPPED: + return "SOUND_POOL_STREAM_STATE_STOPPED"; + break; + case SOUND_POOL_STREAM_STATE_FINISHED: + return "SOUND_POOL_STREAM_STATE_FINISHED"; + break; + default: + return ""; + break; + } + + return NULL; +} + +static void __sp_cb_msg(sound_pool_h pool, sound_pool_state_e prev_state, + sound_pool_state_e cur_state, void *data) +{ + const char *msg = (const char *)data; + _logger_log_info("Sound pool state was changing from %s to %s: %s", + prev_state == SOUND_POOL_STATE_ACTIVE ? + "SOUND_POOL_STATE_ACTIVE" : "SOUND_POOL_STATE_INACTIVE", + cur_state == SOUND_POOL_STATE_ACTIVE ? + "SOUND_POOL_STATE_ACTIVE" : "SOUND_POOL_STATE_INACTIVE", + msg ? msg : "No message"); +} + +static void __sp_cb_scr(sound_pool_h pool, sound_pool_state_e prev_state, + sound_pool_state_e cur_state, void *data) +{ + const char *scr = (const char *)data; + _logger_log_info("Sound pool state was changing from %s to %s; " + "Executing: %s...", + prev_state == SOUND_POOL_STATE_ACTIVE ? "SOUND_POOL_STATE_ACTIVE" : + "SOUND_POOL_STATE_INACTIVE", + cur_state == SOUND_POOL_STATE_ACTIVE ? "SOUND_POOL_STATE_ACTIVE" : + "SOUND_POOL_STATE_INACTIVE", + scr ? scr : "No script"); + __proxy_sound_pool_execute_script(scr); +} + +static void __s_cb_msg(sound_pool_h pool, const char *tag, unsigned id, + sound_pool_stream_state_e prev_state, + sound_pool_stream_state_e cur_state, void *data) +{ + const char *msg = (const char *)data; + _logger_log_info("Stream state was changing from %s to %s: %s", + __stringify_stream_state(prev_state), + __stringify_stream_state(cur_state), + msg ? msg : "No message"); +} + +static void __s_cb_scr(sound_pool_h pool, const char *tag, unsigned id, + sound_pool_stream_state_e prev_state, + sound_pool_stream_state_e cur_state, void *data) +{ + const char *scr = (const char *)data; + _logger_log_info("Sound pool state was changing from %s to %s; " + "Executing: %s...", __stringify_stream_state(prev_state), + __stringify_stream_state(cur_state), + scr ? scr : "No script"); + __proxy_sound_pool_execute_script(scr); +} + +/* CMD_EXIT */ +static int __exit() +{ + return EXIT; +} + +/* CMD_HELP */ +static int __print_cmd_help_msg() +{ + printf("\nTest suite usage help:\n"); + + printf(CMD_HELP "\n"); + printf("\t- Shows this help.\n"); + + printf(CMD_CREATE_POOL "\n"); + printf("\t- creates pool with specific identifier.\n"); + + printf(CMD_DESTROY_POOL "\n"); + printf("\t- destroys pool with specific identifier.\n"); + + printf(CMD_ACTIVATE_POOL "\n"); + printf("\t- activates pool with specific identifier.\n"); + + printf(CMD_DEACTIVATE_POOL "\n"); + printf("\t- deactivates pool with specific identifier.\n"); + + printf(CMD_GET_POOL_STATE "\n"); + printf("\t- shows state of the pool with specific identifier.\n"); + + printf(CMD_SET_POOL_VOLUME "\n"); + printf("\t- use this command to set volume for the specific sound pool.\n"); + + printf(CMD_GET_POOL_VOLUME "\n"); + printf("\t- shows volume of the sound pool with specific identifier.\n"); + + printf(CMD_SET_POOL_CB_MSG "\n"); + printf("\t- sets callback which will show the message when sound pool " + "state is changed.\n"); + + printf(CMD_SET_POOL_CB_SCRIPT "\n"); + printf("\t- sets callback which will execute the script when sound pool " + "state is changed.\n"); + + printf(CMD_UNSET_POOL_CB "\n"); + printf("\t- unsets the callback for the sound pool.\n"); + + printf(CMD_LIST_POOL "\n"); + printf("\t- shows ids of all pools had been created and their states.\n"); + + printf(CMD_LOAD_SOURCE "\n"); + printf("\t- loads the source with specific source tag.\n"); + + printf(CMD_UNLOAD_SOURCE "\n"); + printf("\t- unloads the source with specific source tag.\n"); + + printf(CMD_PLAY_STREAM "\n"); + printf("\t- creates the stream with unique identifier and starts playback.\n" + "\t Source tag to be used for stream creation should be specified.\n"); + + printf(CMD_STOP_STREAM "\n"); + printf("\t- stops the stream playback. Stream unique identifier should be\n" + "\t specified after command. After stopping the stream became invalid.\n"); + + printf(CMD_PAUSE_STREAM "\n"); + printf("\t- pauses the stream playback. Stream unique identifier should be\n" + "\t specified after command.\n"); + + printf(CMD_RESUME_STREAM "\n"); + printf("\t- resumes the stream was paused before. Stream unique identifier\n" + "\t should be specified after command.\n"); + + printf(CMD_SET_STREAM_VOLUME "\n"); + printf("\t- use this command to set volume parameter of the stream.\n"); + + printf(CMD_GET_STREAM_VOLUME "\n"); + printf("\t- shows volume of the stream in the pool with specified " + "identifiers.\n"); + + printf(CMD_SET_STREAM_LOOP "\n"); + printf("\t- use this command to set loop parameter of the stream.\n"); + + printf(CMD_GET_STREAM_LOOP "\n"); + printf("\t- shows loop count of the stream in the pool with specified " + "identifiers.\n"); + + printf(CMD_SET_STREAM_PRIORITY "\n"); + printf("\t- use this command to set priority parameter of the stream.\n"); + + printf(CMD_GET_STREAM_PRIORITY "\n"); + printf("\t- shows priority rank of the stream in the pool with specified " + "identifiers.\n"); + + printf(CMD_GET_STREAM_STATE "\n"); + printf("\t- shows state of the stream in the pool with specified " + "identifiers.\n"); + + printf(CMD_SET_STREAM_CB_MSG "\n"); + printf("\t- sets callback which will show the message when sound stream " + "state is changed.\n"); + + printf(CMD_SET_STREAM_CB_SCRIPT "\n"); + printf("\t- sets callback which will execute the script (from file) when " + "sound stream state is changed.\n"); + + printf(CMD_UNSET_STREAM_CB "\n"); + printf("\t- unsets the callback for the sound stream.\n"); + + printf(CMD_EXECUTE_SCRIPT "\n"); + printf("\t- executes the script from the file in filesystem. Script has to\n" + "\t be compiled with commands supported by testsuite, one command\n" + "\t per single line.\n"); + + printf(CMD_SLEEP "\n"); + printf("\t- suspends execution of the main thread for the specific amount " + "of milleseconds.\n"); + + printf(CMD_EXIT "\n"); + printf("\t- exits from the test suite.\n"); + + printf("\n"); + + return OK; +} + +/* CMD_CREATE_POOL */ +static int __proxy_sound_pool_create(const char *pars) +{ + _logger_log_info(CMD_CREATE_POOL " command was called"); + + unsigned int max_streams = DEFAULT_MAX_STREAMS_PER_POOL_CNT; + if (pars != NULL) + sscanf(pars, " %u", &max_streams); + + _logger_log_info("Creating the pool..."); + + sound_pool_h pool = NULL; + int ret = sound_pool_create(max_streams, &pool); + + if (ret == SOUND_POOL_ERROR_NONE) { + _logger_log_info("sound_pool_create(%u, pool) returned %s value", + max_streams, __stringify_sound_pool_error(ret)); + + size_t idx = 0; + while (idx < MAX_POOL_CNT) { + if (pools[idx++] == NULL) { + pools[--idx] = pool; + break; + } + } + + if (idx == MAX_POOL_CNT) { + _printf(CMD_COLOR_RED, "Limit of possible pools is exceeded. Destroy " + "some pools before creating of new ones.\n"); + + _logger_log_warn("Pool can't be created due to test suite " + "restrictions. Destroying the pool..."); + + ret = sound_pool_destroy(pool); + if (ret == SOUND_POOL_ERROR_NONE) + _logger_log_info("sound_pool_destroy(pool) returned %s value", + __stringify_sound_pool_error(ret)); + else + _logger_log_err("sound_pool_destroy(pool) returned %s value", + __stringify_sound_pool_error(ret)); + + return (ret == SOUND_POOL_ERROR_NONE ? OK : FAIL); + } + + if (!pool) + _logger_log_warn("Created pool is NULL"); + else + _logger_log_info("Identifier of the pool has been created is %zu", idx); + } else { + _logger_log_err("sound_pool_create(%u, pool) returned %s value", + max_streams, __stringify_sound_pool_error(ret)); + } + + return (ret == SOUND_POOL_ERROR_NONE ? OK : FAIL); +} + +/* CMD_DESTROY_POOL */ +static int __proxy_sound_pool_destroy(const char *pars) +{ + int ret = SOUND_POOL_ERROR_NONE; + size_t idx = 0; + if ((pars == NULL) || (sscanf(pars, " %zu", &idx) < 1)) { + _printf(CMD_COLOR_RED, "You have to specify identifier of the pool to be " + "destroyed after command! Format: " CMD_DESTROY_POOL " \n"); + return FAIL; + } + + if (idx > (MAX_POOL_CNT - 1)) { + _printf(CMD_COLOR_RED, "Pool identifier value can't be greater than %d\n", + MAX_POOL_CNT - 1); + return FAIL; + } + + _logger_log_info(CMD_DESTROY_POOL " command was called"); + _logger_log_info("Destroying the pool by %zu identifier...", idx); + + if (pools[idx] == NULL) + _logger_log_warn("Pool to be destroyed is NULL"); + + ret = sound_pool_destroy(pools[idx]); + + if (ret == SOUND_POOL_ERROR_NONE) + _logger_log_info("sound_pool_destroy(pool) returned %s value", + __stringify_sound_pool_error(ret)); + else + _logger_log_err("sound_pool_destroy(pool) returned %s value", + __stringify_sound_pool_error(ret)); + + pools[idx] = NULL; + + return (ret == SOUND_POOL_ERROR_NONE ? OK : FAIL); +} + +/* CMD_ACTIVATE_POOL */ +static int __proxy_sound_pool_activate(const char *pars) +{ + int ret = SOUND_POOL_ERROR_NONE; + size_t idx = 0; + if ((pars == NULL) || (sscanf(pars, " %zu", &idx) < 1)) { + _printf(CMD_COLOR_RED, "You have to specify identifier of the pool " + "to be activated after command name! Format: " + CMD_ACTIVATE_POOL " \n"); + return FAIL; + } + + if (idx > (MAX_POOL_CNT - 1)) { + _printf(CMD_COLOR_RED, "Pool identifier value can't be greater than %d\n", + MAX_POOL_CNT - 1); + return FAIL; + } + + _logger_log_info(CMD_ACTIVATE_POOL " command was called"); + _logger_log_info("Activating the pool by %zu identifier...", idx); + + if (pools[idx] == NULL) + _logger_log_warn("Pool to be activated is NULL"); + + ret = sound_pool_activate(pools[idx]); + + if (ret == SOUND_POOL_ERROR_NONE) + _logger_log_info("sound_pool_set_state(pool, " + "SOUND_POOL_STATE_ACTIVE) returned %s value", + __stringify_sound_pool_error(ret)); + else + _logger_log_err("sound_pool_set_state(pool, " + "SOUND_POOL_STATE_ACTIVE) returned %s value", + __stringify_sound_pool_error(ret)); + + return (ret == SOUND_POOL_ERROR_NONE ? OK : FAIL); +} + +/* CMD_DEACTIVATE_POOL */ +static int __proxy_sound_pool_deactivate(const char *pars) +{ + size_t idx = 0; + if ((pars == NULL) || (sscanf(pars, " %zu", &idx) < 1)) { + _printf(CMD_COLOR_RED, "You have to specify identifier of the pool " + "to be deactivated after command name! Format: " + CMD_DEACTIVATE_POOL " \n"); + return FAIL; + } + + if (idx > (MAX_POOL_CNT - 1)) { + _printf(CMD_COLOR_RED, "Pool identifier value can't be greater than %d\n", + MAX_POOL_CNT - 1); + return FAIL; + } + + _logger_log_info(CMD_DEACTIVATE_POOL " command was called"); + _logger_log_info("Deactivating the pool by %zu identifier...", idx); + + if (pools[idx] == NULL) + _logger_log_warn("Pool to be deactivated is NULL"); + + int ret = sound_pool_deactivate(pools[idx]); + + if (ret == SOUND_POOL_ERROR_NONE) + _logger_log_info("sound_pool_set_state(pool, " + "SOUND_POOL_STATE_INACTIVE) returned %s value", + __stringify_sound_pool_error(ret)); + else + _logger_log_err("sound_pool_set_state(pool, " + "SOUND_POOL_STATE_INACTIVE) returned %s value", + __stringify_sound_pool_error(ret)); + + return (ret == SOUND_POOL_ERROR_NONE ? OK : FAIL); +} + +/* CMD_GET_POOL_STATE */ +static int __proxy_sound_pool_get_state(const char *pars) +{ + size_t idx = 0; + if ((pars == NULL) || (sscanf(pars, " %zu", &idx) < 1)) { + _printf(CMD_COLOR_RED, "You have to specify identifier of the pool " + "to get state for, after command name! Format: " + CMD_GET_POOL_STATE " \n"); + return FAIL; + } + + if (idx > (MAX_POOL_CNT - 1)) { + _printf(CMD_COLOR_RED, "Pool identifier value can't be greater than %d\n", + MAX_POOL_CNT - 1); + return FAIL; + } + + _logger_log_info(CMD_GET_POOL_STATE " command was called"); + _logger_log_info("Getting the pool state by %zu identifier...", idx); + + if (pools[idx] == NULL) + _logger_log_warn("Pool to get state for is NULL"); + + sound_pool_state_e state = SOUND_POOL_STATE_INACTIVE; + int ret = sound_pool_get_state(pools[idx], &state); + + const char *str_state = (state == SOUND_POOL_STATE_ACTIVE ? + "SOUND_POOL_STATE_ACTIVE" : "SOUND_POOL_STATE_INACTIVE"); + + if (ret == SOUND_POOL_ERROR_NONE) + _logger_log_info("sound_pool_get_state(pool, state) returned %s value," + " state is %s", __stringify_sound_pool_error(ret), str_state); + else + _logger_log_err("sound_pool_get_state(pool, state) returned %s value," + " state is %s", __stringify_sound_pool_error(ret), str_state); + + return (ret == SOUND_POOL_ERROR_NONE ? OK : FAIL); +} + +/* CMD_SET_POOL_VOLUME */ +static int __proxy_sound_pool_set_volume(const char *pars) +{ + size_t idx = 0; + float volume = .0f; + if ((pars == NULL) || (sscanf(pars, " %zu %f", &idx, &volume) < 2)) { + _printf(CMD_COLOR_RED, "You have to specify both identifier of the " + "pool and new volume float value to set volume for whole pool! " + "Format: " CMD_SET_POOL_VOLUME " \n"); + return FAIL; + } + + if (idx > (MAX_POOL_CNT - 1)) { + _printf(CMD_COLOR_RED, "Pool identifier value can't be greater than %d\n", + MAX_POOL_CNT - 1); + return FAIL; + } + + _logger_log_info(CMD_SET_POOL_VOLUME " command was called"); + _logger_log_info("Set %f volume value for pool with %zu identifier...", + volume, idx); + + if (pools[idx] == NULL) + _logger_log_warn("Pool to get state for is NULL"); + + if (volume < .0f || volume > 1.0f) + _logger_log_warn("Volume is set as %f, not in [0, 1.0] range", volume); + + int ret = sound_pool_set_volume(pools[idx], volume); + + if (ret == SOUND_POOL_ERROR_NONE) + _logger_log_info("sound_pool_set_global_volume(pool, %f) " + "returned %s value", volume, __stringify_sound_pool_error(ret)); + else + _logger_log_err("sound_pool_set_global_volume(pool, %f) " + "returned %s value", volume, __stringify_sound_pool_error(ret)); + + return (ret == SOUND_POOL_ERROR_NONE ? OK : FAIL); +} + +/* CMD_GET_POOL_VOLUME */ +static int __proxy_sound_pool_get_volume(const char *pars) +{ + size_t idx = 0; + if ((pars == NULL) || (sscanf(pars, " %zu", &idx) < 1)) { + _printf(CMD_COLOR_RED, "You have to specify identifier of the pool " + "to get volume for, after command name! Format: " + CMD_GET_POOL_VOLUME " \n"); + return FAIL; + } + + if (idx > (MAX_POOL_CNT - 1)) { + _printf(CMD_COLOR_RED, "Pool identifier value can't be greater than %d\n", + MAX_POOL_CNT - 1); + return FAIL; + } + + _logger_log_info(CMD_GET_POOL_VOLUME " command was called"); + _logger_log_info("Getting the pool global volume for pool with %zu " + "identifier...", idx); + + if (pools[idx] == NULL) + _logger_log_warn("Pool to get state for is NULL"); + + float volume = .0f; + int ret = sound_pool_get_volume(pools[idx], &volume); + + if (ret == SOUND_POOL_ERROR_NONE) + _logger_log_info("sound_pool_get_global_volume(pool, volume) returned " + "%s value, volume is %f", __stringify_sound_pool_error(ret), + volume); + else + _logger_log_err("sound_pool_get_global_volume(pool, volume) returned " + "%s value, volume is %f", __stringify_sound_pool_error(ret), + volume); + + return (ret == SOUND_POOL_ERROR_NONE ? OK : FAIL); +} + +/* CMD_SET_POOL_CB_MSG */ +static int __proxy_sound_pool_set_state_change_callback_message(const char *pars) +{ + size_t idx = 0; + + char msg[MAX_MSG_LEN] = { '\0' }; + + if ((pars == NULL) || (sscanf(pars, " %zu %"MAX_MSG_LEN_STR"[^ ]", &idx, msg) < 2)) { + _printf(CMD_COLOR_RED, "You have to specify both identifier of the " + "pool and message to be shown each time when state of the pool " + " is changed! Message should be a single word. Format: " + CMD_SET_POOL_CB_MSG " \n"); + return FAIL; + } + + if (idx > (MAX_POOL_CNT - 1)) { + _printf(CMD_COLOR_RED, "Pool identifier value can't be greater than %d\n", + MAX_POOL_CNT - 1); + return FAIL; + } + + _logger_log_info(CMD_SET_POOL_CB_MSG " command was called"); + _logger_log_info("Set state changing callback (%s message) for pool with " + "%zu identifier...", msg, idx); + + if (pools[idx] == NULL) + _logger_log_warn("Pool to set callback for is NULL"); + + if (messages[idx]) + free(messages[idx]); + messages[idx] = strndup(msg, MAX_MSG_LEN); + + int ret = sound_pool_set_state_change_callback(pools[idx], __sp_cb_msg, + messages[idx]); + + if (ret == SOUND_POOL_ERROR_NONE) + _logger_log_info("sound_pool_set_state_change_callback(pool, cb, " + "\"%s\") returned %s value", msg, __stringify_sound_pool_error(ret)); + else + _logger_log_err("sound_pool_set_state_change_callback(pool, cb, " + "\"%s\") returned %s value", msg, __stringify_sound_pool_error(ret)); + + return (ret == SOUND_POOL_ERROR_NONE ? OK : FAIL); +} + +/* CMD_SET_POOL_CB_SCRIPT */ +static int __proxy_sound_pool_set_state_change_callback_script(const char *pars) +{ + size_t idx = 0; + + char scr[MAX_MSG_LEN] = { '\0' }; + + if ((pars == NULL) || (sscanf(pars, " %zu %"MAX_MSG_LEN_STR"[^ ]", &idx, scr) < 2)) { + _printf(CMD_COLOR_RED, "You have to specify both identifier of the " + "pool and script file name to be executed each time when state " + "of the pool will be changed! Format: " + CMD_SET_POOL_CB_SCRIPT "