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