/* * 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; }