sles.cpp revision b7154f2324c8ae44b820c07c69aaa80a4bb9e418
1773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi/* 2773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi * Copyright (C) 2010 The Android Open Source Project 3773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi * 4773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi * Licensed under the Apache License, Version 2.0 (the "License"); 5773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi * you may not use this file except in compliance with the License. 6773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi * You may obtain a copy of the License at 7773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi * 8773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi * http://www.apache.org/licenses/LICENSE-2.0 9773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi * 10773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi * Unless required by applicable law or agreed to in writing, software 11773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi * distributed under the License is distributed on an "AS IS" BASIS, 12773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi * See the License for the specific language governing permissions and 14773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi * limitations under the License. 15773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi */ 16d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten 17d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten/* OpenSL ES prototype */ 18d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten 19773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi#include "sles_allinclusive.h" 20c116ab2a033ee7dc78cfd458defe38d4528383a8Jean-Michel Trivi#include "sles_check_audioplayer_ext.h" 21bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten 22d20441ee29747b206cb0d197260c3ac78d7762daGlenn Kasten#ifdef USE_ANDROID 23773e0429cbb9e85b4f1c6eb5a095ccd7b57f5ba4Jean-Michel Trivi#include "sles_to_android_ext.h" 242045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten#endif 25d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten 26bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten/* Private functions */ 27bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten 28b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten// Map an IObject to it's "object ID" (which is really a class ID) 29b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten 30b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn KastenSLuint32 IObjectToObjectID(IObject *this) 31b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten{ 32b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten assert(NULL != this); 33b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten return this->mClass->mObjectID; 34b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten} 35b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten 36bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten// Map SLInterfaceID to its minimal perfect hash (MPH), or -1 if unknown 37bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten 3861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten/*static*/ int IID_to_MPH(const SLInterfaceID iid) 39d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{ 40bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten if (&SL_IID_array[0] <= iid && &SL_IID_array[MPH_MAX] > iid) 41bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten return iid - &SL_IID_array[0]; 42bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten if (NULL != iid) { 43bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten // FIXME Replace this linear search by a good MPH algorithm 44bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten const struct SLInterfaceID_ *srch = &SL_IID_array[0]; 45bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten unsigned MPH; 46bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten for (MPH = 0; MPH < MPH_MAX; ++MPH, ++srch) 47bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten if (!memcmp(iid, srch, sizeof(struct SLInterfaceID_))) 48bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten return MPH; 49bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten } 50bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten return -1; 51bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten} 52bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten 5329b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten// Check the interface IDs passed into a Create operation 5429b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten 55979a3f8743646af9999a89dff9e13b972b7efd87Glenn KastenSLresult checkInterfaces(const ClassTable *class__, 56bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten SLuint32 numInterfaces, const SLInterfaceID *pInterfaceIds, 57bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten const SLboolean *pInterfaceRequired, unsigned *pExposedMask) 58bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{ 59bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten assert(NULL != class__ && NULL != pExposedMask); 60bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten unsigned exposedMask = 0; 61bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten const struct iid_vtable *interfaces = class__->mInterfaces; 62bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten SLuint32 interfaceCount = class__->mInterfaceCount; 63bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten SLuint32 i; 64bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten // FIXME This section could be pre-computed per class 65bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten for (i = 0; i < interfaceCount; ++i) { 66bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten switch (interfaces[i].mInterface) { 67bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten case INTERFACE_IMPLICIT: 68bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten exposedMask |= 1 << i; 69bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten break; 70bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten default: 71bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten break; 72bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten } 73bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten } 74d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten if (0 < numInterfaces) { 75d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten if (NULL == pInterfaceIds || NULL == pInterfaceRequired) 76d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten return SL_RESULT_PARAMETER_INVALID; 77d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten for (i = 0; i < numInterfaces; ++i) { 78bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten SLInterfaceID iid = pInterfaceIds[i]; 79bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten if (NULL == iid) 80bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten return SL_RESULT_PARAMETER_INVALID; 8129b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten int MPH, index; 8229b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten if ((0 > (MPH = IID_to_MPH(iid))) || 8329b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten (0 > (index = class__->mMPH_to_index[MPH]))) { 84bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten if (pInterfaceRequired[i]) 85bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten return SL_RESULT_FEATURE_UNSUPPORTED; 86bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten continue; 87bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten } 8829b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten // FIXME this seems a bit strong? what is correct logic? 8929b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten // we are requesting a duplicate explicit interface, 9029b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten // or we are requesting one which is already implicit ? 9129b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten // if (exposedMask & (1 << index)) 9229b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten // return SL_RESULT_PARAMETER_INVALID; 9329b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten exposedMask |= (1 << index); 94d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten } 95d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten } 96bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten *pExposedMask = exposedMask; 97d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten return SL_RESULT_SUCCESS; 98d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten} 99d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten 10061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten// private helper shared by decoder and encoder 10161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn KastenSLresult GetCodecCapabilities(SLuint32 decoderId, SLuint32 *pIndex, 10261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten SLAudioCodecDescriptor *pDescriptor, 10361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten const struct CodecDescriptor *codecDescriptors) 104bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{ 10561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten if (NULL == pIndex) 10661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten return SL_RESULT_PARAMETER_INVALID; 10761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten const struct CodecDescriptor *cd = codecDescriptors; 10861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten SLuint32 index; 10961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten if (NULL == pDescriptor) { 11061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten for (index = 0 ; NULL != cd->mDescriptor; ++cd) 11161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten if (cd->mCodecID == decoderId) 11261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten ++index; 11361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten *pIndex = index; 11461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten return SL_RESULT_SUCCESS; 11561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten } 11661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten index = *pIndex; 11761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten for ( ; NULL != cd->mDescriptor; ++cd) { 11861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten if (cd->mCodecID == decoderId) { 11961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten if (0 == index) { 12061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten *pDescriptor = *cd->mDescriptor; 12161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten return SL_RESULT_SUCCESS; 12261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten } 12361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten --index; 12461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten } 12561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten } 12661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten return SL_RESULT_PARAMETER_INVALID; 127bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten} 1282045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten 12961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten/* Interface initialization hooks */ 1302045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten 131a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kastenextern void 132a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten I3DCommit_init(void *), 133a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten I3DDoppler_init(void *), 134a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten I3DGrouping_init(void *), 135a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten I3DLocation_init(void *), 136a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten I3DMacroscopic_init(void *), 137a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten I3DSource_init(void *), 13861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IAudioDecoderCapabilities_init(void *), 13961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IAudioEncoderCapabilities_init(void *), 14061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IAudioEncoder_init(void *), 14161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IAudioIODeviceCapabilities_init(void *), 142a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten IBassBoost_init(void *), 1430b167267bda99b68346045ccab14e810121d5de4Glenn Kasten IBufferQueue_init(void *), 14461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IDeviceVolume_init(void *), 14561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IDynamicInterfaceManagement_init(void *), 14661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IDynamicSource_init(void *), 14761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IEffectSend_init(void *), 1480b167267bda99b68346045ccab14e810121d5de4Glenn Kasten IEngineCapabilities_init(void *), 1490b167267bda99b68346045ccab14e810121d5de4Glenn Kasten IEngine_init(void *), 150a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten IEnvironmentalReverb_init(void *), 151a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten IEqualizer_init(void *), 15261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten ILEDArray_init(void *), 1530b167267bda99b68346045ccab14e810121d5de4Glenn Kasten IMIDIMessage_init(void *), 1540b167267bda99b68346045ccab14e810121d5de4Glenn Kasten IMIDIMuteSolo_init(void *), 1550b167267bda99b68346045ccab14e810121d5de4Glenn Kasten IMIDITempo_init(void *), 1560b167267bda99b68346045ccab14e810121d5de4Glenn Kasten IMIDITime_init(void *), 15761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IMetadataExtraction_init(void *), 15861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IMetadataTraversal_init(void *), 15961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IMuteSolo_init(void *), 16061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IObject_init(void *), 1610b167267bda99b68346045ccab14e810121d5de4Glenn Kasten IOutputMix_init(void *), 16261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IPitch_init(void *), 1630b167267bda99b68346045ccab14e810121d5de4Glenn Kasten IPlay_init(void *), 16461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IPlaybackRate_init(void *), 16561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IPrefetchStatus_init(void *), 166a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten IPresetReverb_init(void *), 16761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IRatePitch_init(void *), 16861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IRecord_init(void *), 1690b167267bda99b68346045ccab14e810121d5de4Glenn Kasten ISeek_init(void *), 17061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IThreadSync_init(void *), 17161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IVibra_init(void *), 172a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten IVirtualizer_init(void *), 1730b167267bda99b68346045ccab14e810121d5de4Glenn Kasten IVisualization_init(void *), 1740b167267bda99b68346045ccab14e810121d5de4Glenn Kasten IVolume_init(void *); 175a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten 176b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten#ifdef USE_OUTPUTMIXEXT 177b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kastenextern void 178b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten IOutputMixExt_init(void *); 179b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten#endif 180b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten 18161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten/*static*/ const struct MPH_init MPH_init_table[MPH_MAX] = { 182a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten { /* MPH_3DCOMMIT, */ I3DCommit_init, NULL }, 183a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten { /* MPH_3DDOPPLER, */ I3DDoppler_init, NULL }, 184a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten { /* MPH_3DGROUPING, */ I3DGrouping_init, NULL }, 185a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten { /* MPH_3DLOCATION, */ I3DLocation_init, NULL }, 186a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten { /* MPH_3DMACROSCOPIC, */ I3DMacroscopic_init, NULL }, 187a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten { /* MPH_3DSOURCE, */ I3DSource_init, NULL }, 18861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten { /* MPH_AUDIODECODERCAPABILITIES, */ IAudioDecoderCapabilities_init, NULL }, 18961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten { /* MPH_AUDIOENCODER, */ IAudioEncoder_init, NULL }, 19061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten { /* MPH_AUDIOENCODERCAPABILITIES, */ IAudioEncoderCapabilities_init, NULL }, 19161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten { /* MPH_AUDIOIODEVICECAPABILITIES, */ IAudioIODeviceCapabilities_init, 192bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten NULL }, 193a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten { /* MPH_BASSBOOST, */ IBassBoost_init, NULL }, 1940b167267bda99b68346045ccab14e810121d5de4Glenn Kasten { /* MPH_BUFFERQUEUE, */ IBufferQueue_init, NULL }, 19561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten { /* MPH_DEVICEVOLUME, */ IDeviceVolume_init, NULL }, 19661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten { /* MPH_DYNAMICINTERFACEMANAGEMENT, */ IDynamicInterfaceManagement_init, 197bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten NULL }, 19861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten { /* MPH_DYNAMICSOURCE, */ IDynamicSource_init, NULL }, 19961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten { /* MPH_EFFECTSEND, */ IEffectSend_init, NULL }, 2000b167267bda99b68346045ccab14e810121d5de4Glenn Kasten { /* MPH_ENGINE, */ IEngine_init, NULL }, 2010b167267bda99b68346045ccab14e810121d5de4Glenn Kasten { /* MPH_ENGINECAPABILITIES, */ IEngineCapabilities_init, NULL }, 202a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten { /* MPH_ENVIRONMENTALREVERB, */ IEnvironmentalReverb_init, NULL }, 203a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten { /* MPH_EQUALIZER, */ IEqualizer_init, NULL }, 20461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten { /* MPH_LED, */ ILEDArray_init, NULL }, 20561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten { /* MPH_METADATAEXTRACTION, */ IMetadataExtraction_init, NULL }, 20661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten { /* MPH_METADATATRAVERSAL, */ IMetadataTraversal_init, NULL }, 2070b167267bda99b68346045ccab14e810121d5de4Glenn Kasten { /* MPH_MIDIMESSAGE, */ IMIDIMessage_init, NULL }, 2080b167267bda99b68346045ccab14e810121d5de4Glenn Kasten { /* MPH_MIDITIME, */ IMIDITime_init, NULL }, 2090b167267bda99b68346045ccab14e810121d5de4Glenn Kasten { /* MPH_MIDITEMPO, */ IMIDITempo_init, NULL }, 2100b167267bda99b68346045ccab14e810121d5de4Glenn Kasten { /* MPH_MIDIMUTESOLO, */ IMIDIMuteSolo_init, NULL }, 21161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten { /* MPH_MUTESOLO, */ IMuteSolo_init, NULL }, 212bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten { /* MPH_NULL, */ NULL, NULL }, 21361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten { /* MPH_OBJECT, */ IObject_init, NULL }, 2140b167267bda99b68346045ccab14e810121d5de4Glenn Kasten { /* MPH_OUTPUTMIX, */ IOutputMix_init, NULL }, 21561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten { /* MPH_PITCH, */ IPitch_init, NULL }, 2160b167267bda99b68346045ccab14e810121d5de4Glenn Kasten { /* MPH_PLAY, */ IPlay_init, NULL }, 21761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten { /* MPH_PLAYBACKRATE, */ IPlaybackRate_init, NULL }, 21861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten { /* MPH_PREFETCHSTATUS, */ IPrefetchStatus_init, NULL }, 219a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten { /* MPH_PRESETREVERB, */ IPresetReverb_init, NULL }, 22061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten { /* MPH_RATEPITCH, */ IRatePitch_init, NULL }, 22161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten { /* MPH_RECORD, */ IRecord_init, NULL }, 2220b167267bda99b68346045ccab14e810121d5de4Glenn Kasten { /* MPH_SEEK, */ ISeek_init, NULL }, 22361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten { /* MPH_THREADSYNC, */ IThreadSync_init, NULL }, 22461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten { /* MPH_VIBRA, */ IVibra_init, NULL }, 225a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten { /* MPH_VIRTUALIZER, */ IVirtualizer_init, NULL }, 226a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten { /* MPH_VISUALIZATION, */ IVisualization_init, NULL }, 2270b167267bda99b68346045ccab14e810121d5de4Glenn Kasten { /* MPH_VOLUME, */ IVolume_init, NULL }, 228bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten { /* MPH_OUTPUTMIXEXT, */ 229bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#ifdef USE_OUTPUTMIXEXT 230b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten IOutputMixExt_init, NULL 231bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#else 232bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten NULL, NULL 233bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#endif 234bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten } 235bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}; 236bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten 237bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten// Construct a new instance of the specified class, exposing selected interfaces 238bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten 239979a3f8743646af9999a89dff9e13b972b7efd87Glenn KastenIObject *construct(const ClassTable *class__, 24029b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten unsigned exposedMask, SLEngineItf engine) 241bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{ 24272a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten IObject *this; 243bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#ifndef NDEBUG 24472a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten this = (IObject *) malloc(class__->mSize); 245bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#else 24672a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten this = (IObject *) calloc(1, class__->mSize); 247bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#endif 248bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten if (NULL != this) { 249bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#ifndef NDEBUG 250bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten // for debugging, to detect uninitialized fields 251bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten memset(this, 0x55, class__->mSize); 252bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#endif 25329b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten this->mClass = class__; 25429b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten this->mExposedMask = exposedMask; 25572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten unsigned lossOfControlMask = 0; 25672a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten IEngine *thisEngine = (IEngine *) engine; 25772a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten if (NULL == thisEngine) 25872a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten thisEngine = &((CEngine *) this)->mEngine; 25972a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten else if (thisEngine->mLossOfControlGlobal) 26072a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten lossOfControlMask = ~0; 26172a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten this->mLossOfControlMask = lossOfControlMask; 262bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten const struct iid_vtable *x = class__->mInterfaces; 263bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten unsigned i; 264bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten for (i = 0; exposedMask; ++i, ++x, exposedMask >>= 1) { 265bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten if (exposedMask & 1) { 26683f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten void *self = (char *) this + x->mOffset; 26772a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten ((IObject **) self)[1] = this; 26883f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten VoidHook init = MPH_init_table[x->mMPH].mInit; 269bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten if (NULL != init) 270bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten (*init)(self); 271bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten } 272bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten } 27372a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten // FIXME need a lock 27472a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten if (INSTANCE_MAX > thisEngine->mInstanceCount) { 27572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten // FIXME ignores Destroy 27672a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten thisEngine->mInstances[thisEngine->mInstanceCount++] = this; 27772a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten } 27872a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten // FIXME else what 279bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten } 280bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten return this; 281bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten} 282bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten 283b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten// The sync thread runs periodically to synchronize audio state between 284b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten// the application and platform-specific device driver; for best results 285b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten// it should run about every graphics frame (e.g. 20 Hz to 50 Hz). 286d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten 287b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kastenstatic void *sync_body(void *arg) 288d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{ 2890b167267bda99b68346045ccab14e810121d5de4Glenn Kasten CEngine *this = (CEngine *) arg; 2900b167267bda99b68346045ccab14e810121d5de4Glenn Kasten for (;;) { 2910b167267bda99b68346045ccab14e810121d5de4Glenn Kasten usleep(20000*50); 2920b167267bda99b68346045ccab14e810121d5de4Glenn Kasten unsigned i; 2930b167267bda99b68346045ccab14e810121d5de4Glenn Kasten for (i = 0; i < INSTANCE_MAX; ++i) { 2940b167267bda99b68346045ccab14e810121d5de4Glenn Kasten IObject *instance = (IObject *) this->mEngine.mInstances[i]; 2950b167267bda99b68346045ccab14e810121d5de4Glenn Kasten if (NULL == instance) 2960b167267bda99b68346045ccab14e810121d5de4Glenn Kasten continue; 297b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten switch (IObjectToObjectID(instance)) { 298b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten case SL_OBJECTID_AUDIOPLAYER: 299b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten write(1, ".", 1); 300b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten break; 301b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten default: 302b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten break; 303b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten } 3040b167267bda99b68346045ccab14e810121d5de4Glenn Kasten } 3052045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten } 3060b167267bda99b68346045ccab14e810121d5de4Glenn Kasten return NULL; 307d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten} 308d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten 3090b167267bda99b68346045ccab14e810121d5de4Glenn Kasten/* Initial entry points */ 310d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten 3110b167267bda99b68346045ccab14e810121d5de4Glenn KastenSLresult SLAPIENTRY slCreateEngine(SLObjectItf *pEngine, SLuint32 numOptions, 3120b167267bda99b68346045ccab14e810121d5de4Glenn Kasten const SLEngineOption *pEngineOptions, SLuint32 numInterfaces, 3130b167267bda99b68346045ccab14e810121d5de4Glenn Kasten const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired) 314d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{ 3150b167267bda99b68346045ccab14e810121d5de4Glenn Kasten if (NULL == pEngine) 316d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten return SL_RESULT_PARAMETER_INVALID; 3170b167267bda99b68346045ccab14e810121d5de4Glenn Kasten *pEngine = NULL; 3180b167267bda99b68346045ccab14e810121d5de4Glenn Kasten // default values 3190b167267bda99b68346045ccab14e810121d5de4Glenn Kasten SLboolean threadSafe = SL_BOOLEAN_TRUE; 3200b167267bda99b68346045ccab14e810121d5de4Glenn Kasten SLboolean lossOfControlGlobal = SL_BOOLEAN_FALSE; 3210b167267bda99b68346045ccab14e810121d5de4Glenn Kasten if (NULL != pEngineOptions) { 3220b167267bda99b68346045ccab14e810121d5de4Glenn Kasten SLuint32 i; 3230b167267bda99b68346045ccab14e810121d5de4Glenn Kasten const SLEngineOption *option = pEngineOptions; 3240b167267bda99b68346045ccab14e810121d5de4Glenn Kasten for (i = 0; i < numOptions; ++i, ++option) { 3250b167267bda99b68346045ccab14e810121d5de4Glenn Kasten switch (option->feature) { 3260b167267bda99b68346045ccab14e810121d5de4Glenn Kasten case SL_ENGINEOPTION_THREADSAFE: 3270b167267bda99b68346045ccab14e810121d5de4Glenn Kasten threadSafe = (SLboolean) option->data; 3280b167267bda99b68346045ccab14e810121d5de4Glenn Kasten break; 3290b167267bda99b68346045ccab14e810121d5de4Glenn Kasten case SL_ENGINEOPTION_LOSSOFCONTROL: 3300b167267bda99b68346045ccab14e810121d5de4Glenn Kasten lossOfControlGlobal = (SLboolean) option->data; 3310b167267bda99b68346045ccab14e810121d5de4Glenn Kasten break; 3320b167267bda99b68346045ccab14e810121d5de4Glenn Kasten default: 3330b167267bda99b68346045ccab14e810121d5de4Glenn Kasten return SL_RESULT_PARAMETER_INVALID; 3340b167267bda99b68346045ccab14e810121d5de4Glenn Kasten } 3350b167267bda99b68346045ccab14e810121d5de4Glenn Kasten } 33629b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten } 3370b167267bda99b68346045ccab14e810121d5de4Glenn Kasten unsigned exposedMask; 338b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten const ClassTable *pCEngine_class = objectIDtoClass(SL_OBJECTID_ENGINE); 339b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten SLresult result = checkInterfaces(pCEngine_class, numInterfaces, 3400b167267bda99b68346045ccab14e810121d5de4Glenn Kasten pInterfaceIds, pInterfaceRequired, &exposedMask); 3410b167267bda99b68346045ccab14e810121d5de4Glenn Kasten if (SL_RESULT_SUCCESS != result) 3420b167267bda99b68346045ccab14e810121d5de4Glenn Kasten return result; 343b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten CEngine *this = (CEngine *) construct(pCEngine_class, exposedMask, NULL); 3440b167267bda99b68346045ccab14e810121d5de4Glenn Kasten if (NULL == this) 3450b167267bda99b68346045ccab14e810121d5de4Glenn Kasten return SL_RESULT_MEMORY_FAILURE; 3460b167267bda99b68346045ccab14e810121d5de4Glenn Kasten this->mObject.mLossOfControlMask = lossOfControlGlobal ? ~0 : 0; 3470b167267bda99b68346045ccab14e810121d5de4Glenn Kasten this->mEngine.mLossOfControlGlobal = lossOfControlGlobal; 3480b167267bda99b68346045ccab14e810121d5de4Glenn Kasten this->mEngineCapabilities.mThreadSafe = threadSafe; 3490b167267bda99b68346045ccab14e810121d5de4Glenn Kasten int ok; 350b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten ok = pthread_create(&this->mSyncThread, (const pthread_attr_t *) NULL, sync_body, this); 3510b167267bda99b68346045ccab14e810121d5de4Glenn Kasten assert(ok == 0); 3520b167267bda99b68346045ccab14e810121d5de4Glenn Kasten *pEngine = &this->mObject.mItf; 353d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten return SL_RESULT_SUCCESS; 354d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten} 355d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten 3560b167267bda99b68346045ccab14e810121d5de4Glenn KastenSLresult SLAPIENTRY slQueryNumSupportedEngineInterfaces( 3570b167267bda99b68346045ccab14e810121d5de4Glenn Kasten SLuint32 *pNumSupportedInterfaces) 358d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{ 3590b167267bda99b68346045ccab14e810121d5de4Glenn Kasten if (NULL == pNumSupportedInterfaces) 3602045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten return SL_RESULT_PARAMETER_INVALID; 361b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten const ClassTable *pCEngine_class = objectIDtoClass(SL_OBJECTID_ENGINE); 362b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten *pNumSupportedInterfaces = pCEngine_class->mInterfaceCount; 363d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten return SL_RESULT_SUCCESS; 364d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten} 365d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten 3660b167267bda99b68346045ccab14e810121d5de4Glenn KastenSLresult SLAPIENTRY slQuerySupportedEngineInterfaces(SLuint32 index, 3670b167267bda99b68346045ccab14e810121d5de4Glenn Kasten SLInterfaceID *pInterfaceId) 368d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{ 3690b167267bda99b68346045ccab14e810121d5de4Glenn Kasten if (NULL == pInterfaceId) 3702045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten return SL_RESULT_PARAMETER_INVALID; 371b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten const ClassTable *pCEngine_class = objectIDtoClass(SL_OBJECTID_ENGINE); 372b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten if (pCEngine_class->mInterfaceCount <= index) 373b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten return SL_RESULT_PARAMETER_INVALID; 374b7154f2324c8ae44b820c07c69aaa80a4bb9e418Glenn Kasten *pInterfaceId = &SL_IID_array[pCEngine_class->mInterfaces[index].mMPH]; 375d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten return SL_RESULT_SUCCESS; 376d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten} 377d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten 378d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten/* End */ 379