static ALCenum opensl_open_playback(ALCdevice *Device, const ALCchar *deviceName) { osl_data *data = NULL; SLresult result; if(!deviceName) deviceName = opensl_device; else if(strcmp(deviceName, opensl_device) != 0) return ALC_INVALID_VALUE; data = calloc(1, sizeof(*data)); if(!data) return ALC_OUT_OF_MEMORY; // create engine result = slCreateEngine(&data->engineObject, 0, NULL, 0, NULL, NULL); PRINTERR(result, "slCreateEngine"); if(SL_RESULT_SUCCESS == result) { result = VCALL(data->engineObject,Realize)(SL_BOOLEAN_FALSE); PRINTERR(result, "engine->Realize"); } if(SL_RESULT_SUCCESS == result) { result = VCALL(data->engineObject,GetInterface)(SL_IID_ENGINE, &data->engine); PRINTERR(result, "engine->GetInterface"); } if(SL_RESULT_SUCCESS == result) { result = VCALL(data->engine,CreateOutputMix)(&data->outputMix, 0, NULL, NULL); PRINTERR(result, "engine->CreateOutputMix"); } if(SL_RESULT_SUCCESS == result) { result = VCALL(data->outputMix,Realize)(SL_BOOLEAN_FALSE); PRINTERR(result, "outputMix->Realize"); } if(SL_RESULT_SUCCESS != result) { if(data->outputMix != NULL) VCALL0(data->outputMix,Destroy)(); data->outputMix = NULL; if(data->engineObject != NULL) VCALL0(data->engineObject,Destroy)(); data->engineObject = NULL; data->engine = NULL; free(data); return ALC_INVALID_VALUE; } al_string_copy_cstr(&Device->DeviceName, deviceName); Device->ExtraData = data; return ALC_NO_ERROR; }
static ALCenum ALCopenslPlayback_open(ALCopenslPlayback *self, const ALCchar *name) { ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice; SLresult result; if(!name) name = opensl_device; else if(strcmp(name, opensl_device) != 0) return ALC_INVALID_VALUE; // create engine result = slCreateEngine(&self->mEngineObj, 0, NULL, 0, NULL, NULL); PRINTERR(result, "slCreateEngine"); if(SL_RESULT_SUCCESS == result) { result = VCALL(self->mEngineObj,Realize)(SL_BOOLEAN_FALSE); PRINTERR(result, "engine->Realize"); } if(SL_RESULT_SUCCESS == result) { result = VCALL(self->mEngineObj,GetInterface)(SL_IID_ENGINE, &self->mEngine); PRINTERR(result, "engine->GetInterface"); } if(SL_RESULT_SUCCESS == result) { result = VCALL(self->mEngine,CreateOutputMix)(&self->mOutputMix, 0, NULL, NULL); PRINTERR(result, "engine->CreateOutputMix"); } if(SL_RESULT_SUCCESS == result) { result = VCALL(self->mOutputMix,Realize)(SL_BOOLEAN_FALSE); PRINTERR(result, "outputMix->Realize"); } if(SL_RESULT_SUCCESS != result) { if(self->mOutputMix != NULL) VCALL0(self->mOutputMix,Destroy)(); self->mOutputMix = NULL; if(self->mEngineObj != NULL) VCALL0(self->mEngineObj,Destroy)(); self->mEngineObj = NULL; self->mEngine = NULL; return ALC_INVALID_VALUE; } alstr_copy_cstr(&device->DeviceName, name); return ALC_NO_ERROR; }
static void ALCopenslPlayback_close(ALCopenslPlayback *self) { if(self->mBufferQueueObj != NULL) VCALL0(self->mBufferQueueObj,Destroy)(); self->mBufferQueueObj = NULL; VCALL0(self->mOutputMix,Destroy)(); self->mOutputMix = NULL; VCALL0(self->mEngineObj,Destroy)(); self->mEngineObj = NULL; self->mEngine = NULL; }
static void opensl_close_playback(ALCdevice *Device) { osl_data *data = Device->ExtraData; if(data->bufferQueueObject != NULL) VCALL0(data->bufferQueueObject,Destroy)(); data->bufferQueueObject = NULL; VCALL0(data->outputMix,Destroy)(); data->outputMix = NULL; VCALL0(data->engineObject,Destroy)(); data->engineObject = NULL; data->engine = NULL; free(data); Device->ExtraData = NULL; }
static void ALCopenslPlayback_Destruct(ALCopenslPlayback* self) { if(self->mBufferQueueObj != NULL) VCALL0(self->mBufferQueueObj,Destroy)(); self->mBufferQueueObj = NULL; if(self->mOutputMix != NULL) VCALL0(self->mOutputMix,Destroy)(); self->mOutputMix = NULL; if(self->mEngineObj != NULL) VCALL0(self->mEngineObj,Destroy)(); self->mEngineObj = NULL; self->mEngine = NULL; ll_ringbuffer_free(self->mRing); self->mRing = NULL; alcnd_destroy(&self->mCond); ALCbackend_Destruct(STATIC_CAST(ALCbackend, self)); }
static void opensl_stop_playback(ALCdevice *Device) { osl_data *data = Device->ExtraData; SLPlayItf player; SLAndroidSimpleBufferQueueItf bufferQueue; SLresult result; result = VCALL(data->bufferQueueObject,GetInterface)(SL_IID_PLAY, &player); PRINTERR(result, "bufferQueue->GetInterface"); if(SL_RESULT_SUCCESS == result) { result = VCALL(player,SetPlayState)(SL_PLAYSTATE_STOPPED); PRINTERR(result, "player->SetPlayState"); } result = VCALL(data->bufferQueueObject,GetInterface)(SL_IID_BUFFERQUEUE, &bufferQueue); PRINTERR(result, "bufferQueue->GetInterface"); if(SL_RESULT_SUCCESS == result) { result = VCALL0(bufferQueue,Clear)(); PRINTERR(result, "bufferQueue->Clear"); } if(SL_RESULT_SUCCESS == result) { SLAndroidSimpleBufferQueueState state; do { althrd_yield(); result = VCALL(bufferQueue,GetState)(&state); } while(SL_RESULT_SUCCESS == result && state.count > 0); PRINTERR(result, "bufferQueue->GetState"); } free(data->buffer); data->buffer = NULL; data->bufferSize = 0; }
static ALCboolean opensl_start_playback(ALCdevice *Device) { osl_data *data = Device->ExtraData; SLAndroidSimpleBufferQueueItf bufferQueue; SLPlayItf player; SLresult result; ALuint i; result = SLObjectItf_GetInterface(data->bufferQueueObject, SL_IID_BUFFERQUEUE, &bufferQueue); PRINTERR(result, "bufferQueue->GetInterface"); if(SL_RESULT_SUCCESS == result) { result = (*bufferQueue)->RegisterCallback(bufferQueue, opensl_callback, Device); PRINTERR(result, "bufferQueue->RegisterCallback"); } if(SL_RESULT_SUCCESS == result) { data->frameSize = FrameSizeFromDevFmt(Device->FmtChans, Device->FmtType); data->bufferSize = Device->UpdateSize * data->frameSize; data->buffer = calloc(Device->NumUpdates, data->bufferSize); if(!data->buffer) { result = SL_RESULT_MEMORY_FAILURE; PRINTERR(result, "calloc"); } } if(SL_RESULT_SUCCESS == result) { result = VCALL0(bufferQueue,Clear)(); PRINTERR(result, "bufferQueue->Clear"); } /* enqueue the first buffer to kick off the callbacks */ for(i = 0;i < Device->NumUpdates;i++) { if(SL_RESULT_SUCCESS == result) { ALvoid *buf = (ALbyte*)data->buffer + i*data->bufferSize; result = (*bufferQueue)->Enqueue(bufferQueue, buf, data->bufferSize); PRINTERR(result, "bufferQueue->Enqueue"); } } data->curBuffer = 0; if(SL_RESULT_SUCCESS == result) { result = SLObjectItf_GetInterface(data->bufferQueueObject, SL_IID_PLAY, &player); PRINTERR(result, "bufferQueue->GetInterface"); } if(SL_RESULT_SUCCESS == result) { result = SLPlayItf_SetPlayState(player, SL_PLAYSTATE_PLAYING); PRINTERR(result, "player->SetPlayState"); } if(SL_RESULT_SUCCESS != result) { if(data->bufferQueueObject != NULL) SLObjectItf_Destroy(data->bufferQueueObject); data->bufferQueueObject = NULL; free(data->buffer); data->buffer = NULL; data->bufferSize = 0; return ALC_FALSE; } return ALC_TRUE; }
static ALCboolean ALCopenslPlayback_reset(ALCopenslPlayback *self) { ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice; SLDataLocator_AndroidSimpleBufferQueue loc_bufq; SLDataLocator_OutputMix loc_outmix; SLDataSource audioSrc; SLDataSink audioSnk; ALuint sampleRate; SLInterfaceID ids[2]; SLboolean reqs[2]; SLresult result; JNIEnv *env; if(self->mBufferQueueObj != NULL) VCALL0(self->mBufferQueueObj,Destroy)(); self->mBufferQueueObj = NULL; sampleRate = device->Frequency; if(!(device->Flags&DEVICE_FREQUENCY_REQUEST) && (env=Android_GetJNIEnv()) != NULL) { /* FIXME: Disabled until I figure out how to get the Context needed for * the getSystemService call. */ #if 0 /* Get necessary stuff for using java.lang.Integer, * android.content.Context, and android.media.AudioManager. */ jclass int_cls = JCALL(env,FindClass)("java/lang/Integer"); jmethodID int_parseint = JCALL(env,GetStaticMethodID)(int_cls, "parseInt", "(Ljava/lang/String;)I" ); TRACE("Integer: %p, parseInt: %p\n", int_cls, int_parseint); jclass ctx_cls = JCALL(env,FindClass)("android/content/Context"); jfieldID ctx_audsvc = JCALL(env,GetStaticFieldID)(ctx_cls, "AUDIO_SERVICE", "Ljava/lang/String;" ); jmethodID ctx_getSysSvc = JCALL(env,GetMethodID)(ctx_cls, "getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;" ); TRACE("Context: %p, AUDIO_SERVICE: %p, getSystemService: %p\n", ctx_cls, ctx_audsvc, ctx_getSysSvc); jclass audmgr_cls = JCALL(env,FindClass)("android/media/AudioManager"); jfieldID audmgr_prop_out_srate = JCALL(env,GetStaticFieldID)(audmgr_cls, "PROPERTY_OUTPUT_SAMPLE_RATE", "Ljava/lang/String;" ); jmethodID audmgr_getproperty = JCALL(env,GetMethodID)(audmgr_cls, "getProperty", "(Ljava/lang/String;)Ljava/lang/String;" ); TRACE("AudioManager: %p, PROPERTY_OUTPUT_SAMPLE_RATE: %p, getProperty: %p\n", audmgr_cls, audmgr_prop_out_srate, audmgr_getproperty); const char *strchars; jstring strobj; /* Now make the calls. */ //AudioManager audMgr = (AudioManager)getSystemService(Context.AUDIO_SERVICE); strobj = JCALL(env,GetStaticObjectField)(ctx_cls, ctx_audsvc); jobject audMgr = JCALL(env,CallObjectMethod)(ctx_cls, ctx_getSysSvc, strobj); strchars = JCALL(env,GetStringUTFChars)(strobj, NULL); TRACE("Context.getSystemService(%s) = %p\n", strchars, audMgr); JCALL(env,ReleaseStringUTFChars)(strobj, strchars); //String srateStr = audMgr.getProperty(AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE); strobj = JCALL(env,GetStaticObjectField)(audmgr_cls, audmgr_prop_out_srate); jstring srateStr = JCALL(env,CallObjectMethod)(audMgr, audmgr_getproperty, strobj); strchars = JCALL(env,GetStringUTFChars)(strobj, NULL); TRACE("audMgr.getProperty(%s) = %p\n", strchars, srateStr); JCALL(env,ReleaseStringUTFChars)(strobj, strchars); //int sampleRate = Integer.parseInt(srateStr); sampleRate = JCALL(env,CallStaticIntMethod)(int_cls, int_parseint, srateStr); strchars = JCALL(env,GetStringUTFChars)(srateStr, NULL); TRACE("Got system sample rate %uhz (%s)\n", sampleRate, strchars); JCALL(env,ReleaseStringUTFChars)(srateStr, strchars); if(!sampleRate) sampleRate = device->Frequency; else sampleRate = maxu(sampleRate, MIN_OUTPUT_RATE); #endif } if(sampleRate != device->Frequency) { device->NumUpdates = (device->NumUpdates*sampleRate + (device->Frequency>>1)) / device->Frequency; device->NumUpdates = maxu(device->NumUpdates, 2); device->Frequency = sampleRate; }
static ALCboolean opensl_reset_playback(ALCdevice *Device) { osl_data *data = Device->ExtraData; SLDataLocator_AndroidSimpleBufferQueue loc_bufq; SLDataLocator_OutputMix loc_outmix; SLDataFormat_PCM format_pcm; SLDataSource audioSrc; SLDataSink audioSnk; SLInterfaceID id; SLboolean req; SLresult result; Device->UpdateSize = (ALuint64)Device->UpdateSize * 44100 / Device->Frequency; Device->UpdateSize = Device->UpdateSize * Device->NumUpdates / 2; Device->NumUpdates = 2; Device->Frequency = 44100; Device->FmtChans = DevFmtStereo; Device->FmtType = DevFmtShort; SetDefaultWFXChannelOrder(Device); id = SL_IID_ANDROIDSIMPLEBUFFERQUEUE; req = SL_BOOLEAN_TRUE; loc_bufq.locatorType = SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE; loc_bufq.numBuffers = Device->NumUpdates; format_pcm.formatType = SL_DATAFORMAT_PCM; format_pcm.numChannels = ChannelsFromDevFmt(Device->FmtChans); format_pcm.samplesPerSec = Device->Frequency * 1000; format_pcm.bitsPerSample = BytesFromDevFmt(Device->FmtType) * 8; format_pcm.containerSize = format_pcm.bitsPerSample; format_pcm.channelMask = GetChannelMask(Device->FmtChans); format_pcm.endianness = IS_LITTLE_ENDIAN ? SL_BYTEORDER_LITTLEENDIAN : SL_BYTEORDER_BIGENDIAN; audioSrc.pLocator = &loc_bufq; audioSrc.pFormat = &format_pcm; loc_outmix.locatorType = SL_DATALOCATOR_OUTPUTMIX; loc_outmix.outputMix = data->outputMix; audioSnk.pLocator = &loc_outmix; audioSnk.pFormat = NULL; if(data->bufferQueueObject != NULL) VCALL0(data->bufferQueueObject,Destroy)(); data->bufferQueueObject = NULL; result = VCALL(data->engine,CreateAudioPlayer)(&data->bufferQueueObject, &audioSrc, &audioSnk, 1, &id, &req); PRINTERR(result, "engine->CreateAudioPlayer"); if(SL_RESULT_SUCCESS == result) { result = VCALL(data->bufferQueueObject,Realize)(SL_BOOLEAN_FALSE); PRINTERR(result, "bufferQueue->Realize"); } if(SL_RESULT_SUCCESS != result) { if(data->bufferQueueObject != NULL) VCALL0(data->bufferQueueObject,Destroy)(); data->bufferQueueObject = NULL; return ALC_FALSE; } return ALC_TRUE; }