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