Home | History | Annotate | Download | only in libopensles
      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 
     22 static 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 USE_PROFILES & USE_PROFILES_OPTIONAL
     28     if ((NULL == pDevice) || (SL_DEFAULTDEVICEID_LED != deviceID)) {
     29         result = SL_RESULT_PARAMETER_INVALID;
     30     } else {
     31         *pDevice = NULL;
     32         unsigned exposedMask;
     33         const ClassTable *pCLEDDevice_class = objectIDtoClass(SL_OBJECTID_LEDDEVICE);
     34         if (NULL == pCLEDDevice_class) {
     35             result = SL_RESULT_FEATURE_UNSUPPORTED;
     36         } else {
     37             result = checkInterfaces(pCLEDDevice_class, numInterfaces, pInterfaceIds,
     38                 pInterfaceRequired, &exposedMask);
     39         }
     40         if (SL_RESULT_SUCCESS == result) {
     41             CLEDDevice *this = (CLEDDevice *) construct(pCLEDDevice_class, exposedMask, self);
     42             if (NULL == this) {
     43                 result = SL_RESULT_MEMORY_FAILURE;
     44             } else {
     45                 this->mDeviceID = deviceID;
     46                 IObject_Publish(&this->mObject);
     47                 // return the new LED object
     48                 *pDevice = &this->mObject.mItf;
     49             }
     50         }
     51     }
     52 #else
     53     result = SL_RESULT_FEATURE_UNSUPPORTED;
     54 #endif
     55 
     56     SL_LEAVE_INTERFACE
     57 }
     58 
     59 
     60 static SLresult IEngine_CreateVibraDevice(SLEngineItf self, SLObjectItf *pDevice, SLuint32 deviceID,
     61     SLuint32 numInterfaces, const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired)
     62 {
     63     SL_ENTER_INTERFACE
     64 
     65 #if USE_PROFILES & USE_PROFILES_OPTIONAL
     66     if ((NULL == pDevice) || (SL_DEFAULTDEVICEID_VIBRA != deviceID)) {
     67         result = SL_RESULT_PARAMETER_INVALID;
     68     } else {
     69         *pDevice = NULL;
     70         unsigned exposedMask;
     71         const ClassTable *pCVibraDevice_class = objectIDtoClass(SL_OBJECTID_VIBRADEVICE);
     72         if (NULL == pCVibraDevice_class) {
     73             result = SL_RESULT_FEATURE_UNSUPPORTED;
     74         } else {
     75             result = checkInterfaces(pCVibraDevice_class, numInterfaces,
     76                 pInterfaceIds, pInterfaceRequired, &exposedMask);
     77         }
     78         if (SL_RESULT_SUCCESS == result) {
     79             CVibraDevice *this = (CVibraDevice *) construct(pCVibraDevice_class, exposedMask, self);
     80             if (NULL == this) {
     81                 result = SL_RESULT_MEMORY_FAILURE;
     82             } else {
     83                 this->mDeviceID = deviceID;
     84                 IObject_Publish(&this->mObject);
     85                 // return the new vibra object
     86                 *pDevice = &this->mObject.mItf;
     87             }
     88         }
     89     }
     90 #else
     91     result = SL_RESULT_FEATURE_UNSUPPORTED;
     92 #endif
     93 
     94     SL_LEAVE_INTERFACE
     95 }
     96 
     97 
     98 static SLresult IEngine_CreateAudioPlayer(SLEngineItf self, SLObjectItf *pPlayer,
     99     SLDataSource *pAudioSrc, SLDataSink *pAudioSnk, SLuint32 numInterfaces,
    100     const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired)
    101 {
    102     SL_ENTER_INTERFACE
    103 
    104     if (NULL == pPlayer) {
    105        result = SL_RESULT_PARAMETER_INVALID;
    106     } else {
    107         *pPlayer = NULL;
    108         unsigned exposedMask;
    109         const ClassTable *pCAudioPlayer_class = objectIDtoClass(SL_OBJECTID_AUDIOPLAYER);
    110         assert(NULL != pCAudioPlayer_class);
    111         result = checkInterfaces(pCAudioPlayer_class, numInterfaces,
    112             pInterfaceIds, pInterfaceRequired, &exposedMask);
    113         if (SL_RESULT_SUCCESS == result) {
    114 
    115             // Construct our new AudioPlayer instance
    116             CAudioPlayer *this = (CAudioPlayer *) construct(pCAudioPlayer_class, exposedMask, self);
    117             if (NULL == this) {
    118                 result = SL_RESULT_MEMORY_FAILURE;
    119             } else {
    120 
    121                 do {
    122 
    123                     // Initialize private fields not associated with an interface
    124 
    125                     // Default data source in case of failure in checkDataSource
    126                     this->mDataSource.mLocator.mLocatorType = SL_DATALOCATOR_NULL;
    127                     this->mDataSource.mFormat.mFormatType = SL_DATAFORMAT_NULL;
    128 
    129                     // Default data sink in case of failure in checkDataSink
    130                     this->mDataSink.mLocator.mLocatorType = SL_DATALOCATOR_NULL;
    131                     this->mDataSink.mFormat.mFormatType = SL_DATAFORMAT_NULL;
    132 
    133                     // Default is no per-channel mute or solo
    134                     this->mMuteMask = 0;
    135                     this->mSoloMask = 0;
    136 
    137                     // Will be set soon for PCM buffer queues, or later by platform-specific code
    138                     // during Realize or Prefetch
    139                     this->mNumChannels = 0;
    140                     this->mSampleRateMilliHz = 0;
    141 
    142                     // More default values, in case destructor needs to be called early
    143                     this->mDirectLevel = 0;
    144 #ifdef USE_OUTPUTMIXEXT
    145                     this->mTrack = NULL;
    146                     this->mGains[0] = 1.0f;
    147                     this->mGains[1] = 1.0f;
    148                     this->mDestroyRequested = SL_BOOLEAN_FALSE;
    149 #endif
    150 #ifdef USE_SNDFILE
    151                     this->mSndFile.mPathname = NULL;
    152                     this->mSndFile.mSNDFILE = NULL;
    153                     memset(&this->mSndFile.mSfInfo, 0, sizeof(SF_INFO));
    154                     memset(&this->mSndFile.mMutex, 0, sizeof(pthread_mutex_t));
    155                     this->mSndFile.mEOF = SL_BOOLEAN_FALSE;
    156                     this->mSndFile.mWhich = 0;
    157                     memset(this->mSndFile.mBuffer, 0, sizeof(this->mSndFile.mBuffer));
    158 #endif
    159 #ifdef ANDROID
    160                     // extra safe initializations of pointers, in case of incomplete construction
    161                     this->mpLock = NULL;
    162                     this->mAudioTrack = NULL;
    163                     // placement new (explicit constructor)
    164                     (void) new (&this->mSfPlayer) android::sp<android::SfPlayer>();
    165                     (void) new (&this->mAuxEffect) android::sp<android::AudioEffect>();
    166 #endif
    167 
    168                     // Check the source and sink parameters against generic constraints,
    169                     // and make a local copy of all parameters in case other application threads
    170                     // change memory concurrently.
    171 
    172                     result = checkDataSource(pAudioSrc, &this->mDataSource);
    173                     if (SL_RESULT_SUCCESS != result) {
    174                         break;
    175                     }
    176 
    177                     result = checkDataSink(pAudioSnk, &this->mDataSink, SL_OBJECTID_AUDIOPLAYER);
    178                     if (SL_RESULT_SUCCESS != result) {
    179                         break;
    180                     }
    181 
    182                     // It would be unsafe to ever refer to the application pointers again
    183                     pAudioSrc = NULL;
    184                     pAudioSnk = NULL;
    185 
    186                     // Check that the requested interfaces are compatible with the data source
    187                     result = checkSourceFormatVsInterfacesCompatibility(&this->mDataSource,
    188                             pCAudioPlayer_class, exposedMask);
    189                     if (SL_RESULT_SUCCESS != result) {
    190                         break;
    191                     }
    192 
    193                     // copy the buffer queue count from source locator to the buffer queue interface
    194                     // we have already range-checked the value down to a smaller width
    195 
    196                     switch (this->mDataSource.mLocator.mLocatorType) {
    197                     case SL_DATALOCATOR_BUFFERQUEUE:
    198 #ifdef ANDROID
    199                     case SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE:
    200 #endif
    201                         this->mBufferQueue.mNumBuffers =
    202                                 (SLuint16) this->mDataSource.mLocator.mBufferQueue.numBuffers;
    203                         assert(SL_DATAFORMAT_PCM == this->mDataSource.mFormat.mFormatType);
    204                         this->mNumChannels = this->mDataSource.mFormat.mPCM.numChannels;
    205                         this->mSampleRateMilliHz = this->mDataSource.mFormat.mPCM.samplesPerSec;
    206                         break;
    207                     default:
    208                         this->mBufferQueue.mNumBuffers = 0;
    209                         break;
    210                     }
    211 
    212                     // check the audio source and sink parameters against platform support
    213 #ifdef ANDROID
    214                     result = android_audioPlayer_checkSourceSink(this);
    215                     if (SL_RESULT_SUCCESS != result) {
    216                         break;
    217                     }
    218 #endif
    219 
    220 #ifdef USE_SNDFILE
    221                     result = SndFile_checkAudioPlayerSourceSink(this);
    222                     if (SL_RESULT_SUCCESS != result) {
    223                         break;
    224                     }
    225 #endif
    226 
    227 #ifdef USE_OUTPUTMIXEXT
    228                     result = IOutputMixExt_checkAudioPlayerSourceSink(this);
    229                     if (SL_RESULT_SUCCESS != result) {
    230                         break;
    231                     }
    232 #endif
    233 
    234                     // FIXME move to dedicated function
    235                     // Allocate memory for buffer queue
    236 
    237                     //if (0 != this->mBufferQueue.mNumBuffers) {
    238                         // inline allocation of circular mArray, up to a typical max
    239                         if (BUFFER_HEADER_TYPICAL >= this->mBufferQueue.mNumBuffers) {
    240                             this->mBufferQueue.mArray = this->mBufferQueue.mTypical;
    241                         } else {
    242                             // Avoid possible integer overflow during multiplication; this arbitrary
    243                             // maximum is big enough to not interfere with real applications, but
    244                             // small enough to not overflow.
    245                             if (this->mBufferQueue.mNumBuffers >= 256) {
    246                                 result = SL_RESULT_MEMORY_FAILURE;
    247                                 break;
    248                             }
    249                             this->mBufferQueue.mArray = (BufferHeader *) malloc((this->mBufferQueue.
    250                                 mNumBuffers + 1) * sizeof(BufferHeader));
    251                             if (NULL == this->mBufferQueue.mArray) {
    252                                 result = SL_RESULT_MEMORY_FAILURE;
    253                                 break;
    254                             }
    255                         }
    256                         this->mBufferQueue.mFront = this->mBufferQueue.mArray;
    257                         this->mBufferQueue.mRear = this->mBufferQueue.mArray;
    258                         //}
    259 
    260                         // used to store the data source of our audio player
    261                         this->mDynamicSource.mDataSource = &this->mDataSource.u.mSource;
    262 
    263                         // platform-specific initialization
    264 #ifdef ANDROID
    265                         android_audioPlayer_create(this);
    266 #endif
    267 
    268                 } while (0);
    269 
    270                 if (SL_RESULT_SUCCESS != result) {
    271                     IObject_Destroy(&this->mObject.mItf);
    272                 } else {
    273                     IObject_Publish(&this->mObject);
    274                     // return the new audio player object
    275                     *pPlayer = &this->mObject.mItf;
    276                 }
    277 
    278             }
    279         }
    280 
    281     }
    282 
    283     SL_LEAVE_INTERFACE
    284 }
    285 
    286 
    287 static SLresult IEngine_CreateAudioRecorder(SLEngineItf self, SLObjectItf *pRecorder,
    288     SLDataSource *pAudioSrc, SLDataSink *pAudioSnk, SLuint32 numInterfaces,
    289     const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired)
    290 {
    291     SL_ENTER_INTERFACE
    292 
    293 #if (USE_PROFILES & USE_PROFILES_OPTIONAL) || defined(ANDROID)
    294     if (NULL == pRecorder) {
    295         result = SL_RESULT_PARAMETER_INVALID;
    296     } else {
    297         *pRecorder = NULL;
    298         unsigned exposedMask;
    299         const ClassTable *pCAudioRecorder_class = objectIDtoClass(SL_OBJECTID_AUDIORECORDER);
    300         if (NULL == pCAudioRecorder_class) {
    301             result = SL_RESULT_FEATURE_UNSUPPORTED;
    302         } else {
    303             result = checkInterfaces(pCAudioRecorder_class, numInterfaces,
    304                     pInterfaceIds, pInterfaceRequired, &exposedMask);
    305         }
    306 
    307         if (SL_RESULT_SUCCESS == result) {
    308 
    309             // Construct our new AudioRecorder instance
    310             CAudioRecorder *this = (CAudioRecorder *) construct(pCAudioRecorder_class, exposedMask,
    311                     self);
    312             if (NULL == this) {
    313                 result = SL_RESULT_MEMORY_FAILURE;
    314             } else {
    315 
    316                 do {
    317 
    318                     // Initialize fields not associated with any interface
    319 
    320                     // Default data source in case of failure in checkDataSource
    321                     this->mDataSource.mLocator.mLocatorType = SL_DATALOCATOR_NULL;
    322                     this->mDataSource.mFormat.mFormatType = SL_DATAFORMAT_NULL;
    323 
    324                     // Default data sink in case of failure in checkDataSink
    325                     this->mDataSink.mLocator.mLocatorType = SL_DATALOCATOR_NULL;
    326                     this->mDataSink.mFormat.mFormatType = SL_DATAFORMAT_NULL;
    327 
    328                     // These fields are set to real values by
    329                     // android_audioRecorder_checkSourceSinkSupport.  Note that the data sink is
    330                     // always PCM buffer queue, so we know the channel count and sample rate early.
    331                     this->mNumChannels = 0;
    332                     this->mSampleRateMilliHz = 0;
    333 #ifdef ANDROID
    334                     this->mAudioRecord = NULL;
    335                     this->mRecordSource = android::AUDIO_SOURCE_DEFAULT;
    336 #endif
    337 
    338                     // Check the source and sink parameters, and make a local copy of all parameters
    339                     result = checkDataSource(pAudioSrc, &this->mDataSource);
    340                     if (SL_RESULT_SUCCESS != result) {
    341                         break;
    342                     }
    343                     result = checkDataSink(pAudioSnk, &this->mDataSink, SL_OBJECTID_AUDIORECORDER);
    344                     if (SL_RESULT_SUCCESS != result) {
    345                         break;
    346                     }
    347 
    348                     // It would be unsafe to ever refer to the application pointers again
    349                     pAudioSrc = NULL;
    350                     pAudioSnk = NULL;
    351 
    352                     // check the audio source and sink parameters against platform support
    353 #ifdef ANDROID
    354                     result = android_audioRecorder_checkSourceSinkSupport(this);
    355                     if (SL_RESULT_SUCCESS != result) {
    356                         SL_LOGE("Cannot create AudioRecorder: invalid source or sink");
    357                         break;
    358                     }
    359 #endif
    360 
    361 #ifdef ANDROID
    362                     // Allocate memory for buffer queue
    363                     SLuint32 locatorType = this->mDataSink.mLocator.mLocatorType;
    364                     if (locatorType == SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE) {
    365                         this->mBufferQueue.mNumBuffers =
    366                             this->mDataSink.mLocator.mBufferQueue.numBuffers;
    367                         // inline allocation of circular Buffer Queue mArray, up to a typical max
    368                         if (BUFFER_HEADER_TYPICAL >= this->mBufferQueue.mNumBuffers) {
    369                             this->mBufferQueue.mArray = this->mBufferQueue.mTypical;
    370                         } else {
    371                             // Avoid possible integer overflow during multiplication; this arbitrary
    372                             // maximum is big enough to not interfere with real applications, but
    373                             // small enough to not overflow.
    374                             if (this->mBufferQueue.mNumBuffers >= 256) {
    375                                 result = SL_RESULT_MEMORY_FAILURE;
    376                                 break;
    377                             }
    378                             this->mBufferQueue.mArray = (BufferHeader *) malloc((this->mBufferQueue.
    379                                     mNumBuffers + 1) * sizeof(BufferHeader));
    380                             if (NULL == this->mBufferQueue.mArray) {
    381                                 result = SL_RESULT_MEMORY_FAILURE;
    382                                 break;
    383                             }
    384                         }
    385                         this->mBufferQueue.mFront = this->mBufferQueue.mArray;
    386                         this->mBufferQueue.mRear = this->mBufferQueue.mArray;
    387                     }
    388 #endif
    389 
    390                     // platform-specific initialization
    391 #ifdef ANDROID
    392                     android_audioRecorder_create(this);
    393 #endif
    394 
    395                 } while (0);
    396 
    397                 if (SL_RESULT_SUCCESS != result) {
    398                     IObject_Destroy(&this->mObject.mItf);
    399                 } else {
    400                     IObject_Publish(&this->mObject);
    401                     // return the new audio recorder object
    402                     *pRecorder = &this->mObject.mItf;
    403                 }
    404             }
    405 
    406         }
    407 
    408     }
    409 #else
    410     result = SL_RESULT_FEATURE_UNSUPPORTED;
    411 #endif
    412 
    413     SL_LEAVE_INTERFACE
    414 }
    415 
    416 
    417 static SLresult IEngine_CreateMidiPlayer(SLEngineItf self, SLObjectItf *pPlayer,
    418     SLDataSource *pMIDISrc, SLDataSource *pBankSrc, SLDataSink *pAudioOutput,
    419     SLDataSink *pVibra, SLDataSink *pLEDArray, SLuint32 numInterfaces,
    420     const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired)
    421 {
    422     SL_ENTER_INTERFACE
    423 
    424 #if USE_PROFILES & (USE_PROFILES_GAME | USE_PROFILES_PHONE)
    425     if ((NULL == pPlayer) || (NULL == pMIDISrc) || (NULL == pAudioOutput)) {
    426         result = SL_RESULT_PARAMETER_INVALID;
    427     } else {
    428         *pPlayer = NULL;
    429         unsigned exposedMask;
    430         const ClassTable *pCMidiPlayer_class = objectIDtoClass(SL_OBJECTID_MIDIPLAYER);
    431         if (NULL == pCMidiPlayer_class) {
    432             result = SL_RESULT_FEATURE_UNSUPPORTED;
    433         } else {
    434             result = checkInterfaces(pCMidiPlayer_class, numInterfaces,
    435                 pInterfaceIds, pInterfaceRequired, &exposedMask);
    436         }
    437         if (SL_RESULT_SUCCESS == result) {
    438             CMidiPlayer *this = (CMidiPlayer *) construct(pCMidiPlayer_class, exposedMask, self);
    439             if (NULL == this) {
    440                 result = SL_RESULT_MEMORY_FAILURE;
    441             } else {
    442                 // FIXME a fake value - why not use value from IPlay_init? what does CT check for?
    443                 this->mPlay.mDuration = 0;
    444                 IObject_Publish(&this->mObject);
    445                 // return the new MIDI player object
    446                 *pPlayer = &this->mObject.mItf;
    447             }
    448         }
    449     }
    450 #else
    451     result = SL_RESULT_FEATURE_UNSUPPORTED;
    452 #endif
    453 
    454     SL_LEAVE_INTERFACE
    455 }
    456 
    457 
    458 static SLresult IEngine_CreateListener(SLEngineItf self, SLObjectItf *pListener,
    459     SLuint32 numInterfaces, const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired)
    460 {
    461     SL_ENTER_INTERFACE
    462 
    463 #if USE_PROFILES & USE_PROFILES_GAME
    464     if (NULL == pListener) {
    465         result = SL_RESULT_PARAMETER_INVALID;
    466     } else {
    467         *pListener = NULL;
    468         unsigned exposedMask;
    469         const ClassTable *pCListener_class = objectIDtoClass(SL_OBJECTID_LISTENER);
    470         if (NULL == pCListener_class) {
    471             result = SL_RESULT_FEATURE_UNSUPPORTED;
    472         } else {
    473             result = checkInterfaces(pCListener_class, numInterfaces,
    474                 pInterfaceIds, pInterfaceRequired, &exposedMask);
    475         }
    476         if (SL_RESULT_SUCCESS == result) {
    477             CListener *this = (CListener *) construct(pCListener_class, exposedMask, self);
    478             if (NULL == this) {
    479                 result = SL_RESULT_MEMORY_FAILURE;
    480             } else {
    481                 IObject_Publish(&this->mObject);
    482                 // return the new 3D listener object
    483                 *pListener = &this->mObject.mItf;
    484             }
    485         }
    486     }
    487 #else
    488     result = SL_RESULT_FEATURE_UNSUPPORTED;
    489 #endif
    490 
    491     SL_LEAVE_INTERFACE
    492 }
    493 
    494 
    495 static SLresult IEngine_Create3DGroup(SLEngineItf self, SLObjectItf *pGroup, SLuint32 numInterfaces,
    496     const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired)
    497 {
    498     SL_ENTER_INTERFACE
    499 
    500 #if USE_PROFILES & USE_PROFILES_GAME
    501     if (NULL == pGroup) {
    502         result = SL_RESULT_PARAMETER_INVALID;
    503     } else {
    504         *pGroup = NULL;
    505         unsigned exposedMask;
    506         const ClassTable *pC3DGroup_class = objectIDtoClass(SL_OBJECTID_3DGROUP);
    507         if (NULL == pC3DGroup_class) {
    508             result = SL_RESULT_FEATURE_UNSUPPORTED;
    509         } else {
    510             result = checkInterfaces(pC3DGroup_class, numInterfaces,
    511                 pInterfaceIds, pInterfaceRequired, &exposedMask);
    512         }
    513         if (SL_RESULT_SUCCESS == result) {
    514             C3DGroup *this = (C3DGroup *) construct(pC3DGroup_class, exposedMask, self);
    515             if (NULL == this) {
    516                 result = SL_RESULT_MEMORY_FAILURE;
    517             } else {
    518                 this->mMemberMask = 0;
    519                 IObject_Publish(&this->mObject);
    520                 // return the new 3D group object
    521                 *pGroup = &this->mObject.mItf;
    522             }
    523         }
    524     }
    525 #else
    526     result = SL_RESULT_FEATURE_UNSUPPORTED;
    527 #endif
    528 
    529     SL_LEAVE_INTERFACE
    530 }
    531 
    532 
    533 static SLresult IEngine_CreateOutputMix(SLEngineItf self, SLObjectItf *pMix, SLuint32 numInterfaces,
    534     const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired)
    535 {
    536     SL_ENTER_INTERFACE
    537 
    538     if (NULL == pMix) {
    539         result = SL_RESULT_PARAMETER_INVALID;
    540     } else {
    541         *pMix = NULL;
    542         unsigned exposedMask;
    543         const ClassTable *pCOutputMix_class = objectIDtoClass(SL_OBJECTID_OUTPUTMIX);
    544         assert(NULL != pCOutputMix_class);
    545         result = checkInterfaces(pCOutputMix_class, numInterfaces,
    546             pInterfaceIds, pInterfaceRequired, &exposedMask);
    547         if (SL_RESULT_SUCCESS == result) {
    548             COutputMix *this = (COutputMix *) construct(pCOutputMix_class, exposedMask, self);
    549             if (NULL == this) {
    550                 result = SL_RESULT_MEMORY_FAILURE;
    551             } else {
    552 #ifdef ANDROID
    553                 android_outputMix_create(this);
    554 #endif
    555 #ifdef USE_SDL
    556                 IEngine *thisEngine = this->mObject.mEngine;
    557                 interface_lock_exclusive(thisEngine);
    558                 bool unpause = false;
    559                 if (NULL == thisEngine->mOutputMix) {
    560                     thisEngine->mOutputMix = this;
    561                     unpause = true;
    562                 }
    563                 interface_unlock_exclusive(thisEngine);
    564 #endif
    565                 IObject_Publish(&this->mObject);
    566 #ifdef USE_SDL
    567                 if (unpause) {
    568                     // Enable SDL_callback to be called periodically by SDL's internal thread
    569                     SDL_PauseAudio(0);
    570                 }
    571 #endif
    572                 // return the new output mix object
    573                 *pMix = &this->mObject.mItf;
    574             }
    575         }
    576     }
    577 
    578     SL_LEAVE_INTERFACE
    579 }
    580 
    581 
    582 static SLresult IEngine_CreateMetadataExtractor(SLEngineItf self, SLObjectItf *pMetadataExtractor,
    583     SLDataSource *pDataSource, SLuint32 numInterfaces, const SLInterfaceID *pInterfaceIds,
    584     const SLboolean *pInterfaceRequired)
    585 {
    586     SL_ENTER_INTERFACE
    587 
    588 #if USE_PROFILES & (USE_PROFILES_GAME | USE_PROFILES_MUSIC)
    589     if (NULL == pMetadataExtractor) {
    590         result = SL_RESULT_PARAMETER_INVALID;
    591     } else {
    592         *pMetadataExtractor = NULL;
    593         unsigned exposedMask;
    594         const ClassTable *pCMetadataExtractor_class =
    595             objectIDtoClass(SL_OBJECTID_METADATAEXTRACTOR);
    596         if (NULL == pCMetadataExtractor_class) {
    597             result = SL_RESULT_FEATURE_UNSUPPORTED;
    598         } else {
    599             result = checkInterfaces(pCMetadataExtractor_class, numInterfaces,
    600                 pInterfaceIds, pInterfaceRequired, &exposedMask);
    601         }
    602         if (SL_RESULT_SUCCESS == result) {
    603             CMetadataExtractor *this = (CMetadataExtractor *)
    604                 construct(pCMetadataExtractor_class, exposedMask, self);
    605             if (NULL == this) {
    606                 result = SL_RESULT_MEMORY_FAILURE;
    607             } else {
    608                 IObject_Publish(&this->mObject);
    609                 // return the new metadata extractor object
    610                 *pMetadataExtractor = &this->mObject.mItf;
    611                 result = SL_RESULT_SUCCESS;
    612             }
    613         }
    614     }
    615 #else
    616     result = SL_RESULT_FEATURE_UNSUPPORTED;
    617 #endif
    618 
    619     SL_LEAVE_INTERFACE
    620 }
    621 
    622 
    623 static SLresult IEngine_CreateExtensionObject(SLEngineItf self, SLObjectItf *pObject,
    624     void *pParameters, SLuint32 objectID, SLuint32 numInterfaces,
    625     const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired)
    626 {
    627     SL_ENTER_INTERFACE
    628 
    629     if (NULL == pObject) {
    630         result = SL_RESULT_PARAMETER_INVALID;
    631     } else {
    632         *pObject = NULL;
    633         result = SL_RESULT_FEATURE_UNSUPPORTED;
    634     }
    635 
    636     SL_LEAVE_INTERFACE
    637 }
    638 
    639 
    640 static SLresult IEngine_QueryNumSupportedInterfaces(SLEngineItf self,
    641     SLuint32 objectID, SLuint32 *pNumSupportedInterfaces)
    642 {
    643     SL_ENTER_INTERFACE
    644 
    645     if (NULL == pNumSupportedInterfaces) {
    646         result = SL_RESULT_PARAMETER_INVALID;
    647     } else {
    648         const ClassTable *class__ = objectIDtoClass(objectID);
    649         if (NULL == class__) {
    650             result = SL_RESULT_FEATURE_UNSUPPORTED;
    651         } else {
    652             SLuint32 count = 0;
    653             SLuint32 i;
    654             for (i = 0; i < class__->mInterfaceCount; ++i) {
    655                 switch (class__->mInterfaces[i].mInterface) {
    656                 case INTERFACE_IMPLICIT:
    657                 case INTERFACE_IMPLICIT_PREREALIZE:
    658                 case INTERFACE_EXPLICIT:
    659                 case INTERFACE_EXPLICIT_PREREALIZE:
    660                 case INTERFACE_DYNAMIC:
    661                     ++count;
    662                     break;
    663                 case INTERFACE_UNAVAILABLE:
    664                     break;
    665                 default:
    666                     assert(false);
    667                     break;
    668                 }
    669             }
    670             *pNumSupportedInterfaces = count;
    671             result = SL_RESULT_SUCCESS;
    672         }
    673     }
    674 
    675     SL_LEAVE_INTERFACE;
    676 }
    677 
    678 
    679 static SLresult IEngine_QuerySupportedInterfaces(SLEngineItf self,
    680     SLuint32 objectID, SLuint32 index, SLInterfaceID *pInterfaceId)
    681 {
    682     SL_ENTER_INTERFACE
    683 
    684     if (NULL == pInterfaceId) {
    685         result = SL_RESULT_PARAMETER_INVALID;
    686     } else {
    687         *pInterfaceId = NULL;
    688         const ClassTable *class__ = objectIDtoClass(objectID);
    689         if (NULL == class__) {
    690             result = SL_RESULT_FEATURE_UNSUPPORTED;
    691         } else {
    692             result = SL_RESULT_PARAMETER_INVALID; // will be reset later
    693             SLuint32 i;
    694             for (i = 0; i < class__->mInterfaceCount; ++i) {
    695                 switch (class__->mInterfaces[i].mInterface) {
    696                 case INTERFACE_IMPLICIT:
    697                 case INTERFACE_IMPLICIT_PREREALIZE:
    698                 case INTERFACE_EXPLICIT:
    699                 case INTERFACE_EXPLICIT_PREREALIZE:
    700                 case INTERFACE_DYNAMIC:
    701                     break;
    702                 case INTERFACE_UNAVAILABLE:
    703                     continue;
    704                 default:
    705                     assert(false);
    706                     break;
    707                 }
    708                 if (index == 0) {
    709                     *pInterfaceId = &SL_IID_array[class__->mInterfaces[i].mMPH];
    710                     result = SL_RESULT_SUCCESS;
    711                     break;
    712                 }
    713                 --index;
    714             }
    715         }
    716     }
    717 
    718     SL_LEAVE_INTERFACE
    719 };
    720 
    721 
    722 static const char * const extensionNames[] = {
    723 #ifdef ANDROID
    724     "ANDROID_SDK_LEVEL_9",  // Android 2.3 aka "Gingerbread"
    725     // in the future, add more entries for each SDK level here, and
    726     // don't delete the entries for previous SDK levels unless support is removed
    727 #else
    728     "WILHELM_DESKTOP",
    729 #endif
    730 };
    731 
    732 
    733 static SLresult IEngine_QueryNumSupportedExtensions(SLEngineItf self, SLuint32 *pNumExtensions)
    734 {
    735     SL_ENTER_INTERFACE
    736 
    737     if (NULL == pNumExtensions) {
    738         result = SL_RESULT_PARAMETER_INVALID;
    739     } else {
    740         *pNumExtensions = sizeof(extensionNames) / sizeof(extensionNames[0]);
    741         result = SL_RESULT_SUCCESS;
    742     }
    743 
    744     SL_LEAVE_INTERFACE
    745 }
    746 
    747 
    748 static SLresult IEngine_QuerySupportedExtension(SLEngineItf self,
    749     SLuint32 index, SLchar *pExtensionName, SLint16 *pNameLength)
    750 {
    751     SL_ENTER_INTERFACE
    752 
    753     if (NULL == pNameLength) {
    754         result = SL_RESULT_PARAMETER_INVALID;
    755     } else {
    756         size_t actualNameLength;
    757         unsigned numExtensions = sizeof(extensionNames) / sizeof(extensionNames[0]);
    758         if (index >= numExtensions) {
    759             actualNameLength = 0;
    760             result = SL_RESULT_PARAMETER_INVALID;
    761         } else {
    762             const char *extensionName = extensionNames[index];
    763             actualNameLength = strlen(extensionName) + 1;
    764             if (NULL == pExtensionName) {
    765                 // application is querying the name length in order to allocate a buffer
    766                 result = SL_RESULT_SUCCESS;
    767             } else {
    768                 SLint16 availableNameLength = *pNameLength;
    769                 if (0 >= availableNameLength) {
    770                     // there is not even room for the terminating NUL
    771                     result = SL_RESULT_BUFFER_INSUFFICIENT;
    772                 } else if (actualNameLength > (size_t) availableNameLength) {
    773                     // "no invalid strings are written. That is, the null-terminator always exists"
    774                     memcpy(pExtensionName, extensionName, (size_t) availableNameLength - 1);
    775                     pExtensionName[(size_t) availableNameLength - 1] = '\0';
    776                     result = SL_RESULT_BUFFER_INSUFFICIENT;
    777                 } else {
    778                     memcpy(pExtensionName, extensionName, actualNameLength);
    779                     result = SL_RESULT_SUCCESS;
    780                 }
    781             }
    782         }
    783         *pNameLength = actualNameLength;
    784     }
    785 
    786     SL_LEAVE_INTERFACE
    787 }
    788 
    789 
    790 static SLresult IEngine_IsExtensionSupported(SLEngineItf self,
    791     const SLchar *pExtensionName, SLboolean *pSupported)
    792 {
    793     SL_ENTER_INTERFACE
    794 
    795     if (NULL == pSupported) {
    796         result = SL_RESULT_PARAMETER_INVALID;
    797     } else {
    798         SLboolean isSupported = SL_BOOLEAN_FALSE;
    799         if (NULL == pExtensionName) {
    800             result = SL_RESULT_PARAMETER_INVALID;
    801         } else {
    802             unsigned numExtensions = sizeof(extensionNames) / sizeof(extensionNames[0]);
    803             unsigned i;
    804             for (i = 0; i < numExtensions; ++i) {
    805                 if (!strcmp((const char *) pExtensionName, extensionNames[i])) {
    806                     isSupported = SL_BOOLEAN_TRUE;
    807                     break;
    808                 }
    809             }
    810             result = SL_RESULT_SUCCESS;
    811         }
    812         *pSupported = isSupported;
    813     }
    814 
    815     SL_LEAVE_INTERFACE
    816 }
    817 
    818 
    819 static const struct SLEngineItf_ IEngine_Itf = {
    820     IEngine_CreateLEDDevice,
    821     IEngine_CreateVibraDevice,
    822     IEngine_CreateAudioPlayer,
    823     IEngine_CreateAudioRecorder,
    824     IEngine_CreateMidiPlayer,
    825     IEngine_CreateListener,
    826     IEngine_Create3DGroup,
    827     IEngine_CreateOutputMix,
    828     IEngine_CreateMetadataExtractor,
    829     IEngine_CreateExtensionObject,
    830     IEngine_QueryNumSupportedInterfaces,
    831     IEngine_QuerySupportedInterfaces,
    832     IEngine_QueryNumSupportedExtensions,
    833     IEngine_QuerySupportedExtension,
    834     IEngine_IsExtensionSupported
    835 };
    836 
    837 void IEngine_init(void *self)
    838 {
    839     IEngine *this = (IEngine *) self;
    840     this->mItf = &IEngine_Itf;
    841     // mLossOfControlGlobal is initialized in slCreateEngine
    842 #ifdef USE_SDL
    843     this->mOutputMix = NULL;
    844 #endif
    845     this->mInstanceCount = 1; // ourself
    846     this->mInstanceMask = 0;
    847     this->mChangedMask = 0;
    848     unsigned i;
    849     for (i = 0; i < MAX_INSTANCE; ++i) {
    850         this->mInstances[i] = NULL;
    851     }
    852     this->mShutdown = SL_BOOLEAN_FALSE;
    853     this->mShutdownAck = SL_BOOLEAN_FALSE;
    854     // mThreadPool is initialized in CEngine_Realize
    855     memset(&this->mThreadPool, 0, sizeof(ThreadPool));
    856 #if defined(ANDROID) && !defined(USE_BACKPORT)
    857     this->mEqNumPresets = 0;
    858     this->mEqPresetNames = NULL;
    859 #endif
    860 }
    861 
    862 void IEngine_deinit(void *self)
    863 {
    864 #if defined(ANDROID) && !defined(USE_BACKPORT)
    865     IEngine *this = (IEngine *) self;
    866     // free equalizer preset names
    867     if (NULL != this->mEqPresetNames) {
    868         for (unsigned i = 0; i < this->mEqNumPresets; ++i) {
    869             if (NULL != this->mEqPresetNames[i]) {
    870                 delete[] this->mEqPresetNames[i];
    871                 this->mEqPresetNames[i] = NULL;
    872             }
    873         }
    874         delete[] this->mEqPresetNames;
    875         this->mEqPresetNames = NULL;
    876     }
    877     this->mEqNumPresets = 0;
    878 #endif
    879 }
    880