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