src/audio/openslES/SDL_openslES.c
author Sylvain Becker <sylvain.becker@gmail.com>
Tue, 05 Feb 2019 15:09:41 +0100
changeset 12597 b5ea5997cbf9
parent 12596 6654faf2160e
child 12598 d3acc7299a95
permissions -rw-r--r--
Android/openslES: set number of buffers of DATALOCATOR to internal NUM_BUFFER
If we increase NUM_BUFFER, Enqueue won't fail with SL_RESULT_BUFFER_INSUFFICIENT
     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, NUM_BUFFERS };
   276 
   277     format_pcm.formatType    = SL_DATAFORMAT_PCM;
   278     format_pcm.numChannels   = this->spec.channels;
   279     format_pcm.samplesPerSec = this->spec.freq * 1000;  /* / kilo Hz to milli Hz */
   280     format_pcm.bitsPerSample = SDL_AUDIO_BITSIZE(this->spec.format);
   281     format_pcm.containerSize = SDL_AUDIO_BITSIZE(this->spec.format);
   282 
   283     if (SDL_AUDIO_ISBIGENDIAN(this->spec.format)) {
   284         format_pcm.endianness = SL_BYTEORDER_BIGENDIAN;
   285     } else {
   286         format_pcm.endianness = SL_BYTEORDER_LITTLEENDIAN;
   287     }
   288 
   289 /*
   290 #define SL_SPEAKER_FRONT_LEFT            ((SLuint32) 0x00000001)
   291 #define SL_SPEAKER_FRONT_RIGHT           ((SLuint32) 0x00000002)
   292 #define SL_SPEAKER_FRONT_CENTER          ((SLuint32) 0x00000004)
   293 #define SL_SPEAKER_LOW_FREQUENCY         ((SLuint32) 0x00000008)
   294 #define SL_SPEAKER_BACK_LEFT             ((SLuint32) 0x00000010)
   295 #define SL_SPEAKER_BACK_RIGHT            ((SLuint32) 0x00000020)
   296 #define SL_SPEAKER_FRONT_LEFT_OF_CENTER  ((SLuint32) 0x00000040)
   297 #define SL_SPEAKER_FRONT_RIGHT_OF_CENTER ((SLuint32) 0x00000080)
   298 #define SL_SPEAKER_BACK_CENTER           ((SLuint32) 0x00000100)
   299 #define SL_SPEAKER_SIDE_LEFT             ((SLuint32) 0x00000200)
   300 #define SL_SPEAKER_SIDE_RIGHT            ((SLuint32) 0x00000400)
   301 #define SL_SPEAKER_TOP_CENTER            ((SLuint32) 0x00000800)
   302 #define SL_SPEAKER_TOP_FRONT_LEFT        ((SLuint32) 0x00001000)
   303 #define SL_SPEAKER_TOP_FRONT_CENTER      ((SLuint32) 0x00002000)
   304 #define SL_SPEAKER_TOP_FRONT_RIGHT       ((SLuint32) 0x00004000)
   305 #define SL_SPEAKER_TOP_BACK_LEFT         ((SLuint32) 0x00008000)
   306 #define SL_SPEAKER_TOP_BACK_CENTER       ((SLuint32) 0x00010000)
   307 #define SL_SPEAKER_TOP_BACK_RIGHT        ((SLuint32) 0x00020000)
   308 */
   309 
   310     if (this->spec.channels == 1) {
   311         format_pcm.channelMask = SL_SPEAKER_FRONT_CENTER;
   312     } else if (this->spec.channels == 2) {
   313         format_pcm.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
   314     } else if (this->spec.channels == 3) {
   315         format_pcm.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT | SL_SPEAKER_FRONT_CENTER;
   316     } else if (this->spec.channels == 4) {
   317         format_pcm.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT |
   318               SL_SPEAKER_BACK_LEFT | SL_SPEAKER_BACK_RIGHT;
   319     } else {
   320         format_pcm.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT |
   321               SL_SPEAKER_BACK_LEFT | SL_SPEAKER_BACK_RIGHT | SL_SPEAKER_FRONT_CENTER;
   322     }
   323 
   324     SLDataSource audioSrc = { &loc_bufq, &format_pcm };
   325 
   326     /* configure audio sink */
   327     SLDataLocator_OutputMix loc_outmix = { SL_DATALOCATOR_OUTPUTMIX, outputMixObject };
   328     SLDataSink audioSnk = { &loc_outmix, NULL };
   329 
   330     /* create audio player */
   331     const SLInterfaceID ids[2] = {
   332         SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
   333         SL_IID_VOLUME
   334     };
   335 
   336     const SLboolean req[2] = {
   337         SL_BOOLEAN_TRUE,
   338         SL_BOOLEAN_FALSE,
   339     };
   340 
   341     result = (*engineEngine)->CreateAudioPlayer(engineEngine, &bqPlayerObject, &audioSrc, &audioSnk, 2, ids, req);
   342     if (SL_RESULT_SUCCESS != result) {
   343         LOGE("CreateAudioPlayer failed");
   344         goto failed;
   345     }
   346 
   347     /* realize the player */
   348     result = (*bqPlayerObject)->Realize(bqPlayerObject, SL_BOOLEAN_FALSE);
   349     if (SL_RESULT_SUCCESS != result) {
   350         LOGE("RealizeAudioPlayer failed");
   351         goto failed;
   352     }
   353 
   354     /* get the play interface */
   355     result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_PLAY, &bqPlayerPlay);
   356     if (SL_RESULT_SUCCESS != result) {
   357         LOGE("SL_IID_PLAY interface get failed");
   358         goto failed;
   359     }
   360 
   361     /* get the buffer queue interface */
   362     result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &bqPlayerBufferQueue);
   363     if (SL_RESULT_SUCCESS != result) {
   364         LOGE("SL_IID_BUFFERQUEUE interface get failed");
   365         goto failed;
   366     }
   367 
   368     /* register callback on the buffer queue */
   369     /* context is '(SDL_PrivateAudioData *)this->hidden' */
   370     result = (*bqPlayerBufferQueue)->RegisterCallback(bqPlayerBufferQueue, bqPlayerCallback, this->hidden);
   371     if (SL_RESULT_SUCCESS != result) {
   372         LOGE("RegisterCallback failed");
   373         goto failed;
   374     }
   375 
   376 #if 0
   377     /* get the effect send interface */
   378     result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_EFFECTSEND, &bqPlayerEffectSend);
   379     if (SL_RESULT_SUCCESS != result)
   380     {
   381 
   382         LOGE("SL_IID_EFFECTSEND interface get failed");
   383         goto failed;
   384     }
   385 #endif
   386 
   387 #if 0   /* mute/solo is not supported for sources that are known to be mono, as this is */
   388     /* get the mute/solo interface */
   389     result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_MUTESOLO, &bqPlayerMuteSolo);
   390     assert(SL_RESULT_SUCCESS == result);
   391     (void) result;
   392 #endif
   393 
   394     /* get the volume interface */
   395     result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_VOLUME, &bqPlayerVolume);
   396     if (SL_RESULT_SUCCESS != result) {
   397         LOGE("SL_IID_VOLUME interface get failed");
   398         /* goto failed; */
   399     }
   400 
   401     /* Create the audio buffer semaphore */
   402     audiodata->playsem = SDL_CreateSemaphore(NUM_BUFFERS - 1);
   403     if (!audiodata->playsem) {
   404         LOGE("cannot create Semaphore!");
   405         goto failed;
   406     }
   407 
   408     /* Create the sound buffers */
   409     audiodata->mixbuff = (Uint8 *) SDL_malloc(NUM_BUFFERS * this->spec.size);
   410     if (audiodata->mixbuff == NULL) {
   411         LOGE("mixbuffer allocate - out of memory");
   412         goto failed;
   413     }
   414 
   415     for (i = 0; i < NUM_BUFFERS; i++) {
   416         audiodata->pmixbuff[i] = audiodata->mixbuff + i * this->spec.size;
   417     }
   418 
   419     /* set the player's state to playing */
   420     result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_PLAYING);
   421     if (SL_RESULT_SUCCESS != result) {
   422         LOGE("Play set state failed");
   423         goto failed;
   424     }
   425 
   426     return 0;
   427 
   428 failed:
   429 
   430     openslES_DestroyPCMPlayer(this);
   431 
   432     return SDL_SetError("Open device failed!");
   433 }
   434 
   435 static void
   436 openslES_DestroyPCMPlayer(_THIS)
   437 {
   438     struct SDL_PrivateAudioData *audiodata = (struct SDL_PrivateAudioData *) this->hidden;
   439     SLresult result;
   440 
   441     /* set the player's state to 'stopped' */
   442     if (bqPlayerPlay != NULL) {
   443         result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_STOPPED);
   444         if (SL_RESULT_SUCCESS != result) {
   445             SDL_SetError("Stopped set state failed");
   446         }
   447     }
   448 
   449     /* destroy buffer queue audio player object, and invalidate all associated interfaces */
   450     if (bqPlayerObject != NULL) {
   451 
   452         (*bqPlayerObject)->Destroy(bqPlayerObject);
   453 
   454         bqPlayerObject = NULL;
   455         bqPlayerPlay = NULL;
   456         bqPlayerBufferQueue = NULL;
   457         /* bqPlayerEffectSend = NULL; */
   458         bqPlayerMuteSolo = NULL;
   459         bqPlayerVolume = NULL;
   460     }
   461 
   462     if (audiodata->playsem) {
   463         SDL_DestroySemaphore(audiodata->playsem);
   464         audiodata->playsem = NULL;
   465     }
   466 
   467     if (audiodata->mixbuff) {
   468         SDL_free(audiodata->mixbuff);
   469     }
   470 
   471     return;
   472 }
   473 
   474 static int
   475 openslES_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
   476 {
   477     this->hidden = (struct SDL_PrivateAudioData *) SDL_calloc(1, (sizeof *this->hidden));
   478     if (this->hidden == NULL) {
   479         return SDL_OutOfMemory();
   480     }
   481 
   482     if (iscapture) {
   483         LOGI("openslES_OpenDevice( ) %s for capture", devname);
   484         return openslES_CreatePCMRecorder(this);
   485     } else {
   486         LOGI("openslES_OpenDevice( ) %s for playing", devname);
   487         return openslES_CreatePCMPlayer(this);
   488     }
   489 }
   490 
   491 static void
   492 openslES_CloseDevice(_THIS)
   493 {
   494     /* struct SDL_PrivateAudioData *audiodata = (struct SDL_PrivateAudioData *) this->hidden; */
   495 
   496     if (this->iscapture) {
   497         LOGI("openslES_CloseDevice( ) for capture");
   498         openslES_DestroyPCMRecorder(this);
   499     } else {
   500         LOGI("openslES_CloseDevice( ) for playing");
   501         openslES_DestroyPCMPlayer(this);
   502     }
   503 
   504     SDL_free(this->hidden);
   505 
   506     return;
   507 }
   508 
   509 static void
   510 openslES_WaitDevice(_THIS)
   511 {
   512     struct SDL_PrivateAudioData *audiodata = (struct SDL_PrivateAudioData *) this->hidden;
   513 
   514     LOGI("openslES_WaitDevice( )");
   515 
   516     /* Wait for an audio chunk to finish */
   517     /* WaitForSingleObject(this->hidden->audio_sem, INFINITE); */
   518     SDL_SemWait(audiodata->playsem);
   519 
   520     return;
   521 }
   522 
   523 /*/           n   playn sem */
   524 /* getbuf     0   -     1 */
   525 /* fill buff  0   -     1 */
   526 /* play       0 - 0     1 */
   527 /* wait       1   0     0 */
   528 /* getbuf     1   0     0 */
   529 /* fill buff  1   0     0 */
   530 /* play       0   0     0 */
   531 /* wait */
   532 /* */
   533 /* okay.. */
   534 
   535 static Uint8 *
   536 openslES_GetDeviceBuf(_THIS)
   537 {
   538     struct SDL_PrivateAudioData *audiodata = (struct SDL_PrivateAudioData *) this->hidden;
   539 
   540     LOGI("openslES_GetDeviceBuf( )");
   541     return audiodata->pmixbuff[audiodata->next_buffer];
   542 }
   543 
   544 static void
   545 openslES_PlayDevice(_THIS)
   546 {
   547     struct SDL_PrivateAudioData *audiodata = (struct SDL_PrivateAudioData *) this->hidden;
   548     SLresult result;
   549 
   550     LOGI("======openslES_PlayDevice( )======");
   551 
   552     /* Queue it up */
   553     result = (*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, audiodata->pmixbuff[audiodata->next_buffer], this->spec.size);
   554 
   555     audiodata->next_buffer++;
   556     if (audiodata->next_buffer >= NUM_BUFFERS) {
   557         audiodata->next_buffer = 0;
   558     }
   559 
   560     /* If Enqueue fails, callback won't be called.
   561      * Post the semphore, not to run out of buffer */
   562     if (SL_RESULT_SUCCESS != result) {
   563         SDL_SemPost(audiodata->playsem);
   564     }
   565 
   566     return;
   567 }
   568 
   569 static int
   570 openslES_Init(SDL_AudioDriverImpl * impl)
   571 {
   572     LOGI("openslES_Init() called");
   573 
   574     if (!openslES_CreateEngine()) {
   575         return 0;
   576     }
   577 
   578     LOGI("openslES_Init() - set pointers");
   579 
   580     /* Set the function pointers */
   581     /* impl->DetectDevices = openslES_DetectDevices; */
   582     impl->OpenDevice    = openslES_OpenDevice;
   583     impl->CloseDevice   = openslES_CloseDevice;
   584     impl->PlayDevice    = openslES_PlayDevice;
   585     impl->GetDeviceBuf  = openslES_GetDeviceBuf;
   586     impl->Deinitialize  = openslES_DestroyEngine;
   587     impl->WaitDevice    = openslES_WaitDevice;
   588 
   589     /* and the capabilities */
   590     impl->HasCaptureSupport             = 0;        /* TODO */
   591     impl->OnlyHasDefaultOutputDevice    = 1;
   592     /* impl->OnlyHasDefaultInputDevice  = 1; */
   593 
   594     LOGI("openslES_Init() - succes");
   595 
   596     /* this audio target is available. */
   597     return 1;
   598 }
   599 
   600 AudioBootStrap openslES_bootstrap = {
   601     "openslES", "opensl ES audio driver", openslES_Init, 0
   602 };
   603 
   604 void openslES_ResumeDevices()
   605 {
   606     if (bqPlayerPlay != NULL) {
   607         /* set the player's state to 'playing' */
   608         SLresult result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_PLAYING);
   609         if (SL_RESULT_SUCCESS != result) {
   610             SDL_SetError("openslES_ResumeDevices failed");
   611         }
   612     }
   613 }
   614 
   615 void openslES_PauseDevices()
   616 {
   617     if (bqPlayerPlay != NULL) {
   618         /* set the player's state to 'paused' */
   619         SLresult result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_PAUSED);
   620         if (SL_RESULT_SUCCESS != result) {
   621             SDL_SetError("openslES_PauseDevices failed");
   622         }
   623     }
   624 }
   625 
   626 #endif /* SDL_AUDIO_DRIVER_OPENSLES */
   627 
   628 /* vi: set ts=4 sw=4 expandtab: */