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