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