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