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