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