1 /* OpenSL: The Standard for Embedded Audio Acceleration
2 * http://www.khronos.org/opensles/
3 * http://www.khronos.org/registry/sles/specs/OpenSL_ES_Specification_1.1.pdf
4 */
5
6 #include "allegro5/allegro.h"
7 #include "allegro5/internal/aintern_audio.h"
8
9 #include <SLES/OpenSLES.h>
10
11 /* TODO:
12 * If an android application goes into the suspend state then the opensl resources
13 * might become 'unrealized' or 'suspended' so care needs to be taken
14 * to realize them again once the application is resumed.
15 */
16
17 /* Not sure if this one is needed, yet */
18 // #include <SLES/OpenSLES_Android.h>
19
20 /* Feel free to change MAX_FRAMES and MAX_BUFFERS if it affects
21 * choppiness for your device.
22 */
23
24 /* Number of samples to read in one call to al_voice_update */
25 static const int MAX_FRAMES = 2048;
26
27 /* Number of opensl buffers to use */
28 #define MAX_BUFFERS 2
29
30 ALLEGRO_DEBUG_CHANNEL("opensl")
31
32 static SLObjectItf engine;
33
opensl_get_error_string(SLresult result)34 static const char * opensl_get_error_string(SLresult result)
35 {
36 switch (result){
37 case SL_RESULT_PRECONDITIONS_VIOLATED: return "Preconditions violated";
38 case SL_RESULT_PARAMETER_INVALID: return "Invalid parameter";
39 case SL_RESULT_MEMORY_FAILURE: return "Memory failure";
40 case SL_RESULT_RESOURCE_ERROR: return "Resource error";
41 case SL_RESULT_RESOURCE_LOST: return "Resource lost";
42 case SL_RESULT_IO_ERROR: return "IO error";
43 case SL_RESULT_BUFFER_INSUFFICIENT: return "Insufficient buffer";
44 case SL_RESULT_CONTENT_CORRUPTED: return "Content corrupted";
45 case SL_RESULT_CONTENT_UNSUPPORTED: return "Content unsupported";
46 case SL_RESULT_CONTENT_NOT_FOUND: return "Content not found";
47 case SL_RESULT_PERMISSION_DENIED: return "Permission denied";
48 case SL_RESULT_FEATURE_UNSUPPORTED: return "Feature unsupported";
49 case SL_RESULT_INTERNAL_ERROR: return "Internal error";
50 case SL_RESULT_UNKNOWN_ERROR: return "Unknown error";
51 case SL_RESULT_OPERATION_ABORTED: return "Operation aborted";
52 case SL_RESULT_CONTROL_LOST: return "Control lost";
53 }
54 return "Unknown OpenSL error";
55 }
56
57 /* Only the original 'engine' object should be passed here */
getEngine(SLObjectItf engine)58 static SLEngineItf getEngine(SLObjectItf engine){
59 SLresult result;
60 SLEngineItf interface;
61 result = (*engine)->GetInterface(engine, SL_IID_ENGINE, &interface);
62 if (result == SL_RESULT_SUCCESS){
63 return interface;
64 } else {
65 ALLEGRO_ERROR("Could not get opensl engine: %s\n", opensl_get_error_string(result));
66 return NULL;
67 }
68 }
69
70 /* Create an output mixer */
createOutputMixer(SLEngineItf engine)71 static SLObjectItf createOutputMixer(SLEngineItf engine){
72 SLresult result;
73 SLObjectItf output;
74 SLboolean required[1];
75 SLInterfaceID ids[1];
76
77 /* Not all android devices support a mixer that you can control
78 * the volume on, so just ignore it for now.
79 */
80 required[0] = SL_BOOLEAN_TRUE;
81 ids[0] = SL_IID_VOLUME;
82
83 result = (*engine)->CreateOutputMix(engine, &output, 0, ids, required);
84 if (result != SL_RESULT_SUCCESS){
85 ALLEGRO_ERROR("Could not create output mix: %s\n", opensl_get_error_string(result));
86 return NULL;
87 }
88
89 result = (*output)->Realize(output, SL_BOOLEAN_FALSE);
90 if (result != SL_RESULT_SUCCESS){
91 ALLEGRO_ERROR("Could not realize the output mix: %s\n", opensl_get_error_string(result));
92 (*output)->Destroy(output);
93 return NULL;
94 }
95
96 return output;
97 }
98
_opensl_open(void)99 static int _opensl_open(void)
100 {
101 SLresult result;
102 SLuint32 state;
103 SLEngineOption options[] = {
104 { SL_ENGINEOPTION_THREADSAFE, (SLuint32) SL_BOOLEAN_TRUE },
105 /*
106 { SL_ENGINEOPTION_MAJORVERSION, (SLuint32) 1 },
107 { SL_ENGINEOPTION_MINORVERSION, (SLuint32) 1 },
108 */
109 };
110
111 result = slCreateEngine(&engine, 1, options, 0, NULL, NULL);
112 if (result != SL_RESULT_SUCCESS){
113 ALLEGRO_ERROR("Could not open audio device: %s\n",
114 opensl_get_error_string(result));
115 return 1;
116 }
117
118 /* Transition the engine to the realized state in synchronous mode */
119 result = (*engine)->GetState(engine, &state);
120 if (result == SL_RESULT_SUCCESS){
121 switch (state){
122 case SL_OBJECT_STATE_UNREALIZED: {
123 result = (*engine)->Realize(engine, SL_BOOLEAN_FALSE);
124 break;
125 }
126 case SL_OBJECT_STATE_REALIZED: {
127 /* This is good */
128 break;
129 }
130 case SL_OBJECT_STATE_SUSPENDED: {
131 result = (*engine)->Resume(engine, SL_BOOLEAN_FALSE);
132 break;
133 }
134 }
135 } else {
136 return 1;
137 }
138
139 // output = createOutputMixer(getEngine(engine));
140
141 return 0;
142 }
143
_opensl_close(void)144 static void _opensl_close(void)
145 {
146 /*
147 if (output != NULL){
148 (*output)->Destroy(output);
149 output = NULL;
150 }
151 */
152
153 if (engine != NULL){
154 (*engine)->Destroy(engine);
155 engine = NULL;
156 }
157 }
158
159 typedef struct OpenSLData{
160 /* Output mixer */
161 SLObjectItf output;
162 /* Audio player */
163 SLObjectItf player;
164 volatile enum { PLAYING, STOPPING, STOPPED } status;
165
166 /* load_voice stuff that isn't used, but might be someday */
167 /*
168 const void * data;
169 int position;
170 int length;
171 */
172
173 /* Size of a single sample: depth * channels */
174 int frame_size;
175 ALLEGRO_THREAD * poll_thread;
176
177 /* local buffers to keep opensl fed since it doesn't copy
178 * data by default.
179 */
180 char * buffers[MAX_BUFFERS];
181 } OpenSLData;
182
setupFormat(ALLEGRO_VOICE * voice)183 static SLDataFormat_PCM setupFormat(ALLEGRO_VOICE * voice){
184 SLDataFormat_PCM format;
185 format.formatType = SL_DATAFORMAT_PCM;
186
187 format.numChannels = al_get_channel_count(voice->chan_conf);
188
189 /* TODO: review the channelMasks */
190 switch (voice->chan_conf){
191 case ALLEGRO_CHANNEL_CONF_1: {
192 /* Not sure if center is right.. */
193 format.channelMask = SL_SPEAKER_FRONT_CENTER;
194 break;
195 }
196 case ALLEGRO_CHANNEL_CONF_2: {
197 format.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
198 break;
199 }
200 case ALLEGRO_CHANNEL_CONF_3: {
201 format.channelMask = SL_SPEAKER_FRONT_LEFT |
202 SL_SPEAKER_FRONT_RIGHT |
203 SL_SPEAKER_FRONT_CENTER;
204 break;
205 }
206 case ALLEGRO_CHANNEL_CONF_4: {
207 format.channelMask = SL_SPEAKER_FRONT_LEFT |
208 SL_SPEAKER_BACK_LEFT |
209 SL_SPEAKER_FRONT_RIGHT |
210 SL_SPEAKER_BACK_RIGHT;
211 break;
212 }
213 case ALLEGRO_CHANNEL_CONF_5_1: {
214 format.channelMask = SL_SPEAKER_FRONT_LEFT |
215 SL_SPEAKER_BACK_LEFT |
216 SL_SPEAKER_FRONT_RIGHT |
217 SL_SPEAKER_BACK_RIGHT |
218 SL_SPEAKER_FRONT_CENTER |
219 SL_SPEAKER_LOW_FREQUENCY;
220 break;
221 }
222 case ALLEGRO_CHANNEL_CONF_6_1: {
223 format.channelMask = SL_SPEAKER_FRONT_LEFT |
224 SL_SPEAKER_BACK_LEFT |
225 SL_SPEAKER_FRONT_RIGHT |
226 SL_SPEAKER_BACK_RIGHT |
227 SL_SPEAKER_FRONT_CENTER |
228 SL_SPEAKER_LOW_FREQUENCY |
229 SL_SPEAKER_SIDE_LEFT |
230 SL_SPEAKER_SIDE_RIGHT;
231
232 break;
233 }
234 case ALLEGRO_CHANNEL_CONF_7_1: {
235 format.channelMask = SL_SPEAKER_FRONT_LEFT |
236 SL_SPEAKER_BACK_LEFT |
237 SL_SPEAKER_FRONT_RIGHT |
238 SL_SPEAKER_BACK_RIGHT |
239 SL_SPEAKER_FRONT_CENTER |
240 SL_SPEAKER_LOW_FREQUENCY |
241 SL_SPEAKER_SIDE_LEFT |
242 SL_SPEAKER_SIDE_RIGHT |
243 SL_SPEAKER_TOP_CENTER;
244 break;
245 }
246 default: {
247 ALLEGRO_ERROR("Cannot allocate voice with unknown channel configuration\n");
248 }
249 }
250
251 switch (voice->frequency){
252 case 8000: format.samplesPerSec = SL_SAMPLINGRATE_8; break;
253 case 11025: format.samplesPerSec = SL_SAMPLINGRATE_11_025; break;
254 case 12000: format.samplesPerSec = SL_SAMPLINGRATE_12; break;
255 case 16000: format.samplesPerSec = SL_SAMPLINGRATE_16; break;
256 case 22050: format.samplesPerSec = SL_SAMPLINGRATE_22_05; break;
257 case 24000: format.samplesPerSec = SL_SAMPLINGRATE_24; break;
258 case 32000: format.samplesPerSec = SL_SAMPLINGRATE_32; break;
259 case 44100: format.samplesPerSec = SL_SAMPLINGRATE_44_1; break;
260 case 48000: format.samplesPerSec = SL_SAMPLINGRATE_48; break;
261 case 64000: format.samplesPerSec = SL_SAMPLINGRATE_64; break;
262 case 88200: format.samplesPerSec = SL_SAMPLINGRATE_88_2; break;
263 case 96000: format.samplesPerSec = SL_SAMPLINGRATE_96; break;
264 case 192000: format.samplesPerSec = SL_SAMPLINGRATE_192; break;
265 default: {
266 ALLEGRO_ERROR("Unsupported frequency %d. Using 44100 instead.\n", voice->frequency);
267 format.samplesPerSec = SL_SAMPLINGRATE_44_1;
268 voice->frequency = 44100;
269 }
270 }
271
272 switch (voice->depth) {
273 case ALLEGRO_AUDIO_DEPTH_UINT8:
274 case ALLEGRO_AUDIO_DEPTH_INT8: {
275 format.bitsPerSample = 8;
276 format.containerSize = 8;
277 break;
278 }
279 case ALLEGRO_AUDIO_DEPTH_UINT16:
280 case ALLEGRO_AUDIO_DEPTH_INT16: {
281 format.bitsPerSample = 16;
282 format.containerSize = 16;
283 break;
284 }
285 case ALLEGRO_AUDIO_DEPTH_UINT24:
286 case ALLEGRO_AUDIO_DEPTH_INT24: {
287 format.bitsPerSample = 24;
288 format.containerSize = 32;
289 break;
290 }
291 case ALLEGRO_AUDIO_DEPTH_FLOAT32: {
292 format.bitsPerSample = 32;
293 format.containerSize = 32;
294 break;
295 }
296 default: {
297 ALLEGRO_WARN("Cannot allocate unknown voice depth\n");
298 }
299 }
300
301 #ifdef ALLEGRO_BIG_ENDIAN
302 format.endianness = SL_BYTEORDER_BIGENDIAN;
303 #else
304 format.endianness = SL_BYTEORDER_LITTLEENDIAN;
305 #endif
306
307 /* Then OpenSL spec says these values are needed for SLDataFormat_PCM_EX
308 * but not all implementations define that struct. If they do then
309 * the following code can be used.
310 */
311
312 /*
313 switch (voice->depth){
314 case ALLEGRO_AUDIO_DEPTH_UINT8:
315 case ALLEGRO_AUDIO_DEPTH_UINT16:
316 case ALLEGRO_AUDIO_DEPTH_UINT24: {
317 format.representation = SL_PCM_REPRESENTATION_UNSIGNED_INT;
318 }
319 case ALLEGRO_AUDIO_DEPTH_INT8:
320 case ALLEGRO_AUDIO_DEPTH_INT16:
321 case ALLEGRO_AUDIO_DEPTH_INT24: {
322 format.representation = SL_PCM_REPRESENTATION_SIGNED_INT;
323 break;
324 }
325 case ALLEGRO_AUDIO_DEPTH_FLOAT32: {
326 format.representation = SL_PCM_REPRESENTATION_FLOAT;
327 break;
328 }
329 }
330 */
331
332 return format;
333 }
334
createAudioPlayer(SLEngineItf engine,SLDataSource * source,SLDataSink * sink)335 static SLObjectItf createAudioPlayer(SLEngineItf engine, SLDataSource * source, SLDataSink * sink){
336 SLresult result;
337 SLObjectItf player;
338
339 SLboolean required[1];
340 SLInterfaceID ids[1];
341
342 required[0] = SL_BOOLEAN_TRUE;
343 ids[0] = SL_IID_BUFFERQUEUE;
344
345 result = (*engine)->CreateAudioPlayer(engine, &player, source, sink, 1, ids, required);
346 if (result != SL_RESULT_SUCCESS){
347 ALLEGRO_ERROR("Could not create audio player: %s\n", opensl_get_error_string(result));
348 return NULL;
349 }
350
351 result = (*player)->Realize(player, SL_BOOLEAN_FALSE);
352
353 if (result != SL_RESULT_SUCCESS){
354 ALLEGRO_ERROR("Could not realize audio player: %s\n", opensl_get_error_string(result));
355 return NULL;
356 }
357
358 return player;
359 }
360
makeStreamingPlayer(ALLEGRO_VOICE * voice,SLObjectItf mixer)361 static SLObjectItf makeStreamingPlayer(ALLEGRO_VOICE * voice, SLObjectItf mixer){
362 SLDataFormat_PCM format = setupFormat(voice);
363 SLDataLocator_BufferQueue bufferQueue;
364 SLDataSource audioSource;
365 SLDataSink audioSink;
366 SLDataLocator_OutputMix output;
367
368 bufferQueue.locatorType = SL_DATALOCATOR_BUFFERQUEUE;
369 bufferQueue.numBuffers = MAX_BUFFERS;
370
371 audioSource.pFormat = (void*) &format;
372 audioSource.pLocator = (void*) &bufferQueue;
373
374 output.locatorType = SL_DATALOCATOR_OUTPUTMIX;
375 output.outputMix = mixer;
376
377 audioSink.pLocator = (void*) &output;
378 audioSink.pFormat = NULL;
379
380 return createAudioPlayer(getEngine(engine), &audioSource, &audioSink);
381
382 /*
383 SLresult result;
384 SLVolumeItf volume;
385 result = (*extra->output)->GetInterface(extra->output, SL_IID_VOLUME, &volume);
386 if (result != SL_RESULT_SUCCESS){
387 ALLEGRO_ERROR("Could not get volume interface: %s\n", opensl_get_error_string(result));
388 return 1;
389 }
390 */
391
392 }
393
394 /* Number of active buffers in the queue. Will not be more than MAX_BUFFERS */
bufferCount(SLObjectItf player)395 static int bufferCount(SLObjectItf player){
396 SLBufferQueueItf queue;
397 SLBufferQueueState state;
398
399 (*player)->GetInterface(player, SL_IID_BUFFERQUEUE, &queue);
400 (*queue)->GetState(queue, &state);
401 return state.count;
402 }
403
404 /* Attach some data to the OpenSL player. The data is not copied */
enqueue(SLObjectItf player,const void * data,int bytes)405 static void enqueue(SLObjectItf player, const void * data, int bytes){
406 SLresult result;
407 SLBufferQueueItf queue;
408 SLPlayItf play;
409
410 result = (*player)->GetInterface(player, SL_IID_BUFFERQUEUE, &queue);
411 if (result != SL_RESULT_SUCCESS){
412 ALLEGRO_ERROR("Could not get bufferqueue interface: %s\n", opensl_get_error_string(result));
413 return;
414 }
415
416 // ALLEGRO_DEBUG("Play voice data %p\n", data);
417
418 result = (*queue)->Enqueue(queue, data, bytes);
419 if (result != SL_RESULT_SUCCESS){
420 ALLEGRO_ERROR("Could not enqueue data: %s\n", opensl_get_error_string(result));
421 return;
422 }
423
424 // result = (*volume)->SetVolumeLevel(volume, -300);
425
426 result = (*player)->GetInterface(player, SL_IID_PLAY, &play);
427
428 /* In case the player is not playing, make it play */
429 result = (*play)->SetPlayState(play, SL_PLAYSTATE_PLAYING);
430
431 if (result != SL_RESULT_SUCCESS){
432 ALLEGRO_ERROR("Could not set play state on OpenSL stream\n");
433 }
434
435 /*
436 SLBufferQueueState state;
437 result = (*queue)->GetState(queue, &state);
438 if (result == SL_RESULT_SUCCESS){
439 ALLEGRO_DEBUG("Buffer queue state count %d index %d\n", state.count, state.playIndex);
440 }
441 */
442 }
443
opensl_update(ALLEGRO_THREAD * self,void * data)444 static void * opensl_update(ALLEGRO_THREAD * self, void * data){
445 ALLEGRO_VOICE *voice = data;
446 OpenSLData * opensl = voice->extra;
447
448 int bufferIndex = 0;
449 while (!al_get_thread_should_stop(self)) {
450 if (opensl->status == PLAYING) {
451 // unsigned int frames = 4096;
452 unsigned int frames = MAX_FRAMES;
453 if (voice->is_streaming) {
454 // streaming audio
455 if (bufferCount(opensl->player) < MAX_BUFFERS){
456 const void * data = _al_voice_update(voice, voice->mutex, &frames);
457 if (data){
458 /* Copy the data to a local buffer because a call to enqueue
459 * will use the memory in place and al_voice_update will
460 * re-use the same buffer for each call so we don't want
461 * to corrupt memory when the next call to al_voice_update
462 * is made.
463 */
464 char * buffer = opensl->buffers[bufferIndex];
465 memcpy(buffer, data, frames * opensl->frame_size);
466 enqueue(opensl->player, buffer, frames * opensl->frame_size);
467
468 bufferIndex = (bufferIndex + 1) % MAX_BUFFERS;
469 }
470 } else {
471 al_rest(0.001);
472 }
473 } else {
474 ALLEGRO_ERROR("Unimplemented direct audio\n");
475 /*
476 // direct buffer audio
477 al_lock_mutex(pv->buffer_mutex);
478 const char *data = pv->buffer;
479 unsigned int len = frames * pv->frame_size;
480 pv->buffer += frames * pv->frame_size;
481 if (pv->buffer > pv->buffer_end) {
482 len = pv->buffer_end - data;
483 pv->buffer = voice->attached_stream->spl_data.buffer.ptr;
484 voice->attached_stream->pos = 0;
485 if (voice->attached_stream->loop == ALLEGRO_PLAYMODE_ONCE) {
486 pv->status = PV_STOPPING;
487 }
488 } else {
489 voice->attached_stream->pos += frames;
490 }
491 al_unlock_mutex(pv->buffer_mutex);
492
493 pa_simple_write(pv->s, data, len, NULL);
494 */
495 }
496 } else if (opensl->status == STOPPING){
497 if (bufferCount(opensl->player) == 0){
498 /* When the buffer count is 0 the opensl buffer queue should
499 * transition to the SL_PLAYSTATE_STOPPED state automatically.
500 */
501 opensl->status = STOPPED;
502 }
503 } else if (opensl->status == STOPPED){
504 al_rest(0.001);
505 }
506 }
507
508 return NULL;
509 }
510
_opensl_allocate_voice(ALLEGRO_VOICE * voice)511 static int _opensl_allocate_voice(ALLEGRO_VOICE *voice)
512 {
513 OpenSLData * data;
514 int i;
515
516 data = al_calloc(1, sizeof(*data));
517 voice->extra = data;
518
519 data->output = createOutputMixer(getEngine(engine));
520 if (data->output == NULL){
521 al_free(data);
522 return 1;
523 }
524
525 data->player = NULL;
526 /*
527 data->data = NULL;
528 data->position = 0;
529 data->length = voice->buffer_size;
530 */
531 data->frame_size = al_get_channel_count(voice->chan_conf) * al_get_audio_depth_size(voice->depth);
532 data->status = STOPPED;
533 data->poll_thread = NULL;
534 for (i = 0; i < MAX_BUFFERS; i++){
535 data->buffers[i] = al_malloc(data->frame_size * MAX_FRAMES);
536 }
537
538 data->player = makeStreamingPlayer(voice, data->output);
539 if (data->player == NULL){
540 return 1;
541 }
542 data->poll_thread = al_create_thread(opensl_update, (void*)voice);
543 al_start_thread(data->poll_thread);
544
545 return 0;
546 }
547
_opensl_deallocate_voice(ALLEGRO_VOICE * voice)548 static void _opensl_deallocate_voice(ALLEGRO_VOICE *voice)
549 {
550 OpenSLData * data = (OpenSLData*) voice->extra;
551 int i;
552 if (data->poll_thread != NULL){
553 al_set_thread_should_stop(data->poll_thread);
554 al_join_thread(data->poll_thread, NULL);
555 al_destroy_thread(data->poll_thread);
556 data->poll_thread = NULL;
557 }
558
559 if (data->player != NULL){
560 (*data->player)->Destroy(data->player);
561 data->player = NULL;
562 }
563
564 if (data->output != NULL){
565 (*data->output)->Destroy(data->output);
566 data->output = NULL;
567 }
568
569 for (i = 0; i < MAX_BUFFERS; i++){
570 al_free(data->buffers[i]);
571 }
572 al_free(voice->extra);
573 voice->extra = NULL;
574 }
575
576 /* load_voice is only called by attach_sample_instance_to_voice which
577 * isn't really used, so we leave it unimplemented for now.
578 */
_opensl_load_voice(ALLEGRO_VOICE * voice,const void * data)579 static int _opensl_load_voice(ALLEGRO_VOICE *voice, const void *data)
580 {
581 (void) voice;
582 (void) data;
583 /*
584 OpenSLData * extra = (OpenSLData*) voice->extra;
585 ALLEGRO_DEBUG("Load voice data %p\n", data);
586 extra->data = data;
587 extra->position = 0;
588 */
589
590 return 1;
591 }
592
_opensl_unload_voice(ALLEGRO_VOICE * voice)593 static void _opensl_unload_voice(ALLEGRO_VOICE *voice)
594 {
595 (void) voice;
596 /*
597 OpenSLData * extra = (OpenSLData*) voice->extra;
598 extra->data = NULL;
599 extra->position = 0;
600 */
601 }
602
603 /*
604 static void updateQueue(SLBufferQueueItf queue, void * context){
605 OpenSLData * data = (OpenSLData*) context;
606 if (data->position < data->length){
607 int bytes = data->frame_size * 1024;
608 if (data->position + bytes > data->length){
609 bytes = ((data->length - data->position) / data->frame_size) * data->frame_size;
610 }
611
612 SLresult result;
613 ALLEGRO_DEBUG("Enqueue %d bytes\n", bytes);
614 result = (*queue)->Enqueue(queue, (char*) data->data + data->position, bytes);
615 data->position += bytes;
616 }
617 }
618 */
619
_opensl_start_voice(ALLEGRO_VOICE * voice)620 static int _opensl_start_voice(ALLEGRO_VOICE *voice)
621 {
622 OpenSLData * extra = (OpenSLData*) voice->extra;
623
624 extra->status = PLAYING;
625
626 /*
627 result = (*extra->player)->GetInterface(extra->player, SL_IID_BUFFERQUEUE, &queue);
628 if (result != SL_RESULT_SUCCESS){
629 ALLEGRO_ERROR("Could not get bufferqueue interface: %s\n", opensl_get_error_string(result));
630 return 1;
631 }
632
633 ALLEGRO_DEBUG("Start playing voice data %p\n", extra->data);
634
635 result = (*queue)->Enqueue(queue, (char*) extra->data + extra->position, extra->frame_size * 32);
636 if (result != SL_RESULT_SUCCESS){
637 ALLEGRO_ERROR("Could not enqueue data: %s\n", opensl_get_error_string(result));
638 }
639 extra->position += extra->frame_size * 32;
640
641 result = (*queue)->RegisterCallback(queue, updateQueue, extra);
642
643 if (result != SL_RESULT_SUCCESS){
644 ALLEGRO_ERROR("Could not register callback: %s\n", opensl_get_error_string(result));
645 }
646
647 // result = (*volume)->SetVolumeLevel(volume, -300);
648
649 result = (*extra->player)->GetInterface(extra->player, SL_IID_PLAY, &play);
650 result = (*play)->SetPlayState(play, SL_PLAYSTATE_PLAYING);
651
652 if (result == SL_RESULT_SUCCESS){
653 ALLEGRO_DEBUG("Started new OpenSL stream\n");
654 }
655
656 result = (*queue)->GetState(queue, &state);
657 if (result == SL_RESULT_SUCCESS){
658 ALLEGRO_DEBUG("Buffer queue state count %d index %d\n", state.count, state.playIndex);
659 }
660 */
661
662 return 0;
663 }
664
_opensl_stop_voice(ALLEGRO_VOICE * voice)665 static int _opensl_stop_voice(ALLEGRO_VOICE* voice)
666 {
667 OpenSLData * data = (OpenSLData*) voice->extra;
668 if (data->status == PLAYING){
669 data->status = STOPPING;
670 }
671
672 while (data->status != STOPPED){
673 al_rest(0.001);
674 }
675
676 return 0;
677 }
678
_opensl_voice_is_playing(const ALLEGRO_VOICE * voice)679 static bool _opensl_voice_is_playing(const ALLEGRO_VOICE *voice)
680 {
681 OpenSLData * extra = (OpenSLData*) voice->extra;
682 return extra->status == PLAYING;
683 }
684
_opensl_get_voice_position(const ALLEGRO_VOICE * voice)685 static unsigned int _opensl_get_voice_position(const ALLEGRO_VOICE *voice)
686 {
687 /* TODO */
688 (void) voice;
689 ALLEGRO_ERROR("Unimplemented: _opensl_get_voice_position\n");
690 return 0;
691 }
692
_opensl_set_voice_position(ALLEGRO_VOICE * voice,unsigned int val)693 static int _opensl_set_voice_position(ALLEGRO_VOICE *voice, unsigned int val)
694 {
695 /* TODO */
696 (void) voice;
697 (void) val;
698 ALLEGRO_ERROR("Unimplemented: _opensl_set_voice_position\n");
699 return 1;
700 }
701
702 ALLEGRO_AUDIO_DRIVER _al_kcm_opensl_driver = {
703 "OpenSL",
704
705 _opensl_open,
706 _opensl_close,
707
708 _opensl_allocate_voice,
709 _opensl_deallocate_voice,
710
711 _opensl_load_voice,
712 _opensl_unload_voice,
713
714 _opensl_start_voice,
715 _opensl_stop_voice,
716
717 _opensl_voice_is_playing,
718
719 _opensl_get_voice_position,
720 _opensl_set_voice_position,
721
722 NULL,
723 NULL
724 };
725