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 /* 3DGrouping implementation */ 18 19 #include "sles_allinclusive.h" 20 21 22 static SLresult I3DGrouping_Set3DGroup(SL3DGroupingItf self, SLObjectItf group) 23 { 24 SL_ENTER_INTERFACE 25 26 // validate input parameters 27 C3DGroup *newGroup = (C3DGroup *) group; 28 result = SL_RESULT_SUCCESS; 29 if (NULL != newGroup) { 30 // check that new group has the correct object ID and is realized, and acquire a strong 31 // reference to it. FYI note that a deadlock will occur if application incorrectly 32 // specifies group as this audio player 33 result = AcquireStrongRef(&newGroup->mObject, SL_OBJECTID_3DGROUP); 34 // the new group is left unlocked, but it will be locked again below 35 } 36 if (SL_RESULT_SUCCESS == result) { 37 I3DGrouping *thiz = (I3DGrouping *) self; 38 IObject *thisObject = InterfaceToIObject(thiz); 39 unsigned id = thisObject->mInstanceID; 40 assert(0 != id); // player object must be published by this point 41 --id; 42 assert(MAX_INSTANCE > id); 43 unsigned mask = 1 << id; 44 interface_lock_exclusive(thiz); 45 C3DGroup *oldGroup = thiz->mGroup; 46 if (newGroup != oldGroup) { 47 // remove this object from the old group's set of objects 48 if (NULL != oldGroup) { 49 IObject *oldGroupObject = &oldGroup->mObject; 50 // note that we already have a strong reference to the old group 51 object_lock_exclusive(oldGroupObject); 52 assert(oldGroup->mMemberMask & mask); 53 oldGroup->mMemberMask &= ~mask; 54 ReleaseStrongRefAndUnlockExclusive(oldGroupObject); 55 } 56 // add this object to the new group's set of objects 57 if (NULL != newGroup) { 58 IObject *newGroupObject = &newGroup->mObject; 59 // we already have a strong reference to the new group, but we need to re-lock it 60 // so that we always lock objects in the same nesting order to prevent a deadlock 61 object_lock_exclusive(newGroupObject); 62 assert(!(newGroup->mMemberMask & mask)); 63 newGroup->mMemberMask |= mask; 64 object_unlock_exclusive(newGroupObject); 65 } 66 thiz->mGroup = newGroup; 67 } 68 interface_unlock_exclusive(thiz); 69 } 70 71 SL_LEAVE_INTERFACE 72 } 73 74 75 static SLresult I3DGrouping_Get3DGroup(SL3DGroupingItf self, SLObjectItf *pGroup) 76 { 77 SL_ENTER_INTERFACE 78 79 if (NULL == pGroup) { 80 result = SL_RESULT_PARAMETER_INVALID; 81 } else { 82 I3DGrouping *thiz = (I3DGrouping *) self; 83 interface_lock_shared(thiz); 84 C3DGroup *group = thiz->mGroup; 85 *pGroup = (NULL != group) ? &group->mObject.mItf : NULL; 86 interface_unlock_shared(thiz); 87 result = SL_RESULT_SUCCESS; 88 } 89 90 SL_LEAVE_INTERFACE 91 } 92 93 94 static const struct SL3DGroupingItf_ I3DGrouping_Itf = { 95 I3DGrouping_Set3DGroup, 96 I3DGrouping_Get3DGroup 97 }; 98 99 void I3DGrouping_init(void *self) 100 { 101 I3DGrouping *thiz = (I3DGrouping *) self; 102 thiz->mItf = &I3DGrouping_Itf; 103 thiz->mGroup = NULL; 104 } 105 106 void I3DGrouping_deinit(void *self) 107 { 108 I3DGrouping *thiz = (I3DGrouping *) self; 109 C3DGroup *group = thiz->mGroup; 110 if (NULL != group) { 111 unsigned mask = 1 << (InterfaceToIObject(thiz)->mInstanceID - 1); 112 IObject *groupObject = &group->mObject; 113 object_lock_exclusive(groupObject); 114 assert(group->mMemberMask & mask); 115 group->mMemberMask &= ~mask; 116 ReleaseStrongRefAndUnlockExclusive(groupObject); 117 } 118 } 119