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