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