IEffectSend.c revision a3080daa505f91df51a808c85ddb37c48745bf7c
161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten/* 261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten * Copyright (C) 2010 The Android Open Source Project 361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten * 461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten * Licensed under the Apache License, Version 2.0 (the "License"); 561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten * you may not use this file except in compliance with the License. 661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten * You may obtain a copy of the License at 761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten * 861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten * http://www.apache.org/licenses/LICENSE-2.0 961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten * 1061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten * Unless required by applicable law or agreed to in writing, software 1161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten * distributed under the License is distributed on an "AS IS" BASIS, 1261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten * See the License for the specific language governing permissions and 1461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten * limitations under the License. 1561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten */ 1661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 1761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten/* EffectSend implementation */ 1861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 1961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten#include "sles_allinclusive.h" 2061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 21343c522ebf4f9c321eef8c3b3b2945f1c1cb8846Glenn Kasten 22343c522ebf4f9c321eef8c3b3b2945f1c1cb8846Glenn Kasten/** \brief Maps AUX index to OutputMix interface index */ 23510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 24510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kastenstatic const unsigned char AUX_to_MPH[AUX_MAX] = { 25510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten MPH_ENVIRONMENTALREVERB, 26510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten MPH_PRESETREVERB 27510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten}; 28510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 29343c522ebf4f9c321eef8c3b3b2945f1c1cb8846Glenn Kasten 30e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten/** \brief This is a private function that validates the effect interface specified by the 31e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten * application when it calls EnableEffectSend, IsEnabled, SetSendLevel, or GetSendLevel. 32e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten * For the interface to be valid, it has to satisfy these requirements: 33e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten * - object is an audio player (MIDI player is not supported yet) 34e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten * - audio sink is an output mix 35e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten * - interface was exposed at object creation time or by DynamicInterface::AddInterface 36e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten * - interface was "gotten" with Object::GetInterface 37e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten */ 38343c522ebf4f9c321eef8c3b3b2945f1c1cb8846Glenn Kasten 39d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kastenstatic struct EnableLevel *getEnableLevel(IEffectSend *this, const void *pAuxEffect) 4061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{ 41343c522ebf4f9c321eef8c3b3b2945f1c1cb8846Glenn Kasten // Make sure this effect send is on an audio player, not a MIDI player 42343c522ebf4f9c321eef8c3b3b2945f1c1cb8846Glenn Kasten CAudioPlayer *audioPlayer = (SL_OBJECTID_AUDIOPLAYER == InterfaceToObjectID(this)) ? 43343c522ebf4f9c321eef8c3b3b2945f1c1cb8846Glenn Kasten (CAudioPlayer *) this->mThis : NULL; 44343c522ebf4f9c321eef8c3b3b2945f1c1cb8846Glenn Kasten if (NULL == audioPlayer) 45343c522ebf4f9c321eef8c3b3b2945f1c1cb8846Glenn Kasten return NULL; 46f51dba65751107c930759938775b75531ec1f330Glenn Kasten // Get the output mix for this player 47f51dba65751107c930759938775b75531ec1f330Glenn Kasten COutputMix *outputMix = CAudioPlayer_GetOutputMix(audioPlayer); 48510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten unsigned aux; 49510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten if (pAuxEffect == &outputMix->mEnvironmentalReverb.mItf) 50510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten aux = AUX_ENVIRONMENTALREVERB; 51510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten else if (pAuxEffect == &outputMix->mPresetReverb.mItf) 52510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten aux = AUX_PRESETREVERB; 53510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten else 54510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten return NULL; 55510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten assert(aux < AUX_MAX); 56e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten // Validate that the application has a valid interface for the effect. The interface must have 57e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten // been exposed at object creation time or by DynamicInterface::AddInterface, and it also must 58e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten // have been "gotten" with Object::GetInterface. 59510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten int index = MPH_to_OutputMix[AUX_to_MPH[aux]]; 60510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten if (0 > index) 61510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten return NULL; 62510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten unsigned mask = 1 << index; 63510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten object_lock_shared(&outputMix->mObject); 64510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten SLuint32 state = outputMix->mObject.mInterfaceStates[index]; 65510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten mask &= outputMix->mObject.mGottenMask; 66510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten object_unlock_shared(&outputMix->mObject); 67510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten switch (state) { 68510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_EXPOSED: 69510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_ADDED: 70510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_SUSPENDED: 71510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_SUSPENDING: 72510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_RESUMING_1: 73510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_RESUMING_2: 74510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten if (mask) 75510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten return &this->mEnableLevels[aux]; 76510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 77510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten default: 78510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 79510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten } 8061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten return NULL; 8161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten} 8261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 8391bfd060b992810ca092f640f77f795bc3d008beGlenn Kasten#if defined(ANDROID) && !defined(USE_BACKPORT) 84172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi/** \brief This is a private function that translates an Android effect framework status code 85172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi * to the SL ES result code used in the EnableEffectSend() function of the SLEffectSendItf 86172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi * interface. 87172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi */ 88172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivistatic SLresult translateEnableFxSendError(android::status_t status) { 89172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi switch (status) { 90172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi case android::NO_ERROR: 91172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi return SL_RESULT_SUCCESS; 92172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi break; 93172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi case android::INVALID_OPERATION: 94172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi case android::BAD_VALUE: 95172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi default: 96172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi return SL_RESULT_RESOURCE_ERROR; 97172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi break; 98172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi } 99172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi} 10091bfd060b992810ca092f640f77f795bc3d008beGlenn Kasten#endif 101172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi 102ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 10361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenstatic SLresult IEffectSend_EnableEffectSend(SLEffectSendItf self, 10461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten const void *pAuxEffect, SLboolean enable, SLmillibel initialLevel) 10561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{ 106ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_ENTER_INTERFACE 107ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 108ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten if (!((SL_MILLIBEL_MIN <= initialLevel) && (initialLevel <= 0))) { 109ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_PARAMETER_INVALID; 110ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } else { 111ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten IEffectSend *this = (IEffectSend *) self; 112ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten struct EnableLevel *enableLevel = getEnableLevel(this, pAuxEffect); 113ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten if (NULL == enableLevel) { 114ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_PARAMETER_INVALID; 115ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } else { 116ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten interface_lock_exclusive(this); 117ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten enableLevel->mEnable = SL_BOOLEAN_FALSE != enable; // normalize 118ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten enableLevel->mSendLevel = initialLevel; 119172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi#if !defined(ANDROID) || defined(USE_BACKPORT) 120ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_SUCCESS; 121172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi#else 122172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi // TODO do not repeat querying of CAudioPlayer, done inside getEnableLevel() 123172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi CAudioPlayer *ap = (SL_OBJECTID_AUDIOPLAYER == InterfaceToObjectID(this)) ? 124172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi (CAudioPlayer *) this->mThis : NULL; 125172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi // check which effect the send is attached to, attach and set level 126172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi if (NULL == ap) { 127172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi result = SL_RESULT_RESOURCE_ERROR; 128172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi } else { 129f51dba65751107c930759938775b75531ec1f330Glenn Kasten COutputMix *outputMix = CAudioPlayer_GetOutputMix(ap); 130ca325fa86f9e52d8300490eee102a3c1188f6bdcJean-Michel Trivi // the initial send level set here is the total energy on the aux bus, 131ca325fa86f9e52d8300490eee102a3c1188f6bdcJean-Michel Trivi // so it must take into account the player volume level 132f51dba65751107c930759938775b75531ec1f330Glenn Kasten if (pAuxEffect == &outputMix->mPresetReverb.mItf) { 133f51dba65751107c930759938775b75531ec1f330Glenn Kasten result = translateEnableFxSendError(android_fxSend_attach(ap, (bool) enable, 134ca325fa86f9e52d8300490eee102a3c1188f6bdcJean-Michel Trivi outputMix->mPresetReverb.mPresetReverbEffect, 135ca325fa86f9e52d8300490eee102a3c1188f6bdcJean-Michel Trivi initialLevel + ap->mVolume.mLevel)); 136f51dba65751107c930759938775b75531ec1f330Glenn Kasten } else if (pAuxEffect == &outputMix->mEnvironmentalReverb.mItf) { 137f51dba65751107c930759938775b75531ec1f330Glenn Kasten result = translateEnableFxSendError(android_fxSend_attach(ap, (bool) enable, 138ca325fa86f9e52d8300490eee102a3c1188f6bdcJean-Michel Trivi outputMix->mEnvironmentalReverb.mEnvironmentalReverbEffect, 139ca325fa86f9e52d8300490eee102a3c1188f6bdcJean-Michel Trivi initialLevel + ap->mVolume.mLevel)); 140172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi } else { 141172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi result = SL_RESULT_RESOURCE_ERROR; 142172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi } 143172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi } 144172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi#endif 145172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi interface_unlock_exclusive(this); 146ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } 147ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } 148ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 149ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_LEAVE_INTERFACE 15061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten} 15161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 152ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 15361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenstatic SLresult IEffectSend_IsEnabled(SLEffectSendItf self, 15461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten const void *pAuxEffect, SLboolean *pEnable) 15561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{ 156ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_ENTER_INTERFACE 157ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 158ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten if (NULL == pEnable) { 159ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_PARAMETER_INVALID; 160ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } else { 161ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten IEffectSend *this = (IEffectSend *) self; 162ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten struct EnableLevel *enableLevel = getEnableLevel(this, pAuxEffect); 163ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten if (NULL == enableLevel) { 164ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_PARAMETER_INVALID; 165ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } else { 166ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten interface_lock_peek(this); 167ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SLboolean enable = enableLevel->mEnable; 168ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten interface_unlock_peek(this); 169ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten *pEnable = enable; 170ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_SUCCESS; 171ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } 172ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } 173ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 174ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_LEAVE_INTERFACE 17561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten} 17661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 177ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 178d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kastenstatic SLresult IEffectSend_SetDirectLevel(SLEffectSendItf self, SLmillibel directLevel) 17961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{ 180ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_ENTER_INTERFACE 181ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 182ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten if (!((SL_MILLIBEL_MIN <= directLevel) && (directLevel <= 0))) { 183ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_PARAMETER_INVALID; 184ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } else { 185ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten IEffectSend *this = (IEffectSend *) self; 186172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi interface_lock_exclusive(this); 187fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi CAudioPlayer *ap = (SL_OBJECTID_AUDIOPLAYER == InterfaceToObjectID(this)) ? 188fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi (CAudioPlayer *) this->mThis : NULL; 189fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi if (NULL != ap) { 190fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi SLmillibel oldDirectLevel = ap->mDirectLevel; 191fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi if (oldDirectLevel != directLevel) { 192fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi ap->mDirectLevel = directLevel; 193fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi#if defined(ANDROID) 194172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi ap->mAmplFromDirectLevel = sles_to_android_amplification(directLevel); 195fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi interface_unlock_exclusive_attributes(this, ATTR_GAIN); 196fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi#else 197fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi interface_unlock_exclusive(this); 19891bfd060b992810ca092f640f77f795bc3d008beGlenn Kasten#endif 199fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi } else { 200fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi interface_unlock_exclusive(this); 201fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi } 202fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi result = SL_RESULT_SUCCESS; 203172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi } else { 204172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi interface_unlock_exclusive(this); 205fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi // the interface itself is invalid because it is not attached to an AudioPlayer 206fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi result = SL_RESULT_PARAMETER_INVALID; 207172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi } 208ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } 209ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 210ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_LEAVE_INTERFACE 21161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten} 21261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 213ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 214d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kastenstatic SLresult IEffectSend_GetDirectLevel(SLEffectSendItf self, SLmillibel *pDirectLevel) 21561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{ 216ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_ENTER_INTERFACE 217ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 218ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten if (NULL == pDirectLevel) { 219ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_PARAMETER_INVALID; 220ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } else { 221ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten IEffectSend *this = (IEffectSend *) self; 222fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi interface_lock_shared(this); 223fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi CAudioPlayer *ap = (SL_OBJECTID_AUDIOPLAYER == InterfaceToObjectID(this)) ? 224fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi (CAudioPlayer *) this->mThis : NULL; 225fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi if (NULL != ap) { 226fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi *pDirectLevel = ap->mDirectLevel; 227fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi result = SL_RESULT_SUCCESS; 228fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi } else { 229fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi // the interface itself is invalid because it is not attached to an AudioPlayer 230fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi result = SL_RESULT_PARAMETER_INVALID; 231fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi } 232fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi interface_unlock_shared(this); 233ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } 234ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 235ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_LEAVE_INTERFACE 23661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten} 23761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 238ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 239e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kastenstatic SLresult IEffectSend_SetSendLevel(SLEffectSendItf self, const void *pAuxEffect, 240e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten SLmillibel sendLevel) 24161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{ 242ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_ENTER_INTERFACE 243ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 244ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten if (!((SL_MILLIBEL_MIN <= sendLevel) && (sendLevel <= 0))) { 245ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_PARAMETER_INVALID; 246ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } else { 247ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten IEffectSend *this = (IEffectSend *) self; 248ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten struct EnableLevel *enableLevel = getEnableLevel(this, pAuxEffect); 249ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten if (NULL == enableLevel) { 250ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_PARAMETER_INVALID; 251ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } else { 252a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten result = SL_RESULT_SUCCESS; 253ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten // EnableEffectSend is exclusive, so this has to be also 254ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten interface_lock_exclusive(this); 255ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten enableLevel->mSendLevel = sendLevel; 256172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi#if defined(ANDROID) && !defined(USE_BACKPORT) 257172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi CAudioPlayer *ap = (SL_OBJECTID_AUDIOPLAYER == InterfaceToObjectID(this)) ? 258172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi (CAudioPlayer *) this->mThis : NULL; 259172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi if (NULL != ap) { 260ca325fa86f9e52d8300490eee102a3c1188f6bdcJean-Michel Trivi // the send level set here is the total energy on the aux bus, so it must take 261ca325fa86f9e52d8300490eee102a3c1188f6bdcJean-Michel Trivi // into account the player volume level 262ca325fa86f9e52d8300490eee102a3c1188f6bdcJean-Michel Trivi result = android_fxSend_setSendLevel(ap, sendLevel + ap->mVolume.mLevel); 263172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi } 264172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi#endif 265ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten interface_unlock_exclusive(this); 266ca325fa86f9e52d8300490eee102a3c1188f6bdcJean-Michel Trivi 267ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } 268ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } 269ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 270ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_LEAVE_INTERFACE 27161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten} 27261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 273ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 274e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kastenstatic SLresult IEffectSend_GetSendLevel(SLEffectSendItf self, const void *pAuxEffect, 275e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten SLmillibel *pSendLevel) 27661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{ 277ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_ENTER_INTERFACE 278ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 279ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten if (NULL == pSendLevel) { 280ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_PARAMETER_INVALID; 281ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } else { 282ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten IEffectSend *this = (IEffectSend *) self; 283ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten struct EnableLevel *enableLevel = getEnableLevel(this, pAuxEffect); 284ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten if (NULL == enableLevel) { 285ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_PARAMETER_INVALID; 286ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } else { 287ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten interface_lock_peek(this); 288ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SLmillibel sendLevel = enableLevel->mSendLevel; 289ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten interface_unlock_peek(this); 290ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten *pSendLevel = sendLevel; 291ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_SUCCESS; 292ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } 293ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } 294ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 295ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_LEAVE_INTERFACE 29661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten} 29761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 298ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 29961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenstatic const struct SLEffectSendItf_ IEffectSend_Itf = { 30061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IEffectSend_EnableEffectSend, 30161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IEffectSend_IsEnabled, 30261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IEffectSend_SetDirectLevel, 30361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IEffectSend_GetDirectLevel, 30461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IEffectSend_SetSendLevel, 30561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IEffectSend_GetSendLevel 30661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}; 30761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 30861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenvoid IEffectSend_init(void *self) 30961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{ 31061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IEffectSend *this = (IEffectSend *) self; 31161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten this->mItf = &IEffectSend_Itf; 3126a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kasten struct EnableLevel *enableLevel = this->mEnableLevels; 3136a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kasten unsigned aux; 3146a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kasten for (aux = 0; aux < AUX_MAX; ++aux, ++enableLevel) { 3156a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kasten enableLevel->mEnable = SL_BOOLEAN_FALSE; 3166a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kasten enableLevel->mSendLevel = SL_MILLIBEL_MIN; 3176a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kasten } 31861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten} 319