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