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