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