IObject.c revision 8b8875067dd02b79361abb00c5d65b02a8ae72b0
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 798c065779232fdd89abace68d2fc7bea786a010d7Glenn Kasten if (NULL != callback) { 80d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten (*callback)(&this->mItf, context, SL_OBJECT_EVENT_ASYNC_TERMINATION, result, state, NULL); 818c065779232fdd89abace68d2fc7bea786a010d7Glenn Kasten } 82d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten} 83d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten 84ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 85d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kastenstatic SLresult IObject_Realize(SLObjectItf self, SLboolean async) 86d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten{ 87ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_ENTER_INTERFACE 88ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 89d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten IObject *this = (IObject *) self; 90276cab2d983b892d1b634474b6249f6bec400c76Glenn Kasten SLuint8 state; 91d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten const ClassTable *class__ = this->mClass; 92d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten object_lock_exclusive(this); 93d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten state = this->mState; 94d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten // Reject redundant calls to Realize 95d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten if (SL_OBJECT_STATE_UNREALIZED != state) { 96510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten object_unlock_exclusive(this); 97ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_PRECONDITIONS_VIOLATED; 98d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten } else { 99ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten // Asynchronous: mark operation pending and cancellable 1008b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten if (async && (SL_OBJECTID_ENGINE != class__->mSLObjectID)) { 101ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten state = SL_OBJECT_STATE_REALIZING_1; 102ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten // Synchronous: mark operation pending and non-cancellable 103ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } else { 104ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten state = SL_OBJECT_STATE_REALIZING_2; 105d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten } 106d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten this->mState = state; 107d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten object_unlock_exclusive(this); 108ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten switch (state) { 109ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten case SL_OBJECT_STATE_REALIZING_1: // asynchronous on non-Engine 110ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten assert(async); 111ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = ThreadPool_add(&this->mEngine->mThreadPool, HandleRealize, this, 0); 112ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten if (SL_RESULT_SUCCESS != result) { 113ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten // Engine was destroyed during realize, or insufficient memory 114ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten object_lock_exclusive(this); 115ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten this->mState = SL_OBJECT_STATE_UNREALIZED; 116ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten object_unlock_exclusive(this); 117ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } 118ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten break; 119ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten case SL_OBJECT_STATE_REALIZING_2: // synchronous, or asynchronous on Engine 120ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten { 121ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten AsyncHook realize = class__->mRealize; 122ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten // Note that the mutex is unlocked during the realize hook 123ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = (NULL != realize) ? (*realize)(this, async) : SL_RESULT_SUCCESS; 124ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten object_lock_exclusive(this); 125ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten assert(SL_OBJECT_STATE_REALIZING_2 == this->mState); 126ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten state = (SL_RESULT_SUCCESS == result) ? SL_OBJECT_STATE_REALIZED : 127ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_OBJECT_STATE_UNREALIZED; 128ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten this->mState = state; 129ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten slObjectCallback callback = this->mCallback; 130ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten void *context = this->mContext; 131ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten object_unlock_exclusive(this); 132ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten // asynchronous Realize on an Engine is actually done synchronously, but still has 133ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten // callback because there is no thread pool yet to do it asynchronously. 1348c065779232fdd89abace68d2fc7bea786a010d7Glenn Kasten if (async && (NULL != callback)) { 135ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten (*callback)(&this->mItf, context, SL_OBJECT_EVENT_ASYNC_TERMINATION, result, state, 136ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten NULL); 137ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } 1388c065779232fdd89abace68d2fc7bea786a010d7Glenn Kasten } 139ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten break; 140ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten default: // impossible 141ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten assert(SL_BOOLEAN_FALSE); 142ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten break; 143d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten } 144d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten } 145ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 146ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_LEAVE_INTERFACE 14761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten} 14861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 149ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 150510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten// Called by a worker thread to handle an asynchronous Object.Resume. 151510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten// Parameter self is the Object. 152510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 153510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kastenstatic void HandleResume(void *self, int unused) 15461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{ 155510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 156510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // valid input parameters 15761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IObject *this = (IObject *) self; 158510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten assert(NULL != this); 15961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten const ClassTable *class__ = this->mClass; 160510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten assert(NULL != class__); 161510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten AsyncHook resume = class__->mResume; 1623a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten SLresult result; 163276cab2d983b892d1b634474b6249f6bec400c76Glenn Kasten SLuint8 state; 164510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 165510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // check object state 16661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten object_lock_exclusive(this); 167510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten state = this->mState; 168510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten switch (state) { 169510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 170510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case SL_OBJECT_STATE_RESUMING_1: // normal case 171510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten if (NULL != resume) { 172510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten this->mState = SL_OBJECT_STATE_RESUMING_2; 173510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten object_unlock_exclusive(this); 174510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // Note that the mutex is unlocked during the resume hook 175510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten result = (*resume)(this, SL_BOOLEAN_TRUE); 176510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten object_lock_exclusive(this); 177510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten assert(SL_OBJECT_STATE_RESUMING_2 == this->mState); 178510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten state = SL_RESULT_SUCCESS == result ? SL_OBJECT_STATE_REALIZED : 179510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten SL_OBJECT_STATE_SUSPENDED; 180510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten } else { 181510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten result = SL_RESULT_SUCCESS; 182510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten state = SL_OBJECT_STATE_REALIZED; 1833a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten } 184510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 185510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 186510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case SL_OBJECT_STATE_RESUMING_1A: // operation was aborted while on work queue 187510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten result = SL_RESULT_OPERATION_ABORTED; 188510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten state = SL_OBJECT_STATE_SUSPENDED; 189510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 190510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 191510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten default: // impossible 192510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten assert(SL_BOOLEAN_FALSE); 193510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten result = SL_RESULT_INTERNAL_ERROR; 194510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 195510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 19661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten } 197510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 198510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // mutex is unlocked, update state 199510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten this->mState = state; 200510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 201510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // Make a copy of these, so we can call the callback with mutex unlocked 202510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten slObjectCallback callback = this->mCallback; 203510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten void *context = this->mContext; 20461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten object_unlock_exclusive(this); 205510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 206510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // Note that the mutex is unlocked during the callback 2078c065779232fdd89abace68d2fc7bea786a010d7Glenn Kasten if (NULL != callback) { 208510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten (*callback)(&this->mItf, context, SL_OBJECT_EVENT_ASYNC_TERMINATION, result, state, NULL); 2098c065779232fdd89abace68d2fc7bea786a010d7Glenn Kasten } 210510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten} 211510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 212ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 213510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kastenstatic SLresult IObject_Resume(SLObjectItf self, SLboolean async) 214510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten{ 215ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_ENTER_INTERFACE 216ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 217510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten IObject *this = (IObject *) self; 218510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten const ClassTable *class__ = this->mClass; 219276cab2d983b892d1b634474b6249f6bec400c76Glenn Kasten SLuint8 state; 220510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten object_lock_exclusive(this); 221510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten state = this->mState; 222510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // Reject redundant calls to Resume 223510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten if (SL_OBJECT_STATE_SUSPENDED != state) { 224510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten object_unlock_exclusive(this); 225ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_PRECONDITIONS_VIOLATED; 226510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten } else { 227ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten // Asynchronous: mark operation pending and cancellable 228ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten if (async) { 229ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten state = SL_OBJECT_STATE_RESUMING_1; 230ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten // Synchronous: mark operatio pending and non-cancellable 231ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } else { 232ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten state = SL_OBJECT_STATE_RESUMING_2; 233510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten } 234ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten this->mState = state; 235510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten object_unlock_exclusive(this); 236ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten switch (state) { 237ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten case SL_OBJECT_STATE_RESUMING_1: // asynchronous 238ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten assert(async); 239ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = ThreadPool_add(&this->mEngine->mThreadPool, HandleResume, this, 0); 240ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten if (SL_RESULT_SUCCESS != result) { 241ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten // Engine was destroyed during resume, or insufficient memory 242ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten object_lock_exclusive(this); 243ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten this->mState = SL_OBJECT_STATE_SUSPENDED; 244ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten object_unlock_exclusive(this); 245ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } 246ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten break; 247ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten case SL_OBJECT_STATE_RESUMING_2: // synchronous 248ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten { 249ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten AsyncHook resume = class__->mResume; 250ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten // Note that the mutex is unlocked during the resume hook 251ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = (NULL != resume) ? (*resume)(this, SL_BOOLEAN_FALSE) : SL_RESULT_SUCCESS; 252ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten object_lock_exclusive(this); 253ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten assert(SL_OBJECT_STATE_RESUMING_2 == this->mState); 254ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten this->mState = (SL_RESULT_SUCCESS == result) ? SL_OBJECT_STATE_REALIZED : 255ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_OBJECT_STATE_SUSPENDED; 256ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten object_unlock_exclusive(this); 257ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } 258ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten break; 259ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten default: // impossible 260ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten assert(SL_BOOLEAN_FALSE); 261ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten break; 262510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten } 263510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten } 264ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 265ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_LEAVE_INTERFACE 26661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten} 26761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 268ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 26961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenstatic SLresult IObject_GetState(SLObjectItf self, SLuint32 *pState) 27061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{ 271ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_ENTER_INTERFACE 272ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 273ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten if (NULL == pState) { 274ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_PARAMETER_INVALID; 275ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } else { 276ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten IObject *this = (IObject *) self; 277ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten // Note that the state is immediately obsolete, so a peek lock is safe 278ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten object_lock_peek(this); 279ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SLuint8 state = this->mState; 280ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten object_unlock_peek(this); 281ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten // Re-map the realizing, resuming, and suspending states 282ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten switch (state) { 283ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten case SL_OBJECT_STATE_REALIZING_1: 284ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten case SL_OBJECT_STATE_REALIZING_1A: 285ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten case SL_OBJECT_STATE_REALIZING_2: 286928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten case SL_OBJECT_STATE_DESTROYING: // application shouldn't call GetState after Destroy 287ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten state = SL_OBJECT_STATE_UNREALIZED; 288ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten break; 289ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten case SL_OBJECT_STATE_RESUMING_1: 290ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten case SL_OBJECT_STATE_RESUMING_1A: 291ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten case SL_OBJECT_STATE_RESUMING_2: 292ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten case SL_OBJECT_STATE_SUSPENDING: 293ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten state = SL_OBJECT_STATE_SUSPENDED; 294ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten break; 295ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten case SL_OBJECT_STATE_UNREALIZED: 296ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten case SL_OBJECT_STATE_REALIZED: 297ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten case SL_OBJECT_STATE_SUSPENDED: 298ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten // These are the "official" object states, return them as is 299ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten break; 300ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten default: 301ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten assert(SL_BOOLEAN_FALSE); 302ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten break; 303ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } 304ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten *pState = state; 305ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_SUCCESS; 306d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten } 307ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 308ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_LEAVE_INTERFACE 30961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten} 31061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 3113a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kastenstatic SLresult IObject_GetInterface(SLObjectItf self, const SLInterfaceID iid, void *pInterface) 31261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{ 313ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_ENTER_INTERFACE 314ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 315ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten if (NULL == pInterface) { 31661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten result = SL_RESULT_PARAMETER_INVALID; 317ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } else { 318ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten void *interface = NULL; 319ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten if (NULL == iid) { 320ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_PARAMETER_INVALID; 321510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten } else { 322ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten IObject *this = (IObject *) self; 323ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten const ClassTable *class__ = this->mClass; 324ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten int MPH, index; 325a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten if ((0 > (MPH = IID_to_MPH(iid))) || 326a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten // no need to check for an initialization hook 327a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten // (NULL == MPH_init_table[MPH].mInit) || 328a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten (0 > (index = class__->mMPH_to_index[MPH]))) { 329ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_FEATURE_UNSUPPORTED; 330510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten } else { 331ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten unsigned mask = 1 << index; 332ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten object_lock_exclusive(this); 333104c000a6f36b871ca11e0394db1e5217f374cafGlenn Kasten if ((SL_OBJECT_STATE_REALIZED != this->mState) && 334104c000a6f36b871ca11e0394db1e5217f374cafGlenn Kasten !(INTERFACE_PREREALIZE & class__->mInterfaces[index].mInterface)) { 335104c000a6f36b871ca11e0394db1e5217f374cafGlenn Kasten // Can't get interface on an unrealized object unless pre-realize is ok 336ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_PRECONDITIONS_VIOLATED; 3378b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten } else if ((MPH_MUTESOLO == MPH) && (SL_OBJECTID_AUDIOPLAYER == 3388b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten class__->mSLObjectID) && (1 == ((CAudioPlayer *) this)->mNumChannels)) { 339f6f5ceb363286d5ebef2c2e70c8a5aa135d5d1eeGlenn Kasten // Can't get the MuteSolo interface of an audio player if the channel count is 340f6f5ceb363286d5ebef2c2e70c8a5aa135d5d1eeGlenn Kasten // mono, but _can_ get the MuteSolo interface if the channel count is unknown 341f6f5ceb363286d5ebef2c2e70c8a5aa135d5d1eeGlenn Kasten result = SL_RESULT_FEATURE_UNSUPPORTED; 342ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } else { 343ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten switch (this->mInterfaceStates[index]) { 344ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten case INTERFACE_EXPOSED: 345ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten case INTERFACE_ADDED: 346e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten interface = (char *) this + class__->mInterfaces[index].mOffset; 347ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten // Note that interface has been gotten, 348ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten // for debugger and to detect incorrect use of interfaces 349e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten if (!(this->mGottenMask & mask)) { 350e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten this->mGottenMask |= mask; 351711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten // This trickery validates the v-table 352e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten ((size_t *) interface)[0] ^= ~0; 353e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten } 354ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_SUCCESS; 355ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten break; 356a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten // Can't get interface if uninitialized, initialized, suspended, 357a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten // suspending, resuming, adding, or removing 358ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten default: 359ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_FEATURE_UNSUPPORTED; 360ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten break; 361ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } 362510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten } 363ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten object_unlock_exclusive(this); 36461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten } 36561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten } 366ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten *(void **)pInterface = interface; 36761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten } 368ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 369ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_LEAVE_INTERFACE 37061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten} 37161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 372ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 37361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenstatic SLresult IObject_RegisterCallback(SLObjectItf self, 37461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten slObjectCallback callback, void *pContext) 37561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{ 376ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_ENTER_INTERFACE 377ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 37861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IObject *this = (IObject *) self; 37961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten object_lock_exclusive(this); 38061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten this->mCallback = callback; 38161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten this->mContext = pContext; 38261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten object_unlock_exclusive(this); 383ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_SUCCESS; 384ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 385ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_LEAVE_INTERFACE 38661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten} 38761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 388ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 389928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten/** \brief This is internal common code for Abort and Destroy. 390928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten * Note: called with mutex unlocked, and returns with mutex locked. 391928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten */ 392510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 393928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kastenstatic void Abort_internal(IObject *this) 394510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten{ 395510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten const ClassTable *class__ = this->mClass; 396928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten bool anyAsync = false; 397510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten object_lock_exclusive(this); 398928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten 399510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // Abort asynchronous operations on the object 400510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten switch (this->mState) { 401510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case SL_OBJECT_STATE_REALIZING_1: // Realize 402510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten this->mState = SL_OBJECT_STATE_REALIZING_1A; 403928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten anyAsync = true; 404510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 405510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case SL_OBJECT_STATE_RESUMING_1: // Resume 406510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten this->mState = SL_OBJECT_STATE_RESUMING_1A; 407928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten anyAsync = true; 408928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten break; 409928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten case SL_OBJECT_STATE_REALIZING_1A: // Realize 410928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten case SL_OBJECT_STATE_REALIZING_2: 411928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten case SL_OBJECT_STATE_RESUMING_1A: // Resume 412928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten case SL_OBJECT_STATE_RESUMING_2: 413928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten anyAsync = true; 414928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten break; 415928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten case SL_OBJECT_STATE_DESTROYING: 416928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten assert(false); 417510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 418510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten default: 419510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 420510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten } 421928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten 422510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // Abort asynchronous operations on interfaces 423510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten SLuint8 *interfaceStateP = this->mInterfaceStates; 424510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten unsigned index; 425510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten for (index = 0; index < class__->mInterfaceCount; ++index, ++interfaceStateP) { 426510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten switch (*interfaceStateP) { 427510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_ADDING_1: // AddInterface 428510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten *interfaceStateP = INTERFACE_ADDING_1A; 429928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten anyAsync = true; 430510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 431510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_RESUMING_1: // ResumeInterface 432510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten *interfaceStateP = INTERFACE_RESUMING_1A; 433928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten anyAsync = true; 434928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten break; 435928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten case INTERFACE_ADDING_1A: // AddInterface 436928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten case INTERFACE_ADDING_2: 437928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten case INTERFACE_RESUMING_1A: // ResumeInterface 438928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten case INTERFACE_RESUMING_2: 439711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten case INTERFACE_REMOVING: // not observable: RemoveInterface is synchronous & mutex locked 440928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten anyAsync = true; 441510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 442510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten default: 443510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 444510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten } 445510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten } 446928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten 447928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten // Wait until all asynchronous operations either complete normally or recognize the abort 448928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten while (anyAsync) { 449928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten object_unlock_exclusive(this); 450928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten // FIXME should use condition variable instead of polling 451928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten usleep(20000); 452928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten anyAsync = false; 453928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten object_lock_exclusive(this); 454928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten switch (this->mState) { 455928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten case SL_OBJECT_STATE_REALIZING_1: // state 1 means it cycled during the usleep window 456928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten case SL_OBJECT_STATE_RESUMING_1: 457928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten case SL_OBJECT_STATE_REALIZING_1A: 458928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten case SL_OBJECT_STATE_REALIZING_2: 459928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten case SL_OBJECT_STATE_RESUMING_1A: 460928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten case SL_OBJECT_STATE_RESUMING_2: 461928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten anyAsync = true; 462928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten break; 463928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten case SL_OBJECT_STATE_DESTROYING: 464928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten assert(false); 465928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten break; 466928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten default: 467928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten break; 468928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten } 469928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten interfaceStateP = this->mInterfaceStates; 470928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten for (index = 0; index < class__->mInterfaceCount; ++index, ++interfaceStateP) { 471928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten switch (*interfaceStateP) { 472928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten case INTERFACE_ADDING_1: // state 1 means it cycled during the usleep window 473928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten case INTERFACE_RESUMING_1: 474928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten case INTERFACE_ADDING_1A: 475928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten case INTERFACE_ADDING_2: 476928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten case INTERFACE_RESUMING_1A: 477928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten case INTERFACE_RESUMING_2: 478928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten case INTERFACE_REMOVING: 479928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten anyAsync = true; 480928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten break; 481928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten default: 482928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten break; 483928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten } 484928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten } 485928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten } 486928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten 487928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten // At this point there are no pending asynchronous operations 488510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten} 489510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 490ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 49161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenstatic void IObject_AbortAsyncOperation(SLObjectItf self) 49261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{ 493ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_ENTER_INTERFACE_VOID 494ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 495510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten IObject *this = (IObject *) self; 496928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten Abort_internal(this); 497928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten object_unlock_exclusive(this); 498ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 499ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_LEAVE_INTERFACE_VOID 50061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten} 50161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 502ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 503f51dba65751107c930759938775b75531ec1f330Glenn Kastenvoid IObject_Destroy(SLObjectItf self) 50461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{ 505ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_ENTER_INTERFACE_VOID 506ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 50761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IObject *this = (IObject *) self; 508928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten // mutex is unlocked 509928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten Abort_internal(this); 510928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten // mutex is locked 51161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten const ClassTable *class__ = this->mClass; 512928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten BoolHook preDestroy = class__->mPreDestroy; 513928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten // The pre-destroy hook is called with mutex locked, and should block until it is safe to 514928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten // destroy. It is OK to unlock the mutex temporarily, as it long as it re-locks the mutex 515928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten // before returning. 516928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten if (NULL != preDestroy) { 517928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten bool okToDestroy = (*preDestroy)(this); 518928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten if (!okToDestroy) { 519928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten object_unlock_exclusive(this); 520928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten // unfortunately Destroy doesn't return a result 521928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten SL_LOGE("Object::Destroy(%p) not allowed", this); 522928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten SL_LEAVE_INTERFACE_VOID 523928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten } 524928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten } 525928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten this->mState = SL_OBJECT_STATE_DESTROYING; 52661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten VoidHook destroy = class__->mDestroy; 527ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten // const, no lock needed 528b0ab2dee391dd2cb257faeaba252ee6ecccc5f03Glenn Kasten IEngine *thisEngine = &this->mEngine->mEngine; 529ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten unsigned i = this->mInstanceID; 530f51dba65751107c930759938775b75531ec1f330Glenn Kasten assert(MAX_INSTANCE >= i); 531928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten // avoid a recursive lock on the engine when destroying the engine itself 532928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten if (thisEngine->mThis != this) { 533928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten interface_lock_exclusive(thisEngine); 534928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten } 535f51dba65751107c930759938775b75531ec1f330Glenn Kasten // An unpublished object has a slot reserved, but the ID hasn't been chosen yet 536ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten assert(0 < thisEngine->mInstanceCount); 537ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten --thisEngine->mInstanceCount; 538f51dba65751107c930759938775b75531ec1f330Glenn Kasten // If object is published, then remove it from exposure to sync thread and debugger 539f51dba65751107c930759938775b75531ec1f330Glenn Kasten if (0 != i) { 540f51dba65751107c930759938775b75531ec1f330Glenn Kasten --i; 541104c000a6f36b871ca11e0394db1e5217f374cafGlenn Kasten unsigned mask = 1 << i; 542104c000a6f36b871ca11e0394db1e5217f374cafGlenn Kasten assert(thisEngine->mInstanceMask & mask); 543104c000a6f36b871ca11e0394db1e5217f374cafGlenn Kasten thisEngine->mInstanceMask &= ~mask; 544f51dba65751107c930759938775b75531ec1f330Glenn Kasten assert(thisEngine->mInstances[i] == this); 545f51dba65751107c930759938775b75531ec1f330Glenn Kasten thisEngine->mInstances[i] = NULL; 54600d2d554e04ac369367c903dbf53b975355d1bcdGlenn Kasten } 547928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten // avoid a recursive unlock on the engine when destroying the engine itself 548928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten if (thisEngine->mThis != this) { 549928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten interface_unlock_exclusive(thisEngine); 550928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten } 551d48ff338b8338c1e3e54e0f9dcd03567a0aa9de4Glenn Kasten // The destroy hook is called with mutex locked 5528c065779232fdd89abace68d2fc7bea786a010d7Glenn Kasten if (NULL != destroy) { 553d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten (*destroy)(this); 5548c065779232fdd89abace68d2fc7bea786a010d7Glenn Kasten } 555a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten // Call the deinitializer for each currently initialized interface, 55661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten // whether it is implicit, explicit, optional, or dynamically added. 5574597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten // The deinitializers are called in the reverse order that the 5584597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten // initializers were called, so that IObject_deinit is called last. 5594597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten unsigned index = class__->mInterfaceCount; 5604597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten const struct iid_vtable *x = &class__->mInterfaces[index]; 5614597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten SLuint8 *interfaceStateP = &this->mInterfaceStates[index]; 5624597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten for ( ; index > 0; --index) { 5634597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten --x; 564711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten size_t offset = x->mOffset; 565711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten void *thisItf = (char *) this + offset; 5664597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten SLuint32 state = *--interfaceStateP; 567510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten switch (state) { 568510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_UNINITIALIZED: 569510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 570510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_EXPOSED: // quiescent states 571510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_ADDED: 572510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_SUSPENDED: 573711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten // The remove hook is called with mutex locked 574711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten { 575711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten VoidHook remove = MPH_init_table[x->mMPH].mRemove; 576711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten if (NULL != remove) { 577711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten (*remove)(thisItf); 578711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten } 579711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten *interfaceStateP = INTERFACE_INITIALIZED; 580711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten } 581a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten // fall through 582a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten case INTERFACE_INITIALIZED: 583510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten { 58461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten VoidHook deinit = MPH_init_table[x->mMPH].mDeinit; 5858c065779232fdd89abace68d2fc7bea786a010d7Glenn Kasten if (NULL != deinit) { 586a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten (*deinit)(thisItf); 587510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten } 588a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten *interfaceStateP = INTERFACE_UNINITIALIZED; 5898c065779232fdd89abace68d2fc7bea786a010d7Glenn Kasten } 590510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 591510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_ADDING_1: // active states indicate incorrect use of API 592510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_ADDING_1A: 593510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_ADDING_2: 594510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_RESUMING_1: 595510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_RESUMING_1A: 596510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_RESUMING_2: 597510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_REMOVING: 598510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_SUSPENDING: 599a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten SL_LOGE("Object::Destroy(%p) while interface %u active", this, index); 600510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 601510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten default: 602510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten assert(SL_BOOLEAN_FALSE); 603510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 60461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten } 60561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten } 6064597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten // The mutex is unlocked and destroyed by IObject_deinit, which is the last deinitializer 607711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten memset(this, 0x55, class__->mSize); // catch broken applications that continue using interfaces 608711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten // was ifdef USE_DEBUG but safer to do this unconditionally 60961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten free(this); 610ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 6118b8875067dd02b79361abb00c5d65b02a8ae72b0Glenn Kasten if (SL_OBJECTID_ENGINE == class__->mSLObjectID) { 612711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten CEngine_Destroyed((CEngine *) this); 613711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten } 614711332800108ad6e0e594796e5f8db0da3eff402Glenn Kasten 615ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_LEAVE_INTERFACE_VOID 61661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten} 61761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 618ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 6193a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kastenstatic SLresult IObject_SetPriority(SLObjectItf self, SLint32 priority, SLboolean preemptable) 62061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{ 621ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_ENTER_INTERFACE 622ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 623a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#if USE_PROFILES & USE_PROFILES_BASE 62461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IObject *this = (IObject *) self; 62561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten object_lock_exclusive(this); 62661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten this->mPriority = priority; 627d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten this->mPreemptable = SL_BOOLEAN_FALSE != preemptable; // normalize 62861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten object_unlock_exclusive(this); 629ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_SUCCESS; 6307a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten#else 6317a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten result = SL_RESULT_FEATURE_UNSUPPORTED; 6327a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten#endif 633ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 634ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_LEAVE_INTERFACE 63561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten} 63661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 637ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 6383a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kastenstatic SLresult IObject_GetPriority(SLObjectItf self, SLint32 *pPriority, SLboolean *pPreemptable) 63961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{ 640ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_ENTER_INTERFACE 641ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 642a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#if USE_PROFILES & USE_PROFILES_BASE 643ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten if (NULL == pPriority || NULL == pPreemptable) { 644ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_PARAMETER_INVALID; 645ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } else { 646ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten IObject *this = (IObject *) self; 647ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten object_lock_shared(this); 648ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SLint32 priority = this->mPriority; 649ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SLboolean preemptable = this->mPreemptable; 650ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten object_unlock_shared(this); 651ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten *pPriority = priority; 652ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten *pPreemptable = preemptable; 653ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_SUCCESS; 654ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } 6557a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten#else 6567a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten result = SL_RESULT_FEATURE_UNSUPPORTED; 6577a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten#endif 658ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 659ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_LEAVE_INTERFACE 66061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten} 66161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 662ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 66361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenstatic SLresult IObject_SetLossOfControlInterfaces(SLObjectItf self, 66461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten SLint16 numInterfaces, SLInterfaceID *pInterfaceIDs, SLboolean enabled) 66561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{ 666ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_ENTER_INTERFACE 667ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 668a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#if USE_PROFILES & USE_PROFILES_BASE 669ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_SUCCESS; 67061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten if (0 < numInterfaces) { 67161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten SLuint32 i; 672ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten if (NULL == pInterfaceIDs) { 673ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_PARAMETER_INVALID; 674ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } else { 675ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten IObject *this = (IObject *) self; 676ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten const ClassTable *class__ = this->mClass; 677ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten unsigned lossOfControlMask = 0; 6787a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten // The cast is due to a typo in the spec, bug 6482 679ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten for (i = 0; i < (SLuint32) numInterfaces; ++i) { 680ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SLInterfaceID iid = pInterfaceIDs[i]; 681ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten if (NULL == iid) { 682ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_PARAMETER_INVALID; 683ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten goto out; 684ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } 685ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten int MPH, index; 6867a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten // We ignore without error any invalid MPH or index, but spec is unclear 687a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten if ((0 <= (MPH = IID_to_MPH(iid))) && 688a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten // no need to check for an initialization hook 689a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten // (NULL == MPH_init_table[MPH].mInit) || 690a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten (0 <= (index = class__->mMPH_to_index[MPH]))) { 691ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten lossOfControlMask |= (1 << index); 692928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten } 693ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } 694ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten object_lock_exclusive(this); 6958c065779232fdd89abace68d2fc7bea786a010d7Glenn Kasten if (enabled) { 696ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten this->mLossOfControlMask |= lossOfControlMask; 6978c065779232fdd89abace68d2fc7bea786a010d7Glenn Kasten } else { 698ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten this->mLossOfControlMask &= ~lossOfControlMask; 6998c065779232fdd89abace68d2fc7bea786a010d7Glenn Kasten } 700ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten object_unlock_exclusive(this); 70161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten } 70261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten } 703ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kastenout: 7047a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten#else 7057a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten result = SL_RESULT_FEATURE_UNSUPPORTED; 7067a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten#endif 707ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 708ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_LEAVE_INTERFACE 70961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten} 71061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 711ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 71261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenstatic const struct SLObjectItf_ IObject_Itf = { 71361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IObject_Realize, 71461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IObject_Resume, 71561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IObject_GetState, 71661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IObject_GetInterface, 71761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IObject_RegisterCallback, 71861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IObject_AbortAsyncOperation, 71961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IObject_Destroy, 72061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IObject_SetPriority, 72161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IObject_GetPriority, 72261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IObject_SetLossOfControlInterfaces, 72361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}; 72461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 7254597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten 7264597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten/** \brief This must be the first initializer called for an object */ 7274597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten 72861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenvoid IObject_init(void *self) 72961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{ 73061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IObject *this = (IObject *) self; 73161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten this->mItf = &IObject_Itf; 7320b167267bda99b68346045ccab14e810121d5de4Glenn Kasten // initialized in construct: 7330b167267bda99b68346045ccab14e810121d5de4Glenn Kasten // mClass 734ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten // mInstanceID 7350b167267bda99b68346045ccab14e810121d5de4Glenn Kasten // mLossOfControlMask 736ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten // mEngine 737a9a70a4451545034c9263dd55b181f2912534c37Glenn Kasten // mInterfaceStates 73861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten this->mState = SL_OBJECT_STATE_UNREALIZED; 739510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten this->mGottenMask = 1; // IObject 740e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten this->mAttributesMask = 0; 74161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten this->mCallback = NULL; 74261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten this->mContext = NULL; 743a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#if USE_PROFILES & USE_PROFILES_BASE 744d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten this->mPriority = SL_PRIORITY_NORMAL; 74561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten this->mPreemptable = SL_BOOLEAN_FALSE; 7467a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten#endif 747928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten this->mStrongRefCount = 0; 74861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten int ok; 74961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten ok = pthread_mutex_init(&this->mMutex, (const pthread_mutexattr_t *) NULL); 75061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten assert(0 == ok); 751fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten#ifdef USE_DEBUG 752fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten memset(&this->mOwner, 0, sizeof(pthread_t)); 753fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten this->mFile = NULL; 754fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten this->mLine = 0; 755fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten#endif 75661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten ok = pthread_cond_init(&this->mCond, (const pthread_condattr_t *) NULL); 75761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten assert(0 == ok); 75861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten} 7594597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten 7604597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten 7614597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten/** \brief This must be the last deinitializer called for an object */ 7624597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten 7634597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kastenvoid IObject_deinit(void *self) 7644597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten{ 7654597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten IObject *this = (IObject *) self; 7664597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten#ifdef USE_DEBUG 7674597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten assert(pthread_equal(pthread_self(), this->mOwner)); 7684597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten#endif 7694597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten int ok; 7704597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten ok = pthread_cond_destroy(&this->mCond); 7714597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten assert(0 == ok); 7724597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten // equivalent to object_unlock_exclusive, but without the rigmarole 7734597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten ok = pthread_mutex_unlock(&this->mMutex); 7744597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten assert(0 == ok); 7754597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten ok = pthread_mutex_destroy(&this->mMutex); 7764597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten assert(0 == ok); 7774597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten // redundant: this->mState = SL_OBJECT_STATE_UNREALIZED; 7784597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten} 779f51dba65751107c930759938775b75531ec1f330Glenn Kasten 780f51dba65751107c930759938775b75531ec1f330Glenn Kasten 781f51dba65751107c930759938775b75531ec1f330Glenn Kasten/** \brief Publish a new object after it is fully initialized. 782f51dba65751107c930759938775b75531ec1f330Glenn Kasten * Publishing will expose the object to sync thread and debugger, 783f51dba65751107c930759938775b75531ec1f330Glenn Kasten * and make it safe to return the SLObjectItf to the application. 784f51dba65751107c930759938775b75531ec1f330Glenn Kasten */ 785f51dba65751107c930759938775b75531ec1f330Glenn Kasten 786f51dba65751107c930759938775b75531ec1f330Glenn Kastenvoid IObject_Publish(IObject *this) 787f51dba65751107c930759938775b75531ec1f330Glenn Kasten{ 788b0ab2dee391dd2cb257faeaba252ee6ecccc5f03Glenn Kasten IEngine *thisEngine = &this->mEngine->mEngine; 789f51dba65751107c930759938775b75531ec1f330Glenn Kasten interface_lock_exclusive(thisEngine); 790f51dba65751107c930759938775b75531ec1f330Glenn Kasten // construct earlier reserved a pending slot, but did not choose the actual slot number 791f51dba65751107c930759938775b75531ec1f330Glenn Kasten unsigned availMask = ~thisEngine->mInstanceMask; 792f51dba65751107c930759938775b75531ec1f330Glenn Kasten assert(availMask); 793f51dba65751107c930759938775b75531ec1f330Glenn Kasten unsigned i = ctz(availMask); 794f51dba65751107c930759938775b75531ec1f330Glenn Kasten assert(MAX_INSTANCE > i); 795f51dba65751107c930759938775b75531ec1f330Glenn Kasten assert(NULL == thisEngine->mInstances[i]); 796f51dba65751107c930759938775b75531ec1f330Glenn Kasten thisEngine->mInstances[i] = this; 797f51dba65751107c930759938775b75531ec1f330Glenn Kasten thisEngine->mInstanceMask |= 1 << i; 798f51dba65751107c930759938775b75531ec1f330Glenn Kasten // avoid zero as a valid instance ID 799f51dba65751107c930759938775b75531ec1f330Glenn Kasten this->mInstanceID = i + 1; 800f51dba65751107c930759938775b75531ec1f330Glenn Kasten interface_unlock_exclusive(thisEngine); 801f51dba65751107c930759938775b75531ec1f330Glenn Kasten} 802