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