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