IEffectSend.c revision a3080daa505f91df51a808c85ddb37c48745bf7c
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;
44343c522ebf4f9c321eef8c3b3b2945f1c1cb8846Glenn Kasten    if (NULL == audioPlayer)
45343c522ebf4f9c321eef8c3b3b2945f1c1cb8846Glenn Kasten        return NULL;
46f51dba65751107c930759938775b75531ec1f330Glenn Kasten    // Get the output mix for this player
47f51dba65751107c930759938775b75531ec1f330Glenn Kasten    COutputMix *outputMix = CAudioPlayer_GetOutputMix(audioPlayer);
48510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    unsigned aux;
49510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    if (pAuxEffect == &outputMix->mEnvironmentalReverb.mItf)
50510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        aux = AUX_ENVIRONMENTALREVERB;
51510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    else if (pAuxEffect == &outputMix->mPresetReverb.mItf)
52510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        aux = AUX_PRESETREVERB;
53510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    else
54510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        return NULL;
55510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    assert(aux < AUX_MAX);
56e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten    // Validate that the application has a valid interface for the effect.  The interface must have
57e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten    // been exposed at object creation time or by DynamicInterface::AddInterface, and it also must
58e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten    // have been "gotten" with Object::GetInterface.
59510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    int index = MPH_to_OutputMix[AUX_to_MPH[aux]];
60510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    if (0 > index)
61510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        return NULL;
62510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    unsigned mask = 1 << index;
63510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    object_lock_shared(&outputMix->mObject);
64510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    SLuint32 state = outputMix->mObject.mInterfaceStates[index];
65510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    mask &= outputMix->mObject.mGottenMask;
66510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    object_unlock_shared(&outputMix->mObject);
67510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    switch (state) {
68510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    case INTERFACE_EXPOSED:
69510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    case INTERFACE_ADDED:
70510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    case INTERFACE_SUSPENDED:
71510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    case INTERFACE_SUSPENDING:
72510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    case INTERFACE_RESUMING_1:
73510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    case INTERFACE_RESUMING_2:
74510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        if (mask)
75510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            return &this->mEnableLevels[aux];
76510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        break;
77510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    default:
78510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        break;
79510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    }
8061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    return NULL;
8161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
8261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
8391bfd060b992810ca092f640f77f795bc3d008beGlenn Kasten#if defined(ANDROID) && !defined(USE_BACKPORT)
84172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi/** \brief This is a private function that translates an Android effect framework status code
85172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi *  to the SL ES result code used in the EnableEffectSend() function of the SLEffectSendItf
86172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi *  interface.
87172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi */
88172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivistatic SLresult translateEnableFxSendError(android::status_t status) {
89172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi    switch (status) {
90172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi        case android::NO_ERROR:
91172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi            return SL_RESULT_SUCCESS;
92172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi            break;
93172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi        case android::INVALID_OPERATION:
94172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi        case android::BAD_VALUE:
95172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi        default:
96172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi            return SL_RESULT_RESOURCE_ERROR;
97172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi            break;
98172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi    }
99172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi}
10091bfd060b992810ca092f640f77f795bc3d008beGlenn Kasten#endif
101172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi
102ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
10361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenstatic SLresult IEffectSend_EnableEffectSend(SLEffectSendItf self,
10461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    const void *pAuxEffect, SLboolean enable, SLmillibel initialLevel)
10561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
106ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_ENTER_INTERFACE
107ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
108ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    if (!((SL_MILLIBEL_MIN <= initialLevel) && (initialLevel <= 0))) {
109ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        result = SL_RESULT_PARAMETER_INVALID;
110ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    } else {
111ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        IEffectSend *this = (IEffectSend *) self;
112ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        struct EnableLevel *enableLevel = getEnableLevel(this, pAuxEffect);
113ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        if (NULL == enableLevel) {
114ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            result = SL_RESULT_PARAMETER_INVALID;
115ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        } else {
116ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            interface_lock_exclusive(this);
117ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            enableLevel->mEnable = SL_BOOLEAN_FALSE != enable; // normalize
118ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            enableLevel->mSendLevel = initialLevel;
119172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi#if !defined(ANDROID) || defined(USE_BACKPORT)
120ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            result = SL_RESULT_SUCCESS;
121172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi#else
122172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi            // TODO do not repeat querying of CAudioPlayer, done inside getEnableLevel()
123172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi            CAudioPlayer *ap = (SL_OBJECTID_AUDIOPLAYER == InterfaceToObjectID(this)) ?
124172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi                    (CAudioPlayer *) this->mThis : NULL;
125172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi            // check which effect the send is attached to, attach and set level
126172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi            if (NULL == ap) {
127172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi                result = SL_RESULT_RESOURCE_ERROR;
128172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi            } else {
129f51dba65751107c930759938775b75531ec1f330Glenn Kasten                COutputMix *outputMix = CAudioPlayer_GetOutputMix(ap);
130ca325fa86f9e52d8300490eee102a3c1188f6bdcJean-Michel Trivi                // the initial send level set here is the total energy on the aux bus,
131ca325fa86f9e52d8300490eee102a3c1188f6bdcJean-Michel Trivi                //  so it must take into account the player volume level
132f51dba65751107c930759938775b75531ec1f330Glenn Kasten                if (pAuxEffect == &outputMix->mPresetReverb.mItf) {
133f51dba65751107c930759938775b75531ec1f330Glenn Kasten                    result = translateEnableFxSendError(android_fxSend_attach(ap, (bool) enable,
134ca325fa86f9e52d8300490eee102a3c1188f6bdcJean-Michel Trivi                        outputMix->mPresetReverb.mPresetReverbEffect,
135ca325fa86f9e52d8300490eee102a3c1188f6bdcJean-Michel Trivi                        initialLevel + ap->mVolume.mLevel));
136f51dba65751107c930759938775b75531ec1f330Glenn Kasten                } else if (pAuxEffect == &outputMix->mEnvironmentalReverb.mItf) {
137f51dba65751107c930759938775b75531ec1f330Glenn Kasten                    result = translateEnableFxSendError(android_fxSend_attach(ap, (bool) enable,
138ca325fa86f9e52d8300490eee102a3c1188f6bdcJean-Michel Trivi                        outputMix->mEnvironmentalReverb.mEnvironmentalReverbEffect,
139ca325fa86f9e52d8300490eee102a3c1188f6bdcJean-Michel Trivi                        initialLevel + ap->mVolume.mLevel));
140172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi                } else {
141172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi                    result = SL_RESULT_RESOURCE_ERROR;
142172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi                }
143172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi            }
144172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi#endif
145172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi            interface_unlock_exclusive(this);
146ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        }
147ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    }
148ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
149ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_LEAVE_INTERFACE
15061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
15161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
152ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
15361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenstatic SLresult IEffectSend_IsEnabled(SLEffectSendItf self,
15461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    const void *pAuxEffect, SLboolean *pEnable)
15561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
156ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_ENTER_INTERFACE
157ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
158ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    if (NULL == pEnable) {
159ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        result = SL_RESULT_PARAMETER_INVALID;
160ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    } else {
161ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        IEffectSend *this = (IEffectSend *) self;
162ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        struct EnableLevel *enableLevel = getEnableLevel(this, pAuxEffect);
163ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        if (NULL == enableLevel) {
164ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            result = SL_RESULT_PARAMETER_INVALID;
165ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        } else {
166ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            interface_lock_peek(this);
167ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            SLboolean enable = enableLevel->mEnable;
168ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            interface_unlock_peek(this);
169ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            *pEnable = enable;
170ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            result = SL_RESULT_SUCCESS;
171ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        }
172ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    }
173ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
174ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_LEAVE_INTERFACE
17561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
17661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
177ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
178d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kastenstatic SLresult IEffectSend_SetDirectLevel(SLEffectSendItf self, SLmillibel directLevel)
17961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
180ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_ENTER_INTERFACE
181ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
182ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    if (!((SL_MILLIBEL_MIN <= directLevel) && (directLevel <= 0))) {
183ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        result = SL_RESULT_PARAMETER_INVALID;
184ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    } else {
185ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        IEffectSend *this = (IEffectSend *) self;
186172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi        interface_lock_exclusive(this);
187fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi        CAudioPlayer *ap = (SL_OBJECTID_AUDIOPLAYER == InterfaceToObjectID(this)) ?
188fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi                (CAudioPlayer *) this->mThis : NULL;
189fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi        if (NULL != ap) {
190fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi            SLmillibel oldDirectLevel = ap->mDirectLevel;
191fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi            if (oldDirectLevel != directLevel) {
192fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi                ap->mDirectLevel = directLevel;
193fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi#if defined(ANDROID)
194172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi                ap->mAmplFromDirectLevel = sles_to_android_amplification(directLevel);
195fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi                interface_unlock_exclusive_attributes(this, ATTR_GAIN);
196fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi#else
197fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi                interface_unlock_exclusive(this);
19891bfd060b992810ca092f640f77f795bc3d008beGlenn Kasten#endif
199fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi            } else {
200fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi                interface_unlock_exclusive(this);
201fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi            }
202fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi            result = SL_RESULT_SUCCESS;
203172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi        } else {
204172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi            interface_unlock_exclusive(this);
205fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi            // the interface itself is invalid because it is not attached to an AudioPlayer
206fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi            result = SL_RESULT_PARAMETER_INVALID;
207172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi        }
208ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    }
209ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
210ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_LEAVE_INTERFACE
21161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
21261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
213ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
214d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kastenstatic SLresult IEffectSend_GetDirectLevel(SLEffectSendItf self, SLmillibel *pDirectLevel)
21561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
216ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_ENTER_INTERFACE
217ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
218ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    if (NULL == pDirectLevel) {
219ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        result = SL_RESULT_PARAMETER_INVALID;
220ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    } else {
221ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        IEffectSend *this = (IEffectSend *) self;
222fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi        interface_lock_shared(this);
223fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi        CAudioPlayer *ap = (SL_OBJECTID_AUDIOPLAYER == InterfaceToObjectID(this)) ?
224fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi                (CAudioPlayer *) this->mThis : NULL;
225fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi        if (NULL != ap) {
226fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi            *pDirectLevel = ap->mDirectLevel;
227fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi            result = SL_RESULT_SUCCESS;
228fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi        } else {
229fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi            // the interface itself is invalid because it is not attached to an AudioPlayer
230fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi            result = SL_RESULT_PARAMETER_INVALID;
231fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi        }
232fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi        interface_unlock_shared(this);
233ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    }
234ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
235ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_LEAVE_INTERFACE
23661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
23761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
238ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
239e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kastenstatic SLresult IEffectSend_SetSendLevel(SLEffectSendItf self, const void *pAuxEffect,
240e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten    SLmillibel sendLevel)
24161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
242ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_ENTER_INTERFACE
243ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
244ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    if (!((SL_MILLIBEL_MIN <= sendLevel) && (sendLevel <= 0))) {
245ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        result = SL_RESULT_PARAMETER_INVALID;
246ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    } else {
247ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        IEffectSend *this = (IEffectSend *) self;
248ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        struct EnableLevel *enableLevel = getEnableLevel(this, pAuxEffect);
249ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        if (NULL == enableLevel) {
250ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            result = SL_RESULT_PARAMETER_INVALID;
251ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        } else {
252a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten            result = SL_RESULT_SUCCESS;
253ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            // EnableEffectSend is exclusive, so this has to be also
254ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            interface_lock_exclusive(this);
255ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            enableLevel->mSendLevel = sendLevel;
256172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi#if defined(ANDROID) && !defined(USE_BACKPORT)
257172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi            CAudioPlayer *ap = (SL_OBJECTID_AUDIOPLAYER == InterfaceToObjectID(this)) ?
258172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi                    (CAudioPlayer *) this->mThis : NULL;
259172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi            if (NULL != ap) {
260ca325fa86f9e52d8300490eee102a3c1188f6bdcJean-Michel Trivi                // the send level set here is the total energy on the aux bus, so it must take
261ca325fa86f9e52d8300490eee102a3c1188f6bdcJean-Michel Trivi                // into account the player volume level
262ca325fa86f9e52d8300490eee102a3c1188f6bdcJean-Michel Trivi                result = android_fxSend_setSendLevel(ap, sendLevel + ap->mVolume.mLevel);
263172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi            }
264172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi#endif
265ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            interface_unlock_exclusive(this);
266ca325fa86f9e52d8300490eee102a3c1188f6bdcJean-Michel Trivi
267ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        }
268ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    }
269ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
270ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_LEAVE_INTERFACE
27161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
27261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
273ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
274e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kastenstatic SLresult IEffectSend_GetSendLevel(SLEffectSendItf self, const void *pAuxEffect,
275e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten    SLmillibel *pSendLevel)
27661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
277ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_ENTER_INTERFACE
278ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
279ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    if (NULL == pSendLevel) {
280ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        result = SL_RESULT_PARAMETER_INVALID;
281ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    } else {
282ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        IEffectSend *this = (IEffectSend *) self;
283ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        struct EnableLevel *enableLevel = getEnableLevel(this, pAuxEffect);
284ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        if (NULL == enableLevel) {
285ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            result = SL_RESULT_PARAMETER_INVALID;
286ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        } else {
287ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            interface_lock_peek(this);
288ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            SLmillibel sendLevel = enableLevel->mSendLevel;
289ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            interface_unlock_peek(this);
290ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            *pSendLevel = sendLevel;
291ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            result = SL_RESULT_SUCCESS;
292ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        }
293ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    }
294ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
295ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_LEAVE_INTERFACE
29661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
29761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
298ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
29961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenstatic const struct SLEffectSendItf_ IEffectSend_Itf = {
30061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IEffectSend_EnableEffectSend,
30161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IEffectSend_IsEnabled,
30261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IEffectSend_SetDirectLevel,
30361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IEffectSend_GetDirectLevel,
30461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IEffectSend_SetSendLevel,
30561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IEffectSend_GetSendLevel
30661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten};
30761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
30861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenvoid IEffectSend_init(void *self)
30961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
31061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IEffectSend *this = (IEffectSend *) self;
31161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    this->mItf = &IEffectSend_Itf;
3126a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kasten    struct EnableLevel *enableLevel = this->mEnableLevels;
3136a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kasten    unsigned aux;
3146a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kasten    for (aux = 0; aux < AUX_MAX; ++aux, ++enableLevel) {
3156a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kasten        enableLevel->mEnable = SL_BOOLEAN_FALSE;
3166a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kasten        enableLevel->mSendLevel = SL_MILLIBEL_MIN;
3176a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kasten    }
31861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
319