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            // the initial send level set here is the total energy on the aux bus,
42            //  so it must take into account the player volume level
43            result = android_fxSend_attachToAux(ap, effectImplementationId, enable,
44                    initialLevel + ap->mVolume.mLevel);
45            if (SL_RESULT_SUCCESS == result) {
46                // there currently is support for only one send bus, so there is a single send
47                // level and a single enable flag
48                thiz->mSendLevel = initialLevel;
49                thiz->mEnabled = enable;
50            }
51        }
52        interface_unlock_exclusive(thiz);
53    }
54
55    SL_LEAVE_INTERFACE
56}
57
58
59static SLresult IAndroidEffectSend_IsEnabled(SLAndroidEffectSendItf self,
60    SLInterfaceID effectImplementationId, SLboolean *pEnable)
61{
62    SL_ENTER_INTERFACE
63
64    if (NULL == pEnable) {
65        result = SL_RESULT_PARAMETER_INVALID;
66    } else {
67        IAndroidEffectSend *thiz = (IAndroidEffectSend *) self;
68        interface_lock_shared(thiz);
69        // there currently is support for only one send bus, so there is a single enable flag
70        SLboolean enable = thiz->mEnabled;
71        interface_unlock_shared(thiz);
72        *pEnable = enable;
73        result = SL_RESULT_SUCCESS;
74    }
75
76    SL_LEAVE_INTERFACE
77}
78
79
80static SLresult IAndroidEffectSend_SetDirectLevel(SLAndroidEffectSendItf self,
81        SLmillibel directLevel)
82{
83    SL_ENTER_INTERFACE
84
85    //if (!((SL_MILLIBEL_MIN <= directLevel) && (directLevel <= 0))) {
86    // comparison (SL_MILLIBEL_MIN <= directLevel) is always true due to range of SLmillibel
87    if (!(directLevel <= 0)) {
88        result = SL_RESULT_PARAMETER_INVALID;
89    } else {
90        IAndroidEffectSend *thiz = (IAndroidEffectSend *) self;
91        interface_lock_exclusive(thiz);
92        CAudioPlayer *ap = (SL_OBJECTID_AUDIOPLAYER == InterfaceToObjectID(thiz)) ?
93                (CAudioPlayer *) thiz->mThis : NULL;
94        if (NULL != ap) {
95            SLmillibel oldDirectLevel = ap->mDirectLevel;
96            if (oldDirectLevel != directLevel) {
97                ap->mDirectLevel = directLevel;
98                ap->mAmplFromDirectLevel = sles_to_android_amplification(directLevel);
99                interface_unlock_exclusive_attributes(thiz, ATTR_GAIN);
100            } else {
101                interface_unlock_exclusive(thiz);
102            }
103            result = SL_RESULT_SUCCESS;
104        } else {
105            interface_unlock_exclusive(thiz);
106            SL_LOGE("invalid interface: not attached to an AudioPlayer");
107            result = SL_RESULT_PARAMETER_INVALID;
108        }
109    }
110
111     SL_LEAVE_INTERFACE
112}
113
114
115static SLresult IAndroidEffectSend_GetDirectLevel(SLAndroidEffectSendItf self,
116        SLmillibel *pDirectLevel)
117{
118    SL_ENTER_INTERFACE
119
120    if (NULL == pDirectLevel) {
121        result = SL_RESULT_PARAMETER_INVALID;
122    } else {
123        IAndroidEffectSend *thiz = (IAndroidEffectSend *) self;
124        interface_lock_shared(thiz);
125        CAudioPlayer *ap = (SL_OBJECTID_AUDIOPLAYER == InterfaceToObjectID(thiz)) ?
126                (CAudioPlayer *) thiz->mThis : NULL;
127        if (NULL != ap) {
128            *pDirectLevel = ap->mDirectLevel;
129            result = SL_RESULT_SUCCESS;
130        } else {
131            SL_LOGE("invalid interface: not attached to an AudioPlayer");
132            result = SL_RESULT_PARAMETER_INVALID;
133        }
134        interface_unlock_shared(thiz);
135    }
136
137    SL_LEAVE_INTERFACE
138}
139
140
141static SLresult IAndroidEffectSend_SetSendLevel(SLAndroidEffectSendItf self,
142        SLInterfaceID effectImplementationId, SLmillibel sendLevel)
143{
144    SL_ENTER_INTERFACE
145
146    //if (!((SL_MILLIBEL_MIN <= sendLevel) && (sendLevel <= 0))) {
147    // comparison (SL_MILLIBEL_MIN <= sendLevel) is always true due to range of SLmillibel
148    if (!(sendLevel <= 0)) {
149        result = SL_RESULT_PARAMETER_INVALID;
150    } else {
151        IAndroidEffectSend *thiz = (IAndroidEffectSend *) self;
152        interface_lock_exclusive(thiz);
153        // is SLAndroidEffectSendItf on an AudioPlayer?
154        CAudioPlayer *ap = (SL_OBJECTID_AUDIOPLAYER == InterfaceToObjectID(thiz)) ?
155                 (CAudioPlayer *) thiz->mThis : NULL;
156        if (NULL == ap) {
157            SL_LOGE("invalid interface: not attached to an AudioPlayer");
158            result = SL_RESULT_PARAMETER_INVALID;
159        } else {
160            COutputMix *outputMix = CAudioPlayer_GetOutputMix(ap);
161            if (android_genericFx_hasEffect(&outputMix->mAndroidEffect, effectImplementationId)) {
162                // the send level set here is the total energy on the aux bus, so it must take
163                // into account the player volume level
164                result = android_fxSend_setSendLevel(ap, sendLevel + ap->mVolume.mLevel);
165            } else {
166                 SL_LOGE("trying to send to an effect not on this AudioPlayer's OutputMix");
167                 result = SL_RESULT_PARAMETER_INVALID;
168            }
169            if (SL_RESULT_SUCCESS == result) {
170                // there currently is support for only one send bus, so there is a single send
171                // level
172                thiz->mSendLevel = sendLevel;
173            }
174        }
175        interface_unlock_exclusive(thiz);
176    }
177
178    SL_LEAVE_INTERFACE
179}
180
181
182static SLresult IAndroidEffectSend_GetSendLevel(SLAndroidEffectSendItf self,
183        SLInterfaceID effectImplementationId, SLmillibel *pSendLevel)
184{
185    SL_ENTER_INTERFACE
186
187    if (NULL == pSendLevel) {
188        result = SL_RESULT_PARAMETER_INVALID;
189    } else {
190        IAndroidEffectSend *thiz = (IAndroidEffectSend *) self;
191        interface_lock_exclusive(thiz);
192        // is SLAndroidEffectSendItf on an AudioPlayer?
193        CAudioPlayer *ap = (SL_OBJECTID_AUDIOPLAYER == InterfaceToObjectID(thiz)) ?
194                (CAudioPlayer *) thiz->mThis : NULL;
195        if (NULL == ap) {
196            SL_LOGE("invalid interface: not attached to an AudioPlayer");
197            result = SL_RESULT_PARAMETER_INVALID;
198        } else {
199            COutputMix *outputMix = CAudioPlayer_GetOutputMix(ap);
200            if (android_genericFx_hasEffect(&outputMix->mAndroidEffect, effectImplementationId)) {
201                result = SL_RESULT_SUCCESS;
202            } else {
203                SL_LOGE("trying to retrieve send level on an effect not on this AudioPlayer's \
204OutputMix");
205                result = SL_RESULT_PARAMETER_INVALID;
206                }
207            if (SL_RESULT_SUCCESS == result) {
208                // there currently is support for only one send bus, so there is a single send
209                // level
210                *pSendLevel = thiz->mSendLevel;
211            }
212        }
213        interface_unlock_exclusive(thiz);
214    }
215
216    SL_LEAVE_INTERFACE
217}
218
219
220static const struct SLAndroidEffectSendItf_ IAndroidEffectSend_Itf = {
221    IAndroidEffectSend_EnableEffectSend,
222    IAndroidEffectSend_IsEnabled,
223    IAndroidEffectSend_SetDirectLevel,
224    IAndroidEffectSend_GetDirectLevel,
225    IAndroidEffectSend_SetSendLevel,
226    IAndroidEffectSend_GetSendLevel
227};
228
229void IAndroidEffectSend_init(void *self)
230{
231    IAndroidEffectSend *thiz = (IAndroidEffectSend *) self;
232    thiz->mItf = &IAndroidEffectSend_Itf;
233    thiz->mEnabled =  SL_BOOLEAN_FALSE;
234    thiz->mSendLevel = SL_MILLIBEL_MIN;
235}
236