IEngine.c revision e878c470cf58c8654d613ab2449468b44a90d6e5
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    "ANDROID_SDK_LEVEL_12", // Android 3.0+ aka "Honeycomb MR1"
851#else
852    "WILHELM_DESKTOP",
853#endif
854};
855
856
857static SLresult IEngine_QueryNumSupportedExtensions(SLEngineItf self, SLuint32 *pNumExtensions)
858{
859    SL_ENTER_INTERFACE
860
861    if (NULL == pNumExtensions) {
862        result = SL_RESULT_PARAMETER_INVALID;
863    } else {
864        *pNumExtensions = sizeof(extensionNames) / sizeof(extensionNames[0]);
865        result = SL_RESULT_SUCCESS;
866    }
867
868    SL_LEAVE_INTERFACE
869}
870
871
872static SLresult IEngine_QuerySupportedExtension(SLEngineItf self,
873    SLuint32 index, SLchar *pExtensionName, SLint16 *pNameLength)
874{
875    SL_ENTER_INTERFACE
876
877    if (NULL == pNameLength) {
878        result = SL_RESULT_PARAMETER_INVALID;
879    } else {
880        size_t actualNameLength;
881        unsigned numExtensions = sizeof(extensionNames) / sizeof(extensionNames[0]);
882        if (index >= numExtensions) {
883            actualNameLength = 0;
884            result = SL_RESULT_PARAMETER_INVALID;
885        } else {
886            const char *extensionName = extensionNames[index];
887            actualNameLength = strlen(extensionName) + 1;
888            if (NULL == pExtensionName) {
889                // application is querying the name length in order to allocate a buffer
890                result = SL_RESULT_SUCCESS;
891            } else {
892                SLint16 availableNameLength = *pNameLength;
893                if (0 >= availableNameLength) {
894                    // there is not even room for the terminating NUL
895                    result = SL_RESULT_BUFFER_INSUFFICIENT;
896                } else if (actualNameLength > (size_t) availableNameLength) {
897                    // "no invalid strings are written. That is, the null-terminator always exists"
898                    memcpy(pExtensionName, extensionName, (size_t) availableNameLength - 1);
899                    pExtensionName[(size_t) availableNameLength - 1] = '\0';
900                    result = SL_RESULT_BUFFER_INSUFFICIENT;
901                } else {
902                    memcpy(pExtensionName, extensionName, actualNameLength);
903                    result = SL_RESULT_SUCCESS;
904                }
905            }
906        }
907        *pNameLength = actualNameLength;
908    }
909
910    SL_LEAVE_INTERFACE
911}
912
913
914static SLresult IEngine_IsExtensionSupported(SLEngineItf self,
915    const SLchar *pExtensionName, SLboolean *pSupported)
916{
917    SL_ENTER_INTERFACE
918
919    if (NULL == pSupported) {
920        result = SL_RESULT_PARAMETER_INVALID;
921    } else {
922        SLboolean isSupported = SL_BOOLEAN_FALSE;
923        if (NULL == pExtensionName) {
924            result = SL_RESULT_PARAMETER_INVALID;
925        } else {
926            unsigned numExtensions = sizeof(extensionNames) / sizeof(extensionNames[0]);
927            unsigned i;
928            for (i = 0; i < numExtensions; ++i) {
929                if (!strcmp((const char *) pExtensionName, extensionNames[i])) {
930                    isSupported = SL_BOOLEAN_TRUE;
931                    break;
932                }
933            }
934            result = SL_RESULT_SUCCESS;
935        }
936        *pSupported = isSupported;
937    }
938
939    SL_LEAVE_INTERFACE
940}
941
942
943static const struct SLEngineItf_ IEngine_Itf = {
944    IEngine_CreateLEDDevice,
945    IEngine_CreateVibraDevice,
946    IEngine_CreateAudioPlayer,
947    IEngine_CreateAudioRecorder,
948    IEngine_CreateMidiPlayer,
949    IEngine_CreateListener,
950    IEngine_Create3DGroup,
951    IEngine_CreateOutputMix,
952    IEngine_CreateMetadataExtractor,
953    IEngine_CreateExtensionObject,
954    IEngine_QueryNumSupportedInterfaces,
955    IEngine_QuerySupportedInterfaces,
956    IEngine_QueryNumSupportedExtensions,
957    IEngine_QuerySupportedExtension,
958    IEngine_IsExtensionSupported
959};
960
961void IEngine_init(void *self)
962{
963    IEngine *thiz = (IEngine *) self;
964    thiz->mItf = &IEngine_Itf;
965    // mLossOfControlGlobal is initialized in slCreateEngine
966#ifdef USE_SDL
967    thiz->mOutputMix = NULL;
968#endif
969    thiz->mInstanceCount = 1; // ourself
970    thiz->mInstanceMask = 0;
971    thiz->mChangedMask = 0;
972    unsigned i;
973    for (i = 0; i < MAX_INSTANCE; ++i) {
974        thiz->mInstances[i] = NULL;
975    }
976    thiz->mShutdown = SL_BOOLEAN_FALSE;
977    thiz->mShutdownAck = SL_BOOLEAN_FALSE;
978}
979
980void IEngine_deinit(void *self)
981{
982}
983
984
985// OpenMAX AL Engine
986
987
988static XAresult IEngine_CreateCameraDevice(XAEngineItf self, XAObjectItf *pDevice,
989        XAuint32 deviceID, 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 IEngine_CreateRadioDevice(XAEngineItf self, XAObjectItf *pDevice,
1002        XAuint32 numInterfaces, const XAInterfaceID *pInterfaceIds,
1003        const XAboolean *pInterfaceRequired)
1004{
1005    XA_ENTER_INTERFACE
1006
1007    //IXAEngine *thiz = (IXAEngine *) self;
1008    result = SL_RESULT_FEATURE_UNSUPPORTED;
1009
1010    XA_LEAVE_INTERFACE
1011}
1012
1013
1014static XAresult IXAEngine_CreateLEDDevice(XAEngineItf self, XAObjectItf *pDevice, XAuint32 deviceID,
1015        XAuint32 numInterfaces, const XAInterfaceID *pInterfaceIds,
1016        const XAboolean *pInterfaceRequired)
1017{
1018    // forward to OpenSL ES
1019    return IEngine_CreateLEDDevice(&((CEngine *) ((IXAEngine *) self)->mThis)->mEngine.mItf,
1020            (SLObjectItf *) pDevice, deviceID, numInterfaces, (const SLInterfaceID *) pInterfaceIds,
1021            (const SLboolean *) pInterfaceRequired);
1022}
1023
1024
1025static XAresult IXAEngine_CreateVibraDevice(XAEngineItf self, XAObjectItf *pDevice,
1026        XAuint32 deviceID, XAuint32 numInterfaces, const XAInterfaceID *pInterfaceIds,
1027        const XAboolean *pInterfaceRequired)
1028{
1029    // forward to OpenSL ES
1030    return IEngine_CreateVibraDevice(&((CEngine *) ((IXAEngine *) self)->mThis)->mEngine.mItf,
1031            (SLObjectItf *) pDevice, deviceID, numInterfaces, (const SLInterfaceID *) pInterfaceIds,
1032            (const SLboolean *) pInterfaceRequired);
1033}
1034
1035
1036static XAresult IEngine_CreateMediaPlayer(XAEngineItf self, XAObjectItf *pPlayer,
1037        XADataSource *pDataSrc, XADataSource *pBankSrc, XADataSink *pAudioSnk,
1038        XADataSink *pImageVideoSnk, XADataSink *pVibra, XADataSink *pLEDArray,
1039        XAuint32 numInterfaces, const XAInterfaceID *pInterfaceIds,
1040        const XAboolean *pInterfaceRequired)
1041{
1042    XA_ENTER_INTERFACE
1043
1044    if (NULL == pPlayer) {
1045        result = XA_RESULT_PARAMETER_INVALID;
1046    } else {
1047        *pPlayer = NULL;
1048        unsigned exposedMask;
1049        const ClassTable *pCMediaPlayer_class = objectIDtoClass(XA_OBJECTID_MEDIAPLAYER);
1050        assert(NULL != pCMediaPlayer_class);
1051        result = checkInterfaces(pCMediaPlayer_class, numInterfaces,
1052                (const SLInterfaceID *) pInterfaceIds, pInterfaceRequired, &exposedMask);
1053        if (XA_RESULT_SUCCESS == result) {
1054
1055            // Construct our new MediaPlayer instance
1056            CMediaPlayer *thiz = (CMediaPlayer *) construct(pCMediaPlayer_class, exposedMask,
1057                    &((CEngine *) ((IXAEngine *) self)->mThis)->mEngine.mItf);
1058            if (NULL == thiz) {
1059                result = XA_RESULT_MEMORY_FAILURE;
1060            } else {
1061
1062                do {
1063
1064                    // Initialize private fields not associated with an interface
1065
1066                    // Default data source in case of failure in checkDataSource
1067                    thiz->mDataSource.mLocator.mLocatorType = SL_DATALOCATOR_NULL;
1068                    thiz->mDataSource.mFormat.mFormatType = XA_DATAFORMAT_NULL;
1069
1070                    // Default andio and image sink in case of failure in checkDataSink
1071                    thiz->mAudioSink.mLocator.mLocatorType = XA_DATALOCATOR_NULL;
1072                    thiz->mAudioSink.mFormat.mFormatType = XA_DATAFORMAT_NULL;
1073                    thiz->mImageVideoSink.mLocator.mLocatorType = XA_DATALOCATOR_NULL;
1074                    thiz->mImageVideoSink.mFormat.mFormatType = XA_DATAFORMAT_NULL;
1075
1076                    // More default values, in case destructor needs to be called early
1077                    thiz->mDirectLevel = 0;
1078
1079                    // (assume calloc or memset 0 during allocation)
1080                    // placement new
1081#ifdef ANDROID
1082                    // FIXME unnecessary once those fields are encapsulated in one class, rather
1083                    //   than a structure
1084                    (void) new (&thiz->mAVPlayer) android::sp<android::GenericPlayer>();
1085#endif
1086
1087                    // Check the source and sink parameters against generic constraints
1088
1089                    result = checkDataSource("pDataSrc", (const SLDataSource *) pDataSrc,
1090                            &thiz->mDataSource, DATALOCATOR_MASK_URI
1091#ifdef ANDROID
1092                            | DATALOCATOR_MASK_ANDROIDFD
1093                            | DATALOCATOR_MASK_ANDROIDBUFFERQUEUE
1094#endif
1095                            , DATAFORMAT_MASK_MIME);
1096                    if (XA_RESULT_SUCCESS != result) {
1097                        break;
1098                    }
1099
1100                    result = checkDataSource("pBankSrc", (const SLDataSource *) pBankSrc,
1101                            &thiz->mBankSource, DATALOCATOR_MASK_NULL | DATALOCATOR_MASK_URI |
1102                            DATALOCATOR_MASK_ADDRESS, DATAFORMAT_MASK_NULL);
1103                    if (XA_RESULT_SUCCESS != result) {
1104                        break;
1105                    }
1106
1107                    result = checkDataSink("pAudioSnk", (const SLDataSink *) pAudioSnk,
1108                            &thiz->mAudioSink, DATALOCATOR_MASK_OUTPUTMIX, DATAFORMAT_MASK_NULL);
1109                    if (XA_RESULT_SUCCESS != result) {
1110                        break;
1111                    }
1112
1113                    result = checkDataSink("pImageVideoSnk", (const SLDataSink *) pImageVideoSnk,
1114                            &thiz->mImageVideoSink, DATALOCATOR_MASK_NATIVEDISPLAY,
1115                            DATAFORMAT_MASK_NULL);
1116                    if (XA_RESULT_SUCCESS != result) {
1117                        break;
1118                    }
1119
1120                    result = checkDataSink("pVibra", (const SLDataSink *) pVibra, &thiz->mVibraSink,
1121                            DATALOCATOR_MASK_NULL | DATALOCATOR_MASK_IODEVICE,
1122                            DATAFORMAT_MASK_NULL);
1123                    if (XA_RESULT_SUCCESS != result) {
1124                        break;
1125                    }
1126
1127                    result = checkDataSink("pLEDArray", (const SLDataSink *) pLEDArray,
1128                            &thiz->mLEDArraySink, DATALOCATOR_MASK_NULL | DATALOCATOR_MASK_IODEVICE,
1129                            DATAFORMAT_MASK_NULL);
1130                    if (XA_RESULT_SUCCESS != result) {
1131                        break;
1132                    }
1133
1134                    // Unsafe to ever refer to application pointers again
1135                    pDataSrc = NULL;
1136                    pBankSrc = NULL;
1137                    pAudioSnk = NULL;
1138                    pImageVideoSnk = NULL;
1139                    pVibra = NULL;
1140                    pLEDArray = NULL;
1141
1142                    // Check that the requested interfaces are compatible with the data source
1143                    // FIXME implement
1144
1145                    // check the source and sink parameters against platform support
1146#ifdef ANDROID
1147                    result = android_Player_checkSourceSink(thiz);
1148                    if (XA_RESULT_SUCCESS != result) {
1149                        break;
1150                    }
1151#endif
1152
1153#ifdef ANDROID
1154                    // AndroidBufferQueue-specific initialization
1155                    if (XA_DATALOCATOR_ANDROIDBUFFERQUEUE ==
1156                            thiz->mDataSource.mLocator.mLocatorType) {
1157                        XAuint16 nbBuffers = (XAuint16) thiz->mDataSource.mLocator.mABQ.numBuffers;
1158
1159                        // Avoid possible integer overflow during multiplication; this arbitrary
1160                        // maximum is big enough to not interfere with real applications, but
1161                        // small enough to not overflow.
1162                        if (nbBuffers >= 256) {
1163                            result = SL_RESULT_MEMORY_FAILURE;
1164                            break;
1165                        }
1166
1167                        // initialize ABQ buffer type
1168                        // assert below has been checked in android_audioPlayer_checkSourceSink
1169                        assert(XA_DATAFORMAT_MIME == thiz->mDataSource.mFormat.mFormatType);
1170                        if (XA_CONTAINERTYPE_MPEG_TS ==
1171                                thiz->mDataSource.mFormat.mMIME.containerType) {
1172                            thiz->mAndroidBufferQueue.mBufferType = kAndroidBufferTypeMpeg2Ts;
1173
1174                            // Set the container type for the StreamInformation interface
1175                            XAMediaContainerInformation *containerInfo =
1176                                    (XAMediaContainerInformation*)
1177                                        // always storing container info at index 0, as per spec
1178                                        &(thiz->mStreamInfo.mStreamInfoTable.itemAt(0).
1179                                                containerInfo);
1180                            containerInfo->containerType = XA_CONTAINERTYPE_MPEG_TS;
1181                            // there are no streams at this stage
1182                            containerInfo->numStreams = 0;
1183
1184                        } else {
1185                            thiz->mAndroidBufferQueue.mBufferType = kAndroidBufferTypeInvalid;
1186                            SL_LOGE("Invalid buffer type in Android Buffer Queue");
1187                            result = SL_RESULT_CONTENT_UNSUPPORTED;
1188                        }
1189
1190                        // initialize ABQ memory
1191                        thiz->mAndroidBufferQueue.mBufferArray = (AdvancedBufferHeader *)
1192                                    malloc( (nbBuffers + 1) * sizeof(AdvancedBufferHeader));
1193                        if (NULL == thiz->mAndroidBufferQueue.mBufferArray) {
1194                            result = SL_RESULT_MEMORY_FAILURE;
1195                            break;
1196                        } else {
1197                            for (XAuint16 i=0 ; i<(nbBuffers + 1) ; i++) {
1198                                thiz->mAndroidBufferQueue.mBufferArray[i].mDataBuffer = NULL;
1199                                thiz->mAndroidBufferQueue.mBufferArray[i].mDataSize = 0;
1200                                thiz->mAndroidBufferQueue.mBufferArray[i].mDataSizeConsumed = 0;
1201                                thiz->mAndroidBufferQueue.mBufferArray[i].mBufferContext = NULL;
1202                                thiz->mAndroidBufferQueue.mBufferArray[i].mBufferState =
1203                                        XA_ANDROIDBUFFERQUEUEEVENT_NONE;
1204                                switch (thiz->mAndroidBufferQueue.mBufferType) {
1205                                  case kAndroidBufferTypeMpeg2Ts:
1206                                    thiz->mAndroidBufferQueue.mBufferArray[i].mItems.mTsCmdData.
1207                                            mTsCmdCode = ANDROID_MP2TSEVENT_NONE;
1208                                    thiz->mAndroidBufferQueue.mBufferArray[i].mItems.mTsCmdData.
1209                                            mPts = 0;
1210                                    break;
1211                                  default:
1212                                    result = SL_RESULT_CONTENT_UNSUPPORTED;
1213                                    break;
1214                                }
1215                            }
1216                            thiz->mAndroidBufferQueue.mFront =
1217                                    thiz->mAndroidBufferQueue.mBufferArray;
1218                            thiz->mAndroidBufferQueue.mRear =
1219                                    thiz->mAndroidBufferQueue.mBufferArray;
1220                        }
1221
1222                        thiz->mAndroidBufferQueue.mNumBuffers = nbBuffers;
1223
1224                    }
1225#endif
1226
1227                    // used to store the data source of our audio player
1228                    thiz->mDynamicSource.mDataSource = &thiz->mDataSource.u.mSource;
1229
1230                    // platform-specific initialization
1231#ifdef ANDROID
1232                    android_Player_create(thiz);
1233#endif
1234
1235                } while (0);
1236
1237                if (XA_RESULT_SUCCESS != result) {
1238                    IObject_Destroy(&thiz->mObject.mItf);
1239                } else {
1240                    IObject_Publish(&thiz->mObject);
1241                    // return the new media player object
1242                    *pPlayer = (XAObjectItf) &thiz->mObject.mItf;
1243                }
1244
1245            }
1246        }
1247
1248    }
1249
1250    XA_LEAVE_INTERFACE
1251}
1252
1253
1254static XAresult IEngine_CreateMediaRecorder(XAEngineItf self, XAObjectItf *pRecorder,
1255        XADataSource *pAudioSrc, XADataSource *pImageVideoSrc,
1256        XADataSink *pDataSnk, XAuint32 numInterfaces, const XAInterfaceID *pInterfaceIds,
1257        const XAboolean *pInterfaceRequired)
1258{
1259    XA_ENTER_INTERFACE
1260
1261    //IXAEngine *thiz = (IXAEngine *) self;
1262    result = SL_RESULT_FEATURE_UNSUPPORTED;
1263
1264#if 0
1265    "pAudioSrc", pAudioSrc,
1266    "pImageVideoSrc", pImageVideoSrc,
1267    "pDataSink", pDataSnk,
1268#endif
1269
1270    XA_LEAVE_INTERFACE
1271}
1272
1273
1274static XAresult IXAEngine_CreateOutputMix(XAEngineItf self, XAObjectItf *pMix,
1275        XAuint32 numInterfaces, const XAInterfaceID *pInterfaceIds,
1276        const XAboolean *pInterfaceRequired)
1277{
1278    // forward to OpenSL ES
1279    return IEngine_CreateOutputMix(&((CEngine *) ((IXAEngine *) self)->mThis)->mEngine.mItf,
1280            (SLObjectItf *) pMix, numInterfaces, (const SLInterfaceID *) pInterfaceIds,
1281            (const SLboolean *) pInterfaceRequired);
1282}
1283
1284
1285static XAresult IXAEngine_CreateMetadataExtractor(XAEngineItf self, XAObjectItf *pMetadataExtractor,
1286            XADataSource *pDataSource, XAuint32 numInterfaces,
1287            const XAInterfaceID *pInterfaceIds, const XAboolean *pInterfaceRequired)
1288{
1289    // forward to OpenSL ES
1290    return IEngine_CreateMetadataExtractor(&((CEngine *) ((IXAEngine *) self)->mThis)->mEngine.mItf,
1291            (SLObjectItf *) pMetadataExtractor, (SLDataSource *) pDataSource, numInterfaces,
1292            (const SLInterfaceID *) pInterfaceIds, (const SLboolean *) pInterfaceRequired);
1293}
1294
1295
1296static XAresult IXAEngine_CreateExtensionObject(XAEngineItf self, XAObjectItf *pObject,
1297            void *pParameters, XAuint32 objectID, XAuint32 numInterfaces,
1298            const XAInterfaceID *pInterfaceIds, const XAboolean *pInterfaceRequired)
1299{
1300    // forward to OpenSL ES
1301    return IEngine_CreateExtensionObject(&((CEngine *) ((IXAEngine *) self)->mThis)->mEngine.mItf,
1302            (SLObjectItf *) pObject, pParameters, objectID, numInterfaces,
1303            (const SLInterfaceID *) pInterfaceIds, (const SLboolean *) pInterfaceRequired);
1304}
1305
1306
1307static XAresult IEngine_GetImplementationInfo(XAEngineItf self, XAuint32 *pMajor, XAuint32 *pMinor,
1308        XAuint32 *pStep, /* XAuint32 nImplementationTextSize, */ const XAchar *pImplementationText)
1309{
1310    XA_ENTER_INTERFACE
1311
1312    //IXAEngine *thiz = (IXAEngine *) self;
1313    result = SL_RESULT_FEATURE_UNSUPPORTED;
1314
1315    XA_LEAVE_INTERFACE
1316}
1317
1318
1319static XAresult IXAEngine_QuerySupportedProfiles(XAEngineItf self, XAint16 *pProfilesSupported)
1320{
1321    XA_ENTER_INTERFACE
1322
1323    if (NULL == pProfilesSupported) {
1324        result = XA_RESULT_PARAMETER_INVALID;
1325    } else {
1326#if 1
1327        *pProfilesSupported = 0;
1328        // the code below was copied from OpenSL ES and needs to be adapted for OpenMAX AL.
1329#else
1330        // The generic implementation doesn't implement any of the profiles, they shouldn't be
1331        // declared as supported. Also exclude the fake profiles BASE and OPTIONAL.
1332        *pProfilesSupported = USE_PROFILES &
1333                (USE_PROFILES_GAME | USE_PROFILES_MUSIC | USE_PROFILES_PHONE);
1334#endif
1335        result = XA_RESULT_SUCCESS;
1336    }
1337
1338    XA_LEAVE_INTERFACE
1339}
1340
1341
1342static XAresult IXAEngine_QueryNumSupportedInterfaces(XAEngineItf self, XAuint32 objectID,
1343        XAuint32 *pNumSupportedInterfaces)
1344{
1345    // forward to OpenSL ES
1346    return IEngine_QueryNumSupportedInterfaces(
1347            &((CEngine *) ((IXAEngine *) self)->mThis)->mEngine.mItf, objectID,
1348            pNumSupportedInterfaces);
1349}
1350
1351
1352static XAresult IXAEngine_QuerySupportedInterfaces(XAEngineItf self, XAuint32 objectID,
1353        XAuint32 index, XAInterfaceID *pInterfaceId)
1354{
1355    // forward to OpenSL ES
1356    return IEngine_QuerySupportedInterfaces(
1357            &((CEngine *) ((IXAEngine *) self)->mThis)->mEngine.mItf, objectID, index,
1358            (SLInterfaceID *) pInterfaceId);
1359}
1360
1361
1362static XAresult IXAEngine_QueryNumSupportedExtensions(XAEngineItf self, XAuint32 *pNumExtensions)
1363{
1364    // forward to OpenSL ES
1365    return IEngine_QueryNumSupportedExtensions(
1366            &((CEngine *) ((IXAEngine *) self)->mThis)->mEngine.mItf, pNumExtensions);
1367}
1368
1369
1370static XAresult IXAEngine_QuerySupportedExtension(XAEngineItf self, XAuint32 index,
1371        XAchar *pExtensionName, XAint16 *pNameLength)
1372{
1373    // forward to OpenSL ES
1374    return IEngine_QuerySupportedExtension(&((CEngine *) ((IXAEngine *) self)->mThis)->mEngine.mItf,
1375            index, pExtensionName, (SLint16 *) pNameLength);
1376}
1377
1378
1379static XAresult IXAEngine_IsExtensionSupported(XAEngineItf self, const XAchar *pExtensionName,
1380        XAboolean *pSupported)
1381{
1382    // forward to OpenSL ES
1383    return IEngine_IsExtensionSupported(&((CEngine *) ((IXAEngine *) self)->mThis)->mEngine.mItf,
1384            pExtensionName, pSupported);
1385}
1386
1387
1388static XAresult IXAEngine_QueryLEDCapabilities(XAEngineItf self, XAuint32 *pIndex,
1389        XAuint32 *pLEDDeviceID, XALEDDescriptor *pDescriptor)
1390{
1391    // forward to OpenSL ES EngineCapabilities
1392    return (XAresult) IEngineCapabilities_QueryLEDCapabilities(
1393            &((CEngine *) ((IXAEngine *) self)->mThis)->mEngineCapabilities.mItf, pIndex,
1394            pLEDDeviceID, (SLLEDDescriptor *) pDescriptor);
1395}
1396
1397
1398static XAresult IXAEngine_QueryVibraCapabilities(XAEngineItf self, XAuint32 *pIndex,
1399        XAuint32 *pVibraDeviceID, XAVibraDescriptor *pDescriptor)
1400{
1401    // forward to OpenSL ES EngineCapabilities
1402    return (XAresult) IEngineCapabilities_QueryVibraCapabilities(
1403            &((CEngine *) ((IXAEngine *) self)->mThis)->mEngineCapabilities.mItf, pIndex,
1404            pVibraDeviceID, (SLVibraDescriptor *) pDescriptor);
1405}
1406
1407
1408// OpenMAX AL engine v-table
1409
1410static const struct XAEngineItf_ IXAEngine_Itf = {
1411    IEngine_CreateCameraDevice,
1412    IEngine_CreateRadioDevice,
1413    IXAEngine_CreateLEDDevice,
1414    IXAEngine_CreateVibraDevice,
1415    IEngine_CreateMediaPlayer,
1416    IEngine_CreateMediaRecorder,
1417    IXAEngine_CreateOutputMix,
1418    IXAEngine_CreateMetadataExtractor,
1419    IXAEngine_CreateExtensionObject,
1420    IEngine_GetImplementationInfo,
1421    IXAEngine_QuerySupportedProfiles,
1422    IXAEngine_QueryNumSupportedInterfaces,
1423    IXAEngine_QuerySupportedInterfaces,
1424    IXAEngine_QueryNumSupportedExtensions,
1425    IXAEngine_QuerySupportedExtension,
1426    IXAEngine_IsExtensionSupported,
1427    IXAEngine_QueryLEDCapabilities,
1428    IXAEngine_QueryVibraCapabilities
1429};
1430
1431
1432void IXAEngine_init(void *self)
1433{
1434    IXAEngine *thiz = (IXAEngine *) self;
1435    thiz->mItf = &IXAEngine_Itf;
1436}
1437
1438
1439void IXAEngine_deinit(void *self)
1440{
1441}
1442