182b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten/*
282b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten * Copyright (C) 2010 The Android Open Source Project
382b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten *
482b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten * Licensed under the Apache License, Version 2.0 (the "License");
582b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten * you may not use this file except in compliance with the License.
682b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten * You may obtain a copy of the License at
782b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten *
882b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten *      http://www.apache.org/licenses/LICENSE-2.0
982b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten *
1082b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten * Unless required by applicable law or agreed to in writing, software
1182b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten * distributed under the License is distributed on an "AS IS" BASIS,
1282b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1382b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten * See the License for the specific language governing permissions and
1482b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten * limitations under the License.
1582b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten */
1682b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten
1782b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten/* 3DLocation implementation */
1882b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten
1982b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten#include "sles_allinclusive.h"
2082b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten
21f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten
22437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kastenstatic SLresult I3DLocation_SetLocationCartesian(SL3DLocationItf self, const SLVec3D *pLocation)
2382b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten{
24f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten    SL_ENTER_INTERFACE
25f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten
26f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten    if (NULL == pLocation) {
27f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten        result = SL_RESULT_PARAMETER_INVALID;
28f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten    } else {
2950bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten        I3DLocation *thiz = (I3DLocation *) self;
30f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten        SLVec3D locationCartesian = *pLocation;
3150bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten        interface_lock_exclusive(thiz);
3250bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten        thiz->mLocationCartesian = locationCartesian;
3350bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten        thiz->mLocationActive = CARTESIAN_SET_SPHERICAL_UNKNOWN;
3450bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten        interface_unlock_exclusive(thiz);
35f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten        result = SL_RESULT_SUCCESS;
36f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten    }
37f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten
38f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten    SL_LEAVE_INTERFACE
3982b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten}
4082b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten
41f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten
4282b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kastenstatic SLresult I3DLocation_SetLocationSpherical(SL3DLocationItf self,
4382b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten    SLmillidegree azimuth, SLmillidegree elevation, SLmillimeter distance)
4482b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten{
45f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten    SL_ENTER_INTERFACE
46f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten
47437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kasten    if (!((-360000 <= azimuth) && (azimuth <= 360000) &&
48437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kasten        (-90000 <= elevation) && (elevation <= 90000) &&
49f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten        (0 <= distance) && (distance <= SL_MILLIMETER_MAX))) {
50f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten        result = SL_RESULT_PARAMETER_INVALID;
51f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten    } else {
5250bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten        I3DLocation *thiz = (I3DLocation *) self;
5350bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten        interface_lock_exclusive(thiz);
5450bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten        thiz->mLocationSpherical.mAzimuth = azimuth;
5550bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten        thiz->mLocationSpherical.mElevation = elevation;
5650bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten        thiz->mLocationSpherical.mDistance = distance;
5750bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten        thiz->mLocationActive = CARTESIAN_UNKNOWN_SPHERICAL_SET;
5850bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten        interface_unlock_exclusive(thiz);
59f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten        result = SL_RESULT_SUCCESS;
60f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten    }
61f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten
62f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten    SL_LEAVE_INTERFACE
6382b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten}
6482b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten
65f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten
6682b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kastenstatic SLresult I3DLocation_Move(SL3DLocationItf self, const SLVec3D *pMovement)
6782b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten{
68f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten    SL_ENTER_INTERFACE
69f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten
70f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten    if (NULL == pMovement) {
71f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten        result = SL_RESULT_PARAMETER_INVALID;
72f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten    } else {
7350bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten        I3DLocation *thiz = (I3DLocation *) self;
74f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten        SLVec3D movementCartesian = *pMovement;
7550bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten        interface_lock_exclusive(thiz);
76f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten        for (;;) {
7750bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten            enum CartesianSphericalActive locationActive = thiz->mLocationActive;
78f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten            switch (locationActive) {
79f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten            case CARTESIAN_COMPUTED_SPHERICAL_SET:
80f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten            case CARTESIAN_SET_SPHERICAL_COMPUTED:  // not in 1.0.1
81f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten            case CARTESIAN_SET_SPHERICAL_REQUESTED: // not in 1.0.1
82f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten            case CARTESIAN_SET_SPHERICAL_UNKNOWN:
8350bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten                thiz->mLocationCartesian.x += movementCartesian.x;
8450bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten                thiz->mLocationCartesian.y += movementCartesian.y;
8550bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten                thiz->mLocationCartesian.z += movementCartesian.z;
8650bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten                thiz->mLocationActive = CARTESIAN_SET_SPHERICAL_UNKNOWN;
87f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten                break;
88f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten            case CARTESIAN_UNKNOWN_SPHERICAL_SET:
8950bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten                thiz->mLocationActive = CARTESIAN_REQUESTED_SPHERICAL_SET;
90f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten                // fall through
91f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten            case CARTESIAN_REQUESTED_SPHERICAL_SET:
92f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten                // matched by cond_broadcast in case multiple requesters
93f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten#if 0
9450bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten                interface_cond_wait(thiz);
95f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten#else
9650bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten                thiz->mLocationActive = CARTESIAN_COMPUTED_SPHERICAL_SET;
97f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten#endif
98f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten                continue;
99f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten            default:
100f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten                assert(SL_BOOLEAN_FALSE);
101f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten                break;
102f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten            }
10382b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten            break;
10482b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten        }
10550bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten        interface_unlock_exclusive(thiz);
106f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten        result = SL_RESULT_SUCCESS;
10782b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten    }
108f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten
109f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten    SL_LEAVE_INTERFACE
11082b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten}
11182b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten
112f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten
113437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kastenstatic SLresult I3DLocation_GetLocationCartesian(SL3DLocationItf self, SLVec3D *pLocation)
11482b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten{
115f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten    SL_ENTER_INTERFACE
116f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten
117f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten    if (NULL == pLocation) {
118f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten        result = SL_RESULT_PARAMETER_INVALID;
119f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten    } else {
12050bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten        I3DLocation *thiz = (I3DLocation *) self;
12150bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten        interface_lock_exclusive(thiz);
122f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten        for (;;) {
12350bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten            enum CartesianSphericalActive locationActive = thiz->mLocationActive;
124f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten            switch (locationActive) {
125f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten            case CARTESIAN_COMPUTED_SPHERICAL_SET:
126f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten            case CARTESIAN_SET_SPHERICAL_COMPUTED:  // not in 1.0.1
127f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten            case CARTESIAN_SET_SPHERICAL_REQUESTED: // not in 1.0.1
128f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten            case CARTESIAN_SET_SPHERICAL_UNKNOWN:
129f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten                {
13050bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten                SLVec3D locationCartesian = thiz->mLocationCartesian;
13150bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten                interface_unlock_exclusive(thiz);
132f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten                *pLocation = locationCartesian;
133f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten                }
134f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten                break;
135f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten            case CARTESIAN_UNKNOWN_SPHERICAL_SET:
13650bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten                thiz->mLocationActive = CARTESIAN_REQUESTED_SPHERICAL_SET;
137f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten                // fall through
138f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten            case CARTESIAN_REQUESTED_SPHERICAL_SET:
139f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten                // matched by cond_broadcast in case multiple requesters
140f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten#if 0
14150bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten                interface_cond_wait(thiz);
142f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten#else
14350bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten                thiz->mLocationActive = CARTESIAN_COMPUTED_SPHERICAL_SET;
144f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten#endif
145f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten                continue;
146f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten            default:
147f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten                assert(SL_BOOLEAN_FALSE);
14850bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten                interface_unlock_exclusive(thiz);
149f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten                pLocation->x = 0;
150f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten                pLocation->y = 0;
151f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten                pLocation->z = 0;
152f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten                break;
15382b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten            }
15482b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten            break;
15582b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten        }
156f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten        result = SL_RESULT_SUCCESS;
15782b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten    }
158f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten
159f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten    SL_LEAVE_INTERFACE
16082b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten}
16182b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten
162f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten
16382b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kastenstatic SLresult I3DLocation_SetOrientationVectors(SL3DLocationItf self,
16482b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten    const SLVec3D *pFront, const SLVec3D *pAbove)
16582b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten{
166f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten    SL_ENTER_INTERFACE
167f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten
168f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten    if (NULL == pFront || NULL == pAbove) {
169f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten        result = SL_RESULT_PARAMETER_INVALID;
170f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten    } else {
171f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten        SLVec3D front = *pFront;
172f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten        SLVec3D above = *pAbove;
173f51f5c6ec99ebc8f2c833a68f232bc1c874a7f2fGlenn Kasten        // NTH Check for vectors close to zero or close to parallel
17450bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten        I3DLocation *thiz = (I3DLocation *) self;
17550bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten        interface_lock_exclusive(thiz);
17650bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten        thiz->mOrientationVectors.mFront = front;
17750bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten        thiz->mOrientationVectors.mAbove = above;
17850bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten        thiz->mOrientationActive = ANGLES_UNKNOWN_VECTORS_SET;
17950bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten        thiz->mRotatePending = SL_BOOLEAN_FALSE;
18050bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten        interface_unlock_exclusive(thiz);
181f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten        result = SL_RESULT_SUCCESS;
182f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten    }
183f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten
184f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten    SL_LEAVE_INTERFACE
18582b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten}
18682b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten
187f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten
18882b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kastenstatic SLresult I3DLocation_SetOrientationAngles(SL3DLocationItf self,
18982b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten    SLmillidegree heading, SLmillidegree pitch, SLmillidegree roll)
19082b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten{
191f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten    SL_ENTER_INTERFACE
192f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten
193437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kasten    if (!((-360000 <= heading) && (heading <= 360000) &&
194437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kasten        (-90000 <= pitch) && (pitch <= 90000) &&
195f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten        (-360000 <= roll) && (roll <= 360000))) {
196f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten        result = SL_RESULT_PARAMETER_INVALID;
197f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten    } else {
19850bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten        I3DLocation *thiz = (I3DLocation *) self;
19950bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten        interface_lock_exclusive(thiz);
20050bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten        thiz->mOrientationAngles.mHeading = heading;
20150bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten        thiz->mOrientationAngles.mPitch = pitch;
20250bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten        thiz->mOrientationAngles.mRoll = roll;
20350bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten        thiz->mOrientationActive = ANGLES_SET_VECTORS_UNKNOWN;
20450bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten        thiz->mRotatePending = SL_BOOLEAN_FALSE;
20550bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten        interface_unlock_exclusive(thiz);
206f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten        result = SL_RESULT_SUCCESS;
207f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten    }
208f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten
209f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten    SL_LEAVE_INTERFACE
21082b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten}
21182b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten
212f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten
213437f9ab9914ea61112aa496a047162a0d22194cdGlenn Kastenstatic SLresult I3DLocation_Rotate(SL3DLocationItf self, SLmillidegree theta, const SLVec3D *pAxis)
21482b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten{
215f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten    SL_ENTER_INTERFACE
216f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten
217f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten    if (!((-360000 <= theta) && (theta <= 360000)) || (NULL == pAxis)) {
218f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten        result = SL_RESULT_PARAMETER_INVALID;
219f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten    } else {
220f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten        SLVec3D axis = *pAxis;
221f51f5c6ec99ebc8f2c833a68f232bc1c874a7f2fGlenn Kasten        // NTH Check that axis is not (close to) zero vector, length does not matter
22250bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten        I3DLocation *thiz = (I3DLocation *) self;
22350bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten        interface_lock_exclusive(thiz);
22450bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten        while (thiz->mRotatePending)
225f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten#if 0
22650bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten            interface_cond_wait(thiz);
227f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten#else
228f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten            break;
229f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten#endif
23050bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten        thiz->mTheta = theta;
23150bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten        thiz->mAxis = axis;
23250bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten        thiz->mRotatePending = SL_BOOLEAN_TRUE;
23350bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten        interface_unlock_exclusive(thiz);
234f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten        result = SL_RESULT_SUCCESS;
235f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten    }
236f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten
237f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten    SL_LEAVE_INTERFACE
23882b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten}
23982b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten
240f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten
24182b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kastenstatic SLresult I3DLocation_GetOrientationVectors(SL3DLocationItf self,
24282b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten    SLVec3D *pFront, SLVec3D *pUp)
24382b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten{
244f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten    SL_ENTER_INTERFACE
245f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten
246f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten    if (NULL == pFront || NULL == pUp) {
247f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten        result = SL_RESULT_PARAMETER_INVALID;
248f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten    } else {
24950bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten        I3DLocation *thiz = (I3DLocation *) self;
25050bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten        interface_lock_shared(thiz);
25150bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten        SLVec3D front = thiz->mOrientationVectors.mFront;
25250bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten        SLVec3D up = thiz->mOrientationVectors.mUp;
25350bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten        interface_unlock_shared(thiz);
254f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten        *pFront = front;
255f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten        *pUp = up;
256f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten        result = SL_RESULT_SUCCESS;
257f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten    }
258f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten
259f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten    SL_LEAVE_INTERFACE
26082b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten}
26182b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten
262f156301680273e71e56e898f98798f5b5b2431f6Glenn Kasten
26382b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kastenstatic const struct SL3DLocationItf_ I3DLocation_Itf = {
26482b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten    I3DLocation_SetLocationCartesian,
26582b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten    I3DLocation_SetLocationSpherical,
26682b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten    I3DLocation_Move,
26782b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten    I3DLocation_GetLocationCartesian,
26882b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten    I3DLocation_SetOrientationVectors,
26982b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten    I3DLocation_SetOrientationAngles,
27082b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten    I3DLocation_Rotate,
27182b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten    I3DLocation_GetOrientationVectors
27282b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten};
27382b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten
27482b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kastenvoid I3DLocation_init(void *self)
27582b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten{
27650bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten    I3DLocation *thiz = (I3DLocation *) self;
27750bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten    thiz->mItf = &I3DLocation_Itf;
27850bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten    thiz->mLocationCartesian.x = 0;
27950bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten    thiz->mLocationCartesian.y = 0;
28050bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten    thiz->mLocationCartesian.z = 0;
28150bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten    memset(&thiz->mLocationSpherical, 0x55, sizeof(thiz->mLocationSpherical));
28250bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten    thiz->mLocationActive = CARTESIAN_SET_SPHERICAL_UNKNOWN;
28350bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten    thiz->mOrientationAngles.mHeading = 0;
28450bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten    thiz->mOrientationAngles.mPitch = 0;
28550bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten    thiz->mOrientationAngles.mRoll = 0;
28650bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten    memset(&thiz->mOrientationVectors, 0x55, sizeof(thiz->mOrientationVectors));
28750bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten    thiz->mOrientationActive = ANGLES_SET_VECTORS_UNKNOWN;
28850bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten    thiz->mTheta = 0x55555555;
28950bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten    thiz->mAxis.x = 0x55555555;
29050bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten    thiz->mAxis.y = 0x55555555;
29150bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten    thiz->mAxis.z = 0x55555555;
29250bccde01980ae803b8656e8b08ecacb65540f50Glenn Kasten    thiz->mRotatePending = SL_BOOLEAN_FALSE;
29382b1fcaca1b9c870c1a7978f0986fdad2fe7d06eGlenn Kasten}
294