IObject.c revision ccdf07b17f23b4c040dd3f62478d0965eba804e3
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
2161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenstatic SLresult IObject_Realize(SLObjectItf self, SLboolean async)
2261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
2361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IObject *this = (IObject *) self;
2461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    const ClassTable *class__ = this->mClass;
253d146e0a31f5ee2a7d9807c4e99994084fdd3283Jean-Michel Trivi    AsyncHook realize = class__->mRealize;
263a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten    SLresult result;
273a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten    slObjectCallback callback = NULL;
283a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten    void *context = NULL;
293a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten    SLuint32 state = 0;
3061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    object_lock_exclusive(this);
3161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    if (SL_OBJECT_STATE_UNREALIZED != this->mState) {
3261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        result = SL_RESULT_PRECONDITIONS_VIOLATED;
3361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    } else {
343a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten        // FIXME The realize hook and callback should be asynchronous if requested
35ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten        // FIXME For asynchronous, mark operation pending to prevent duplication
363a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten        result = NULL != realize ? (*realize)(this, async) : SL_RESULT_SUCCESS;
3761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        if (SL_RESULT_SUCCESS == result)
3861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten            this->mState = SL_OBJECT_STATE_REALIZED;
393a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten        // Make a copy of these, so we can call the callback with mutex unlocked
403a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten        if (async) {
413a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten            callback = this->mCallback;
423a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten            context = this->mContext;
433a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten            state = this->mState;
443a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten        }
4561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    }
4661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    object_unlock_exclusive(this);
473a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten    if (NULL != callback)
483a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten        (*callback)(self, context, SL_OBJECT_EVENT_ASYNC_TERMINATION, result, state, NULL);
4961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    return result;
5061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
5161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
5261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenstatic SLresult IObject_Resume(SLObjectItf self, SLboolean async)
5361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
5461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IObject *this = (IObject *) self;
5561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    const ClassTable *class__ = this->mClass;
563a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten    StatusHook resume = class__->mResume;
573a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten    SLresult result;
583a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten    slObjectCallback callback = NULL;
593a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten    void *context = NULL;
603a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten    SLuint32 state = 0;
6161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    object_lock_exclusive(this);
6261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    if (SL_OBJECT_STATE_SUSPENDED != this->mState) {
6361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        result = SL_RESULT_PRECONDITIONS_VIOLATED;
6461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    } else {
653a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten        // FIXME The resume hook and callback should be asynchronous if requested
66ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten        // FIXME For asynchronous, mark operation pending to prevent duplication
673a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten        result = NULL != resume ? (*resume)(this) : SL_RESULT_SUCCESS;
6861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        if (SL_RESULT_SUCCESS == result)
6961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten            this->mState = SL_OBJECT_STATE_REALIZED;
703a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten        // Make a copy of these, so we can call the callback with mutex unlocked
713a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten        if (async) {
723a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten            callback = this->mCallback;
733a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten            context = this->mContext;
743a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten            state = this->mState;
753a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten        }
7661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    }
7761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    object_unlock_exclusive(this);
783a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten    if (NULL != callback)
793a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten        (*callback)(self, context, SL_OBJECT_EVENT_ASYNC_TERMINATION, result, state, NULL);
8061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    return result;
8161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
8261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
8361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenstatic SLresult IObject_GetState(SLObjectItf self, SLuint32 *pState)
8461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
8561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    if (NULL == pState)
8661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        return SL_RESULT_PARAMETER_INVALID;
8761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IObject *this = (IObject *) self;
883a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten    // Note that the state is immediately obsolete, so a peek lock is safe
893a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten    object_lock_peek(this);
9061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    SLuint32 state = this->mState;
913a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten    object_unlock_peek(this);
9261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    *pState = state;
9361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    return SL_RESULT_SUCCESS;
9461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
9561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
963a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kastenstatic SLresult IObject_GetInterface(SLObjectItf self, const SLInterfaceID iid, void *pInterface)
9761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
9861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    if (NULL == pInterface)
9961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        return SL_RESULT_PARAMETER_INVALID;
10061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    SLresult result;
10161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    void *interface = NULL;
10261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    if (NULL == iid)
10361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        result = SL_RESULT_PARAMETER_INVALID;
10461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    else {
10561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        IObject *this = (IObject *) self;
10661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        const ClassTable *class__ = this->mClass;
10761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        int MPH, index;
10861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        if ((0 > (MPH = IID_to_MPH(iid))) ||
10961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten            (0 > (index = class__->mMPH_to_index[MPH])))
11061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten            result = SL_RESULT_FEATURE_UNSUPPORTED;
11161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        else {
11261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten            unsigned mask = 1 << index;
11361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten            object_lock_shared(this);
11461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten            if (SL_OBJECT_STATE_REALIZED != this->mState)
11561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten                result = SL_RESULT_PRECONDITIONS_VIOLATED;
11661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten            else if (!(this->mExposedMask & mask))
11761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten                result = SL_RESULT_FEATURE_UNSUPPORTED;
11861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten            else {
11961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten                // FIXME Should note that interface has been gotten,
12061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten                // so as to detect use of ill-gotten interfaces; be sure
12161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten                // to change the lock to exclusive if that is done
12261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten                interface = (char *) this + class__->mInterfaces[index].mOffset;
12361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten                result = SL_RESULT_SUCCESS;
12461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten            }
12561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten            object_unlock_shared(this);
12661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        }
12761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    }
12861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    *(void **)pInterface = interface;
12961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    return SL_RESULT_SUCCESS;
13061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
13161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
13261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenstatic SLresult IObject_RegisterCallback(SLObjectItf self,
13361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    slObjectCallback callback, void *pContext)
13461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
13561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IObject *this = (IObject *) self;
13661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    object_lock_exclusive(this);
13761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    this->mCallback = callback;
13861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    this->mContext = pContext;
13961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    object_unlock_exclusive(this);
14061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    return SL_RESULT_SUCCESS;
14161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
14261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
14361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenstatic void IObject_AbortAsyncOperation(SLObjectItf self)
14461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
14561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    // FIXME Asynchronous operations are not yet implemented
14661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
14761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
14861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenstatic void IObject_Destroy(SLObjectItf self)
14961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
150ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten    // FIXME Check for dependencies, e.g. destroying an output mix with attached players,
151ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten    //       destroying an engine with extant objects, etc.
1523a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kasten    // FIXME The abort should be atomic w.r.t. destroy, so another async can't be started in window
153ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten    // FIXME Destroy may need to be made asynchronous to permit safe cleanup of resources
154ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten    // FIXME For asynchronous, mark operation pending to prevent duplication
15561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IObject_AbortAsyncOperation(self);
15661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IObject *this = (IObject *) self;
15761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    const ClassTable *class__ = this->mClass;
15861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    VoidHook destroy = class__->mDestroy;
15961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    const struct iid_vtable *x = class__->mInterfaces;
160ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten    // const, no lock needed
161ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten    IEngine *thisEngine = this->mEngine;
162ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten    unsigned i = this->mInstanceID;
163ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten    assert(0 < i && i <= INSTANCE_MAX);
164ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten    --i;
165ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten    // remove object from exposure to sync thread
166ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten    interface_lock_exclusive(thisEngine);
167ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten    assert(0 < thisEngine->mInstanceCount);
168ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten    --thisEngine->mInstanceCount;
169ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten    assert(0 != thisEngine->mInstanceMask);
170ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten    thisEngine->mInstanceMask &= ~(1 << i);
171ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten    assert(thisEngine->mInstances[i] == this);
172ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten    thisEngine->mInstances[i] = NULL;
173ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten    interface_unlock_exclusive(thisEngine);
17461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    object_lock_exclusive(this);
17561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    // Call the deinitializer for each currently exposed interface,
17661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    // whether it is implicit, explicit, optional, or dynamically added.
17761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    unsigned exposedMask = this->mExposedMask;
17861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    for ( ; exposedMask; exposedMask >>= 1, ++x) {
17961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        if (exposedMask & 1) {
18061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten            VoidHook deinit = MPH_init_table[x->mMPH].mDeinit;
18161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten            if (NULL != deinit)
18261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten                (*deinit)((char *) this + x->mOffset);
18361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        }
18461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    }
18561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    if (NULL != destroy)
18661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        (*destroy)(this);
18761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    // redundant: this->mState = SL_OBJECT_STATE_UNREALIZED;
18861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    object_unlock_exclusive(this);
18961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten#ifndef NDEBUG
19061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    memset(this, 0x55, class__->mSize);
19161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten#endif
19261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    free(this);
19361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
19461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
1953a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kastenstatic SLresult IObject_SetPriority(SLObjectItf self, SLint32 priority, SLboolean preemptable)
19661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
19761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IObject *this = (IObject *) self;
19861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    object_lock_exclusive(this);
19961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    this->mPriority = priority;
20061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    this->mPreemptable = preemptable;
20161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    object_unlock_exclusive(this);
20261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    return SL_RESULT_SUCCESS;
20361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
20461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
2053a413f1863daa026ed2b9fc9eac01e1341116cdbGlenn Kastenstatic SLresult IObject_GetPriority(SLObjectItf self, SLint32 *pPriority, SLboolean *pPreemptable)
20661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
20761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    if (NULL == pPriority || NULL == pPreemptable)
20861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        return SL_RESULT_PARAMETER_INVALID;
20961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IObject *this = (IObject *) self;
21061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    object_lock_shared(this);
21161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    SLint32 priority = this->mPriority;
21261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    SLboolean preemptable = this->mPreemptable;
21361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    object_unlock_shared(this);
21461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    *pPriority = priority;
21561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    *pPreemptable = preemptable;
21661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    return SL_RESULT_SUCCESS;
21761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
21861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
21961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenstatic SLresult IObject_SetLossOfControlInterfaces(SLObjectItf self,
22061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    SLint16 numInterfaces, SLInterfaceID *pInterfaceIDs, SLboolean enabled)
22161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
22261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    if (0 < numInterfaces) {
22361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        SLuint32 i;
22461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        if (NULL == pInterfaceIDs)
22561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten            return SL_RESULT_PARAMETER_INVALID;
22661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        IObject *this = (IObject *) self;
22761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        const ClassTable *class__ = this->mClass;
22861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        unsigned lossOfControlMask = 0;
22961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        // FIXME The cast is due to a typo in the spec
23061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        for (i = 0; i < (SLuint32) numInterfaces; ++i) {
23161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten            SLInterfaceID iid = pInterfaceIDs[i];
23261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten            if (NULL == iid)
23361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten                return SL_RESULT_PARAMETER_INVALID;
23461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten            int MPH, index;
23561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten            if (0 <= (MPH = IID_to_MPH(iid)) &&
23661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten                (0 <= (index = class__->mMPH_to_index[MPH])))
23761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten                lossOfControlMask |= (1 << index);
23861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        }
23961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        object_lock_exclusive(this);
24061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        if (enabled)
24161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten            this->mLossOfControlMask |= lossOfControlMask;
24261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        else
24361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten            this->mLossOfControlMask &= ~lossOfControlMask;
24461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        object_unlock_exclusive(this);
24561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    }
24661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    return SL_RESULT_SUCCESS;
24761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
24861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
24961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenstatic const struct SLObjectItf_ IObject_Itf = {
25061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IObject_Realize,
25161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IObject_Resume,
25261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IObject_GetState,
25361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IObject_GetInterface,
25461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IObject_RegisterCallback,
25561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IObject_AbortAsyncOperation,
25661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IObject_Destroy,
25761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IObject_SetPriority,
25861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IObject_GetPriority,
25961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IObject_SetLossOfControlInterfaces,
26061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten};
26161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
26261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenvoid IObject_init(void *self)
26361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
26461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IObject *this = (IObject *) self;
26561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    this->mItf = &IObject_Itf;
2660b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    // initialized in construct:
2670b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    // mClass
268ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten    // mInstanceID
2690b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    // mExposedMask
2700b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    // mLossOfControlMask
271ccdf07b17f23b4c040dd3f62478d0965eba804e3Glenn Kasten    // mEngine
27261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    this->mState = SL_OBJECT_STATE_UNREALIZED;
27361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    this->mCallback = NULL;
27461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    this->mContext = NULL;
27561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    this->mPriority = 0;
27661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    this->mPreemptable = SL_BOOLEAN_FALSE;
27761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    int ok;
27861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    ok = pthread_mutex_init(&this->mMutex, (const pthread_mutexattr_t *) NULL);
27961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    assert(0 == ok);
28061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    ok = pthread_cond_init(&this->mCond, (const pthread_condattr_t *) NULL);
28161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    assert(0 == ok);
28261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
283