| /* |
| * Copyright (C) 2010 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| /* AndroidEffectSend implementation */ |
| |
| #include "sles_allinclusive.h" |
| |
| |
| static SLresult IAndroidEffectSend_EnableEffectSend(SLAndroidEffectSendItf self, |
| SLInterfaceID effectImplementationId, SLboolean enable, SLmillibel initialLevel) |
| { |
| SL_ENTER_INTERFACE |
| |
| //if (!((SL_MILLIBEL_MIN <= initialLevel) && (initialLevel <= 0))) { |
| // comparison (SL_MILLIBEL_MIN <= initialLevel) is always true due to range of SLmillibel |
| if (!(initialLevel <= 0)) { |
| result = SL_RESULT_PARAMETER_INVALID; |
| } else { |
| IAndroidEffectSend *thiz = (IAndroidEffectSend *) self; |
| interface_lock_exclusive(thiz); |
| // is SLAndroidEffectSendItf on an AudioPlayer? |
| CAudioPlayer *ap = (SL_OBJECTID_AUDIOPLAYER == InterfaceToObjectID(thiz)) ? |
| (CAudioPlayer *) thiz->mThis : NULL; |
| if (NULL == ap) { |
| SL_LOGE("invalid interface: not attached to an AudioPlayer"); |
| result = SL_RESULT_PARAMETER_INVALID; |
| } else { |
| // the initial send level set here is the total energy on the aux bus, |
| // so it must take into account the player volume level |
| result = android_fxSend_attachToAux(ap, effectImplementationId, enable, |
| initialLevel + ap->mVolume.mLevel); |
| if (SL_RESULT_SUCCESS == result) { |
| // there currently is support for only one send bus, so there is a single send |
| // level and a single enable flag |
| thiz->mSendLevel = initialLevel; |
| thiz->mEnabled = enable; |
| } |
| } |
| interface_unlock_exclusive(thiz); |
| } |
| |
| SL_LEAVE_INTERFACE |
| } |
| |
| |
| static SLresult IAndroidEffectSend_IsEnabled(SLAndroidEffectSendItf self, |
| SLInterfaceID effectImplementationId, SLboolean *pEnable) |
| { |
| SL_ENTER_INTERFACE |
| |
| if (NULL == pEnable) { |
| result = SL_RESULT_PARAMETER_INVALID; |
| } else { |
| IAndroidEffectSend *thiz = (IAndroidEffectSend *) self; |
| interface_lock_shared(thiz); |
| // there currently is support for only one send bus, so there is a single enable flag |
| SLboolean enable = thiz->mEnabled; |
| interface_unlock_shared(thiz); |
| *pEnable = enable; |
| result = SL_RESULT_SUCCESS; |
| } |
| |
| SL_LEAVE_INTERFACE |
| } |
| |
| |
| static SLresult IAndroidEffectSend_SetDirectLevel(SLAndroidEffectSendItf self, |
| SLmillibel directLevel) |
| { |
| SL_ENTER_INTERFACE |
| |
| //if (!((SL_MILLIBEL_MIN <= directLevel) && (directLevel <= 0))) { |
| // comparison (SL_MILLIBEL_MIN <= directLevel) is always true due to range of SLmillibel |
| if (!(directLevel <= 0)) { |
| result = SL_RESULT_PARAMETER_INVALID; |
| } else { |
| IAndroidEffectSend *thiz = (IAndroidEffectSend *) self; |
| interface_lock_exclusive(thiz); |
| CAudioPlayer *ap = (SL_OBJECTID_AUDIOPLAYER == InterfaceToObjectID(thiz)) ? |
| (CAudioPlayer *) thiz->mThis : NULL; |
| if (NULL != ap) { |
| SLmillibel oldDirectLevel = ap->mDirectLevel; |
| if (oldDirectLevel != directLevel) { |
| ap->mDirectLevel = directLevel; |
| ap->mAmplFromDirectLevel = sles_to_android_amplification(directLevel); |
| interface_unlock_exclusive_attributes(thiz, ATTR_GAIN); |
| } else { |
| interface_unlock_exclusive(thiz); |
| } |
| result = SL_RESULT_SUCCESS; |
| } else { |
| interface_unlock_exclusive(thiz); |
| SL_LOGE("invalid interface: not attached to an AudioPlayer"); |
| result = SL_RESULT_PARAMETER_INVALID; |
| } |
| } |
| |
| SL_LEAVE_INTERFACE |
| } |
| |
| |
| static SLresult IAndroidEffectSend_GetDirectLevel(SLAndroidEffectSendItf self, |
| SLmillibel *pDirectLevel) |
| { |
| SL_ENTER_INTERFACE |
| |
| if (NULL == pDirectLevel) { |
| result = SL_RESULT_PARAMETER_INVALID; |
| } else { |
| IAndroidEffectSend *thiz = (IAndroidEffectSend *) self; |
| interface_lock_shared(thiz); |
| CAudioPlayer *ap = (SL_OBJECTID_AUDIOPLAYER == InterfaceToObjectID(thiz)) ? |
| (CAudioPlayer *) thiz->mThis : NULL; |
| if (NULL != ap) { |
| *pDirectLevel = ap->mDirectLevel; |
| result = SL_RESULT_SUCCESS; |
| } else { |
| SL_LOGE("invalid interface: not attached to an AudioPlayer"); |
| result = SL_RESULT_PARAMETER_INVALID; |
| } |
| interface_unlock_shared(thiz); |
| } |
| |
| SL_LEAVE_INTERFACE |
| } |
| |
| |
| static SLresult IAndroidEffectSend_SetSendLevel(SLAndroidEffectSendItf self, |
| SLInterfaceID effectImplementationId, SLmillibel sendLevel) |
| { |
| SL_ENTER_INTERFACE |
| |
| //if (!((SL_MILLIBEL_MIN <= sendLevel) && (sendLevel <= 0))) { |
| // comparison (SL_MILLIBEL_MIN <= sendLevel) is always true due to range of SLmillibel |
| if (!(sendLevel <= 0)) { |
| result = SL_RESULT_PARAMETER_INVALID; |
| } else { |
| IAndroidEffectSend *thiz = (IAndroidEffectSend *) self; |
| interface_lock_exclusive(thiz); |
| // is SLAndroidEffectSendItf on an AudioPlayer? |
| CAudioPlayer *ap = (SL_OBJECTID_AUDIOPLAYER == InterfaceToObjectID(thiz)) ? |
| (CAudioPlayer *) thiz->mThis : NULL; |
| if (NULL == ap) { |
| SL_LOGE("invalid interface: not attached to an AudioPlayer"); |
| result = SL_RESULT_PARAMETER_INVALID; |
| } else { |
| COutputMix *outputMix = CAudioPlayer_GetOutputMix(ap); |
| if (android_genericFx_hasEffect(&outputMix->mAndroidEffect, effectImplementationId)) { |
| // the send level set here is the total energy on the aux bus, so it must take |
| // into account the player volume level |
| result = android_fxSend_setSendLevel(ap, sendLevel + ap->mVolume.mLevel); |
| } else { |
| SL_LOGE("trying to send to an effect not on this AudioPlayer's OutputMix"); |
| result = SL_RESULT_PARAMETER_INVALID; |
| } |
| if (SL_RESULT_SUCCESS == result) { |
| // there currently is support for only one send bus, so there is a single send |
| // level |
| thiz->mSendLevel = sendLevel; |
| } |
| } |
| interface_unlock_exclusive(thiz); |
| } |
| |
| SL_LEAVE_INTERFACE |
| } |
| |
| |
| static SLresult IAndroidEffectSend_GetSendLevel(SLAndroidEffectSendItf self, |
| SLInterfaceID effectImplementationId, SLmillibel *pSendLevel) |
| { |
| SL_ENTER_INTERFACE |
| |
| if (NULL == pSendLevel) { |
| result = SL_RESULT_PARAMETER_INVALID; |
| } else { |
| IAndroidEffectSend *thiz = (IAndroidEffectSend *) self; |
| interface_lock_exclusive(thiz); |
| // is SLAndroidEffectSendItf on an AudioPlayer? |
| CAudioPlayer *ap = (SL_OBJECTID_AUDIOPLAYER == InterfaceToObjectID(thiz)) ? |
| (CAudioPlayer *) thiz->mThis : NULL; |
| if (NULL == ap) { |
| SL_LOGE("invalid interface: not attached to an AudioPlayer"); |
| result = SL_RESULT_PARAMETER_INVALID; |
| } else { |
| COutputMix *outputMix = CAudioPlayer_GetOutputMix(ap); |
| if (android_genericFx_hasEffect(&outputMix->mAndroidEffect, effectImplementationId)) { |
| result = SL_RESULT_SUCCESS; |
| } else { |
| SL_LOGE("trying to retrieve send level on an effect not on this AudioPlayer's \ |
| OutputMix"); |
| result = SL_RESULT_PARAMETER_INVALID; |
| } |
| if (SL_RESULT_SUCCESS == result) { |
| // there currently is support for only one send bus, so there is a single send |
| // level |
| *pSendLevel = thiz->mSendLevel; |
| } |
| } |
| interface_unlock_exclusive(thiz); |
| } |
| |
| SL_LEAVE_INTERFACE |
| } |
| |
| |
| static const struct SLAndroidEffectSendItf_ IAndroidEffectSend_Itf = { |
| IAndroidEffectSend_EnableEffectSend, |
| IAndroidEffectSend_IsEnabled, |
| IAndroidEffectSend_SetDirectLevel, |
| IAndroidEffectSend_GetDirectLevel, |
| IAndroidEffectSend_SetSendLevel, |
| IAndroidEffectSend_GetSendLevel |
| }; |
| |
| void IAndroidEffectSend_init(void *self) |
| { |
| IAndroidEffectSend *thiz = (IAndroidEffectSend *) self; |
| thiz->mItf = &IAndroidEffectSend_Itf; |
| thiz->mEnabled = SL_BOOLEAN_FALSE; |
| thiz->mSendLevel = SL_MILLIBEL_MIN; |
| } |