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 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 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 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 // fall through 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 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 // fall through 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 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 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 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 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 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