IAndroidEffectSend.c revision ad79bbfd16ba81a45842179178332fbd06ad365e
1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17/* AndroidEffectSend implementation */
18
19#include "sles_allinclusive.h"
20
21
22static SLresult IAndroidEffectSend_EnableEffectSend(SLAndroidEffectSendItf self,
23    SLInterfaceID effectImplementationId, SLboolean enable, SLmillibel initialLevel)
24{
25    SL_ENTER_INTERFACE
26
27    //if (!((SL_MILLIBEL_MIN <= initialLevel) && (initialLevel <= 0))) {
28    // comparison (SL_MILLIBEL_MIN <= initialLevel) is always true due to range of SLmillibel
29    if (!(initialLevel <= 0)) {
30        result = SL_RESULT_PARAMETER_INVALID;
31    } else {
32        IAndroidEffectSend *thiz = (IAndroidEffectSend *) self;
33        interface_lock_exclusive(thiz);
34        // is SLAndroidEffectSendItf on an AudioPlayer?
35        CAudioPlayer *ap = (SL_OBJECTID_AUDIOPLAYER == InterfaceToObjectID(thiz)) ?
36                (CAudioPlayer *) thiz->mThis : NULL;
37        if (NULL == ap) {
38            SL_LOGE("invalid interface: not attached to an AudioPlayer");
39            result = SL_RESULT_PARAMETER_INVALID;
40        } else {
41            COutputMix *outputMix = CAudioPlayer_GetOutputMix(ap);
42            // the initial send level set here is the total energy on the aux bus,
43            //  so it must take into account the player volume level
44            result = android_fxSend_attachToAux(ap, effectImplementationId, enable,
45                    initialLevel + ap->mVolume.mLevel);
46            if (SL_RESULT_SUCCESS == result) {
47                // there currently is support for only one send bus, so there is a single send
48                // level and a single enable flag
49                thiz->mSendLevel = initialLevel;
50                thiz->mEnabled = enable;
51            }
52        }
53        interface_unlock_exclusive(thiz);
54    }
55
56    SL_LEAVE_INTERFACE
57}
58
59
60static SLresult IAndroidEffectSend_IsEnabled(SLAndroidEffectSendItf self,
61    SLInterfaceID effectImplementationId, SLboolean *pEnable)
62{
63    SL_ENTER_INTERFACE
64
65    if (NULL == pEnable) {
66        result = SL_RESULT_PARAMETER_INVALID;
67    } else {
68        IAndroidEffectSend *thiz = (IAndroidEffectSend *) self;
69        interface_lock_shared(thiz);
70        // there currently is support for only one send bus, so there is a single enable flag
71        SLboolean enable = thiz->mEnabled;
72        interface_unlock_shared(thiz);
73        *pEnable = enable;
74        result = SL_RESULT_SUCCESS;
75    }
76
77    SL_LEAVE_INTERFACE
78}
79
80
81static SLresult IAndroidEffectSend_SetDirectLevel(SLAndroidEffectSendItf self,
82        SLmillibel directLevel)
83{
84    SL_ENTER_INTERFACE
85
86    //if (!((SL_MILLIBEL_MIN <= directLevel) && (directLevel <= 0))) {
87    // comparison (SL_MILLIBEL_MIN <= directLevel) is always true due to range of SLmillibel
88    if (!(directLevel <= 0)) {
89        result = SL_RESULT_PARAMETER_INVALID;
90    } else {
91        IAndroidEffectSend *thiz = (IAndroidEffectSend *) self;
92        interface_lock_exclusive(thiz);
93        CAudioPlayer *ap = (SL_OBJECTID_AUDIOPLAYER == InterfaceToObjectID(thiz)) ?
94                (CAudioPlayer *) thiz->mThis : NULL;
95        if (NULL != ap) {
96            SLmillibel oldDirectLevel = ap->mDirectLevel;
97            if (oldDirectLevel != directLevel) {
98                ap->mDirectLevel = directLevel;
99                ap->mAmplFromDirectLevel = sles_to_android_amplification(directLevel);
100                interface_unlock_exclusive_attributes(thiz, ATTR_GAIN);
101            } else {
102                interface_unlock_exclusive(thiz);
103            }
104            result = SL_RESULT_SUCCESS;
105        } else {
106            interface_unlock_exclusive(thiz);
107            SL_LOGE("invalid interface: not attached to an AudioPlayer");
108            result = SL_RESULT_PARAMETER_INVALID;
109        }
110    }
111
112     SL_LEAVE_INTERFACE
113}
114
115
116static SLresult IAndroidEffectSend_GetDirectLevel(SLAndroidEffectSendItf self,
117        SLmillibel *pDirectLevel)
118{
119    SL_ENTER_INTERFACE
120
121    if (NULL == pDirectLevel) {
122        result = SL_RESULT_PARAMETER_INVALID;
123    } else {
124        IAndroidEffectSend *thiz = (IAndroidEffectSend *) self;
125        interface_lock_peek(thiz);
126        CAudioPlayer *ap = (SL_OBJECTID_AUDIOPLAYER == InterfaceToObjectID(thiz)) ?
127                (CAudioPlayer *) thiz->mThis : NULL;
128        if (NULL != ap) {
129            *pDirectLevel = ap->mDirectLevel;
130            result = SL_RESULT_SUCCESS;
131        } else {
132            SL_LOGE("invalid interface: not attached to an AudioPlayer");
133            result = SL_RESULT_PARAMETER_INVALID;
134        }
135        interface_unlock_peek(thiz);
136    }
137
138    SL_LEAVE_INTERFACE
139}
140
141
142static SLresult IAndroidEffectSend_SetSendLevel(SLAndroidEffectSendItf self,
143        SLInterfaceID effectImplementationId, SLmillibel sendLevel)
144{
145    SL_ENTER_INTERFACE
146
147    //if (!((SL_MILLIBEL_MIN <= sendLevel) && (sendLevel <= 0))) {
148    // comparison (SL_MILLIBEL_MIN <= sendLevel) is always true due to range of SLmillibel
149    if (!(sendLevel <= 0)) {
150        result = SL_RESULT_PARAMETER_INVALID;
151    } else {
152        IAndroidEffectSend *thiz = (IAndroidEffectSend *) self;
153        interface_lock_exclusive(thiz);
154        // is SLAndroidEffectSendItf on an AudioPlayer?
155        CAudioPlayer *ap = (SL_OBJECTID_AUDIOPLAYER == InterfaceToObjectID(thiz)) ?
156                 (CAudioPlayer *) thiz->mThis : NULL;
157        if (NULL == ap) {
158            SL_LOGE("invalid interface: not attached to an AudioPlayer");
159            result = SL_RESULT_PARAMETER_INVALID;
160        } else {
161            COutputMix *outputMix = CAudioPlayer_GetOutputMix(ap);
162            if (android_genericFx_hasEffect(&outputMix->mAndroidEffect, effectImplementationId)) {
163                // the send level set here is the total energy on the aux bus, so it must take
164                // into account the player volume level
165                result = android_fxSend_setSendLevel(ap, sendLevel + ap->mVolume.mLevel);
166            } else {
167                 SL_LOGE("trying to send to an effect not on this AudioPlayer's OutputMix");
168                 result = SL_RESULT_PARAMETER_INVALID;
169            }
170            if (SL_RESULT_SUCCESS == result) {
171                // there currently is support for only one send bus, so there is a single send
172                // level
173                thiz->mSendLevel = sendLevel;
174            }
175        }
176        interface_unlock_exclusive(thiz);
177    }
178
179    SL_LEAVE_INTERFACE
180}
181
182
183static SLresult IAndroidEffectSend_GetSendLevel(SLAndroidEffectSendItf self,
184        SLInterfaceID effectImplementationId, SLmillibel *pSendLevel)
185{
186    SL_ENTER_INTERFACE
187
188    if (NULL == pSendLevel) {
189        result = SL_RESULT_PARAMETER_INVALID;
190    } else {
191        IAndroidEffectSend *thiz = (IAndroidEffectSend *) self;
192        interface_lock_exclusive(thiz);
193        // is SLAndroidEffectSendItf on an AudioPlayer?
194        CAudioPlayer *ap = (SL_OBJECTID_AUDIOPLAYER == InterfaceToObjectID(thiz)) ?
195                (CAudioPlayer *) thiz->mThis : NULL;
196        if (NULL == ap) {
197            SL_LOGE("invalid interface: not attached to an AudioPlayer");
198            result = SL_RESULT_PARAMETER_INVALID;
199        } else {
200            COutputMix *outputMix = CAudioPlayer_GetOutputMix(ap);
201            if (android_genericFx_hasEffect(&outputMix->mAndroidEffect, effectImplementationId)) {
202                result = SL_RESULT_SUCCESS;
203            } else {
204                SL_LOGE("trying to retrieve send level on an effect not on this AudioPlayer's \
205OutputMix");
206                result = SL_RESULT_PARAMETER_INVALID;
207                }
208            if (SL_RESULT_SUCCESS == result) {
209                // there currently is support for only one send bus, so there is a single send
210                // level
211                *pSendLevel = thiz->mSendLevel;
212            }
213        }
214        interface_unlock_exclusive(thiz);
215    }
216
217    SL_LEAVE_INTERFACE
218}
219
220
221static const struct SLAndroidEffectSendItf_ IAndroidEffectSend_Itf = {
222    IAndroidEffectSend_EnableEffectSend,
223    IAndroidEffectSend_IsEnabled,
224    IAndroidEffectSend_SetDirectLevel,
225    IAndroidEffectSend_GetDirectLevel,
226    IAndroidEffectSend_SetSendLevel,
227    IAndroidEffectSend_GetSendLevel
228};
229
230void IAndroidEffectSend_init(void *self)
231{
232    IAndroidEffectSend *thiz = (IAndroidEffectSend *) self;
233    thiz->mItf = &IAndroidEffectSend_Itf;
234    thiz->mEnabled =  SL_BOOLEAN_FALSE;
235    thiz->mSendLevel = SL_MILLIBEL_MIN;
236}
237