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"
)
--- /dev/null
+/*
+ * 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 <glib.h>
+
+#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_ */
--- /dev/null
+/*
+ * 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 <glib.h>
+#include <AL/al.h>
+#include <AL/alc.h>
+
+#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__ */
--- /dev/null
+/*
+ * 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 <glib.h>
+#include <AL/al.h>
+#include <AL/alc.h>
+
+#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__ */
--- /dev/null
+/*
+ * 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 <glib.h>
+#include <AL/al.h>
+#include <AL/alc.h>
+
+#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__ */
--- /dev/null
+/*
+ * 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 <pthread.h>
+#include <glib.h>
+#include <AL/al.h>
+#include <AL/alc.h>
+
+#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__ */
* @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
*
* @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.
*
* @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.
* @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);
/**
* @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.
* @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);
/**
* @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.
* @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.
* @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);
/**
* @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.
* @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);
* @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.
* @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.
* @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.
*
* @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.
*
* @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.
* @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);
/**
* @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.
* @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.
* @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);
/**
* @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);
/**
* @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);
/**
* @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);
/**
* @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);
/**
* @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);
/**
--- /dev/null
+/*
+ * 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 <glib.h>
+#include <dlog.h>
+#include <AL/al.h>
+#include <AL/alc.h>
+
+#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"<Enter>"FONT_COLOR_RESET); \
+ } while (0)
+
+#define SP_DEBUG_FLEAVE() \
+ do { \
+ LOGD(FONT_COLOR_PURPLE"<Leave>"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__ */
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}
%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}
--- /dev/null
+/*
+ * 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();
+}
* 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;
+}
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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 <AL/alut.h>
+
+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;
+}
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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;
+}