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