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