IEngine.c revision 3c170255cc71942f310b676d968cf73328aa5d70
1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17/* Engine implementation */
18
19#include "sles_allinclusive.h"
20
21
22static SLresult IEngine_CreateLEDDevice(SLEngineItf self, SLObjectItf *pDevice, SLuint32 deviceID,
23    SLuint32 numInterfaces, const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired)
24{
25    SL_ENTER_INTERFACE
26
27    if (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        result = checkInterfaces(pCLEDDevice_class, numInterfaces, pInterfaceIds,
34            pInterfaceRequired, &exposedMask);
35        if (SL_RESULT_SUCCESS == result) {
36            CLEDDevice *this = (CLEDDevice *) construct(pCLEDDevice_class, exposedMask, self);
37            if (NULL == this) {
38                result = SL_RESULT_MEMORY_FAILURE;
39            } else {
40                this->mDeviceID = deviceID;
41                *pDevice = &this->mObject.mItf;
42            }
43        }
44    }
45
46    SL_LEAVE_INTERFACE
47}
48
49
50static SLresult IEngine_CreateVibraDevice(SLEngineItf self, SLObjectItf *pDevice, SLuint32 deviceID,
51    SLuint32 numInterfaces, const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired)
52{
53    SL_ENTER_INTERFACE
54
55    if (NULL == pDevice || SL_DEFAULTDEVICEID_VIBRA != deviceID) {
56        result = SL_RESULT_PARAMETER_INVALID;
57    } else {
58        *pDevice = NULL;
59        unsigned exposedMask;
60        const ClassTable *pCVibraDevice_class = objectIDtoClass(SL_OBJECTID_VIBRADEVICE);
61        result = checkInterfaces(pCVibraDevice_class, numInterfaces,
62            pInterfaceIds, pInterfaceRequired, &exposedMask);
63        if (SL_RESULT_SUCCESS == result) {
64            CVibraDevice *this = (CVibraDevice *) construct(pCVibraDevice_class, exposedMask, self);
65            if (NULL == this) {
66                result = SL_RESULT_MEMORY_FAILURE;
67            } else {
68                this->mDeviceID = deviceID;
69                *pDevice = &this->mObject.mItf;
70            }
71        }
72    }
73
74    SL_LEAVE_INTERFACE
75}
76
77
78static SLresult IEngine_CreateAudioPlayer(SLEngineItf self, SLObjectItf *pPlayer,
79    SLDataSource *pAudioSrc, SLDataSink *pAudioSnk, SLuint32 numInterfaces,
80    const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired)
81{
82    SL_ENTER_INTERFACE
83
84    if (NULL == pPlayer) {
85       result = SL_RESULT_PARAMETER_INVALID;
86    } else {
87        *pPlayer = NULL;
88        unsigned exposedMask;
89        const ClassTable *pCAudioPlayer_class = objectIDtoClass(SL_OBJECTID_AUDIOPLAYER);
90        result = checkInterfaces(pCAudioPlayer_class, numInterfaces,
91            pInterfaceIds, pInterfaceRequired, &exposedMask);
92        if (SL_RESULT_SUCCESS == result) {
93
94            // Construct our new AudioPlayer instance
95            CAudioPlayer *this = (CAudioPlayer *) construct(pCAudioPlayer_class, exposedMask, self);
96            if (NULL == this) {
97                result = SL_RESULT_MEMORY_FAILURE;
98            } else {
99
100                do {
101
102                    // Initialize private fields not associated with an interface
103                    this->mMuteMask = 0;
104                    this->mSoloMask = 0;
105                    // const, will be set later by the containing AudioPlayer or MidiPlayer
106                    this->mNumChannels = 0;
107                    this->mSampleRateMilliHz = 0;
108
109                    // Check the source and sink parameters against generic constraints,
110                    // and make a local copy of all parameters in case other application threads
111                    // change memory concurrently.
112
113                    result = checkDataSource(pAudioSrc, &this->mDataSource);
114                    if (SL_RESULT_SUCCESS != result) {
115                        break;
116                    }
117
118                    result = checkSourceFormatVsInterfacesCompatibility(&this->mDataSource,
119                            numInterfaces, pInterfaceIds, pInterfaceRequired);
120                    if (SL_RESULT_SUCCESS != result) {
121                        break;
122                    }
123
124                    result = checkDataSink(pAudioSnk, &this->mDataSink);
125                    if (SL_RESULT_SUCCESS != result) {
126                        break;
127                    }
128
129                    // check the audio source and sink parameters against platform support
130#ifdef ANDROID
131                    result = sles_to_android_checkAudioPlayerSourceSink(this);
132                    if (SL_RESULT_SUCCESS != result)
133                        break;
134#else
135                    {
136                    // FIXME This is b/c we init buffer queues in SndFile below, which is not always
137                    // present
138                    SLuint32 locatorType = *(SLuint32 *) pAudioSrc->pLocator;
139                    if (locatorType == SL_DATALOCATOR_BUFFERQUEUE)
140                        this->mBufferQueue.mNumBuffers = ((SLDataLocator_BufferQueue *)
141                            pAudioSrc->pLocator)->numBuffers;
142                    }
143#endif
144
145#ifdef USE_SNDFILE
146                    result = SndFile_checkAudioPlayerSourceSink(this);
147                    if (SL_RESULT_SUCCESS != result)
148                        break;
149#endif
150
151#ifdef USE_OUTPUTMIXEXT
152                    result = IOutputMixExt_checkAudioPlayerSourceSink(this);
153                    if (SL_RESULT_SUCCESS != result)
154                        break;
155#endif
156
157                    // Allocate memory for buffer queue
158                    //if (0 != this->mBufferQueue.mNumBuffers) {
159                        // inline allocation of circular mArray, up to a typical max
160                        if (BUFFER_HEADER_TYPICAL >= this->mBufferQueue.mNumBuffers) {
161                            this->mBufferQueue.mArray = this->mBufferQueue.mTypical;
162                        } else {
163                            // Avoid possible integer overflow during multiplication; this arbitrary
164                            // maximum is big enough to not interfere with real applications, but
165                            // small enough to not overflow.
166                            if (this->mBufferQueue.mNumBuffers >= 256) {
167                                result = SL_RESULT_MEMORY_FAILURE;
168                                break;
169                            }
170                            this->mBufferQueue.mArray = (BufferHeader *) malloc((this->mBufferQueue.
171                                mNumBuffers + 1) * sizeof(BufferHeader));
172                            if (NULL == this->mBufferQueue.mArray) {
173                                result = SL_RESULT_MEMORY_FAILURE;
174                                break;
175                            }
176                        }
177                        this->mBufferQueue.mFront = this->mBufferQueue.mArray;
178                        this->mBufferQueue.mRear = this->mBufferQueue.mArray;
179                        //}
180
181                        // used to store the data source of our audio player
182                        this->mDynamicSource.mDataSource = &this->mDataSource.u.mSource;
183
184                        // platform-specific initialization
185#ifdef ANDROID
186                        sles_to_android_audioPlayerCreate(this);
187#endif
188
189                        // return the new audio player object
190                        *pPlayer = &this->mObject.mItf;
191
192                } while (0);
193
194                if (SL_RESULT_SUCCESS != result)
195                    (*this->mObject.mItf->Destroy)(&this->mObject.mItf);
196
197            }
198        }
199
200    }
201
202    SL_LEAVE_INTERFACE
203}
204
205
206static SLresult IEngine_CreateAudioRecorder(SLEngineItf self, SLObjectItf *pRecorder,
207    SLDataSource *pAudioSrc, SLDataSink *pAudioSnk, SLuint32 numInterfaces,
208    const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired)
209{
210    SL_ENTER_INTERFACE
211
212    if (NULL == pRecorder) {
213        result = SL_RESULT_PARAMETER_INVALID;
214    } else {
215        *pRecorder = NULL;
216        unsigned exposedMask;
217        const ClassTable *pCAudioRecorder_class = objectIDtoClass(SL_OBJECTID_AUDIORECORDER);
218        result = checkInterfaces(pCAudioRecorder_class, numInterfaces,
219            pInterfaceIds, pInterfaceRequired, &exposedMask);
220        if (SL_RESULT_SUCCESS == result) {
221
222            // Construct our new AudioRecorder instance
223            CAudioRecorder *this = (CAudioRecorder *) construct(pCAudioRecorder_class, exposedMask,
224                self);
225            if (NULL == this) {
226                result = SL_RESULT_MEMORY_FAILURE;
227            } else {
228
229                do {
230
231                    // Check the source and sink parameters, and make a local copy of all parameters
232                    result = checkDataSource(pAudioSrc, &this->mDataSource);
233                    if (SL_RESULT_SUCCESS != result)
234                        break;
235                    result = checkDataSink(pAudioSnk, &this->mDataSink);
236                    if (SL_RESULT_SUCCESS != result)
237                        break;
238
239                    // FIXME This section is not yet fully implemented
240
241                    // return the new audio recorder object
242                    *pRecorder = &this->mObject.mItf;
243
244                } while (0);
245
246                if (SL_RESULT_SUCCESS != result)
247                    (*this->mObject.mItf->Destroy)(&this->mObject.mItf);
248            }
249
250        }
251
252    }
253
254    SL_LEAVE_INTERFACE
255}
256
257
258static SLresult IEngine_CreateMidiPlayer(SLEngineItf self, SLObjectItf *pPlayer,
259    SLDataSource *pMIDISrc, SLDataSource *pBankSrc, SLDataSink *pAudioOutput,
260    SLDataSink *pVibra, SLDataSink *pLEDArray, SLuint32 numInterfaces,
261    const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired)
262{
263    SL_ENTER_INTERFACE
264
265    if (NULL == pPlayer || NULL == pMIDISrc || NULL == pAudioOutput) {
266        result = SL_RESULT_PARAMETER_INVALID;
267    } else {
268        *pPlayer = NULL;
269        unsigned exposedMask;
270        const ClassTable *pCMidiPlayer_class = objectIDtoClass(SL_OBJECTID_MIDIPLAYER);
271        result = checkInterfaces(pCMidiPlayer_class, numInterfaces,
272            pInterfaceIds, pInterfaceRequired, &exposedMask);
273        if (SL_RESULT_SUCCESS == result) {
274            CMidiPlayer *this = (CMidiPlayer *) construct(pCMidiPlayer_class, exposedMask, self);
275            if (NULL == this) {
276                result = SL_RESULT_MEMORY_FAILURE;
277            } else {
278                // return the new MIDI player object
279                *pPlayer = &this->mObject.mItf;
280            }
281        }
282    }
283
284    SL_LEAVE_INTERFACE
285}
286
287
288static SLresult IEngine_CreateListener(SLEngineItf self, SLObjectItf *pListener,
289    SLuint32 numInterfaces, const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired)
290{
291    SL_ENTER_INTERFACE
292
293    if (NULL == pListener) {
294        result = SL_RESULT_PARAMETER_INVALID;
295    } else {
296        *pListener = NULL;
297        unsigned exposedMask;
298        const ClassTable *pCListener_class = objectIDtoClass(SL_OBJECTID_LISTENER);
299        result = checkInterfaces(pCListener_class, numInterfaces,
300            pInterfaceIds, pInterfaceRequired, &exposedMask);
301        if (SL_RESULT_SUCCESS == result) {
302            CListener *this = (CListener *) construct(pCListener_class, exposedMask, self);
303            if (NULL == this) {
304                result = SL_RESULT_MEMORY_FAILURE;
305            } else {
306                // return the new listener object
307                *pListener = &this->mObject.mItf;
308            }
309        }
310    }
311
312    SL_LEAVE_INTERFACE
313}
314
315
316static SLresult IEngine_Create3DGroup(SLEngineItf self, SLObjectItf *pGroup, SLuint32 numInterfaces,
317    const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired)
318{
319    SL_ENTER_INTERFACE
320
321    if (NULL == pGroup) {
322        result = SL_RESULT_PARAMETER_INVALID;
323    } else {
324        *pGroup = NULL;
325        unsigned exposedMask;
326        const ClassTable *pC3DGroup_class = objectIDtoClass(SL_OBJECTID_3DGROUP);
327        result = checkInterfaces(pC3DGroup_class, numInterfaces,
328            pInterfaceIds, pInterfaceRequired, &exposedMask);
329        if (SL_RESULT_SUCCESS == result) {
330            C3DGroup *this = (C3DGroup *) construct(pC3DGroup_class, exposedMask, self);
331            if (NULL == this) {
332                result = SL_RESULT_MEMORY_FAILURE;
333            } else {
334                this->mMemberMask = 0;
335                // return the new 3DGroup object
336                *pGroup = &this->mObject.mItf;
337            }
338        }
339    }
340
341    SL_LEAVE_INTERFACE
342}
343
344
345static SLresult IEngine_CreateOutputMix(SLEngineItf self, SLObjectItf *pMix, SLuint32 numInterfaces,
346    const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired)
347{
348    SL_ENTER_INTERFACE
349
350    if (NULL == pMix) {
351        result = SL_RESULT_PARAMETER_INVALID;
352    } else {
353        *pMix = NULL;
354        unsigned exposedMask;
355        const ClassTable *pCOutputMix_class = objectIDtoClass(SL_OBJECTID_OUTPUTMIX);
356        result = checkInterfaces(pCOutputMix_class, numInterfaces,
357            pInterfaceIds, pInterfaceRequired, &exposedMask);
358        if (SL_RESULT_SUCCESS == result) {
359            COutputMix *this = (COutputMix *) construct(pCOutputMix_class, exposedMask, self);
360            if (NULL == this) {
361                result = SL_RESULT_MEMORY_FAILURE;
362            } else {
363                *pMix = &this->mObject.mItf;
364            }
365        }
366    }
367
368    SL_LEAVE_INTERFACE
369}
370
371
372static SLresult IEngine_CreateMetadataExtractor(SLEngineItf self, SLObjectItf *pMetadataExtractor,
373    SLDataSource *pDataSource, SLuint32 numInterfaces, const SLInterfaceID *pInterfaceIds,
374    const SLboolean *pInterfaceRequired)
375{
376    SL_ENTER_INTERFACE
377
378    if (NULL == pMetadataExtractor) {
379        result = SL_RESULT_PARAMETER_INVALID;
380    } else {
381        *pMetadataExtractor = NULL;
382        unsigned exposedMask;
383        const ClassTable *pCMetadataExtractor_class =
384            objectIDtoClass(SL_OBJECTID_METADATAEXTRACTOR);
385        result = checkInterfaces(pCMetadataExtractor_class, numInterfaces,
386            pInterfaceIds, pInterfaceRequired, &exposedMask);
387        if (SL_RESULT_SUCCESS == result) {
388            CMetadataExtractor *this = (CMetadataExtractor *)
389                construct(pCMetadataExtractor_class, exposedMask, self);
390            if (NULL == this) {
391                result = SL_RESULT_MEMORY_FAILURE;
392            } else {
393                *pMetadataExtractor = &this->mObject.mItf;
394                result = SL_RESULT_SUCCESS;
395            }
396        }
397    }
398
399    SL_LEAVE_INTERFACE
400}
401
402
403static SLresult IEngine_CreateExtensionObject(SLEngineItf self, SLObjectItf *pObject,
404    void *pParameters, SLuint32 objectID, SLuint32 numInterfaces,
405    const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired)
406{
407    SL_ENTER_INTERFACE
408
409    if (NULL == pObject) {
410        result = SL_RESULT_PARAMETER_INVALID;
411    } else {
412        *pObject = NULL;
413        result = SL_RESULT_FEATURE_UNSUPPORTED;
414    }
415
416    SL_LEAVE_INTERFACE
417}
418
419
420static SLresult IEngine_QueryNumSupportedInterfaces(SLEngineItf self,
421    SLuint32 objectID, SLuint32 *pNumSupportedInterfaces)
422{
423    SL_ENTER_INTERFACE
424
425    if (NULL == pNumSupportedInterfaces) {
426        result = SL_RESULT_PARAMETER_INVALID;
427    } else {
428        const ClassTable *class__ = objectIDtoClass(objectID);
429        if (NULL == class__) {
430            result = SL_RESULT_FEATURE_UNSUPPORTED;
431        } else {
432            // FIXME Cache this value
433            SLuint32 count = 0;
434            SLuint32 i;
435            for (i = 0; i < class__->mInterfaceCount; ++i)
436                if (class__->mInterfaces[i].mInterface != INTERFACE_UNAVAILABLE)
437                    ++count;
438            *pNumSupportedInterfaces = count;
439            result = SL_RESULT_SUCCESS;
440        }
441    }
442
443    SL_LEAVE_INTERFACE;
444}
445
446
447static SLresult IEngine_QuerySupportedInterfaces(SLEngineItf self,
448    SLuint32 objectID, SLuint32 index, SLInterfaceID *pInterfaceId)
449{
450    SL_ENTER_INTERFACE
451
452    if (NULL == pInterfaceId) {
453        result = SL_RESULT_PARAMETER_INVALID;
454    } else {
455        *pInterfaceId = NULL;
456        const ClassTable *class__ = objectIDtoClass(objectID);
457        if (NULL == class__) {
458            result = SL_RESULT_FEATURE_UNSUPPORTED;
459        } else {
460            result = SL_RESULT_PARAMETER_INVALID; // will be reset later
461            // FIXME O(n)
462            SLuint32 i;
463            for (i = 0; i < class__->mInterfaceCount; ++i) {
464                // FIXME check whether published also (might be internal implicit)
465                if (INTERFACE_UNAVAILABLE == class__->mInterfaces[i].mInterface)
466                    continue;
467                if (index == 0) {
468                    *pInterfaceId = &SL_IID_array[class__->mInterfaces[i].mMPH];
469                    result = SL_RESULT_SUCCESS;
470                    break;
471                }
472                --index;
473            }
474        }
475    }
476
477    SL_LEAVE_INTERFACE
478};
479
480
481static SLresult IEngine_QueryNumSupportedExtensions(SLEngineItf self, SLuint32 *pNumExtensions)
482{
483    SL_ENTER_INTERFACE
484
485    if (NULL == pNumExtensions) {
486        result = SL_RESULT_PARAMETER_INVALID;
487    } else {
488        *pNumExtensions = 0;
489        result = SL_RESULT_SUCCESS;
490    }
491
492    SL_LEAVE_INTERFACE
493}
494
495
496static SLresult IEngine_QuerySupportedExtension(SLEngineItf self,
497    SLuint32 index, SLchar *pExtensionName, SLint16 *pNameLength)
498{
499    SL_ENTER_INTERFACE
500
501    // any index >= 0 will be >= number of supported extensions
502    result = SL_RESULT_PARAMETER_INVALID;
503
504    SL_LEAVE_INTERFACE
505}
506
507
508static SLresult IEngine_IsExtensionSupported(SLEngineItf self,
509    const SLchar *pExtensionName, SLboolean *pSupported)
510{
511    SL_ENTER_INTERFACE
512
513    if (NULL == pExtensionName || NULL == pSupported) {
514        result = SL_RESULT_PARAMETER_INVALID;
515    } else {
516        // no extensions are supported
517        *pSupported = SL_BOOLEAN_FALSE;
518        result = SL_RESULT_SUCCESS;
519    }
520
521    SL_LEAVE_INTERFACE
522}
523
524
525static const struct SLEngineItf_ IEngine_Itf = {
526    IEngine_CreateLEDDevice,
527    IEngine_CreateVibraDevice,
528    IEngine_CreateAudioPlayer,
529    IEngine_CreateAudioRecorder,
530    IEngine_CreateMidiPlayer,
531    IEngine_CreateListener,
532    IEngine_Create3DGroup,
533    IEngine_CreateOutputMix,
534    IEngine_CreateMetadataExtractor,
535    IEngine_CreateExtensionObject,
536    IEngine_QueryNumSupportedInterfaces,
537    IEngine_QuerySupportedInterfaces,
538    IEngine_QueryNumSupportedExtensions,
539    IEngine_QuerySupportedExtension,
540    IEngine_IsExtensionSupported
541};
542
543void IEngine_init(void *self)
544{
545    IEngine *this = (IEngine *) self;
546    this->mItf = &IEngine_Itf;
547    // mLossOfControlGlobal is initialized in CreateEngine
548#ifdef USE_SDL
549    this->mOutputMix = NULL;
550#endif
551    this->mInstanceCount = 1; // ourself
552    this->mInstanceMask = 0;
553    this->mChangedMask = 0;
554    unsigned i;
555    for (i = 0; i < MAX_INSTANCE; ++i)
556        this->mInstances[i] = NULL;
557    this->mShutdown = SL_BOOLEAN_FALSE;
558    int ok;
559    ok = pthread_cond_init(&this->mShutdownCond, (const pthread_condattr_t *) NULL);
560    assert(0 == ok);
561}
562