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