Blame channels/rdpsnd/client/opensles/opensl_io.c

Packit 1fb8d4
/*
Packit 1fb8d4
opensl_io.c:
Packit 1fb8d4
Android OpenSL input/output module
Packit 1fb8d4
Copyright (c) 2012, Victor Lazzarini
Packit 1fb8d4
All rights reserved.
Packit 1fb8d4
Packit 1fb8d4
Redistribution and use in source and binary forms, with or without
Packit 1fb8d4
modification, are permitted provided that the following conditions are met:
Packit 1fb8d4
	* Redistributions of source code must retain the above copyright
Packit 1fb8d4
	  notice, this list of conditions and the following disclaimer.
Packit 1fb8d4
	* Redistributions in binary form must reproduce the above copyright
Packit 1fb8d4
	  notice, this list of conditions and the following disclaimer in the
Packit 1fb8d4
	  documentation and/or other materials provided with the distribution.
Packit 1fb8d4
	* Neither the name of the <organization> nor the
Packit 1fb8d4
	  names of its contributors may be used to endorse or promote products
Packit 1fb8d4
	  derived from this software without specific prior written permission.
Packit 1fb8d4
Packit 1fb8d4
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
Packit 1fb8d4
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
Packit 1fb8d4
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
Packit 1fb8d4
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
Packit 1fb8d4
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
Packit 1fb8d4
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
Packit 1fb8d4
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
Packit 1fb8d4
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
Packit 1fb8d4
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
Packit 1fb8d4
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Packit 1fb8d4
*/
Packit 1fb8d4
Packit 1fb8d4
#include <assert.h>
Packit 1fb8d4
Packit 1fb8d4
#include "rdpsnd_main.h"
Packit 1fb8d4
#include "opensl_io.h"
Packit 1fb8d4
#define CONV16BIT 32768
Packit 1fb8d4
#define CONVMYFLT (1./32768.)
Packit 1fb8d4
Packit 1fb8d4
static void bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void* context);
Packit 1fb8d4
Packit 1fb8d4
// creates the OpenSL ES audio engine
Packit 1fb8d4
static SLresult openSLCreateEngine(OPENSL_STREAM* p)
Packit 1fb8d4
{
Packit 1fb8d4
	SLresult result;
Packit 1fb8d4
	// create engine
Packit 1fb8d4
	result = slCreateEngine(&(p->engineObject), 0, NULL, 0, NULL, NULL);
Packit 1fb8d4
	DEBUG_SND("engineObject=%p", (void*) p->engineObject);
Packit 1fb8d4
Packit 1fb8d4
	if (result != SL_RESULT_SUCCESS) goto  engine_end;
Packit 1fb8d4
Packit 1fb8d4
	// realize the engine
Packit 1fb8d4
	result = (*p->engineObject)->Realize(p->engineObject, SL_BOOLEAN_FALSE);
Packit 1fb8d4
	DEBUG_SND("Realize=%"PRIu32"", result);
Packit 1fb8d4
Packit 1fb8d4
	if (result != SL_RESULT_SUCCESS) goto engine_end;
Packit 1fb8d4
Packit 1fb8d4
	// get the engine interface, which is needed in order to create other objects
Packit 1fb8d4
	result = (*p->engineObject)->GetInterface(p->engineObject, SL_IID_ENGINE,
Packit 1fb8d4
	         &(p->engineEngine));
Packit 1fb8d4
	DEBUG_SND("engineEngine=%p", (void*) p->engineEngine);
Packit 1fb8d4
Packit 1fb8d4
	if (result != SL_RESULT_SUCCESS) goto  engine_end;
Packit 1fb8d4
Packit 1fb8d4
engine_end:
Packit 1fb8d4
	return result;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
// opens the OpenSL ES device for output
Packit 1fb8d4
static SLresult openSLPlayOpen(OPENSL_STREAM* p)
Packit 1fb8d4
{
Packit 1fb8d4
	SLresult result;
Packit 1fb8d4
	SLuint32 sr = p->sr;
Packit 1fb8d4
	SLuint32  channels = p->outchannels;
Packit 1fb8d4
	assert(p->engineObject);
Packit 1fb8d4
	assert(p->engineEngine);
Packit 1fb8d4
Packit 1fb8d4
	if (channels)
Packit 1fb8d4
	{
Packit 1fb8d4
		// configure audio source
Packit 1fb8d4
		SLDataLocator_AndroidSimpleBufferQueue loc_bufq =
Packit 1fb8d4
		{
Packit 1fb8d4
			SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE,
Packit 1fb8d4
			p->queuesize
Packit 1fb8d4
		};
Packit 1fb8d4
Packit 1fb8d4
		switch (sr)
Packit 1fb8d4
		{
Packit 1fb8d4
			case 8000:
Packit 1fb8d4
				sr = SL_SAMPLINGRATE_8;
Packit 1fb8d4
				break;
Packit 1fb8d4
Packit 1fb8d4
			case 11025:
Packit 1fb8d4
				sr = SL_SAMPLINGRATE_11_025;
Packit 1fb8d4
				break;
Packit 1fb8d4
Packit 1fb8d4
			case 16000:
Packit 1fb8d4
				sr = SL_SAMPLINGRATE_16;
Packit 1fb8d4
				break;
Packit 1fb8d4
Packit 1fb8d4
			case 22050:
Packit 1fb8d4
				sr = SL_SAMPLINGRATE_22_05;
Packit 1fb8d4
				break;
Packit 1fb8d4
Packit 1fb8d4
			case 24000:
Packit 1fb8d4
				sr = SL_SAMPLINGRATE_24;
Packit 1fb8d4
				break;
Packit 1fb8d4
Packit 1fb8d4
			case 32000:
Packit 1fb8d4
				sr = SL_SAMPLINGRATE_32;
Packit 1fb8d4
				break;
Packit 1fb8d4
Packit 1fb8d4
			case 44100:
Packit 1fb8d4
				sr = SL_SAMPLINGRATE_44_1;
Packit 1fb8d4
				break;
Packit 1fb8d4
Packit 1fb8d4
			case 48000:
Packit 1fb8d4
				sr = SL_SAMPLINGRATE_48;
Packit 1fb8d4
				break;
Packit 1fb8d4
Packit 1fb8d4
			case 64000:
Packit 1fb8d4
				sr = SL_SAMPLINGRATE_64;
Packit 1fb8d4
				break;
Packit 1fb8d4
Packit 1fb8d4
			case 88200:
Packit 1fb8d4
				sr = SL_SAMPLINGRATE_88_2;
Packit 1fb8d4
				break;
Packit 1fb8d4
Packit 1fb8d4
			case 96000:
Packit 1fb8d4
				sr = SL_SAMPLINGRATE_96;
Packit 1fb8d4
				break;
Packit 1fb8d4
Packit 1fb8d4
			case 192000:
Packit 1fb8d4
				sr = SL_SAMPLINGRATE_192;
Packit 1fb8d4
				break;
Packit 1fb8d4
Packit 1fb8d4
			default:
Packit 1fb8d4
				return -1;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		const SLInterfaceID ids[] = {SL_IID_VOLUME};
Packit 1fb8d4
		const SLboolean req[] = {SL_BOOLEAN_FALSE};
Packit 1fb8d4
		result = (*p->engineEngine)->CreateOutputMix(p->engineEngine,
Packit 1fb8d4
		         &(p->outputMixObject), 1, ids, req);
Packit 1fb8d4
		DEBUG_SND("engineEngine=%p", (void*) p->engineEngine);
Packit 1fb8d4
		assert(!result);
Packit 1fb8d4
Packit 1fb8d4
		if (result != SL_RESULT_SUCCESS) goto end_openaudio;
Packit 1fb8d4
Packit 1fb8d4
		// realize the output mix
Packit 1fb8d4
		result = (*p->outputMixObject)->Realize(p->outputMixObject, SL_BOOLEAN_FALSE);
Packit 1fb8d4
		DEBUG_SND("Realize=%"PRIu32"", result);
Packit 1fb8d4
		assert(!result);
Packit 1fb8d4
Packit 1fb8d4
		if (result != SL_RESULT_SUCCESS) goto end_openaudio;
Packit 1fb8d4
Packit 1fb8d4
		int speakers;
Packit 1fb8d4
Packit 1fb8d4
		if (channels > 1)
Packit 1fb8d4
			speakers = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
Packit 1fb8d4
		else speakers = SL_SPEAKER_FRONT_CENTER;
Packit 1fb8d4
Packit 1fb8d4
		SLDataFormat_PCM format_pcm = {SL_DATAFORMAT_PCM, channels, sr,
Packit 1fb8d4
		                               SL_PCMSAMPLEFORMAT_FIXED_16, SL_PCMSAMPLEFORMAT_FIXED_16,
Packit 1fb8d4
		                               speakers, SL_BYTEORDER_LITTLEENDIAN
Packit 1fb8d4
		                              };
Packit 1fb8d4
		SLDataSource audioSrc = {&loc_bufq, &format_pcm};
Packit 1fb8d4
		// configure audio sink
Packit 1fb8d4
		SLDataLocator_OutputMix loc_outmix = {SL_DATALOCATOR_OUTPUTMIX, p->outputMixObject};
Packit 1fb8d4
		SLDataSink audioSnk = {&loc_outmix, NULL};
Packit 1fb8d4
		// create audio player
Packit 1fb8d4
		const SLInterfaceID ids1[] = {SL_IID_ANDROIDSIMPLEBUFFERQUEUE, SL_IID_VOLUME};
Packit 1fb8d4
		const SLboolean req1[] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};
Packit 1fb8d4
		result = (*p->engineEngine)->CreateAudioPlayer(p->engineEngine,
Packit 1fb8d4
		         &(p->bqPlayerObject), &audioSrc, &audioSnk, 2, ids1, req1);
Packit 1fb8d4
		DEBUG_SND("bqPlayerObject=%p", (void*) p->bqPlayerObject);
Packit 1fb8d4
		assert(!result);
Packit 1fb8d4
Packit 1fb8d4
		if (result != SL_RESULT_SUCCESS) goto end_openaudio;
Packit 1fb8d4
Packit 1fb8d4
		// realize the player
Packit 1fb8d4
		result = (*p->bqPlayerObject)->Realize(p->bqPlayerObject, SL_BOOLEAN_FALSE);
Packit 1fb8d4
		DEBUG_SND("Realize=%"PRIu32"", result);
Packit 1fb8d4
		assert(!result);
Packit 1fb8d4
Packit 1fb8d4
		if (result != SL_RESULT_SUCCESS) goto end_openaudio;
Packit 1fb8d4
Packit 1fb8d4
		// get the play interface
Packit 1fb8d4
		result = (*p->bqPlayerObject)->GetInterface(p->bqPlayerObject, SL_IID_PLAY,
Packit 1fb8d4
		         &(p->bqPlayerPlay));
Packit 1fb8d4
		DEBUG_SND("bqPlayerPlay=%p", (void*) p->bqPlayerPlay);
Packit 1fb8d4
		assert(!result);
Packit 1fb8d4
Packit 1fb8d4
		if (result != SL_RESULT_SUCCESS) goto end_openaudio;
Packit 1fb8d4
Packit 1fb8d4
		// get the volume interface
Packit 1fb8d4
		result = (*p->bqPlayerObject)->GetInterface(p->bqPlayerObject, SL_IID_VOLUME,
Packit 1fb8d4
		         &(p->bqPlayerVolume));
Packit 1fb8d4
		DEBUG_SND("bqPlayerVolume=%p", (void*) p->bqPlayerVolume);
Packit 1fb8d4
		assert(!result);
Packit 1fb8d4
Packit 1fb8d4
		if (result != SL_RESULT_SUCCESS) goto end_openaudio;
Packit 1fb8d4
Packit 1fb8d4
		// get the buffer queue interface
Packit 1fb8d4
		result = (*p->bqPlayerObject)->GetInterface(p->bqPlayerObject,
Packit 1fb8d4
		         SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
Packit 1fb8d4
		         &(p->bqPlayerBufferQueue));
Packit 1fb8d4
		DEBUG_SND("bqPlayerBufferQueue=%p", (void*) p->bqPlayerBufferQueue);
Packit 1fb8d4
		assert(!result);
Packit 1fb8d4
Packit 1fb8d4
		if (result != SL_RESULT_SUCCESS) goto end_openaudio;
Packit 1fb8d4
Packit 1fb8d4
		// register callback on the buffer queue
Packit 1fb8d4
		result = (*p->bqPlayerBufferQueue)->RegisterCallback(p->bqPlayerBufferQueue,
Packit 1fb8d4
		         bqPlayerCallback, p);
Packit 1fb8d4
		DEBUG_SND("bqPlayerCallback=%p", (void*) p->bqPlayerCallback);
Packit 1fb8d4
		assert(!result);
Packit 1fb8d4
Packit 1fb8d4
		if (result != SL_RESULT_SUCCESS) goto end_openaudio;
Packit 1fb8d4
Packit 1fb8d4
		// set the player's state to playing
Packit 1fb8d4
		result = (*p->bqPlayerPlay)->SetPlayState(p->bqPlayerPlay,
Packit 1fb8d4
		         SL_PLAYSTATE_PLAYING);
Packit 1fb8d4
		DEBUG_SND("SetPlayState=%"PRIu32"", result);
Packit 1fb8d4
		assert(!result);
Packit 1fb8d4
	end_openaudio:
Packit 1fb8d4
		assert(!result);
Packit 1fb8d4
		return result;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return SL_RESULT_SUCCESS;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
// close the OpenSL IO and destroy the audio engine
Packit 1fb8d4
static void openSLDestroyEngine(OPENSL_STREAM* p)
Packit 1fb8d4
{
Packit 1fb8d4
	// destroy buffer queue audio player object, and invalidate all associated interfaces
Packit 1fb8d4
	if (p->bqPlayerObject != NULL)
Packit 1fb8d4
	{
Packit 1fb8d4
		(*p->bqPlayerObject)->Destroy(p->bqPlayerObject);
Packit 1fb8d4
		p->bqPlayerObject = NULL;
Packit 1fb8d4
		p->bqPlayerVolume = NULL;
Packit 1fb8d4
		p->bqPlayerPlay = NULL;
Packit 1fb8d4
		p->bqPlayerBufferQueue = NULL;
Packit 1fb8d4
		p->bqPlayerEffectSend = NULL;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	// destroy output mix object, and invalidate all associated interfaces
Packit 1fb8d4
	if (p->outputMixObject != NULL)
Packit 1fb8d4
	{
Packit 1fb8d4
		(*p->outputMixObject)->Destroy(p->outputMixObject);
Packit 1fb8d4
		p->outputMixObject = NULL;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	// destroy engine object, and invalidate all associated interfaces
Packit 1fb8d4
	if (p->engineObject != NULL)
Packit 1fb8d4
	{
Packit 1fb8d4
		(*p->engineObject)->Destroy(p->engineObject);
Packit 1fb8d4
		p->engineObject = NULL;
Packit 1fb8d4
		p->engineEngine = NULL;
Packit 1fb8d4
	}
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
Packit 1fb8d4
// open the android audio device for and/or output
Packit 1fb8d4
OPENSL_STREAM* android_OpenAudioDevice(int sr, int outchannels,
Packit 1fb8d4
                                       int bufferframes)
Packit 1fb8d4
{
Packit 1fb8d4
	OPENSL_STREAM* p;
Packit 1fb8d4
	p = (OPENSL_STREAM*) calloc(1, sizeof(OPENSL_STREAM));
Packit 1fb8d4
Packit 1fb8d4
	if (!p)
Packit 1fb8d4
		return NULL;
Packit 1fb8d4
Packit 1fb8d4
	p->queuesize = bufferframes;
Packit 1fb8d4
	p->outchannels = outchannels;
Packit 1fb8d4
	p->sr = sr;
Packit 1fb8d4
Packit 1fb8d4
	if (openSLCreateEngine(p) != SL_RESULT_SUCCESS)
Packit 1fb8d4
	{
Packit 1fb8d4
		android_CloseAudioDevice(p);
Packit 1fb8d4
		return NULL;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (openSLPlayOpen(p) != SL_RESULT_SUCCESS)
Packit 1fb8d4
	{
Packit 1fb8d4
		android_CloseAudioDevice(p);
Packit 1fb8d4
		return NULL;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	p->queue = Queue_New(TRUE, -1, -1);
Packit 1fb8d4
Packit 1fb8d4
	if (!p->queue)
Packit 1fb8d4
	{
Packit 1fb8d4
		android_CloseAudioDevice(p);
Packit 1fb8d4
		return NULL;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return p;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
// close the android audio device
Packit 1fb8d4
void android_CloseAudioDevice(OPENSL_STREAM* p)
Packit 1fb8d4
{
Packit 1fb8d4
	if (p == NULL)
Packit 1fb8d4
		return;
Packit 1fb8d4
Packit 1fb8d4
	openSLDestroyEngine(p);
Packit 1fb8d4
Packit 1fb8d4
	if (p->queue)
Packit 1fb8d4
		Queue_Free(p->queue);
Packit 1fb8d4
Packit 1fb8d4
	free(p);
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
// this callback handler is called every time a buffer finishes playing
Packit 1fb8d4
static void bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void* context)
Packit 1fb8d4
{
Packit 1fb8d4
	OPENSL_STREAM* p = (OPENSL_STREAM*) context;
Packit 1fb8d4
	assert(p);
Packit 1fb8d4
	assert(p->queue);
Packit 1fb8d4
	void* data = Queue_Dequeue(p->queue);
Packit 1fb8d4
	free(data);
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
// puts a buffer of size samples to the device
Packit 1fb8d4
int android_AudioOut(OPENSL_STREAM* p, const short* buffer, int size)
Packit 1fb8d4
{
Packit 1fb8d4
	assert(p);
Packit 1fb8d4
	assert(buffer);
Packit 1fb8d4
	assert(size > 0);
Packit 1fb8d4
Packit 1fb8d4
	/* Assure, that the queue is not full. */
Packit 1fb8d4
	if (p->queuesize <= Queue_Count(p->queue)
Packit 1fb8d4
	    && WaitForSingleObject(p->queue->event, INFINITE) == WAIT_FAILED)
Packit 1fb8d4
	{
Packit 1fb8d4
		DEBUG_SND("WaitForSingleObject failed!");
Packit 1fb8d4
		return -1;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	void* data = calloc(size, sizeof(short));
Packit 1fb8d4
Packit 1fb8d4
	if (!data)
Packit 1fb8d4
	{
Packit 1fb8d4
		DEBUG_SND("unable to allocate a buffer");
Packit 1fb8d4
		return -1;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	memcpy(data, buffer, size * sizeof(short));
Packit 1fb8d4
	Queue_Enqueue(p->queue, data);
Packit 1fb8d4
	(*p->bqPlayerBufferQueue)->Enqueue(p->bqPlayerBufferQueue,
Packit 1fb8d4
	                                   data, sizeof(short) * size);
Packit 1fb8d4
	return size;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
int android_GetOutputMute(OPENSL_STREAM* p)
Packit 1fb8d4
{
Packit 1fb8d4
	SLboolean mute;
Packit 1fb8d4
	assert(p);
Packit 1fb8d4
	assert(p->bqPlayerVolume);
Packit 1fb8d4
	SLresult rc = (*p->bqPlayerVolume)->GetMute(p->bqPlayerVolume, &mute);
Packit 1fb8d4
Packit 1fb8d4
	if (SL_RESULT_SUCCESS != rc)
Packit 1fb8d4
		return SL_BOOLEAN_FALSE;
Packit 1fb8d4
Packit 1fb8d4
	return mute;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
BOOL android_SetOutputMute(OPENSL_STREAM* p, BOOL _mute)
Packit 1fb8d4
{
Packit 1fb8d4
	SLboolean mute = _mute;
Packit 1fb8d4
	assert(p);
Packit 1fb8d4
	assert(p->bqPlayerVolume);
Packit 1fb8d4
	SLresult rc = (*p->bqPlayerVolume)->SetMute(p->bqPlayerVolume, mute);
Packit 1fb8d4
Packit 1fb8d4
	if (SL_RESULT_SUCCESS != rc)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
int android_GetOutputVolume(OPENSL_STREAM* p)
Packit 1fb8d4
{
Packit 1fb8d4
	SLmillibel level;
Packit 1fb8d4
	assert(p);
Packit 1fb8d4
	assert(p->bqPlayerVolume);
Packit 1fb8d4
	SLresult rc = (*p->bqPlayerVolume)->GetVolumeLevel(p->bqPlayerVolume, &level);
Packit 1fb8d4
Packit 1fb8d4
	if (SL_RESULT_SUCCESS != rc)
Packit 1fb8d4
		return 0;
Packit 1fb8d4
Packit 1fb8d4
	return level;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
int android_GetOutputVolumeMax(OPENSL_STREAM* p)
Packit 1fb8d4
{
Packit 1fb8d4
	SLmillibel level;
Packit 1fb8d4
	assert(p);
Packit 1fb8d4
	assert(p->bqPlayerVolume);
Packit 1fb8d4
	SLresult rc = (*p->bqPlayerVolume)->GetMaxVolumeLevel(p->bqPlayerVolume,
Packit 1fb8d4
	              &level);
Packit 1fb8d4
Packit 1fb8d4
	if (SL_RESULT_SUCCESS != rc)
Packit 1fb8d4
		return 0;
Packit 1fb8d4
Packit 1fb8d4
	return level;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
Packit 1fb8d4
BOOL android_SetOutputVolume(OPENSL_STREAM* p, int level)
Packit 1fb8d4
{
Packit 1fb8d4
	SLresult rc = (*p->bqPlayerVolume)->SetVolumeLevel(p->bqPlayerVolume, level);
Packit 1fb8d4
Packit 1fb8d4
	if (SL_RESULT_SUCCESS != rc)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4