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