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/* 3DSource implementation */
18
19#include "sles_allinclusive.h"
20
21
22static SLresult I3DSource_SetHeadRelative(SL3DSourceItf self, SLboolean headRelative)
23{
24    SL_ENTER_INTERFACE
25
26    I3DSource *thiz = (I3DSource *) self;
27    interface_lock_poke(thiz);
28    thiz->mHeadRelative = SL_BOOLEAN_FALSE != headRelative; // normalize
29    interface_unlock_poke(thiz);
30    result = SL_RESULT_SUCCESS;
31
32    SL_LEAVE_INTERFACE
33}
34
35
36static SLresult I3DSource_GetHeadRelative(SL3DSourceItf self, SLboolean *pHeadRelative)
37{
38    SL_ENTER_INTERFACE
39
40    if (NULL == pHeadRelative) {
41        result = SL_RESULT_PARAMETER_INVALID;
42    } else {
43        I3DSource *thiz = (I3DSource *) self;
44        interface_lock_peek(thiz);
45        SLboolean headRelative = thiz->mHeadRelative;
46        interface_unlock_peek(thiz);
47        *pHeadRelative = headRelative;
48        result = SL_RESULT_SUCCESS;
49    }
50
51    SL_LEAVE_INTERFACE
52}
53
54
55static SLresult I3DSource_SetRolloffDistances(SL3DSourceItf self,
56    SLmillimeter minDistance, SLmillimeter maxDistance)
57{
58    SL_ENTER_INTERFACE
59
60    if (!((0 < minDistance) && (minDistance <= SL_MILLIMETER_MAX) &&
61        (minDistance <= maxDistance) && (maxDistance <= SL_MILLIMETER_MAX))) {
62        result = SL_RESULT_PARAMETER_INVALID;
63    } else {
64        I3DSource *thiz = (I3DSource *) self;
65        interface_lock_exclusive(thiz);
66        thiz->mMinDistance = minDistance;
67        thiz->mMaxDistance = maxDistance;
68        interface_unlock_exclusive(thiz);
69        result = SL_RESULT_SUCCESS;
70    }
71
72    SL_LEAVE_INTERFACE
73}
74
75
76static SLresult I3DSource_GetRolloffDistances(SL3DSourceItf self,
77    SLmillimeter *pMinDistance, SLmillimeter *pMaxDistance)
78{
79    SL_ENTER_INTERFACE
80
81    if (NULL == pMinDistance || NULL == pMaxDistance) {
82        result = SL_RESULT_PARAMETER_INVALID;
83    } else {
84        I3DSource *thiz = (I3DSource *) self; interface_lock_shared(thiz);
85        SLmillimeter minDistance = thiz->mMinDistance;
86        SLmillimeter maxDistance = thiz->mMaxDistance;
87        interface_unlock_shared(thiz);
88        *pMinDistance = minDistance;
89        *pMaxDistance = maxDistance;
90        result = SL_RESULT_SUCCESS;
91    }
92
93    SL_LEAVE_INTERFACE
94}
95
96
97static SLresult I3DSource_SetRolloffMaxDistanceMute(SL3DSourceItf self, SLboolean mute)
98{
99    SL_ENTER_INTERFACE
100
101    I3DSource *thiz = (I3DSource *) self;
102    interface_lock_poke(thiz);
103    thiz->mRolloffMaxDistanceMute = SL_BOOLEAN_FALSE != mute; // normalize
104    interface_unlock_poke(thiz);
105    result = SL_RESULT_SUCCESS;
106
107    SL_LEAVE_INTERFACE
108}
109
110
111static SLresult I3DSource_GetRolloffMaxDistanceMute(SL3DSourceItf self, SLboolean *pMute)
112{
113    SL_ENTER_INTERFACE
114
115    if (NULL == pMute) {
116        result = SL_RESULT_PARAMETER_INVALID;
117    } else {
118        I3DSource *thiz = (I3DSource *) self;
119        interface_lock_peek(thiz);
120        SLboolean mute = thiz->mRolloffMaxDistanceMute;
121        interface_unlock_peek(thiz);
122        *pMute = mute;
123        result = SL_RESULT_SUCCESS;
124    }
125
126    SL_LEAVE_INTERFACE
127}
128
129
130static SLresult I3DSource_SetRolloffFactor(SL3DSourceItf self, SLpermille rolloffFactor)
131{
132    SL_ENTER_INTERFACE
133
134    if (!((0 <= rolloffFactor) && (rolloffFactor <= 10000))) {
135        result = SL_RESULT_PARAMETER_INVALID;
136    } else {
137        I3DSource *thiz = (I3DSource *) self;
138        interface_lock_poke(thiz);
139        thiz->mRolloffFactor = rolloffFactor;
140        interface_unlock_poke(thiz);
141        result = SL_RESULT_SUCCESS;
142    }
143
144    SL_LEAVE_INTERFACE
145}
146
147
148static SLresult I3DSource_GetRolloffFactor(SL3DSourceItf self, SLpermille *pRolloffFactor)
149{
150    SL_ENTER_INTERFACE
151
152    I3DSource *thiz = (I3DSource *) self;
153    interface_lock_peek(thiz);
154    SLpermille rolloffFactor = thiz->mRolloffFactor;
155    interface_unlock_peek(thiz);
156    *pRolloffFactor = rolloffFactor;
157    result = SL_RESULT_SUCCESS;
158
159    SL_LEAVE_INTERFACE
160}
161
162
163static SLresult I3DSource_SetRoomRolloffFactor(SL3DSourceItf self, SLpermille roomRolloffFactor)
164{
165    SL_ENTER_INTERFACE
166
167    if (!((0 <= roomRolloffFactor) && (roomRolloffFactor <= 10000))) {
168        result = SL_RESULT_PARAMETER_INVALID;
169    } else {
170        I3DSource *thiz = (I3DSource *) self;
171        interface_lock_poke(thiz);
172        thiz->mRoomRolloffFactor = roomRolloffFactor;
173        interface_unlock_poke(thiz);
174        result = SL_RESULT_SUCCESS;
175    }
176
177    SL_LEAVE_INTERFACE
178}
179
180
181static SLresult I3DSource_GetRoomRolloffFactor(SL3DSourceItf self, SLpermille *pRoomRolloffFactor)
182{
183    SL_ENTER_INTERFACE
184
185    I3DSource *thiz = (I3DSource *) self;
186    interface_lock_peek(thiz);
187    SLpermille roomRolloffFactor = thiz->mRoomRolloffFactor;
188    interface_unlock_peek(thiz);
189    *pRoomRolloffFactor = roomRolloffFactor;
190    result = SL_RESULT_SUCCESS;
191
192    SL_LEAVE_INTERFACE
193}
194
195
196static SLresult I3DSource_SetRolloffModel(SL3DSourceItf self, SLuint8 model)
197{
198    SL_ENTER_INTERFACE
199
200    switch (model) {
201    case SL_ROLLOFFMODEL_LINEAR:
202    case SL_ROLLOFFMODEL_EXPONENTIAL:
203        {
204        I3DSource *thiz = (I3DSource *) self;
205        interface_lock_poke(thiz);
206        thiz->mDistanceModel = model;
207        interface_unlock_poke(thiz);
208        result = SL_RESULT_SUCCESS;
209        }
210        break;
211    default:
212        result = SL_RESULT_PARAMETER_INVALID;
213        break;
214    }
215
216    SL_LEAVE_INTERFACE
217}
218
219
220static SLresult I3DSource_GetRolloffModel(SL3DSourceItf self, SLuint8 *pModel)
221{
222    SL_ENTER_INTERFACE
223
224    I3DSource *thiz = (I3DSource *) self;
225    interface_lock_peek(thiz);
226    SLuint8 model = thiz->mDistanceModel;
227    interface_unlock_peek(thiz);
228    *pModel = model;
229    result = SL_RESULT_SUCCESS;
230
231    SL_LEAVE_INTERFACE
232}
233
234
235static SLresult I3DSource_SetCone(SL3DSourceItf self, SLmillidegree innerAngle,
236    SLmillidegree outerAngle, SLmillibel outerLevel)
237{
238    SL_ENTER_INTERFACE
239
240    if (!((0 <= innerAngle) && (innerAngle <= 360000) &&
241        (0 <= outerAngle) && (outerAngle <= 360000) &&
242        (SL_MILLIBEL_MIN <= outerLevel) && (outerLevel <= 0))) {
243        result = SL_RESULT_PARAMETER_INVALID;
244    } else {
245        I3DSource *thiz = (I3DSource *) self;
246        interface_lock_exclusive(thiz);
247        thiz->mConeInnerAngle = innerAngle;
248        thiz->mConeOuterAngle = outerAngle;
249        thiz->mConeOuterLevel = outerLevel;
250        interface_unlock_exclusive(thiz);
251        result = SL_RESULT_SUCCESS;
252    }
253
254    SL_LEAVE_INTERFACE
255}
256
257
258static SLresult I3DSource_GetCone(SL3DSourceItf self, SLmillidegree *pInnerAngle,
259    SLmillidegree *pOuterAngle, SLmillibel *pOuterLevel)
260{
261    SL_ENTER_INTERFACE
262
263    if (NULL == pInnerAngle || NULL == pOuterAngle || NULL == pOuterLevel) {
264        result = SL_RESULT_PARAMETER_INVALID;
265    } else {
266        I3DSource *thiz = (I3DSource *) self;
267        interface_lock_shared(thiz);
268        SLmillidegree innerAngle = thiz->mConeInnerAngle;
269        SLmillidegree outerAngle = thiz->mConeOuterAngle;
270        SLmillibel outerLevel = thiz->mConeOuterLevel;
271        interface_unlock_shared(thiz);
272        *pInnerAngle = innerAngle;
273        *pOuterAngle = outerAngle;
274        *pOuterLevel = outerLevel;
275        result = SL_RESULT_SUCCESS;
276    }
277
278    SL_LEAVE_INTERFACE
279}
280
281
282static const struct SL3DSourceItf_ I3DSource_Itf = {
283    I3DSource_SetHeadRelative,
284    I3DSource_GetHeadRelative,
285    I3DSource_SetRolloffDistances,
286    I3DSource_GetRolloffDistances,
287    I3DSource_SetRolloffMaxDistanceMute,
288    I3DSource_GetRolloffMaxDistanceMute,
289    I3DSource_SetRolloffFactor,
290    I3DSource_GetRolloffFactor,
291    I3DSource_SetRoomRolloffFactor,
292    I3DSource_GetRoomRolloffFactor,
293    I3DSource_SetRolloffModel,
294    I3DSource_GetRolloffModel,
295    I3DSource_SetCone,
296    I3DSource_GetCone
297};
298
299void I3DSource_init(void *self)
300{
301    I3DSource *thiz = (I3DSource *) self;
302    thiz->mItf = &I3DSource_Itf;
303    thiz->mHeadRelative = SL_BOOLEAN_FALSE;
304    thiz->mRolloffMaxDistanceMute = SL_BOOLEAN_FALSE;
305    thiz->mMaxDistance = SL_MILLIMETER_MAX;
306    thiz->mMinDistance = 1000;
307    thiz->mConeInnerAngle = 360000;
308    thiz->mConeOuterAngle = 360000;
309    thiz->mConeOuterLevel = 0;
310    thiz->mRolloffFactor = 1000;
311    thiz->mRoomRolloffFactor = 0;
312    thiz->mDistanceModel = SL_ROLLOFFMODEL_EXPONENTIAL;
313}
314