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