sles.c revision 0b167267bda99b68346045ccab14e810121d5de4
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 26d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten/* Forward declarations */ 27d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten 28bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenextern const struct SLInterfaceID_ SL_IID_array[MPH_MAX]; 29bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten 30bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten/* Private functions */ 31bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten 32bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten// Map SLInterfaceID to its minimal perfect hash (MPH), or -1 if unknown 33bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten 3461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten/*static*/ int IID_to_MPH(const SLInterfaceID iid) 35d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{ 36bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten if (&SL_IID_array[0] <= iid && &SL_IID_array[MPH_MAX] > iid) 37bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten return iid - &SL_IID_array[0]; 38bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten if (NULL != iid) { 39bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten // FIXME Replace this linear search by a good MPH algorithm 40bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten const struct SLInterfaceID_ *srch = &SL_IID_array[0]; 41bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten unsigned MPH; 42bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten for (MPH = 0; MPH < MPH_MAX; ++MPH, ++srch) 43bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten if (!memcmp(iid, srch, sizeof(struct SLInterfaceID_))) 44bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten return MPH; 45bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten } 46bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten return -1; 47bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten} 48bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten 4929b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten// Check the interface IDs passed into a Create operation 5029b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten 5172a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kastenstatic SLresult checkInterfaces(const ClassTable *class__, 52bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten SLuint32 numInterfaces, const SLInterfaceID *pInterfaceIds, 53bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten const SLboolean *pInterfaceRequired, unsigned *pExposedMask) 54bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{ 55bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten assert(NULL != class__ && NULL != pExposedMask); 56bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten unsigned exposedMask = 0; 57bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten const struct iid_vtable *interfaces = class__->mInterfaces; 58bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten SLuint32 interfaceCount = class__->mInterfaceCount; 59bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten SLuint32 i; 60bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten // FIXME This section could be pre-computed per class 61bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten for (i = 0; i < interfaceCount; ++i) { 62bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten switch (interfaces[i].mInterface) { 63bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten case INTERFACE_IMPLICIT: 64bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten exposedMask |= 1 << i; 65bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten break; 66bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten default: 67bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten break; 68bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten } 69bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten } 70d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten if (0 < numInterfaces) { 71d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten if (NULL == pInterfaceIds || NULL == pInterfaceRequired) 72d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten return SL_RESULT_PARAMETER_INVALID; 73d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten for (i = 0; i < numInterfaces; ++i) { 74bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten SLInterfaceID iid = pInterfaceIds[i]; 75bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten if (NULL == iid) 76bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten return SL_RESULT_PARAMETER_INVALID; 7729b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten int MPH, index; 7829b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten if ((0 > (MPH = IID_to_MPH(iid))) || 7929b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten (0 > (index = class__->mMPH_to_index[MPH]))) { 80bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten if (pInterfaceRequired[i]) 81bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten return SL_RESULT_FEATURE_UNSUPPORTED; 82bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten continue; 83bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten } 8429b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten // FIXME this seems a bit strong? what is correct logic? 8529b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten // we are requesting a duplicate explicit interface, 8629b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten // or we are requesting one which is already implicit ? 8729b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten // if (exposedMask & (1 << index)) 8829b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten // return SL_RESULT_PARAMETER_INVALID; 8929b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten exposedMask |= (1 << index); 90d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten } 91d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten } 92bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten *pExposedMask = exposedMask; 93d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten return SL_RESULT_SUCCESS; 94d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten} 95d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten 9661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten// private helper shared by decoder and encoder 9761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn KastenSLresult GetCodecCapabilities(SLuint32 decoderId, SLuint32 *pIndex, 9861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten SLAudioCodecDescriptor *pDescriptor, 9961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten const struct CodecDescriptor *codecDescriptors) 100bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{ 10161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten if (NULL == pIndex) 10261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten return SL_RESULT_PARAMETER_INVALID; 10361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten const struct CodecDescriptor *cd = codecDescriptors; 10461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten SLuint32 index; 10561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten if (NULL == pDescriptor) { 10661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten for (index = 0 ; NULL != cd->mDescriptor; ++cd) 10761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten if (cd->mCodecID == decoderId) 10861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten ++index; 10961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten *pIndex = index; 11061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten return SL_RESULT_SUCCESS; 11161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten } 11261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten index = *pIndex; 11361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten for ( ; NULL != cd->mDescriptor; ++cd) { 11461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten if (cd->mCodecID == decoderId) { 11561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten if (0 == index) { 11661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten *pDescriptor = *cd->mDescriptor; 11761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten return SL_RESULT_SUCCESS; 11861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten } 11961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten --index; 12061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten } 12161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten } 12261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten return SL_RESULT_PARAMETER_INVALID; 123bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten} 1242045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten 12561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten/* Interface initialization hooks */ 1262045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten 127bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#ifdef USE_OUTPUTMIXEXT 128d20441ee29747b206cb0d197260c3ac78d7762daGlenn Kastenextern const struct SLOutputMixExtItf_ OutputMixExt_OutputMixExtItf; 129d20441ee29747b206cb0d197260c3ac78d7762daGlenn Kasten 130bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic void OutputMixExt_init(void *self) 131d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{ 13272a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten IOutputMixExt *this = 13372a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten (IOutputMixExt *) self; 134bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten this->mItf = &OutputMixExt_OutputMixExtItf; 135d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten} 136bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#endif // USE_OUTPUTMIXEXT 137d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten 138a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten#ifdef __cplusplus 139a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kastenextern "C" { 140a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten#endif 141a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten 142a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kastenextern void 143a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten I3DCommit_init(void *), 144a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten I3DDoppler_init(void *), 145a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten I3DGrouping_init(void *), 146a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten I3DLocation_init(void *), 147a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten I3DMacroscopic_init(void *), 148a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten I3DSource_init(void *), 14961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IAudioDecoderCapabilities_init(void *), 15061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IAudioEncoderCapabilities_init(void *), 15161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IAudioEncoder_init(void *), 15261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IAudioIODeviceCapabilities_init(void *), 153a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten IBassBoost_init(void *), 1540b167267bda99b68346045ccab14e810121d5de4Glenn Kasten IBufferQueue_init(void *), 15561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IDeviceVolume_init(void *), 15661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IDynamicInterfaceManagement_init(void *), 15761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IDynamicSource_init(void *), 15861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IEffectSend_init(void *), 1590b167267bda99b68346045ccab14e810121d5de4Glenn Kasten IEngineCapabilities_init(void *), 1600b167267bda99b68346045ccab14e810121d5de4Glenn Kasten IEngine_init(void *), 161a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten IEnvironmentalReverb_init(void *), 162a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten IEqualizer_init(void *), 16361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten ILEDArray_init(void *), 1640b167267bda99b68346045ccab14e810121d5de4Glenn Kasten IMIDIMessage_init(void *), 1650b167267bda99b68346045ccab14e810121d5de4Glenn Kasten IMIDIMuteSolo_init(void *), 1660b167267bda99b68346045ccab14e810121d5de4Glenn Kasten IMIDITempo_init(void *), 1670b167267bda99b68346045ccab14e810121d5de4Glenn Kasten IMIDITime_init(void *), 16861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IMetadataExtraction_init(void *), 16961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IMetadataTraversal_init(void *), 17061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IMuteSolo_init(void *), 17161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IObject_init(void *), 1720b167267bda99b68346045ccab14e810121d5de4Glenn Kasten IOutputMix_init(void *), 17361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IPitch_init(void *), 1740b167267bda99b68346045ccab14e810121d5de4Glenn Kasten IPlay_init(void *), 17561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IPlaybackRate_init(void *), 17661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IPrefetchStatus_init(void *), 177a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten IPresetReverb_init(void *), 17861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IRatePitch_init(void *), 17961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IRecord_init(void *), 1800b167267bda99b68346045ccab14e810121d5de4Glenn Kasten ISeek_init(void *), 18161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IThreadSync_init(void *), 18261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IVibra_init(void *), 183a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten IVirtualizer_init(void *), 1840b167267bda99b68346045ccab14e810121d5de4Glenn Kasten IVisualization_init(void *), 1850b167267bda99b68346045ccab14e810121d5de4Glenn Kasten IVolume_init(void *); 186a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten 187a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten#ifdef __cplusplus 188a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten} 189a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten#endif 190a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten 19161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten/*static*/ const struct MPH_init MPH_init_table[MPH_MAX] = { 192a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten { /* MPH_3DCOMMIT, */ I3DCommit_init, NULL }, 193a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten { /* MPH_3DDOPPLER, */ I3DDoppler_init, NULL }, 194a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten { /* MPH_3DGROUPING, */ I3DGrouping_init, NULL }, 195a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten { /* MPH_3DLOCATION, */ I3DLocation_init, NULL }, 196a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten { /* MPH_3DMACROSCOPIC, */ I3DMacroscopic_init, NULL }, 197a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten { /* MPH_3DSOURCE, */ I3DSource_init, NULL }, 19861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten { /* MPH_AUDIODECODERCAPABILITIES, */ IAudioDecoderCapabilities_init, NULL }, 19961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten { /* MPH_AUDIOENCODER, */ IAudioEncoder_init, NULL }, 20061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten { /* MPH_AUDIOENCODERCAPABILITIES, */ IAudioEncoderCapabilities_init, NULL }, 20161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten { /* MPH_AUDIOIODEVICECAPABILITIES, */ IAudioIODeviceCapabilities_init, 202bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten NULL }, 203a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten { /* MPH_BASSBOOST, */ IBassBoost_init, NULL }, 2040b167267bda99b68346045ccab14e810121d5de4Glenn Kasten { /* MPH_BUFFERQUEUE, */ IBufferQueue_init, NULL }, 20561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten { /* MPH_DEVICEVOLUME, */ IDeviceVolume_init, NULL }, 20661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten { /* MPH_DYNAMICINTERFACEMANAGEMENT, */ IDynamicInterfaceManagement_init, 207bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten NULL }, 20861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten { /* MPH_DYNAMICSOURCE, */ IDynamicSource_init, NULL }, 20961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten { /* MPH_EFFECTSEND, */ IEffectSend_init, NULL }, 2100b167267bda99b68346045ccab14e810121d5de4Glenn Kasten { /* MPH_ENGINE, */ IEngine_init, NULL }, 2110b167267bda99b68346045ccab14e810121d5de4Glenn Kasten { /* MPH_ENGINECAPABILITIES, */ IEngineCapabilities_init, NULL }, 212a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten { /* MPH_ENVIRONMENTALREVERB, */ IEnvironmentalReverb_init, NULL }, 213a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten { /* MPH_EQUALIZER, */ IEqualizer_init, NULL }, 21461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten { /* MPH_LED, */ ILEDArray_init, NULL }, 21561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten { /* MPH_METADATAEXTRACTION, */ IMetadataExtraction_init, NULL }, 21661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten { /* MPH_METADATATRAVERSAL, */ IMetadataTraversal_init, NULL }, 2170b167267bda99b68346045ccab14e810121d5de4Glenn Kasten { /* MPH_MIDIMESSAGE, */ IMIDIMessage_init, NULL }, 2180b167267bda99b68346045ccab14e810121d5de4Glenn Kasten { /* MPH_MIDITIME, */ IMIDITime_init, NULL }, 2190b167267bda99b68346045ccab14e810121d5de4Glenn Kasten { /* MPH_MIDITEMPO, */ IMIDITempo_init, NULL }, 2200b167267bda99b68346045ccab14e810121d5de4Glenn Kasten { /* MPH_MIDIMUTESOLO, */ IMIDIMuteSolo_init, NULL }, 22161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten { /* MPH_MUTESOLO, */ IMuteSolo_init, NULL }, 222bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten { /* MPH_NULL, */ NULL, NULL }, 22361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten { /* MPH_OBJECT, */ IObject_init, NULL }, 2240b167267bda99b68346045ccab14e810121d5de4Glenn Kasten { /* MPH_OUTPUTMIX, */ IOutputMix_init, NULL }, 22561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten { /* MPH_PITCH, */ IPitch_init, NULL }, 2260b167267bda99b68346045ccab14e810121d5de4Glenn Kasten { /* MPH_PLAY, */ IPlay_init, NULL }, 22761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten { /* MPH_PLAYBACKRATE, */ IPlaybackRate_init, NULL }, 22861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten { /* MPH_PREFETCHSTATUS, */ IPrefetchStatus_init, NULL }, 229a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten { /* MPH_PRESETREVERB, */ IPresetReverb_init, NULL }, 23061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten { /* MPH_RATEPITCH, */ IRatePitch_init, NULL }, 23161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten { /* MPH_RECORD, */ IRecord_init, NULL }, 2320b167267bda99b68346045ccab14e810121d5de4Glenn Kasten { /* MPH_SEEK, */ ISeek_init, NULL }, 23361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten { /* MPH_THREADSYNC, */ IThreadSync_init, NULL }, 23461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten { /* MPH_VIBRA, */ IVibra_init, NULL }, 235a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten { /* MPH_VIRTUALIZER, */ IVirtualizer_init, NULL }, 236a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten { /* MPH_VISUALIZATION, */ IVisualization_init, NULL }, 2370b167267bda99b68346045ccab14e810121d5de4Glenn Kasten { /* MPH_VOLUME, */ IVolume_init, NULL }, 238bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten { /* MPH_OUTPUTMIXEXT, */ 239bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#ifdef USE_OUTPUTMIXEXT 240bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten OutputMixExt_init, NULL 241bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#else 242bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten NULL, NULL 243bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#endif 244bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten } 245bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}; 246bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten 247bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten/* Classes vs. interfaces */ 248bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten 249bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten// 3DGroup class 250bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten 251bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic const struct iid_vtable _3DGroup_interfaces[] = { 252bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_OBJECT, INTERFACE_IMPLICIT, 25372a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(C3DGroup, mObject)}, 254bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_DYNAMICINTERFACEMANAGEMENT, INTERFACE_IMPLICIT, 25572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(C3DGroup, mDynamicInterfaceManagement)}, 256bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_3DLOCATION, INTERFACE_IMPLICIT, 25772a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(C3DGroup, m3DLocation)}, 258bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_3DDOPPLER, INTERFACE_DYNAMIC_GAME, 25972a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(C3DGroup, m3DDoppler)}, 260bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_3DSOURCE, INTERFACE_GAME, 26172a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(C3DGroup, m3DSource)}, 262bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_3DMACROSCOPIC, INTERFACE_OPTIONAL, 26372a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(C3DGroup, m3DMacroscopic)}, 264bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}; 265bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten 266a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten/*static*/ const ClassTable C3DGroup_class = { 267bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten _3DGroup_interfaces, 268bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten sizeof(_3DGroup_interfaces)/sizeof(_3DGroup_interfaces[0]), 269bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten MPH_to_3DGroup, 270bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten //"3DGroup", 27172a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten sizeof(C3DGroup), 272bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten SL_OBJECTID_3DGROUP, 273bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten NULL, 27472a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten NULL, 275bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten NULL 276d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten}; 277d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten 278bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten// AudioPlayer class 279bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten 280bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten/* AudioPlayer private functions */ 2812045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten 2822045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten#ifdef USE_SNDFILE 2832045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten 2842045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten// FIXME should run this asynchronously esp. for socket fd, not on mix thread 2852045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kastenstatic void SLAPIENTRY SndFile_Callback(SLBufferQueueItf caller, void *pContext) 2862045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{ 2872045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten struct SndFile *this = (struct SndFile *) pContext; 2882045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten SLresult result; 2892045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten if (NULL != this->mRetryBuffer && 0 < this->mRetrySize) { 290bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten result = (*caller)->Enqueue(caller, this->mRetryBuffer, 291bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten this->mRetrySize); 2922045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten if (SL_RESULT_BUFFER_INSUFFICIENT == result) 2932045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten return; // what, again? 2942045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten assert(SL_RESULT_SUCCESS == result); 2952045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten this->mRetryBuffer = NULL; 2962045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten this->mRetrySize = 0; 2972045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten return; 2982045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten } 2992045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten short *pBuffer = this->mIs0 ? this->mBuffer0 : this->mBuffer1; 3002045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten this->mIs0 ^= SL_BOOLEAN_TRUE; 3012045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten sf_count_t count; 3022045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten // FIXME magic number 3032045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten count = sf_read_short(this->mSNDFILE, pBuffer, (sf_count_t) 512); 3042045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten if (0 < count) { 3052045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten SLuint32 size = count * sizeof(short); 3062045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten // FIXME if we had an internal API, could call this directly 3072045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten result = (*caller)->Enqueue(caller, pBuffer, size); 3082045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten if (SL_RESULT_BUFFER_INSUFFICIENT == result) { 3092045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten this->mRetryBuffer = pBuffer; 3102045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten this->mRetrySize = size; 3112045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten return; 3122045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten } 3132045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten assert(SL_RESULT_SUCCESS == result); 3142045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten } 3152045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten} 3162045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten 3172045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kastenstatic SLboolean SndFile_IsSupported(const SF_INFO *sfinfo) 3182045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{ 3192045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten switch (sfinfo->format & SF_FORMAT_TYPEMASK) { 3202045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten case SF_FORMAT_WAV: 3212045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten break; 3222045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten default: 3232045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten return SL_BOOLEAN_FALSE; 3242045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten } 3252045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten switch (sfinfo->format & SF_FORMAT_SUBMASK) { 3262045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten case SF_FORMAT_PCM_16: 3272045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten break; 3282045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten default: 3292045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten return SL_BOOLEAN_FALSE; 3302045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten } 3312045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten switch (sfinfo->samplerate) { 3322045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten case 44100: 3332045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten break; 3342045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten default: 3352045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten return SL_BOOLEAN_FALSE; 3362045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten } 3372045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten switch (sfinfo->channels) { 3382045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten case 2: 3392045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten break; 3402045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten default: 3412045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten return SL_BOOLEAN_FALSE; 3422045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten } 3432045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten return SL_BOOLEAN_TRUE; 3442045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten} 3452045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten 346bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#endif // USE_SNDFILE 3472045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten 348a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi 349bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic SLresult AudioPlayer_Realize(void *self) 350bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{ 35172a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten CAudioPlayer *this = (CAudioPlayer *) self; 352bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten SLresult result = SL_RESULT_SUCCESS; 35348913d4519d5112319c4277d4966435fec2f551cJean-Michel Trivi 354a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi#ifdef USE_ANDROID 355a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi // FIXME move this to android specific files 35648913d4519d5112319c4277d4966435fec2f551cJean-Michel Trivi result = sles_to_android_realizeAudioPlayer(this); 357a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi#endif 358a852e9eca77c64fcba11eb590bec7a11aca5fe16Jean-Michel Trivi 359bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#ifdef USE_SNDFILE 3602045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten if (NULL != this->mSndFile.mPathname) { 3612045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten SF_INFO sfinfo; 3622045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten sfinfo.format = 0; 3632045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten this->mSndFile.mSNDFILE = sf_open( 3642045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten (const char *) this->mSndFile.mPathname, SFM_READ, &sfinfo); 3652045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten if (NULL == this->mSndFile.mSNDFILE) { 3662045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten result = SL_RESULT_CONTENT_NOT_FOUND; 3672045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten } else if (!SndFile_IsSupported(&sfinfo)) { 3682045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten sf_close(this->mSndFile.mSNDFILE); 3692045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten this->mSndFile.mSNDFILE = NULL; 3702045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten result = SL_RESULT_CONTENT_UNSUPPORTED; 3712045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten } else { 37229b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten // FIXME how do we know this interface is exposed? 373bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten SLBufferQueueItf bufferQueue = &this->mBufferQueue.mItf; 3742045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten // FIXME should use a private internal API, and disallow 3752045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten // application to have access to our buffer queue 3762045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten // FIXME if we had an internal API, could call this directly 37729b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten // FIXME can't call this directly as we get a double lock 37829b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten // result = (*bufferQueue)->RegisterCallback(bufferQueue, 37929b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten // SndFile_Callback, &this->mSndFile); 38029b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten // FIXME so let's inline the code, but this is maintenance risk 38129b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten // we know we are called by Object_Realize, which holds a lock, 38229b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten // but if interface lock != object lock, need to rewrite this 38372a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten IBufferQueue *thisBQ = 38472a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten (IBufferQueue *) bufferQueue; 38529b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten thisBQ->mCallback = SndFile_Callback; 38629b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten thisBQ->mContext = &this->mSndFile; 3872045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten } 3882045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten } 389bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#endif // USE_SNDFILE 3902045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten return result; 3912045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten} 3922045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten 393bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic void AudioPlayer_Destroy(void *self) 3942045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{ 39572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten CAudioPlayer *this = (CAudioPlayer *) self; 3962045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten // FIXME stop the player in a way that app can't restart it 397bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten // Free the buffer queue, if it was larger than typical 398bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten if (NULL != this->mBufferQueue.mArray && 399bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten this->mBufferQueue.mArray != this->mBufferQueue.mTypical) { 4002045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten free(this->mBufferQueue.mArray); 401bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten this->mBufferQueue.mArray = NULL; 402bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten } 4032045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten#ifdef USE_SNDFILE 4042045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten if (NULL != this->mSndFile.mSNDFILE) { 4052045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten sf_close(this->mSndFile.mSNDFILE); 4062045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten this->mSndFile.mSNDFILE = NULL; 4072045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten } 408bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#endif // USE_SNDFILE 409bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten} 410bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten 411bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic const struct iid_vtable AudioPlayer_interfaces[] = { 412bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_OBJECT, INTERFACE_IMPLICIT, 41372a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CAudioPlayer, mObject)}, 414bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_DYNAMICINTERFACEMANAGEMENT, INTERFACE_IMPLICIT, 41572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CAudioPlayer, mDynamicInterfaceManagement)}, 416bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_PLAY, INTERFACE_IMPLICIT, 41772a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CAudioPlayer, mPlay)}, 418bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_3DDOPPLER, INTERFACE_DYNAMIC_GAME, 41972a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CAudioPlayer, m3DDoppler)}, 420bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_3DGROUPING, INTERFACE_GAME, 42172a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CAudioPlayer, m3DGrouping)}, 422bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_3DLOCATION, INTERFACE_GAME, 42372a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CAudioPlayer, m3DLocation)}, 424bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_3DSOURCE, INTERFACE_GAME, 42572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CAudioPlayer, m3DSource)}, 426bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten // FIXME Currently we create an internal buffer queue for playing files 427bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_BUFFERQUEUE, /* INTERFACE_GAME */ INTERFACE_IMPLICIT, 42872a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CAudioPlayer, mBufferQueue)}, 429bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_EFFECTSEND, INTERFACE_MUSIC_GAME, 43072a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CAudioPlayer, mEffectSend)}, 431bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_MUTESOLO, INTERFACE_GAME, 43272a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CAudioPlayer, mMuteSolo)}, 433bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_METADATAEXTRACTION, INTERFACE_MUSIC_GAME, 43472a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CAudioPlayer, mMetadataExtraction)}, 435bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_METADATATRAVERSAL, INTERFACE_MUSIC_GAME, 43672a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CAudioPlayer, mMetadataTraversal)}, 437bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_PREFETCHSTATUS, INTERFACE_TBD, 43872a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CAudioPlayer, mPrefetchStatus)}, 439bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_RATEPITCH, INTERFACE_DYNAMIC_GAME, 44072a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CAudioPlayer, mRatePitch)}, 441bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_SEEK, INTERFACE_TBD, 44272a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CAudioPlayer, mSeek)}, 443bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_VOLUME, INTERFACE_TBD, 44472a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CAudioPlayer, mVolume)}, 445bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_3DMACROSCOPIC, INTERFACE_OPTIONAL, 44672a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CAudioPlayer, m3DMacroscopic)}, 447bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_BASSBOOST, INTERFACE_OPTIONAL, 44872a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CAudioPlayer, mBassBoost)}, 449bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_DYNAMICSOURCE, INTERFACE_OPTIONAL, 45072a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CAudioPlayer, mDynamicSource)}, 451bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_ENVIRONMENTALREVERB, INTERFACE_OPTIONAL, 45272a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CAudioPlayer, mEnvironmentalReverb)}, 453bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_EQUALIZER, INTERFACE_OPTIONAL, 45472a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CAudioPlayer, mEqualizer)}, 455bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_PITCH, INTERFACE_OPTIONAL, 45672a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CAudioPlayer, mPitch)}, 457bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_PRESETREVERB, INTERFACE_OPTIONAL, 45872a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CAudioPlayer, mPresetReverb)}, 459bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_PLAYBACKRATE, INTERFACE_OPTIONAL, 46072a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CAudioPlayer, mPlaybackRate)}, 461bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_VIRTUALIZER, INTERFACE_OPTIONAL, 46272a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CAudioPlayer, mVirtualizer)}, 463bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_VISUALIZATION, INTERFACE_OPTIONAL, 46472a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CAudioPlayer, mVisualization)} 465bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}; 466bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten 467a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kastenstatic const ClassTable CAudioPlayer_class = { 468bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten AudioPlayer_interfaces, 469bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten sizeof(AudioPlayer_interfaces)/sizeof(AudioPlayer_interfaces[0]), 470bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten MPH_to_AudioPlayer, 471bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten //"AudioPlayer", 47272a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten sizeof(CAudioPlayer), 473bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten SL_OBJECTID_AUDIOPLAYER, 474bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten AudioPlayer_Realize, 47529b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten NULL /*AudioPlayer_Resume*/, 476bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten AudioPlayer_Destroy 477bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}; 478bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten 479bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten// AudioRecorder class 480bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten 481bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic const struct iid_vtable AudioRecorder_interfaces[] = { 482bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_OBJECT, INTERFACE_IMPLICIT, 48372a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CAudioRecorder, mObject)}, 484bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_DYNAMICINTERFACEMANAGEMENT, INTERFACE_IMPLICIT, 48572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CAudioRecorder, mDynamicInterfaceManagement)}, 486bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_RECORD, INTERFACE_IMPLICIT, 48772a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CAudioRecorder, mRecord)}, 488bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_AUDIOENCODER, INTERFACE_TBD, 48972a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CAudioRecorder, mAudioEncoder)}, 490bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_BASSBOOST, INTERFACE_OPTIONAL, 49172a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CAudioRecorder, mBassBoost)}, 492bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_DYNAMICSOURCE, INTERFACE_OPTIONAL, 49372a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CAudioRecorder, mDynamicSource)}, 494bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_EQUALIZER, INTERFACE_OPTIONAL, 49572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CAudioRecorder, mEqualizer)}, 496bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_VISUALIZATION, INTERFACE_OPTIONAL, 49772a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CAudioRecorder, mVisualization)}, 498bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_VOLUME, INTERFACE_OPTIONAL, 49972a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CAudioRecorder, mVolume)} 500bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}; 501bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten 502a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kastenstatic const ClassTable CAudioRecorder_class = { 503bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten AudioRecorder_interfaces, 504bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten sizeof(AudioRecorder_interfaces)/sizeof(AudioRecorder_interfaces[0]), 505bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten MPH_to_AudioRecorder, 506bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten //"AudioRecorder", 50772a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten sizeof(CAudioRecorder), 508bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten SL_OBJECTID_AUDIORECORDER, 509bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten NULL, 51029b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten NULL, 511bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten NULL 512bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}; 513bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten 514bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten// Engine class 515bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten 516bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic const struct iid_vtable Engine_interfaces[] = { 517bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_OBJECT, INTERFACE_IMPLICIT, 51872a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CEngine, mObject)}, 519bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_DYNAMICINTERFACEMANAGEMENT, INTERFACE_IMPLICIT, 52072a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CEngine, mDynamicInterfaceManagement)}, 521bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_ENGINE, INTERFACE_IMPLICIT, 52272a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CEngine, mEngine)}, 523bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_ENGINECAPABILITIES, INTERFACE_IMPLICIT, 52472a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CEngine, mEngineCapabilities)}, 525bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_THREADSYNC, INTERFACE_IMPLICIT, 52672a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CEngine, mThreadSync)}, 527bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_AUDIOIODEVICECAPABILITIES, INTERFACE_IMPLICIT, 52872a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CEngine, mAudioIODeviceCapabilities)}, 529bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_AUDIODECODERCAPABILITIES, INTERFACE_EXPLICIT, 53072a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CEngine, mAudioDecoderCapabilities)}, 531bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_AUDIOENCODERCAPABILITIES, INTERFACE_EXPLICIT, 53272a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CEngine, mAudioEncoderCapabilities)}, 533bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_3DCOMMIT, INTERFACE_EXPLICIT_GAME, 53472a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CEngine, m3DCommit)}, 535bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_DEVICEVOLUME, INTERFACE_OPTIONAL, 53672a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CEngine, mDeviceVolume)} 537bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}; 538bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten 539a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kastenstatic const ClassTable CEngine_class = { 540bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten Engine_interfaces, 541bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten sizeof(Engine_interfaces)/sizeof(Engine_interfaces[0]), 542bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten MPH_to_Engine, 543bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten //"Engine", 54472a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten sizeof(CEngine), 545bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten SL_OBJECTID_ENGINE, 546bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten NULL, 54729b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten NULL, 548bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten NULL 549bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}; 550bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten 551bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten// LEDDevice class 552bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten 553bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic const struct iid_vtable LEDDevice_interfaces[] = { 554bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_OBJECT, INTERFACE_IMPLICIT, 55572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CLEDDevice, mObject)}, 556bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_DYNAMICINTERFACEMANAGEMENT, INTERFACE_IMPLICIT, 55772a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CLEDDevice, mDynamicInterfaceManagement)}, 558bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_LED, INTERFACE_IMPLICIT, 55972a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CLEDDevice, mLEDArray)} 560bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}; 561bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten 562a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kastenstatic const ClassTable CLEDDevice_class = { 563bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten LEDDevice_interfaces, 564bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten sizeof(LEDDevice_interfaces)/sizeof(LEDDevice_interfaces[0]), 565bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten MPH_to_LEDDevice, 566bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten //"LEDDevice", 56772a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten sizeof(CLEDDevice), 568bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten SL_OBJECTID_LEDDEVICE, 569bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten NULL, 57029b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten NULL, 571bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten NULL 572bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}; 573bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten 574bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten// Listener class 575bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten 576bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic const struct iid_vtable Listener_interfaces[] = { 577bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_OBJECT, INTERFACE_IMPLICIT, 57872a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CListener, mObject)}, 579bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_DYNAMICINTERFACEMANAGEMENT, INTERFACE_IMPLICIT, 58072a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CListener, mDynamicInterfaceManagement)}, 581bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_3DDOPPLER, INTERFACE_DYNAMIC_GAME, 58272a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(C3DGroup, m3DDoppler)}, 583bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_3DLOCATION, INTERFACE_EXPLICIT_GAME, 58472a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(C3DGroup, m3DLocation)} 585bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}; 586bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten 587a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kastenstatic const ClassTable CListener_class = { 588bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten Listener_interfaces, 589bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten sizeof(Listener_interfaces)/sizeof(Listener_interfaces[0]), 590bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten MPH_to_Listener, 591bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten //"Listener", 59272a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten sizeof(CListener), 593bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten SL_OBJECTID_LISTENER, 594bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten NULL, 59529b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten NULL, 596bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten NULL 597bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}; 598bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten 599bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten// MetadataExtractor class 600bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten 601bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic const struct iid_vtable MetadataExtractor_interfaces[] = { 602bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_OBJECT, INTERFACE_IMPLICIT, 60372a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CMetadataExtractor, mObject)}, 604bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_DYNAMICINTERFACEMANAGEMENT, INTERFACE_IMPLICIT, 60572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CMetadataExtractor, mDynamicInterfaceManagement)}, 606bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_DYNAMICSOURCE, INTERFACE_IMPLICIT, 60772a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CMetadataExtractor, mDynamicSource)}, 608bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_METADATAEXTRACTION, INTERFACE_IMPLICIT, 60972a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CMetadataExtractor, mMetadataExtraction)}, 610bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_METADATATRAVERSAL, INTERFACE_IMPLICIT, 61172a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CMetadataExtractor, mMetadataTraversal)} 612bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}; 613bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten 614a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kastenstatic const ClassTable CMetadataExtractor_class = { 615bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten MetadataExtractor_interfaces, 616bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten sizeof(MetadataExtractor_interfaces) / 617bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten sizeof(MetadataExtractor_interfaces[0]), 618bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten MPH_to_MetadataExtractor, 619bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten //"MetadataExtractor", 62072a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten sizeof(CMetadataExtractor), 621bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten SL_OBJECTID_METADATAEXTRACTOR, 622bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten NULL, 62329b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten NULL, 624bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten NULL 625bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}; 626bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten 627bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten// MidiPlayer class 628bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten 629bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic const struct iid_vtable MidiPlayer_interfaces[] = { 630bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_OBJECT, INTERFACE_IMPLICIT, 63172a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CMidiPlayer, mObject)}, 632bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_DYNAMICINTERFACEMANAGEMENT, INTERFACE_IMPLICIT, 63372a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CMidiPlayer, mDynamicInterfaceManagement)}, 634bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_PLAY, INTERFACE_IMPLICIT, 63572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CMidiPlayer, mPlay)}, 636bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_3DDOPPLER, INTERFACE_DYNAMIC_GAME, 63772a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(C3DGroup, m3DDoppler)}, 638bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_3DGROUPING, INTERFACE_GAME, 63972a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CMidiPlayer, m3DGrouping)}, 640bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_3DLOCATION, INTERFACE_GAME, 64172a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CMidiPlayer, m3DLocation)}, 642bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_3DSOURCE, INTERFACE_GAME, 64372a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CMidiPlayer, m3DSource)}, 644bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_BUFFERQUEUE, INTERFACE_GAME, 64572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CMidiPlayer, mBufferQueue)}, 646bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_EFFECTSEND, INTERFACE_GAME, 64772a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CMidiPlayer, mEffectSend)}, 648bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_MUTESOLO, INTERFACE_GAME, 64972a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CMidiPlayer, mMuteSolo)}, 650bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_METADATAEXTRACTION, INTERFACE_GAME, 65172a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CMidiPlayer, mMetadataExtraction)}, 652bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_METADATATRAVERSAL, INTERFACE_GAME, 65372a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CMidiPlayer, mMetadataTraversal)}, 654bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_MIDIMESSAGE, INTERFACE_PHONE_GAME, 65572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CMidiPlayer, mMIDIMessage)}, 656bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_MIDITIME, INTERFACE_PHONE_GAME, 65772a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CMidiPlayer, mMIDITime)}, 658bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_MIDITEMPO, INTERFACE_PHONE_GAME, 65972a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CMidiPlayer, mMIDITempo)}, 660bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_MIDIMUTESOLO, INTERFACE_GAME, 66172a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CMidiPlayer, mMIDIMuteSolo)}, 662bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_PREFETCHSTATUS, INTERFACE_PHONE_GAME, 66372a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CMidiPlayer, mPrefetchStatus)}, 664bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_SEEK, INTERFACE_PHONE_GAME, 66572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CMidiPlayer, mSeek)}, 666bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_VOLUME, INTERFACE_PHONE_GAME, 66772a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CMidiPlayer, mVolume)}, 668bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_3DMACROSCOPIC, INTERFACE_OPTIONAL, 66972a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CMidiPlayer, m3DMacroscopic)}, 670bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_BASSBOOST, INTERFACE_OPTIONAL, 67172a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CMidiPlayer, mBassBoost)}, 672bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_DYNAMICSOURCE, INTERFACE_OPTIONAL, 67372a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CMidiPlayer, mDynamicSource)}, 674bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_ENVIRONMENTALREVERB, INTERFACE_OPTIONAL, 67572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CMidiPlayer, mEnvironmentalReverb)}, 676bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_EQUALIZER, INTERFACE_OPTIONAL, 67772a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CMidiPlayer, mEqualizer)}, 678bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_PITCH, INTERFACE_OPTIONAL, 67972a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CMidiPlayer, mPitch)}, 680bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_PRESETREVERB, INTERFACE_OPTIONAL, 68172a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CMidiPlayer, mPresetReverb)}, 682bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_PLAYBACKRATE, INTERFACE_OPTIONAL, 68372a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CMidiPlayer, mPlaybackRate)}, 684bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_VIRTUALIZER, INTERFACE_OPTIONAL, 68572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CMidiPlayer, mVirtualizer)}, 686bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_VISUALIZATION, INTERFACE_OPTIONAL, 68772a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CMidiPlayer, mVisualization)} 688bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}; 689bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten 690a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kastenstatic const ClassTable CMidiPlayer_class = { 691bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten MidiPlayer_interfaces, 692bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten sizeof(MidiPlayer_interfaces)/sizeof(MidiPlayer_interfaces[0]), 693bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten MPH_to_MidiPlayer, 694bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten //"MidiPlayer", 69572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten sizeof(CMidiPlayer), 696bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten SL_OBJECTID_MIDIPLAYER, 697bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten NULL, 69829b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten NULL, 699bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten NULL 700bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}; 701bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten 702bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten// OutputMix class 703bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten 704bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic const struct iid_vtable OutputMix_interfaces[] = { 705bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_OBJECT, INTERFACE_IMPLICIT, 70672a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(COutputMix, mObject)}, 707bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_DYNAMICINTERFACEMANAGEMENT, INTERFACE_IMPLICIT, 70872a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(COutputMix, mDynamicInterfaceManagement)}, 709bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_OUTPUTMIX, INTERFACE_IMPLICIT, 71072a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(COutputMix, mOutputMix)}, 711bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#ifdef USE_OUTPUTMIXEXT 712bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_OUTPUTMIXEXT, INTERFACE_IMPLICIT, 71372a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(COutputMix, mOutputMixExt)}, 714bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#else 715bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_OUTPUTMIXEXT, INTERFACE_TBD /*NOT AVAIL*/, 0}, 716bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#endif 717bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_ENVIRONMENTALREVERB, INTERFACE_DYNAMIC_GAME, 71872a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(COutputMix, mEnvironmentalReverb)}, 719bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_EQUALIZER, INTERFACE_DYNAMIC_MUSIC_GAME, 72072a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(COutputMix, mEqualizer)}, 721bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_PRESETREVERB, INTERFACE_DYNAMIC_MUSIC, 72272a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(COutputMix, mPresetReverb)}, 723bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_VIRTUALIZER, INTERFACE_DYNAMIC_MUSIC_GAME, 72472a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(COutputMix, mVirtualizer)}, 725bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_VOLUME, INTERFACE_GAME_MUSIC, 72672a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(COutputMix, mVolume)}, 727bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_BASSBOOST, INTERFACE_OPTIONAL_DYNAMIC, 72872a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(COutputMix, mBassBoost)}, 729bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_VISUALIZATION, INTERFACE_OPTIONAL, 73072a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(COutputMix, mVisualization)} 731bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}; 732bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten 733a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kastenstatic const ClassTable COutputMix_class = { 734bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten OutputMix_interfaces, 735bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten sizeof(OutputMix_interfaces)/sizeof(OutputMix_interfaces[0]), 736bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten MPH_to_OutputMix, 737bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten //"OutputMix", 73872a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten sizeof(COutputMix), 739bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten SL_OBJECTID_OUTPUTMIX, 740bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten NULL, 74129b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten NULL, 742bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten NULL 743bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}; 744bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten 745bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten// Vibra class 746bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten 747bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kastenstatic const struct iid_vtable VibraDevice_interfaces[] = { 748bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_OBJECT, INTERFACE_OPTIONAL, 74972a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CVibraDevice, mObject)}, 750bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_DYNAMICINTERFACEMANAGEMENT, INTERFACE_OPTIONAL, 75172a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CVibraDevice, mDynamicInterfaceManagement)}, 752bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten {MPH_VIBRA, INTERFACE_OPTIONAL, 75372a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten offsetof(CVibraDevice, mVibra)} 754bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}; 755bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten 756a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kastenstatic const ClassTable CVibraDevice_class = { 757bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten VibraDevice_interfaces, 758bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten sizeof(VibraDevice_interfaces)/sizeof(VibraDevice_interfaces[0]), 759bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten MPH_to_Vibra, 760bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten //"VibraDevice", 76172a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten sizeof(CVibraDevice), 762bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten SL_OBJECTID_VIBRADEVICE, 763bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten NULL, 76429b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten NULL, 765bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten NULL 766bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}; 767bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten 768bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten/* Map SL_OBJECTID to class */ 769bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten 77072a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kastenstatic const ClassTable * const classes[] = { 771bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten // Do not change order of these entries; they are in numerical order 772a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten &CEngine_class, 773a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten &CLEDDevice_class, 774a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten &CAudioPlayer_class, 775a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten &CAudioRecorder_class, 776a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten &CMidiPlayer_class, 777a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten &CListener_class, 778a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten &C3DGroup_class, 779a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten &CVibraDevice_class, 780a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten &COutputMix_class, 781a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten &CMetadataExtractor_class 782bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}; 783bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten 78472a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kastenstatic const ClassTable *objectIDtoClass(SLuint32 objectID) 785bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{ 786bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten SLuint32 objectID0 = classes[0]->mObjectID; 787bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten if (objectID0 <= objectID && 788bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten classes[sizeof(classes)/sizeof(classes[0])-1]->mObjectID >= objectID) 789bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten return classes[objectID - objectID0]; 790bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten return NULL; 791bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten} 792bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten 793bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten// Construct a new instance of the specified class, exposing selected interfaces 794bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten 79572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kastenstatic IObject *construct(const ClassTable *class__, 79629b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten unsigned exposedMask, SLEngineItf engine) 797bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten{ 79872a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten IObject *this; 799bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#ifndef NDEBUG 80072a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten this = (IObject *) malloc(class__->mSize); 801bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#else 80272a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten this = (IObject *) calloc(1, class__->mSize); 803bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#endif 804bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten if (NULL != this) { 805bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#ifndef NDEBUG 806bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten // for debugging, to detect uninitialized fields 807bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten memset(this, 0x55, class__->mSize); 808bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#endif 80929b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten this->mClass = class__; 81029b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten this->mExposedMask = exposedMask; 81172a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten unsigned lossOfControlMask = 0; 81272a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten IEngine *thisEngine = (IEngine *) engine; 81372a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten if (NULL == thisEngine) 81472a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten thisEngine = &((CEngine *) this)->mEngine; 81572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten else if (thisEngine->mLossOfControlGlobal) 81672a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten lossOfControlMask = ~0; 81772a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten this->mLossOfControlMask = lossOfControlMask; 818bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten const struct iid_vtable *x = class__->mInterfaces; 819bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten unsigned i; 820bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten for (i = 0; exposedMask; ++i, ++x, exposedMask >>= 1) { 821bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten if (exposedMask & 1) { 82283f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten void *self = (char *) this + x->mOffset; 82372a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten ((IObject **) self)[1] = this; 82483f93b0afd3607b1570d8473c2f6e45276c133baGlenn Kasten VoidHook init = MPH_init_table[x->mMPH].mInit; 825bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten if (NULL != init) 826bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten (*init)(self); 827bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten } 828bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten } 82972a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten // FIXME need a lock 83072a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten if (INSTANCE_MAX > thisEngine->mInstanceCount) { 83172a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten // FIXME ignores Destroy 83272a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten thisEngine->mInstances[thisEngine->mInstanceCount++] = this; 83372a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten } 83472a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten // FIXME else what 835bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten } 836bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten return this; 837bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten} 838bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten 8390b167267bda99b68346045ccab14e810121d5de4Glenn Kasten// Runs every graphics frame (50 Hz) to update audio 840d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten 8410b167267bda99b68346045ccab14e810121d5de4Glenn Kastenstatic void *frame_body(void *arg) 842d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{ 8430b167267bda99b68346045ccab14e810121d5de4Glenn Kasten CEngine *this = (CEngine *) arg; 8440b167267bda99b68346045ccab14e810121d5de4Glenn Kasten for (;;) { 8450b167267bda99b68346045ccab14e810121d5de4Glenn Kasten usleep(20000*50); 8460b167267bda99b68346045ccab14e810121d5de4Glenn Kasten unsigned i; 8470b167267bda99b68346045ccab14e810121d5de4Glenn Kasten for (i = 0; i < INSTANCE_MAX; ++i) { 8480b167267bda99b68346045ccab14e810121d5de4Glenn Kasten IObject *instance = (IObject *) this->mEngine.mInstances[i]; 8490b167267bda99b68346045ccab14e810121d5de4Glenn Kasten if (NULL == instance) 8500b167267bda99b68346045ccab14e810121d5de4Glenn Kasten continue; 8510b167267bda99b68346045ccab14e810121d5de4Glenn Kasten if (instance->mClass != &CAudioPlayer_class) 8520b167267bda99b68346045ccab14e810121d5de4Glenn Kasten continue; 8530b167267bda99b68346045ccab14e810121d5de4Glenn Kasten write(1, ".", 1); 8540b167267bda99b68346045ccab14e810121d5de4Glenn Kasten } 8552045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten } 8560b167267bda99b68346045ccab14e810121d5de4Glenn Kasten return NULL; 857d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten} 858d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten 8590b167267bda99b68346045ccab14e810121d5de4Glenn Kasten/* Initial entry points */ 860d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten 8610b167267bda99b68346045ccab14e810121d5de4Glenn KastenSLresult SLAPIENTRY slCreateEngine(SLObjectItf *pEngine, SLuint32 numOptions, 8620b167267bda99b68346045ccab14e810121d5de4Glenn Kasten const SLEngineOption *pEngineOptions, SLuint32 numInterfaces, 8630b167267bda99b68346045ccab14e810121d5de4Glenn Kasten const SLInterfaceID *pInterfaceIds, const SLboolean *pInterfaceRequired) 864d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{ 8650b167267bda99b68346045ccab14e810121d5de4Glenn Kasten if (NULL == pEngine) 866d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten return SL_RESULT_PARAMETER_INVALID; 8670b167267bda99b68346045ccab14e810121d5de4Glenn Kasten *pEngine = NULL; 8680b167267bda99b68346045ccab14e810121d5de4Glenn Kasten // default values 8690b167267bda99b68346045ccab14e810121d5de4Glenn Kasten SLboolean threadSafe = SL_BOOLEAN_TRUE; 8700b167267bda99b68346045ccab14e810121d5de4Glenn Kasten SLboolean lossOfControlGlobal = SL_BOOLEAN_FALSE; 8710b167267bda99b68346045ccab14e810121d5de4Glenn Kasten if (NULL != pEngineOptions) { 8720b167267bda99b68346045ccab14e810121d5de4Glenn Kasten SLuint32 i; 8730b167267bda99b68346045ccab14e810121d5de4Glenn Kasten const SLEngineOption *option = pEngineOptions; 8740b167267bda99b68346045ccab14e810121d5de4Glenn Kasten for (i = 0; i < numOptions; ++i, ++option) { 8750b167267bda99b68346045ccab14e810121d5de4Glenn Kasten switch (option->feature) { 8760b167267bda99b68346045ccab14e810121d5de4Glenn Kasten case SL_ENGINEOPTION_THREADSAFE: 8770b167267bda99b68346045ccab14e810121d5de4Glenn Kasten threadSafe = (SLboolean) option->data; 8780b167267bda99b68346045ccab14e810121d5de4Glenn Kasten break; 8790b167267bda99b68346045ccab14e810121d5de4Glenn Kasten case SL_ENGINEOPTION_LOSSOFCONTROL: 8800b167267bda99b68346045ccab14e810121d5de4Glenn Kasten lossOfControlGlobal = (SLboolean) option->data; 8810b167267bda99b68346045ccab14e810121d5de4Glenn Kasten break; 8820b167267bda99b68346045ccab14e810121d5de4Glenn Kasten default: 8830b167267bda99b68346045ccab14e810121d5de4Glenn Kasten return SL_RESULT_PARAMETER_INVALID; 8840b167267bda99b68346045ccab14e810121d5de4Glenn Kasten } 8850b167267bda99b68346045ccab14e810121d5de4Glenn Kasten } 88629b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten } 8870b167267bda99b68346045ccab14e810121d5de4Glenn Kasten unsigned exposedMask; 8880b167267bda99b68346045ccab14e810121d5de4Glenn Kasten SLresult result = checkInterfaces(&CEngine_class, numInterfaces, 8890b167267bda99b68346045ccab14e810121d5de4Glenn Kasten pInterfaceIds, pInterfaceRequired, &exposedMask); 8900b167267bda99b68346045ccab14e810121d5de4Glenn Kasten if (SL_RESULT_SUCCESS != result) 8910b167267bda99b68346045ccab14e810121d5de4Glenn Kasten return result; 8920b167267bda99b68346045ccab14e810121d5de4Glenn Kasten CEngine *this = (CEngine *) 8930b167267bda99b68346045ccab14e810121d5de4Glenn Kasten construct(&CEngine_class, exposedMask, NULL); 8940b167267bda99b68346045ccab14e810121d5de4Glenn Kasten if (NULL == this) 8950b167267bda99b68346045ccab14e810121d5de4Glenn Kasten return SL_RESULT_MEMORY_FAILURE; 8960b167267bda99b68346045ccab14e810121d5de4Glenn Kasten this->mObject.mLossOfControlMask = lossOfControlGlobal ? ~0 : 0; 8970b167267bda99b68346045ccab14e810121d5de4Glenn Kasten this->mEngine.mLossOfControlGlobal = lossOfControlGlobal; 8980b167267bda99b68346045ccab14e810121d5de4Glenn Kasten this->mEngineCapabilities.mThreadSafe = threadSafe; 8990b167267bda99b68346045ccab14e810121d5de4Glenn Kasten int ok; 9000b167267bda99b68346045ccab14e810121d5de4Glenn Kasten ok = pthread_create(&this->mFrameThread, (const pthread_attr_t *) NULL, 9010b167267bda99b68346045ccab14e810121d5de4Glenn Kasten frame_body, this); 9020b167267bda99b68346045ccab14e810121d5de4Glenn Kasten assert(ok == 0); 9030b167267bda99b68346045ccab14e810121d5de4Glenn Kasten *pEngine = &this->mObject.mItf; 904d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten return SL_RESULT_SUCCESS; 905d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten} 906d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten 9070b167267bda99b68346045ccab14e810121d5de4Glenn KastenSLresult SLAPIENTRY slQueryNumSupportedEngineInterfaces( 9080b167267bda99b68346045ccab14e810121d5de4Glenn Kasten SLuint32 *pNumSupportedInterfaces) 909d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{ 9100b167267bda99b68346045ccab14e810121d5de4Glenn Kasten if (NULL == pNumSupportedInterfaces) 9112045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten return SL_RESULT_PARAMETER_INVALID; 9120b167267bda99b68346045ccab14e810121d5de4Glenn Kasten *pNumSupportedInterfaces = CEngine_class.mInterfaceCount; 913d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten return SL_RESULT_SUCCESS; 914d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten} 915d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten 9160b167267bda99b68346045ccab14e810121d5de4Glenn KastenSLresult SLAPIENTRY slQuerySupportedEngineInterfaces(SLuint32 index, 9170b167267bda99b68346045ccab14e810121d5de4Glenn Kasten SLInterfaceID *pInterfaceId) 918d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten{ 9190b167267bda99b68346045ccab14e810121d5de4Glenn Kasten if (sizeof(Engine_interfaces)/sizeof(Engine_interfaces[0]) < index) 9202045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten return SL_RESULT_PARAMETER_INVALID; 9210b167267bda99b68346045ccab14e810121d5de4Glenn Kasten if (NULL == pInterfaceId) 9222045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten return SL_RESULT_PARAMETER_INVALID; 9230b167267bda99b68346045ccab14e810121d5de4Glenn Kasten *pInterfaceId = &SL_IID_array[Engine_interfaces[index].mMPH]; 924d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten return SL_RESULT_SUCCESS; 925d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten} 926d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten 9270b167267bda99b68346045ccab14e810121d5de4Glenn Kasten#ifdef USE_OUTPUTMIXEXT 928d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten 9290b167267bda99b68346045ccab14e810121d5de4Glenn Kasten/* OutputMixExt implementation */ 930d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten 9310b167267bda99b68346045ccab14e810121d5de4Glenn Kasten// Used by SDL and Android but not specific to or dependent on either platform 932d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten 9330b167267bda99b68346045ccab14e810121d5de4Glenn Kastenstatic void OutputMixExt_FillBuffer(SLOutputMixExtItf self, void *pBuffer, 9340b167267bda99b68346045ccab14e810121d5de4Glenn Kasten SLuint32 size) 9352045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{ 9362045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten // Force to be a multiple of a frame, assumes stereo 16-bit PCM 9372045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten size &= ~3; 93872a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten IOutputMixExt *thisExt = 93972a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten (IOutputMixExt *) self; 94029b9008a17cae003590a5ff361e98809f02e3025Glenn Kasten // FIXME Finding one interface from another, but is it exposed? 94172a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten IOutputMix *this = 94272a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten &((COutputMix *) thisExt->mThis)->mOutputMix; 9432045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten unsigned activeMask = this->mActiveMask; 9442045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten struct Track *track = &this->mTracks[0]; 9452045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten unsigned i; 9462045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten SLboolean mixBufferHasData = SL_BOOLEAN_FALSE; 9472045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten // FIXME O(32) loop even when few tracks are active. 9482045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten // To avoid loop, use activeMask to check for active track(s) 9492045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten // and decide whether we actually need to copy or mix. 9502045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten for (i = 0; 0 != activeMask; ++i, ++track, activeMask >>= 1) { 9512045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten assert(i < 32); 9522045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten if (!(activeMask & 1)) 9532045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten continue; 9542045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten // track is allocated 95572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten IPlay *play = track->mPlay; 9562045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten if (NULL == play) 9572045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten continue; 9582045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten // track is initialized 9592045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten if (SL_PLAYSTATE_PLAYING != play->mState) 9602045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten continue; 9612045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten // track is playing 9622045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten void *dstWriter = pBuffer; 9632045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten unsigned desired = size; 9642045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten SLboolean trackContributedToMix = SL_BOOLEAN_FALSE; 9652045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten while (desired > 0) { 96672a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten IBufferQueue *bufferQueue; 9672045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten const struct BufferHeader *oldFront, *newFront, *rear; 9682045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten unsigned actual = desired; 9692045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten if (track->mAvail < actual) 9702045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten actual = track->mAvail; 9712045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten // force actual to be a frame multiple 9722045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten if (actual > 0) { 9732045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten // FIXME check for either mute or volume 0 9742045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten // in which case skip the input buffer processing 9752045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten assert(NULL != track->mReader); 9762045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten // FIXME && gain == 1.0 9772045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten if (mixBufferHasData) { 978bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten stereo *mixBuffer = (stereo *) dstWriter; 979bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten const stereo *source = (const stereo *) track->mReader; 9802045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten unsigned j; 981bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten for (j = 0; j < actual; j += sizeof(stereo), ++mixBuffer, 982bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten ++source) { 9832045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten // apply gain here 9842045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten mixBuffer->left += source->left; 9852045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten mixBuffer->right += source->right; 9862045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten } 9872045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten } else { 9882045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten memcpy(dstWriter, track->mReader, actual); 9892045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten trackContributedToMix = SL_BOOLEAN_TRUE; 9902045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten } 9912045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten dstWriter = (char *) dstWriter + actual; 9922045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten desired -= actual; 9932045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten track->mReader = (char *) track->mReader + actual; 9942045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten track->mAvail -= actual; 9952045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten if (track->mAvail == 0) { 9962045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten bufferQueue = track->mBufferQueue; 9972045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten if (NULL != bufferQueue) { 9982045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten oldFront = bufferQueue->mFront; 9992045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten rear = bufferQueue->mRear; 10002045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten assert(oldFront != rear); 10012045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten newFront = oldFront; 1002bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten if (++newFront == 1003bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten &bufferQueue->mArray[bufferQueue->mNumBuffers]) 10042045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten newFront = bufferQueue->mArray; 10052045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten bufferQueue->mFront = (struct BufferHeader *) newFront; 10062045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten assert(0 < bufferQueue->mState.count); 10072045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten --bufferQueue->mState.count; 10082045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten // FIXME here or in Enqueue? 10092045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten ++bufferQueue->mState.playIndex; 1010bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten // FIXME a good time to do an early warning 10112045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten // callback depending on buffer count 10122045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten } 10132045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten } 10142045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten continue; 10152045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten } 10162045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten // actual == 0 10172045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten bufferQueue = track->mBufferQueue; 10182045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten if (NULL != bufferQueue) { 10192045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten oldFront = bufferQueue->mFront; 10202045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten rear = bufferQueue->mRear; 10212045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten if (oldFront != rear) { 10222045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kastengot_one: 10232045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten assert(0 < bufferQueue->mState.count); 10242045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten track->mReader = oldFront->mBuffer; 10252045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten track->mAvail = oldFront->mSize; 10262045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten continue; 10272045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten } 10282045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten // FIXME should be able to configure when to 10292045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten // kick off the callback e.g. high/low water-marks etc. 1030bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten // need data but none available, attempt a desperate callback 10312045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten slBufferQueueCallback callback = bufferQueue->mCallback; 10322045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten if (NULL != callback) { 1033bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten (*callback)((SLBufferQueueItf) bufferQueue, 1034bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten bufferQueue->mContext); 1035bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten // if lucky, the callback enqueued a buffer 10362045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten if (rear != bufferQueue->mRear) 10372045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten goto got_one; 1038bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten // unlucky, queue still empty, the callback failed 10392045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten } 10402045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten // here on underflow due to no callback, or failed callback 10412045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten // FIXME underflow, send silence (or previous buffer?) 10422045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten // we did a callback to try to kick start again but failed 10432045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten // should log this 10442045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten } 1045bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten // no buffer queue or underflow, clear out rest of partial buffer 10462045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten if (!mixBufferHasData && trackContributedToMix) 10472045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten memset(dstWriter, 0, actual); 10482045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten break; 10492045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten } 10502045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten if (trackContributedToMix) 10512045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten mixBufferHasData = SL_BOOLEAN_TRUE; 10522045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten } 10532045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten // No active tracks, so output silence 10542045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten if (!mixBufferHasData) 10552045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten memset(pBuffer, 0, size); 10562045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten} 10572045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten 1058bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten/*static*/ const struct SLOutputMixExtItf_ OutputMixExt_OutputMixExtItf = { 1059bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten OutputMixExt_FillBuffer 1060bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten}; 1061bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten 1062bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#endif // USE_OUTPUTMIXEXT 1063bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten 10642045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten#ifdef USE_SDL 10652045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten 1066bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten// FIXME move to separate source file 1067bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten 10682045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten/* SDL platform implementation */ 10692045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten 10702045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kastenstatic void SDLCALL SDL_callback(void *context, Uint8 *stream, int len) 10712045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{ 10722045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten assert(len > 0); 1073bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten OutputMixExt_FillBuffer((SLOutputMixExtItf) context, stream, 1074bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten (SLuint32) len); 10752045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten} 10762045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten 10772045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kastenvoid SDL_start(SLObjectItf self) 10782045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten{ 1079bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten //assert(self != NULL); 10802045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten // FIXME make this an operation on Object: GetClass 108172a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten //IObject *this = (IObject *) self; 1082a6d984c32855a239f7f79a3d3b7f2ddfb8cb9697Glenn Kasten //assert(&COutputMix_class == this->mClass); 1083bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten SLresult result; 1084bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten SLOutputMixExtItf OutputMixExt; 1085bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten result = (*self)->GetInterface(self, SL_IID_OUTPUTMIXEXT, &OutputMixExt); 1086bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten assert(SL_RESULT_SUCCESS == result); 10872045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten 10882045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten SDL_AudioSpec fmt; 10892045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten fmt.freq = 44100; 10902045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten fmt.format = AUDIO_S16; 10912045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten fmt.channels = 2; 10922045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten fmt.samples = 256; 10932045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten fmt.callback = SDL_callback; 1094bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten // FIXME should be a GetInterface 109572a04d8e9e059dad969d166a6a70491fe1e65970Glenn Kasten // fmt.userdata = &((COutputMix *) this)->mOutputMixExt; 1096bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten fmt.userdata = (void *) OutputMixExt; 10972045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten 10982045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten if (SDL_OpenAudio(&fmt, NULL) < 0) { 10992045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten fprintf(stderr, "Unable to open audio: %s\n", SDL_GetError()); 11002045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten exit(1); 11012045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten } 11022045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten SDL_PauseAudio(0); 11032045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten} 11042045b02407f6ac0a570faee3157b24317c8a69e0Glenn Kasten 1105bd3cb772fc94c5baf0d1fe1a63693b33ca5fe9e3Glenn Kasten#endif // USE_SDL 1106d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten 11070b167267bda99b68346045ccab14e810121d5de4Glenn Kasten#include "IEngine.c" 11080b167267bda99b68346045ccab14e810121d5de4Glenn Kasten 1109d7143537437acbd4b97761a1c5bf852be9ba485aGlenn Kasten/* End */ 1110