src/audio/openslES/SDL_openslES.c
author Sylvain Becker <sylvain.becker@gmail.com>
Tue, 05 Feb 2019 15:05:32 +0100
changeset 12596 6654faf2160e
parent 12545 599ebb123f0a
child 12597 b5ea5997cbf9
permissions -rw-r--r--
Android/openslES: prevent to run out of buffers if Enqueue() fails.
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2019 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 #include "SDL_audio.h"
    26 #include "../SDL_audio_c.h"
    27 #include "SDL_openslES.h"
    28 
    29 /* for native audio */
    30 #include <SLES/OpenSLES.h>
    31 #include <SLES/OpenSLES_Android.h>
    32 
    33 #include <android/log.h>
    34 
    35 #define LOG_TAG "SDL_openslES"
    36 
    37 #if 0
    38 #define LOGI(...)  __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
    39 #define LOGE(...)  __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
    40 // #define LOGI(...) do {} while (0)
    41 // #define LOGE(...) do {} while (0)
    42 #else
    43 #define LOGI(...)
    44 #define LOGE(...)
    45 #endif
    46 
    47 /* engine interfaces */
    48 static SLObjectItf engineObject = NULL;
    49 static SLEngineItf engineEngine;
    50 
    51 /* output mix interfaces */
    52 static SLObjectItf outputMixObject = NULL;
    53 // static SLEnvironmentalReverbItf outputMixEnvironmentalReverb = NULL;
    54 
    55 /* aux effect on the output mix, used by the buffer queue player */
    56 /* static const SLEnvironmentalReverbSettings reverbSettings = SL_I3DL2_ENVIRONMENT_PRESET_STONECORRIDOR; */
    57 
    58 /* buffer queue player interfaces */
    59 static SLObjectItf                   bqPlayerObject      = NULL;
    60 static SLPlayItf                     bqPlayerPlay        = NULL;
    61 static SLAndroidSimpleBufferQueueItf bqPlayerBufferQueue = NULL;
    62 /*static SLEffectSendItf          bqPlayerEffectSend = NULL; */
    63 static SLMuteSoloItf                 bqPlayerMuteSolo    = NULL;
    64 static SLVolumeItf                   bqPlayerVolume      = NULL;
    65 
    66 #if 0
    67 /* recorder interfaces TODO */
    68 static SLObjectItf                   recorderObject = NULL;
    69 static SLRecordItf                   recorderRecord;
    70 static SLAndroidSimpleBufferQueueItf recorderBufferQueue;
    71 #endif
    72 
    73 /* pointer and size of the next player buffer to enqueue, and number of remaining buffers */
    74 #if 0
    75 static short      *nextBuffer;
    76 static unsigned    nextSize;
    77 static int         nextCount;
    78 #endif
    79 
    80 // static SDL_AudioDevice* audioDevice = NULL;
    81 
    82 #if 0
    83 static const char *sldevaudiorecorderstr = "SLES Audio Recorder";
    84 static const char *sldevaudioplayerstr   = "SLES Audio Player";
    85 
    86 #define  SLES_DEV_AUDIO_RECORDER  sldevaudiorecorderstr
    87 #define  SLES_DEV_AUDIO_PLAYER  sldevaudioplayerstr
    88 static void openslES_DetectDevices( int iscapture )
    89 {
    90   LOGI( "openSLES_DetectDevices()" );
    91     if ( iscapture )
    92             addfn( SLES_DEV_AUDIO_RECORDER );
    93   else
    94             addfn( SLES_DEV_AUDIO_PLAYER );
    95   return;
    96 }
    97 #endif
    98 
    99 static void openslES_DestroyEngine();
   100 
   101 static int
   102 openslES_CreateEngine()
   103 {
   104     SLresult result;
   105 
   106     LOGI("openSLES_CreateEngine()");
   107 
   108     /* create engine */
   109     result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL);
   110     if (SL_RESULT_SUCCESS != result) {
   111         LOGE("slCreateEngine failed");
   112         goto error;
   113     }
   114 
   115     LOGI("slCreateEngine OK");
   116 
   117     /* realize the engine */
   118     result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
   119     if (SL_RESULT_SUCCESS != result) {
   120         LOGE("RealizeEngine failed");
   121         goto error;
   122     }
   123 
   124     LOGI("RealizeEngine OK");
   125 
   126     /* get the engine interface, which is needed in order to create other objects */
   127     result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine);
   128     if (SL_RESULT_SUCCESS != result) {
   129         LOGE("EngineGetInterface failed");
   130         goto error;
   131     }
   132 
   133     LOGI("EngineGetInterface OK");
   134 
   135     /* create output mix, with environmental reverb specified as a non-required interface */
   136     /* const SLInterfaceID ids[1] = { SL_IID_ENVIRONMENTALREVERB }; */
   137     /* const SLboolean req[1] = { SL_BOOLEAN_FALSE }; */
   138 
   139     const SLInterfaceID ids[1] = { SL_IID_VOLUME };
   140     const SLboolean req[1] = { SL_BOOLEAN_FALSE };
   141     result = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 1, ids, req);
   142 
   143     if (SL_RESULT_SUCCESS != result) {
   144         LOGE("CreateOutputMix failed");
   145         goto error;
   146     }
   147     LOGI("CreateOutputMix OK");
   148 
   149     /* realize the output mix */
   150     result = (*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE);
   151     if (SL_RESULT_SUCCESS != result) {
   152         LOGE("RealizeOutputMix failed");
   153         goto error;
   154     }
   155     return 1;
   156 
   157 error:
   158     openslES_DestroyEngine();
   159     return 0;
   160 }
   161 
   162 static void openslES_DestroyPCMPlayer(_THIS);
   163 static void openslES_DestroyPCMRecorder(_THIS);
   164 
   165 static void openslES_DestroyEngine()
   166 {
   167     LOGI("openslES_DestroyEngine()");
   168 
   169 //        openslES_DestroyPCMPlayer(this);
   170 //    openslES_DestroyPCMRecorder(this);
   171 
   172     /* destroy output mix object, and invalidate all associated interfaces */
   173     if (outputMixObject != NULL) {
   174         (*outputMixObject)->Destroy(outputMixObject);
   175         outputMixObject = NULL;
   176         /* outputMixEnvironmentalReverb = NULL; */
   177     }
   178 
   179     /* destroy engine object, and invalidate all associated interfaces */
   180     if (engineObject != NULL) {
   181         (*engineObject)->Destroy(engineObject);
   182         engineObject = NULL;
   183         engineEngine = NULL;
   184     }
   185 
   186     return;
   187 }
   188 
   189 /* this callback handler is called every time a buffer finishes playing */
   190 static void
   191 bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void *context)
   192 {
   193     struct SDL_PrivateAudioData *audiodata = (struct SDL_PrivateAudioData *) context;
   194     static int t = 0;
   195 
   196     /* assert(bq == bqPlayerBufferQueue); */
   197     /* assert(NULL == context); */
   198 
   199     /* for streaming playback, replace this test by logic to find and fill the next buffer */
   200 #if 0
   201     if (--nextCount > 0 && NULL != nextBuffer && 0 != nextSize)
   202     {
   203         SLresult result;
   204 
   205         /* enqueue another buffer */
   206         result = (*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, nextBuffer, nextSize);
   207         /* the most likely other result is SL_RESULT_BUFFER_INSUFFICIENT, */
   208         /* which for this code example would indicate a programming error */
   209         assert(SL_RESULT_SUCCESS == result);
   210         (void) result;
   211     }
   212 #endif
   213     LOGI("SLES: Playback Callmeback %u", t++);
   214     SDL_SemPost(audiodata->playsem);
   215     return;
   216 }
   217 
   218 static int
   219 openslES_CreatePCMRecorder(_THIS)
   220 {
   221 /*    struct SDL_PrivateAudioData *audiodata = (struct SDL_PrivateAudioData *) this->hidden; */
   222 
   223     LOGE("openslES_CreatePCMRecorder not implimented yet!");
   224     return SDL_SetError("openslES_CreatePCMRecorder not implimented yet!");
   225 }
   226 
   227 static void
   228 openslES_DestroyPCMRecorder(_THIS)
   229 {
   230 /*    struct SDL_PrivateAudioData *audiodata = (struct SDL_PrivateAudioData *) this->hidden; */
   231 
   232     return;
   233 }
   234 
   235 static int
   236 openslES_CreatePCMPlayer(_THIS)
   237 {
   238     struct SDL_PrivateAudioData *audiodata = (struct SDL_PrivateAudioData *) this->hidden;
   239 
   240     SLDataFormat_PCM format_pcm;
   241 
   242     SDL_AudioFormat test_format = 0;
   243     SLresult result;
   244     int i;
   245 
   246 #if 0
   247 
   248       test_format = SDL_FirstAudioFormat( this->spec.format );
   249 
   250       while (test_format != 0) {
   251 
   252           if (SDL_AUDIO_ISSIGNED(test_format) && SDL_AUDIO_ISINT(test_format)) {
   253               break;
   254           }
   255           test_format = SDL_NextAudioFormat();
   256       }
   257 
   258       if ( test_format == 0 ) {
   259           /* Didn't find a compatible format : */
   260           LOGI( "No compatible audio format!" );
   261           return SDL_SetError("No compatible audio format!");
   262       }
   263 
   264       this->spec.format = test_format;
   265 #endif
   266 
   267     /* Update the fragment size as size in bytes */
   268     SDL_CalculateAudioSpec(&this->spec);
   269 
   270     LOGI("Try to open %u hz %u bit chan %u %s samples %u",
   271           this->spec.freq, SDL_AUDIO_BITSIZE(this->spec.format),
   272           this->spec.channels, (test_format & 0x1000) ? "BE" : "LE", this->spec.samples);
   273 
   274     /* configure audio source */
   275     SLDataLocator_AndroidSimpleBufferQueue loc_bufq = { SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 2 };
   276     /* SLDataLocator_AndroidSimpleBufferQueue loc_bufq = { SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, OPENSLES_BUFFERS }; */
   277 
   278     format_pcm.formatType    = SL_DATAFORMAT_PCM;
   279     format_pcm.numChannels   = this->spec.channels;
   280     format_pcm.samplesPerSec = this->spec.freq * 1000;  /* / kilo Hz to milli Hz */
   281     format_pcm.bitsPerSample = SDL_AUDIO_BITSIZE(this->spec.format);
   282     format_pcm.containerSize = SDL_AUDIO_BITSIZE(this->spec.format);
   283 
   284     if (SDL_AUDIO_ISBIGENDIAN(this->spec.format)) {
   285         format_pcm.endianness = SL_BYTEORDER_BIGENDIAN;
   286     } else {
   287         format_pcm.endianness = SL_BYTEORDER_LITTLEENDIAN;
   288     }
   289 
   290 /*
   291 #define SL_SPEAKER_FRONT_LEFT            ((SLuint32) 0x00000001)
   292 #define SL_SPEAKER_FRONT_RIGHT           ((SLuint32) 0x00000002)
   293 #define SL_SPEAKER_FRONT_CENTER          ((SLuint32) 0x00000004)
   294 #define SL_SPEAKER_LOW_FREQUENCY         ((SLuint32) 0x00000008)
   295 #define SL_SPEAKER_BACK_LEFT             ((SLuint32) 0x00000010)
   296 #define SL_SPEAKER_BACK_RIGHT            ((SLuint32) 0x00000020)
   297 #define SL_SPEAKER_FRONT_LEFT_OF_CENTER  ((SLuint32) 0x00000040)
   298 #define SL_SPEAKER_FRONT_RIGHT_OF_CENTER ((SLuint32) 0x00000080)
   299 #define SL_SPEAKER_BACK_CENTER           ((SLuint32) 0x00000100)
   300 #define SL_SPEAKER_SIDE_LEFT             ((SLuint32) 0x00000200)
   301 #define SL_SPEAKER_SIDE_RIGHT            ((SLuint32) 0x00000400)
   302 #define SL_SPEAKER_TOP_CENTER            ((SLuint32) 0x00000800)
   303 #define SL_SPEAKER_TOP_FRONT_LEFT        ((SLuint32) 0x00001000)
   304 #define SL_SPEAKER_TOP_FRONT_CENTER      ((SLuint32) 0x00002000)
   305 #define SL_SPEAKER_TOP_FRONT_RIGHT       ((SLuint32) 0x00004000)
   306 #define SL_SPEAKER_TOP_BACK_LEFT         ((SLuint32) 0x00008000)
   307 #define SL_SPEAKER_TOP_BACK_CENTER       ((SLuint32) 0x00010000)
   308 #define SL_SPEAKER_TOP_BACK_RIGHT        ((SLuint32) 0x00020000)
   309 */
   310 
   311     if (this->spec.channels == 1) {
   312         format_pcm.channelMask = SL_SPEAKER_FRONT_CENTER;
   313     } else if (this->spec.channels == 2) {
   314         format_pcm.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
   315     } else if (this->spec.channels == 3) {
   316         format_pcm.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT | SL_SPEAKER_FRONT_CENTER;
   317     } else if (this->spec.channels == 4) {
   318         format_pcm.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT |
   319               SL_SPEAKER_BACK_LEFT | SL_SPEAKER_BACK_RIGHT;
   320     } else {
   321         format_pcm.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT |
   322               SL_SPEAKER_BACK_LEFT | SL_SPEAKER_BACK_RIGHT | SL_SPEAKER_FRONT_CENTER;
   323     }
   324 
   325     SLDataSource audioSrc = { &loc_bufq, &format_pcm };
   326 
   327     /* configure audio sink */
   328     SLDataLocator_OutputMix loc_outmix = { SL_DATALOCATOR_OUTPUTMIX, outputMixObject };
   329     SLDataSink audioSnk = { &loc_outmix, NULL };
   330 
   331     /* create audio player */
   332     const SLInterfaceID ids[2] = {
   333         SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
   334         SL_IID_VOLUME
   335     };
   336 
   337     const SLboolean req[2] = {
   338         SL_BOOLEAN_TRUE,
   339         SL_BOOLEAN_FALSE,
   340     };
   341 
   342     result = (*engineEngine)->CreateAudioPlayer(engineEngine, &bqPlayerObject, &audioSrc, &audioSnk, 2, ids, req);
   343     if (SL_RESULT_SUCCESS != result) {
   344         LOGE("CreateAudioPlayer failed");
   345         goto failed;
   346     }
   347 
   348     /* realize the player */
   349     result = (*bqPlayerObject)->Realize(bqPlayerObject, SL_BOOLEAN_FALSE);
   350     if (SL_RESULT_SUCCESS != result) {
   351         LOGE("RealizeAudioPlayer failed");
   352         goto failed;
   353     }
   354 
   355     /* get the play interface */
   356     result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_PLAY, &bqPlayerPlay);
   357     if (SL_RESULT_SUCCESS != result) {
   358         LOGE("SL_IID_PLAY interface get failed");
   359         goto failed;
   360     }
   361 
   362     /* get the buffer queue interface */
   363     result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &bqPlayerBufferQueue);
   364     if (SL_RESULT_SUCCESS != result) {
   365         LOGE("SL_IID_BUFFERQUEUE interface get failed");
   366         goto failed;
   367     }
   368 
   369     /* register callback on the buffer queue */
   370     /* context is '(SDL_PrivateAudioData *)this->hidden' */
   371     result = (*bqPlayerBufferQueue)->RegisterCallback(bqPlayerBufferQueue, bqPlayerCallback, this->hidden);
   372     if (SL_RESULT_SUCCESS != result) {
   373         LOGE("RegisterCallback failed");
   374         goto failed;
   375     }
   376 
   377 #if 0
   378     /* get the effect send interface */
   379     result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_EFFECTSEND, &bqPlayerEffectSend);
   380     if (SL_RESULT_SUCCESS != result)
   381     {
   382 
   383         LOGE("SL_IID_EFFECTSEND interface get failed");
   384         goto failed;
   385     }
   386 #endif
   387 
   388 #if 0   /* mute/solo is not supported for sources that are known to be mono, as this is */
   389     /* get the mute/solo interface */
   390     result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_MUTESOLO, &bqPlayerMuteSolo);
   391     assert(SL_RESULT_SUCCESS == result);
   392     (void) result;
   393 #endif
   394 
   395     /* get the volume interface */
   396     result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_VOLUME, &bqPlayerVolume);
   397     if (SL_RESULT_SUCCESS != result) {
   398         LOGE("SL_IID_VOLUME interface get failed");
   399         /* goto failed; */
   400     }
   401 
   402     /* Create the audio buffer semaphore */
   403     audiodata->playsem = SDL_CreateSemaphore(NUM_BUFFERS - 1);
   404     if (!audiodata->playsem) {
   405         LOGE("cannot create Semaphore!");
   406         goto failed;
   407     }
   408 
   409     /* Create the sound buffers */
   410     audiodata->mixbuff = (Uint8 *) SDL_malloc(NUM_BUFFERS * this->spec.size);
   411     if (audiodata->mixbuff == NULL) {
   412         LOGE("mixbuffer allocate - out of memory");
   413         goto failed;
   414     }
   415 
   416     for (i = 0; i < NUM_BUFFERS; i++) {
   417         audiodata->pmixbuff[i] = audiodata->mixbuff + i * this->spec.size;
   418     }
   419 
   420     /* set the player's state to playing */
   421     result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_PLAYING);
   422     if (SL_RESULT_SUCCESS != result) {
   423         LOGE("Play set state failed");
   424         goto failed;
   425     }
   426 
   427     return 0;
   428 
   429 failed:
   430 
   431     openslES_DestroyPCMPlayer(this);
   432 
   433     return SDL_SetError("Open device failed!");
   434 }
   435 
   436 static void
   437 openslES_DestroyPCMPlayer(_THIS)
   438 {
   439     struct SDL_PrivateAudioData *audiodata = (struct SDL_PrivateAudioData *) this->hidden;
   440     SLresult result;
   441 
   442     /* set the player's state to 'stopped' */
   443     if (bqPlayerPlay != NULL) {
   444         result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_STOPPED);
   445         if (SL_RESULT_SUCCESS != result) {
   446             SDL_SetError("Stopped set state failed");
   447         }
   448     }
   449 
   450     /* destroy buffer queue audio player object, and invalidate all associated interfaces */
   451     if (bqPlayerObject != NULL) {
   452 
   453         (*bqPlayerObject)->Destroy(bqPlayerObject);
   454 
   455         bqPlayerObject = NULL;
   456         bqPlayerPlay = NULL;
   457         bqPlayerBufferQueue = NULL;
   458         /* bqPlayerEffectSend = NULL; */
   459         bqPlayerMuteSolo = NULL;
   460         bqPlayerVolume = NULL;
   461     }
   462 
   463     if (audiodata->playsem) {
   464         SDL_DestroySemaphore(audiodata->playsem);
   465         audiodata->playsem = NULL;
   466     }
   467 
   468     if (audiodata->mixbuff) {
   469         SDL_free(audiodata->mixbuff);
   470     }
   471 
   472     return;
   473 }
   474 
   475 static int
   476 openslES_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
   477 {
   478     this->hidden = (struct SDL_PrivateAudioData *) SDL_calloc(1, (sizeof *this->hidden));
   479     if (this->hidden == NULL) {
   480         return SDL_OutOfMemory();
   481     }
   482 
   483     if (iscapture) {
   484         LOGI("openslES_OpenDevice( ) %s for capture", devname);
   485         return openslES_CreatePCMRecorder(this);
   486     } else {
   487         LOGI("openslES_OpenDevice( ) %s for playing", devname);
   488         return openslES_CreatePCMPlayer(this);
   489     }
   490 }
   491 
   492 static void
   493 openslES_CloseDevice(_THIS)
   494 {
   495     /* struct SDL_PrivateAudioData *audiodata = (struct SDL_PrivateAudioData *) this->hidden; */
   496 
   497     if (this->iscapture) {
   498         LOGI("openslES_CloseDevice( ) for capture");
   499         openslES_DestroyPCMRecorder(this);
   500     } else {
   501         LOGI("openslES_CloseDevice( ) for playing");
   502         openslES_DestroyPCMPlayer(this);
   503     }
   504 
   505     SDL_free(this->hidden);
   506 
   507     return;
   508 }
   509 
   510 static void
   511 openslES_WaitDevice(_THIS)
   512 {
   513     struct SDL_PrivateAudioData *audiodata = (struct SDL_PrivateAudioData *) this->hidden;
   514 
   515     LOGI("openslES_WaitDevice( )");
   516 
   517     /* Wait for an audio chunk to finish */
   518     /* WaitForSingleObject(this->hidden->audio_sem, INFINITE); */
   519     SDL_SemWait(audiodata->playsem);
   520 
   521     return;
   522 }
   523 
   524 /*/           n   playn sem */
   525 /* getbuf     0   -     1 */
   526 /* fill buff  0   -     1 */
   527 /* play       0 - 0     1 */
   528 /* wait       1   0     0 */
   529 /* getbuf     1   0     0 */
   530 /* fill buff  1   0     0 */
   531 /* play       0   0     0 */
   532 /* wait */
   533 /* */
   534 /* okay.. */
   535 
   536 static Uint8 *
   537 openslES_GetDeviceBuf(_THIS)
   538 {
   539     struct SDL_PrivateAudioData *audiodata = (struct SDL_PrivateAudioData *) this->hidden;
   540 
   541     LOGI("openslES_GetDeviceBuf( )");
   542     return audiodata->pmixbuff[audiodata->next_buffer];
   543 }
   544 
   545 static void
   546 openslES_PlayDevice(_THIS)
   547 {
   548     struct SDL_PrivateAudioData *audiodata = (struct SDL_PrivateAudioData *) this->hidden;
   549     SLresult result;
   550 
   551     LOGI("======openslES_PlayDevice( )======");
   552 
   553     /* Queue it up */
   554     result = (*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, audiodata->pmixbuff[audiodata->next_buffer], this->spec.size);
   555 
   556     audiodata->next_buffer++;
   557     if (audiodata->next_buffer >= NUM_BUFFERS) {
   558         audiodata->next_buffer = 0;
   559     }
   560 
   561     /* If Enqueue fails, callback won't be called.
   562      * Post the semphore, not to run out of buffer */
   563     if (SL_RESULT_SUCCESS != result) {
   564         SDL_SemPost(audiodata->playsem);
   565     }
   566 
   567     return;
   568 }
   569 
   570 static int
   571 openslES_Init(SDL_AudioDriverImpl * impl)
   572 {
   573     LOGI("openslES_Init() called");
   574 
   575     if (!openslES_CreateEngine()) {
   576         return 0;
   577     }
   578 
   579     LOGI("openslES_Init() - set pointers");
   580 
   581     /* Set the function pointers */
   582     /* impl->DetectDevices = openslES_DetectDevices; */
   583     impl->OpenDevice    = openslES_OpenDevice;
   584     impl->CloseDevice   = openslES_CloseDevice;
   585     impl->PlayDevice    = openslES_PlayDevice;
   586     impl->GetDeviceBuf  = openslES_GetDeviceBuf;
   587     impl->Deinitialize  = openslES_DestroyEngine;
   588     impl->WaitDevice    = openslES_WaitDevice;
   589 
   590     /* and the capabilities */
   591     impl->HasCaptureSupport             = 0;        /* TODO */
   592     impl->OnlyHasDefaultOutputDevice    = 1;
   593     /* impl->OnlyHasDefaultInputDevice  = 1; */
   594 
   595     LOGI("openslES_Init() - succes");
   596 
   597     /* this audio target is available. */
   598     return 1;
   599 }
   600 
   601 AudioBootStrap openslES_bootstrap = {
   602     "openslES", "opensl ES audio driver", openslES_Init, 0
   603 };
   604 
   605 void openslES_ResumeDevices()
   606 {
   607     if (bqPlayerPlay != NULL) {
   608         /* set the player's state to 'playing' */
   609         SLresult result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_PLAYING);
   610         if (SL_RESULT_SUCCESS != result) {
   611             SDL_SetError("openslES_ResumeDevices failed");
   612         }
   613     }
   614 }
   615 
   616 void openslES_PauseDevices()
   617 {
   618     if (bqPlayerPlay != NULL) {
   619         /* set the player's state to 'paused' */
   620         SLresult result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_PAUSED);
   621         if (SL_RESULT_SUCCESS != result) {
   622             SDL_SetError("openslES_PauseDevices failed");
   623         }
   624     }
   625 }
   626 
   627 #endif /* SDL_AUDIO_DRIVER_OPENSLES */
   628 
   629 /* vi: set ts=4 sw=4 expandtab: */