161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten/* 261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten * Copyright (C) 2010 The Android Open Source Project 361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten * 461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten * Licensed under the Apache License, Version 2.0 (the "License"); 561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten * you may not use this file except in compliance with the License. 661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten * You may obtain a copy of the License at 761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten * 861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten * http://www.apache.org/licenses/LICENSE-2.0 961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten * 1061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten * Unless required by applicable law or agreed to in writing, software 1161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten * distributed under the License is distributed on an "AS IS" BASIS, 1261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten * See the License for the specific language governing permissions and 1461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten * limitations under the License. 1561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten */ 1661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 1761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten/* DynamicInterfaceManagement implementation */ 1861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 1961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten#include "sles_allinclusive.h" 2061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 21ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 22510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten// Called by a worker thread to handle an asynchronous AddInterface. 23510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten// Parameter self is the DynamicInterface, and MPH specifies which interface to add. 24510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 25cf3a6383a9bc9a94ca5b424ea97313293ee0dcb0Glenn Kastenstatic void HandleAdd(void *self, void *ignored, int MPH) 26510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten{ 27510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 28510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // validate input parameters 29bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten IDynamicInterfaceManagement *thiz = (IDynamicInterfaceManagement *) self; 30bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten assert(NULL != thiz); 31bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten IObject *thisObject = InterfaceToIObject(thiz); 32510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten assert(NULL != thisObject); 33510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten assert(0 <= MPH && MPH < MPH_MAX); 34bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten const ClassTable *clazz = thisObject->mClass; 35bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten assert(NULL != clazz); 36bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten int index = clazz->mMPH_to_index[MPH]; 37bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten assert(0 <= index && index < (int) clazz->mInterfaceCount); 38510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten SLuint8 *interfaceStateP = &thisObject->mInterfaceStates[index]; 39510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten SLresult result; 40510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 41510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // check interface state 42510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten object_lock_exclusive(thisObject); 43276cab2d983b892d1b634474b6249f6bec400c76Glenn Kasten SLuint8 state = *interfaceStateP; 44510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten switch (state) { 45510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 46510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_ADDING_1: // normal case 47510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten { 48510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // change state to indicate we are now adding the interface 49510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten *interfaceStateP = INTERFACE_ADDING_2; 50510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten object_unlock_exclusive(thisObject); 51510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 52510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // this section runs with mutex unlocked 53bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten const struct iid_vtable *x = &clazz->mInterfaces[index]; 54510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten size_t offset = x->mOffset; 55510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten void *thisItf = (char *) thisObject + offset; 56a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten BoolHook expose = MPH_init_table[MPH].mExpose; 57a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten // call the optional expose hook 58a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten if ((NULL == expose) || (*expose)(thisItf)) { 59a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten result = SL_RESULT_SUCCESS; 60a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten } else { 61a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten result = SL_RESULT_FEATURE_UNSUPPORTED; 62e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten } 63510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 64510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // re-lock mutex to update state 65510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten object_lock_exclusive(thisObject); 66510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten assert(INTERFACE_ADDING_2 == *interfaceStateP); 67a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten if (SL_RESULT_SUCCESS == result) { 68a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten ((size_t *) thisItf)[0] ^= ~0; 69a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten state = INTERFACE_ADDED; 70a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten } else { 71a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten state = INTERFACE_INITIALIZED; 72a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten } 73510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten } 74510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 75510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 76510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_ADDING_1A: // operation was aborted while on work queue 77510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten result = SL_RESULT_OPERATION_ABORTED; 78a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten state = INTERFACE_INITIALIZED; 79510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 80510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 81510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten default: // impossible 82510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten assert(SL_BOOLEAN_FALSE); 83510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten result = SL_RESULT_INTERNAL_ERROR; 84510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 85510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 86510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten } 87510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 88510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // mutex is locked, update state 89510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten *interfaceStateP = state; 90510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 91510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // Make a copy of these, so we can call the callback with mutex unlocked 92bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten slDynamicInterfaceManagementCallback callback = thiz->mCallback; 93bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten void *context = thiz->mContext; 94510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten object_unlock_exclusive(thisObject); 95510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 96510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // Note that the mutex is unlocked during the callback 97510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten if (NULL != callback) { 98510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten const SLInterfaceID iid = &SL_IID_array[MPH]; // equal but not == to the original IID 99bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten (*callback)(&thiz->mItf, context, SL_DYNAMIC_ITF_EVENT_ASYNC_TERMINATION, result, iid); 100510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten } 101510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 102510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten} 103510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 104ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 1053a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kastenstatic SLresult IDynamicInterfaceManagement_AddInterface(SLDynamicInterfaceManagementItf self, 1063a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten const SLInterfaceID iid, SLboolean async) 10761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{ 108ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_ENTER_INTERFACE 109ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 110510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // validate input parameters 111ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten if (NULL == iid) { 112ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_PARAMETER_INVALID; 113ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } else { 114bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten IDynamicInterfaceManagement *thiz = (IDynamicInterfaceManagement *) self; 115bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten IObject *thisObject = InterfaceToIObject(thiz); 116bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten const ClassTable *clazz = thisObject->mClass; 117ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten int MPH, index; 118a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten if ((0 > (MPH = IID_to_MPH(iid))) || 119a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten // no need to check for an initialization hook 120a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten // (NULL == MPH_init_table[MPH].mInit) || 121bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten (0 > (index = clazz->mMPH_to_index[MPH]))) { 122ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_FEATURE_UNSUPPORTED; 123ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } else { 124bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten assert(index < (int) clazz->mInterfaceCount); 125ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SLuint8 *interfaceStateP = &thisObject->mInterfaceStates[index]; 126510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 127ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten // check interface state 128ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten object_lock_exclusive(thisObject); 129ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten switch (*interfaceStateP) { 130ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 131a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten case INTERFACE_INITIALIZED: // normal case 132ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten if (async) { 133ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten // Asynchronous: mark operation pending and cancellable 134ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten *interfaceStateP = INTERFACE_ADDING_1; 135ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten object_unlock_exclusive(thisObject); 136ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 137ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten // this section runs with mutex unlocked 138cf3a6383a9bc9a94ca5b424ea97313293ee0dcb0Glenn Kasten result = ThreadPool_add_ppi(&thisObject->mEngine->mThreadPool, HandleAdd, thiz, 139cf3a6383a9bc9a94ca5b424ea97313293ee0dcb0Glenn Kasten NULL, MPH); 140ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten if (SL_RESULT_SUCCESS != result) { 141ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten // Engine was destroyed during add, or insufficient memory, 142ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten // so restore mInterfaceStates state to prior value 143ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten object_lock_exclusive(thisObject); 144ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten switch (*interfaceStateP) { 145ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten case INTERFACE_ADDING_1: // normal 146ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten case INTERFACE_ADDING_1A: // operation aborted while mutex unlocked 147a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten *interfaceStateP = INTERFACE_INITIALIZED; 148ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten break; 149ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten default: // unexpected 150ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten // leave state alone 151ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten break; 152ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } 153ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } 154ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 155ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } else { 156ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten // Synchronous: mark operation pending to prevent duplication 157ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten *interfaceStateP = INTERFACE_ADDING_2; 158ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten object_unlock_exclusive(thisObject); 159ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 160ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten // this section runs with mutex unlocked 161bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten const struct iid_vtable *x = &clazz->mInterfaces[index]; 162ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten size_t offset = x->mOffset; 163ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten void *thisItf = (char *) thisObject + offset; 164a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten // call the optional expose hook 165a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten BoolHook expose = MPH_init_table[MPH].mExpose; 166a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten if ((NULL == expose) || (*expose)(thisItf)) { 167a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten result = SL_RESULT_SUCCESS; 168a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten } else { 169a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten result = SL_RESULT_FEATURE_UNSUPPORTED; 170e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten } 171ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 172ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten // re-lock mutex to update state 173ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten object_lock_exclusive(thisObject); 174ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten assert(INTERFACE_ADDING_2 == *interfaceStateP); 175a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten if (SL_RESULT_SUCCESS == result) { 176a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten *interfaceStateP = INTERFACE_ADDED; 177a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten } else { 178a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten *interfaceStateP = INTERFACE_INITIALIZED; 179a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten } 180ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } 181510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 182ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten // mutex is still locked 183ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten break; 184ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 185ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten default: // disallow adding of (partially) initialized interfaces 186ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_PRECONDITIONS_VIOLATED; 187ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten break; 188510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 189510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten } 190510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 191510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten object_unlock_exclusive(thisObject); 192510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 19361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten } 19461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten } 195510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 196ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_LEAVE_INTERFACE 19761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten} 19861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 199ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 20061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenstatic SLresult IDynamicInterfaceManagement_RemoveInterface( 20161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten SLDynamicInterfaceManagementItf self, const SLInterfaceID iid) 20261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{ 203ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_ENTER_INTERFACE 204510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 205711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten#if USE_PROFILES & USE_PROFILES_BASE 206ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten // validate input parameters 207ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten if (NULL == iid) { 208ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_PARAMETER_INVALID; 209ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } else { 210bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten IDynamicInterfaceManagement *thiz = (IDynamicInterfaceManagement *) self; 211bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten IObject *thisObject = InterfaceToIObject(thiz); 212bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten const ClassTable *clazz = thisObject->mClass; 213ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten int MPH, index; 214a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten if ((0 > (MPH = IID_to_MPH(iid))) || 215a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten // no need to check for an initialization hook 216a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten // (NULL == MPH_init_table[MPH].mInit) || 217bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten (0 > (index = clazz->mMPH_to_index[MPH]))) { 218ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_PRECONDITIONS_VIOLATED; 219ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } else { 220ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SLuint8 *interfaceStateP = &thisObject->mInterfaceStates[index]; 221510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 222ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten // check interface state 223ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten object_lock_exclusive(thisObject); 224ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten switch (*interfaceStateP) { 225ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 226ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten case INTERFACE_ADDED: // normal cases 227ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten case INTERFACE_SUSPENDED: 228ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten { 229711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten // Compute address of the interface 230bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten const struct iid_vtable *x = &clazz->mInterfaces[index]; 231ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten size_t offset = x->mOffset; 232ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten void *thisItf = (char *) thisObject + offset; 233711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten 234711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten // Mark operation pending (not necessary; remove is synchronous with mutex locked) 235711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten *interfaceStateP = INTERFACE_REMOVING; 236711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten 237711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten // Check if application ever called Object::GetInterface 238711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten unsigned mask = 1 << index; 239711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten if (thisObject->mGottenMask & mask) { 240711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten thisObject->mGottenMask &= ~mask; 241711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten // This trickery invalidates the v-table 242711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten ((size_t *) thisItf)[0] ^= ~0; 243711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten } 244711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten 245711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten // The remove hook is called with mutex locked 246a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten VoidHook remove = MPH_init_table[MPH].mRemove; 247a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten if (NULL != remove) { 248a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten (*remove)(thisItf); 249a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten } 250ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_SUCCESS; 251ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 252ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten assert(INTERFACE_REMOVING == *interfaceStateP); 253a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten *interfaceStateP = INTERFACE_INITIALIZED; 254ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } 255510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 256ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten // mutex is still locked 257ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten break; 258510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 259ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten default: 260ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten // disallow removal of non-dynamic interfaces, or interfaces which are 261ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten // currently being resumed (will not auto-cancel an asynchronous resume) 262ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_PRECONDITIONS_VIOLATED; 263ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten break; 264510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 265ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } 266510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 267ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten object_unlock_exclusive(thisObject); 268ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } 26961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten } 270711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten#else 271711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten result = SL_RESULT_FEATURE_UNSUPPORTED; 272711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten#endif 273510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 274ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_LEAVE_INTERFACE 27561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten} 27661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 277ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 278510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten// Called by a worker thread to handle an asynchronous ResumeInterface. 279510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten// Parameter self is the DynamicInterface, and MPH specifies which interface to resume. 280510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 281cf3a6383a9bc9a94ca5b424ea97313293ee0dcb0Glenn Kastenstatic void HandleResume(void *self, void *ignored, int MPH) 282510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten{ 283510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 284510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // validate input parameters 285bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten IDynamicInterfaceManagement *thiz = (IDynamicInterfaceManagement *) self; 286bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten assert(NULL != thiz); 287bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten IObject *thisObject = InterfaceToIObject(thiz); 288510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten assert(NULL != thisObject); 289510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten assert(0 <= MPH && MPH < MPH_MAX); 290bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten const ClassTable *clazz = thisObject->mClass; 291bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten assert(NULL != clazz); 292bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten int index = clazz->mMPH_to_index[MPH]; 293bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten assert(0 <= index && index < (int) clazz->mInterfaceCount); 294510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten SLuint8 *interfaceStateP = &thisObject->mInterfaceStates[index]; 295510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten SLresult result; 296510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 297510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // check interface state 298510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten object_lock_exclusive(thisObject); 299276cab2d983b892d1b634474b6249f6bec400c76Glenn Kasten SLuint8 state = *interfaceStateP; 300510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten switch (state) { 301510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 302510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_RESUMING_1: // normal case 303510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten { 304510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // change state to indicate we are now resuming the interface 305510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten *interfaceStateP = INTERFACE_RESUMING_2; 306510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten object_unlock_exclusive(thisObject); 307510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 308510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // this section runs with mutex unlocked 309bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten const struct iid_vtable *x = &clazz->mInterfaces[index]; 310510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten size_t offset = x->mOffset; 311510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten void *thisItf = (char *) thisObject + offset; 312510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten VoidHook resume = MPH_init_table[MPH].mResume; 313a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten if (NULL != resume) { 314510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten (*resume)(thisItf); 315a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten } 316510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten result = SL_RESULT_SUCCESS; 317510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 318510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // re-lock mutex to update state 319510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten object_lock_exclusive(thisObject); 320510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten assert(INTERFACE_RESUMING_2 == *interfaceStateP); 321510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten state = INTERFACE_ADDED; 322510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten } 323510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 324510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 325510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_RESUMING_1A: // operation was aborted while on work queue 326510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten result = SL_RESULT_OPERATION_ABORTED; 327510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten state = INTERFACE_SUSPENDED; 328510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 329510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 330510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten default: // impossible 331510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten assert(SL_BOOLEAN_FALSE); 332510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten result = SL_RESULT_INTERNAL_ERROR; 333510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 334510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 335510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten } 336510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 337510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // mutex is locked, update state 338510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten *interfaceStateP = state; 339510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 340510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // Make a copy of these, so we can call the callback with mutex unlocked 341bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten slDynamicInterfaceManagementCallback callback = thiz->mCallback; 342bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten void *context = thiz->mContext; 343510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten object_unlock_exclusive(thisObject); 344510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 345510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // Note that the mutex is unlocked during the callback 346510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten if (NULL != callback) { 347510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten const SLInterfaceID iid = &SL_IID_array[MPH]; // equal but not == to the original IID 348bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten (*callback)(&thiz->mItf, context, SL_DYNAMIC_ITF_EVENT_ASYNC_TERMINATION, result, iid); 349510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten } 350510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten} 351510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 352ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 3533a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kastenstatic SLresult IDynamicInterfaceManagement_ResumeInterface(SLDynamicInterfaceManagementItf self, 35461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten const SLInterfaceID iid, SLboolean async) 35561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{ 356ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_ENTER_INTERFACE 357ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 358510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // validate input parameters 359ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten if (NULL == iid) { 360ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_PARAMETER_INVALID; 361ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } else { 362bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten IDynamicInterfaceManagement *thiz = (IDynamicInterfaceManagement *) self; 363bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten IObject *thisObject = InterfaceToIObject(thiz); 364bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten const ClassTable *clazz = thisObject->mClass; 365ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten int MPH, index; 366a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten if ((0 > (MPH = IID_to_MPH(iid))) || 367a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten // no need to check for an initialization hook 368a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten // (NULL == MPH_init_table[MPH].mInit) || 369bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten (0 > (index = clazz->mMPH_to_index[MPH]))) { 370ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_PRECONDITIONS_VIOLATED; 371ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } else { 372bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten assert(index < (int) clazz->mInterfaceCount); 373ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SLuint8 *interfaceStateP = &thisObject->mInterfaceStates[index]; 374510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 375ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten // check interface state 376ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten object_lock_exclusive(thisObject); 377ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten switch (*interfaceStateP) { 378ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 379ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten case INTERFACE_SUSPENDED: // normal case 380ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten if (async) { 381ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten // Asynchronous: mark operation pending and cancellable 382ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten *interfaceStateP = INTERFACE_RESUMING_1; 383ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten object_unlock_exclusive(thisObject); 384ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 385ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten // this section runs with mutex unlocked 386cf3a6383a9bc9a94ca5b424ea97313293ee0dcb0Glenn Kasten result = ThreadPool_add_ppi(&thisObject->mEngine->mThreadPool, HandleResume, 387cf3a6383a9bc9a94ca5b424ea97313293ee0dcb0Glenn Kasten thiz, NULL, MPH); 388ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten if (SL_RESULT_SUCCESS != result) { 389ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten // Engine was destroyed during resume, or insufficient memory, 390ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten // so restore mInterfaceStates state to prior value 391ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten object_lock_exclusive(thisObject); 392ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten switch (*interfaceStateP) { 393ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten case INTERFACE_RESUMING_1: // normal 394ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten case INTERFACE_RESUMING_1A: // operation aborted while mutex unlocked 395ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten *interfaceStateP = INTERFACE_SUSPENDED; 396ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten break; 397ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten default: // unexpected 398ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten // leave state alone 399ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten break; 400ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } 401ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } 402ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 403ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } else { 404ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten // Synchronous: mark operation pending to prevent duplication 405ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten *interfaceStateP = INTERFACE_RESUMING_2; 406ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten object_unlock_exclusive(thisObject); 407ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 408ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten // this section runs with mutex unlocked 409bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten const struct iid_vtable *x = &clazz->mInterfaces[index]; 410ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten size_t offset = x->mOffset; 411bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten void *thisItf = (char *) thiz + offset; 412ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten VoidHook resume = MPH_init_table[MPH].mResume; 413a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten if (NULL != resume) { 414ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten (*resume)(thisItf); 415a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten } 416ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_SUCCESS; 417ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 418ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten // re-lock mutex to update state 419ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten object_lock_exclusive(thisObject); 420ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten assert(INTERFACE_RESUMING_2 == *interfaceStateP); 421ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten *interfaceStateP = INTERFACE_ADDED; 422ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } 423510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 424711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten // mutex is now locked 425ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten break; 426510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 427ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten default: // disallow resumption of non-suspended interfaces 428ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_PRECONDITIONS_VIOLATED; 429ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten break; 430510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten } 431510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 432510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten object_unlock_exclusive(thisObject); 4333a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten } 4343a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten } 435510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 436ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_LEAVE_INTERFACE 43761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten} 43861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 439ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 4403a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kastenstatic SLresult IDynamicInterfaceManagement_RegisterCallback(SLDynamicInterfaceManagementItf self, 44161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten slDynamicInterfaceManagementCallback callback, void *pContext) 44261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{ 443ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_ENTER_INTERFACE 444ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 445bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten IDynamicInterfaceManagement *thiz = (IDynamicInterfaceManagement *) self; 446bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten IObject *thisObject = InterfaceToIObject(thiz); 44761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten object_lock_exclusive(thisObject); 448bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten thiz->mCallback = callback; 449bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten thiz->mContext = pContext; 45061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten object_unlock_exclusive(thisObject); 451ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_SUCCESS; 452ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 453ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_LEAVE_INTERFACE 45461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten} 45561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 456ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 45761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenstatic const struct SLDynamicInterfaceManagementItf_ IDynamicInterfaceManagement_Itf = { 45861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IDynamicInterfaceManagement_AddInterface, 45961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IDynamicInterfaceManagement_RemoveInterface, 46061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IDynamicInterfaceManagement_ResumeInterface, 46161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IDynamicInterfaceManagement_RegisterCallback 46261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}; 46361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 46461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenvoid IDynamicInterfaceManagement_init(void *self) 46561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{ 466bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten IDynamicInterfaceManagement *thiz = (IDynamicInterfaceManagement *) self; 467bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten thiz->mItf = &IDynamicInterfaceManagement_Itf; 468bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten thiz->mCallback = NULL; 469bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten thiz->mContext = NULL; 47061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten} 471