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