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 22 static 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 // comparison (SL_MILLIBEL_MIN <= initialLevel) is always true due to range of SLmillibel 29 if (!(initialLevel <= 0)) { 30 result = SL_RESULT_PARAMETER_INVALID; 31 } else { 32 IAndroidEffectSend *thiz = (IAndroidEffectSend *) self; 33 interface_lock_exclusive(thiz); 34 // is SLAndroidEffectSendItf on an AudioPlayer? 35 CAudioPlayer *ap = (SL_OBJECTID_AUDIOPLAYER == InterfaceToObjectID(thiz)) ? 36 (CAudioPlayer *) thiz->mThis : NULL; 37 if (NULL == ap) { 38 SL_LOGE("invalid interface: not attached to an AudioPlayer"); 39 result = SL_RESULT_PARAMETER_INVALID; 40 } else { 41 COutputMix *outputMix = CAudioPlayer_GetOutputMix(ap); 42 // the initial send level set here is the total energy on the aux bus, 43 // so it must take into account the player volume level 44 result = android_fxSend_attachToAux(ap, effectImplementationId, enable, 45 initialLevel + ap->mVolume.mLevel); 46 if (SL_RESULT_SUCCESS == result) { 47 // there currently is support for only one send bus, so there is a single send 48 // level and a single enable flag 49 thiz->mSendLevel = initialLevel; 50 thiz->mEnabled = enable; 51 } 52 } 53 interface_unlock_exclusive(thiz); 54 } 55 56 SL_LEAVE_INTERFACE 57 } 58 59 60 static SLresult IAndroidEffectSend_IsEnabled(SLAndroidEffectSendItf self, 61 SLInterfaceID effectImplementationId, SLboolean *pEnable) 62 { 63 SL_ENTER_INTERFACE 64 65 if (NULL == pEnable) { 66 result = SL_RESULT_PARAMETER_INVALID; 67 } else { 68 IAndroidEffectSend *thiz = (IAndroidEffectSend *) self; 69 interface_lock_shared(thiz); 70 // there currently is support for only one send bus, so there is a single enable flag 71 SLboolean enable = thiz->mEnabled; 72 interface_unlock_shared(thiz); 73 *pEnable = enable; 74 result = SL_RESULT_SUCCESS; 75 } 76 77 SL_LEAVE_INTERFACE 78 } 79 80 81 static SLresult IAndroidEffectSend_SetDirectLevel(SLAndroidEffectSendItf self, 82 SLmillibel directLevel) 83 { 84 SL_ENTER_INTERFACE 85 86 //if (!((SL_MILLIBEL_MIN <= directLevel) && (directLevel <= 0))) { 87 // comparison (SL_MILLIBEL_MIN <= directLevel) is always true due to range of SLmillibel 88 if (!(directLevel <= 0)) { 89 result = SL_RESULT_PARAMETER_INVALID; 90 } else { 91 IAndroidEffectSend *thiz = (IAndroidEffectSend *) self; 92 interface_lock_exclusive(thiz); 93 CAudioPlayer *ap = (SL_OBJECTID_AUDIOPLAYER == InterfaceToObjectID(thiz)) ? 94 (CAudioPlayer *) thiz->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(thiz, ATTR_GAIN); 101 } else { 102 interface_unlock_exclusive(thiz); 103 } 104 result = SL_RESULT_SUCCESS; 105 } else { 106 interface_unlock_exclusive(thiz); 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 116 static 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 *thiz = (IAndroidEffectSend *) self; 125 interface_lock_shared(thiz); 126 CAudioPlayer *ap = (SL_OBJECTID_AUDIOPLAYER == InterfaceToObjectID(thiz)) ? 127 (CAudioPlayer *) thiz->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_shared(thiz); 136 } 137 138 SL_LEAVE_INTERFACE 139 } 140 141 142 static 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 // comparison (SL_MILLIBEL_MIN <= sendLevel) is always true due to range of SLmillibel 149 if (!(sendLevel <= 0)) { 150 result = SL_RESULT_PARAMETER_INVALID; 151 } else { 152 IAndroidEffectSend *thiz = (IAndroidEffectSend *) self; 153 interface_lock_exclusive(thiz); 154 // is SLAndroidEffectSendItf on an AudioPlayer? 155 CAudioPlayer *ap = (SL_OBJECTID_AUDIOPLAYER == InterfaceToObjectID(thiz)) ? 156 (CAudioPlayer *) thiz->mThis : NULL; 157 if (NULL == ap) { 158 SL_LOGE("invalid interface: not attached to an AudioPlayer"); 159 result = SL_RESULT_PARAMETER_INVALID; 160 } else { 161 COutputMix *outputMix = CAudioPlayer_GetOutputMix(ap); 162 if (android_genericFx_hasEffect(&outputMix->mAndroidEffect, effectImplementationId)) { 163 // the send level set here is the total energy on the aux bus, so it must take 164 // into account the player volume level 165 result = android_fxSend_setSendLevel(ap, sendLevel + ap->mVolume.mLevel); 166 } else { 167 SL_LOGE("trying to send to an effect not on this AudioPlayer's OutputMix"); 168 result = SL_RESULT_PARAMETER_INVALID; 169 } 170 if (SL_RESULT_SUCCESS == result) { 171 // there currently is support for only one send bus, so there is a single send 172 // level 173 thiz->mSendLevel = sendLevel; 174 } 175 } 176 interface_unlock_exclusive(thiz); 177 } 178 179 SL_LEAVE_INTERFACE 180 } 181 182 183 static SLresult IAndroidEffectSend_GetSendLevel(SLAndroidEffectSendItf self, 184 SLInterfaceID effectImplementationId, SLmillibel *pSendLevel) 185 { 186 SL_ENTER_INTERFACE 187 188 if (NULL == pSendLevel) { 189 result = SL_RESULT_PARAMETER_INVALID; 190 } else { 191 IAndroidEffectSend *thiz = (IAndroidEffectSend *) self; 192 interface_lock_exclusive(thiz); 193 // is SLAndroidEffectSendItf on an AudioPlayer? 194 CAudioPlayer *ap = (SL_OBJECTID_AUDIOPLAYER == InterfaceToObjectID(thiz)) ? 195 (CAudioPlayer *) thiz->mThis : NULL; 196 if (NULL == ap) { 197 SL_LOGE("invalid interface: not attached to an AudioPlayer"); 198 result = SL_RESULT_PARAMETER_INVALID; 199 } else { 200 COutputMix *outputMix = CAudioPlayer_GetOutputMix(ap); 201 if (android_genericFx_hasEffect(&outputMix->mAndroidEffect, effectImplementationId)) { 202 result = SL_RESULT_SUCCESS; 203 } else { 204 SL_LOGE("trying to retrieve send level on an effect not on this AudioPlayer's \ 205 OutputMix"); 206 result = SL_RESULT_PARAMETER_INVALID; 207 } 208 if (SL_RESULT_SUCCESS == result) { 209 // there currently is support for only one send bus, so there is a single send 210 // level 211 *pSendLevel = thiz->mSendLevel; 212 } 213 } 214 interface_unlock_exclusive(thiz); 215 } 216 217 SL_LEAVE_INTERFACE 218 } 219 220 221 static const struct SLAndroidEffectSendItf_ IAndroidEffectSend_Itf = { 222 IAndroidEffectSend_EnableEffectSend, 223 IAndroidEffectSend_IsEnabled, 224 IAndroidEffectSend_SetDirectLevel, 225 IAndroidEffectSend_GetDirectLevel, 226 IAndroidEffectSend_SetSendLevel, 227 IAndroidEffectSend_GetSendLevel 228 }; 229 230 void IAndroidEffectSend_init(void *self) 231 { 232 IAndroidEffectSend *thiz = (IAndroidEffectSend *) self; 233 thiz->mItf = &IAndroidEffectSend_Itf; 234 thiz->mEnabled = SL_BOOLEAN_FALSE; 235 thiz->mSendLevel = SL_MILLIBEL_MIN; 236 } 237