IObject.c revision 510f3671f716f6835282e4b0fd0275c20e9dadd8
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/* Object implementation */ 1861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 1961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten#include "sles_allinclusive.h" 2061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 21510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten// Called by a worker thread to handle an asynchronous Object.Realize. 22510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten// Parameter self is the Object. 23d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten 24510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kastenstatic void HandleRealize(void *self, int unused) 2561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{ 26510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 27510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // validate input parameters 28510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten IObject *this = (IObject *) self; 29510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten assert(NULL != this); 3061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten const ClassTable *class__ = this->mClass; 31510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten assert(NULL != class__); 323d146e0a31f5ee2a7d9807c4e99994084fdd3283Jean-Michel Trivi AsyncHook realize = class__->mRealize; 333a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten SLresult result; 34d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten SLuint32 state; 35510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 36510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // check object state 3761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten object_lock_exclusive(this); 38510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten state = this->mState; 39510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten switch (state) { 40510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 41510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case SL_OBJECT_STATE_REALIZING_1: // normal case 42510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten if (NULL != realize) { 43510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten this->mState = SL_OBJECT_STATE_REALIZING_2; 44510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten object_unlock_exclusive(this); 45510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // Note that the mutex is unlocked during the realize hook 46510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten result = (*realize)(this, SL_BOOLEAN_TRUE); 47510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten object_lock_exclusive(this); 48510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten assert(SL_OBJECT_STATE_REALIZING_2 == this->mState); 49510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten state = SL_RESULT_SUCCESS == result ? SL_OBJECT_STATE_REALIZED : 50510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten SL_OBJECT_STATE_UNREALIZED; 51510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten } else { 52510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten result = SL_RESULT_SUCCESS; 53510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten state = SL_OBJECT_STATE_REALIZED; 54510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten } 55510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 56510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 57510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case SL_OBJECT_STATE_REALIZING_1A: // operation was aborted while on work queue 58510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten result = SL_RESULT_OPERATION_ABORTED; 59510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten state = SL_OBJECT_STATE_UNREALIZED; 60510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 61510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 62510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten default: // impossible 63510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten assert(SL_BOOLEAN_FALSE); 64510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten result = SL_RESULT_INTERNAL_ERROR; 65510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 66510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 6761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten } 68510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 69510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // mutex is locked, update state 70d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten this->mState = state; 71510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 72d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten // Make a copy of these, so we can call the callback with mutex unlocked 73d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten slObjectCallback callback = this->mCallback; 74d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten void *context = this->mContext; 7561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten object_unlock_exclusive(this); 76510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 77d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten // Note that the mutex is unlocked during the callback 783a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten if (NULL != callback) 79d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten (*callback)(&this->mItf, context, SL_OBJECT_EVENT_ASYNC_TERMINATION, result, state, NULL); 80d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten} 81d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten 82d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kastenstatic SLresult IObject_Realize(SLObjectItf self, SLboolean async) 83d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten{ 84d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten IObject *this = (IObject *) self; 85d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten SLuint32 state; 86d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten const ClassTable *class__ = this->mClass; 87d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten object_lock_exclusive(this); 88d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten state = this->mState; 89d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten // Reject redundant calls to Realize 90d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten if (SL_OBJECT_STATE_UNREALIZED != state) { 91510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten object_unlock_exclusive(this); 92510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten return SL_RESULT_PRECONDITIONS_VIOLATED; 93510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten } 94d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten // Asynchronous: mark operation pending and cancellable 95510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten if (async && (SL_OBJECTID_ENGINE != class__->mObjectID)) { 96d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten state = SL_OBJECT_STATE_REALIZING_1; 97d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten // Synchronous: mark operation pending and non-cancellable 98d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten } else { 99d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten state = SL_OBJECT_STATE_REALIZING_2; 100d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten } 101510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten this->mState = state; 102d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten object_unlock_exclusive(this); 103510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten SLresult result; 104d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten switch (state) { 105d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten case SL_OBJECT_STATE_REALIZING_1: // asynchronous on non-Engine 106d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten assert(async); 107510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten result = ThreadPool_add(&this->mEngine->mThreadPool, HandleRealize, this, 0); 108510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten if (SL_RESULT_SUCCESS != result) { 109510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // Engine was destroyed during realize, or insufficient memory 110510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten object_lock_exclusive(this); 111510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten this->mState = SL_OBJECT_STATE_UNREALIZED; 112510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten object_unlock_exclusive(this); 113d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten } 114d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten break; 115d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten case SL_OBJECT_STATE_REALIZING_2: // synchronous, or asynchronous on Engine 116d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten { 117d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten AsyncHook realize = class__->mRealize; 118d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten // Note that the mutex is unlocked during the realize hook 119510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten result = (NULL != realize) ? (*realize)(this, async) : SL_RESULT_SUCCESS; 120d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten object_lock_exclusive(this); 121d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten assert(SL_OBJECT_STATE_REALIZING_2 == this->mState); 122510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten state = (SL_RESULT_SUCCESS == result) ? SL_OBJECT_STATE_REALIZED : 123510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten SL_OBJECT_STATE_UNREALIZED; 124d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten this->mState = state; 125d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten slObjectCallback callback = this->mCallback; 126d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten void *context = this->mContext; 127d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten object_unlock_exclusive(this); 128d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten // asynchronous Realize on an Engine is actually done synchronously, but still has callback 129d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten // This is because there is no thread pool yet to do it asynchronously. 130d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten if (async && (NULL != callback)) 131510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten (*callback)(&this->mItf, context, SL_OBJECT_EVENT_ASYNC_TERMINATION, result, state, 132510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten NULL); 133d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten } 134d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten break; 135510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten default: // impossible 136510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten assert(SL_BOOLEAN_FALSE); 137d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten break; 138d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten } 13961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten return result; 14061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten} 14161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 142510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten// Called by a worker thread to handle an asynchronous Object.Resume. 143510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten// Parameter self is the Object. 144510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 145510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kastenstatic void HandleResume(void *self, int unused) 14661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{ 147510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 148510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // valid input parameters 14961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IObject *this = (IObject *) self; 150510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten assert(NULL != this); 15161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten const ClassTable *class__ = this->mClass; 152510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten assert(NULL != class__); 153510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten AsyncHook resume = class__->mResume; 1543a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten SLresult result; 155510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten SLuint32 state; 156510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 157510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // check object state 15861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten object_lock_exclusive(this); 159510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten state = this->mState; 160510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten switch (state) { 161510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 162510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case SL_OBJECT_STATE_RESUMING_1: // normal case 163510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten if (NULL != resume) { 164510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten this->mState = SL_OBJECT_STATE_RESUMING_2; 165510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten object_unlock_exclusive(this); 166510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // Note that the mutex is unlocked during the resume hook 167510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten result = (*resume)(this, SL_BOOLEAN_TRUE); 168510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten object_lock_exclusive(this); 169510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten assert(SL_OBJECT_STATE_RESUMING_2 == this->mState); 170510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten state = SL_RESULT_SUCCESS == result ? SL_OBJECT_STATE_REALIZED : 171510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten SL_OBJECT_STATE_SUSPENDED; 172510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten } else { 173510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten result = SL_RESULT_SUCCESS; 174510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten state = SL_OBJECT_STATE_REALIZED; 1753a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten } 176510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 177510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 178510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case SL_OBJECT_STATE_RESUMING_1A: // operation was aborted while on work queue 179510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten result = SL_RESULT_OPERATION_ABORTED; 180510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten state = SL_OBJECT_STATE_SUSPENDED; 181510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 182510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 183510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten default: // impossible 184510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten assert(SL_BOOLEAN_FALSE); 185510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten result = SL_RESULT_INTERNAL_ERROR; 186510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 187510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 18861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten } 189510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 190510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // mutex is unlocked, update state 191510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten this->mState = state; 192510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 193510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // Make a copy of these, so we can call the callback with mutex unlocked 194510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten slObjectCallback callback = this->mCallback; 195510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten void *context = this->mContext; 19661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten object_unlock_exclusive(this); 197510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 198510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // Note that the mutex is unlocked during the callback 1993a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten if (NULL != callback) 200510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten (*callback)(&this->mItf, context, SL_OBJECT_EVENT_ASYNC_TERMINATION, result, state, NULL); 201510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten} 202510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 203510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kastenstatic SLresult IObject_Resume(SLObjectItf self, SLboolean async) 204510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten{ 205510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten IObject *this = (IObject *) self; 206510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten const ClassTable *class__ = this->mClass; 207510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten SLresult result; 208510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten SLuint32 state; 209510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten object_lock_exclusive(this); 210510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten state = this->mState; 211510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // Reject redundant calls to Resume 212510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten if (SL_OBJECT_STATE_SUSPENDED != state) { 213510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten object_unlock_exclusive(this); 214510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten return SL_RESULT_PRECONDITIONS_VIOLATED; 215510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten } 216510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // Asynchronous: mark operation pending and cancellable 217510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten if (async) { 218510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten state = SL_OBJECT_STATE_RESUMING_1; 219510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // Synchronous: mark operatio pending and non-cancellable 220510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten } else { 221510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten state = SL_OBJECT_STATE_RESUMING_2; 222510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten } 223510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten this->mState = state; 224510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten object_unlock_exclusive(this); 225510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten switch (state) { 226510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case SL_OBJECT_STATE_RESUMING_1: // asynchronous 227510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten assert(async); 228510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten result = ThreadPool_add(&this->mEngine->mThreadPool, HandleResume, this, 0); 229510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten if (SL_RESULT_SUCCESS != result) { 230510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // Engine was destroyed during resume, or insufficient memory 231510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten object_lock_exclusive(this); 232510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten this->mState = SL_OBJECT_STATE_SUSPENDED; 233510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten object_unlock_exclusive(this); 234510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten } 235510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 236510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case SL_OBJECT_STATE_RESUMING_2: // synchronous 237510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten { 238510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten AsyncHook resume = class__->mResume; 239510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // Note that the mutex is unlocked during the resume hook 240510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten result = (NULL != resume) ? (*resume)(this, SL_BOOLEAN_FALSE) : SL_RESULT_SUCCESS; 241510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten object_lock_exclusive(this); 242510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten assert(SL_OBJECT_STATE_RESUMING_2 == this->mState); 243510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten this->mState = (SL_RESULT_SUCCESS == result) ? SL_OBJECT_STATE_REALIZED : 244510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten SL_OBJECT_STATE_SUSPENDED; 245510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten object_unlock_exclusive(this); 246510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten } 247510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 248510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten default: // impossible 249510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten assert(SL_BOOLEAN_FALSE); 250510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 251510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten } 25261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten return result; 25361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten} 25461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 25561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenstatic SLresult IObject_GetState(SLObjectItf self, SLuint32 *pState) 25661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{ 25761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten if (NULL == pState) 25861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten return SL_RESULT_PARAMETER_INVALID; 25961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IObject *this = (IObject *) self; 2603a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten // Note that the state is immediately obsolete, so a peek lock is safe 2613a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten object_lock_peek(this); 26261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten SLuint32 state = this->mState; 2633a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten object_unlock_peek(this); 264510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // Re-map the realizing and suspended states 265d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten switch (state) { 266d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten case SL_OBJECT_STATE_REALIZING_1: 267510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case SL_OBJECT_STATE_REALIZING_1A: 268d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten case SL_OBJECT_STATE_REALIZING_2: 269d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten state = SL_OBJECT_STATE_UNREALIZED; 270d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten break; 271510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case SL_OBJECT_STATE_RESUMING_1: 272510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case SL_OBJECT_STATE_RESUMING_1A: 273510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case SL_OBJECT_STATE_RESUMING_2: 274510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case SL_OBJECT_STATE_SUSPENDING: 275510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten state = SL_OBJECT_STATE_SUSPENDED; 276510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 277510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case SL_OBJECT_STATE_UNREALIZED: 278510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case SL_OBJECT_STATE_REALIZED: 279510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case SL_OBJECT_STATE_SUSPENDED: 280510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // These are the "official" object states, return them as is 281510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 282d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten default: 283510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten assert(SL_BOOLEAN_FALSE); 284d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten break; 285d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten } 28661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten *pState = state; 28761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten return SL_RESULT_SUCCESS; 28861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten} 28961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 2903a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kastenstatic SLresult IObject_GetInterface(SLObjectItf self, const SLInterfaceID iid, void *pInterface) 29161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{ 29261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten if (NULL == pInterface) 29361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten return SL_RESULT_PARAMETER_INVALID; 29461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten SLresult result; 29561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten void *interface = NULL; 29661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten if (NULL == iid) 29761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten result = SL_RESULT_PARAMETER_INVALID; 29861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten else { 29961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IObject *this = (IObject *) self; 30061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten const ClassTable *class__ = this->mClass; 30161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten int MPH, index; 302510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten if ((0 > (MPH = IID_to_MPH(iid))) || (0 > (index = class__->mMPH_to_index[MPH]))) { 30361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten result = SL_RESULT_FEATURE_UNSUPPORTED; 304510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten } else { 30561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten unsigned mask = 1 << index; 306510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten object_lock_exclusive(this); 307510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // Can't get interface on a suspended/suspending/resuming object 308510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten if (SL_OBJECT_STATE_REALIZED != this->mState) { 30961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten result = SL_RESULT_PRECONDITIONS_VIOLATED; 310510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten } else { 311510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten switch (this->mInterfaceStates[index]) { 312510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_EXPOSED: 313510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_ADDED: 314510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // Note that interface has been gotten, 315510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // for debugger and to detect incorrect use of interfaces 316510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten this->mGottenMask |= mask; 317510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten interface = (char *) this + class__->mInterfaces[index].mOffset; 318510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten result = SL_RESULT_SUCCESS; 319510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 320510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // Can't get interface if uninitialized/suspend(ed,ing)/resuming/adding/removing 321510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten default: 322510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten result = SL_RESULT_FEATURE_UNSUPPORTED; 323510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 324510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten } 32561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten } 326510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten object_unlock_exclusive(this); 32761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten } 32861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten } 32961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten *(void **)pInterface = interface; 33061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten return SL_RESULT_SUCCESS; 33161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten} 33261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 33361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenstatic SLresult IObject_RegisterCallback(SLObjectItf self, 33461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten slObjectCallback callback, void *pContext) 33561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{ 33661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IObject *this = (IObject *) self; 33761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten object_lock_exclusive(this); 33861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten this->mCallback = callback; 33961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten this->mContext = pContext; 34061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten object_unlock_exclusive(this); 34161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten return SL_RESULT_SUCCESS; 34261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten} 34361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 344510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten// internal common code for Abort and Destroy 345510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 346510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kastenstatic void Abort_internal(IObject *this, SLboolean shutdown) 347510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten{ 348510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // FIXME Aborting asynchronous operations during phase 2 is not yet implemented 349510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten const ClassTable *class__ = this->mClass; 350510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten object_lock_exclusive(this); 351510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // Abort asynchronous operations on the object 352510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten switch (this->mState) { 353510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case SL_OBJECT_STATE_REALIZING_1: // Realize 354510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten this->mState = SL_OBJECT_STATE_REALIZING_1A; 355510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 356510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case SL_OBJECT_STATE_RESUMING_1: // Resume 357510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten this->mState = SL_OBJECT_STATE_RESUMING_1A; 358510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 359510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten default: 360510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 361510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten } 362510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // Abort asynchronous operations on interfaces 363510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // FIXME O(n), could be O(1) using a generation count 364510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten SLuint8 *interfaceStateP = this->mInterfaceStates; 365510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten unsigned index; 366510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten for (index = 0; index < class__->mInterfaceCount; ++index, ++interfaceStateP) { 367510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten switch (*interfaceStateP) { 368510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_ADDING_1: // AddInterface 369510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten *interfaceStateP = INTERFACE_ADDING_1A; 370510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 371510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_RESUMING_1: // ResumeInterface 372510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten *interfaceStateP = INTERFACE_RESUMING_1A; 373510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 374510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten default: 375510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 376510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten } 377510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten } 378510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten#if 0 379510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // FIXME Not fully implemented, the intention is to advise other threads to exit from sync ops 380510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // FIXME Also need to wait for async ops to recognize the shutdown 381510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten if (shutdown) 382510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten this->mShutdown = SL_BOOLEAN_TRUE; 383510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten#endif 384510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten object_unlock_exclusive(this); 385510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten} 386510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 38761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenstatic void IObject_AbortAsyncOperation(SLObjectItf self) 38861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{ 389510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten IObject *this = (IObject *) self; 390510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten Abort_internal(this, SL_BOOLEAN_FALSE); 39161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten} 39261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 39361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenstatic void IObject_Destroy(SLObjectItf self) 39461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{ 395ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten // FIXME Check for dependencies, e.g. destroying an output mix with attached players, 396ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten // destroying an engine with extant objects, etc. 3973a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten // FIXME The abort should be atomic w.r.t. destroy, so another async can't be started in window 398ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten // FIXME Destroy may need to be made asynchronous to permit safe cleanup of resources 39961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IObject *this = (IObject *) self; 400510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten Abort_internal(this, SL_BOOLEAN_TRUE); 40161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten const ClassTable *class__ = this->mClass; 40261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten VoidHook destroy = class__->mDestroy; 40361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten const struct iid_vtable *x = class__->mInterfaces; 404ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten // const, no lock needed 405ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten IEngine *thisEngine = this->mEngine; 406ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten unsigned i = this->mInstanceID; 407ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten assert(0 < i && i <= INSTANCE_MAX); 408ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten --i; 409510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // remove object from exposure to sync thread and debugger 410ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten interface_lock_exclusive(thisEngine); 411ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten assert(0 < thisEngine->mInstanceCount); 412ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten --thisEngine->mInstanceCount; 413ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten assert(0 != thisEngine->mInstanceMask); 414ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten thisEngine->mInstanceMask &= ~(1 << i); 415ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten assert(thisEngine->mInstances[i] == this); 416ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten thisEngine->mInstances[i] = NULL; 41700d2d554e04ac369367c903dbf53b975355d1bcdGlenn Kasten#ifdef USE_SDL 41800d2d554e04ac369367c903dbf53b975355d1bcdGlenn Kasten if (SL_OBJECTID_OUTPUTMIX == class__->mObjectID && (COutputMix *) this == thisEngine->mOutputMix) { 41900d2d554e04ac369367c903dbf53b975355d1bcdGlenn Kasten SDL_PauseAudio(1); 42000d2d554e04ac369367c903dbf53b975355d1bcdGlenn Kasten thisEngine->mOutputMix = NULL; 42100d2d554e04ac369367c903dbf53b975355d1bcdGlenn Kasten // Note we don't attempt to connect another output mix to SDL 42200d2d554e04ac369367c903dbf53b975355d1bcdGlenn Kasten } 42300d2d554e04ac369367c903dbf53b975355d1bcdGlenn Kasten#endif 424ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten interface_unlock_exclusive(thisEngine); 42561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten object_lock_exclusive(this); 426d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten if (NULL != destroy) 427d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten (*destroy)(this); 42861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten // Call the deinitializer for each currently exposed interface, 42961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten // whether it is implicit, explicit, optional, or dynamically added. 430510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten unsigned incorrect = 0; 431510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten SLuint8 *interfaceStateP = this->mInterfaceStates; 432510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten unsigned index; 433510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten for (index = 0; index < class__->mInterfaceCount; ++index, ++x, ++interfaceStateP) { 434510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten SLuint32 state = *interfaceStateP; 435510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten switch (state) { 436510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_UNINITIALIZED: 437510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 438510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_EXPOSED: // quiescent states 439510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_ADDED: 440510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_SUSPENDED: 441510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten { 44261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten VoidHook deinit = MPH_init_table[x->mMPH].mDeinit; 44361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten if (NULL != deinit) 44461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten (*deinit)((char *) this + x->mOffset); 445510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten } 446510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 447510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_ADDING_1: // active states indicate incorrect use of API 448510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_ADDING_1A: 449510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_ADDING_2: 450510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_RESUMING_1: 451510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_RESUMING_1A: 452510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_RESUMING_2: 453510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_REMOVING: 454510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_SUSPENDING: 455510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten ++incorrect; 456510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 457510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten default: 458510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten assert(SL_BOOLEAN_FALSE); 459510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 46061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten } 46161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten } 46261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten // redundant: this->mState = SL_OBJECT_STATE_UNREALIZED; 46361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten object_unlock_exclusive(this); 46461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten#ifndef NDEBUG 46561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten memset(this, 0x55, class__->mSize); 46661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten#endif 46761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten free(this); 468510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // one or more interfaces was actively changing at time of Destroy 469510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten assert(incorrect == 0); 470510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // FIXME assert might be the wrong thing to do; instead block until active ops complete? 47161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten} 47261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 4733a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kastenstatic SLresult IObject_SetPriority(SLObjectItf self, SLint32 priority, SLboolean preemptable) 47461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{ 47561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IObject *this = (IObject *) self; 47661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten object_lock_exclusive(this); 47761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten this->mPriority = priority; 478d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten this->mPreemptable = SL_BOOLEAN_FALSE != preemptable; // normalize 47961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten object_unlock_exclusive(this); 48061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten return SL_RESULT_SUCCESS; 48161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten} 48261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 4833a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kastenstatic SLresult IObject_GetPriority(SLObjectItf self, SLint32 *pPriority, SLboolean *pPreemptable) 48461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{ 48561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten if (NULL == pPriority || NULL == pPreemptable) 48661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten return SL_RESULT_PARAMETER_INVALID; 48761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IObject *this = (IObject *) self; 48861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten object_lock_shared(this); 48961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten SLint32 priority = this->mPriority; 49061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten SLboolean preemptable = this->mPreemptable; 49161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten object_unlock_shared(this); 49261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten *pPriority = priority; 49361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten *pPreemptable = preemptable; 49461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten return SL_RESULT_SUCCESS; 49561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten} 49661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 49761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenstatic SLresult IObject_SetLossOfControlInterfaces(SLObjectItf self, 49861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten SLint16 numInterfaces, SLInterfaceID *pInterfaceIDs, SLboolean enabled) 49961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{ 50061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten if (0 < numInterfaces) { 50161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten SLuint32 i; 50261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten if (NULL == pInterfaceIDs) 50361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten return SL_RESULT_PARAMETER_INVALID; 50461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IObject *this = (IObject *) self; 50561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten const ClassTable *class__ = this->mClass; 50661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten unsigned lossOfControlMask = 0; 50761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten // FIXME The cast is due to a typo in the spec 50861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten for (i = 0; i < (SLuint32) numInterfaces; ++i) { 50961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten SLInterfaceID iid = pInterfaceIDs[i]; 51061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten if (NULL == iid) 51161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten return SL_RESULT_PARAMETER_INVALID; 51261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten int MPH, index; 513510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten if ((0 <= (MPH = IID_to_MPH(iid))) && (0 <= (index = class__->mMPH_to_index[MPH]))) 51461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten lossOfControlMask |= (1 << index); 51561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten } 51661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten object_lock_exclusive(this); 51761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten if (enabled) 51861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten this->mLossOfControlMask |= lossOfControlMask; 51961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten else 52061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten this->mLossOfControlMask &= ~lossOfControlMask; 52161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten object_unlock_exclusive(this); 52261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten } 52361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten return SL_RESULT_SUCCESS; 52461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten} 52561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 52661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenstatic const struct SLObjectItf_ IObject_Itf = { 52761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IObject_Realize, 52861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IObject_Resume, 52961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IObject_GetState, 53061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IObject_GetInterface, 53161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IObject_RegisterCallback, 53261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IObject_AbortAsyncOperation, 53361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IObject_Destroy, 53461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IObject_SetPriority, 53561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IObject_GetPriority, 53661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IObject_SetLossOfControlInterfaces, 53761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}; 53861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 53961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenvoid IObject_init(void *self) 54061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{ 54161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IObject *this = (IObject *) self; 54261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten this->mItf = &IObject_Itf; 5430b167267bda99b68346045ccab14e810121d5de4Glenn Kasten // initialized in construct: 5440b167267bda99b68346045ccab14e810121d5de4Glenn Kasten // mClass 545ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten // mInstanceID 5460b167267bda99b68346045ccab14e810121d5de4Glenn Kasten // mLossOfControlMask 547ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten // mEngine 548510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // mInstanceStates 54961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten this->mState = SL_OBJECT_STATE_UNREALIZED; 550510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten this->mGottenMask = 1; // IObject 55161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten this->mCallback = NULL; 55261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten this->mContext = NULL; 553d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten this->mPriority = SL_PRIORITY_NORMAL; 55461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten this->mPreemptable = SL_BOOLEAN_FALSE; 55561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten int ok; 55661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten ok = pthread_mutex_init(&this->mMutex, (const pthread_mutexattr_t *) NULL); 55761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten assert(0 == ok); 55861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten ok = pthread_cond_init(&this->mCond, (const pthread_condattr_t *) NULL); 55961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten assert(0 == ok); 56061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten} 561