IEffectSend.c revision fef6033d852daec8d88060b252e72f322724dca1
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;
4661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    // Make sure the sink for this player is an output mix
47343c522ebf4f9c321eef8c3b3b2945f1c1cb8846Glenn Kasten    COutputMix *outputMix = audioPlayer->mOutputMix;
4861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    if (NULL == outputMix)
4961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        return NULL;
50510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    unsigned aux;
51510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    if (pAuxEffect == &outputMix->mEnvironmentalReverb.mItf)
52510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        aux = AUX_ENVIRONMENTALREVERB;
53510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    else if (pAuxEffect == &outputMix->mPresetReverb.mItf)
54510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        aux = AUX_PRESETREVERB;
55510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    else
56510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        return NULL;
57510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    assert(aux < AUX_MAX);
58e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten    // Validate that the application has a valid interface for the effect.  The interface must have
59e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten    // been exposed at object creation time or by DynamicInterface::AddInterface, and it also must
60e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten    // have been "gotten" with Object::GetInterface.
61510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    int index = MPH_to_OutputMix[AUX_to_MPH[aux]];
62510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    if (0 > index)
63510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        return NULL;
64510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    unsigned mask = 1 << index;
65510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    object_lock_shared(&outputMix->mObject);
66510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    SLuint32 state = outputMix->mObject.mInterfaceStates[index];
67510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    mask &= outputMix->mObject.mGottenMask;
68510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    object_unlock_shared(&outputMix->mObject);
69510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    switch (state) {
70510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    case INTERFACE_EXPOSED:
71510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    case INTERFACE_ADDED:
72510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    case INTERFACE_SUSPENDED:
73510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    case INTERFACE_SUSPENDING:
74510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    case INTERFACE_RESUMING_1:
75510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    case INTERFACE_RESUMING_2:
76510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        if (mask)
77510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten            return &this->mEnableLevels[aux];
78510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        break;
79510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    default:
80510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten        break;
81510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten    }
8261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    return NULL;
8361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
8461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
8591bfd060b992810ca092f640f77f795bc3d008beGlenn Kasten#if defined(ANDROID) && !defined(USE_BACKPORT)
86172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi/** \brief This is a private function that translates an Android effect framework status code
87172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi *  to the SL ES result code used in the EnableEffectSend() function of the SLEffectSendItf
88172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi *  interface.
89172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi */
90172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivistatic SLresult translateEnableFxSendError(android::status_t status) {
91172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi    switch (status) {
92172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi        case android::NO_ERROR:
93172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi            return SL_RESULT_SUCCESS;
94172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi            break;
95172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi        case android::INVALID_OPERATION:
96172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi        case android::BAD_VALUE:
97172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi        default:
98172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi            return SL_RESULT_RESOURCE_ERROR;
99172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi            break;
100172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi    }
101172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi}
10291bfd060b992810ca092f640f77f795bc3d008beGlenn Kasten#endif
103172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi
104ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
10561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenstatic SLresult IEffectSend_EnableEffectSend(SLEffectSendItf self,
10661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    const void *pAuxEffect, SLboolean enable, SLmillibel initialLevel)
10761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
108ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_ENTER_INTERFACE
109ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
110ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    if (!((SL_MILLIBEL_MIN <= initialLevel) && (initialLevel <= 0))) {
111ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        result = SL_RESULT_PARAMETER_INVALID;
112ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    } else {
113ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        IEffectSend *this = (IEffectSend *) self;
114ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        struct EnableLevel *enableLevel = getEnableLevel(this, pAuxEffect);
115ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        if (NULL == enableLevel) {
116ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            result = SL_RESULT_PARAMETER_INVALID;
117ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        } else {
118ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            interface_lock_exclusive(this);
119ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            enableLevel->mEnable = SL_BOOLEAN_FALSE != enable; // normalize
120ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            enableLevel->mSendLevel = initialLevel;
121172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi#if !defined(ANDROID) || defined(USE_BACKPORT)
122ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            result = SL_RESULT_SUCCESS;
123172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi#else
124172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi            // TODO do not repeat querying of CAudioPlayer, done inside getEnableLevel()
125172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi            CAudioPlayer *ap = (SL_OBJECTID_AUDIOPLAYER == InterfaceToObjectID(this)) ?
126172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi                    (CAudioPlayer *) this->mThis : NULL;
127172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi            // check which effect the send is attached to, attach and set level
128172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi            if (NULL == ap) {
129172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi                result = SL_RESULT_RESOURCE_ERROR;
130172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi            } else {
131172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi                if (pAuxEffect == &ap->mOutputMix->mPresetReverb.mItf) {
132172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi                    result = translateEnableFxSendError(
133172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi                            android_fxSend_attach( ap, (bool) enable,
134172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi                                    ap->mOutputMix->mPresetReverb.mPresetReverbEffect,
135172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi                                    initialLevel) );
136172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi                } else if (pAuxEffect == &ap->mOutputMix->mEnvironmentalReverb.mItf) {
137172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi                    result = translateEnableFxSendError(
138172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi                            android_fxSend_attach( ap, (bool) enable,
139172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi                                    ap->mOutputMix->mEnvironmentalReverb.mEnvironmentalReverbEffect,
140172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi                                    initialLevel) );
141172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi                } else {
142172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi                    result = SL_RESULT_RESOURCE_ERROR;
143172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi                }
144172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi            }
145172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi#endif
146172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi            interface_unlock_exclusive(this);
147ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        }
148ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    }
149ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
150ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_LEAVE_INTERFACE
15161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
15261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
153ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
15461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenstatic SLresult IEffectSend_IsEnabled(SLEffectSendItf self,
15561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    const void *pAuxEffect, SLboolean *pEnable)
15661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
157ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_ENTER_INTERFACE
158ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
159ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    if (NULL == pEnable) {
160ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        result = SL_RESULT_PARAMETER_INVALID;
161ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    } else {
162ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        IEffectSend *this = (IEffectSend *) self;
163ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        struct EnableLevel *enableLevel = getEnableLevel(this, pAuxEffect);
164ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        if (NULL == enableLevel) {
165ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            result = SL_RESULT_PARAMETER_INVALID;
166ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        } else {
167ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            interface_lock_peek(this);
168ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            SLboolean enable = enableLevel->mEnable;
169ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            interface_unlock_peek(this);
170ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            *pEnable = enable;
171ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            result = SL_RESULT_SUCCESS;
172ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        }
173ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    }
174ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
175ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_LEAVE_INTERFACE
17661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
17761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
178ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
179d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kastenstatic SLresult IEffectSend_SetDirectLevel(SLEffectSendItf self, SLmillibel directLevel)
18061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
181ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_ENTER_INTERFACE
182ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
183ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    if (!((SL_MILLIBEL_MIN <= directLevel) && (directLevel <= 0))) {
184ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        result = SL_RESULT_PARAMETER_INVALID;
185ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    } else {
186ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        IEffectSend *this = (IEffectSend *) self;
187172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi        interface_lock_exclusive(this);
188fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi        CAudioPlayer *ap = (SL_OBJECTID_AUDIOPLAYER == InterfaceToObjectID(this)) ?
189fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi                (CAudioPlayer *) this->mThis : NULL;
190fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi        if (NULL != ap) {
191fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi            SLmillibel oldDirectLevel = ap->mDirectLevel;
192fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi            if (oldDirectLevel != directLevel) {
193fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi                ap->mDirectLevel = directLevel;
194fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi#if defined(ANDROID)
195172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi                ap->mAmplFromDirectLevel = sles_to_android_amplification(directLevel);
196fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi                interface_unlock_exclusive_attributes(this, ATTR_GAIN);
197fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi#else
198fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi                interface_unlock_exclusive(this);
19991bfd060b992810ca092f640f77f795bc3d008beGlenn Kasten#endif
200fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi            } else {
201fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi                interface_unlock_exclusive(this);
202fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi            }
203fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi            result = SL_RESULT_SUCCESS;
204172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi        } else {
205172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi            interface_unlock_exclusive(this);
206fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi            // the interface itself is invalid because it is not attached to an AudioPlayer
207fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi            result = SL_RESULT_PARAMETER_INVALID;
208172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi        }
209ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    }
210ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
211ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_LEAVE_INTERFACE
21261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
21361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
214ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
215d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kastenstatic SLresult IEffectSend_GetDirectLevel(SLEffectSendItf self, SLmillibel *pDirectLevel)
21661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
217ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_ENTER_INTERFACE
218ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
219ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    if (NULL == pDirectLevel) {
220ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        result = SL_RESULT_PARAMETER_INVALID;
221ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    } else {
222ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        IEffectSend *this = (IEffectSend *) self;
223fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi        interface_lock_shared(this);
224fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi        CAudioPlayer *ap = (SL_OBJECTID_AUDIOPLAYER == InterfaceToObjectID(this)) ?
225fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi                (CAudioPlayer *) this->mThis : NULL;
226fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi        if (NULL != ap) {
227fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi            *pDirectLevel = ap->mDirectLevel;
228fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi            result = SL_RESULT_SUCCESS;
229fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi        } else {
230fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi            // the interface itself is invalid because it is not attached to an AudioPlayer
231fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi            result = SL_RESULT_PARAMETER_INVALID;
232fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi        }
233fef6033d852daec8d88060b252e72f322724dca1Jean-Michel Trivi        interface_unlock_shared(this);
234ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    }
235ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
236ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_LEAVE_INTERFACE
23761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
23861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
239ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
240e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kastenstatic SLresult IEffectSend_SetSendLevel(SLEffectSendItf self, const void *pAuxEffect,
241e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten    SLmillibel sendLevel)
24261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
243ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_ENTER_INTERFACE
244ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
245ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    if (!((SL_MILLIBEL_MIN <= sendLevel) && (sendLevel <= 0))) {
246ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        result = SL_RESULT_PARAMETER_INVALID;
247ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    } else {
248ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        IEffectSend *this = (IEffectSend *) self;
249ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        struct EnableLevel *enableLevel = getEnableLevel(this, pAuxEffect);
250ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        if (NULL == enableLevel) {
251ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            result = SL_RESULT_PARAMETER_INVALID;
252ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        } else {
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) {
260172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi                android_fxSend_setSendLevel(ap, sendLevel);
261172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi            }
262172e4da556ad3cb1d2a06cfa019903310aa291d5Jean-Michel Trivi#endif
263ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            interface_unlock_exclusive(this);
264ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            result = SL_RESULT_SUCCESS;
265ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        }
266ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    }
267ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
268ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_LEAVE_INTERFACE
26961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
27061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
271ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
272e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kastenstatic SLresult IEffectSend_GetSendLevel(SLEffectSendItf self, const void *pAuxEffect,
273e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten    SLmillibel *pSendLevel)
27461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
275ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_ENTER_INTERFACE
276ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
277ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    if (NULL == pSendLevel) {
278ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        result = SL_RESULT_PARAMETER_INVALID;
279ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    } else {
280ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        IEffectSend *this = (IEffectSend *) self;
281ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        struct EnableLevel *enableLevel = getEnableLevel(this, pAuxEffect);
282ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        if (NULL == enableLevel) {
283ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            result = SL_RESULT_PARAMETER_INVALID;
284ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        } else {
285ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            interface_lock_peek(this);
286ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            SLmillibel sendLevel = enableLevel->mSendLevel;
287ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            interface_unlock_peek(this);
288ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            *pSendLevel = sendLevel;
289ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten            result = SL_RESULT_SUCCESS;
290ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten        }
291ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    }
292ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
293ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten    SL_LEAVE_INTERFACE
29461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
29561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
296ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten
29761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenstatic const struct SLEffectSendItf_ IEffectSend_Itf = {
29861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IEffectSend_EnableEffectSend,
29961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IEffectSend_IsEnabled,
30061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IEffectSend_SetDirectLevel,
30161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IEffectSend_GetDirectLevel,
30261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IEffectSend_SetSendLevel,
30361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IEffectSend_GetSendLevel
30461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten};
30561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
30661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenvoid IEffectSend_init(void *self)
30761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
30861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IEffectSend *this = (IEffectSend *) self;
30961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    this->mItf = &IEffectSend_Itf;
3106a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kasten    struct EnableLevel *enableLevel = this->mEnableLevels;
3116a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kasten    unsigned aux;
3126a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kasten    for (aux = 0; aux < AUX_MAX; ++aux, ++enableLevel) {
3136a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kasten        enableLevel->mEnable = SL_BOOLEAN_FALSE;
3146a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kasten        enableLevel->mSendLevel = SL_MILLIBEL_MIN;
3156a357b8fa57b0bc1557cd5ab9f9fb86aabaaa18cGlenn Kasten    }
31661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
317