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