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