IObject.c revision 0b167267bda99b68346045ccab14e810121d5de4
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;
2561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    StatusHook realize = class__->mRealize;
2661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    SLresult result = SL_RESULT_SUCCESS;
2761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    object_lock_exclusive(this);
2861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    // FIXME The realize hook and callback should be asynchronous if requested
2961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    if (SL_OBJECT_STATE_UNREALIZED != this->mState) {
3061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        result = SL_RESULT_PRECONDITIONS_VIOLATED;
3161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    } else {
3261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        if (NULL != realize)
3361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten            result = (*realize)(this);
3461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        if (SL_RESULT_SUCCESS == result)
3561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten            this->mState = SL_OBJECT_STATE_REALIZED;
3661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        // FIXME callback should not run with mutex lock
3761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        if (async && (NULL != this->mCallback))
3861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten            (*this->mCallback)(self, this->mContext,
3961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten            SL_OBJECT_EVENT_ASYNC_TERMINATION, result, this->mState, NULL);
4061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    }
4161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    object_unlock_exclusive(this);
4261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    return result;
4361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
4461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
4561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenstatic SLresult IObject_Resume(SLObjectItf self, SLboolean async)
4661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
4761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IObject *this = (IObject *) self;
4861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    const ClassTable *class__ = this->mClass;
4961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    StatusHook resume = class__->mResume;
5061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    SLresult result = SL_RESULT_SUCCESS;
5161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    object_lock_exclusive(this);
5261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    // FIXME The resume hook and callback should be asynchronous if requested
5361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    if (SL_OBJECT_STATE_SUSPENDED != this->mState) {
5461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        result = SL_RESULT_PRECONDITIONS_VIOLATED;
5561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    } else {
5661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        if (NULL != resume)
5761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten            result = (*resume)(this);
5861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        if (SL_RESULT_SUCCESS == result)
5961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten            this->mState = SL_OBJECT_STATE_REALIZED;
6061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        // FIXME callback should not run with mutex lock
6161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        if (async && (NULL != this->mCallback))
6261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten            (*this->mCallback)(self, this->mContext,
6361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten            SL_OBJECT_EVENT_ASYNC_TERMINATION, result, this->mState, NULL);
6461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    }
6561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    object_unlock_exclusive(this);
6661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    return result;
6761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
6861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
6961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenstatic SLresult IObject_GetState(SLObjectItf self, SLuint32 *pState)
7061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
7161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    if (NULL == pState)
7261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        return SL_RESULT_PARAMETER_INVALID;
7361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IObject *this = (IObject *) self;
7461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    // FIXME Investigate what it would take to change to a peek lock
7561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    object_lock_shared(this);
7661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    SLuint32 state = this->mState;
7761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    object_unlock_shared(this);
7861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    *pState = state;
7961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    return SL_RESULT_SUCCESS;
8061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
8161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
8261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenstatic SLresult IObject_GetInterface(SLObjectItf self, const SLInterfaceID iid,
8361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    void *pInterface)
8461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
8561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    if (NULL == pInterface)
8661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        return SL_RESULT_PARAMETER_INVALID;
8761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    SLresult result;
8861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    void *interface = NULL;
8961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    if (NULL == iid)
9061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        result = SL_RESULT_PARAMETER_INVALID;
9161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    else {
9261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        IObject *this = (IObject *) self;
9361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        const ClassTable *class__ = this->mClass;
9461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        int MPH, index;
9561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        if ((0 > (MPH = IID_to_MPH(iid))) ||
9661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten            (0 > (index = class__->mMPH_to_index[MPH])))
9761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten            result = SL_RESULT_FEATURE_UNSUPPORTED;
9861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        else {
9961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten            unsigned mask = 1 << index;
10061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten            object_lock_shared(this);
10161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten            if (SL_OBJECT_STATE_REALIZED != this->mState)
10261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten                result = SL_RESULT_PRECONDITIONS_VIOLATED;
10361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten            else if (!(this->mExposedMask & mask))
10461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten                result = SL_RESULT_FEATURE_UNSUPPORTED;
10561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten            else {
10661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten                // FIXME Should note that interface has been gotten,
10761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten                // so as to detect use of ill-gotten interfaces; be sure
10861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten                // to change the lock to exclusive if that is done
10961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten                interface = (char *) this + class__->mInterfaces[index].mOffset;
11061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten                result = SL_RESULT_SUCCESS;
11161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten            }
11261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten            object_unlock_shared(this);
11361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        }
11461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    }
11561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    *(void **)pInterface = interface;
11661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    return SL_RESULT_SUCCESS;
11761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
11861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
11961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenstatic SLresult IObject_RegisterCallback(SLObjectItf self,
12061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    slObjectCallback callback, void *pContext)
12161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
12261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IObject *this = (IObject *) self;
12361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    // FIXME This could be a poke lock, if we had atomic double-word load/store
12461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    object_lock_exclusive(this);
12561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    this->mCallback = callback;
12661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    this->mContext = pContext;
12761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    object_unlock_exclusive(this);
12861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    return SL_RESULT_SUCCESS;
12961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
13061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
13161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenstatic void IObject_AbortAsyncOperation(SLObjectItf self)
13261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
13361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    // FIXME Asynchronous operations are not yet implemented
13461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
13561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
13661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenstatic void IObject_Destroy(SLObjectItf self)
13761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
13861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IObject_AbortAsyncOperation(self);
13961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IObject *this = (IObject *) self;
14061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    const ClassTable *class__ = this->mClass;
14161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    VoidHook destroy = class__->mDestroy;
14261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    const struct iid_vtable *x = class__->mInterfaces;
14361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    object_lock_exclusive(this);
14461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    // Call the deinitializer for each currently exposed interface,
14561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    // whether it is implicit, explicit, optional, or dynamically added.
14661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    unsigned exposedMask = this->mExposedMask;
14761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    for ( ; exposedMask; exposedMask >>= 1, ++x) {
14861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        if (exposedMask & 1) {
14961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten            VoidHook deinit = MPH_init_table[x->mMPH].mDeinit;
15061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten            if (NULL != deinit)
15161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten                (*deinit)((char *) this + x->mOffset);
15261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        }
15361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    }
15461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    if (NULL != destroy)
15561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        (*destroy)(this);
15661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    // redundant: this->mState = SL_OBJECT_STATE_UNREALIZED;
15761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    object_unlock_exclusive(this);
15861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten#ifndef NDEBUG
15961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    memset(this, 0x55, class__->mSize);
16061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten#endif
16161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    free(this);
16261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
16361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
16461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenstatic SLresult IObject_SetPriority(SLObjectItf self, SLint32 priority,
16561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    SLboolean preemptable)
16661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
16761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IObject *this = (IObject *) self;
16861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    object_lock_exclusive(this);
16961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    this->mPriority = priority;
17061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    this->mPreemptable = preemptable;
17161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    object_unlock_exclusive(this);
17261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    return SL_RESULT_SUCCESS;
17361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
17461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
17561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenstatic SLresult IObject_GetPriority(SLObjectItf self, SLint32 *pPriority,
17661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    SLboolean *pPreemptable)
17761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
17861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    if (NULL == pPriority || NULL == pPreemptable)
17961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        return SL_RESULT_PARAMETER_INVALID;
18061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IObject *this = (IObject *) self;
18161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    object_lock_shared(this);
18261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    SLint32 priority = this->mPriority;
18361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    SLboolean preemptable = this->mPreemptable;
18461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    object_unlock_shared(this);
18561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    *pPriority = priority;
18661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    *pPreemptable = preemptable;
18761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    return SL_RESULT_SUCCESS;
18861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
18961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
19061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenstatic SLresult IObject_SetLossOfControlInterfaces(SLObjectItf self,
19161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    SLint16 numInterfaces, SLInterfaceID *pInterfaceIDs, SLboolean enabled)
19261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
19361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    if (0 < numInterfaces) {
19461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        SLuint32 i;
19561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        if (NULL == pInterfaceIDs)
19661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten            return SL_RESULT_PARAMETER_INVALID;
19761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        IObject *this = (IObject *) self;
19861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        const ClassTable *class__ = this->mClass;
19961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        unsigned lossOfControlMask = 0;
20061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        // FIXME The cast is due to a typo in the spec
20161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        for (i = 0; i < (SLuint32) numInterfaces; ++i) {
20261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten            SLInterfaceID iid = pInterfaceIDs[i];
20361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten            if (NULL == iid)
20461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten                return SL_RESULT_PARAMETER_INVALID;
20561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten            int MPH, index;
20661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten            if (0 <= (MPH = IID_to_MPH(iid)) &&
20761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten                (0 <= (index = class__->mMPH_to_index[MPH])))
20861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten                lossOfControlMask |= (1 << index);
20961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        }
21061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        object_lock_exclusive(this);
21161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        if (enabled)
21261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten            this->mLossOfControlMask |= lossOfControlMask;
21361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        else
21461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten            this->mLossOfControlMask &= ~lossOfControlMask;
21561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten        object_unlock_exclusive(this);
21661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    }
21761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    return SL_RESULT_SUCCESS;
21861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
21961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
22061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenstatic const struct SLObjectItf_ IObject_Itf = {
22161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IObject_Realize,
22261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IObject_Resume,
22361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IObject_GetState,
22461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IObject_GetInterface,
22561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IObject_RegisterCallback,
22661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IObject_AbortAsyncOperation,
22761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IObject_Destroy,
22861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IObject_SetPriority,
22961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IObject_GetPriority,
23061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IObject_SetLossOfControlInterfaces,
23161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten};
23261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten
23361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kastenvoid IObject_init(void *self)
23461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten{
23561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    IObject *this = (IObject *) self;
23661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    this->mItf = &IObject_Itf;
2370b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    // initialized in construct:
2380b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    // mClass
2390b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    // mExposedMask
2400b167267bda99b68346045ccab14e810121d5de4Glenn Kasten    // mLossOfControlMask
24161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    this->mState = SL_OBJECT_STATE_UNREALIZED;
24261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten#ifndef NDEBUG
24361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    this->mCallback = NULL;
24461ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    this->mContext = NULL;
24561ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    this->mPriority = 0;
24661ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    this->mPreemptable = SL_BOOLEAN_FALSE;
24761ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten#endif
24861ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    int ok;
24961ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    ok = pthread_mutex_init(&this->mMutex, (const pthread_mutexattr_t *) NULL);
25061ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    assert(0 == ok);
25161ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    ok = pthread_cond_init(&this->mCond, (const pthread_condattr_t *) NULL);
25261ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten    assert(0 == ok);
25361ac0ade16f84d877dfd8d0e984eb203d4a2901dGlenn Kasten}
254