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 22static 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 *this = (I3DLocation *) self; 30 SLVec3D locationCartesian = *pLocation; 31 interface_lock_exclusive(this); 32 this->mLocationCartesian = locationCartesian; 33 this->mLocationActive = CARTESIAN_SET_SPHERICAL_UNKNOWN; 34 interface_unlock_exclusive(this); 35 result = SL_RESULT_SUCCESS; 36 } 37 38 SL_LEAVE_INTERFACE 39} 40 41 42static 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 *this = (I3DLocation *) self; 53 interface_lock_exclusive(this); 54 this->mLocationSpherical.mAzimuth = azimuth; 55 this->mLocationSpherical.mElevation = elevation; 56 this->mLocationSpherical.mDistance = distance; 57 this->mLocationActive = CARTESIAN_UNKNOWN_SPHERICAL_SET; 58 interface_unlock_exclusive(this); 59 result = SL_RESULT_SUCCESS; 60 } 61 62 SL_LEAVE_INTERFACE 63} 64 65 66static 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 *this = (I3DLocation *) self; 74 SLVec3D movementCartesian = *pMovement; 75 interface_lock_exclusive(this); 76 for (;;) { 77 enum CartesianSphericalActive locationActive = this->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 this->mLocationCartesian.x += movementCartesian.x; 84 this->mLocationCartesian.y += movementCartesian.y; 85 this->mLocationCartesian.z += movementCartesian.z; 86 this->mLocationActive = CARTESIAN_SET_SPHERICAL_UNKNOWN; 87 break; 88 case CARTESIAN_UNKNOWN_SPHERICAL_SET: 89 this->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(this); 95#else 96 this->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(this); 106 result = SL_RESULT_SUCCESS; 107 } 108 109 SL_LEAVE_INTERFACE 110} 111 112 113static 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 *this = (I3DLocation *) self; 121 interface_lock_exclusive(this); 122 for (;;) { 123 enum CartesianSphericalActive locationActive = this->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 = this->mLocationCartesian; 131 interface_unlock_exclusive(this); 132 *pLocation = locationCartesian; 133 } 134 break; 135 case CARTESIAN_UNKNOWN_SPHERICAL_SET: 136 this->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(this); 142#else 143 this->mLocationActive = CARTESIAN_COMPUTED_SPHERICAL_SET; 144#endif 145 continue; 146 default: 147 assert(SL_BOOLEAN_FALSE); 148 interface_unlock_exclusive(this); 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 163static 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 *this = (I3DLocation *) self; 175 interface_lock_exclusive(this); 176 this->mOrientationVectors.mFront = front; 177 this->mOrientationVectors.mAbove = above; 178 this->mOrientationActive = ANGLES_UNKNOWN_VECTORS_SET; 179 this->mRotatePending = SL_BOOLEAN_FALSE; 180 interface_unlock_exclusive(this); 181 result = SL_RESULT_SUCCESS; 182 } 183 184 SL_LEAVE_INTERFACE 185} 186 187 188static 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 *this = (I3DLocation *) self; 199 interface_lock_exclusive(this); 200 this->mOrientationAngles.mHeading = heading; 201 this->mOrientationAngles.mPitch = pitch; 202 this->mOrientationAngles.mRoll = roll; 203 this->mOrientationActive = ANGLES_SET_VECTORS_UNKNOWN; 204 this->mRotatePending = SL_BOOLEAN_FALSE; 205 interface_unlock_exclusive(this); 206 result = SL_RESULT_SUCCESS; 207 } 208 209 SL_LEAVE_INTERFACE 210} 211 212 213static 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 *this = (I3DLocation *) self; 223 interface_lock_exclusive(this); 224 while (this->mRotatePending) 225#if 0 226 interface_cond_wait(this); 227#else 228 break; 229#endif 230 this->mTheta = theta; 231 this->mAxis = axis; 232 this->mRotatePending = SL_BOOLEAN_TRUE; 233 interface_unlock_exclusive(this); 234 result = SL_RESULT_SUCCESS; 235 } 236 237 SL_LEAVE_INTERFACE 238} 239 240 241static 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 *this = (I3DLocation *) self; 250 interface_lock_shared(this); 251 SLVec3D front = this->mOrientationVectors.mFront; 252 SLVec3D up = this->mOrientationVectors.mUp; 253 interface_unlock_shared(this); 254 *pFront = front; 255 *pUp = up; 256 result = SL_RESULT_SUCCESS; 257 } 258 259 SL_LEAVE_INTERFACE 260} 261 262 263static 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 274void I3DLocation_init(void *self) 275{ 276 I3DLocation *this = (I3DLocation *) self; 277 this->mItf = &I3DLocation_Itf; 278 this->mLocationCartesian.x = 0; 279 this->mLocationCartesian.y = 0; 280 this->mLocationCartesian.z = 0; 281 memset(&this->mLocationSpherical, 0x55, sizeof(this->mLocationSpherical)); 282 this->mLocationActive = CARTESIAN_SET_SPHERICAL_UNKNOWN; 283 this->mOrientationAngles.mHeading = 0; 284 this->mOrientationAngles.mPitch = 0; 285 this->mOrientationAngles.mRoll = 0; 286 memset(&this->mOrientationVectors, 0x55, sizeof(this->mOrientationVectors)); 287 this->mOrientationActive = ANGLES_SET_VECTORS_UNKNOWN; 288 this->mTheta = 0x55555555; 289 this->mAxis.x = 0x55555555; 290 this->mAxis.y = 0x55555555; 291 this->mAxis.z = 0x55555555; 292 this->mRotatePending = SL_BOOLEAN_FALSE; 293} 294