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