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
IAndroidEffectSend_EnableEffectSend(SLAndroidEffectSendItf self,SLInterfaceID effectImplementationId,SLboolean enable,SLmillibel initialLevel)22 static 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
IAndroidEffectSend_IsEnabled(SLAndroidEffectSendItf self,SLInterfaceID effectImplementationId,SLboolean * pEnable)60 static 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
IAndroidEffectSend_SetDirectLevel(SLAndroidEffectSendItf self,SLmillibel directLevel)81 static 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
IAndroidEffectSend_GetDirectLevel(SLAndroidEffectSendItf self,SLmillibel * pDirectLevel)116 static 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_shared(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_shared(thiz);
136 }
137
138 SL_LEAVE_INTERFACE
139 }
140
141
IAndroidEffectSend_SetSendLevel(SLAndroidEffectSendItf self,SLInterfaceID effectImplementationId,SLmillibel sendLevel)142 static 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
IAndroidEffectSend_GetSendLevel(SLAndroidEffectSendItf self,SLInterfaceID effectImplementationId,SLmillibel * pSendLevel)183 static 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 \
205 OutputMix");
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
221 static 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
IAndroidEffectSend_init(void * self)230 void 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