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