1/* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17/* AndroidEffectSend implementation */ 18 19#include "sles_allinclusive.h" 20 21 22static SLresult IAndroidEffectSend_EnableEffectSend(SLAndroidEffectSendItf self, 23 SLInterfaceID effectImplementationId, SLboolean enable, SLmillibel initialLevel) 24{ 25 SL_ENTER_INTERFACE 26 27 if (!((SL_MILLIBEL_MIN <= initialLevel) && (initialLevel <= 0))) { 28 result = SL_RESULT_PARAMETER_INVALID; 29 } else { 30 IAndroidEffectSend *this = (IAndroidEffectSend *) self; 31 interface_lock_exclusive(this); 32 // is SLAndroidEffectSendItf on an AudioPlayer? 33 CAudioPlayer *ap = (SL_OBJECTID_AUDIOPLAYER == InterfaceToObjectID(this)) ? 34 (CAudioPlayer *) this->mThis : NULL; 35 if (NULL == ap) { 36 SL_LOGE("invalid interface: not attached to an AudioPlayer"); 37 result = SL_RESULT_PARAMETER_INVALID; 38 } else { 39 COutputMix *outputMix = CAudioPlayer_GetOutputMix(ap); 40#ifdef USE_BACKPORT 41 result = SL_RESULT_SUCCESS; 42#else 43 // the initial send level set here is the total energy on the aux bus, 44 // so it must take into account the player volume level 45 result = android_fxSend_attachToAux(ap, effectImplementationId, enable, 46 initialLevel + ap->mVolume.mLevel); 47#endif 48 if (SL_RESULT_SUCCESS == result) { 49 // there currently is support for only one send bus, so there is a single send 50 // level and a single enable flag 51 this->mSendLevel = initialLevel; 52 this->mEnabled = enable; 53 } 54 } 55 interface_unlock_exclusive(this); 56 } 57 58 SL_LEAVE_INTERFACE 59} 60 61 62static SLresult IAndroidEffectSend_IsEnabled(SLAndroidEffectSendItf self, 63 SLInterfaceID effectImplementationId, SLboolean *pEnable) 64{ 65 SL_ENTER_INTERFACE 66 67 if (NULL == pEnable) { 68 result = SL_RESULT_PARAMETER_INVALID; 69 } else { 70 IAndroidEffectSend *this = (IAndroidEffectSend *) self; 71 interface_lock_shared(this); 72 // there currently is support for only one send bus, so there is a single enable flag 73 SLboolean enable = this->mEnabled; 74 interface_unlock_shared(this); 75 *pEnable = enable; 76 result = SL_RESULT_SUCCESS; 77 } 78 79 SL_LEAVE_INTERFACE 80} 81 82 83static SLresult IAndroidEffectSend_SetDirectLevel(SLAndroidEffectSendItf self, 84 SLmillibel directLevel) 85{ 86 SL_ENTER_INTERFACE 87 88 if (!((SL_MILLIBEL_MIN <= directLevel) && (directLevel <= 0))) { 89 result = SL_RESULT_PARAMETER_INVALID; 90 } else { 91 IAndroidEffectSend *this = (IAndroidEffectSend *) self; 92 interface_lock_exclusive(this); 93 CAudioPlayer *ap = (SL_OBJECTID_AUDIOPLAYER == InterfaceToObjectID(this)) ? 94 (CAudioPlayer *) this->mThis : NULL; 95 if (NULL != ap) { 96 SLmillibel oldDirectLevel = ap->mDirectLevel; 97 if (oldDirectLevel != directLevel) { 98 ap->mDirectLevel = directLevel; 99 ap->mAmplFromDirectLevel = sles_to_android_amplification(directLevel); 100 interface_unlock_exclusive_attributes(this, ATTR_GAIN); 101 } else { 102 interface_unlock_exclusive(this); 103 } 104 result = SL_RESULT_SUCCESS; 105 } else { 106 interface_unlock_exclusive(this); 107 SL_LOGE("invalid interface: not attached to an AudioPlayer"); 108 result = SL_RESULT_PARAMETER_INVALID; 109 } 110 } 111 112 SL_LEAVE_INTERFACE 113} 114 115 116static SLresult IAndroidEffectSend_GetDirectLevel(SLAndroidEffectSendItf self, 117 SLmillibel *pDirectLevel) 118{ 119 SL_ENTER_INTERFACE 120 121 if (NULL == pDirectLevel) { 122 result = SL_RESULT_PARAMETER_INVALID; 123 } else { 124 IAndroidEffectSend *this = (IAndroidEffectSend *) self; 125 interface_lock_peek(this); 126 CAudioPlayer *ap = (SL_OBJECTID_AUDIOPLAYER == InterfaceToObjectID(this)) ? 127 (CAudioPlayer *) this->mThis : NULL; 128 if (NULL != ap) { 129 *pDirectLevel = ap->mDirectLevel; 130 result = SL_RESULT_SUCCESS; 131 } else { 132 SL_LOGE("invalid interface: not attached to an AudioPlayer"); 133 result = SL_RESULT_PARAMETER_INVALID; 134 } 135 interface_unlock_peek(this); 136 } 137 138 SL_LEAVE_INTERFACE 139} 140 141 142static SLresult IAndroidEffectSend_SetSendLevel(SLAndroidEffectSendItf self, 143 SLInterfaceID effectImplementationId, SLmillibel sendLevel) 144{ 145 SL_ENTER_INTERFACE 146 147 if (!((SL_MILLIBEL_MIN <= sendLevel) && (sendLevel <= 0))) { 148 result = SL_RESULT_PARAMETER_INVALID; 149 } else { 150 IAndroidEffectSend *this = (IAndroidEffectSend *) self; 151 interface_lock_exclusive(this); 152 // is SLAndroidEffectSendItf on an AudioPlayer? 153 CAudioPlayer *ap = (SL_OBJECTID_AUDIOPLAYER == InterfaceToObjectID(this)) ? 154 (CAudioPlayer *) this->mThis : NULL; 155 if (NULL == ap) { 156 SL_LOGE("invalid interface: not attached to an AudioPlayer"); 157 result = SL_RESULT_PARAMETER_INVALID; 158 } else { 159 COutputMix *outputMix = CAudioPlayer_GetOutputMix(ap); 160#ifdef USE_BACKPORT 161 result = SL_RESULT_SUCCESS; 162#else 163 if (android_genericFx_hasEffect(&outputMix->mAndroidEffect, effectImplementationId)) { 164 // the send level set here is the total energy on the aux bus, so it must take 165 // into account the player volume level 166 result = android_fxSend_setSendLevel(ap, sendLevel + ap->mVolume.mLevel); 167 } else { 168 SL_LOGE("trying to send to an effect not on this AudioPlayer's OutputMix"); 169 result = SL_RESULT_PARAMETER_INVALID; 170 } 171#endif 172 if (SL_RESULT_SUCCESS == result) { 173 // there currently is support for only one send bus, so there is a single send 174 // level 175 this->mSendLevel = sendLevel; 176 } 177 } 178 interface_unlock_exclusive(this); 179 } 180 181 SL_LEAVE_INTERFACE 182} 183 184 185static SLresult IAndroidEffectSend_GetSendLevel(SLAndroidEffectSendItf self, 186 SLInterfaceID effectImplementationId, SLmillibel *pSendLevel) 187{ 188 SL_ENTER_INTERFACE 189 190 if (NULL == pSendLevel) { 191 result = SL_RESULT_PARAMETER_INVALID; 192 } else { 193 IAndroidEffectSend *this = (IAndroidEffectSend *) self; 194 interface_lock_exclusive(this); 195 // is SLAndroidEffectSendItf on an AudioPlayer? 196 CAudioPlayer *ap = (SL_OBJECTID_AUDIOPLAYER == InterfaceToObjectID(this)) ? 197 (CAudioPlayer *) this->mThis : NULL; 198 if (NULL == ap) { 199 SL_LOGE("invalid interface: not attached to an AudioPlayer"); 200 result = SL_RESULT_PARAMETER_INVALID; 201 } else { 202 COutputMix *outputMix = CAudioPlayer_GetOutputMix(ap); 203#ifdef USE_BACKPORT 204 result = SL_RESULT_SUCCESS; 205#else 206 if (android_genericFx_hasEffect(&outputMix->mAndroidEffect, effectImplementationId)) { 207 result = SL_RESULT_SUCCESS; 208 } else { 209 SL_LOGE("trying to retrieve send level on an effect not on this AudioPlayer's \ 210OutputMix"); 211 result = SL_RESULT_PARAMETER_INVALID; 212 } 213#endif 214 if (SL_RESULT_SUCCESS == result) { 215 // there currently is support for only one send bus, so there is a single send 216 // level 217 *pSendLevel = this->mSendLevel; 218 } 219 } 220 interface_unlock_exclusive(this); 221 } 222 223 SL_LEAVE_INTERFACE 224} 225 226 227static const struct SLAndroidEffectSendItf_ IAndroidEffectSend_Itf = { 228 IAndroidEffectSend_EnableEffectSend, 229 IAndroidEffectSend_IsEnabled, 230 IAndroidEffectSend_SetDirectLevel, 231 IAndroidEffectSend_GetDirectLevel, 232 IAndroidEffectSend_SetSendLevel, 233 IAndroidEffectSend_GetSendLevel 234}; 235 236void IAndroidEffectSend_init(void *self) 237{ 238 IAndroidEffectSend *this = (IAndroidEffectSend *) self; 239 this->mItf = &IAndroidEffectSend_Itf; 240 this->mEnabled = SL_BOOLEAN_FALSE; 241 this->mSendLevel = SL_MILLIBEL_MIN; 242} 243