Disable session backward compatibility with soundpool
[platform/core/api/sound-pool.git] / src / stream.c
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 /**
18  * @file stream.c
19  * @brief This file include implementation of protected API
20  * for the sound streams(OpenAL sources) as part of SoundPool.
21  */
22
23 #include "internal/stream.h"
24 #include "internal/priority.h"
25
26 #include "internal/stream_cb_manager.h"
27
28 static const char *__stringify_stream_state(sound_pool_stream_state_e state);
29 static void __al_source_state_cb(ALuint source, ALenum state, ALvoid *data);
30 static sound_pool_error_e __sound_pool_add_stream(sound_pool_t *pool, sound_stream_t *stream);
31 static sound_pool_error_e __sound_pool_remove_stream(sound_pool_t *pool, sound_stream_t *stream);
32
33 static const char *__stringify_stream_state(sound_pool_stream_state_e state)
34 {
35         switch (state) {
36         case SOUND_POOL_STREAM_STATE_NONE:
37                 return "SOUND_POOL_STREAM_STATE_NONE";
38         case SOUND_POOL_STREAM_STATE_PLAYING:
39                 return "SOUND_POOL_STREAM_STATE_PLAYING";
40         case SOUND_POOL_STREAM_STATE_PAUSED:
41                 return "SOUND_POOL_STREAM_STATE_PAUSED";
42         case SOUND_POOL_STREAM_STATE_SUSPENDED:
43                 return "SOUND_POOL_STREAM_STATE_SUSPENDED";
44         case SOUND_POOL_STREAM_STATE_STOPPED:
45                 return "SOUND_POOL_STREAM_STATE_STOPPED";
46         case SOUND_POOL_STREAM_STATE_FINISHED:
47                 return "SOUND_POOL_STREAM_STATE_FINISHED";
48         default:
49                 return "";
50         }
51 }
52
53 static void __al_source_state_cb(ALuint source, ALenum state, ALvoid *data)
54 {
55         SP_DEBUG_FENTER();
56
57         sound_stream_t *stream = (sound_stream_t *)data;
58         SP_RETM_IF(!stream, "Can't handle stream in OpenAL callback, it is NULL");
59         sound_pool_t *pool = stream->parent_source->parent_pool;
60         SP_RETM_IF(!pool, "Can't handle stream in OpenAL callback, stream's sound "
61                         "pool is NULL");
62
63         stream->state_previous = stream->state;
64
65         switch (state) {
66         case AL_INITIAL:
67                 stream->state = SOUND_POOL_STREAM_STATE_NONE;
68                 break;
69         case AL_PLAYING:
70                 stream->state = SOUND_POOL_STREAM_STATE_PLAYING;
71                 break;
72         case AL_PAUSED:
73                 if (pool->state == SOUND_POOL_STATE_INACTIVE) {
74                         stream->state = SOUND_POOL_STREAM_STATE_SUSPENDED;
75                 } else if (pool->state == SOUND_POOL_STATE_ACTIVE) {
76                         if (stream->suspended) { /* Stream stopped due to priority issue */
77                                 stream->state = SOUND_POOL_STREAM_STATE_SUSPENDED;
78                         } else {
79                                 stream->state = SOUND_POOL_STREAM_STATE_PAUSED;
80                         }
81                 }
82                 break;
83         case AL_STOPPED:
84                 if (stream->stopped)
85                         stream->state = SOUND_POOL_STREAM_STATE_STOPPED;
86                 else
87                         stream->state = SOUND_POOL_STREAM_STATE_FINISHED;
88                 break;
89         default:
90                 SP_ERROR("Invalid OpenAl state value [%#04x]", state);
91                 return;
92         }
93
94         SP_INFO("Stream [%s:%d] state changed from [%s] to [%s]",
95                         stream->parent_source->tag_name, stream->id,
96                         __stringify_stream_state(stream->state_previous),
97                         __stringify_stream_state(stream->state));
98
99         SP_RETM_IF(_stream_cb_manager_register_event(pool->cbmgr, stream) !=
100                         SOUND_POOL_ERROR_NONE, "State changing event wasn't registered."
101                         "Callbacks will be not called");
102
103         SP_DEBUG_FLEAVE();
104 }
105
106 static sound_pool_error_e __sound_pool_add_stream(sound_pool_t *pool,
107                 sound_stream_t *stream)
108 {
109         SP_DEBUG_FENTER();
110         SP_INST_CHECK(pool, SOUND_POOL_ERROR_INVALID_PARAMETER);
111         SP_INST_CHECK(stream, SOUND_POOL_ERROR_INVALID_PARAMETER);
112         SP_RETVM_IF(!pool->streams, SOUND_POOL_ERROR_INVALID_OPERATION, "Sound "
113                         "pool to add the stream is corrupted: NULL streams hash table");
114         stream->id = ++(pool->max_stream_index);
115         SP_DEBUG("Id assigned to the stream is [%u]", stream->id);
116         SP_RETVM_IF(g_hash_table_contains(pool->streams, (gpointer)&stream->id),
117                         SOUND_POOL_ERROR_INVALID_PARAMETER,
118                         "Stream ID already exists in streams hash table.");
119         SP_RETVM_IF(stream->parent_source->parent_pool != pool,
120                         SOUND_POOL_ERROR_INVALID_OPERATION, "Sound stream can't be added "
121                         "to the pool different to the pool for which sound stream was created");
122
123         SP_RETVM_IF(!g_hash_table_insert(pool->streams, (gpointer)&stream->id, stream),
124                         SOUND_POOL_ERROR_INVALID_OPERATION, "Error occurred when adding "
125                         "the stream [%u] to the sound pool", stream->id);
126
127         sound_pool_error_e ret =
128                         _sound_stream_priority_add_stream(pool->mgr_priority, stream);
129         SP_RETVM_IF(SOUND_POOL_ERROR_NONE != ret, ret, "Error occurred when adding "
130                         "the stream [%u] to the priority queue.", stream->id);
131
132         SP_DEBUG_FLEAVE();
133         return SOUND_POOL_ERROR_NONE;
134 }
135
136 static sound_pool_error_e __sound_pool_remove_stream(sound_pool_t *pool, sound_stream_t *stream)
137 {
138         SP_DEBUG_FENTER();
139         SP_INST_CHECK(pool, SOUND_POOL_ERROR_INVALID_PARAMETER);
140         SP_INST_CHECK(pool->mgr_priority, SOUND_POOL_ERROR_INVALID_PARAMETER);
141         SP_INST_CHECK(stream, SOUND_POOL_ERROR_INVALID_PARAMETER);
142         SP_INST_CHECK(stream->parent_source, SOUND_POOL_ERROR_INVALID_PARAMETER);
143
144         if (stream->parent_source->parent_pool == pool) {
145                 if (!g_hash_table_remove(pool->streams, &stream->id)
146                                 || SOUND_POOL_ERROR_NONE
147                                                 != _sound_stream_priority_remove_stream(pool->mgr_priority,
148                                                                 stream))
149                         SP_DEBUG("Id [%u] doesn't exist in streams hash table", stream->id);
150                 else
151                         SP_INFO("[%u] sound stream was removed from pool", stream->id);
152         } else {
153                 SP_DEBUG("Stream wasn't removed from sound pool as it isn't known by "
154                                 "the pool for which operation is performed");
155         }
156
157         SP_DEBUG_FLEAVE();
158         return SOUND_POOL_ERROR_NONE;
159 }
160
161 static sound_pool_error_e __sound_stream_init(sound_stream_t *stream,
162                 unsigned loop, float volume, unsigned priority, sound_pool_stream_priority_policy_e priority_policy,
163                 sound_pool_stream_state_changed_cb cb, void *data)
164 {
165         SP_DEBUG_FENTER();
166         sound_pool_error_e ret = SOUND_POOL_ERROR_NONE;
167
168         if (cb) {
169                 ret = _sound_stream_set_callback(stream, cb, data);
170                 SP_RETVM_IF(ret != SOUND_POOL_ERROR_NONE, ret,
171                                 "Error occurred when setting sound stream callback");
172         }
173
174         ret = _sound_stream_set_loop(stream, loop);
175         SP_RETVM_IF(ret != SOUND_POOL_ERROR_NONE, ret,
176                         "Error occurred when setting sound stream loop parameter");
177
178         ret = _sound_stream_set_volume(stream, volume);
179         SP_RETVM_IF(ret != SOUND_POOL_ERROR_NONE, ret,
180                         "Error occurred when setting sound stream volume parameter");
181
182         ret = _sound_stream_set_priority(stream, priority);
183         SP_RETVM_IF(ret != SOUND_POOL_ERROR_NONE, ret,
184                         "Error occurred when setting sound stream priority parameter");
185
186         ret = _sound_stream_set_priority_policy(stream, priority_policy);
187         SP_RETVM_IF(ret != SOUND_POOL_ERROR_NONE, ret,
188                         "Error occurred when setting sound stream priority_policy parameter");
189
190         SP_DEBUG_FLEAVE();
191         return ret;
192 }
193
194 sound_pool_error_e _sound_stream_create(sound_source_t *src, unsigned loop,
195                 float volume, unsigned priority, sound_pool_stream_priority_policy_e priority_policy,
196                 sound_pool_stream_state_changed_cb cb,
197                 void *data, sound_stream_t **stream)
198 {
199         SP_DEBUG_FENTER();
200         SP_RETVM_IF(!src, SOUND_POOL_ERROR_INVALID_PARAMETER,
201                         "Can't create sound stream in NULL sound source");
202         SP_RETVM_IF(!stream, SOUND_POOL_ERROR_INVALID_PARAMETER,
203                         "Can't create sound stream. Stream pointer is NULL");
204         SP_RETVM_IF(!src->parent_pool, SOUND_POOL_ERROR_INVALID_PARAMETER,
205                         "Can't create sound stream. Source's pool is NULL");
206
207         SP_RETVM_IF(!alcMakeContextCurrent(src->parent_pool->al_context),
208                         SOUND_POOL_ERROR_INVALID_OPERATION, "Can't set current context.");
209
210         sound_pool_error_e ret = SOUND_POOL_ERROR_NONE;
211         sound_stream_t *_stream = NULL;
212         SP_RETVM_IF(!(_stream = g_try_malloc0(sizeof(*_stream))),
213                         SOUND_POOL_ERROR_OUT_OF_MEMORY,
214                         "Memory alloc failure. Can't create sound stream");
215
216         _stream->parent_source = src;
217         _stream->state_previous = SOUND_POOL_STREAM_STATE_NONE;
218         _stream->state = SOUND_POOL_STREAM_STATE_NONE;
219         _stream->stopped = FALSE;
220
221         alGenSources((ALsizei)1, &_stream->al_source);
222         if (alGetError() != AL_NO_ERROR) {
223                 ret = SOUND_POOL_ERROR_OUT_OF_MEMORY;
224                 GOTO_FAIL("OpenAL error occurred when trying to generate OpenAL Source",
225                                 cfail);
226         }
227
228         alSourcei(_stream->al_source, AL_BUFFER, src->al_buffer);
229         if (alGetError() != AL_NO_ERROR) {
230                 ret = SOUND_POOL_ERROR_INVALID_OPERATION;
231                 GOTO_FAIL("OpenAL error occurred when trying to assign OpenAL Buffer "
232                                 "to OpenAL Source", cfail);
233         }
234
235         alSourcep(_stream->al_source, AL_SOURCE_STATE_CALLBACK,
236                         (ALvoid *)__al_source_state_cb);
237         if (alGetError() != AL_NO_ERROR) {
238                 ret = SOUND_POOL_ERROR_INVALID_OPERATION;
239                 GOTO_FAIL("OpenAL error occurred when trying to assign OpenAL Callback "
240                                 "to OpenAL Source", cfail);
241         }
242
243         alSourcep(_stream->al_source, AL_SOURCE_STATE_CALLBACK_DATA, (ALvoid *)_stream);
244         if (alGetError() != AL_NO_ERROR) {
245                 ret = SOUND_POOL_ERROR_INVALID_OPERATION;
246                 GOTO_FAIL("OpenAL error occurred when trying to assign OpenAL Callback "
247                                 "Data to OpenAL Source", cfail);
248         }
249
250         ret = __sound_stream_init(_stream, loop, volume, priority, priority_policy, cb, data);
251         if (ret != SOUND_POOL_ERROR_NONE)
252                 GOTO_FAIL("Sound stream initialization error occurred", cfail);
253
254         ret = __sound_pool_add_stream(src->parent_pool, _stream);
255         if (ret != SOUND_POOL_ERROR_NONE)
256                 GOTO_FAIL("Error occurred when trying to add source to pool", cfail);
257
258         *stream = _stream;
259         SP_DEBUG_FLEAVE();
260         return ret;
261
262 cfail:
263         if (SOUND_POOL_ERROR_NONE == _sound_stream_destroy(_stream))
264                 _stream = NULL;
265
266         SP_SAFE_GFREE(_stream);
267
268         SP_DEBUG_FLEAVE();
269         return ret;
270 }
271
272 sound_pool_error_e _sound_stream_destroy(sound_stream_t *stream)
273 {
274         SP_DEBUG_FENTER();
275         SP_RETVM_IF(!stream, SOUND_POOL_ERROR_INVALID_PARAMETER,
276                         "Can't destroy NULL sound stream");
277         SP_RETVM_IF(!stream->parent_source, SOUND_POOL_ERROR_INVALID_PARAMETER,
278                         "Invalid parent source.");
279         SP_RETVM_IF(!stream->parent_source->parent_pool, SOUND_POOL_ERROR_INVALID_PARAMETER,
280                         "Empty parent pool pointer.");
281
282         if (stream->parent_source) {
283                 if (__sound_pool_remove_stream(stream->parent_source->parent_pool,
284                                 stream) != SOUND_POOL_ERROR_NONE)
285                         SP_DEBUG("Stream[%s] wasn't removed from sound pool. Continue destroying",
286                                         stream->parent_source->tag_name);
287                 if (alcMakeContextCurrent(stream->parent_source->parent_pool->al_context)) {
288                         alSourcei(stream->al_source, AL_BUFFER, 0);
289                         alDeleteSources(1, &stream->al_source);
290                         SP_DEBUG("Deleting OpenAL source with id [%u]", stream->al_source);
291                         if (alGetError() != AL_NO_ERROR)
292                                 SP_ERROR("OpenAL error while stream[%d] destroying.", stream->id);
293                 } else {
294                         SP_DEBUG("Can't set current context for deleting OpenAL source with id [%u]",
295                                         stream->al_source);
296                 }
297         }
298
299         SP_SAFE_GFREE(stream);
300
301         SP_DEBUG_FLEAVE();
302         return SOUND_POOL_ERROR_NONE;
303 }
304
305 sound_pool_error_e _sound_stream_play(sound_stream_t *stream)
306 {
307         SP_DEBUG_FENTER();
308         SP_INST_CHECK(stream, SOUND_POOL_ERROR_INVALID_PARAMETER);
309         SP_INST_CHECK(stream->parent_source, SOUND_POOL_ERROR_INVALID_PARAMETER);
310         sound_pool_t *pool = stream->parent_source->parent_pool;
311         sound_pool_error_e ret = SOUND_POOL_ERROR_NONE;
312         SP_INST_CHECK(pool, SOUND_POOL_ERROR_INVALID_PARAMETER);
313         SP_RETVM_IF(stream->state != SOUND_POOL_STREAM_STATE_SUSPENDED &&
314                         stream->state != SOUND_POOL_STREAM_STATE_PAUSED &&
315                         stream->state != SOUND_POOL_STREAM_STATE_NONE,
316                         SOUND_POOL_ERROR_INVALID_OPERATION, "Can't play stream[%s] in [%s] "
317                         "state", stream->parent_source->tag_name, __stringify_stream_state(stream->state));
318         SP_RETVM_IF(stream->state == SOUND_POOL_STREAM_STATE_SUSPENDED &&
319                         pool->state == SOUND_POOL_STATE_INACTIVE,
320                         SOUND_POOL_ERROR_INVALID_OPERATION, "Can't play suspended stream "
321                         "in inactive sound pool");
322
323         SP_RETVM_IF(!alcMakeContextCurrent(pool->al_context),
324                         SOUND_POOL_ERROR_INVALID_OPERATION, "Can't set current context.");
325
326         alSourcePlay(stream->al_source);
327         SP_RETVM_IF(alGetError() != AL_NO_ERROR, SOUND_POOL_ERROR_INVALID_OPERATION,
328                                         "OpenAL error occured when trying to play OpenAL Source");
329
330         SP_DEBUG_FLEAVE();
331         return ret;
332 }
333
334 sound_pool_error_e  _sound_stream_suspend(sound_stream_t *stream)
335 {
336         SP_DEBUG_FENTER();
337         SP_INST_CHECK(stream, SOUND_POOL_ERROR_INVALID_PARAMETER);
338         SP_INST_CHECK(stream->parent_source, SOUND_POOL_ERROR_INVALID_PARAMETER);
339         sound_pool_error_e ret = SOUND_POOL_ERROR_NONE;
340         stream->suspended = TRUE; /* Shows it was stopped due to priority */
341         alSourcePause(stream->al_source);
342         stream->suspended = FALSE;
343
344         SP_DEBUG_FLEAVE();
345         return ret;
346 }
347
348 sound_pool_error_e _sound_stream_send_event(sound_stream_t *stream, sound_pool_stream_state_e state)
349 {
350         SP_DEBUG_FENTER();
351         sound_pool_t *pool = stream->parent_source->parent_pool;
352         sound_pool_error_e ret = SOUND_POOL_ERROR_NONE;
353         stream->state_previous = stream->state;
354         stream->state = state;
355         ret = _stream_cb_manager_register_event(pool->cbmgr, stream);
356         SP_RETVM_IF(SOUND_POOL_ERROR_NONE != ret, ret, "State changing event "
357                                 "wasn't registered. Callbacks will be not called");
358
359         SP_DEBUG_FLEAVE();
360         return ret;
361 }
362
363 sound_pool_error_e _sound_stream_pause(sound_stream_t *stream)
364 {
365         SP_DEBUG_FENTER();
366         SP_INST_CHECK(stream, SOUND_POOL_ERROR_INVALID_PARAMETER);
367         SP_INST_CHECK(stream->parent_source, SOUND_POOL_ERROR_INVALID_PARAMETER);
368         sound_pool_t *pool = stream->parent_source->parent_pool;
369         sound_pool_error_e ret = SOUND_POOL_ERROR_NONE;
370         SP_INST_CHECK(pool, SOUND_POOL_ERROR_INVALID_PARAMETER);
371         SP_RETVM_IF(stream->state != SOUND_POOL_STREAM_STATE_SUSPENDED &&
372                         stream->state != SOUND_POOL_STREAM_STATE_PLAYING,
373                         SOUND_POOL_ERROR_INVALID_OPERATION, "Can't pause stream in [%s] "
374                         "state", __stringify_stream_state(stream->state));
375
376         SP_RETVM_IF(!alcMakeContextCurrent(pool->al_context),
377                         SOUND_POOL_ERROR_INVALID_OPERATION, "Can't set current context.");
378
379         if (pool->state == SOUND_POOL_STATE_INACTIVE &&
380                         stream->state == SOUND_POOL_STREAM_STATE_SUSPENDED) {
381                 ret = _sound_stream_send_event(stream, SOUND_POOL_STREAM_STATE_PAUSED);
382                 SP_INFO("Don't paused due to SoundPool is in inactive state.");
383         } else {
384                 alSourcePause(stream->al_source);
385         }
386
387         SP_DEBUG_FLEAVE();
388         return ret;
389 }
390
391 sound_pool_error_e _sound_stream_resume(sound_stream_t *stream)
392 {
393         SP_DEBUG_FENTER();
394         SP_INST_CHECK(stream, SOUND_POOL_ERROR_INVALID_PARAMETER);
395         SP_INST_CHECK(stream->parent_source, SOUND_POOL_ERROR_INVALID_PARAMETER);
396         sound_pool_t *pool = stream->parent_source->parent_pool;
397         sound_pool_error_e ret = SOUND_POOL_ERROR_NONE;
398         SP_INST_CHECK(pool, SOUND_POOL_ERROR_INVALID_PARAMETER);
399         SP_RETVM_IF(stream->state != SOUND_POOL_STREAM_STATE_PAUSED,
400                         SOUND_POOL_ERROR_INVALID_OPERATION, "Can't resume stream in [%s] "
401                         "state", __stringify_stream_state(stream->state));
402
403         SP_RETVM_IF(!alcMakeContextCurrent(pool->al_context),
404                         SOUND_POOL_ERROR_INVALID_OPERATION, "Can't set current context.");
405
406         if (pool->state == SOUND_POOL_STATE_INACTIVE &&
407                         stream->state == SOUND_POOL_STREAM_STATE_PAUSED) {
408                 ret = _sound_stream_send_event(stream, SOUND_POOL_STREAM_STATE_SUSPENDED);
409                 SP_INFO("Don't resumed due to SoundPool is in inactive state.");
410         } else {
411                 alSourcePlay(stream->al_source);
412         }
413
414         SP_DEBUG_FLEAVE();
415         return ret;
416 }
417
418 sound_pool_error_e _sound_stream_stop(sound_stream_t *stream)
419 {
420         SP_DEBUG_FENTER();
421         SP_INST_CHECK(stream, SOUND_POOL_ERROR_INVALID_PARAMETER);
422         SP_INST_CHECK(stream->parent_source, SOUND_POOL_ERROR_INVALID_PARAMETER);
423         sound_pool_t *pool = stream->parent_source->parent_pool;
424         SP_INST_CHECK(pool, SOUND_POOL_ERROR_INVALID_PARAMETER);
425         SP_RETVM_IF(stream->state != SOUND_POOL_STREAM_STATE_PLAYING &&
426                         stream->state != SOUND_POOL_STREAM_STATE_SUSPENDED &&
427                         stream->state != SOUND_POOL_STREAM_STATE_PAUSED,
428                         SOUND_POOL_ERROR_INVALID_OPERATION, "Can't stop stream in [%s] "
429                         "state", __stringify_stream_state(stream->state));
430
431         SP_RETVM_IF(!alcMakeContextCurrent(pool->al_context),
432                         SOUND_POOL_ERROR_INVALID_OPERATION, "Can't set current context.");
433
434         stream->stopped = TRUE;
435         alSourceStop(stream->al_source);
436
437         SP_DEBUG_FLEAVE();
438         return SOUND_POOL_ERROR_NONE;
439 }
440
441 sound_pool_error_e _sound_stream_set_loop(sound_stream_t *stream, unsigned loop)
442 {
443         SP_DEBUG_FENTER();
444         SP_INST_CHECK(stream, SOUND_POOL_ERROR_INVALID_PARAMETER);
445         sound_pool_t *pool = stream->parent_source->parent_pool;
446         SP_INST_CHECK(pool, SOUND_POOL_ERROR_INVALID_PARAMETER);
447         SP_RETVM_IF(!alcMakeContextCurrent(pool->al_context),
448                         SOUND_POOL_ERROR_INVALID_OPERATION, "Can't set current context.");
449
450         alSourcei(stream->al_source, AL_LOOP_COUNT, (ALint)loop);
451         stream->loop = loop;
452
453         SP_DEBUG_FLEAVE();
454         return SOUND_POOL_ERROR_NONE;
455 }
456
457 sound_pool_error_e _sound_stream_set_volume(sound_stream_t *stream, float volume)
458 {
459         SP_DEBUG_FENTER();
460         SP_INST_CHECK(stream, SOUND_POOL_ERROR_INVALID_PARAMETER);
461         SP_RETVM_IF((volume < 0.0f || volume > 1.0f),
462                         SOUND_POOL_ERROR_INVALID_PARAMETER,
463                         "Volume for sound stream should be in range 0.0..1.0.");
464         sound_pool_t *pool = stream->parent_source->parent_pool;
465         SP_INST_CHECK(pool, SOUND_POOL_ERROR_INVALID_PARAMETER);
466         SP_RETVM_IF(!alcMakeContextCurrent(pool->al_context),
467                         SOUND_POOL_ERROR_INVALID_OPERATION, "Can't set current context.");
468
469         alSourcef(stream->al_source, AL_GAIN, volume);
470
471         stream->volume = volume;
472
473         SP_DEBUG_FLEAVE();
474         return SOUND_POOL_ERROR_NONE;
475 }
476
477 sound_pool_error_e _sound_stream_set_mute(sound_stream_t *stream, gboolean mute)
478 {
479         SP_DEBUG_FENTER();
480
481         SP_INST_CHECK(stream, SOUND_POOL_ERROR_INVALID_PARAMETER);
482
483         sound_pool_t *pool = stream->parent_source->parent_pool;
484         SP_INST_CHECK(pool, SOUND_POOL_ERROR_INVALID_PARAMETER);
485         SP_RETVM_IF(!alcMakeContextCurrent(pool->al_context),
486                         SOUND_POOL_ERROR_INVALID_OPERATION, "Can't set current context.");
487
488         alSourcef(stream->al_source, AL_GAIN, ((int)!mute * stream->volume));
489         stream->mute = mute;
490
491         SP_DEBUG_FLEAVE();
492         return SOUND_POOL_ERROR_NONE;
493 }
494
495 sound_pool_error_e _sound_stream_get_volume(sound_stream_t *stream, float *volume)
496 {
497         SP_DEBUG_FENTER();
498         SP_INST_CHECK(stream, SOUND_POOL_ERROR_INVALID_PARAMETER);
499         SP_INST_CHECK(volume, SOUND_POOL_ERROR_INVALID_PARAMETER);
500
501         *volume = stream->volume;
502
503         SP_DEBUG_FLEAVE();
504         return SOUND_POOL_ERROR_NONE;
505 }
506
507 sound_pool_error_e _sound_stream_get_state(sound_stream_t *stream,
508                 sound_pool_stream_state_e *state)
509 {
510         SP_DEBUG_FENTER();
511         SP_INST_CHECK(stream, SOUND_POOL_ERROR_INVALID_PARAMETER);
512         SP_INST_CHECK(state, SOUND_POOL_ERROR_INVALID_PARAMETER);
513
514         *state = stream->state;
515
516         if (stream->mute)
517                 SP_DEBUG(" Stream is in Mute.");
518
519         SP_DEBUG_FLEAVE();
520         return SOUND_POOL_ERROR_NONE;
521 }
522
523 sound_pool_error_e _sound_stream_set_priority(sound_stream_t *stream,
524                 unsigned rank)
525 {
526         SP_DEBUG_FENTER();
527         SP_INST_CHECK(stream, SOUND_POOL_ERROR_INVALID_PARAMETER);
528         SP_INST_CHECK(stream->parent_source, SOUND_POOL_ERROR_INVALID_PARAMETER);
529         SP_INST_CHECK(stream->parent_source->parent_pool, SOUND_POOL_ERROR_INVALID_PARAMETER);
530         SP_INST_CHECK(stream->parent_source->parent_pool->mgr_priority,
531                         SOUND_POOL_ERROR_INVALID_PARAMETER);
532         sound_pool_error_e ret = SOUND_POOL_ERROR_NONE;
533
534         stream->priority = rank;
535         if (stream->parent_source->parent_pool->state == SOUND_POOL_STATE_INACTIVE) {
536                 if (stream->state == SOUND_POOL_STREAM_STATE_NONE) {
537                         ret = _sound_stream_send_event(stream, SOUND_POOL_STREAM_STATE_SUSPENDED);
538                         SP_RETVM_IF(SOUND_POOL_ERROR_NONE != ret, ret, "Error occured during"
539                                         "send event");
540                 }
541                 SP_DEBUG("No need to update priority, Sound pool is INACTIVE.");
542                 return SOUND_POOL_ERROR_NONE;
543         }
544
545         _sound_stream_priority_update_playback(stream->parent_source->parent_pool->mgr_priority);
546
547         SP_DEBUG_FLEAVE();
548         return SOUND_POOL_ERROR_NONE;
549 }
550
551 sound_pool_error_e _sound_stream_set_priority_policy(sound_stream_t *stream,
552                 sound_pool_stream_priority_policy_e priority_policy)
553 {
554         SP_DEBUG_FENTER();
555         SP_INST_CHECK(stream, SOUND_POOL_ERROR_INVALID_PARAMETER);
556         SP_INST_CHECK(stream->parent_source, SOUND_POOL_ERROR_INVALID_PARAMETER);
557         SP_INST_CHECK(stream->parent_source->parent_pool, SOUND_POOL_ERROR_INVALID_PARAMETER);
558         SP_INST_CHECK(stream->parent_source->parent_pool->mgr_priority,
559                         SOUND_POOL_ERROR_INVALID_PARAMETER);
560
561         SP_RETVM_IF((priority_policy > SOUND_POOL_STREAM_PRIORITY_POLICY_SUSPENDED),
562                         SOUND_POOL_ERROR_INVALID_PARAMETER,
563                         "Priority policy can be 0 or 1.");
564
565
566         stream->priority_policy = priority_policy;
567
568         SP_INFO("Priority policy is %d.", stream->priority_policy);
569         SP_DEBUG_FLEAVE();
570         return SOUND_POOL_ERROR_NONE;
571 }
572
573 sound_pool_error_e _sound_stream_get_priority(sound_stream_t *stream,
574                 unsigned *rank)
575 {
576         SP_DEBUG_FENTER();
577         SP_INST_CHECK(stream, SOUND_POOL_ERROR_INVALID_PARAMETER);
578         SP_INST_CHECK(rank, SOUND_POOL_ERROR_INVALID_PARAMETER);
579
580         *rank = stream->priority;
581
582         SP_DEBUG_FLEAVE();
583         return SOUND_POOL_ERROR_NONE;
584 }
585
586 sound_pool_error_e _sound_stream_set_callback(sound_stream_t *stream,
587                 sound_pool_stream_state_changed_cb callback, void *data)
588 {
589         SP_DEBUG_FENTER();
590         SP_INST_CHECK(stream, SOUND_POOL_ERROR_INVALID_PARAMETER);
591         SP_INST_CHECK(callback, SOUND_POOL_ERROR_INVALID_PARAMETER);
592
593         stream->state_cb_info.callback = callback;
594         stream->state_cb_info.user_data = data;
595
596         SP_DEBUG_FLEAVE();
597         return SOUND_POOL_ERROR_NONE;
598 }
599
600 sound_pool_error_e _sound_pool_get_stream_by_id(sound_pool_t *pool, unsigned id,
601                 sound_stream_t **stream)
602 {
603         SP_DEBUG_FENTER();
604         SP_INST_CHECK(pool, SOUND_POOL_ERROR_INVALID_PARAMETER);
605         SP_INST_CHECK(stream, SOUND_POOL_ERROR_INVALID_PARAMETER);
606
607         SP_RETVM_IF(!pool->streams, SOUND_POOL_ERROR_INVALID_OPERATION, "Corrupted "
608                         "sound pool. Sources hash table is NULL");
609
610         *stream = (sound_stream_t *)g_hash_table_lookup(pool->streams, &id);
611         SP_RETVM_IF(!(*stream), SOUND_POOL_ERROR_KEY_NOT_AVAILABLE, "Tag doesn't "
612                         "exist in sources hash table");
613
614         SP_DEBUG_FLEAVE();
615         return SOUND_POOL_ERROR_NONE;
616 }