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