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