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 /* 3DLocation implementation */
18
19 #include "sles_allinclusive.h"
20
21
I3DLocation_SetLocationCartesian(SL3DLocationItf self,const SLVec3D * pLocation)22 static SLresult I3DLocation_SetLocationCartesian(SL3DLocationItf self, const SLVec3D *pLocation)
23 {
24 SL_ENTER_INTERFACE
25
26 if (NULL == pLocation) {
27 result = SL_RESULT_PARAMETER_INVALID;
28 } else {
29 I3DLocation *thiz = (I3DLocation *) self;
30 SLVec3D locationCartesian = *pLocation;
31 interface_lock_exclusive(thiz);
32 thiz->mLocationCartesian = locationCartesian;
33 thiz->mLocationActive = CARTESIAN_SET_SPHERICAL_UNKNOWN;
34 interface_unlock_exclusive(thiz);
35 result = SL_RESULT_SUCCESS;
36 }
37
38 SL_LEAVE_INTERFACE
39 }
40
41
I3DLocation_SetLocationSpherical(SL3DLocationItf self,SLmillidegree azimuth,SLmillidegree elevation,SLmillimeter distance)42 static SLresult I3DLocation_SetLocationSpherical(SL3DLocationItf self,
43 SLmillidegree azimuth, SLmillidegree elevation, SLmillimeter distance)
44 {
45 SL_ENTER_INTERFACE
46
47 if (!((-360000 <= azimuth) && (azimuth <= 360000) &&
48 (-90000 <= elevation) && (elevation <= 90000) &&
49 (0 <= distance) && (distance <= SL_MILLIMETER_MAX))) {
50 result = SL_RESULT_PARAMETER_INVALID;
51 } else {
52 I3DLocation *thiz = (I3DLocation *) self;
53 interface_lock_exclusive(thiz);
54 thiz->mLocationSpherical.mAzimuth = azimuth;
55 thiz->mLocationSpherical.mElevation = elevation;
56 thiz->mLocationSpherical.mDistance = distance;
57 thiz->mLocationActive = CARTESIAN_UNKNOWN_SPHERICAL_SET;
58 interface_unlock_exclusive(thiz);
59 result = SL_RESULT_SUCCESS;
60 }
61
62 SL_LEAVE_INTERFACE
63 }
64
65
I3DLocation_Move(SL3DLocationItf self,const SLVec3D * pMovement)66 static SLresult I3DLocation_Move(SL3DLocationItf self, const SLVec3D *pMovement)
67 {
68 SL_ENTER_INTERFACE
69
70 if (NULL == pMovement) {
71 result = SL_RESULT_PARAMETER_INVALID;
72 } else {
73 I3DLocation *thiz = (I3DLocation *) self;
74 SLVec3D movementCartesian = *pMovement;
75 interface_lock_exclusive(thiz);
76 for (;;) {
77 enum CartesianSphericalActive locationActive = thiz->mLocationActive;
78 switch (locationActive) {
79 case CARTESIAN_COMPUTED_SPHERICAL_SET:
80 case CARTESIAN_SET_SPHERICAL_COMPUTED: // not in 1.0.1
81 case CARTESIAN_SET_SPHERICAL_REQUESTED: // not in 1.0.1
82 case CARTESIAN_SET_SPHERICAL_UNKNOWN:
83 thiz->mLocationCartesian.x += movementCartesian.x;
84 thiz->mLocationCartesian.y += movementCartesian.y;
85 thiz->mLocationCartesian.z += movementCartesian.z;
86 thiz->mLocationActive = CARTESIAN_SET_SPHERICAL_UNKNOWN;
87 break;
88 case CARTESIAN_UNKNOWN_SPHERICAL_SET:
89 thiz->mLocationActive = CARTESIAN_REQUESTED_SPHERICAL_SET;
90 FALLTHROUGH_INTENDED;
91 case CARTESIAN_REQUESTED_SPHERICAL_SET:
92 // matched by cond_broadcast in case multiple requesters
93 #if 0
94 interface_cond_wait(thiz);
95 #else
96 thiz->mLocationActive = CARTESIAN_COMPUTED_SPHERICAL_SET;
97 #endif
98 continue;
99 default:
100 assert(SL_BOOLEAN_FALSE);
101 break;
102 }
103 break;
104 }
105 interface_unlock_exclusive(thiz);
106 result = SL_RESULT_SUCCESS;
107 }
108
109 SL_LEAVE_INTERFACE
110 }
111
112
I3DLocation_GetLocationCartesian(SL3DLocationItf self,SLVec3D * pLocation)113 static SLresult I3DLocation_GetLocationCartesian(SL3DLocationItf self, SLVec3D *pLocation)
114 {
115 SL_ENTER_INTERFACE
116
117 if (NULL == pLocation) {
118 result = SL_RESULT_PARAMETER_INVALID;
119 } else {
120 I3DLocation *thiz = (I3DLocation *) self;
121 interface_lock_exclusive(thiz);
122 for (;;) {
123 enum CartesianSphericalActive locationActive = thiz->mLocationActive;
124 switch (locationActive) {
125 case CARTESIAN_COMPUTED_SPHERICAL_SET:
126 case CARTESIAN_SET_SPHERICAL_COMPUTED: // not in 1.0.1
127 case CARTESIAN_SET_SPHERICAL_REQUESTED: // not in 1.0.1
128 case CARTESIAN_SET_SPHERICAL_UNKNOWN:
129 {
130 SLVec3D locationCartesian = thiz->mLocationCartesian;
131 interface_unlock_exclusive(thiz);
132 *pLocation = locationCartesian;
133 }
134 break;
135 case CARTESIAN_UNKNOWN_SPHERICAL_SET:
136 thiz->mLocationActive = CARTESIAN_REQUESTED_SPHERICAL_SET;
137 FALLTHROUGH_INTENDED;
138 case CARTESIAN_REQUESTED_SPHERICAL_SET:
139 // matched by cond_broadcast in case multiple requesters
140 #if 0
141 interface_cond_wait(thiz);
142 #else
143 thiz->mLocationActive = CARTESIAN_COMPUTED_SPHERICAL_SET;
144 #endif
145 continue;
146 default:
147 assert(SL_BOOLEAN_FALSE);
148 interface_unlock_exclusive(thiz);
149 pLocation->x = 0;
150 pLocation->y = 0;
151 pLocation->z = 0;
152 break;
153 }
154 break;
155 }
156 result = SL_RESULT_SUCCESS;
157 }
158
159 SL_LEAVE_INTERFACE
160 }
161
162
I3DLocation_SetOrientationVectors(SL3DLocationItf self,const SLVec3D * pFront,const SLVec3D * pAbove)163 static SLresult I3DLocation_SetOrientationVectors(SL3DLocationItf self,
164 const SLVec3D *pFront, const SLVec3D *pAbove)
165 {
166 SL_ENTER_INTERFACE
167
168 if (NULL == pFront || NULL == pAbove) {
169 result = SL_RESULT_PARAMETER_INVALID;
170 } else {
171 SLVec3D front = *pFront;
172 SLVec3D above = *pAbove;
173 // NTH Check for vectors close to zero or close to parallel
174 I3DLocation *thiz = (I3DLocation *) self;
175 interface_lock_exclusive(thiz);
176 thiz->mOrientationVectors.mFront = front;
177 thiz->mOrientationVectors.mAbove = above;
178 thiz->mOrientationActive = ANGLES_UNKNOWN_VECTORS_SET;
179 thiz->mRotatePending = SL_BOOLEAN_FALSE;
180 interface_unlock_exclusive(thiz);
181 result = SL_RESULT_SUCCESS;
182 }
183
184 SL_LEAVE_INTERFACE
185 }
186
187
I3DLocation_SetOrientationAngles(SL3DLocationItf self,SLmillidegree heading,SLmillidegree pitch,SLmillidegree roll)188 static SLresult I3DLocation_SetOrientationAngles(SL3DLocationItf self,
189 SLmillidegree heading, SLmillidegree pitch, SLmillidegree roll)
190 {
191 SL_ENTER_INTERFACE
192
193 if (!((-360000 <= heading) && (heading <= 360000) &&
194 (-90000 <= pitch) && (pitch <= 90000) &&
195 (-360000 <= roll) && (roll <= 360000))) {
196 result = SL_RESULT_PARAMETER_INVALID;
197 } else {
198 I3DLocation *thiz = (I3DLocation *) self;
199 interface_lock_exclusive(thiz);
200 thiz->mOrientationAngles.mHeading = heading;
201 thiz->mOrientationAngles.mPitch = pitch;
202 thiz->mOrientationAngles.mRoll = roll;
203 thiz->mOrientationActive = ANGLES_SET_VECTORS_UNKNOWN;
204 thiz->mRotatePending = SL_BOOLEAN_FALSE;
205 interface_unlock_exclusive(thiz);
206 result = SL_RESULT_SUCCESS;
207 }
208
209 SL_LEAVE_INTERFACE
210 }
211
212
I3DLocation_Rotate(SL3DLocationItf self,SLmillidegree theta,const SLVec3D * pAxis)213 static SLresult I3DLocation_Rotate(SL3DLocationItf self, SLmillidegree theta, const SLVec3D *pAxis)
214 {
215 SL_ENTER_INTERFACE
216
217 if (!((-360000 <= theta) && (theta <= 360000)) || (NULL == pAxis)) {
218 result = SL_RESULT_PARAMETER_INVALID;
219 } else {
220 SLVec3D axis = *pAxis;
221 // NTH Check that axis is not (close to) zero vector, length does not matter
222 I3DLocation *thiz = (I3DLocation *) self;
223 interface_lock_exclusive(thiz);
224 while (thiz->mRotatePending)
225 #if 0
226 interface_cond_wait(thiz);
227 #else
228 break;
229 #endif
230 thiz->mTheta = theta;
231 thiz->mAxis = axis;
232 thiz->mRotatePending = SL_BOOLEAN_TRUE;
233 interface_unlock_exclusive(thiz);
234 result = SL_RESULT_SUCCESS;
235 }
236
237 SL_LEAVE_INTERFACE
238 }
239
240
I3DLocation_GetOrientationVectors(SL3DLocationItf self,SLVec3D * pFront,SLVec3D * pUp)241 static SLresult I3DLocation_GetOrientationVectors(SL3DLocationItf self,
242 SLVec3D *pFront, SLVec3D *pUp)
243 {
244 SL_ENTER_INTERFACE
245
246 if (NULL == pFront || NULL == pUp) {
247 result = SL_RESULT_PARAMETER_INVALID;
248 } else {
249 I3DLocation *thiz = (I3DLocation *) self;
250 interface_lock_shared(thiz);
251 SLVec3D front = thiz->mOrientationVectors.mFront;
252 SLVec3D up = thiz->mOrientationVectors.mUp;
253 interface_unlock_shared(thiz);
254 *pFront = front;
255 *pUp = up;
256 result = SL_RESULT_SUCCESS;
257 }
258
259 SL_LEAVE_INTERFACE
260 }
261
262
263 static const struct SL3DLocationItf_ I3DLocation_Itf = {
264 I3DLocation_SetLocationCartesian,
265 I3DLocation_SetLocationSpherical,
266 I3DLocation_Move,
267 I3DLocation_GetLocationCartesian,
268 I3DLocation_SetOrientationVectors,
269 I3DLocation_SetOrientationAngles,
270 I3DLocation_Rotate,
271 I3DLocation_GetOrientationVectors
272 };
273
I3DLocation_init(void * self)274 void I3DLocation_init(void *self)
275 {
276 I3DLocation *thiz = (I3DLocation *) self;
277 thiz->mItf = &I3DLocation_Itf;
278 thiz->mLocationCartesian.x = 0;
279 thiz->mLocationCartesian.y = 0;
280 thiz->mLocationCartesian.z = 0;
281 memset(&thiz->mLocationSpherical, 0x55, sizeof(thiz->mLocationSpherical));
282 thiz->mLocationActive = CARTESIAN_SET_SPHERICAL_UNKNOWN;
283 thiz->mOrientationAngles.mHeading = 0;
284 thiz->mOrientationAngles.mPitch = 0;
285 thiz->mOrientationAngles.mRoll = 0;
286 memset(&thiz->mOrientationVectors, 0x55, sizeof(thiz->mOrientationVectors));
287 thiz->mOrientationActive = ANGLES_SET_VECTORS_UNKNOWN;
288 thiz->mTheta = 0x55555555;
289 thiz->mAxis.x = 0x55555555;
290 thiz->mAxis.y = 0x55555555;
291 thiz->mAxis.z = 0x55555555;
292 thiz->mRotatePending = SL_BOOLEAN_FALSE;
293 }
294