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