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