IEngine.c revision 928ea4ffff40c82987cfb1ac9e3095fdc6968709
1e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter/* 2e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter * Copyright (C) 2010 The Android Open Source Project 3e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter * 4e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter * Licensed under the Apache License, Version 2.0 (the "License"); 5e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter * you may not use this file except in compliance with the License. 6e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter * You may obtain a copy of the License at 7e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter * 8e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter * http://www.apache.org/licenses/LICENSE-2.0 9e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter * 10e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter * Unless required by applicable law or agreed to in writing, software 11e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter * distributed under the License is distributed on an "AS IS" BASIS, 12e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter * See the License for the specific language governing permissions and 14e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter * limitations under the License. 15e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter */ 16e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter 174bb8118816874c696d9f1adab48490df1da365f7Eino-Ville Talvala/* Engine implementation */ 184bb8118816874c696d9f1adab48490df1da365f7Eino-Ville Talvala 19e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter#include "sles_allinclusive.h" 20e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter 21e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter 22e538206d15282afbc5b168d60b1026a5dfcd13c0James Painterstatic SLresult IEngine_CreateLEDDevice(SLEngineItf self, SLObjectItf *pDevice, SLuint32 deviceID, 23e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter SLuint32 numInterfaces, const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired) 24e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter{ 25e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter SL_ENTER_INTERFACE 26e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter 27e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter#ifdef USE_OPTIONAL 28e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter if ((NULL == pDevice) || (SL_DEFAULTDEVICEID_LED != deviceID)) { 29e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter result = SL_RESULT_PARAMETER_INVALID; 30e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter } else { 31e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter *pDevice = NULL; 32e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter unsigned exposedMask; 33e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter const ClassTable *pCLEDDevice_class = objectIDtoClass(SL_OBJECTID_LEDDEVICE); 34e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter result = checkInterfaces(pCLEDDevice_class, numInterfaces, pInterfaceIds, 35e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter pInterfaceRequired, &exposedMask); 36e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter if (SL_RESULT_SUCCESS == result) { 37e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter CLEDDevice *this = (CLEDDevice *) construct(pCLEDDevice_class, exposedMask, self); 38e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter if (NULL == this) { 39e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter result = SL_RESULT_MEMORY_FAILURE; 40e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter } else { 41e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter this->mDeviceID = deviceID; 42e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter *pDevice = &this->mObject.mItf; 43e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter } 44e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter } 45e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter } 46e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter#else 47e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter result = SL_RESULT_FEATURE_UNSUPPORTED; 48e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter#endif 49e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter 50e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter SL_LEAVE_INTERFACE 51e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter} 52e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter 53e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter 54e538206d15282afbc5b168d60b1026a5dfcd13c0James Painterstatic SLresult IEngine_CreateVibraDevice(SLEngineItf self, SLObjectItf *pDevice, SLuint32 deviceID, 55e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter SLuint32 numInterfaces, const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired) 56e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter{ 57e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter SL_ENTER_INTERFACE 58e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter 59e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter#ifdef USE_OPTIONAL 60e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter if ((NULL == pDevice) || (SL_DEFAULTDEVICEID_VIBRA != deviceID)) { 61e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter result = SL_RESULT_PARAMETER_INVALID; 62e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter } else { 63e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter *pDevice = NULL; 64e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter unsigned exposedMask; 65e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter const ClassTable *pCVibraDevice_class = objectIDtoClass(SL_OBJECTID_VIBRADEVICE); 66e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter result = checkInterfaces(pCVibraDevice_class, numInterfaces, 67e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter pInterfaceIds, pInterfaceRequired, &exposedMask); 68e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter if (SL_RESULT_SUCCESS == result) { 69e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter CVibraDevice *this = (CVibraDevice *) construct(pCVibraDevice_class, exposedMask, self); 70e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter if (NULL == this) { 71e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter result = SL_RESULT_MEMORY_FAILURE; 72e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter } else { 73e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter this->mDeviceID = deviceID; 74e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter *pDevice = &this->mObject.mItf; 75e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter } 76e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter } 77e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter } 78e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter#else 79e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter result = SL_RESULT_FEATURE_UNSUPPORTED; 80e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter#endif 81e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter 82e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter SL_LEAVE_INTERFACE 83e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter} 84e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter 85e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter 86e538206d15282afbc5b168d60b1026a5dfcd13c0James Painterstatic SLresult IEngine_CreateAudioPlayer(SLEngineItf self, SLObjectItf *pPlayer, 87e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter SLDataSource *pAudioSrc, SLDataSink *pAudioSnk, SLuint32 numInterfaces, 88e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired) 89e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter{ 90e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter SL_ENTER_INTERFACE 91e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter 92e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter if (NULL == pPlayer) { 93e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter result = SL_RESULT_PARAMETER_INVALID; 94e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter } else { 95e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter *pPlayer = NULL; 96e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter unsigned exposedMask; 97e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter const ClassTable *pCAudioPlayer_class = objectIDtoClass(SL_OBJECTID_AUDIOPLAYER); 98e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter result = checkInterfaces(pCAudioPlayer_class, numInterfaces, 99e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter pInterfaceIds, pInterfaceRequired, &exposedMask); 100e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter if (SL_RESULT_SUCCESS == result) { 101e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter 102e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter // Construct our new AudioPlayer instance 103e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter CAudioPlayer *this = (CAudioPlayer *) construct(pCAudioPlayer_class, exposedMask, self); 104e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter if (NULL == this) { 105e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter result = SL_RESULT_MEMORY_FAILURE; 106e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter } else { 107e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter 108e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter do { 109e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter 110e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter // Initialize private fields not associated with an interface 111e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter this->mOutputMix = NULL; 112e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter this->mMuteMask = 0; 113e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter this->mSoloMask = 0; 114e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter // const, will be set later by the containing AudioPlayer or MidiPlayer 115e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter this->mNumChannels = 0; 116e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter this->mSampleRateMilliHz = 0; 117e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter 118e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter // Check the source and sink parameters against generic constraints, 119e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter // and make a local copy of all parameters in case other application threads 120e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter // change memory concurrently. 121e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter 122e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter result = checkDataSource(pAudioSrc, &this->mDataSource); 123e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter if (SL_RESULT_SUCCESS != result) { 124e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter break; 125e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter } 126e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter 127e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter result = checkSourceFormatVsInterfacesCompatibility(&this->mDataSource, 128e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter numInterfaces, pInterfaceIds, pInterfaceRequired); 129e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter if (SL_RESULT_SUCCESS != result) { 130e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter break; 131e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter } 132e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter 133e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter result = checkDataSink(pAudioSnk, &this->mDataSink, SL_OBJECTID_AUDIOPLAYER); 134e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter if (SL_RESULT_SUCCESS != result) { 135e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter break; 136e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter } 137e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter 138e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter // copy the buffer queue count from source locator to the buffer queue interface 139e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter // we have already range-checked the value down to a smaller width 140e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter 141e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter this->mBufferQueue.mNumBuffers = (SL_DATALOCATOR_BUFFERQUEUE == *(SLuint32 *) 142e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter pAudioSrc->pLocator) ? (SLuint16) ((SLDataLocator_BufferQueue *) 143e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter pAudioSrc->pLocator)->numBuffers : 0; 144e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter 145e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter // link this audio player to its associated output mix via a strong reference 146e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter if (SL_DATALOCATOR_OUTPUTMIX == this->mDataSink.mLocator.mLocatorType) { 147e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter this->mOutputMix = (COutputMix *) 148e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter this->mDataSink.mLocator.mOutputMix.outputMix; 149e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter } 150e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter 151e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter // check the audio source and sink parameters against platform support 152e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter#ifdef ANDROID 153e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter result = android_audioPlayer_checkSourceSink(this); 154e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter if (SL_RESULT_SUCCESS != result) { 155e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter break; 156e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter } 157e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter#endif 158e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter 159e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter#ifdef USE_SNDFILE 160e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter result = SndFile_checkAudioPlayerSourceSink(this); 161e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter if (SL_RESULT_SUCCESS != result) { 162e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter break; 163e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter } 164e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter#endif 165e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter 166e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter#ifdef USE_OUTPUTMIXEXT 167e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter result = IOutputMixExt_checkAudioPlayerSourceSink(this); 168e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter if (SL_RESULT_SUCCESS != result) { 169e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter break; 170e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter } 171e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter#endif 172e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter 173e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter // FIXME move to dedicated function 174e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter // Allocate memory for buffer queue 175e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter 176e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter //if (0 != this->mBufferQueue.mNumBuffers) { 177e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter // inline allocation of circular mArray, up to a typical max 178e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter if (BUFFER_HEADER_TYPICAL >= this->mBufferQueue.mNumBuffers) { 179e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter this->mBufferQueue.mArray = this->mBufferQueue.mTypical; 180e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter } else { 181e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter // Avoid possible integer overflow during multiplication; this arbitrary 182e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter // maximum is big enough to not interfere with real applications, but 183e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter // small enough to not overflow. 184e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter if (this->mBufferQueue.mNumBuffers >= 256) { 185e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter result = SL_RESULT_MEMORY_FAILURE; 186e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter break; 187e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter } 188e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter this->mBufferQueue.mArray = (BufferHeader *) malloc((this->mBufferQueue. 189e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter mNumBuffers + 1) * sizeof(BufferHeader)); 190e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter if (NULL == this->mBufferQueue.mArray) { 191e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter result = SL_RESULT_MEMORY_FAILURE; 192e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter break; 193e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter } 194e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter } 195e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter this->mBufferQueue.mFront = this->mBufferQueue.mArray; 196e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter this->mBufferQueue.mRear = this->mBufferQueue.mArray; 197e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter //} 198e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter 199e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter // used to store the data source of our audio player 200e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter this->mDynamicSource.mDataSource = &this->mDataSource.u.mSource; 201e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter 202e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter // platform-specific initialization 203e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter#ifdef ANDROID 204e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter android_audioPlayer_create(this); 205e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter#endif 206e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter 207e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter // return the new audio player object 208e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter *pPlayer = &this->mObject.mItf; 209e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter 210e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter } while (0); 211e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter 212e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter if (SL_RESULT_SUCCESS != result) { 213e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter (*this->mObject.mItf->Destroy)(&this->mObject.mItf); 214e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter // equivalent to calling IObject_Destroy directly 215e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter } 216e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter 217e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter } 218e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter } 219e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter 220e538206d15282afbc5b168d60b1026a5dfcd13c0James Painter } 221 222 SL_LEAVE_INTERFACE 223} 224 225 226static SLresult IEngine_CreateAudioRecorder(SLEngineItf self, SLObjectItf *pRecorder, 227 SLDataSource *pAudioSrc, SLDataSink *pAudioSnk, SLuint32 numInterfaces, 228 const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired) 229{ 230 SL_ENTER_INTERFACE 231 232 SL_LOGV("IEngine_CreateAudioRecorder() entering"); 233 234#if defined(USE_OPTIONAL) || defined(ANDROID) 235 if (NULL == pRecorder) { 236 result = SL_RESULT_PARAMETER_INVALID; 237 } else { 238 *pRecorder = NULL; 239 unsigned exposedMask; 240 const ClassTable *pCAudioRecorder_class = objectIDtoClass(SL_OBJECTID_AUDIORECORDER); 241 result = checkInterfaces(pCAudioRecorder_class, numInterfaces, 242 pInterfaceIds, pInterfaceRequired, &exposedMask); 243 244 if (SL_RESULT_SUCCESS == result) { 245 246 // Construct our new AudioRecorder instance 247 CAudioRecorder *this = (CAudioRecorder *) construct(pCAudioRecorder_class, exposedMask, 248 self); 249 if (NULL == this) { 250 result = SL_RESULT_MEMORY_FAILURE; 251 } else { 252 253 do { 254 // const, will be set later by the containing AudioRecorder 255 this->mNumChannels = 0; 256 this->mSampleRateMilliHz = 0; 257 258 // Check the source and sink parameters, and make a local copy of all parameters 259 result = checkDataSource(pAudioSrc, &this->mDataSource); 260 if (SL_RESULT_SUCCESS != result) { 261 break; 262 } 263 result = checkDataSink(pAudioSnk, &this->mDataSink, SL_OBJECTID_AUDIORECORDER); 264 if (SL_RESULT_SUCCESS != result) { 265 break; 266 } 267 268 // check the audio source and sink parameters against platform support 269#ifdef ANDROID 270 result = android_audioRecorder_checkSourceSinkSupport(this); 271 if (SL_RESULT_SUCCESS != result) { 272 SL_LOGE("Android: Cannot create AudioRecorder: invalid source or sink"); 273 break; 274 } 275#endif 276 277#ifdef ANDROID 278 // FIXME move to dedicated function 279 SLuint32 locatorType = *(SLuint32 *) pAudioSnk->pLocator; 280 if (locatorType == SL_DATALOCATOR_BUFFERQUEUE) { 281 this->mBufferQueue.mNumBuffers = ((SLDataLocator_BufferQueue *) 282 pAudioSnk->pLocator)->numBuffers; 283 // inline allocation of circular Buffer Queue mArray, up to a typical max 284 if (BUFFER_HEADER_TYPICAL >= this->mBufferQueue.mNumBuffers) { 285 this->mBufferQueue.mArray = this->mBufferQueue.mTypical; 286 } else { 287 // Avoid possible integer overflow during multiplication; this arbitrary 288 // maximum is big enough to not interfere with real applications, but 289 // small enough to not overflow. 290 if (this->mBufferQueue.mNumBuffers >= 256) { 291 result = SL_RESULT_MEMORY_FAILURE; 292 break; 293 } 294 this->mBufferQueue.mArray = (BufferHeader *) malloc((this->mBufferQueue. 295 mNumBuffers + 1) * sizeof(BufferHeader)); 296 if (NULL == this->mBufferQueue.mArray) { 297 result = SL_RESULT_MEMORY_FAILURE; 298 break; 299 } 300 } 301 this->mBufferQueue.mFront = this->mBufferQueue.mArray; 302 this->mBufferQueue.mRear = this->mBufferQueue.mArray; 303 } 304#endif 305 306 // platform-specific initialization 307#ifdef ANDROID 308 android_audioRecorder_create(this); 309#endif 310 311 // return the new audio recorder object 312 *pRecorder = &this->mObject.mItf; 313 314 } while (0); 315 316 if (SL_RESULT_SUCCESS != result) { 317 (*this->mObject.mItf->Destroy)(&this->mObject.mItf); 318 // equivalent to calling IObject_Destroy directly 319 } 320 } 321 322 } 323 324 } 325#else 326 result = SL_RESULT_FEATURE_UNSUPPORTED; 327#endif 328 329 SL_LEAVE_INTERFACE 330} 331 332 333static SLresult IEngine_CreateMidiPlayer(SLEngineItf self, SLObjectItf *pPlayer, 334 SLDataSource *pMIDISrc, SLDataSource *pBankSrc, SLDataSink *pAudioOutput, 335 SLDataSink *pVibra, SLDataSink *pLEDArray, SLuint32 numInterfaces, 336 const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired) 337{ 338 SL_ENTER_INTERFACE 339 340#if defined(USE_GAME) || defined(USE_PHONE) 341 if ((NULL == pPlayer) || (NULL == pMIDISrc) || (NULL == pAudioOutput)) { 342 result = SL_RESULT_PARAMETER_INVALID; 343 } else { 344 *pPlayer = NULL; 345 unsigned exposedMask; 346 const ClassTable *pCMidiPlayer_class = objectIDtoClass(SL_OBJECTID_MIDIPLAYER); 347 result = checkInterfaces(pCMidiPlayer_class, numInterfaces, 348 pInterfaceIds, pInterfaceRequired, &exposedMask); 349 if (SL_RESULT_SUCCESS == result) { 350 CMidiPlayer *this = (CMidiPlayer *) construct(pCMidiPlayer_class, exposedMask, self); 351 if (NULL == this) { 352 result = SL_RESULT_MEMORY_FAILURE; 353 } else { 354 // return the new MIDI player object 355 *pPlayer = &this->mObject.mItf; 356 // FIXME a fake value - why not use value from IPlay_init? what does CT check for? 357 this->mPlay.mDuration = 0; 358 } 359 } 360 } 361#else 362 result = SL_RESULT_FEATURE_UNSUPPORTED; 363#endif 364 365 SL_LEAVE_INTERFACE 366} 367 368 369static SLresult IEngine_CreateListener(SLEngineItf self, SLObjectItf *pListener, 370 SLuint32 numInterfaces, const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired) 371{ 372 SL_ENTER_INTERFACE 373 374#ifdef USE_GAME 375 if (NULL == pListener) { 376 result = SL_RESULT_PARAMETER_INVALID; 377 } else { 378 *pListener = NULL; 379 unsigned exposedMask; 380 const ClassTable *pCListener_class = objectIDtoClass(SL_OBJECTID_LISTENER); 381 result = checkInterfaces(pCListener_class, numInterfaces, 382 pInterfaceIds, pInterfaceRequired, &exposedMask); 383 if (SL_RESULT_SUCCESS == result) { 384 CListener *this = (CListener *) construct(pCListener_class, exposedMask, self); 385 if (NULL == this) { 386 result = SL_RESULT_MEMORY_FAILURE; 387 } else { 388 // return the new listener object 389 *pListener = &this->mObject.mItf; 390 } 391 } 392 } 393#else 394 result = SL_RESULT_FEATURE_UNSUPPORTED; 395#endif 396 397 SL_LEAVE_INTERFACE 398} 399 400 401static SLresult IEngine_Create3DGroup(SLEngineItf self, SLObjectItf *pGroup, SLuint32 numInterfaces, 402 const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired) 403{ 404 SL_ENTER_INTERFACE 405 406#ifdef USE_GAME 407 if (NULL == pGroup) { 408 result = SL_RESULT_PARAMETER_INVALID; 409 } else { 410 *pGroup = NULL; 411 unsigned exposedMask; 412 const ClassTable *pC3DGroup_class = objectIDtoClass(SL_OBJECTID_3DGROUP); 413 result = checkInterfaces(pC3DGroup_class, numInterfaces, 414 pInterfaceIds, pInterfaceRequired, &exposedMask); 415 if (SL_RESULT_SUCCESS == result) { 416 C3DGroup *this = (C3DGroup *) construct(pC3DGroup_class, exposedMask, self); 417 if (NULL == this) { 418 result = SL_RESULT_MEMORY_FAILURE; 419 } else { 420 this->mMemberMask = 0; 421 // return the new 3DGroup object 422 *pGroup = &this->mObject.mItf; 423 } 424 } 425 } 426#else 427 result = SL_RESULT_FEATURE_UNSUPPORTED; 428#endif 429 430 SL_LEAVE_INTERFACE 431} 432 433 434static SLresult IEngine_CreateOutputMix(SLEngineItf self, SLObjectItf *pMix, SLuint32 numInterfaces, 435 const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired) 436{ 437 SL_ENTER_INTERFACE 438 439 if (NULL == pMix) { 440 result = SL_RESULT_PARAMETER_INVALID; 441 } else { 442 *pMix = NULL; 443 unsigned exposedMask; 444 const ClassTable *pCOutputMix_class = objectIDtoClass(SL_OBJECTID_OUTPUTMIX); 445 result = checkInterfaces(pCOutputMix_class, numInterfaces, 446 pInterfaceIds, pInterfaceRequired, &exposedMask); 447 if (SL_RESULT_SUCCESS == result) { 448 COutputMix *this = (COutputMix *) construct(pCOutputMix_class, exposedMask, self); 449 if (NULL == this) { 450 result = SL_RESULT_MEMORY_FAILURE; 451 } else { 452 *pMix = &this->mObject.mItf; 453 } 454 } 455 } 456 457 SL_LEAVE_INTERFACE 458} 459 460 461static SLresult IEngine_CreateMetadataExtractor(SLEngineItf self, SLObjectItf *pMetadataExtractor, 462 SLDataSource *pDataSource, SLuint32 numInterfaces, const SLInterfaceID *pInterfaceIds, 463 const SLboolean *pInterfaceRequired) 464{ 465 SL_ENTER_INTERFACE 466 467#if defined(USE_GAME) || defined(USE_MUSIC) 468 if (NULL == pMetadataExtractor) { 469 result = SL_RESULT_PARAMETER_INVALID; 470 } else { 471 *pMetadataExtractor = NULL; 472 unsigned exposedMask; 473 const ClassTable *pCMetadataExtractor_class = 474 objectIDtoClass(SL_OBJECTID_METADATAEXTRACTOR); 475 result = checkInterfaces(pCMetadataExtractor_class, numInterfaces, 476 pInterfaceIds, pInterfaceRequired, &exposedMask); 477 if (SL_RESULT_SUCCESS == result) { 478 CMetadataExtractor *this = (CMetadataExtractor *) 479 construct(pCMetadataExtractor_class, exposedMask, self); 480 if (NULL == this) { 481 result = SL_RESULT_MEMORY_FAILURE; 482 } else { 483 *pMetadataExtractor = &this->mObject.mItf; 484 result = SL_RESULT_SUCCESS; 485 } 486 } 487 } 488#else 489 result = SL_RESULT_FEATURE_UNSUPPORTED; 490#endif 491 492 SL_LEAVE_INTERFACE 493} 494 495 496static SLresult IEngine_CreateExtensionObject(SLEngineItf self, SLObjectItf *pObject, 497 void *pParameters, SLuint32 objectID, SLuint32 numInterfaces, 498 const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired) 499{ 500 SL_ENTER_INTERFACE 501 502 if (NULL == pObject) { 503 result = SL_RESULT_PARAMETER_INVALID; 504 } else { 505 *pObject = NULL; 506 result = SL_RESULT_FEATURE_UNSUPPORTED; 507 } 508 509 SL_LEAVE_INTERFACE 510} 511 512 513static SLresult IEngine_QueryNumSupportedInterfaces(SLEngineItf self, 514 SLuint32 objectID, SLuint32 *pNumSupportedInterfaces) 515{ 516 SL_ENTER_INTERFACE 517 518 if (NULL == pNumSupportedInterfaces) { 519 result = SL_RESULT_PARAMETER_INVALID; 520 } else { 521 const ClassTable *class__ = objectIDtoClass(objectID); 522 if (NULL == class__) { 523 result = SL_RESULT_FEATURE_UNSUPPORTED; 524 } else { 525 SLuint32 count = 0; 526 SLuint32 i; 527 for (i = 0; i < class__->mInterfaceCount; ++i) { 528 switch (class__->mInterfaces[i].mInterface) { 529 case INTERFACE_IMPLICIT: 530 case INTERFACE_EXPLICIT: 531 case INTERFACE_DYNAMIC: 532 ++count; 533 break; 534 case INTERFACE_UNAVAILABLE: 535 break; 536 default: 537 assert(false); 538 break; 539 } 540 } 541 *pNumSupportedInterfaces = count; 542 result = SL_RESULT_SUCCESS; 543 } 544 } 545 546 SL_LEAVE_INTERFACE; 547} 548 549 550static SLresult IEngine_QuerySupportedInterfaces(SLEngineItf self, 551 SLuint32 objectID, SLuint32 index, SLInterfaceID *pInterfaceId) 552{ 553 SL_ENTER_INTERFACE 554 555 if (NULL == pInterfaceId) { 556 result = SL_RESULT_PARAMETER_INVALID; 557 } else { 558 *pInterfaceId = NULL; 559 const ClassTable *class__ = objectIDtoClass(objectID); 560 if (NULL == class__) { 561 result = SL_RESULT_FEATURE_UNSUPPORTED; 562 } else { 563 result = SL_RESULT_PARAMETER_INVALID; // will be reset later 564 SLuint32 i; 565 for (i = 0; i < class__->mInterfaceCount; ++i) { 566 switch (class__->mInterfaces[i].mInterface) { 567 case INTERFACE_IMPLICIT: 568 case INTERFACE_EXPLICIT: 569 case INTERFACE_DYNAMIC: 570 break; 571 case INTERFACE_UNAVAILABLE: 572 continue; 573 default: 574 assert(false); 575 break; 576 } 577 if (index == 0) { 578 *pInterfaceId = &SL_IID_array[class__->mInterfaces[i].mMPH]; 579 result = SL_RESULT_SUCCESS; 580 break; 581 } 582 --index; 583 } 584 } 585 } 586 587 SL_LEAVE_INTERFACE 588}; 589 590 591static SLresult IEngine_QueryNumSupportedExtensions(SLEngineItf self, SLuint32 *pNumExtensions) 592{ 593 SL_ENTER_INTERFACE 594 595 if (NULL == pNumExtensions) { 596 result = SL_RESULT_PARAMETER_INVALID; 597 } else { 598 *pNumExtensions = 0; 599 result = SL_RESULT_SUCCESS; 600 } 601 602 SL_LEAVE_INTERFACE 603} 604 605 606static SLresult IEngine_QuerySupportedExtension(SLEngineItf self, 607 SLuint32 index, SLchar *pExtensionName, SLint16 *pNameLength) 608{ 609 SL_ENTER_INTERFACE 610 611 // any index >= 0 will be >= number of supported extensions 612 result = SL_RESULT_PARAMETER_INVALID; 613 614 SL_LEAVE_INTERFACE 615} 616 617 618static SLresult IEngine_IsExtensionSupported(SLEngineItf self, 619 const SLchar *pExtensionName, SLboolean *pSupported) 620{ 621 SL_ENTER_INTERFACE 622 623 if (NULL == pExtensionName || NULL == pSupported) { 624 result = SL_RESULT_PARAMETER_INVALID; 625 } else { 626 // no extensions are supported 627 *pSupported = SL_BOOLEAN_FALSE; 628 result = SL_RESULT_SUCCESS; 629 } 630 631 SL_LEAVE_INTERFACE 632} 633 634 635static const struct SLEngineItf_ IEngine_Itf = { 636 IEngine_CreateLEDDevice, 637 IEngine_CreateVibraDevice, 638 IEngine_CreateAudioPlayer, 639 IEngine_CreateAudioRecorder, 640 IEngine_CreateMidiPlayer, 641 IEngine_CreateListener, 642 IEngine_Create3DGroup, 643 IEngine_CreateOutputMix, 644 IEngine_CreateMetadataExtractor, 645 IEngine_CreateExtensionObject, 646 IEngine_QueryNumSupportedInterfaces, 647 IEngine_QuerySupportedInterfaces, 648 IEngine_QueryNumSupportedExtensions, 649 IEngine_QuerySupportedExtension, 650 IEngine_IsExtensionSupported 651}; 652 653void IEngine_init(void *self) 654{ 655 IEngine *this = (IEngine *) self; 656 this->mItf = &IEngine_Itf; 657 // mLossOfControlGlobal is initialized in CreateEngine 658#ifdef USE_SDL 659 this->mOutputMix = NULL; 660#endif 661 this->mInstanceCount = 1; // ourself 662 this->mInstanceMask = 0; 663 this->mChangedMask = 0; 664 unsigned i; 665 for (i = 0; i < MAX_INSTANCE; ++i) { 666 this->mInstances[i] = NULL; 667 } 668 this->mShutdown = SL_BOOLEAN_FALSE; 669 this->mShutdownAck = SL_BOOLEAN_FALSE; 670#if defined(ANDROID) && !defined(USE_BACKPORT) 671 this->mEqNumPresets = 0; 672 this->mEqPresetNames = NULL; 673#endif 674} 675