2 * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the License);
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an AS IS BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 * @brief This file include implementation of protected API
20 * for the sound sources(OpenAL buffers) as part of SoundPool.
23 #include "internal/source.h"
24 #include "internal/stream.h"
28 static int __sound_pool_add_source(sound_pool_t *pool, sound_source_t *src);
29 static int __sound_pool_remove_source(sound_pool_t *pool, sound_source_t *src);
31 static int __sound_pool_add_source(sound_pool_t *pool, sound_source_t *src)
34 SP_INST_CHECK(pool, SOUND_POOL_ERROR_INVALID_PARAMETER);
35 SP_INST_CHECK(src, SOUND_POOL_ERROR_INVALID_PARAMETER);
36 SP_RETVM_IF(!pool->sources, SOUND_POOL_ERROR_INVALID_OPERATION, "Sound "
37 "pool to add the source is corrupted: NULL sources hash table");
38 SP_RETVM_IF(!src->tag_name, SOUND_POOL_ERROR_INVALID_OPERATION,
39 "Source to be added to sound pool is corrupted: NULL tag name");
40 SP_RETVM_IF(src->parent_pool != pool, SOUND_POOL_ERROR_INVALID_OPERATION,
41 "Sound source can't be added to the pool different to the pool for"
42 " which sound source was created");
43 SP_RETVM_IF(g_hash_table_contains(pool->sources, src->tag_name),
44 SOUND_POOL_ERROR_INVALID_PARAMETER,
45 "Tag already exists in sources hash table.");
47 SP_RETVM_IF(!g_hash_table_insert(pool->sources, src->tag_name, src),
48 SOUND_POOL_ERROR_INVALID_OPERATION, "Error occurred when adding "
49 "the source tagged [%s] to the sound pool", src->tag_name);
52 return SOUND_POOL_ERROR_NONE;
55 static int __sound_pool_remove_source(sound_pool_t *pool, sound_source_t *src)
58 SP_INST_CHECK(pool, SOUND_POOL_ERROR_INVALID_PARAMETER);
59 SP_INST_CHECK(pool->sources, SOUND_POOL_ERROR_INVALID_PARAMETER);
60 SP_INST_CHECK(src, SOUND_POOL_ERROR_INVALID_PARAMETER);
62 if (src->parent_pool == pool && src->tag_name) {
63 if (!g_hash_table_steal(pool->sources, src->tag_name)) {
64 SP_DEBUG("Tag [%s] doesn't exist in sources hash table",
67 return SOUND_POOL_ERROR_NONE;
71 g_hash_table_iter_init(&iter, pool->streams);
72 while (g_hash_table_iter_next(&iter, &key, &value)) {
73 guint size_before = g_hash_table_size(pool->streams);
74 gchar *tag = (gchar*)key;
75 sound_stream_t *stream = (sound_stream_t*)value;
76 SP_INFO("(%s)(%s)", src->tag_name, stream->parent_source->tag_name);
77 if (src == stream->parent_source)
78 _sound_stream_destroy((sound_stream_t*)value);
79 guint size_after = g_hash_table_size(pool->streams);
80 if (size_before != size_after)
81 g_hash_table_iter_init(&iter, pool->streams);
84 SP_DEBUG("Source wasn't removed from sound pool as it isn't known by "
85 "the pool for which operation is performed, or tag corrupted");
89 return SOUND_POOL_ERROR_NONE;
92 sound_pool_error_e _sound_source_create(sound_pool_t *pool, const char *tag,
96 SP_RETVM_IF(!pool, SOUND_POOL_ERROR_INVALID_PARAMETER,
97 "Can't create sound source in NULL sound pool");
98 SP_RETVM_IF(!tag, SOUND_POOL_ERROR_INVALID_PARAMETER,
99 "Can't create sound source with NULL tag name");
100 SP_RETVM_IF(!src, SOUND_POOL_ERROR_INVALID_PARAMETER,
101 "Can't create sound source. Source pointer is NULL");
102 SP_RETVM_IF(strnlen(tag, MAX_TAG_LEN + 1) == MAX_TAG_LEN + 1,
103 SOUND_POOL_ERROR_INVALID_PARAMETER, "Can't create sound source "
104 "with tag name longer than %u", MAX_TAG_LEN);
105 SP_RETVM_IF(!pool->sources, SOUND_POOL_ERROR_INVALID_OPERATION, "Sound "
106 "pool to create source is corrupted: NULL sources hash table.");
107 SP_RETVM_IF(g_hash_table_contains(pool->sources, tag),
108 SOUND_POOL_ERROR_INVALID_PARAMETER,
109 "Tag already exists in sources hash table.");
111 SP_RETVM_IF(!alcMakeContextCurrent(pool->al_context),
112 SOUND_POOL_ERROR_INVALID_OPERATION,
113 "Can't set current context.");
115 sound_source_t *_src = NULL;
116 SP_RETVM_IF(!(_src = g_try_malloc0(sizeof(*_src))),
117 SOUND_POOL_ERROR_OUT_OF_MEMORY,
118 "Memory alloc failure. Can't create sound _src");
120 int ret = SOUND_POOL_ERROR_NONE;
121 alGenBuffers(1, &_src->al_buffer);
122 if (alGetError() != AL_NO_ERROR) {
123 ret = SOUND_POOL_ERROR_OUT_OF_MEMORY;
124 GOTO_FAIL("OpenAL error occurred when trying to generate Buffer id", cfail);
127 _src->parent_pool = pool;
128 _src->tag_name = NULL;
129 _src->tag_name = g_strndup(tag, MAX_TAG_LEN);
131 ret = __sound_pool_add_source(pool, _src);
132 if (ret != SOUND_POOL_ERROR_NONE)
133 GOTO_FAIL("Error occurred when trying to add source to pool", cfail);
140 ret = _sound_source_destroy(_src);
141 SP_RETVM_IF(SOUND_POOL_ERROR_NONE != ret, ret, "Error occurred during removal "
142 "of sound source[%s].", tag);
147 sound_pool_error_e _sound_source_destroy(sound_source_t *src)
150 SP_RETVM_IF(!src, SOUND_POOL_ERROR_INVALID_PARAMETER,
151 "Can't destroy NULL sound source");
153 /* If parent pool exists, then source has to be removed from the pool */
154 if (src->parent_pool && __sound_pool_remove_source(src->parent_pool, src)
155 != SOUND_POOL_ERROR_NONE)
156 SP_DEBUG("Source wasn't removed from sound pool.");
158 SP_DEBUG("Deleting OpenAL buffer with id [%u]", src->al_buffer);
159 alDeleteBuffers(1, &src->al_buffer);
161 SP_SAFE_GFREE(src->tag_name);
165 return SOUND_POOL_ERROR_NONE;
168 sound_pool_error_e _sound_source_load_from_file(sound_source_t *src,
172 SP_INST_CHECK(src, SOUND_POOL_ERROR_INVALID_PARAMETER);
173 SP_INST_CHECK(fname, SOUND_POOL_ERROR_INVALID_PARAMETER);
174 SP_INST_CHECK(src->parent_pool, SOUND_POOL_ERROR_INVALID_OPERATION);
175 SP_RETVM_IF(!alcMakeContextCurrent(src->parent_pool->al_context),
176 SOUND_POOL_ERROR_INVALID_OPERATION, "Can't set current AL context.");
178 int ret = SOUND_POOL_ERROR_NONE;
185 alutLoadWAVFile((ALbyte*)fname, &format, &data, &size, &freq, &loop);
186 SP_RETVM_IF(alGetError() != AL_NO_ERROR || !data,
187 SOUND_POOL_ERROR_NO_SUCH_FILE, "Can't load audio file. No such "
190 alBufferData(src->al_buffer, format, data, size, freq);
191 if (alGetError() != AL_NO_ERROR) {
192 SP_ERROR("Can't create audio buffer from file [%s]", fname);
193 ret = SOUND_POOL_ERROR_INVALID_OPERATION;
196 alutUnloadWAV(format, data, size, freq);
202 sound_pool_error_e _sound_pool_get_source_by_tag(sound_pool_t *pool,
203 const char *tag, sound_source_t **src)
206 SP_INST_CHECK(pool, SOUND_POOL_ERROR_INVALID_PARAMETER);
207 SP_INST_CHECK(tag, SOUND_POOL_ERROR_INVALID_PARAMETER);
208 SP_INST_CHECK(src, SOUND_POOL_ERROR_INVALID_PARAMETER);
209 SP_RETVM_IF(!pool->sources, SOUND_POOL_ERROR_INVALID_PARAMETER, "Corrupted "
210 "sound pool. Sources hash table is NULL");
212 *src = (sound_source_t *)g_hash_table_lookup(pool->sources, tag);
213 SP_RETVM_IF(!(*src), SOUND_POOL_ERROR_KEY_NOT_AVAILABLE, "Tag doesn't "
214 "exist in sources hash table");
217 return SOUND_POOL_ERROR_NONE;