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