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