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