IEffectSend.c revision 9e60b0a390d780539459f41c2bf4a45a326a7b62
161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten/*
261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten * Copyright (C) 2010 The Android Open Source Project
361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten *
461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten * Licensed under the Apache License, Version 2.0 (the "License");
561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten * you may not use this file except in compliance with the License.
661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten * You may obtain a copy of the License at
761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten *
861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten *      http://www.apache.org/licenses/LICENSE-2.0
961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten *
1061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten * Unless required by applicable law or agreed to in writing, software
1161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten * distributed under the License is distributed on an "AS IS" BASIS,
1261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten * See the License for the specific language governing permissions and
1461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten * limitations under the License.
1561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten */
1661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
1761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten/* EffectSend implementation */
1861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
1961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten#include "sles_allinclusive.h"
2061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
21343c522ebf4f9c321eef8c3b3b2945f1c1cb8846Glenn Kasten
22343c522ebf4f9c321eef8c3b3b2945f1c1cb8846Glenn Kasten/** \brief Maps AUX index to OutputMix interface index */
23510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
24510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kastenstatic const unsigned char AUX_to_MPH[AUX_MAX] = {
25510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    MPH_ENVIRONMENTALREVERB,
26510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    MPH_PRESETREVERB
27510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten};
28510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten
29343c522ebf4f9c321eef8c3b3b2945f1c1cb8846Glenn Kasten
30e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten/** \brief This is a private function that validates the effect interface specified by the
31e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten *  application when it calls EnableEffectSend, IsEnabled, SetSendLevel, or GetSendLevel.
32e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten *  For the interface to be valid, it has to satisfy these requirements:
33e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten *   - object is an audio player (MIDI player is not supported yet)
34e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten *   - audio sink is an output mix
35e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten *   - interface was exposed at object creation time or by DynamicInterface::AddInterface
36e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten *   - interface was "gotten" with Object::GetInterface
37e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten */
38343c522ebf4f9c321eef8c3b3b2945f1c1cb8846Glenn Kasten
39d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kastenstatic struct EnableLevel *getEnableLevel(IEffectSend *this, const void *pAuxEffect)
4061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
41343c522ebf4f9c321eef8c3b3b2945f1c1cb8846Glenn Kasten    // Make sure this effect send is on an audio player, not a MIDI player
42343c522ebf4f9c321eef8c3b3b2945f1c1cb8846Glenn Kasten    CAudioPlayer *audioPlayer = (SL_OBJECTID_AUDIOPLAYER == InterfaceToObjectID(this)) ?
43343c522ebf4f9c321eef8c3b3b2945f1c1cb8846Glenn Kasten        (CAudioPlayer *) this->mThis : NULL;
449e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten    if (NULL == audioPlayer) {
45343c522ebf4f9c321eef8c3b3b2945f1c1cb8846Glenn Kasten        return NULL;
469e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten    }
47f51dba65751107c930759938775b75531ec1f330Glenn Kasten    // Get the output mix for this player
48f51dba65751107c930759938775b75531ec1f330Glenn Kasten    COutputMix *outputMix = CAudioPlayer_GetOutputMix(audioPlayer);
49510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    unsigned aux;
509e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten    if (pAuxEffect == &outputMix->mEnvironmentalReverb.mItf) {
51510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        aux = AUX_ENVIRONMENTALREVERB;
529e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten    } else if (pAuxEffect == &outputMix->mPresetReverb.mItf) {
53510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        aux = AUX_PRESETREVERB;
549e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten    } else {
559e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten        SL_LOGE("EffectSend on unknown aux effect %p", pAuxEffect);
56510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        return NULL;
579e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten    }
58510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    assert(aux < AUX_MAX);
59e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten    // Validate that the application has a valid interface for the effect.  The interface must have
60e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten    // been exposed at object creation time or by DynamicInterface::AddInterface, and it also must
61e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten    // have been "gotten" with Object::GetInterface.
629e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten    unsigned MPH = AUX_to_MPH[aux];
639e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten    int index = MPH_to_OutputMix[MPH];
649e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten    if (0 > index) {
659e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten        SL_LOGE("EffectSend aux=%u MPH=%u", aux, MPH);
66510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        return NULL;
679e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten    }
68510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    unsigned mask = 1 << index;
69510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    object_lock_shared(&outputMix->mObject);
70510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    SLuint32 state = outputMix->mObject.mInterfaceStates[index];
71510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    mask &= outputMix->mObject.mGottenMask;
72510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    object_unlock_shared(&outputMix->mObject);
73510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    switch (state) {
74510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    case INTERFACE_EXPOSED:
75510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    case INTERFACE_ADDED:
76510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    case INTERFACE_SUSPENDED:
77510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    case INTERFACE_SUSPENDING:
78510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    case INTERFACE_RESUMING_1:
79510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    case INTERFACE_RESUMING_2:
809e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten        if (mask) {
81510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            return &this->mEnableLevels[aux];
829e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten        }
839e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten        SL_LOGE("EffectSend no GetInterface yet");
84510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        break;
85510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    default:
869e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten        SL_LOGE("EffectSend invalid interface state %lu", state);
87510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        break;
88510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    }
8961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    return NULL;
9061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
9161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
9291bfd060b992810ca092f640f77f795bc3d008beGlenn Kasten#if defined(ANDROID) && !defined(USE_BACKPORT)
93172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi/** \brief This is a private function that translates an Android effect framework status code
94172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi *  to the SL ES result code used in the EnableEffectSend() function of the SLEffectSendItf
95172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi *  interface.
96172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi */
97172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivistatic SLresult translateEnableFxSendError(android::status_t status) {
98172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi    switch (status) {
999e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten    case android::NO_ERROR:
1009e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten        return SL_RESULT_SUCCESS;
1019e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten    case android::INVALID_OPERATION:
1029e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten    case android::BAD_VALUE:
1039e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten    default:
1049e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten        SL_LOGE("EffectSend status %u", status);
1059e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten        return SL_RESULT_RESOURCE_ERROR;
106172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi    }
107172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi}
10891bfd060b992810ca092f640f77f795bc3d008beGlenn Kasten#endif
109172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi
110ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
11161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenstatic SLresult IEffectSend_EnableEffectSend(SLEffectSendItf self,
11261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    const void *pAuxEffect, SLboolean enable, SLmillibel initialLevel)
11361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
114ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_ENTER_INTERFACE
115ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
116ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    if (!((SL_MILLIBEL_MIN <= initialLevel) && (initialLevel <= 0))) {
117ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        result = SL_RESULT_PARAMETER_INVALID;
118ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    } else {
119ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        IEffectSend *this = (IEffectSend *) self;
120ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        struct EnableLevel *enableLevel = getEnableLevel(this, pAuxEffect);
121ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        if (NULL == enableLevel) {
122ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            result = SL_RESULT_PARAMETER_INVALID;
123ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        } else {
124ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            interface_lock_exclusive(this);
125ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            enableLevel->mEnable = SL_BOOLEAN_FALSE != enable; // normalize
126ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            enableLevel->mSendLevel = initialLevel;
127172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi#if !defined(ANDROID) || defined(USE_BACKPORT)
128ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            result = SL_RESULT_SUCCESS;
129172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi#else
130172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi            // TODO do not repeat querying of CAudioPlayer, done inside getEnableLevel()
131172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi            CAudioPlayer *ap = (SL_OBJECTID_AUDIOPLAYER == InterfaceToObjectID(this)) ?
132172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi                    (CAudioPlayer *) this->mThis : NULL;
1339e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten            // note that if this was a MIDI player, getEnableLevel would have returned NULL
1349e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten            assert(NULL != ap);
135172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi            // check which effect the send is attached to, attach and set level
1369e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten            COutputMix *outputMix = CAudioPlayer_GetOutputMix(ap);
1379e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten            // the initial send level set here is the total energy on the aux bus,
1389e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten            //  so it must take into account the player volume level
1399e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten            if (pAuxEffect == &outputMix->mPresetReverb.mItf) {
1409e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten                result = translateEnableFxSendError(android_fxSend_attach(ap, (bool) enable,
1419e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten                    outputMix->mPresetReverb.mPresetReverbEffect,
1429e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten                    initialLevel + ap->mVolume.mLevel));
1439e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten            } else if (pAuxEffect == &outputMix->mEnvironmentalReverb.mItf) {
1449e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten                result = translateEnableFxSendError(android_fxSend_attach(ap, (bool) enable,
1459e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten                    outputMix->mEnvironmentalReverb.mEnvironmentalReverbEffect,
1469e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten                    initialLevel + ap->mVolume.mLevel));
147172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi            } else {
1489e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten                SL_LOGE("EffectSend unknown aux effect %p", pAuxEffect);
1499e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten                result = SL_RESULT_PARAMETER_INVALID;
150172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi            }
151172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi#endif
152172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi            interface_unlock_exclusive(this);
153ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        }
154ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    }
155ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
156ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_LEAVE_INTERFACE
15761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
15861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
159ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
16061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenstatic SLresult IEffectSend_IsEnabled(SLEffectSendItf self,
16161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    const void *pAuxEffect, SLboolean *pEnable)
16261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
163ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_ENTER_INTERFACE
164ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
165ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    if (NULL == pEnable) {
166ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        result = SL_RESULT_PARAMETER_INVALID;
167ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    } else {
168ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        IEffectSend *this = (IEffectSend *) self;
169ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        struct EnableLevel *enableLevel = getEnableLevel(this, pAuxEffect);
170ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        if (NULL == enableLevel) {
1719e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten            *pEnable = SL_BOOLEAN_FALSE;
172ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            result = SL_RESULT_PARAMETER_INVALID;
173ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        } else {
1749e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten            interface_lock_shared(this);
175ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            SLboolean enable = enableLevel->mEnable;
1769e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten            interface_unlock_shared(this);
177ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            *pEnable = enable;
178ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            result = SL_RESULT_SUCCESS;
179ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        }
180ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    }
181ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
182ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_LEAVE_INTERFACE
18361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
18461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
185ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
186d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kastenstatic SLresult IEffectSend_SetDirectLevel(SLEffectSendItf self, SLmillibel directLevel)
18761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
188ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_ENTER_INTERFACE
189ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
190ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    if (!((SL_MILLIBEL_MIN <= directLevel) && (directLevel <= 0))) {
191ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        result = SL_RESULT_PARAMETER_INVALID;
192ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    } else {
193ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        IEffectSend *this = (IEffectSend *) self;
194172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi        interface_lock_exclusive(this);
195fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi        CAudioPlayer *ap = (SL_OBJECTID_AUDIOPLAYER == InterfaceToObjectID(this)) ?
196fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi                (CAudioPlayer *) this->mThis : NULL;
197fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi        if (NULL != ap) {
198fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi            SLmillibel oldDirectLevel = ap->mDirectLevel;
199fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi            if (oldDirectLevel != directLevel) {
200fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi                ap->mDirectLevel = directLevel;
201fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi#if defined(ANDROID)
202172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi                ap->mAmplFromDirectLevel = sles_to_android_amplification(directLevel);
203fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi                interface_unlock_exclusive_attributes(this, ATTR_GAIN);
204fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi#else
205fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi                interface_unlock_exclusive(this);
20691bfd060b992810ca092f640f77f795bc3d008beGlenn Kasten#endif
207fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi            } else {
208fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi                interface_unlock_exclusive(this);
209fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi            }
210172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi        } else {
2119e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten            // MIDI player is silently not supported
212172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi            interface_unlock_exclusive(this);
213172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi        }
2149e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten        result = SL_RESULT_SUCCESS;
215ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    }
216ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
217ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_LEAVE_INTERFACE
21861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
21961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
220ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
221d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kastenstatic SLresult IEffectSend_GetDirectLevel(SLEffectSendItf self, SLmillibel *pDirectLevel)
22261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
223ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_ENTER_INTERFACE
224ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
225ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    if (NULL == pDirectLevel) {
226ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        result = SL_RESULT_PARAMETER_INVALID;
227ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    } else {
228ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        IEffectSend *this = (IEffectSend *) self;
229fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi        interface_lock_shared(this);
230fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi        CAudioPlayer *ap = (SL_OBJECTID_AUDIOPLAYER == InterfaceToObjectID(this)) ?
231fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi                (CAudioPlayer *) this->mThis : NULL;
232fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi        if (NULL != ap) {
233fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi            *pDirectLevel = ap->mDirectLevel;
234fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi        } else {
2359e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten            // MIDI player is silently not supported
2369e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten            *pDirectLevel = 0;
237fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi        }
238fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi        interface_unlock_shared(this);
2399e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten        result = SL_RESULT_SUCCESS;
240ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    }
241ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
242ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_LEAVE_INTERFACE
24361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
24461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
245ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
246e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kastenstatic SLresult IEffectSend_SetSendLevel(SLEffectSendItf self, const void *pAuxEffect,
247e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten    SLmillibel sendLevel)
24861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
249ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_ENTER_INTERFACE
250ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
251ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    if (!((SL_MILLIBEL_MIN <= sendLevel) && (sendLevel <= 0))) {
252ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        result = SL_RESULT_PARAMETER_INVALID;
253ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    } else {
254ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        IEffectSend *this = (IEffectSend *) self;
255ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        struct EnableLevel *enableLevel = getEnableLevel(this, pAuxEffect);
256ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        if (NULL == enableLevel) {
257ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            result = SL_RESULT_PARAMETER_INVALID;
258ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        } else {
259a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten            result = SL_RESULT_SUCCESS;
260ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            // EnableEffectSend is exclusive, so this has to be also
261ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            interface_lock_exclusive(this);
262ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            enableLevel->mSendLevel = sendLevel;
263172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi#if defined(ANDROID) && !defined(USE_BACKPORT)
264172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi            CAudioPlayer *ap = (SL_OBJECTID_AUDIOPLAYER == InterfaceToObjectID(this)) ?
265172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi                    (CAudioPlayer *) this->mThis : NULL;
266172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi            if (NULL != ap) {
267ca325fa86f9e52d8300490eee102a3c1188f6bdcJean-Michel Trivi                // the send level set here is the total energy on the aux bus, so it must take
268ca325fa86f9e52d8300490eee102a3c1188f6bdcJean-Michel Trivi                // into account the player volume level
269ca325fa86f9e52d8300490eee102a3c1188f6bdcJean-Michel Trivi                result = android_fxSend_setSendLevel(ap, sendLevel + ap->mVolume.mLevel);
270172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi            }
271172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi#endif
272ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            interface_unlock_exclusive(this);
273ca325fa86f9e52d8300490eee102a3c1188f6bdcJean-Michel Trivi
274ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        }
275ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    }
276ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
277ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_LEAVE_INTERFACE
27861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
27961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
280ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
281e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kastenstatic SLresult IEffectSend_GetSendLevel(SLEffectSendItf self, const void *pAuxEffect,
282e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten    SLmillibel *pSendLevel)
28361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
284ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_ENTER_INTERFACE
285ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
286ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    if (NULL == pSendLevel) {
287ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        result = SL_RESULT_PARAMETER_INVALID;
288ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    } else {
289ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        IEffectSend *this = (IEffectSend *) self;
290ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        struct EnableLevel *enableLevel = getEnableLevel(this, pAuxEffect);
291ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        if (NULL == enableLevel) {
292ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            result = SL_RESULT_PARAMETER_INVALID;
293ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        } else {
2949e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten            interface_lock_shared(this);
295ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            SLmillibel sendLevel = enableLevel->mSendLevel;
2969e60b0a390d780539459f41c2bf4a45a326a7b62Glenn Kasten            interface_unlock_shared(this);
297ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            *pSendLevel = sendLevel;
298ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            result = SL_RESULT_SUCCESS;
299ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        }
300ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    }
301ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
302ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_LEAVE_INTERFACE
30361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
30461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
305ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
30661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenstatic const struct SLEffectSendItf_ IEffectSend_Itf = {
30761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IEffectSend_EnableEffectSend,
30861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IEffectSend_IsEnabled,
30961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IEffectSend_SetDirectLevel,
31061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IEffectSend_GetDirectLevel,
31161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IEffectSend_SetSendLevel,
31261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IEffectSend_GetSendLevel
31361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten};
31461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
31561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenvoid IEffectSend_init(void *self)
31661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
31761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IEffectSend *this = (IEffectSend *) self;
31861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    this->mItf = &IEffectSend_Itf;
3196a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kasten    struct EnableLevel *enableLevel = this->mEnableLevels;
3206a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kasten    unsigned aux;
3216a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kasten    for (aux = 0; aux < AUX_MAX; ++aux, ++enableLevel) {
3226a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kasten        enableLevel->mEnable = SL_BOOLEAN_FALSE;
3236a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kasten        enableLevel->mSendLevel = SL_MILLIBEL_MIN;
3246a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kasten    }
32561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
326