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