/* * 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))) { result = SL_RESULT_PARAMETER_INVALID; } else { IAndroidEffectSend *this = (IAndroidEffectSend *) self; interface_lock_exclusive(this); // is SLAndroidEffectSendItf on an AudioPlayer? CAudioPlayer *ap = (SL_OBJECTID_AUDIOPLAYER == InterfaceToObjectID(this)) ? (CAudioPlayer *) this->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); #ifdef USE_BACKPORT result = SL_RESULT_SUCCESS; #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); #endif 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 this->mSendLevel = initialLevel; this->mEnabled = enable; } } interface_unlock_exclusive(this); } 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 *this = (IAndroidEffectSend *) self; interface_lock_shared(this); // there currently is support for only one send bus, so there is a single enable flag SLboolean enable = this->mEnabled; interface_unlock_shared(this); *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))) { result = SL_RESULT_PARAMETER_INVALID; } else { IAndroidEffectSend *this = (IAndroidEffectSend *) self; interface_lock_exclusive(this); CAudioPlayer *ap = (SL_OBJECTID_AUDIOPLAYER == InterfaceToObjectID(this)) ? (CAudioPlayer *) this->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(this, ATTR_GAIN); } else { interface_unlock_exclusive(this); } result = SL_RESULT_SUCCESS; } else { interface_unlock_exclusive(this); 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 *this = (IAndroidEffectSend *) self; interface_lock_peek(this); CAudioPlayer *ap = (SL_OBJECTID_AUDIOPLAYER == InterfaceToObjectID(this)) ? (CAudioPlayer *) this->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_peek(this); } SL_LEAVE_INTERFACE } static SLresult IAndroidEffectSend_SetSendLevel(SLAndroidEffectSendItf self, SLInterfaceID effectImplementationId, SLmillibel sendLevel) { SL_ENTER_INTERFACE if (!((SL_MILLIBEL_MIN <= sendLevel) && (sendLevel <= 0))) { result = SL_RESULT_PARAMETER_INVALID; } else { IAndroidEffectSend *this = (IAndroidEffectSend *) self; interface_lock_exclusive(this); // is SLAndroidEffectSendItf on an AudioPlayer? CAudioPlayer *ap = (SL_OBJECTID_AUDIOPLAYER == InterfaceToObjectID(this)) ? (CAudioPlayer *) this->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); #ifdef USE_BACKPORT result = SL_RESULT_SUCCESS; #else 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; } #endif if (SL_RESULT_SUCCESS == result) { // there currently is support for only one send bus, so there is a single send // level this->mSendLevel = sendLevel; } } interface_unlock_exclusive(this); } 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 *this = (IAndroidEffectSend *) self; interface_lock_exclusive(this); // is SLAndroidEffectSendItf on an AudioPlayer? CAudioPlayer *ap = (SL_OBJECTID_AUDIOPLAYER == InterfaceToObjectID(this)) ? (CAudioPlayer *) this->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); #ifdef USE_BACKPORT result = SL_RESULT_SUCCESS; #else 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; } #endif if (SL_RESULT_SUCCESS == result) { // there currently is support for only one send bus, so there is a single send // level *pSendLevel = this->mSendLevel; } } interface_unlock_exclusive(this); } 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 *this = (IAndroidEffectSend *) self; this->mItf = &IAndroidEffectSend_Itf; this->mEnabled = SL_BOOLEAN_FALSE; this->mSendLevel = SL_MILLIBEL_MIN; }