IObject.c revision f6f5ceb363286d5ebef2c2e70c8a5aa135d5d1ee
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 100ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten if (async && (SL_OBJECTID_ENGINE != class__->mObjectID)) { 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))) || 326a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten // there must an initialization hook present 327a3080daa505f91df51a808c85ddb37c48745bf7cGlenn 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); 3335e3b06982dbf1eae237cc74326e66d51d3cdd664Glenn Kasten if ((SL_OBJECT_STATE_REALIZED != this->mState) && (INTERFACE_EXPLICIT_PREREALIZE != 3345e3b06982dbf1eae237cc74326e66d51d3cdd664Glenn Kasten class__->mInterfaces[index].mInterface)) { 335b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi // Can't get interface on a suspended/suspending/resuming object 3365e3b06982dbf1eae237cc74326e66d51d3cdd664Glenn Kasten // unless this is an explicit pre-realize interface 337ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_PRECONDITIONS_VIOLATED; 338f6f5ceb363286d5ebef2c2e70c8a5aa135d5d1eeGlenn Kasten } else if ((MPH_MUTESOLO == MPH) && (SL_OBJECTID_AUDIOPLAYER == class__->mObjectID) 339f6f5ceb363286d5ebef2c2e70c8a5aa135d5d1eeGlenn Kasten && (1 == ((CAudioPlayer *) this)->mNumChannels)) { 340f6f5ceb363286d5ebef2c2e70c8a5aa135d5d1eeGlenn Kasten // Can't get the MuteSolo interface of an audio player if the channel count is 341f6f5ceb363286d5ebef2c2e70c8a5aa135d5d1eeGlenn Kasten // mono, but _can_ get the MuteSolo interface if the channel count is unknown 342f6f5ceb363286d5ebef2c2e70c8a5aa135d5d1eeGlenn Kasten result = SL_RESULT_FEATURE_UNSUPPORTED; 343ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } else { 344ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten switch (this->mInterfaceStates[index]) { 345ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten case INTERFACE_EXPOSED: 346ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten case INTERFACE_ADDED: 347e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten interface = (char *) this + class__->mInterfaces[index].mOffset; 348ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten // Note that interface has been gotten, 349ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten // for debugger and to detect incorrect use of interfaces 350e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten if (!(this->mGottenMask & mask)) { 351e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten this->mGottenMask |= mask; 352e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten ((size_t *) interface)[0] ^= ~0; 353e5d006b298ce7683d66f7ec86136403cf5fb20d6Glenn Kasten } 354ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_SUCCESS; 355ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten break; 356ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten // Can't get interface if uninitialized/suspend(ed,ing)/resuming/adding/removing 357ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten default: 358ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_FEATURE_UNSUPPORTED; 359ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten break; 360ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } 361510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten } 362ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten object_unlock_exclusive(this); 36361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten } 36461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten } 365ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten *(void **)pInterface = interface; 36661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten } 367ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 368ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_LEAVE_INTERFACE 36961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten} 37061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 371ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 37261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenstatic SLresult IObject_RegisterCallback(SLObjectItf self, 37361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten slObjectCallback callback, void *pContext) 37461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{ 375ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_ENTER_INTERFACE 376ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 37761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IObject *this = (IObject *) self; 37861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten object_lock_exclusive(this); 37961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten this->mCallback = callback; 38061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten this->mContext = pContext; 38161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten object_unlock_exclusive(this); 382ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_SUCCESS; 383ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 384ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_LEAVE_INTERFACE 38561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten} 38661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 387ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 388928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten/** \brief This is internal common code for Abort and Destroy. 389928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten * Note: called with mutex unlocked, and returns with mutex locked. 390928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten */ 391510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 392928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kastenstatic void Abort_internal(IObject *this) 393510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten{ 394510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten const ClassTable *class__ = this->mClass; 395928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten bool anyAsync = false; 396510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten object_lock_exclusive(this); 397928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten 398510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // Abort asynchronous operations on the object 399510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten switch (this->mState) { 400510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case SL_OBJECT_STATE_REALIZING_1: // Realize 401510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten this->mState = SL_OBJECT_STATE_REALIZING_1A; 402928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten anyAsync = true; 403510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 404510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case SL_OBJECT_STATE_RESUMING_1: // Resume 405510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten this->mState = SL_OBJECT_STATE_RESUMING_1A; 406928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten anyAsync = true; 407928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten break; 408928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten case SL_OBJECT_STATE_REALIZING_1A: // Realize 409928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten case SL_OBJECT_STATE_REALIZING_2: 410928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten case SL_OBJECT_STATE_RESUMING_1A: // Resume 411928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten case SL_OBJECT_STATE_RESUMING_2: 412928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten anyAsync = true; 413928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten break; 414928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten case SL_OBJECT_STATE_DESTROYING: 415928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten assert(false); 416510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 417510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten default: 418510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 419510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten } 420928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten 421510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // Abort asynchronous operations on interfaces 422510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten SLuint8 *interfaceStateP = this->mInterfaceStates; 423510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten unsigned index; 424510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten for (index = 0; index < class__->mInterfaceCount; ++index, ++interfaceStateP) { 425510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten switch (*interfaceStateP) { 426510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_ADDING_1: // AddInterface 427510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten *interfaceStateP = INTERFACE_ADDING_1A; 428928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten anyAsync = true; 429510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 430510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_RESUMING_1: // ResumeInterface 431510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten *interfaceStateP = INTERFACE_RESUMING_1A; 432928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten anyAsync = true; 433928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten break; 434928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten case INTERFACE_ADDING_1A: // AddInterface 435928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten case INTERFACE_ADDING_2: 436928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten case INTERFACE_RESUMING_1A: // ResumeInterface 437928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten case INTERFACE_RESUMING_2: 438928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten case INTERFACE_REMOVING: // RemoveInterface is sync, but partially without a mutex lock 439928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten anyAsync = true; 440510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 441510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten default: 442510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 443510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten } 444510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten } 445928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten 446928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten // Wait until all asynchronous operations either complete normally or recognize the abort 447928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten while (anyAsync) { 448928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten object_unlock_exclusive(this); 449928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten // FIXME should use condition variable instead of polling 450928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten usleep(20000); 451928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten anyAsync = false; 452928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten object_lock_exclusive(this); 453928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten switch (this->mState) { 454928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten case SL_OBJECT_STATE_REALIZING_1: // state 1 means it cycled during the usleep window 455928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten case SL_OBJECT_STATE_RESUMING_1: 456928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten case SL_OBJECT_STATE_REALIZING_1A: 457928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten case SL_OBJECT_STATE_REALIZING_2: 458928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten case SL_OBJECT_STATE_RESUMING_1A: 459928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten case SL_OBJECT_STATE_RESUMING_2: 460928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten anyAsync = true; 461928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten break; 462928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten case SL_OBJECT_STATE_DESTROYING: 463928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten assert(false); 464928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten break; 465928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten default: 466928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten break; 467928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten } 468928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten interfaceStateP = this->mInterfaceStates; 469928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten for (index = 0; index < class__->mInterfaceCount; ++index, ++interfaceStateP) { 470928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten switch (*interfaceStateP) { 471928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten case INTERFACE_ADDING_1: // state 1 means it cycled during the usleep window 472928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten case INTERFACE_RESUMING_1: 473928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten case INTERFACE_ADDING_1A: 474928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten case INTERFACE_ADDING_2: 475928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten case INTERFACE_RESUMING_1A: 476928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten case INTERFACE_RESUMING_2: 477928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten case INTERFACE_REMOVING: 478928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten anyAsync = true; 479928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten break; 480928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten default: 481928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten break; 482928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten } 483928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten } 484928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten } 485928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten 486928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten // At this point there are no pending asynchronous operations 487510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten} 488510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten 489ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 49061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenstatic void IObject_AbortAsyncOperation(SLObjectItf self) 49161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{ 492ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_ENTER_INTERFACE_VOID 493ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 494510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten IObject *this = (IObject *) self; 495928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten Abort_internal(this); 496928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten object_unlock_exclusive(this); 497ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 498ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_LEAVE_INTERFACE_VOID 49961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten} 50061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 501ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 502f51dba65751107c930759938775b75531ec1f330Glenn Kastenvoid IObject_Destroy(SLObjectItf self) 50361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{ 504ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_ENTER_INTERFACE_VOID 505ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 50661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IObject *this = (IObject *) self; 507928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten // mutex is unlocked 508928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten Abort_internal(this); 509928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten // mutex is locked 51061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten const ClassTable *class__ = this->mClass; 511928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten BoolHook preDestroy = class__->mPreDestroy; 512928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten // The pre-destroy hook is called with mutex locked, and should block until it is safe to 513928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten // destroy. It is OK to unlock the mutex temporarily, as it long as it re-locks the mutex 514928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten // before returning. 515928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten if (NULL != preDestroy) { 516928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten bool okToDestroy = (*preDestroy)(this); 517928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten if (!okToDestroy) { 518928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten object_unlock_exclusive(this); 519928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten // unfortunately Destroy doesn't return a result 520928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten SL_LOGE("Object::Destroy(%p) not allowed", this); 521928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten SL_LEAVE_INTERFACE_VOID 522928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten } 523928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten } 524928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten this->mState = SL_OBJECT_STATE_DESTROYING; 52561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten VoidHook destroy = class__->mDestroy; 526ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten // const, no lock needed 527ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten IEngine *thisEngine = this->mEngine; 528ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten unsigned i = this->mInstanceID; 529f51dba65751107c930759938775b75531ec1f330Glenn Kasten assert(MAX_INSTANCE >= i); 530928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten // avoid a recursive lock on the engine when destroying the engine itself 531928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten if (thisEngine->mThis != this) { 532928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten interface_lock_exclusive(thisEngine); 533928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten } 534f51dba65751107c930759938775b75531ec1f330Glenn Kasten // An unpublished object has a slot reserved, but the ID hasn't been chosen yet 535ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten assert(0 < thisEngine->mInstanceCount); 536ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten --thisEngine->mInstanceCount; 537f51dba65751107c930759938775b75531ec1f330Glenn Kasten // If object is published, then remove it from exposure to sync thread and debugger 538f51dba65751107c930759938775b75531ec1f330Glenn Kasten if (0 != i) { 539f51dba65751107c930759938775b75531ec1f330Glenn Kasten --i; 540f51dba65751107c930759938775b75531ec1f330Glenn Kasten assert(0 != thisEngine->mInstanceMask); 541f51dba65751107c930759938775b75531ec1f330Glenn Kasten thisEngine->mInstanceMask &= ~(1 << i); 542f51dba65751107c930759938775b75531ec1f330Glenn Kasten assert(thisEngine->mInstances[i] == this); 543f51dba65751107c930759938775b75531ec1f330Glenn Kasten thisEngine->mInstances[i] = NULL; 54400d2d554e04ac369367c903dbf53b975355d1bcdGlenn Kasten } 545928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten // avoid a recursive unlock on the engine when destroying the engine itself 546928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten if (thisEngine->mThis != this) { 547928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten interface_unlock_exclusive(thisEngine); 548928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten } 549d48ff338b8338c1e3e54e0f9dcd03567a0aa9de4Glenn Kasten // The destroy hook is called with mutex locked 5508c065779232fdd89abace68d2fc7bea786a010d7Glenn Kasten if (NULL != destroy) { 551d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten (*destroy)(this); 5528c065779232fdd89abace68d2fc7bea786a010d7Glenn Kasten } 55361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten // Call the deinitializer for each currently exposed interface, 55461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten // whether it is implicit, explicit, optional, or dynamically added. 5554597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten // The deinitializers are called in the reverse order that the 5564597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten // initializers were called, so that IObject_deinit is called last. 557510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten unsigned incorrect = 0; 5584597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten unsigned index = class__->mInterfaceCount; 5594597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten const struct iid_vtable *x = &class__->mInterfaces[index]; 5604597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten SLuint8 *interfaceStateP = &this->mInterfaceStates[index]; 5614597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten for ( ; index > 0; --index) { 5624597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten --x; 5634597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten SLuint32 state = *--interfaceStateP; 564510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten switch (state) { 565510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_UNINITIALIZED: 566510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 567510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_EXPOSED: // quiescent states 568510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_ADDED: 569510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_SUSPENDED: 570510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten { 57161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten VoidHook deinit = MPH_init_table[x->mMPH].mDeinit; 5728c065779232fdd89abace68d2fc7bea786a010d7Glenn Kasten if (NULL != deinit) { 57361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten (*deinit)((char *) this + x->mOffset); 574510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten } 5758c065779232fdd89abace68d2fc7bea786a010d7Glenn Kasten } 576510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 577510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_ADDING_1: // active states indicate incorrect use of API 578510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_ADDING_1A: 579510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_ADDING_2: 580510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_RESUMING_1: 581510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_RESUMING_1A: 582510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_RESUMING_2: 583510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_REMOVING: 584510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten case INTERFACE_SUSPENDING: 585510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten ++incorrect; 586510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 587510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten default: 588510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten assert(SL_BOOLEAN_FALSE); 589510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten break; 59061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten } 59161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten } 5924597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten // The mutex is unlocked and destroyed by IObject_deinit, which is the last deinitializer 593fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten#ifdef USE_DEBUG 59461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten memset(this, 0x55, class__->mSize); 59561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten#endif 59661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten free(this); 597510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // one or more interfaces was actively changing at time of Destroy 598510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten assert(incorrect == 0); 599ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 600ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_LEAVE_INTERFACE_VOID 60161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten} 60261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 603ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 6043a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kastenstatic SLresult IObject_SetPriority(SLObjectItf self, SLint32 priority, SLboolean preemptable) 60561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{ 606ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_ENTER_INTERFACE 607ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 608a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#if USE_PROFILES & USE_PROFILES_BASE 60961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IObject *this = (IObject *) self; 61061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten object_lock_exclusive(this); 61161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten this->mPriority = priority; 612d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten this->mPreemptable = SL_BOOLEAN_FALSE != preemptable; // normalize 61361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten object_unlock_exclusive(this); 614ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_SUCCESS; 6157a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten#else 6167a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten result = SL_RESULT_FEATURE_UNSUPPORTED; 6177a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten#endif 618ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 619ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_LEAVE_INTERFACE 62061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten} 62161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 622ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 6233a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kastenstatic SLresult IObject_GetPriority(SLObjectItf self, SLint32 *pPriority, SLboolean *pPreemptable) 62461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{ 625ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_ENTER_INTERFACE 626ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 627a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#if USE_PROFILES & USE_PROFILES_BASE 628ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten if (NULL == pPriority || NULL == pPreemptable) { 629ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_PARAMETER_INVALID; 630ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } else { 631ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten IObject *this = (IObject *) self; 632ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten object_lock_shared(this); 633ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SLint32 priority = this->mPriority; 634ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SLboolean preemptable = this->mPreemptable; 635ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten object_unlock_shared(this); 636ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten *pPriority = priority; 637ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten *pPreemptable = preemptable; 638ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_SUCCESS; 639ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } 6407a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten#else 6417a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten result = SL_RESULT_FEATURE_UNSUPPORTED; 6427a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten#endif 643ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 644ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_LEAVE_INTERFACE 64561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten} 64661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 647ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 64861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenstatic SLresult IObject_SetLossOfControlInterfaces(SLObjectItf self, 64961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten SLint16 numInterfaces, SLInterfaceID *pInterfaceIDs, SLboolean enabled) 65061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{ 651ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_ENTER_INTERFACE 652ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 653a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#if USE_PROFILES & USE_PROFILES_BASE 654ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_SUCCESS; 65561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten if (0 < numInterfaces) { 65661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten SLuint32 i; 657ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten if (NULL == pInterfaceIDs) { 658ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_PARAMETER_INVALID; 659ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } else { 660ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten IObject *this = (IObject *) self; 661ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten const ClassTable *class__ = this->mClass; 662ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten unsigned lossOfControlMask = 0; 6637a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten // The cast is due to a typo in the spec, bug 6482 664ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten for (i = 0; i < (SLuint32) numInterfaces; ++i) { 665ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SLInterfaceID iid = pInterfaceIDs[i]; 666ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten if (NULL == iid) { 667ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten result = SL_RESULT_PARAMETER_INVALID; 668ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten goto out; 669ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } 670ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten int MPH, index; 6717a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten // We ignore without error any invalid MPH or index, but spec is unclear 672a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten if ((0 <= (MPH = IID_to_MPH(iid))) && 673a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten // no need to check for an initialization hook 674a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten // (NULL == MPH_init_table[MPH].mInit) || 675a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten (0 <= (index = class__->mMPH_to_index[MPH]))) { 676ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten lossOfControlMask |= (1 << index); 677928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten } 678ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten } 679ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten object_lock_exclusive(this); 6808c065779232fdd89abace68d2fc7bea786a010d7Glenn Kasten if (enabled) { 681ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten this->mLossOfControlMask |= lossOfControlMask; 6828c065779232fdd89abace68d2fc7bea786a010d7Glenn Kasten } else { 683ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten this->mLossOfControlMask &= ~lossOfControlMask; 6848c065779232fdd89abace68d2fc7bea786a010d7Glenn Kasten } 685ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten object_unlock_exclusive(this); 68661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten } 68761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten } 688ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kastenout: 6897a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten#else 6907a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten result = SL_RESULT_FEATURE_UNSUPPORTED; 6917a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten#endif 692ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 693ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten SL_LEAVE_INTERFACE 69461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten} 69561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 696ed46c29d6a09112dbbf584c82953f63289596fd6Glenn Kasten 69761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenstatic const struct SLObjectItf_ IObject_Itf = { 69861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IObject_Realize, 69961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IObject_Resume, 70061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IObject_GetState, 70161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IObject_GetInterface, 70261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IObject_RegisterCallback, 70361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IObject_AbortAsyncOperation, 70461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IObject_Destroy, 70561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IObject_SetPriority, 70661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IObject_GetPriority, 70761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IObject_SetLossOfControlInterfaces, 70861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}; 70961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten 7104597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten 7114597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten/** \brief This must be the first initializer called for an object */ 7124597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten 71361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenvoid IObject_init(void *self) 71461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{ 71561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten IObject *this = (IObject *) self; 71661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten this->mItf = &IObject_Itf; 7170b167267bda99b68346045ccab14e810121d5de4Glenn Kasten // initialized in construct: 7180b167267bda99b68346045ccab14e810121d5de4Glenn Kasten // mClass 719ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten // mInstanceID 7200b167267bda99b68346045ccab14e810121d5de4Glenn Kasten // mLossOfControlMask 721ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten // mEngine 722510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten // mInstanceStates 72361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten this->mState = SL_OBJECT_STATE_UNREALIZED; 724510f3671f716f6835282e4b0fd0275c20e9dadd8Glenn Kasten this->mGottenMask = 1; // IObject 725e5bf0d2c9531a7064eb3ddcafaf93ac1b0974037Glenn Kasten this->mAttributesMask = 0; 72661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten this->mCallback = NULL; 72761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten this->mContext = NULL; 728a3080daa505f91df51a808c85ddb37c48745bf7cGlenn Kasten#if USE_PROFILES & USE_PROFILES_BASE 729d2a7f0d6883a6d3835642e7b282f05ed1c54fe63Glenn Kasten this->mPriority = SL_PRIORITY_NORMAL; 73061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten this->mPreemptable = SL_BOOLEAN_FALSE; 7317a79f519d89eb0e1a5b3f4005484b16d6854d7e2Glenn Kasten#endif 732928ea4ffff40c82987cfb1ac9e3095fdc6968709Glenn Kasten this->mStrongRefCount = 0; 73361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten int ok; 73461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten ok = pthread_mutex_init(&this->mMutex, (const pthread_mutexattr_t *) NULL); 73561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten assert(0 == ok); 736fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten#ifdef USE_DEBUG 737fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten memset(&this->mOwner, 0, sizeof(pthread_t)); 738fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten this->mFile = NULL; 739fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten this->mLine = 0; 740fe96fa06360516c60490c7a697e1148017b4c1b2Glenn Kasten#endif 74161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten ok = pthread_cond_init(&this->mCond, (const pthread_condattr_t *) NULL); 74261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten assert(0 == ok); 74361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten} 7444597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten 7454597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten 7464597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten/** \brief This must be the last deinitializer called for an object */ 7474597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten 7484597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kastenvoid IObject_deinit(void *self) 7494597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten{ 7504597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten IObject *this = (IObject *) self; 7514597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten#ifdef USE_DEBUG 7524597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten assert(pthread_equal(pthread_self(), this->mOwner)); 7534597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten#endif 7544597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten int ok; 7554597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten ok = pthread_cond_destroy(&this->mCond); 7564597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten assert(0 == ok); 7574597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten // equivalent to object_unlock_exclusive, but without the rigmarole 7584597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten ok = pthread_mutex_unlock(&this->mMutex); 7594597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten assert(0 == ok); 7604597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten ok = pthread_mutex_destroy(&this->mMutex); 7614597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten assert(0 == ok); 7624597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten // redundant: this->mState = SL_OBJECT_STATE_UNREALIZED; 7634597a7427b697df31d0bbf4c2040806d0c27b6e0Glenn Kasten} 764f51dba65751107c930759938775b75531ec1f330Glenn Kasten 765f51dba65751107c930759938775b75531ec1f330Glenn Kasten 766f51dba65751107c930759938775b75531ec1f330Glenn Kasten/** \brief Publish a new object after it is fully initialized. 767f51dba65751107c930759938775b75531ec1f330Glenn Kasten * Publishing will expose the object to sync thread and debugger, 768f51dba65751107c930759938775b75531ec1f330Glenn Kasten * and make it safe to return the SLObjectItf to the application. 769f51dba65751107c930759938775b75531ec1f330Glenn Kasten */ 770f51dba65751107c930759938775b75531ec1f330Glenn Kasten 771f51dba65751107c930759938775b75531ec1f330Glenn Kastenvoid IObject_Publish(IObject *this) 772f51dba65751107c930759938775b75531ec1f330Glenn Kasten{ 773f51dba65751107c930759938775b75531ec1f330Glenn Kasten IEngine *thisEngine = this->mEngine; 774f51dba65751107c930759938775b75531ec1f330Glenn Kasten interface_lock_exclusive(thisEngine); 775f51dba65751107c930759938775b75531ec1f330Glenn Kasten // construct earlier reserved a pending slot, but did not choose the actual slot number 776f51dba65751107c930759938775b75531ec1f330Glenn Kasten unsigned availMask = ~thisEngine->mInstanceMask; 777f51dba65751107c930759938775b75531ec1f330Glenn Kasten assert(availMask); 778f51dba65751107c930759938775b75531ec1f330Glenn Kasten unsigned i = ctz(availMask); 779f51dba65751107c930759938775b75531ec1f330Glenn Kasten assert(MAX_INSTANCE > i); 780f51dba65751107c930759938775b75531ec1f330Glenn Kasten assert(NULL == thisEngine->mInstances[i]); 781f51dba65751107c930759938775b75531ec1f330Glenn Kasten thisEngine->mInstances[i] = this; 782f51dba65751107c930759938775b75531ec1f330Glenn Kasten thisEngine->mInstanceMask |= 1 << i; 783f51dba65751107c930759938775b75531ec1f330Glenn Kasten // avoid zero as a valid instance ID 784f51dba65751107c930759938775b75531ec1f330Glenn Kasten this->mInstanceID = i + 1; 785f51dba65751107c930759938775b75531ec1f330Glenn Kasten interface_unlock_exclusive(thisEngine); 786f51dba65751107c930759938775b75531ec1f330Glenn Kasten} 787