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