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