• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
IEngine_CreateLEDDevice(SLEngineItf self,SLObjectItf * pDevice,SLuint32 deviceID,SLuint32 numInterfaces,const SLInterfaceID * pInterfaceIds,const SLboolean * pInterfaceRequired)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 
IEngine_CreateVibraDevice(SLEngineItf self,SLObjectItf * pDevice,SLuint32 deviceID,SLuint32 numInterfaces,const SLInterfaceID * pInterfaceIds,const SLboolean * pInterfaceRequired)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 
IEngine_CreateAudioPlayer(SLEngineItf self,SLObjectItf * pPlayer,SLDataSource * pAudioSrc,SLDataSink * pAudioSnk,SLuint32 numInterfaces,const SLInterfaceID * pInterfaceIds,const SLboolean * pInterfaceRequired)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 
IEngine_CreateAudioRecorder(SLEngineItf self,SLObjectItf * pRecorder,SLDataSource * pAudioSrc,SLDataSink * pAudioSnk,SLuint32 numInterfaces,const SLInterfaceID * pInterfaceIds,const SLboolean * pInterfaceRequired)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 
IEngine_CreateMidiPlayer(SLEngineItf self,SLObjectItf * pPlayer,SLDataSource * pMIDISrc,SLDataSource * pBankSrc,SLDataSink * pAudioOutput,SLDataSink * pVibra,SLDataSink * pLEDArray,SLuint32 numInterfaces,const SLInterfaceID * pInterfaceIds,const SLboolean * pInterfaceRequired)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 
IEngine_CreateListener(SLEngineItf self,SLObjectItf * pListener,SLuint32 numInterfaces,const SLInterfaceID * pInterfaceIds,const SLboolean * pInterfaceRequired)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 
IEngine_Create3DGroup(SLEngineItf self,SLObjectItf * pGroup,SLuint32 numInterfaces,const SLInterfaceID * pInterfaceIds,const SLboolean * pInterfaceRequired)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 
IEngine_CreateOutputMix(SLEngineItf self,SLObjectItf * pMix,SLuint32 numInterfaces,const SLInterfaceID * pInterfaceIds,const SLboolean * pInterfaceRequired)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 
IEngine_CreateMetadataExtractor(SLEngineItf self,SLObjectItf * pMetadataExtractor,SLDataSource * pDataSource,SLuint32 numInterfaces,const SLInterfaceID * pInterfaceIds,const SLboolean * pInterfaceRequired)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 
IEngine_CreateExtensionObject(SLEngineItf self,SLObjectItf * pObject,void * pParameters,SLuint32 objectID,SLuint32 numInterfaces,const SLInterfaceID * pInterfaceIds,const SLboolean * pInterfaceRequired)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 
IEngine_QueryNumSupportedInterfaces(SLEngineItf self,SLuint32 objectID,SLuint32 * pNumSupportedInterfaces)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 
IEngine_QuerySupportedInterfaces(SLEngineItf self,SLuint32 objectID,SLuint32 index,SLInterfaceID * pInterfaceId)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 
IEngine_QueryNumSupportedExtensions(SLEngineItf self,SLuint32 * pNumExtensions)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 
IEngine_QuerySupportedExtension(SLEngineItf self,SLuint32 index,SLchar * pExtensionName,SLint16 * pNameLength)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 
IEngine_IsExtensionSupported(SLEngineItf self,const SLchar * pExtensionName,SLboolean * pSupported)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 
IEngine_init(void * self)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 
IEngine_deinit(void * self)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