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 /* Utility functions */
23
initializeBufferQueueMembers(CAudioPlayer * ap)24 static SLresult initializeBufferQueueMembers(CAudioPlayer *ap) {
25 // inline allocation of circular mArray, up to a typical max
26 if (BUFFER_HEADER_TYPICAL >= ap->mBufferQueue.mNumBuffers) {
27 ap->mBufferQueue.mArray = ap->mBufferQueue.mTypical;
28 } else {
29 // Avoid possible integer overflow during multiplication; this arbitrary
30 // maximum is big enough to not interfere with real applications, but
31 // small enough to not overflow.
32 if (ap->mBufferQueue.mNumBuffers >= 256) {
33 return SL_RESULT_MEMORY_FAILURE;
34 }
35 ap->mBufferQueue.mArray = (BufferHeader *)
36 malloc((ap->mBufferQueue.mNumBuffers + 1) * sizeof(BufferHeader));
37 if (NULL == ap->mBufferQueue.mArray) {
38 return SL_RESULT_MEMORY_FAILURE;
39 }
40 }
41 ap->mBufferQueue.mFront = ap->mBufferQueue.mArray;
42 ap->mBufferQueue.mRear = ap->mBufferQueue.mArray;
43 return SL_RESULT_SUCCESS;
44 }
45
46 #ifdef ANDROID
initializeAndroidBufferQueueMembers(CAudioPlayer * ap)47 static SLresult initializeAndroidBufferQueueMembers(CAudioPlayer *ap) {
48 // Avoid possible integer overflow during multiplication; this arbitrary
49 // maximum is big enough to not interfere with real applications, but
50 // small enough to not overflow.
51 if (ap->mAndroidBufferQueue.mNumBuffers >= 256) {
52 return SL_RESULT_MEMORY_FAILURE;
53 }
54 ap->mAndroidBufferQueue.mBufferArray = (AdvancedBufferHeader *)
55 malloc( (ap->mAndroidBufferQueue.mNumBuffers + 1) * sizeof(AdvancedBufferHeader));
56 if (NULL == ap->mAndroidBufferQueue.mBufferArray) {
57 return SL_RESULT_MEMORY_FAILURE;
58 } else {
59
60 // initialize ABQ buffer type
61 // assert below has been checked in android_audioPlayer_checkSourceSink
62 assert(SL_DATAFORMAT_MIME == ap->mDataSource.mFormat.mFormatType);
63 switch(ap->mDataSource.mFormat.mMIME.containerType) {
64 case SL_CONTAINERTYPE_MPEG_TS:
65 ap->mAndroidBufferQueue.mBufferType = kAndroidBufferTypeMpeg2Ts;
66 break;
67 case SL_CONTAINERTYPE_AAC:
68 case SL_CONTAINERTYPE_RAW: {
69 const char* mime = (char*)ap->mDataSource.mFormat.mMIME.mimeType;
70 if ((mime != NULL) && !(strcasecmp(mime, ANDROID_MIME_AACADTS) &&
71 strcasecmp(mime, ANDROID_MIME_AACADTS_ANDROID_FRAMEWORK))) {
72 ap->mAndroidBufferQueue.mBufferType = kAndroidBufferTypeAacadts;
73 } else {
74 ap->mAndroidBufferQueue.mBufferType = kAndroidBufferTypeInvalid;
75 SL_LOGE("CreateAudioPlayer: Invalid buffer type in Android Buffer Queue");
76 return SL_RESULT_CONTENT_UNSUPPORTED;
77 }
78 } break;
79 default:
80 ap->mAndroidBufferQueue.mBufferType = kAndroidBufferTypeInvalid;
81 SL_LOGE("CreateAudioPlayer: Invalid buffer type in Android Buffer Queue");
82 return SL_RESULT_CONTENT_UNSUPPORTED;
83 }
84
85 // initialize ABQ memory
86 for (SLuint16 i=0 ; i<(ap->mAndroidBufferQueue.mNumBuffers + 1) ; i++) {
87 AdvancedBufferHeader *pBuf = &ap->mAndroidBufferQueue.mBufferArray[i];
88 pBuf->mDataBuffer = NULL;
89 pBuf->mDataSize = 0;
90 pBuf->mDataSizeConsumed = 0;
91 pBuf->mBufferContext = NULL;
92 pBuf->mBufferState = SL_ANDROIDBUFFERQUEUEEVENT_NONE;
93 switch (ap->mAndroidBufferQueue.mBufferType) {
94 case kAndroidBufferTypeMpeg2Ts:
95 pBuf->mItems.mTsCmdData.mTsCmdCode = ANDROID_MP2TSEVENT_NONE;
96 pBuf->mItems.mTsCmdData.mPts = 0;
97 break;
98 case kAndroidBufferTypeAacadts:
99 pBuf->mItems.mAdtsCmdData.mAdtsCmdCode = ANDROID_ADTSEVENT_NONE;
100 break;
101 default:
102 return SL_RESULT_CONTENT_UNSUPPORTED;
103 }
104 }
105 ap->mAndroidBufferQueue.mFront = ap->mAndroidBufferQueue.mBufferArray;
106 ap->mAndroidBufferQueue.mRear = ap->mAndroidBufferQueue.mBufferArray;
107 }
108
109 return SL_RESULT_SUCCESS;
110 }
111 #endif
112
113
IEngine_CreateLEDDevice(SLEngineItf self,SLObjectItf * pDevice,SLuint32 deviceID,SLuint32 numInterfaces,const SLInterfaceID * pInterfaceIds,const SLboolean * pInterfaceRequired)114 static SLresult IEngine_CreateLEDDevice(SLEngineItf self, SLObjectItf *pDevice, SLuint32 deviceID,
115 SLuint32 numInterfaces, const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired)
116 {
117 SL_ENTER_INTERFACE
118
119 #if USE_PROFILES & USE_PROFILES_OPTIONAL
120 if ((NULL == pDevice) || (SL_DEFAULTDEVICEID_LED != deviceID)) {
121 result = SL_RESULT_PARAMETER_INVALID;
122 } else {
123 *pDevice = NULL;
124 unsigned exposedMask;
125 const ClassTable *pCLEDDevice_class = objectIDtoClass(SL_OBJECTID_LEDDEVICE);
126 if (NULL == pCLEDDevice_class) {
127 result = SL_RESULT_FEATURE_UNSUPPORTED;
128 } else {
129 result = checkInterfaces(pCLEDDevice_class, numInterfaces, pInterfaceIds,
130 pInterfaceRequired, &exposedMask, NULL);
131 }
132 if (SL_RESULT_SUCCESS == result) {
133 CLEDDevice *thiz = (CLEDDevice *) construct(pCLEDDevice_class, exposedMask, self);
134 if (NULL == thiz) {
135 result = SL_RESULT_MEMORY_FAILURE;
136 } else {
137 thiz->mDeviceID = deviceID;
138 IObject_Publish(&thiz->mObject);
139 // return the new LED object
140 *pDevice = &thiz->mObject.mItf;
141 }
142 }
143 }
144 #else
145 result = SL_RESULT_FEATURE_UNSUPPORTED;
146 #endif
147
148 SL_LEAVE_INTERFACE
149 }
150
151
IEngine_CreateVibraDevice(SLEngineItf self,SLObjectItf * pDevice,SLuint32 deviceID,SLuint32 numInterfaces,const SLInterfaceID * pInterfaceIds,const SLboolean * pInterfaceRequired)152 static SLresult IEngine_CreateVibraDevice(SLEngineItf self, SLObjectItf *pDevice, SLuint32 deviceID,
153 SLuint32 numInterfaces, const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired)
154 {
155 SL_ENTER_INTERFACE
156
157 #if USE_PROFILES & USE_PROFILES_OPTIONAL
158 if ((NULL == pDevice) || (SL_DEFAULTDEVICEID_VIBRA != deviceID)) {
159 result = SL_RESULT_PARAMETER_INVALID;
160 } else {
161 *pDevice = NULL;
162 unsigned exposedMask;
163 const ClassTable *pCVibraDevice_class = objectIDtoClass(SL_OBJECTID_VIBRADEVICE);
164 if (NULL == pCVibraDevice_class) {
165 result = SL_RESULT_FEATURE_UNSUPPORTED;
166 } else {
167 result = checkInterfaces(pCVibraDevice_class, numInterfaces,
168 pInterfaceIds, pInterfaceRequired, &exposedMask, NULL);
169 }
170 if (SL_RESULT_SUCCESS == result) {
171 CVibraDevice *thiz = (CVibraDevice *) construct(pCVibraDevice_class, exposedMask, self);
172 if (NULL == thiz) {
173 result = SL_RESULT_MEMORY_FAILURE;
174 } else {
175 thiz->mDeviceID = deviceID;
176 IObject_Publish(&thiz->mObject);
177 // return the new vibra object
178 *pDevice = &thiz->mObject.mItf;
179 }
180 }
181 }
182 #else
183 result = SL_RESULT_FEATURE_UNSUPPORTED;
184 #endif
185
186 SL_LEAVE_INTERFACE
187 }
188
189
IEngine_CreateAudioPlayer(SLEngineItf self,SLObjectItf * pPlayer,SLDataSource * pAudioSrc,SLDataSink * pAudioSnk,SLuint32 numInterfaces,const SLInterfaceID * pInterfaceIds,const SLboolean * pInterfaceRequired)190 static SLresult IEngine_CreateAudioPlayer(SLEngineItf self, SLObjectItf *pPlayer,
191 SLDataSource *pAudioSrc, SLDataSink *pAudioSnk, SLuint32 numInterfaces,
192 const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired)
193 {
194 SL_ENTER_INTERFACE
195
196 if (NULL == pPlayer) {
197 result = SL_RESULT_PARAMETER_INVALID;
198 } else {
199 *pPlayer = NULL;
200 unsigned exposedMask, requiredMask;
201 const ClassTable *pCAudioPlayer_class = objectIDtoClass(SL_OBJECTID_AUDIOPLAYER);
202 assert(NULL != pCAudioPlayer_class);
203 result = checkInterfaces(pCAudioPlayer_class, numInterfaces,
204 pInterfaceIds, pInterfaceRequired, &exposedMask, &requiredMask);
205 if (SL_RESULT_SUCCESS == result) {
206
207 // Construct our new AudioPlayer instance
208 CAudioPlayer *thiz = (CAudioPlayer *) construct(pCAudioPlayer_class, exposedMask, self);
209 if (NULL == thiz) {
210 result = SL_RESULT_MEMORY_FAILURE;
211 } else {
212
213 do {
214
215 // Initialize private fields not associated with an interface
216
217 // Default data source in case of failure in checkDataSource
218 thiz->mDataSource.mLocator.mLocatorType = SL_DATALOCATOR_NULL;
219 thiz->mDataSource.mFormat.mFormatType = SL_DATAFORMAT_NULL;
220
221 // Default data sink in case of failure in checkDataSink
222 thiz->mDataSink.mLocator.mLocatorType = SL_DATALOCATOR_NULL;
223 thiz->mDataSink.mFormat.mFormatType = SL_DATAFORMAT_NULL;
224
225 // Default is no per-channel mute or solo
226 thiz->mMuteMask = 0;
227 thiz->mSoloMask = 0;
228
229 // Will be set soon for PCM buffer queues, or later by platform-specific code
230 // during Realize or Prefetch
231 thiz->mNumChannels = UNKNOWN_NUMCHANNELS;
232 thiz->mSampleRateMilliHz = UNKNOWN_SAMPLERATE;
233
234 // More default values, in case destructor needs to be called early
235 thiz->mDirectLevel = 0;
236 #ifdef USE_OUTPUTMIXEXT
237 thiz->mTrack = NULL;
238 thiz->mGains[0] = 1.0f;
239 thiz->mGains[1] = 1.0f;
240 thiz->mDestroyRequested = SL_BOOLEAN_FALSE;
241 #endif
242 #ifdef USE_SNDFILE
243 thiz->mSndFile.mPathname = NULL;
244 thiz->mSndFile.mSNDFILE = NULL;
245 memset(&thiz->mSndFile.mSfInfo, 0, sizeof(SF_INFO));
246 memset(&thiz->mSndFile.mMutex, 0, sizeof(pthread_mutex_t));
247 thiz->mSndFile.mEOF = SL_BOOLEAN_FALSE;
248 thiz->mSndFile.mWhich = 0;
249 memset(thiz->mSndFile.mBuffer, 0, sizeof(thiz->mSndFile.mBuffer));
250 #endif
251 #ifdef ANDROID
252 // placement new (explicit constructor)
253 // FIXME unnecessary once those fields are encapsulated in one class, rather
254 // than a structure
255 (void) new (&thiz->mAudioTrack) android::sp<android::AudioTrackProxy>();
256 (void) new (&thiz->mCallbackProtector)
257 android::sp<android::CallbackProtector>();
258 (void) new (&thiz->mAuxEffect) android::sp<android::AudioEffect>();
259 (void) new (&thiz->mAPlayer) android::sp<android::GenericPlayer>();
260 #endif
261
262 // Check the source and sink parameters against generic constraints,
263 // and make a local copy of all parameters in case other application threads
264 // change memory concurrently.
265
266 result = checkDataSource("pAudioSrc", pAudioSrc, &thiz->mDataSource,
267 DATALOCATOR_MASK_URI | DATALOCATOR_MASK_ADDRESS |
268 DATALOCATOR_MASK_BUFFERQUEUE
269 #ifdef ANDROID
270 | DATALOCATOR_MASK_ANDROIDFD | DATALOCATOR_MASK_ANDROIDSIMPLEBUFFERQUEUE
271 | DATALOCATOR_MASK_ANDROIDBUFFERQUEUE
272 #endif
273 , DATAFORMAT_MASK_MIME | DATAFORMAT_MASK_PCM);
274
275 if (SL_RESULT_SUCCESS != result) {
276 break;
277 }
278
279 result = checkDataSink("pAudioSnk", pAudioSnk, &thiz->mDataSink,
280 DATALOCATOR_MASK_OUTPUTMIX // for playback
281 #ifdef ANDROID
282 | DATALOCATOR_MASK_ANDROIDSIMPLEBUFFERQUEUE // for decode to a BQ
283 | DATALOCATOR_MASK_BUFFERQUEUE // for decode to a BQ
284 #endif
285 , DATAFORMAT_MASK_NULL
286 #ifdef ANDROID
287 | DATAFORMAT_MASK_PCM // for decode to PCM
288 #endif
289 );
290 if (SL_RESULT_SUCCESS != result) {
291 break;
292 }
293
294 // It would be unsafe to ever refer to the application pointers again
295 pAudioSrc = NULL;
296 pAudioSnk = NULL;
297
298 // Check that the requested interfaces are compatible with data source and sink
299 result = checkSourceSinkVsInterfacesCompatibility(&thiz->mDataSource,
300 &thiz->mDataSink, pCAudioPlayer_class, requiredMask);
301 if (SL_RESULT_SUCCESS != result) {
302 break;
303 }
304
305 // copy the buffer queue count from source locator (for playback) / from the
306 // sink locator (for decode on ANDROID build) to the buffer queue interface
307 // we have already range-checked the value down to a smaller width
308 SLuint16 nbBuffers = 0;
309 bool usesAdvancedBufferHeaders = false;
310 bool usesSimpleBufferQueue = false;
311 // creating an AudioPlayer which decodes AAC ADTS buffers to a PCM buffer queue
312 // will cause usesAdvancedBufferHeaders and usesSimpleBufferQueue to be true
313 switch (thiz->mDataSource.mLocator.mLocatorType) {
314 case SL_DATALOCATOR_BUFFERQUEUE:
315 #ifdef ANDROID
316 case SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE:
317 #endif
318 usesSimpleBufferQueue = true;
319 nbBuffers = (SLuint16) thiz->mDataSource.mLocator.mBufferQueue.numBuffers;
320 assert(SL_DATAFORMAT_PCM == thiz->mDataSource.mFormat.mFormatType);
321 thiz->mNumChannels = thiz->mDataSource.mFormat.mPCM.numChannels;
322 thiz->mSampleRateMilliHz = thiz->mDataSource.mFormat.mPCM.samplesPerSec;
323 break;
324 #ifdef ANDROID
325 case SL_DATALOCATOR_ANDROIDBUFFERQUEUE:
326 usesAdvancedBufferHeaders = true;
327 nbBuffers = (SLuint16) thiz->mDataSource.mLocator.mABQ.numBuffers;
328 thiz->mAndroidBufferQueue.mNumBuffers = nbBuffers;
329 break;
330 #endif
331 default:
332 nbBuffers = 0;
333 break;
334 }
335 #ifdef ANDROID
336 switch(thiz->mDataSink.mLocator.mLocatorType) {
337 case SL_DATALOCATOR_BUFFERQUEUE:
338 case SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE:
339 usesSimpleBufferQueue = true;
340 nbBuffers = thiz->mDataSink.mLocator.mBufferQueue.numBuffers;
341 assert(SL_DATAFORMAT_PCM == thiz->mDataSink.mFormat.mFormatType);
342 // FIXME The values specified by the app are meaningless. We get the
343 // real values from the decoder. But the data sink checks currently require
344 // that the app specify these useless values. Needs doc/fix.
345 // Instead use the "unknown" values, as needed by prepare completion.
346 // thiz->mNumChannels = thiz->mDataSink.mFormat.mPCM.numChannels;
347 // thiz->mSampleRateMilliHz = thiz->mDataSink.mFormat.mPCM.samplesPerSec;
348 thiz->mNumChannels = UNKNOWN_NUMCHANNELS;
349 thiz->mSampleRateMilliHz = UNKNOWN_SAMPLERATE;
350 break;
351 default:
352 // leave nbBuffers unchanged
353 break;
354 }
355 #endif
356 thiz->mBufferQueue.mNumBuffers = nbBuffers;
357
358 // check the audio source and sink parameters against platform support
359 #ifdef ANDROID
360 result = android_audioPlayer_checkSourceSink(thiz);
361 if (SL_RESULT_SUCCESS != result) {
362 break;
363 }
364 #endif
365
366 #ifdef USE_SNDFILE
367 result = SndFile_checkAudioPlayerSourceSink(thiz);
368 if (SL_RESULT_SUCCESS != result) {
369 break;
370 }
371 #endif
372
373 #ifdef USE_OUTPUTMIXEXT
374 result = IOutputMixExt_checkAudioPlayerSourceSink(thiz);
375 if (SL_RESULT_SUCCESS != result) {
376 break;
377 }
378 #endif
379
380 // Allocate memory for buffer queue
381 if (usesAdvancedBufferHeaders) {
382 #ifdef ANDROID
383 // locator is SL_DATALOCATOR_ANDROIDBUFFERQUEUE
384 result = initializeAndroidBufferQueueMembers(thiz);
385 #else
386 assert(false);
387 #endif
388 }
389
390 if (usesSimpleBufferQueue) {
391 // locator is SL_DATALOCATOR_BUFFERQUEUE
392 // or SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE
393 result = initializeBufferQueueMembers(thiz);
394 }
395
396 // used to store the data source of our audio player
397 thiz->mDynamicSource.mDataSource = &thiz->mDataSource.u.mSource;
398
399 // platform-specific initialization
400 #ifdef ANDROID
401 android_audioPlayer_create(thiz);
402 #endif
403
404 } while (0);
405
406 if (SL_RESULT_SUCCESS != result) {
407 IObject_Destroy(&thiz->mObject.mItf);
408 } else {
409 IObject_Publish(&thiz->mObject);
410 // return the new audio player object
411 *pPlayer = &thiz->mObject.mItf;
412 }
413
414 }
415 }
416
417 }
418
419 SL_LEAVE_INTERFACE
420 }
421
422
IEngine_CreateAudioRecorder(SLEngineItf self,SLObjectItf * pRecorder,SLDataSource * pAudioSrc,SLDataSink * pAudioSnk,SLuint32 numInterfaces,const SLInterfaceID * pInterfaceIds,const SLboolean * pInterfaceRequired)423 static SLresult IEngine_CreateAudioRecorder(SLEngineItf self, SLObjectItf *pRecorder,
424 SLDataSource *pAudioSrc, SLDataSink *pAudioSnk, SLuint32 numInterfaces,
425 const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired)
426 {
427 SL_ENTER_INTERFACE
428
429 #if (USE_PROFILES & USE_PROFILES_OPTIONAL) || defined(ANDROID)
430 if (NULL == pRecorder) {
431 result = SL_RESULT_PARAMETER_INVALID;
432 } else {
433 *pRecorder = NULL;
434 unsigned exposedMask;
435 const ClassTable *pCAudioRecorder_class = objectIDtoClass(SL_OBJECTID_AUDIORECORDER);
436 if (NULL == pCAudioRecorder_class) {
437 result = SL_RESULT_FEATURE_UNSUPPORTED;
438 } else {
439 result = checkInterfaces(pCAudioRecorder_class, numInterfaces,
440 pInterfaceIds, pInterfaceRequired, &exposedMask, NULL);
441 }
442
443 if (SL_RESULT_SUCCESS == result) {
444
445 // Construct our new AudioRecorder instance
446 CAudioRecorder *thiz = (CAudioRecorder *) construct(pCAudioRecorder_class, exposedMask,
447 self);
448 if (NULL == thiz) {
449 result = SL_RESULT_MEMORY_FAILURE;
450 } else {
451
452 do {
453
454 // Initialize fields not associated with any interface
455
456 // Default data source in case of failure in checkDataSource
457 thiz->mDataSource.mLocator.mLocatorType = SL_DATALOCATOR_NULL;
458 thiz->mDataSource.mFormat.mFormatType = SL_DATAFORMAT_NULL;
459
460 // Default data sink in case of failure in checkDataSink
461 thiz->mDataSink.mLocator.mLocatorType = SL_DATALOCATOR_NULL;
462 thiz->mDataSink.mFormat.mFormatType = SL_DATAFORMAT_NULL;
463
464 // These fields are set to real values by
465 // android_audioRecorder_checkSourceSinkSupport. Note that the data sink is
466 // always PCM buffer queue, so we know the channel count and sample rate early.
467 thiz->mNumChannels = UNKNOWN_NUMCHANNELS;
468 thiz->mSampleRateMilliHz = UNKNOWN_SAMPLERATE;
469 #ifdef ANDROID
470 thiz->mAudioRecord = NULL;
471 thiz->mRecordSource = AUDIO_SOURCE_DEFAULT;
472 #endif
473
474 // Check the source and sink parameters, and make a local copy of all parameters
475 result = checkDataSource("pAudioSrc", pAudioSrc, &thiz->mDataSource,
476 DATALOCATOR_MASK_IODEVICE, DATAFORMAT_MASK_NULL);
477 if (SL_RESULT_SUCCESS != result) {
478 break;
479 }
480 result = checkDataSink("pAudioSnk", pAudioSnk, &thiz->mDataSink,
481 DATALOCATOR_MASK_URI
482 #ifdef ANDROID
483 | DATALOCATOR_MASK_ANDROIDSIMPLEBUFFERQUEUE
484 #endif
485 , DATAFORMAT_MASK_MIME | DATAFORMAT_MASK_PCM
486 );
487 if (SL_RESULT_SUCCESS != result) {
488 break;
489 }
490
491 // It would be unsafe to ever refer to the application pointers again
492 pAudioSrc = NULL;
493 pAudioSnk = NULL;
494
495 // check the audio source and sink parameters against platform support
496 #ifdef ANDROID
497 result = android_audioRecorder_checkSourceSinkSupport(thiz);
498 if (SL_RESULT_SUCCESS != result) {
499 SL_LOGE("Cannot create AudioRecorder: invalid source or sink");
500 break;
501 }
502 #endif
503
504 #ifdef ANDROID
505 // Allocate memory for buffer queue
506 SLuint32 locatorType = thiz->mDataSink.mLocator.mLocatorType;
507 if (locatorType == SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE) {
508 thiz->mBufferQueue.mNumBuffers =
509 thiz->mDataSink.mLocator.mBufferQueue.numBuffers;
510 // inline allocation of circular Buffer Queue mArray, up to a typical max
511 if (BUFFER_HEADER_TYPICAL >= thiz->mBufferQueue.mNumBuffers) {
512 thiz->mBufferQueue.mArray = thiz->mBufferQueue.mTypical;
513 } else {
514 // Avoid possible integer overflow during multiplication; this arbitrary
515 // maximum is big enough to not interfere with real applications, but
516 // small enough to not overflow.
517 if (thiz->mBufferQueue.mNumBuffers >= 256) {
518 result = SL_RESULT_MEMORY_FAILURE;
519 break;
520 }
521 thiz->mBufferQueue.mArray = (BufferHeader *) malloc((thiz->mBufferQueue.
522 mNumBuffers + 1) * sizeof(BufferHeader));
523 if (NULL == thiz->mBufferQueue.mArray) {
524 result = SL_RESULT_MEMORY_FAILURE;
525 break;
526 }
527 }
528 thiz->mBufferQueue.mFront = thiz->mBufferQueue.mArray;
529 thiz->mBufferQueue.mRear = thiz->mBufferQueue.mArray;
530 }
531 #endif
532
533 // platform-specific initialization
534 #ifdef ANDROID
535 android_audioRecorder_create(thiz);
536 #endif
537
538 } while (0);
539
540 if (SL_RESULT_SUCCESS != result) {
541 IObject_Destroy(&thiz->mObject.mItf);
542 } else {
543 IObject_Publish(&thiz->mObject);
544 // return the new audio recorder object
545 *pRecorder = &thiz->mObject.mItf;
546 }
547 }
548
549 }
550
551 }
552 #else
553 result = SL_RESULT_FEATURE_UNSUPPORTED;
554 #endif
555
556 SL_LEAVE_INTERFACE
557 }
558
559
IEngine_CreateMidiPlayer(SLEngineItf self,SLObjectItf * pPlayer,SLDataSource * pMIDISrc,SLDataSource * pBankSrc,SLDataSink * pAudioOutput,SLDataSink * pVibra,SLDataSink * pLEDArray,SLuint32 numInterfaces,const SLInterfaceID * pInterfaceIds,const SLboolean * pInterfaceRequired)560 static SLresult IEngine_CreateMidiPlayer(SLEngineItf self, SLObjectItf *pPlayer,
561 SLDataSource *pMIDISrc, SLDataSource *pBankSrc, SLDataSink *pAudioOutput,
562 SLDataSink *pVibra, SLDataSink *pLEDArray, SLuint32 numInterfaces,
563 const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired)
564 {
565 SL_ENTER_INTERFACE
566
567 #if USE_PROFILES & (USE_PROFILES_GAME | USE_PROFILES_PHONE)
568 if ((NULL == pPlayer) || (NULL == pMIDISrc) || (NULL == pAudioOutput)) {
569 result = SL_RESULT_PARAMETER_INVALID;
570 } else {
571 *pPlayer = NULL;
572 unsigned exposedMask;
573 const ClassTable *pCMidiPlayer_class = objectIDtoClass(SL_OBJECTID_MIDIPLAYER);
574 if (NULL == pCMidiPlayer_class) {
575 result = SL_RESULT_FEATURE_UNSUPPORTED;
576 } else {
577 result = checkInterfaces(pCMidiPlayer_class, numInterfaces,
578 pInterfaceIds, pInterfaceRequired, &exposedMask, NULL);
579 }
580 if (SL_RESULT_SUCCESS == result) {
581 CMidiPlayer *thiz = (CMidiPlayer *) construct(pCMidiPlayer_class, exposedMask, self);
582 if (NULL == thiz) {
583 result = SL_RESULT_MEMORY_FAILURE;
584 } else {
585 #if 0
586 "pMIDISrc", pMIDISrc, URI | MIDIBUFFERQUEUE, NONE
587 "pBankSrc", pBanksrc, NULL | URI | ADDRESS, NULL
588 "pAudioOutput", pAudioOutput, OUTPUTMIX, NULL
589 "pVibra", pVibra, NULL | IODEVICE, NULL
590 "pLEDArray", pLEDArray, NULL | IODEVICE, NULL
591 #endif
592 // a fake value - why not use value from IPlay_init? what does CT check for?
593 thiz->mPlay.mDuration = 0;
594 IObject_Publish(&thiz->mObject);
595 // return the new MIDI player object
596 *pPlayer = &thiz->mObject.mItf;
597 }
598 }
599 }
600 #else
601 result = SL_RESULT_FEATURE_UNSUPPORTED;
602 #endif
603
604 SL_LEAVE_INTERFACE
605 }
606
607
IEngine_CreateListener(SLEngineItf self,SLObjectItf * pListener,SLuint32 numInterfaces,const SLInterfaceID * pInterfaceIds,const SLboolean * pInterfaceRequired)608 static SLresult IEngine_CreateListener(SLEngineItf self, SLObjectItf *pListener,
609 SLuint32 numInterfaces, const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired)
610 {
611 SL_ENTER_INTERFACE
612
613 #if USE_PROFILES & USE_PROFILES_GAME
614 if (NULL == pListener) {
615 result = SL_RESULT_PARAMETER_INVALID;
616 } else {
617 *pListener = NULL;
618 unsigned exposedMask;
619 const ClassTable *pCListener_class = objectIDtoClass(SL_OBJECTID_LISTENER);
620 if (NULL == pCListener_class) {
621 result = SL_RESULT_FEATURE_UNSUPPORTED;
622 } else {
623 result = checkInterfaces(pCListener_class, numInterfaces,
624 pInterfaceIds, pInterfaceRequired, &exposedMask, NULL);
625 }
626 if (SL_RESULT_SUCCESS == result) {
627 CListener *thiz = (CListener *) construct(pCListener_class, exposedMask, self);
628 if (NULL == thiz) {
629 result = SL_RESULT_MEMORY_FAILURE;
630 } else {
631 IObject_Publish(&thiz->mObject);
632 // return the new 3D listener object
633 *pListener = &thiz->mObject.mItf;
634 }
635 }
636 }
637 #else
638 result = SL_RESULT_FEATURE_UNSUPPORTED;
639 #endif
640
641 SL_LEAVE_INTERFACE
642 }
643
644
IEngine_Create3DGroup(SLEngineItf self,SLObjectItf * pGroup,SLuint32 numInterfaces,const SLInterfaceID * pInterfaceIds,const SLboolean * pInterfaceRequired)645 static SLresult IEngine_Create3DGroup(SLEngineItf self, SLObjectItf *pGroup, SLuint32 numInterfaces,
646 const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired)
647 {
648 SL_ENTER_INTERFACE
649
650 #if USE_PROFILES & USE_PROFILES_GAME
651 if (NULL == pGroup) {
652 result = SL_RESULT_PARAMETER_INVALID;
653 } else {
654 *pGroup = NULL;
655 unsigned exposedMask;
656 const ClassTable *pC3DGroup_class = objectIDtoClass(SL_OBJECTID_3DGROUP);
657 if (NULL == pC3DGroup_class) {
658 result = SL_RESULT_FEATURE_UNSUPPORTED;
659 } else {
660 result = checkInterfaces(pC3DGroup_class, numInterfaces,
661 pInterfaceIds, pInterfaceRequired, &exposedMask, NULL);
662 }
663 if (SL_RESULT_SUCCESS == result) {
664 C3DGroup *thiz = (C3DGroup *) construct(pC3DGroup_class, exposedMask, self);
665 if (NULL == thiz) {
666 result = SL_RESULT_MEMORY_FAILURE;
667 } else {
668 thiz->mMemberMask = 0;
669 IObject_Publish(&thiz->mObject);
670 // return the new 3D group object
671 *pGroup = &thiz->mObject.mItf;
672 }
673 }
674 }
675 #else
676 result = SL_RESULT_FEATURE_UNSUPPORTED;
677 #endif
678
679 SL_LEAVE_INTERFACE
680 }
681
682
IEngine_CreateOutputMix(SLEngineItf self,SLObjectItf * pMix,SLuint32 numInterfaces,const SLInterfaceID * pInterfaceIds,const SLboolean * pInterfaceRequired)683 static SLresult IEngine_CreateOutputMix(SLEngineItf self, SLObjectItf *pMix, SLuint32 numInterfaces,
684 const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired)
685 {
686 SL_ENTER_INTERFACE
687
688 if (NULL == pMix) {
689 result = SL_RESULT_PARAMETER_INVALID;
690 } else {
691 *pMix = NULL;
692 unsigned exposedMask;
693 const ClassTable *pCOutputMix_class = objectIDtoClass(SL_OBJECTID_OUTPUTMIX);
694 assert(NULL != pCOutputMix_class);
695 result = checkInterfaces(pCOutputMix_class, numInterfaces,
696 pInterfaceIds, pInterfaceRequired, &exposedMask, NULL);
697 if (SL_RESULT_SUCCESS == result) {
698 COutputMix *thiz = (COutputMix *) construct(pCOutputMix_class, exposedMask, self);
699 if (NULL == thiz) {
700 result = SL_RESULT_MEMORY_FAILURE;
701 } else {
702 #ifdef ANDROID
703 android_outputMix_create(thiz);
704 #endif
705 #ifdef USE_SDL
706 IEngine *thisEngine = &thiz->mObject.mEngine->mEngine;
707 interface_lock_exclusive(thisEngine);
708 bool unpause = false;
709 if (NULL == thisEngine->mOutputMix) {
710 thisEngine->mOutputMix = thiz;
711 unpause = true;
712 }
713 interface_unlock_exclusive(thisEngine);
714 #endif
715 IObject_Publish(&thiz->mObject);
716 #ifdef USE_SDL
717 if (unpause) {
718 // Enable SDL_callback to be called periodically by SDL's internal thread
719 SDL_PauseAudio(0);
720 }
721 #endif
722 // return the new output mix object
723 *pMix = &thiz->mObject.mItf;
724 }
725 }
726 }
727
728 SL_LEAVE_INTERFACE
729 }
730
731
IEngine_CreateMetadataExtractor(SLEngineItf self,SLObjectItf * pMetadataExtractor,SLDataSource * pDataSource,SLuint32 numInterfaces,const SLInterfaceID * pInterfaceIds,const SLboolean * pInterfaceRequired)732 static SLresult IEngine_CreateMetadataExtractor(SLEngineItf self, SLObjectItf *pMetadataExtractor,
733 SLDataSource *pDataSource, SLuint32 numInterfaces, const SLInterfaceID *pInterfaceIds,
734 const SLboolean *pInterfaceRequired)
735 {
736 SL_ENTER_INTERFACE
737
738 #if USE_PROFILES & (USE_PROFILES_GAME | USE_PROFILES_MUSIC)
739 if (NULL == pMetadataExtractor) {
740 result = SL_RESULT_PARAMETER_INVALID;
741 } else {
742 *pMetadataExtractor = NULL;
743 unsigned exposedMask;
744 const ClassTable *pCMetadataExtractor_class =
745 objectIDtoClass(SL_OBJECTID_METADATAEXTRACTOR);
746 if (NULL == pCMetadataExtractor_class) {
747 result = SL_RESULT_FEATURE_UNSUPPORTED;
748 } else {
749 result = checkInterfaces(pCMetadataExtractor_class, numInterfaces,
750 pInterfaceIds, pInterfaceRequired, &exposedMask, NULL);
751 }
752 if (SL_RESULT_SUCCESS == result) {
753 CMetadataExtractor *thiz = (CMetadataExtractor *)
754 construct(pCMetadataExtractor_class, exposedMask, self);
755 if (NULL == thiz) {
756 result = SL_RESULT_MEMORY_FAILURE;
757 } else {
758 #if 0
759 "pDataSource", pDataSource, NONE, NONE
760 #endif
761 IObject_Publish(&thiz->mObject);
762 // return the new metadata extractor object
763 *pMetadataExtractor = &thiz->mObject.mItf;
764 result = SL_RESULT_SUCCESS;
765 }
766 }
767 }
768 #else
769 result = SL_RESULT_FEATURE_UNSUPPORTED;
770 #endif
771
772 SL_LEAVE_INTERFACE
773 }
774
775
IEngine_CreateExtensionObject(SLEngineItf self,SLObjectItf * pObject,void * pParameters,SLuint32 objectID,SLuint32 numInterfaces,const SLInterfaceID * pInterfaceIds,const SLboolean * pInterfaceRequired)776 static SLresult IEngine_CreateExtensionObject(SLEngineItf self, SLObjectItf *pObject,
777 void *pParameters, SLuint32 objectID, SLuint32 numInterfaces,
778 const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired)
779 {
780 SL_ENTER_INTERFACE
781
782 if (NULL == pObject) {
783 result = SL_RESULT_PARAMETER_INVALID;
784 } else {
785 *pObject = NULL;
786 result = SL_RESULT_FEATURE_UNSUPPORTED;
787 }
788
789 SL_LEAVE_INTERFACE
790 }
791
792
IEngine_QueryNumSupportedInterfaces(SLEngineItf self,SLuint32 objectID,SLuint32 * pNumSupportedInterfaces)793 static SLresult IEngine_QueryNumSupportedInterfaces(SLEngineItf self,
794 SLuint32 objectID, SLuint32 *pNumSupportedInterfaces)
795 {
796 SL_ENTER_INTERFACE
797
798 if (NULL == pNumSupportedInterfaces) {
799 result = SL_RESULT_PARAMETER_INVALID;
800 } else {
801 const ClassTable *clazz = objectIDtoClass(objectID);
802 if (NULL == clazz) {
803 result = SL_RESULT_FEATURE_UNSUPPORTED;
804 } else {
805 SLuint32 count = 0;
806 SLuint32 i;
807 for (i = 0; i < clazz->mInterfaceCount; ++i) {
808 switch (clazz->mInterfaces[i].mInterface) {
809 case INTERFACE_IMPLICIT:
810 case INTERFACE_IMPLICIT_PREREALIZE:
811 case INTERFACE_EXPLICIT:
812 case INTERFACE_EXPLICIT_PREREALIZE:
813 case INTERFACE_DYNAMIC:
814 ++count;
815 break;
816 case INTERFACE_UNAVAILABLE:
817 break;
818 default:
819 assert(false);
820 break;
821 }
822 }
823 *pNumSupportedInterfaces = count;
824 result = SL_RESULT_SUCCESS;
825 }
826 }
827
828 SL_LEAVE_INTERFACE;
829 }
830
831
IEngine_QuerySupportedInterfaces(SLEngineItf self,SLuint32 objectID,SLuint32 index,SLInterfaceID * pInterfaceId)832 static SLresult IEngine_QuerySupportedInterfaces(SLEngineItf self,
833 SLuint32 objectID, SLuint32 index, SLInterfaceID *pInterfaceId)
834 {
835 SL_ENTER_INTERFACE
836
837 if (NULL == pInterfaceId) {
838 result = SL_RESULT_PARAMETER_INVALID;
839 } else {
840 *pInterfaceId = NULL;
841 const ClassTable *clazz = objectIDtoClass(objectID);
842 if (NULL == clazz) {
843 result = SL_RESULT_FEATURE_UNSUPPORTED;
844 } else {
845 result = SL_RESULT_PARAMETER_INVALID; // will be reset later
846 SLuint32 i;
847 for (i = 0; i < clazz->mInterfaceCount; ++i) {
848 switch (clazz->mInterfaces[i].mInterface) {
849 case INTERFACE_IMPLICIT:
850 case INTERFACE_IMPLICIT_PREREALIZE:
851 case INTERFACE_EXPLICIT:
852 case INTERFACE_EXPLICIT_PREREALIZE:
853 case INTERFACE_DYNAMIC:
854 break;
855 case INTERFACE_UNAVAILABLE:
856 continue;
857 default:
858 assert(false);
859 break;
860 }
861 if (index == 0) {
862 *pInterfaceId = &SL_IID_array[clazz->mInterfaces[i].mMPH];
863 result = SL_RESULT_SUCCESS;
864 break;
865 }
866 --index;
867 }
868 }
869 }
870
871 SL_LEAVE_INTERFACE
872 };
873
874
875 static const char * const extensionNames[] = {
876 #ifdef ANDROID
877 #define _(n) #n
878 #define __(n) _(n)
879 "ANDROID_SDK_LEVEL_" __(PLATFORM_SDK_VERSION),
880 #undef _
881 #undef __
882 #else
883 "WILHELM_DESKTOP",
884 #endif
885 };
886
887
IEngine_QueryNumSupportedExtensions(SLEngineItf self,SLuint32 * pNumExtensions)888 static SLresult IEngine_QueryNumSupportedExtensions(SLEngineItf self, SLuint32 *pNumExtensions)
889 {
890 SL_ENTER_INTERFACE
891
892 if (NULL == pNumExtensions) {
893 result = SL_RESULT_PARAMETER_INVALID;
894 } else {
895 *pNumExtensions = sizeof(extensionNames) / sizeof(extensionNames[0]);
896 result = SL_RESULT_SUCCESS;
897 }
898
899 SL_LEAVE_INTERFACE
900 }
901
902
IEngine_QuerySupportedExtension(SLEngineItf self,SLuint32 index,SLchar * pExtensionName,SLint16 * pNameLength)903 static SLresult IEngine_QuerySupportedExtension(SLEngineItf self,
904 SLuint32 index, SLchar *pExtensionName, SLint16 *pNameLength)
905 {
906 SL_ENTER_INTERFACE
907
908 if (NULL == pNameLength) {
909 result = SL_RESULT_PARAMETER_INVALID;
910 } else {
911 size_t actualNameLength;
912 unsigned numExtensions = sizeof(extensionNames) / sizeof(extensionNames[0]);
913 if (index >= numExtensions) {
914 actualNameLength = 0;
915 result = SL_RESULT_PARAMETER_INVALID;
916 } else {
917 const char *extensionName = extensionNames[index];
918 actualNameLength = strlen(extensionName) + 1;
919 if (NULL == pExtensionName) {
920 // application is querying the name length in order to allocate a buffer
921 result = SL_RESULT_SUCCESS;
922 } else {
923 SLint16 availableNameLength = *pNameLength;
924 if (0 >= availableNameLength) {
925 // there is not even room for the terminating NUL
926 result = SL_RESULT_BUFFER_INSUFFICIENT;
927 } else if (actualNameLength > (size_t) availableNameLength) {
928 // "no invalid strings are written. That is, the null-terminator always exists"
929 memcpy(pExtensionName, extensionName, (size_t) availableNameLength - 1);
930 pExtensionName[(size_t) availableNameLength - 1] = '\0';
931 result = SL_RESULT_BUFFER_INSUFFICIENT;
932 } else {
933 memcpy(pExtensionName, extensionName, actualNameLength);
934 result = SL_RESULT_SUCCESS;
935 }
936 }
937 }
938 *pNameLength = actualNameLength;
939 }
940
941 SL_LEAVE_INTERFACE
942 }
943
944
IEngine_IsExtensionSupported(SLEngineItf self,const SLchar * pExtensionName,SLboolean * pSupported)945 static SLresult IEngine_IsExtensionSupported(SLEngineItf self,
946 const SLchar *pExtensionName, SLboolean *pSupported)
947 {
948 SL_ENTER_INTERFACE
949
950 if (NULL == pSupported) {
951 result = SL_RESULT_PARAMETER_INVALID;
952 } else {
953 SLboolean isSupported = SL_BOOLEAN_FALSE;
954 if (NULL == pExtensionName) {
955 result = SL_RESULT_PARAMETER_INVALID;
956 } else {
957 unsigned numExtensions = sizeof(extensionNames) / sizeof(extensionNames[0]);
958 unsigned i;
959 for (i = 0; i < numExtensions; ++i) {
960 if (!strcmp((const char *) pExtensionName, extensionNames[i])) {
961 isSupported = SL_BOOLEAN_TRUE;
962 break;
963 }
964 }
965 result = SL_RESULT_SUCCESS;
966 }
967 *pSupported = isSupported;
968 }
969
970 SL_LEAVE_INTERFACE
971 }
972
973
974 static const struct SLEngineItf_ IEngine_Itf = {
975 IEngine_CreateLEDDevice,
976 IEngine_CreateVibraDevice,
977 IEngine_CreateAudioPlayer,
978 IEngine_CreateAudioRecorder,
979 IEngine_CreateMidiPlayer,
980 IEngine_CreateListener,
981 IEngine_Create3DGroup,
982 IEngine_CreateOutputMix,
983 IEngine_CreateMetadataExtractor,
984 IEngine_CreateExtensionObject,
985 IEngine_QueryNumSupportedInterfaces,
986 IEngine_QuerySupportedInterfaces,
987 IEngine_QueryNumSupportedExtensions,
988 IEngine_QuerySupportedExtension,
989 IEngine_IsExtensionSupported
990 };
991
IEngine_init(void * self)992 void IEngine_init(void *self)
993 {
994 IEngine *thiz = (IEngine *) self;
995 thiz->mItf = &IEngine_Itf;
996 // mLossOfControlGlobal is initialized in slCreateEngine
997 #ifdef USE_SDL
998 thiz->mOutputMix = NULL;
999 #endif
1000 thiz->mInstanceCount = 1; // ourself
1001 thiz->mInstanceMask = 0;
1002 thiz->mChangedMask = 0;
1003 unsigned i;
1004 for (i = 0; i < MAX_INSTANCE; ++i) {
1005 thiz->mInstances[i] = NULL;
1006 }
1007 thiz->mShutdown = SL_BOOLEAN_FALSE;
1008 thiz->mShutdownAck = SL_BOOLEAN_FALSE;
1009 }
1010
IEngine_deinit(void * self)1011 void IEngine_deinit(void *self)
1012 {
1013 }
1014
1015
1016 // OpenMAX AL Engine
1017
1018
IEngine_CreateCameraDevice(XAEngineItf self,XAObjectItf * pDevice,XAuint32 deviceID,XAuint32 numInterfaces,const XAInterfaceID * pInterfaceIds,const XAboolean * pInterfaceRequired)1019 static XAresult IEngine_CreateCameraDevice(XAEngineItf self, XAObjectItf *pDevice,
1020 XAuint32 deviceID, XAuint32 numInterfaces, const XAInterfaceID *pInterfaceIds,
1021 const XAboolean *pInterfaceRequired)
1022 {
1023 XA_ENTER_INTERFACE
1024
1025 //IXAEngine *thiz = (IXAEngine *) self;
1026 result = SL_RESULT_FEATURE_UNSUPPORTED;
1027
1028 XA_LEAVE_INTERFACE
1029 }
1030
1031
IEngine_CreateRadioDevice(XAEngineItf self,XAObjectItf * pDevice,XAuint32 numInterfaces,const XAInterfaceID * pInterfaceIds,const XAboolean * pInterfaceRequired)1032 static XAresult IEngine_CreateRadioDevice(XAEngineItf self, XAObjectItf *pDevice,
1033 XAuint32 numInterfaces, const XAInterfaceID *pInterfaceIds,
1034 const XAboolean *pInterfaceRequired)
1035 {
1036 XA_ENTER_INTERFACE
1037
1038 //IXAEngine *thiz = (IXAEngine *) self;
1039 result = SL_RESULT_FEATURE_UNSUPPORTED;
1040
1041 XA_LEAVE_INTERFACE
1042 }
1043
1044
IXAEngine_CreateLEDDevice(XAEngineItf self,XAObjectItf * pDevice,XAuint32 deviceID,XAuint32 numInterfaces,const XAInterfaceID * pInterfaceIds,const XAboolean * pInterfaceRequired)1045 static XAresult IXAEngine_CreateLEDDevice(XAEngineItf self, XAObjectItf *pDevice, XAuint32 deviceID,
1046 XAuint32 numInterfaces, const XAInterfaceID *pInterfaceIds,
1047 const XAboolean *pInterfaceRequired)
1048 {
1049 // forward to OpenSL ES
1050 return IEngine_CreateLEDDevice(&((CEngine *) ((IXAEngine *) self)->mThis)->mEngine.mItf,
1051 (SLObjectItf *) pDevice, deviceID, numInterfaces, (const SLInterfaceID *) pInterfaceIds,
1052 (const SLboolean *) pInterfaceRequired);
1053 }
1054
1055
IXAEngine_CreateVibraDevice(XAEngineItf self,XAObjectItf * pDevice,XAuint32 deviceID,XAuint32 numInterfaces,const XAInterfaceID * pInterfaceIds,const XAboolean * pInterfaceRequired)1056 static XAresult IXAEngine_CreateVibraDevice(XAEngineItf self, XAObjectItf *pDevice,
1057 XAuint32 deviceID, XAuint32 numInterfaces, const XAInterfaceID *pInterfaceIds,
1058 const XAboolean *pInterfaceRequired)
1059 {
1060 // forward to OpenSL ES
1061 return IEngine_CreateVibraDevice(&((CEngine *) ((IXAEngine *) self)->mThis)->mEngine.mItf,
1062 (SLObjectItf *) pDevice, deviceID, numInterfaces, (const SLInterfaceID *) pInterfaceIds,
1063 (const SLboolean *) pInterfaceRequired);
1064 }
1065
1066
IEngine_CreateMediaPlayer(XAEngineItf self,XAObjectItf * pPlayer,XADataSource * pDataSrc,XADataSource * pBankSrc,XADataSink * pAudioSnk,XADataSink * pImageVideoSnk,XADataSink * pVibra,XADataSink * pLEDArray,XAuint32 numInterfaces,const XAInterfaceID * pInterfaceIds,const XAboolean * pInterfaceRequired)1067 static XAresult IEngine_CreateMediaPlayer(XAEngineItf self, XAObjectItf *pPlayer,
1068 XADataSource *pDataSrc, XADataSource *pBankSrc, XADataSink *pAudioSnk,
1069 XADataSink *pImageVideoSnk, XADataSink *pVibra, XADataSink *pLEDArray,
1070 XAuint32 numInterfaces, const XAInterfaceID *pInterfaceIds,
1071 const XAboolean *pInterfaceRequired)
1072 {
1073 XA_ENTER_INTERFACE
1074
1075 if (NULL == pPlayer) {
1076 result = XA_RESULT_PARAMETER_INVALID;
1077 } else {
1078 *pPlayer = NULL;
1079 unsigned exposedMask;
1080 const ClassTable *pCMediaPlayer_class = objectIDtoClass(XA_OBJECTID_MEDIAPLAYER);
1081 assert(NULL != pCMediaPlayer_class);
1082 result = checkInterfaces(pCMediaPlayer_class, numInterfaces,
1083 (const SLInterfaceID *) pInterfaceIds, pInterfaceRequired, &exposedMask, NULL);
1084 if (XA_RESULT_SUCCESS == result) {
1085
1086 // Construct our new MediaPlayer instance
1087 CMediaPlayer *thiz = (CMediaPlayer *) construct(pCMediaPlayer_class, exposedMask,
1088 &((CEngine *) ((IXAEngine *) self)->mThis)->mEngine.mItf);
1089 if (NULL == thiz) {
1090 result = XA_RESULT_MEMORY_FAILURE;
1091 } else {
1092
1093 do {
1094
1095 // Initialize private fields not associated with an interface
1096
1097 // Default data source in case of failure in checkDataSource
1098 thiz->mDataSource.mLocator.mLocatorType = SL_DATALOCATOR_NULL;
1099 thiz->mDataSource.mFormat.mFormatType = XA_DATAFORMAT_NULL;
1100
1101 // Default andio and image sink in case of failure in checkDataSink
1102 thiz->mAudioSink.mLocator.mLocatorType = XA_DATALOCATOR_NULL;
1103 thiz->mAudioSink.mFormat.mFormatType = XA_DATAFORMAT_NULL;
1104 thiz->mImageVideoSink.mLocator.mLocatorType = XA_DATALOCATOR_NULL;
1105 thiz->mImageVideoSink.mFormat.mFormatType = XA_DATAFORMAT_NULL;
1106
1107 // More default values, in case destructor needs to be called early
1108 thiz->mNumChannels = UNKNOWN_NUMCHANNELS;
1109
1110 // (assume calloc or memset 0 during allocation)
1111 // placement new
1112 #ifdef ANDROID
1113 // placement new (explicit constructor)
1114 // FIXME unnecessary once those fields are encapsulated in one class, rather
1115 // than a structure
1116 (void) new (&thiz->mAVPlayer) android::sp<android::GenericPlayer>();
1117 (void) new (&thiz->mCallbackProtector)
1118 android::sp<android::CallbackProtector>();
1119 #endif
1120
1121 // Check the source and sink parameters against generic constraints
1122
1123 result = checkDataSource("pDataSrc", (const SLDataSource *) pDataSrc,
1124 &thiz->mDataSource, DATALOCATOR_MASK_URI
1125 #ifdef ANDROID
1126 | DATALOCATOR_MASK_ANDROIDFD
1127 | DATALOCATOR_MASK_ANDROIDBUFFERQUEUE
1128 #endif
1129 , DATAFORMAT_MASK_MIME);
1130 if (XA_RESULT_SUCCESS != result) {
1131 break;
1132 }
1133
1134 result = checkDataSource("pBankSrc", (const SLDataSource *) pBankSrc,
1135 &thiz->mBankSource, DATALOCATOR_MASK_NULL | DATALOCATOR_MASK_URI |
1136 DATALOCATOR_MASK_ADDRESS, DATAFORMAT_MASK_NULL);
1137 if (XA_RESULT_SUCCESS != result) {
1138 break;
1139 }
1140
1141 result = checkDataSink("pAudioSnk", (const SLDataSink *) pAudioSnk,
1142 &thiz->mAudioSink, DATALOCATOR_MASK_OUTPUTMIX, DATAFORMAT_MASK_NULL);
1143 if (XA_RESULT_SUCCESS != result) {
1144 break;
1145 }
1146
1147 result = checkDataSink("pImageVideoSnk", (const SLDataSink *) pImageVideoSnk,
1148 &thiz->mImageVideoSink,
1149 DATALOCATOR_MASK_NULL | DATALOCATOR_MASK_NATIVEDISPLAY,
1150 DATAFORMAT_MASK_NULL);
1151 if (XA_RESULT_SUCCESS != result) {
1152 break;
1153 }
1154
1155 result = checkDataSink("pVibra", (const SLDataSink *) pVibra, &thiz->mVibraSink,
1156 DATALOCATOR_MASK_NULL | DATALOCATOR_MASK_IODEVICE,
1157 DATAFORMAT_MASK_NULL);
1158 if (XA_RESULT_SUCCESS != result) {
1159 break;
1160 }
1161
1162 result = checkDataSink("pLEDArray", (const SLDataSink *) pLEDArray,
1163 &thiz->mLEDArraySink, DATALOCATOR_MASK_NULL | DATALOCATOR_MASK_IODEVICE,
1164 DATAFORMAT_MASK_NULL);
1165 if (XA_RESULT_SUCCESS != result) {
1166 break;
1167 }
1168
1169 // Unsafe to ever refer to application pointers again
1170 pDataSrc = NULL;
1171 pBankSrc = NULL;
1172 pAudioSnk = NULL;
1173 pImageVideoSnk = NULL;
1174 pVibra = NULL;
1175 pLEDArray = NULL;
1176
1177 // Check that the requested interfaces are compatible with the data source
1178 // FIXME implement
1179
1180 // check the source and sink parameters against platform support
1181 #ifdef ANDROID
1182 result = android_Player_checkSourceSink(thiz);
1183 if (XA_RESULT_SUCCESS != result) {
1184 break;
1185 }
1186 #endif
1187
1188 #ifdef ANDROID
1189 // AndroidBufferQueue-specific initialization
1190 if (XA_DATALOCATOR_ANDROIDBUFFERQUEUE ==
1191 thiz->mDataSource.mLocator.mLocatorType) {
1192 XAuint16 nbBuffers = (XAuint16) thiz->mDataSource.mLocator.mABQ.numBuffers;
1193
1194 // Avoid possible integer overflow during multiplication; this arbitrary
1195 // maximum is big enough to not interfere with real applications, but
1196 // small enough to not overflow.
1197 if (nbBuffers >= 256) {
1198 result = SL_RESULT_MEMORY_FAILURE;
1199 break;
1200 }
1201
1202 // initialize ABQ buffer type
1203 // assert below has been checked in android_audioPlayer_checkSourceSink
1204 assert(XA_DATAFORMAT_MIME == thiz->mDataSource.mFormat.mFormatType);
1205 if (XA_CONTAINERTYPE_MPEG_TS ==
1206 thiz->mDataSource.mFormat.mMIME.containerType) {
1207 thiz->mAndroidBufferQueue.mBufferType = kAndroidBufferTypeMpeg2Ts;
1208
1209 // Set the container type for the StreamInformation interface
1210 XAMediaContainerInformation *containerInfo =
1211 (XAMediaContainerInformation*)
1212 // always storing container info at index 0, as per spec
1213 &(thiz->mStreamInfo.mStreamInfoTable.itemAt(0).
1214 containerInfo);
1215 containerInfo->containerType = XA_CONTAINERTYPE_MPEG_TS;
1216 // there are no streams at this stage
1217 containerInfo->numStreams = 0;
1218
1219 } else {
1220 thiz->mAndroidBufferQueue.mBufferType = kAndroidBufferTypeInvalid;
1221 SL_LOGE("Invalid buffer type in Android Buffer Queue");
1222 result = SL_RESULT_CONTENT_UNSUPPORTED;
1223 }
1224
1225 // initialize ABQ memory
1226 thiz->mAndroidBufferQueue.mBufferArray = (AdvancedBufferHeader *)
1227 malloc( (nbBuffers + 1) * sizeof(AdvancedBufferHeader));
1228 if (NULL == thiz->mAndroidBufferQueue.mBufferArray) {
1229 result = SL_RESULT_MEMORY_FAILURE;
1230 break;
1231 } else {
1232 for (XAuint16 i=0 ; i<(nbBuffers + 1) ; i++) {
1233 thiz->mAndroidBufferQueue.mBufferArray[i].mDataBuffer = NULL;
1234 thiz->mAndroidBufferQueue.mBufferArray[i].mDataSize = 0;
1235 thiz->mAndroidBufferQueue.mBufferArray[i].mDataSizeConsumed = 0;
1236 thiz->mAndroidBufferQueue.mBufferArray[i].mBufferContext = NULL;
1237 thiz->mAndroidBufferQueue.mBufferArray[i].mBufferState =
1238 XA_ANDROIDBUFFERQUEUEEVENT_NONE;
1239 switch (thiz->mAndroidBufferQueue.mBufferType) {
1240 case kAndroidBufferTypeMpeg2Ts:
1241 thiz->mAndroidBufferQueue.mBufferArray[i].mItems.mTsCmdData.
1242 mTsCmdCode = ANDROID_MP2TSEVENT_NONE;
1243 thiz->mAndroidBufferQueue.mBufferArray[i].mItems.mTsCmdData.
1244 mPts = 0;
1245 break;
1246 default:
1247 result = SL_RESULT_CONTENT_UNSUPPORTED;
1248 break;
1249 }
1250 }
1251 thiz->mAndroidBufferQueue.mFront =
1252 thiz->mAndroidBufferQueue.mBufferArray;
1253 thiz->mAndroidBufferQueue.mRear =
1254 thiz->mAndroidBufferQueue.mBufferArray;
1255 }
1256
1257 thiz->mAndroidBufferQueue.mNumBuffers = nbBuffers;
1258
1259 }
1260 #endif
1261
1262 // used to store the data source of our audio player
1263 thiz->mDynamicSource.mDataSource = &thiz->mDataSource.u.mSource;
1264
1265 // platform-specific initialization
1266 #ifdef ANDROID
1267 android_Player_create(thiz);
1268 #endif
1269
1270 } while (0);
1271
1272 if (XA_RESULT_SUCCESS != result) {
1273 IObject_Destroy(&thiz->mObject.mItf);
1274 } else {
1275 IObject_Publish(&thiz->mObject);
1276 // return the new media player object
1277 *pPlayer = (XAObjectItf) &thiz->mObject.mItf;
1278 }
1279
1280 }
1281 }
1282
1283 }
1284
1285 XA_LEAVE_INTERFACE
1286 }
1287
1288
IEngine_CreateMediaRecorder(XAEngineItf self,XAObjectItf * pRecorder,XADataSource * pAudioSrc,XADataSource * pImageVideoSrc,XADataSink * pDataSnk,XAuint32 numInterfaces,const XAInterfaceID * pInterfaceIds,const XAboolean * pInterfaceRequired)1289 static XAresult IEngine_CreateMediaRecorder(XAEngineItf self, XAObjectItf *pRecorder,
1290 XADataSource *pAudioSrc, XADataSource *pImageVideoSrc,
1291 XADataSink *pDataSnk, XAuint32 numInterfaces, const XAInterfaceID *pInterfaceIds,
1292 const XAboolean *pInterfaceRequired)
1293 {
1294 XA_ENTER_INTERFACE
1295
1296 //IXAEngine *thiz = (IXAEngine *) self;
1297 result = SL_RESULT_FEATURE_UNSUPPORTED;
1298
1299 #if 0
1300 "pAudioSrc", pAudioSrc,
1301 "pImageVideoSrc", pImageVideoSrc,
1302 "pDataSink", pDataSnk,
1303 #endif
1304
1305 XA_LEAVE_INTERFACE
1306 }
1307
1308
IXAEngine_CreateOutputMix(XAEngineItf self,XAObjectItf * pMix,XAuint32 numInterfaces,const XAInterfaceID * pInterfaceIds,const XAboolean * pInterfaceRequired)1309 static XAresult IXAEngine_CreateOutputMix(XAEngineItf self, XAObjectItf *pMix,
1310 XAuint32 numInterfaces, const XAInterfaceID *pInterfaceIds,
1311 const XAboolean *pInterfaceRequired)
1312 {
1313 // forward to OpenSL ES
1314 return IEngine_CreateOutputMix(&((CEngine *) ((IXAEngine *) self)->mThis)->mEngine.mItf,
1315 (SLObjectItf *) pMix, numInterfaces, (const SLInterfaceID *) pInterfaceIds,
1316 (const SLboolean *) pInterfaceRequired);
1317 }
1318
1319
IXAEngine_CreateMetadataExtractor(XAEngineItf self,XAObjectItf * pMetadataExtractor,XADataSource * pDataSource,XAuint32 numInterfaces,const XAInterfaceID * pInterfaceIds,const XAboolean * pInterfaceRequired)1320 static XAresult IXAEngine_CreateMetadataExtractor(XAEngineItf self, XAObjectItf *pMetadataExtractor,
1321 XADataSource *pDataSource, XAuint32 numInterfaces,
1322 const XAInterfaceID *pInterfaceIds, const XAboolean *pInterfaceRequired)
1323 {
1324 // forward to OpenSL ES
1325 return IEngine_CreateMetadataExtractor(&((CEngine *) ((IXAEngine *) self)->mThis)->mEngine.mItf,
1326 (SLObjectItf *) pMetadataExtractor, (SLDataSource *) pDataSource, numInterfaces,
1327 (const SLInterfaceID *) pInterfaceIds, (const SLboolean *) pInterfaceRequired);
1328 }
1329
1330
IXAEngine_CreateExtensionObject(XAEngineItf self,XAObjectItf * pObject,void * pParameters,XAuint32 objectID,XAuint32 numInterfaces,const XAInterfaceID * pInterfaceIds,const XAboolean * pInterfaceRequired)1331 static XAresult IXAEngine_CreateExtensionObject(XAEngineItf self, XAObjectItf *pObject,
1332 void *pParameters, XAuint32 objectID, XAuint32 numInterfaces,
1333 const XAInterfaceID *pInterfaceIds, const XAboolean *pInterfaceRequired)
1334 {
1335 // forward to OpenSL ES
1336 return IEngine_CreateExtensionObject(&((CEngine *) ((IXAEngine *) self)->mThis)->mEngine.mItf,
1337 (SLObjectItf *) pObject, pParameters, objectID, numInterfaces,
1338 (const SLInterfaceID *) pInterfaceIds, (const SLboolean *) pInterfaceRequired);
1339 }
1340
1341
IEngine_GetImplementationInfo(XAEngineItf self,XAuint32 * pMajor,XAuint32 * pMinor,XAuint32 * pStep,const XAchar * pImplementationText)1342 static XAresult IEngine_GetImplementationInfo(XAEngineItf self, XAuint32 *pMajor, XAuint32 *pMinor,
1343 XAuint32 *pStep, /* XAuint32 nImplementationTextSize, */ const XAchar *pImplementationText)
1344 {
1345 XA_ENTER_INTERFACE
1346
1347 //IXAEngine *thiz = (IXAEngine *) self;
1348 result = SL_RESULT_FEATURE_UNSUPPORTED;
1349
1350 XA_LEAVE_INTERFACE
1351 }
1352
1353
IXAEngine_QuerySupportedProfiles(XAEngineItf self,XAint16 * pProfilesSupported)1354 static XAresult IXAEngine_QuerySupportedProfiles(XAEngineItf self, XAint16 *pProfilesSupported)
1355 {
1356 XA_ENTER_INTERFACE
1357
1358 if (NULL == pProfilesSupported) {
1359 result = XA_RESULT_PARAMETER_INVALID;
1360 } else {
1361 #if 1
1362 *pProfilesSupported = 0;
1363 // the code below was copied from OpenSL ES and needs to be adapted for OpenMAX AL.
1364 #else
1365 // The generic implementation doesn't implement any of the profiles, they shouldn't be
1366 // declared as supported. Also exclude the fake profiles BASE and OPTIONAL.
1367 *pProfilesSupported = USE_PROFILES &
1368 (USE_PROFILES_GAME | USE_PROFILES_MUSIC | USE_PROFILES_PHONE);
1369 #endif
1370 result = XA_RESULT_SUCCESS;
1371 }
1372
1373 XA_LEAVE_INTERFACE
1374 }
1375
1376
IXAEngine_QueryNumSupportedInterfaces(XAEngineItf self,XAuint32 objectID,XAuint32 * pNumSupportedInterfaces)1377 static XAresult IXAEngine_QueryNumSupportedInterfaces(XAEngineItf self, XAuint32 objectID,
1378 XAuint32 *pNumSupportedInterfaces)
1379 {
1380 // forward to OpenSL ES
1381 return IEngine_QueryNumSupportedInterfaces(
1382 &((CEngine *) ((IXAEngine *) self)->mThis)->mEngine.mItf, objectID,
1383 pNumSupportedInterfaces);
1384 }
1385
1386
IXAEngine_QuerySupportedInterfaces(XAEngineItf self,XAuint32 objectID,XAuint32 index,XAInterfaceID * pInterfaceId)1387 static XAresult IXAEngine_QuerySupportedInterfaces(XAEngineItf self, XAuint32 objectID,
1388 XAuint32 index, XAInterfaceID *pInterfaceId)
1389 {
1390 // forward to OpenSL ES
1391 return IEngine_QuerySupportedInterfaces(
1392 &((CEngine *) ((IXAEngine *) self)->mThis)->mEngine.mItf, objectID, index,
1393 (SLInterfaceID *) pInterfaceId);
1394 }
1395
1396
IXAEngine_QueryNumSupportedExtensions(XAEngineItf self,XAuint32 * pNumExtensions)1397 static XAresult IXAEngine_QueryNumSupportedExtensions(XAEngineItf self, XAuint32 *pNumExtensions)
1398 {
1399 // forward to OpenSL ES
1400 return IEngine_QueryNumSupportedExtensions(
1401 &((CEngine *) ((IXAEngine *) self)->mThis)->mEngine.mItf, pNumExtensions);
1402 }
1403
1404
IXAEngine_QuerySupportedExtension(XAEngineItf self,XAuint32 index,XAchar * pExtensionName,XAint16 * pNameLength)1405 static XAresult IXAEngine_QuerySupportedExtension(XAEngineItf self, XAuint32 index,
1406 XAchar *pExtensionName, XAint16 *pNameLength)
1407 {
1408 // forward to OpenSL ES
1409 return IEngine_QuerySupportedExtension(&((CEngine *) ((IXAEngine *) self)->mThis)->mEngine.mItf,
1410 index, pExtensionName, (SLint16 *) pNameLength);
1411 }
1412
1413
IXAEngine_IsExtensionSupported(XAEngineItf self,const XAchar * pExtensionName,XAboolean * pSupported)1414 static XAresult IXAEngine_IsExtensionSupported(XAEngineItf self, const XAchar *pExtensionName,
1415 XAboolean *pSupported)
1416 {
1417 // forward to OpenSL ES
1418 return IEngine_IsExtensionSupported(&((CEngine *) ((IXAEngine *) self)->mThis)->mEngine.mItf,
1419 pExtensionName, pSupported);
1420 }
1421
1422
IXAEngine_QueryLEDCapabilities(XAEngineItf self,XAuint32 * pIndex,XAuint32 * pLEDDeviceID,XALEDDescriptor * pDescriptor)1423 static XAresult IXAEngine_QueryLEDCapabilities(XAEngineItf self, XAuint32 *pIndex,
1424 XAuint32 *pLEDDeviceID, XALEDDescriptor *pDescriptor)
1425 {
1426 // forward to OpenSL ES EngineCapabilities
1427 return (XAresult) IEngineCapabilities_QueryLEDCapabilities(
1428 &((CEngine *) ((IXAEngine *) self)->mThis)->mEngineCapabilities.mItf, pIndex,
1429 pLEDDeviceID, (SLLEDDescriptor *) pDescriptor);
1430 }
1431
1432
IXAEngine_QueryVibraCapabilities(XAEngineItf self,XAuint32 * pIndex,XAuint32 * pVibraDeviceID,XAVibraDescriptor * pDescriptor)1433 static XAresult IXAEngine_QueryVibraCapabilities(XAEngineItf self, XAuint32 *pIndex,
1434 XAuint32 *pVibraDeviceID, XAVibraDescriptor *pDescriptor)
1435 {
1436 // forward to OpenSL ES EngineCapabilities
1437 return (XAresult) IEngineCapabilities_QueryVibraCapabilities(
1438 &((CEngine *) ((IXAEngine *) self)->mThis)->mEngineCapabilities.mItf, pIndex,
1439 pVibraDeviceID, (SLVibraDescriptor *) pDescriptor);
1440 }
1441
1442
1443 // OpenMAX AL engine v-table
1444
1445 static const struct XAEngineItf_ IXAEngine_Itf = {
1446 IEngine_CreateCameraDevice,
1447 IEngine_CreateRadioDevice,
1448 IXAEngine_CreateLEDDevice,
1449 IXAEngine_CreateVibraDevice,
1450 IEngine_CreateMediaPlayer,
1451 IEngine_CreateMediaRecorder,
1452 IXAEngine_CreateOutputMix,
1453 IXAEngine_CreateMetadataExtractor,
1454 IXAEngine_CreateExtensionObject,
1455 IEngine_GetImplementationInfo,
1456 IXAEngine_QuerySupportedProfiles,
1457 IXAEngine_QueryNumSupportedInterfaces,
1458 IXAEngine_QuerySupportedInterfaces,
1459 IXAEngine_QueryNumSupportedExtensions,
1460 IXAEngine_QuerySupportedExtension,
1461 IXAEngine_IsExtensionSupported,
1462 IXAEngine_QueryLEDCapabilities,
1463 IXAEngine_QueryVibraCapabilities
1464 };
1465
1466
IXAEngine_init(void * self)1467 void IXAEngine_init(void *self)
1468 {
1469 IXAEngine *thiz = (IXAEngine *) self;
1470 thiz->mItf = &IXAEngine_Itf;
1471 }
1472
1473
IXAEngine_deinit(void * self)1474 void IXAEngine_deinit(void *self)
1475 {
1476 }
1477