/* * Copyright (C) 2010 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* 3DGrouping implementation */ #include "sles_allinclusive.h" static SLresult I3DGrouping_Set3DGroup(SL3DGroupingItf self, SLObjectItf group) { SL_ENTER_INTERFACE // validate input parameters C3DGroup *newGroup = (C3DGroup *) group; result = SL_RESULT_SUCCESS; if (NULL != newGroup) { // check that new group has the correct object ID and is realized, and acquire a strong // reference to it. FYI note that a deadlock will occur if application incorrectly // specifies group as this audio player result = AcquireStrongRef(&newGroup->mObject, SL_OBJECTID_3DGROUP); // the new group is left unlocked, but it will be locked again below } if (SL_RESULT_SUCCESS == result) { I3DGrouping *this = (I3DGrouping *) self; IObject *thisObject = InterfaceToIObject(this); unsigned id = thisObject->mInstanceID; assert(0 != id); // player object must be published by this point --id; assert(MAX_INSTANCE > id); unsigned mask = 1 << id; interface_lock_exclusive(this); C3DGroup *oldGroup = this->mGroup; if (newGroup != oldGroup) { // remove this object from the old group's set of objects if (NULL != oldGroup) { IObject *oldGroupObject = &oldGroup->mObject; // note that we already have a strong reference to the old group object_lock_exclusive(oldGroupObject); assert(oldGroup->mMemberMask & mask); oldGroup->mMemberMask &= ~mask; ReleaseStrongRefAndUnlockExclusive(oldGroupObject); } // add this object to the new group's set of objects if (NULL != newGroup) { IObject *newGroupObject = &newGroup->mObject; // we already have a strong reference to the new group, but we need to re-lock it // so that we always lock objects in the same nesting order to prevent a deadlock object_lock_exclusive(newGroupObject); assert(!(newGroup->mMemberMask & mask)); newGroup->mMemberMask |= mask; object_unlock_exclusive(newGroupObject); } this->mGroup = newGroup; } interface_unlock_exclusive(this); } SL_LEAVE_INTERFACE } static SLresult I3DGrouping_Get3DGroup(SL3DGroupingItf self, SLObjectItf *pGroup) { SL_ENTER_INTERFACE if (NULL == pGroup) { result = SL_RESULT_PARAMETER_INVALID; } else { I3DGrouping *this = (I3DGrouping *) self; interface_lock_shared(this); C3DGroup *group = this->mGroup; *pGroup = (NULL != group) ? &group->mObject.mItf : NULL; interface_unlock_shared(this); result = SL_RESULT_SUCCESS; } SL_LEAVE_INTERFACE } static const struct SL3DGroupingItf_ I3DGrouping_Itf = { I3DGrouping_Set3DGroup, I3DGrouping_Get3DGroup }; void I3DGrouping_init(void *self) { I3DGrouping *this = (I3DGrouping *) self; this->mItf = &I3DGrouping_Itf; this->mGroup = NULL; } void I3DGrouping_deinit(void *self) { I3DGrouping *this = (I3DGrouping *) self; C3DGroup *group = this->mGroup; if (NULL != group) { unsigned mask = 1 << (InterfaceToIObject(this)->mInstanceID - 1); IObject *groupObject = &group->mObject; object_lock_exclusive(groupObject); assert(group->mMemberMask & mask); group->mMemberMask &= ~mask; ReleaseStrongRefAndUnlockExclusive(groupObject); } }