IObject.c revision ed46c29d6a09112dbbf584c82953f63289596fd6
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 21ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 22510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten// Called by a worker thread to handle an asynchronous Object.Realize. 23510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten// Parameter self is the Object. 24d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten 25510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kastenstatic void HandleRealize(void *self, int unused) 2661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{ 27510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 28510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // validate input parameters 29510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten IObject *this = (IObject *) self; 30510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten assert(NULL != this); 3161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten const ClassTable *class__ = this->mClass; 32510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten assert(NULL != class__); 333d146e0a31f5ee2a7d9807c4e99994084fdd3283Jean-Michel Trivi AsyncHook realize = class__->mRealize; 343a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten SLresult result; 35276cab2d983b892d1b634474b6249f6bec400c76Glenn Kasten SLuint8 state; 36510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 37510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // check object state 3861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten object_lock_exclusive(this); 39510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten state = this->mState; 40510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten switch (state) { 41510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 42510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case SL_OBJECT_STATE_REALIZING_1: // normal case 43510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten if (NULL != realize) { 44510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten this->mState = SL_OBJECT_STATE_REALIZING_2; 45510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten object_unlock_exclusive(this); 46510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // Note that the mutex is unlocked during the realize hook 47510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten result = (*realize)(this, SL_BOOLEAN_TRUE); 48510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten object_lock_exclusive(this); 49510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten assert(SL_OBJECT_STATE_REALIZING_2 == this->mState); 50510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten state = SL_RESULT_SUCCESS == result ? SL_OBJECT_STATE_REALIZED : 51510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten SL_OBJECT_STATE_UNREALIZED; 52510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten } else { 53510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten result = SL_RESULT_SUCCESS; 54510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten state = SL_OBJECT_STATE_REALIZED; 55510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten } 56510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 57510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 58510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case SL_OBJECT_STATE_REALIZING_1A: // operation was aborted while on work queue 59510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten result = SL_RESULT_OPERATION_ABORTED; 60510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten state = SL_OBJECT_STATE_UNREALIZED; 61510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 62510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 63510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten default: // impossible 64510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten assert(SL_BOOLEAN_FALSE); 65510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten result = SL_RESULT_INTERNAL_ERROR; 66510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 67510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 6861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten } 69510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 70510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // mutex is locked, update state 71d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten this->mState = state; 72510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 73d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten // Make a copy of these, so we can call the callback with mutex unlocked 74d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten slObjectCallback callback = this->mCallback; 75d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten void *context = this->mContext; 7661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten object_unlock_exclusive(this); 77510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 78d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten // Note that the mutex is unlocked during the callback 793a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten if (NULL != callback) 80d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten (*callback)(&this->mItf, context, SL_OBJECT_EVENT_ASYNC_TERMINATION, result, state, NULL); 81d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten} 82d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten 83ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 84d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kastenstatic SLresult IObject_Realize(SLObjectItf self, SLboolean async) 85d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten{ 86ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_ENTER_INTERFACE 87ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 88d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten IObject *this = (IObject *) self; 89276cab2d983b892d1b634474b6249f6bec400c76Glenn Kasten SLuint8 state; 90d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten const ClassTable *class__ = this->mClass; 91d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten object_lock_exclusive(this); 92d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten state = this->mState; 93d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten // Reject redundant calls to Realize 94d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten if (SL_OBJECT_STATE_UNREALIZED != state) { 95510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten object_unlock_exclusive(this); 96ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_PRECONDITIONS_VIOLATED; 97d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten } else { 98ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten // Asynchronous: mark operation pending and cancellable 99ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten if (async && (SL_OBJECTID_ENGINE != class__->mObjectID)) { 100ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten state = SL_OBJECT_STATE_REALIZING_1; 101ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten // Synchronous: mark operation pending and non-cancellable 102ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } else { 103ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten state = SL_OBJECT_STATE_REALIZING_2; 104d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten } 105d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten this->mState = state; 106d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten object_unlock_exclusive(this); 107ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten switch (state) { 108ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten case SL_OBJECT_STATE_REALIZING_1: // asynchronous on non-Engine 109ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten assert(async); 110ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = ThreadPool_add(&this->mEngine->mThreadPool, HandleRealize, this, 0); 111ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten if (SL_RESULT_SUCCESS != result) { 112ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten // Engine was destroyed during realize, or insufficient memory 113ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten object_lock_exclusive(this); 114ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten this->mState = SL_OBJECT_STATE_UNREALIZED; 115ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten object_unlock_exclusive(this); 116ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } 117ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten break; 118ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten case SL_OBJECT_STATE_REALIZING_2: // synchronous, or asynchronous on Engine 119ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten { 120ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten AsyncHook realize = class__->mRealize; 121ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten // Note that the mutex is unlocked during the realize hook 122ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = (NULL != realize) ? (*realize)(this, async) : SL_RESULT_SUCCESS; 123ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten object_lock_exclusive(this); 124ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten assert(SL_OBJECT_STATE_REALIZING_2 == this->mState); 125ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten state = (SL_RESULT_SUCCESS == result) ? SL_OBJECT_STATE_REALIZED : 126ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_OBJECT_STATE_UNREALIZED; 127ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten this->mState = state; 128ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten slObjectCallback callback = this->mCallback; 129ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten void *context = this->mContext; 130ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten object_unlock_exclusive(this); 131ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten // asynchronous Realize on an Engine is actually done synchronously, but still has 132ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten // callback because there is no thread pool yet to do it asynchronously. 133ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten if (async && (NULL != callback)) 134ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten (*callback)(&this->mItf, context, SL_OBJECT_EVENT_ASYNC_TERMINATION, result, state, 135ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten NULL); 136ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } 137ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten break; 138ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten default: // impossible 139ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten assert(SL_BOOLEAN_FALSE); 140ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten break; 141d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten } 142d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten } 143ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 144ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_LEAVE_INTERFACE 14561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten} 14661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 147ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 148510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten// Called by a worker thread to handle an asynchronous Object.Resume. 149510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten// Parameter self is the Object. 150510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 151510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kastenstatic void HandleResume(void *self, int unused) 15261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{ 153510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 154510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // valid input parameters 15561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IObject *this = (IObject *) self; 156510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten assert(NULL != this); 15761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten const ClassTable *class__ = this->mClass; 158510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten assert(NULL != class__); 159510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten AsyncHook resume = class__->mResume; 1603a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten SLresult result; 161276cab2d983b892d1b634474b6249f6bec400c76Glenn Kasten SLuint8 state; 162510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 163510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // check object state 16461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten object_lock_exclusive(this); 165510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten state = this->mState; 166510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten switch (state) { 167510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 168510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case SL_OBJECT_STATE_RESUMING_1: // normal case 169510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten if (NULL != resume) { 170510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten this->mState = SL_OBJECT_STATE_RESUMING_2; 171510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten object_unlock_exclusive(this); 172510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // Note that the mutex is unlocked during the resume hook 173510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten result = (*resume)(this, SL_BOOLEAN_TRUE); 174510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten object_lock_exclusive(this); 175510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten assert(SL_OBJECT_STATE_RESUMING_2 == this->mState); 176510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten state = SL_RESULT_SUCCESS == result ? SL_OBJECT_STATE_REALIZED : 177510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten SL_OBJECT_STATE_SUSPENDED; 178510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten } else { 179510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten result = SL_RESULT_SUCCESS; 180510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten state = SL_OBJECT_STATE_REALIZED; 1813a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten } 182510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 183510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 184510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case SL_OBJECT_STATE_RESUMING_1A: // operation was aborted while on work queue 185510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten result = SL_RESULT_OPERATION_ABORTED; 186510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten state = SL_OBJECT_STATE_SUSPENDED; 187510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 188510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 189510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten default: // impossible 190510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten assert(SL_BOOLEAN_FALSE); 191510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten result = SL_RESULT_INTERNAL_ERROR; 192510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 193510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 19461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten } 195510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 196510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // mutex is unlocked, update state 197510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten this->mState = state; 198510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 199510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // Make a copy of these, so we can call the callback with mutex unlocked 200510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten slObjectCallback callback = this->mCallback; 201510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten void *context = this->mContext; 20261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten object_unlock_exclusive(this); 203510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 204510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // Note that the mutex is unlocked during the callback 2053a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten if (NULL != callback) 206510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten (*callback)(&this->mItf, context, SL_OBJECT_EVENT_ASYNC_TERMINATION, result, state, NULL); 207510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten} 208510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 209ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 210510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kastenstatic SLresult IObject_Resume(SLObjectItf self, SLboolean async) 211510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten{ 212ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_ENTER_INTERFACE 213ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 214510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten IObject *this = (IObject *) self; 215510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten const ClassTable *class__ = this->mClass; 216276cab2d983b892d1b634474b6249f6bec400c76Glenn Kasten SLuint8 state; 217510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten object_lock_exclusive(this); 218510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten state = this->mState; 219510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // Reject redundant calls to Resume 220510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten if (SL_OBJECT_STATE_SUSPENDED != state) { 221510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten object_unlock_exclusive(this); 222ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_PRECONDITIONS_VIOLATED; 223510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten } else { 224ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten // Asynchronous: mark operation pending and cancellable 225ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten if (async) { 226ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten state = SL_OBJECT_STATE_RESUMING_1; 227ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten // Synchronous: mark operatio pending and non-cancellable 228ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } else { 229ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten state = SL_OBJECT_STATE_RESUMING_2; 230510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten } 231ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten this->mState = state; 232510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten object_unlock_exclusive(this); 233ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten switch (state) { 234ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten case SL_OBJECT_STATE_RESUMING_1: // asynchronous 235ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten assert(async); 236ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = ThreadPool_add(&this->mEngine->mThreadPool, HandleResume, this, 0); 237ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten if (SL_RESULT_SUCCESS != result) { 238ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten // Engine was destroyed during resume, or insufficient memory 239ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten object_lock_exclusive(this); 240ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten this->mState = SL_OBJECT_STATE_SUSPENDED; 241ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten object_unlock_exclusive(this); 242ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } 243ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten break; 244ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten case SL_OBJECT_STATE_RESUMING_2: // synchronous 245ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten { 246ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten AsyncHook resume = class__->mResume; 247ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten // Note that the mutex is unlocked during the resume hook 248ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = (NULL != resume) ? (*resume)(this, SL_BOOLEAN_FALSE) : SL_RESULT_SUCCESS; 249ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten object_lock_exclusive(this); 250ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten assert(SL_OBJECT_STATE_RESUMING_2 == this->mState); 251ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten this->mState = (SL_RESULT_SUCCESS == result) ? SL_OBJECT_STATE_REALIZED : 252ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_OBJECT_STATE_SUSPENDED; 253ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten object_unlock_exclusive(this); 254ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } 255ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten break; 256ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten default: // impossible 257ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten assert(SL_BOOLEAN_FALSE); 258ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten break; 259510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten } 260510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten } 261ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 262ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_LEAVE_INTERFACE 26361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten} 26461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 265ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 26661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenstatic SLresult IObject_GetState(SLObjectItf self, SLuint32 *pState) 26761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{ 268ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_ENTER_INTERFACE 269ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 270ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten if (NULL == pState) { 271ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_PARAMETER_INVALID; 272ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } else { 273ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten IObject *this = (IObject *) self; 274ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten // Note that the state is immediately obsolete, so a peek lock is safe 275ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten object_lock_peek(this); 276ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SLuint8 state = this->mState; 277ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten object_unlock_peek(this); 278ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten // Re-map the realizing, resuming, and suspending states 279ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten switch (state) { 280ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten case SL_OBJECT_STATE_REALIZING_1: 281ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten case SL_OBJECT_STATE_REALIZING_1A: 282ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten case SL_OBJECT_STATE_REALIZING_2: 283ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten state = SL_OBJECT_STATE_UNREALIZED; 284ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten break; 285ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten case SL_OBJECT_STATE_RESUMING_1: 286ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten case SL_OBJECT_STATE_RESUMING_1A: 287ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten case SL_OBJECT_STATE_RESUMING_2: 288ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten case SL_OBJECT_STATE_SUSPENDING: 289ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten state = SL_OBJECT_STATE_SUSPENDED; 290ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten break; 291ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten case SL_OBJECT_STATE_UNREALIZED: 292ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten case SL_OBJECT_STATE_REALIZED: 293ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten case SL_OBJECT_STATE_SUSPENDED: 294ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten // These are the "official" object states, return them as is 295ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten break; 296ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten default: 297ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten assert(SL_BOOLEAN_FALSE); 298ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten break; 299ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } 300ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten *pState = state; 301ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_SUCCESS; 302d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten } 303ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 304ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_LEAVE_INTERFACE 30561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten} 30661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 307ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 3083a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kastenstatic SLresult IObject_GetInterface(SLObjectItf self, const SLInterfaceID iid, void *pInterface) 30961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{ 310ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_ENTER_INTERFACE 311ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 312ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten if (NULL == pInterface) { 31361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten result = SL_RESULT_PARAMETER_INVALID; 314ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } else { 315ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten void *interface = NULL; 316ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten if (NULL == iid) { 317ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_PARAMETER_INVALID; 318510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten } else { 319ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten IObject *this = (IObject *) self; 320ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten const ClassTable *class__ = this->mClass; 321ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten int MPH, index; 322ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten if ((0 > (MPH = IID_to_MPH(iid))) || (0 > (index = class__->mMPH_to_index[MPH]))) { 323ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_FEATURE_UNSUPPORTED; 324510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten } else { 325ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten unsigned mask = 1 << index; 326ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten object_lock_exclusive(this); 327ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten // Can't get interface on a suspended/suspending/resuming object 328ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten if (SL_OBJECT_STATE_REALIZED != this->mState) { 329ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_PRECONDITIONS_VIOLATED; 330ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } else { 331ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten switch (this->mInterfaceStates[index]) { 332ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten case INTERFACE_EXPOSED: 333ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten case INTERFACE_ADDED: 334ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten // Note that interface has been gotten, 335ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten // for debugger and to detect incorrect use of interfaces 336ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten this->mGottenMask |= mask; 337ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten interface = (char *) this + class__->mInterfaces[index].mOffset; 338ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_SUCCESS; 339ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten break; 340ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten // Can't get interface if uninitialized/suspend(ed,ing)/resuming/adding/removing 341ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten default: 342ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_FEATURE_UNSUPPORTED; 343ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten break; 344ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } 345510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten } 346ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten object_unlock_exclusive(this); 34761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten } 34861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten } 349ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten *(void **)pInterface = interface; 35061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten } 351ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 352ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_LEAVE_INTERFACE 35361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten} 35461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 355ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 35661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenstatic SLresult IObject_RegisterCallback(SLObjectItf self, 35761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten slObjectCallback callback, void *pContext) 35861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{ 359ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_ENTER_INTERFACE 360ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 36161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IObject *this = (IObject *) self; 36261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten object_lock_exclusive(this); 36361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten this->mCallback = callback; 36461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten this->mContext = pContext; 36561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten object_unlock_exclusive(this); 366ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_SUCCESS; 367ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 368ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_LEAVE_INTERFACE 36961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten} 37061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 371ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 372510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten// internal common code for Abort and Destroy 373510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 374510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kastenstatic void Abort_internal(IObject *this, SLboolean shutdown) 375510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten{ 376510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // FIXME Aborting asynchronous operations during phase 2 is not yet implemented 377510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten const ClassTable *class__ = this->mClass; 378510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten object_lock_exclusive(this); 379510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // Abort asynchronous operations on the object 380510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten switch (this->mState) { 381510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case SL_OBJECT_STATE_REALIZING_1: // Realize 382510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten this->mState = SL_OBJECT_STATE_REALIZING_1A; 383510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 384510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case SL_OBJECT_STATE_RESUMING_1: // Resume 385510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten this->mState = SL_OBJECT_STATE_RESUMING_1A; 386510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 387510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten default: 388510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 389510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten } 390510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // Abort asynchronous operations on interfaces 391510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // FIXME O(n), could be O(1) using a generation count 392510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten SLuint8 *interfaceStateP = this->mInterfaceStates; 393510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten unsigned index; 394510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten for (index = 0; index < class__->mInterfaceCount; ++index, ++interfaceStateP) { 395510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten switch (*interfaceStateP) { 396510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_ADDING_1: // AddInterface 397510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten *interfaceStateP = INTERFACE_ADDING_1A; 398510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 399510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_RESUMING_1: // ResumeInterface 400510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten *interfaceStateP = INTERFACE_RESUMING_1A; 401510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 402510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten default: 403510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 404510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten } 405510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten } 406510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten#if 0 407510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // FIXME Not fully implemented, the intention is to advise other threads to exit from sync ops 408510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // FIXME Also need to wait for async ops to recognize the shutdown 409510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten if (shutdown) 410510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten this->mShutdown = SL_BOOLEAN_TRUE; 411510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten#endif 412510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten object_unlock_exclusive(this); 413510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten} 414510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 415ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 41661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenstatic void IObject_AbortAsyncOperation(SLObjectItf self) 41761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{ 418ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_ENTER_INTERFACE_VOID 419ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 420510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten IObject *this = (IObject *) self; 421510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten Abort_internal(this, SL_BOOLEAN_FALSE); 422ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 423ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_LEAVE_INTERFACE_VOID 42461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten} 42561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 426ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 42761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenstatic void IObject_Destroy(SLObjectItf self) 42861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{ 429ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_ENTER_INTERFACE_VOID 430ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 431ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten // FIXME Check for dependencies, e.g. destroying an output mix with attached players, 432ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten // destroying an engine with extant objects, etc. 4333a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten // FIXME The abort should be atomic w.r.t. destroy, so another async can't be started in window 434ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten // FIXME Destroy may need to be made asynchronous to permit safe cleanup of resources 43561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IObject *this = (IObject *) self; 436510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten Abort_internal(this, SL_BOOLEAN_TRUE); 43761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten const ClassTable *class__ = this->mClass; 43861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten VoidHook destroy = class__->mDestroy; 43961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten const struct iid_vtable *x = class__->mInterfaces; 440ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten // const, no lock needed 441ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten IEngine *thisEngine = this->mEngine; 442ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten unsigned i = this->mInstanceID; 443d07ed7df4ec9338f97f12627690d58ed9b34f25bGlenn Kasten assert(0 < i && i <= MAX_INSTANCE); 444ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten --i; 445510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // remove object from exposure to sync thread and debugger 446ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten interface_lock_exclusive(thisEngine); 447ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten assert(0 < thisEngine->mInstanceCount); 448ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten --thisEngine->mInstanceCount; 449ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten assert(0 != thisEngine->mInstanceMask); 450ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten thisEngine->mInstanceMask &= ~(1 << i); 451ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten assert(thisEngine->mInstances[i] == this); 452ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten thisEngine->mInstances[i] = NULL; 45300d2d554e04ac369367c903dbf53b975355d1bcdGlenn Kasten#ifdef USE_SDL 454e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten if ((SL_OBJECTID_OUTPUTMIX == class__->mObjectID) && 455e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten (((COutputMix *) this == thisEngine->mOutputMix))) { 45600d2d554e04ac369367c903dbf53b975355d1bcdGlenn Kasten SDL_PauseAudio(1); 45700d2d554e04ac369367c903dbf53b975355d1bcdGlenn Kasten thisEngine->mOutputMix = NULL; 45800d2d554e04ac369367c903dbf53b975355d1bcdGlenn Kasten // Note we don't attempt to connect another output mix to SDL 45900d2d554e04ac369367c903dbf53b975355d1bcdGlenn Kasten } 46000d2d554e04ac369367c903dbf53b975355d1bcdGlenn Kasten#endif 461ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten interface_unlock_exclusive(thisEngine); 46261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten object_lock_exclusive(this); 463d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten if (NULL != destroy) 464d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten (*destroy)(this); 46561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten // Call the deinitializer for each currently exposed interface, 46661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten // whether it is implicit, explicit, optional, or dynamically added. 467510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten unsigned incorrect = 0; 468510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten SLuint8 *interfaceStateP = this->mInterfaceStates; 469510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten unsigned index; 470510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten for (index = 0; index < class__->mInterfaceCount; ++index, ++x, ++interfaceStateP) { 471510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten SLuint32 state = *interfaceStateP; 472510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten switch (state) { 473510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_UNINITIALIZED: 474510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 475510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_EXPOSED: // quiescent states 476510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_ADDED: 477510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_SUSPENDED: 478510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten { 47961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten VoidHook deinit = MPH_init_table[x->mMPH].mDeinit; 48061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten if (NULL != deinit) 48161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten (*deinit)((char *) this + x->mOffset); 482510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten } 483510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 484510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_ADDING_1: // active states indicate incorrect use of API 485510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_ADDING_1A: 486510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_ADDING_2: 487510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_RESUMING_1: 488510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_RESUMING_1A: 489510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_RESUMING_2: 490510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_REMOVING: 491510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_SUSPENDING: 492510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten ++incorrect; 493510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 494510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten default: 495510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten assert(SL_BOOLEAN_FALSE); 496510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 49761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten } 49861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten } 49961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten // redundant: this->mState = SL_OBJECT_STATE_UNREALIZED; 50061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten object_unlock_exclusive(this); 50161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten#ifndef NDEBUG 50261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten memset(this, 0x55, class__->mSize); 50361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten#endif 50461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten free(this); 505510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // one or more interfaces was actively changing at time of Destroy 506510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten assert(incorrect == 0); 507510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // FIXME assert might be the wrong thing to do; instead block until active ops complete? 508ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 509ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_LEAVE_INTERFACE_VOID 51061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten} 51161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 512ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 5133a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kastenstatic SLresult IObject_SetPriority(SLObjectItf self, SLint32 priority, SLboolean preemptable) 51461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{ 515ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_ENTER_INTERFACE 516ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 51761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IObject *this = (IObject *) self; 51861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten object_lock_exclusive(this); 51961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten this->mPriority = priority; 520d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten this->mPreemptable = SL_BOOLEAN_FALSE != preemptable; // normalize 52161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten object_unlock_exclusive(this); 522ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_SUCCESS; 523ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 524ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_LEAVE_INTERFACE 52561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten} 52661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 527ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 5283a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kastenstatic SLresult IObject_GetPriority(SLObjectItf self, SLint32 *pPriority, SLboolean *pPreemptable) 52961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{ 530ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_ENTER_INTERFACE 531ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 532ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten if (NULL == pPriority || NULL == pPreemptable) { 533ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_PARAMETER_INVALID; 534ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } else { 535ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten IObject *this = (IObject *) self; 536ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten object_lock_shared(this); 537ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SLint32 priority = this->mPriority; 538ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SLboolean preemptable = this->mPreemptable; 539ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten object_unlock_shared(this); 540ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten *pPriority = priority; 541ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten *pPreemptable = preemptable; 542ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_SUCCESS; 543ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } 544ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 545ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_LEAVE_INTERFACE 54661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten} 54761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 548ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 54961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenstatic SLresult IObject_SetLossOfControlInterfaces(SLObjectItf self, 55061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten SLint16 numInterfaces, SLInterfaceID *pInterfaceIDs, SLboolean enabled) 55161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{ 552ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_ENTER_INTERFACE 553ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 554ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_SUCCESS; 55561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten if (0 < numInterfaces) { 55661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten SLuint32 i; 557ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten if (NULL == pInterfaceIDs) { 558ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_PARAMETER_INVALID; 559ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } else { 560ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten IObject *this = (IObject *) self; 561ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten const ClassTable *class__ = this->mClass; 562ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten unsigned lossOfControlMask = 0; 563ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten // FIXME The cast is due to a typo in the spec 564ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten for (i = 0; i < (SLuint32) numInterfaces; ++i) { 565ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SLInterfaceID iid = pInterfaceIDs[i]; 566ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten if (NULL == iid) { 567ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_PARAMETER_INVALID; 568ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten goto out; 569ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } 570ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten int MPH, index; 571ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten // FIXME no error if invalid MPH or index? 572ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten if ((0 <= (MPH = IID_to_MPH(iid))) && (0 <= (index = class__->mMPH_to_index[MPH]))) 573ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten lossOfControlMask |= (1 << index); 574ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } 575ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten object_lock_exclusive(this); 576ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten if (enabled) 577ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten this->mLossOfControlMask |= lossOfControlMask; 578ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten else 579ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten this->mLossOfControlMask &= ~lossOfControlMask; 580ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten object_unlock_exclusive(this); 58161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten } 58261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten } 583ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kastenout: 584ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 585ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_LEAVE_INTERFACE 58661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten} 58761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 588ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 58961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenstatic const struct SLObjectItf_ IObject_Itf = { 59061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IObject_Realize, 59161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IObject_Resume, 59261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IObject_GetState, 59361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IObject_GetInterface, 59461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IObject_RegisterCallback, 59561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IObject_AbortAsyncOperation, 59661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IObject_Destroy, 59761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IObject_SetPriority, 59861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IObject_GetPriority, 59961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IObject_SetLossOfControlInterfaces, 60061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}; 60161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 60261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenvoid IObject_init(void *self) 60361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{ 60461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IObject *this = (IObject *) self; 60561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten this->mItf = &IObject_Itf; 6060b167267bda99b68346045ccab14e810121d5de4Glenn Kasten // initialized in construct: 6070b167267bda99b68346045ccab14e810121d5de4Glenn Kasten // mClass 608ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten // mInstanceID 6090b167267bda99b68346045ccab14e810121d5de4Glenn Kasten // mLossOfControlMask 610ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten // mEngine 611510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // mInstanceStates 61261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten this->mState = SL_OBJECT_STATE_UNREALIZED; 613510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten this->mGottenMask = 1; // IObject 614e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten this->mAttributesMask = 0; 61561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten this->mCallback = NULL; 61661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten this->mContext = NULL; 617d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten this->mPriority = SL_PRIORITY_NORMAL; 61861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten this->mPreemptable = SL_BOOLEAN_FALSE; 61961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten int ok; 62061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten ok = pthread_mutex_init(&this->mMutex, (const pthread_mutexattr_t *) NULL); 62161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten assert(0 == ok); 62261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten ok = pthread_cond_init(&this->mCond, (const pthread_condattr_t *) NULL); 62361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten assert(0 == ok); 62461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten} 625