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