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