1 /*
2   Simple DirectMedia Layer
3   Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
4 
5   This software is provided 'as-is', without any express or implied
6   warranty.  In no event will the authors be held liable for any damages
7   arising from the use of this software.
8 
9   Permission is granted to anyone to use this software for any purpose,
10   including commercial applications, and to alter it and redistribute it
11   freely, subject to the following restrictions:
12 
13   1. The origin of this software must not be misrepresented; you must not
14      claim that you wrote the original software. If you use this software
15      in a product, an acknowledgment in the product documentation would be
16      appreciated but is not required.
17   2. Altered source versions must be plainly marked as such, and must not be
18      misrepresented as being the original software.
19   3. This notice may not be removed or altered from any source distribution.
20 */
21 #include "../../SDL_internal.h"
22 
23 #if SDL_AUDIO_DRIVER_OPENSLES
24 
25 /* For more discussion of low latency audio on Android, see this:
26    https://googlesamples.github.io/android-audio-high-performance/guides/opensl_es.html
27 */
28 
29 #include "SDL_assert.h"
30 #include "SDL_audio.h"
31 #include "../SDL_audio_c.h"
32 #include "../../core/android/SDL_android.h"
33 #include "SDL_openslES.h"
34 
35 /* for native audio */
36 #include <SLES/OpenSLES.h>
37 #include <SLES/OpenSLES_Android.h>
38 
39 #include <android/log.h>
40 
41 #if 0
42 #define LOG_TAG "SDL_openslES"
43 #define LOGE(...)  __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
44 #define LOGI(...)  __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
45 //#define LOGV(...)  __android_log_print(ANDROID_LOG_VERBOSE,LOG_TAG,__VA_ARGS__)
46 #define LOGV(...)
47 #else
48 #define LOGE(...)
49 #define LOGI(...)
50 #define LOGV(...)
51 #endif
52 
53 /*
54 #define SL_SPEAKER_FRONT_LEFT            ((SLuint32) 0x00000001)
55 #define SL_SPEAKER_FRONT_RIGHT           ((SLuint32) 0x00000002)
56 #define SL_SPEAKER_FRONT_CENTER          ((SLuint32) 0x00000004)
57 #define SL_SPEAKER_LOW_FREQUENCY         ((SLuint32) 0x00000008)
58 #define SL_SPEAKER_BACK_LEFT             ((SLuint32) 0x00000010)
59 #define SL_SPEAKER_BACK_RIGHT            ((SLuint32) 0x00000020)
60 #define SL_SPEAKER_FRONT_LEFT_OF_CENTER  ((SLuint32) 0x00000040)
61 #define SL_SPEAKER_FRONT_RIGHT_OF_CENTER ((SLuint32) 0x00000080)
62 #define SL_SPEAKER_BACK_CENTER           ((SLuint32) 0x00000100)
63 #define SL_SPEAKER_SIDE_LEFT             ((SLuint32) 0x00000200)
64 #define SL_SPEAKER_SIDE_RIGHT            ((SLuint32) 0x00000400)
65 #define SL_SPEAKER_TOP_CENTER            ((SLuint32) 0x00000800)
66 #define SL_SPEAKER_TOP_FRONT_LEFT        ((SLuint32) 0x00001000)
67 #define SL_SPEAKER_TOP_FRONT_CENTER      ((SLuint32) 0x00002000)
68 #define SL_SPEAKER_TOP_FRONT_RIGHT       ((SLuint32) 0x00004000)
69 #define SL_SPEAKER_TOP_BACK_LEFT         ((SLuint32) 0x00008000)
70 #define SL_SPEAKER_TOP_BACK_CENTER       ((SLuint32) 0x00010000)
71 #define SL_SPEAKER_TOP_BACK_RIGHT        ((SLuint32) 0x00020000)
72 */
73 #define SL_ANDROID_SPEAKER_STEREO (SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT)
74 #define SL_ANDROID_SPEAKER_QUAD (SL_ANDROID_SPEAKER_STEREO | SL_SPEAKER_BACK_LEFT | SL_SPEAKER_BACK_RIGHT)
75 #define SL_ANDROID_SPEAKER_5DOT1 (SL_ANDROID_SPEAKER_QUAD | SL_SPEAKER_FRONT_CENTER  | SL_SPEAKER_LOW_FREQUENCY)
76 #define SL_ANDROID_SPEAKER_7DOT1 (SL_ANDROID_SPEAKER_5DOT1 | SL_SPEAKER_SIDE_LEFT | SL_SPEAKER_SIDE_RIGHT)
77 
78 /* engine interfaces */
79 static SLObjectItf engineObject;
80 static SLEngineItf engineEngine;
81 
82 /* output mix interfaces */
83 static SLObjectItf outputMixObject;
84 
85 /* buffer queue player interfaces */
86 static SLObjectItf bqPlayerObject;
87 static SLPlayItf bqPlayerPlay;
88 static SLAndroidSimpleBufferQueueItf bqPlayerBufferQueue;
89 #if 0
90 static SLVolumeItf bqPlayerVolume;
91 #endif
92 
93 /* recorder interfaces */
94 static SLObjectItf recorderObject;
95 static SLRecordItf recorderRecord;
96 static SLAndroidSimpleBufferQueueItf recorderBufferQueue;
97 
98 #if 0
99 static const char *sldevaudiorecorderstr = "SLES Audio Recorder";
100 static const char *sldevaudioplayerstr   = "SLES Audio Player";
101 
102 #define  SLES_DEV_AUDIO_RECORDER  sldevaudiorecorderstr
103 #define  SLES_DEV_AUDIO_PLAYER  sldevaudioplayerstr
104 static void openslES_DetectDevices( int iscapture )
105 {
106     LOGI( "openSLES_DetectDevices()" );
107     if ( iscapture )
108             addfn( SLES_DEV_AUDIO_RECORDER );
109     else
110             addfn( SLES_DEV_AUDIO_PLAYER );
111 }
112 #endif
113 
openslES_DestroyEngine(void)114 static void openslES_DestroyEngine(void)
115 {
116     LOGI("openslES_DestroyEngine()");
117 
118     /* destroy output mix object, and invalidate all associated interfaces */
119     if (outputMixObject != NULL) {
120         (*outputMixObject)->Destroy(outputMixObject);
121         outputMixObject = NULL;
122     }
123 
124     /* destroy engine object, and invalidate all associated interfaces */
125     if (engineObject != NULL) {
126         (*engineObject)->Destroy(engineObject);
127         engineObject = NULL;
128         engineEngine = NULL;
129     }
130 }
131 
132 static int
openslES_CreateEngine(void)133 openslES_CreateEngine(void)
134 {
135     SLresult result;
136 
137     LOGI("openSLES_CreateEngine()");
138 
139     /* create engine */
140     result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL);
141     if (SL_RESULT_SUCCESS != result) {
142         LOGE("slCreateEngine failed: %d", result);
143         goto error;
144     }
145     LOGI("slCreateEngine OK");
146 
147     /* realize the engine */
148     result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
149     if (SL_RESULT_SUCCESS != result) {
150         LOGE("RealizeEngine failed: %d", result);
151         goto error;
152     }
153     LOGI("RealizeEngine OK");
154 
155     /* get the engine interface, which is needed in order to create other objects */
156     result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine);
157     if (SL_RESULT_SUCCESS != result) {
158         LOGE("EngineGetInterface failed: %d", result);
159         goto error;
160     }
161     LOGI("EngineGetInterface OK");
162 
163     /* create output mix */
164     const SLInterfaceID ids[1] = { SL_IID_VOLUME };
165     const SLboolean req[1] = { SL_BOOLEAN_FALSE };
166     result = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 1, ids, req);
167     if (SL_RESULT_SUCCESS != result) {
168         LOGE("CreateOutputMix failed: %d", result);
169         goto error;
170     }
171     LOGI("CreateOutputMix OK");
172 
173     /* realize the output mix */
174     result = (*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE);
175     if (SL_RESULT_SUCCESS != result) {
176         LOGE("RealizeOutputMix failed: %d", result);
177         goto error;
178     }
179     return 1;
180 
181 error:
182     openslES_DestroyEngine();
183     return 0;
184 }
185 
186 /* this callback handler is called every time a buffer finishes recording */
187 static void
bqRecorderCallback(SLAndroidSimpleBufferQueueItf bq,void * context)188 bqRecorderCallback(SLAndroidSimpleBufferQueueItf bq, void *context)
189 {
190     struct SDL_PrivateAudioData *audiodata = (struct SDL_PrivateAudioData *) context;
191 
192     LOGV("SLES: Recording Callback");
193     SDL_SemPost(audiodata->playsem);
194 }
195 
196 static void
openslES_DestroyPCMRecorder(_THIS)197 openslES_DestroyPCMRecorder(_THIS)
198 {
199     struct SDL_PrivateAudioData *audiodata = this->hidden;
200     SLresult result;
201 
202     /* stop recording */
203     if (recorderRecord != NULL) {
204         result = (*recorderRecord)->SetRecordState(recorderRecord, SL_RECORDSTATE_STOPPED);
205         if (SL_RESULT_SUCCESS != result) {
206             LOGE("SetRecordState stopped: %d", result);
207         }
208     }
209 
210     /* destroy audio recorder object, and invalidate all associated interfaces */
211     if (recorderObject != NULL) {
212         (*recorderObject)->Destroy(recorderObject);
213         recorderObject = NULL;
214         recorderRecord = NULL;
215         recorderBufferQueue = NULL;
216     }
217 
218     if (audiodata->playsem) {
219         SDL_DestroySemaphore(audiodata->playsem);
220         audiodata->playsem = NULL;
221     }
222 
223     if (audiodata->mixbuff) {
224         SDL_free(audiodata->mixbuff);
225     }
226 }
227 
228 static int
openslES_CreatePCMRecorder(_THIS)229 openslES_CreatePCMRecorder(_THIS)
230 {
231     struct SDL_PrivateAudioData *audiodata = this->hidden;
232     SLDataFormat_PCM format_pcm;
233     SLresult result;
234     int i;
235 
236     if (!Android_JNI_RequestPermission("android.permission.RECORD_AUDIO")) {
237         LOGE("This app doesn't have RECORD_AUDIO permission");
238         return SDL_SetError("This app doesn't have RECORD_AUDIO permission");
239     }
240 
241     /* Just go with signed 16-bit audio as it's the most compatible */
242     this->spec.format = AUDIO_S16SYS;
243     this->spec.channels = 1;
244     /*this->spec.freq = SL_SAMPLINGRATE_16 / 1000;*/
245 
246     /* Update the fragment size as size in bytes */
247     SDL_CalculateAudioSpec(&this->spec);
248 
249     LOGI("Try to open %u hz %u bit chan %u %s samples %u",
250           this->spec.freq, SDL_AUDIO_BITSIZE(this->spec.format),
251           this->spec.channels, (this->spec.format & 0x1000) ? "BE" : "LE", this->spec.samples);
252 
253     /* configure audio source */
254     SLDataLocator_IODevice loc_dev = {SL_DATALOCATOR_IODEVICE, SL_IODEVICE_AUDIOINPUT, SL_DEFAULTDEVICEID_AUDIOINPUT, NULL};
255     SLDataSource audioSrc = {&loc_dev, NULL};
256 
257     /* configure audio sink */
258     SLDataLocator_AndroidSimpleBufferQueue loc_bufq = { SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, NUM_BUFFERS };
259 
260     format_pcm.formatType    = SL_DATAFORMAT_PCM;
261     format_pcm.numChannels   = this->spec.channels;
262     format_pcm.samplesPerSec = this->spec.freq * 1000;  /* / kilo Hz to milli Hz */
263     format_pcm.bitsPerSample = SDL_AUDIO_BITSIZE(this->spec.format);
264     format_pcm.containerSize = SDL_AUDIO_BITSIZE(this->spec.format);
265     format_pcm.endianness    = SL_BYTEORDER_LITTLEENDIAN;
266     format_pcm.channelMask   = SL_SPEAKER_FRONT_CENTER;
267 
268     SLDataSink audioSnk = { &loc_bufq, &format_pcm };
269 
270     /* create audio recorder */
271     /* (requires the RECORD_AUDIO permission) */
272     const SLInterfaceID ids[1] = {
273         SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
274     };
275     const SLboolean req[1] = {
276         SL_BOOLEAN_TRUE,
277     };
278 
279     result = (*engineEngine)->CreateAudioRecorder(engineEngine, &recorderObject, &audioSrc, &audioSnk, 1, ids, req);
280     if (SL_RESULT_SUCCESS != result) {
281         LOGE("CreateAudioRecorder failed: %d", result);
282         goto failed;
283     }
284 
285     /* realize the recorder */
286     result = (*recorderObject)->Realize(recorderObject, SL_BOOLEAN_FALSE);
287     if (SL_RESULT_SUCCESS != result) {
288         LOGE("RealizeAudioPlayer failed: %d", result);
289         goto failed;
290     }
291 
292     /* get the record interface */
293     result = (*recorderObject)->GetInterface(recorderObject, SL_IID_RECORD, &recorderRecord);
294     if (SL_RESULT_SUCCESS != result) {
295         LOGE("SL_IID_RECORD interface get failed: %d", result);
296         goto failed;
297     }
298 
299     /* get the buffer queue interface */
300     result = (*recorderObject)->GetInterface(recorderObject, SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &recorderBufferQueue);
301     if (SL_RESULT_SUCCESS != result) {
302         LOGE("SL_IID_BUFFERQUEUE interface get failed: %d", result);
303         goto failed;
304     }
305 
306     /* register callback on the buffer queue */
307     /* context is '(SDL_PrivateAudioData *)this->hidden' */
308     result = (*recorderBufferQueue)->RegisterCallback(recorderBufferQueue, bqRecorderCallback, this->hidden);
309     if (SL_RESULT_SUCCESS != result) {
310         LOGE("RegisterCallback failed: %d", result);
311         goto failed;
312     }
313 
314     /* Create the audio buffer semaphore */
315     audiodata->playsem = SDL_CreateSemaphore(0);
316     if (!audiodata->playsem) {
317         LOGE("cannot create Semaphore!");
318         goto failed;
319     }
320 
321     /* Create the sound buffers */
322     audiodata->mixbuff = (Uint8 *) SDL_malloc(NUM_BUFFERS * this->spec.size);
323     if (audiodata->mixbuff == NULL) {
324         LOGE("mixbuffer allocate - out of memory");
325         goto failed;
326     }
327 
328     for (i = 0; i < NUM_BUFFERS; i++) {
329         audiodata->pmixbuff[i] = audiodata->mixbuff + i * this->spec.size;
330     }
331 
332     /* in case already recording, stop recording and clear buffer queue */
333     result = (*recorderRecord)->SetRecordState(recorderRecord, SL_RECORDSTATE_STOPPED);
334     if (SL_RESULT_SUCCESS != result) {
335         LOGE("Record set state failed: %d", result);
336         goto failed;
337     }
338 
339     /* enqueue empty buffers to be filled by the recorder */
340     for (i = 0; i < NUM_BUFFERS; i++) {
341         result = (*recorderBufferQueue)->Enqueue(recorderBufferQueue, audiodata->pmixbuff[i], this->spec.size);
342         if (SL_RESULT_SUCCESS != result) {
343             LOGE("Record enqueue buffers failed: %d", result);
344             goto failed;
345         }
346     }
347 
348     /* start recording */
349     result = (*recorderRecord)->SetRecordState(recorderRecord, SL_RECORDSTATE_RECORDING);
350     if (SL_RESULT_SUCCESS != result) {
351         LOGE("Record set state failed: %d", result);
352         goto failed;
353     }
354 
355     return 0;
356 
357 failed:
358 
359     openslES_DestroyPCMRecorder(this);
360 
361     return SDL_SetError("Open device failed!");
362 }
363 
364 /* this callback handler is called every time a buffer finishes playing */
365 static void
bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq,void * context)366 bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void *context)
367 {
368     struct SDL_PrivateAudioData *audiodata = (struct SDL_PrivateAudioData *) context;
369 
370     LOGV("SLES: Playback Callback");
371     SDL_SemPost(audiodata->playsem);
372 }
373 
374 static void
openslES_DestroyPCMPlayer(_THIS)375 openslES_DestroyPCMPlayer(_THIS)
376 {
377     struct SDL_PrivateAudioData *audiodata = this->hidden;
378     SLresult result;
379 
380     /* set the player's state to 'stopped' */
381     if (bqPlayerPlay != NULL) {
382         result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_STOPPED);
383         if (SL_RESULT_SUCCESS != result) {
384             LOGE("SetPlayState stopped failed: %d", result);
385         }
386     }
387 
388     /* destroy buffer queue audio player object, and invalidate all associated interfaces */
389     if (bqPlayerObject != NULL) {
390 
391         (*bqPlayerObject)->Destroy(bqPlayerObject);
392 
393         bqPlayerObject = NULL;
394         bqPlayerPlay = NULL;
395         bqPlayerBufferQueue = NULL;
396     }
397 
398     if (audiodata->playsem) {
399         SDL_DestroySemaphore(audiodata->playsem);
400         audiodata->playsem = NULL;
401     }
402 
403     if (audiodata->mixbuff) {
404         SDL_free(audiodata->mixbuff);
405     }
406 }
407 
408 static int
openslES_CreatePCMPlayer(_THIS)409 openslES_CreatePCMPlayer(_THIS)
410 {
411     struct SDL_PrivateAudioData *audiodata = this->hidden;
412     SLDataFormat_PCM format_pcm;
413     SLresult result;
414     int i;
415 
416     /* If we want to add floating point audio support (requires API level 21)
417        it can be done as described here:
418         https://developer.android.com/ndk/guides/audio/opensl/android-extensions.html#floating-point
419     */
420 #if 1
421     /* Just go with signed 16-bit audio as it's the most compatible */
422     this->spec.format = AUDIO_S16SYS;
423 #else
424     SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
425     while (test_format != 0) {
426         if (SDL_AUDIO_ISSIGNED(test_format) && SDL_AUDIO_ISINT(test_format)) {
427             break;
428         }
429         test_format = SDL_NextAudioFormat();
430     }
431 
432     if (test_format == 0) {
433         /* Didn't find a compatible format : */
434         LOGI( "No compatible audio format, using signed 16-bit audio" );
435         test_format = AUDIO_S16SYS;
436     }
437     this->spec.format = test_format;
438 #endif
439 
440     /* Update the fragment size as size in bytes */
441     SDL_CalculateAudioSpec(&this->spec);
442 
443     LOGI("Try to open %u hz %u bit chan %u %s samples %u",
444           this->spec.freq, SDL_AUDIO_BITSIZE(this->spec.format),
445           this->spec.channels, (this->spec.format & 0x1000) ? "BE" : "LE", this->spec.samples);
446 
447     /* configure audio source */
448     SLDataLocator_AndroidSimpleBufferQueue loc_bufq = { SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, NUM_BUFFERS };
449 
450     format_pcm.formatType    = SL_DATAFORMAT_PCM;
451     format_pcm.numChannels   = this->spec.channels;
452     format_pcm.samplesPerSec = this->spec.freq * 1000;  /* / kilo Hz to milli Hz */
453     format_pcm.bitsPerSample = SDL_AUDIO_BITSIZE(this->spec.format);
454     format_pcm.containerSize = SDL_AUDIO_BITSIZE(this->spec.format);
455 
456     if (SDL_AUDIO_ISBIGENDIAN(this->spec.format)) {
457         format_pcm.endianness = SL_BYTEORDER_BIGENDIAN;
458     } else {
459         format_pcm.endianness = SL_BYTEORDER_LITTLEENDIAN;
460     }
461 
462     switch (this->spec.channels)
463     {
464     case 1:
465         format_pcm.channelMask = SL_SPEAKER_FRONT_LEFT;
466         break;
467     case 2:
468         format_pcm.channelMask = SL_ANDROID_SPEAKER_STEREO;
469         break;
470     case 3:
471         format_pcm.channelMask = SL_ANDROID_SPEAKER_STEREO | SL_SPEAKER_FRONT_CENTER;
472         break;
473     case 4:
474         format_pcm.channelMask = SL_ANDROID_SPEAKER_QUAD;
475         break;
476     case 5:
477         format_pcm.channelMask = SL_ANDROID_SPEAKER_QUAD | SL_SPEAKER_FRONT_CENTER;
478         break;
479     case 6:
480         format_pcm.channelMask = SL_ANDROID_SPEAKER_5DOT1;
481         break;
482     case 7:
483         format_pcm.channelMask = SL_ANDROID_SPEAKER_5DOT1 | SL_SPEAKER_BACK_CENTER;
484         break;
485     case 8:
486         format_pcm.channelMask = SL_ANDROID_SPEAKER_7DOT1;
487         break;
488     default:
489         /* Unknown number of channels, fall back to stereo */
490         this->spec.channels = 2;
491         format_pcm.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
492         break;
493     }
494 
495     SLDataSource audioSrc = { &loc_bufq, &format_pcm };
496 
497     /* configure audio sink */
498     SLDataLocator_OutputMix loc_outmix = { SL_DATALOCATOR_OUTPUTMIX, outputMixObject };
499     SLDataSink audioSnk = { &loc_outmix, NULL };
500 
501     /* create audio player */
502     const SLInterfaceID ids[2] = {
503         SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
504         SL_IID_VOLUME
505     };
506 
507     const SLboolean req[2] = {
508         SL_BOOLEAN_TRUE,
509         SL_BOOLEAN_FALSE,
510     };
511 
512     result = (*engineEngine)->CreateAudioPlayer(engineEngine, &bqPlayerObject, &audioSrc, &audioSnk, 2, ids, req);
513     if (SL_RESULT_SUCCESS != result) {
514         LOGE("CreateAudioPlayer failed: %d", result);
515         goto failed;
516     }
517 
518     /* realize the player */
519     result = (*bqPlayerObject)->Realize(bqPlayerObject, SL_BOOLEAN_FALSE);
520     if (SL_RESULT_SUCCESS != result) {
521         LOGE("RealizeAudioPlayer failed: %d", result);
522         goto failed;
523     }
524 
525     /* get the play interface */
526     result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_PLAY, &bqPlayerPlay);
527     if (SL_RESULT_SUCCESS != result) {
528         LOGE("SL_IID_PLAY interface get failed: %d", result);
529         goto failed;
530     }
531 
532     /* get the buffer queue interface */
533     result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &bqPlayerBufferQueue);
534     if (SL_RESULT_SUCCESS != result) {
535         LOGE("SL_IID_BUFFERQUEUE interface get failed: %d", result);
536         goto failed;
537     }
538 
539     /* register callback on the buffer queue */
540     /* context is '(SDL_PrivateAudioData *)this->hidden' */
541     result = (*bqPlayerBufferQueue)->RegisterCallback(bqPlayerBufferQueue, bqPlayerCallback, this->hidden);
542     if (SL_RESULT_SUCCESS != result) {
543         LOGE("RegisterCallback failed: %d", result);
544         goto failed;
545     }
546 
547 #if 0
548     /* get the volume interface */
549     result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_VOLUME, &bqPlayerVolume);
550     if (SL_RESULT_SUCCESS != result) {
551         LOGE("SL_IID_VOLUME interface get failed: %d", result);
552         /* goto failed; */
553     }
554 #endif
555 
556     /* Create the audio buffer semaphore */
557     audiodata->playsem = SDL_CreateSemaphore(NUM_BUFFERS - 1);
558     if (!audiodata->playsem) {
559         LOGE("cannot create Semaphore!");
560         goto failed;
561     }
562 
563     /* Create the sound buffers */
564     audiodata->mixbuff = (Uint8 *) SDL_malloc(NUM_BUFFERS * this->spec.size);
565     if (audiodata->mixbuff == NULL) {
566         LOGE("mixbuffer allocate - out of memory");
567         goto failed;
568     }
569 
570     for (i = 0; i < NUM_BUFFERS; i++) {
571         audiodata->pmixbuff[i] = audiodata->mixbuff + i * this->spec.size;
572     }
573 
574     /* set the player's state to playing */
575     result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_PLAYING);
576     if (SL_RESULT_SUCCESS != result) {
577         LOGE("Play set state failed: %d", result);
578         goto failed;
579     }
580 
581     return 0;
582 
583 failed:
584 
585     openslES_DestroyPCMPlayer(this);
586 
587     return SDL_SetError("Open device failed!");
588 }
589 
590 static int
openslES_OpenDevice(_THIS,void * handle,const char * devname,int iscapture)591 openslES_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
592 {
593     this->hidden = (struct SDL_PrivateAudioData *) SDL_calloc(1, (sizeof *this->hidden));
594     if (this->hidden == NULL) {
595         return SDL_OutOfMemory();
596     }
597 
598     if (iscapture) {
599         LOGI("openslES_OpenDevice() %s for capture", devname);
600         return openslES_CreatePCMRecorder(this);
601     } else {
602         LOGI("openslES_OpenDevice() %s for playing", devname);
603         return openslES_CreatePCMPlayer(this);
604     }
605 }
606 
607 static void
openslES_WaitDevice(_THIS)608 openslES_WaitDevice(_THIS)
609 {
610     struct SDL_PrivateAudioData *audiodata = this->hidden;
611 
612     LOGV("openslES_WaitDevice()");
613 
614     /* Wait for an audio chunk to finish */
615     SDL_SemWait(audiodata->playsem);
616 }
617 
618 static void
openslES_PlayDevice(_THIS)619 openslES_PlayDevice(_THIS)
620 {
621     struct SDL_PrivateAudioData *audiodata = this->hidden;
622     SLresult result;
623 
624     LOGV("======openslES_PlayDevice()======");
625 
626     /* Queue it up */
627     result = (*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, audiodata->pmixbuff[audiodata->next_buffer], this->spec.size);
628 
629     audiodata->next_buffer++;
630     if (audiodata->next_buffer >= NUM_BUFFERS) {
631         audiodata->next_buffer = 0;
632     }
633 
634     /* If Enqueue fails, callback won't be called.
635      * Post the semphore, not to run out of buffer */
636     if (SL_RESULT_SUCCESS != result) {
637         SDL_SemPost(audiodata->playsem);
638     }
639 }
640 
641 /*/           n   playn sem */
642 /* getbuf     0   -     1 */
643 /* fill buff  0   -     1 */
644 /* play       0 - 0     1 */
645 /* wait       1   0     0 */
646 /* getbuf     1   0     0 */
647 /* fill buff  1   0     0 */
648 /* play       0   0     0 */
649 /* wait */
650 /* */
651 /* okay.. */
652 
653 static Uint8 *
openslES_GetDeviceBuf(_THIS)654 openslES_GetDeviceBuf(_THIS)
655 {
656     struct SDL_PrivateAudioData *audiodata = this->hidden;
657 
658     LOGV("openslES_GetDeviceBuf()");
659     return audiodata->pmixbuff[audiodata->next_buffer];
660 }
661 
662 static int
openslES_CaptureFromDevice(_THIS,void * buffer,int buflen)663 openslES_CaptureFromDevice(_THIS, void *buffer, int buflen)
664 {
665     struct SDL_PrivateAudioData *audiodata = this->hidden;
666     SLresult result;
667 
668     /* Wait for new recorded data */
669     SDL_SemWait(audiodata->playsem);
670 
671     /* Copy it to the output buffer */
672     SDL_assert(buflen == this->spec.size);
673     SDL_memcpy(buffer, audiodata->pmixbuff[audiodata->next_buffer], this->spec.size);
674 
675     /* Re-enqueue the buffer */
676     result = (*recorderBufferQueue)->Enqueue(recorderBufferQueue, audiodata->pmixbuff[audiodata->next_buffer], this->spec.size);
677     if (SL_RESULT_SUCCESS != result) {
678         LOGE("Record enqueue buffers failed: %d", result);
679         return -1;
680     }
681 
682     audiodata->next_buffer++;
683     if (audiodata->next_buffer >= NUM_BUFFERS) {
684         audiodata->next_buffer = 0;
685     }
686 
687     return this->spec.size;
688 }
689 
690 static void
openslES_CloseDevice(_THIS)691 openslES_CloseDevice(_THIS)
692 {
693     /* struct SDL_PrivateAudioData *audiodata = this->hidden; */
694 
695     if (this->iscapture) {
696         LOGI("openslES_CloseDevice() for capture");
697         openslES_DestroyPCMRecorder(this);
698     } else {
699         LOGI("openslES_CloseDevice() for playing");
700         openslES_DestroyPCMPlayer(this);
701     }
702 
703     SDL_free(this->hidden);
704 }
705 
706 static int
openslES_Init(SDL_AudioDriverImpl * impl)707 openslES_Init(SDL_AudioDriverImpl * impl)
708 {
709     LOGI("openslES_Init() called");
710 
711     if (!openslES_CreateEngine()) {
712         return 0;
713     }
714 
715     LOGI("openslES_Init() - set pointers");
716 
717     /* Set the function pointers */
718     /* impl->DetectDevices = openslES_DetectDevices; */
719     impl->OpenDevice    = openslES_OpenDevice;
720     impl->WaitDevice    = openslES_WaitDevice;
721     impl->PlayDevice    = openslES_PlayDevice;
722     impl->GetDeviceBuf  = openslES_GetDeviceBuf;
723     impl->CaptureFromDevice = openslES_CaptureFromDevice;
724     impl->CloseDevice   = openslES_CloseDevice;
725     impl->Deinitialize  = openslES_DestroyEngine;
726 
727     /* and the capabilities */
728     impl->HasCaptureSupport = 1;
729     impl->OnlyHasDefaultOutputDevice = 1;
730     impl->OnlyHasDefaultCaptureDevice = 1;
731 
732     LOGI("openslES_Init() - success");
733 
734     /* this audio target is available. */
735     return 1;
736 }
737 
738 AudioBootStrap openslES_bootstrap = {
739     "openslES", "opensl ES audio driver", openslES_Init, 0
740 };
741 
openslES_ResumeDevices(void)742 void openslES_ResumeDevices(void)
743 {
744     if (bqPlayerPlay != NULL) {
745         /* set the player's state to 'playing' */
746         SLresult result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_PLAYING);
747         if (SL_RESULT_SUCCESS != result) {
748             LOGE("openslES_ResumeDevices failed: %d", result);
749         }
750     }
751 }
752 
openslES_PauseDevices(void)753 void openslES_PauseDevices(void)
754 {
755     if (bqPlayerPlay != NULL) {
756         /* set the player's state to 'paused' */
757         SLresult result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_PAUSED);
758         if (SL_RESULT_SUCCESS != result) {
759             LOGE("openslES_PauseDevices failed: %d", result);
760         }
761     }
762 }
763 
764 #endif /* SDL_AUDIO_DRIVER_OPENSLES */
765 
766 /* vi: set ts=4 sw=4 expandtab: */
767