khronosfws/openmax_al/src/common/xaobjectitf.c
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Fri, 14 May 2010 16:22:35 +0300
changeset 16 43d09473c595
parent 12 5a06f39ad45b
child 25 6f7ceef7b1d1
permissions -rw-r--r--
Revision: 201017 Kit: 201019

/*
* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description: 
*
*/

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

#include "xaobjectitf.h"

/**
 * Base interface XAObjectItf implementation
 */
XAresult XAObjectItfImpl_Realize(XAObjectItf self, XAboolean async)
{
    XAObjectItfImpl* pObjImp = (XAObjectItfImpl*)(*self);
    XAresult retval = XA_RESULT_SUCCESS;

    DEBUG_API("->XAObjectItfImpl_Realize");
    if( !pObjImp || pObjImp != pObjImp->self)
    {
        DEBUG_ERR("XA_RESULT_PARAMETER_INVALID");
        DEBUG_API("<-XAObjectItfImpl_Realize");
        /* invalid parameter */
        return XA_RESULT_PARAMETER_INVALID;
    }

    if( async )
    {
        /* invoke asynchronously */
        if( !pObjImp->callBack )
        {
            retval = XA_RESULT_PARAMETER_INVALID;
        }
        else
        {
            /* check if another async operation is processed */
            if(pObjImp->asyncOngoing)
            {
                /* abort ongoing operation */
                XAImpl_CancelThread(pObjImp->asyncThr);
            }
            pObjImp->asyncOngoing = XA_BOOLEAN_TRUE;
            if(XAImpl_StartThread(pObjImp->asyncThr, NULL,
                    XAObjectItfImpl_AsyncRealize,(void*)(self)))
            {
                pObjImp->asyncOngoing = XA_BOOLEAN_FALSE;
                retval = XA_RESULT_RESOURCE_ERROR;
            }
            else
            {
                retval = XA_RESULT_SUCCESS;
            }
        }
    }
    else
    {
        /* Check if the object is in unrealized state */
        if(pObjImp->state != XA_OBJECT_STATE_UNREALIZED)
        {
            DEBUG_ERR("XA_RESULT_PRECONDITIONS_VIOLATED");
            DEBUG_API("<-XAObjectItfImpl_Realize");
            return XA_RESULT_PRECONDITIONS_VIOLATED;
        }
        /* invoke synchronously */
        if( pObjImp->DoRealizeImpl )
        {
            retval = pObjImp->DoRealizeImpl(self);
        }
    }
    DEBUG_API("<-XAObjectItfImpl_Realize");
    return retval;
}

XAresult XAObjectItfImpl_Resume(XAObjectItf self, XAboolean async)
{
    XAresult retval = XA_RESULT_SUCCESS;
    XAObjectItfImpl* pObjImp = (XAObjectItfImpl*)(*self);
    DEBUG_API("->XAObjectItfImpl_Resume");

    if( !pObjImp || pObjImp != pObjImp->self )
    {
        DEBUG_ERR("XA_RESULT_PARAMETER_INVALID");
        DEBUG_API("<-XAObjectItfImpl_Resume");
        /* invalid parameter */
        return XA_RESULT_PARAMETER_INVALID;
    }
    if( async )
    {
        /* invoke asynchronously */
        if( !pObjImp->callBack )
        {
            retval = XA_RESULT_PARAMETER_INVALID;
        }
        else
        {
            /* check if another async operation is processed */
            if(pObjImp->asyncOngoing)
            {
                /* abort ongoing operation */
                XAImpl_CancelThread(pObjImp->asyncThr);
            }
            pObjImp->asyncOngoing = XA_BOOLEAN_TRUE;
            if(XAImpl_StartThread(pObjImp->asyncThr, NULL,
                    XAObjectItfImpl_AsyncResume,(void*)(self)))
            {
                pObjImp->asyncOngoing = XA_BOOLEAN_FALSE;
                retval = XA_RESULT_RESOURCE_ERROR;
            }
            else
            {
                retval = XA_RESULT_SUCCESS;
            }
        }
    }
    else
    {
        /* invoke synchronously */
        if( pObjImp->DoResumeImpl )
        {
            retval = pObjImp->DoResumeImpl(self);
        }
    }
    DEBUG_API("<-XAObjectItfImpl_Resume");
    return retval;
}

XAresult XAObjectItfImpl_GetState(XAObjectItf self, XAuint32 *pState)
{
    XAObjectItfImpl* pObjImp = (XAObjectItfImpl*)(*self);
    DEBUG_API("->XAObjectItfImpl_GetState");
    if( !pObjImp || pObjImp != pObjImp->self || !pState )
    {
        DEBUG_ERR("XA_RESULT_PARAMETER_INVALID");
        DEBUG_API("<-XAObjectItfImpl_GetState");
        /* invalid parameter */
        return XA_RESULT_PARAMETER_INVALID;
    }
    *pState = pObjImp->state;

    DEBUG_API("<-XAObjectItfImpl_GetState");
    return XA_RESULT_SUCCESS;
}

XAresult XAObjectItfImpl_GetInterface(XAObjectItf self, const XAInterfaceID iid,
                                       void *pInterface)
{
    XAObjectItfImpl* pObjImp = (XAObjectItfImpl*)(*self);
    XAObjItfMapEntry *mapEntry = NULL;
    DEBUG_API("->XAObjectItfImpl_GetInterface");

    if( !pObjImp || pObjImp != pObjImp->self || !pInterface || !iid )
    {
        DEBUG_ERR("XA_RESULT_PARAMETER_INVALID");
        DEBUG_API("<-XAObjectItfImpl_GetInterface");
        /* invalid parameter */
        return XA_RESULT_PARAMETER_INVALID;
    }

    if(pObjImp->state != XA_OBJECT_STATE_REALIZED)
    {
        DEBUG_ERR("XA_RESULT_PRECONDITIONS_VIOLATED");
        DEBUG_API("<-XAObjectItfImpl_GetInterface");
        /*state is not correct */
        return XA_RESULT_PRECONDITIONS_VIOLATED;
    }

    mapEntry = XAObjectItfImpl_GetItfEntry(self, iid);
    if( mapEntry && mapEntry->pItf )
    {
        *(void**)pInterface = &(mapEntry->pItf);
        DEBUG_API("<-XAObjectItfImpl_GetInterface");
        return XA_RESULT_SUCCESS;
    }
    else
    {
        DEBUG_ERR("XA_RESULT_FEATURE_UNSUPPORTED");
        DEBUG_API("<-XAObjectItfImpl_GetInterface");
        return XA_RESULT_FEATURE_UNSUPPORTED;
    }
}


XAresult XAObjectItfImpl_RegisterCallback(XAObjectItf self,
                                       xaObjectCallback callback,
                                       void *pContext)
{
    XAObjectItfImpl* pObjImp = (XAObjectItfImpl*)(*self);
    DEBUG_API("->XAObjectItfImpl_RegisterCallback");

    if( !pObjImp || pObjImp != pObjImp->self )
    {
        DEBUG_ERR("XA_RESULT_PARAMETER_INVALID");
        DEBUG_API("<-XAObjectItfImpl_RegisterCallback");
        /* invalid parameter */
        return XA_RESULT_PARAMETER_INVALID;
    }
    pObjImp->callBack = callback;
    pObjImp->context = pContext;
    pObjImp->cbPtrToSelf = self;

    DEBUG_API("<-XAObjectItfImpl_RegisterCallback");
    return XA_RESULT_SUCCESS;
}

void XAObjectItfImpl_AbortAsyncOperation(XAObjectItf self)
{
    XAObjectItfImpl* pObjImp = (XAObjectItfImpl*)(*self);
    DEBUG_API("->XAObjectItfImpl_AbortAsyncOperation");

    if( pObjImp &&
       (pObjImp == pObjImp->self) &&
        pObjImp->callBack &&
        pObjImp->asyncOngoing )
    {
        /* abort ongoing operation */
        XAImpl_CancelThread(pObjImp->asyncThr);
    }

    DEBUG_API("<-XAObjectItfImpl_AbortAsyncOperation");
}

void XAObjectItfImpl_Destroy(XAObjectItf self)
{
    XAObjectItfImpl* pObjImp = (XAObjectItfImpl*)(*self);
    DEBUG_API("->XAObjectItfImpl_Destroy");

    if( pObjImp && pObjImp == pObjImp->self )
    {
        if( pObjImp->asyncOngoing )
        {
            /* abort ongoing operation */
            XAImpl_CancelThread(pObjImp->asyncThr);
        }
        /* free object specific resources */
        if( pObjImp->FreeResourcesImpl )
        {
            pObjImp->FreeResourcesImpl(self);
        }
        free(pObjImp->interfaceMap);
        XAImpl_DeleteThreadHandle(pObjImp->asyncThr);
        free(pObjImp);
    }

    DEBUG_API("<-XAObjectItfImpl_Destroy");
}

XAresult XAObjectItfImpl_SetPriority(XAObjectItf self, XAint32 priority,
                                  XAboolean preemptable)
{
    XAObjectItfImpl* pObjImp = (XAObjectItfImpl*)(*self);
    DEBUG_API("->XAObjectItfImpl_SetPriority");

    if( !pObjImp || pObjImp != pObjImp->self )
    {
        DEBUG_ERR("XA_RESULT_PARAMETER_INVALID");
        DEBUG_API("<-XAObjectItfImpl_SetPriority");
        /* invalid parameter */
        return XA_RESULT_PARAMETER_INVALID;
    }
    pObjImp->priority = priority;
    pObjImp->preemptable = preemptable;

    DEBUG_API("<-XAObjectItfImpl_SetPriority");
    return XA_RESULT_SUCCESS;
}

XAresult XAObjectItfImpl_GetPriority(XAObjectItf self, XAint32 *pPriority,
                                  XAboolean *pPreemptable)
{
    XAObjectItfImpl* pObjImp = (XAObjectItfImpl*)(*self);
    DEBUG_API("->XAObjectItfImpl_GetPriority");

    if( !pObjImp || pObjImp != pObjImp->self )
    {
        DEBUG_ERR("XA_RESULT_PARAMETER_INVALID");
        DEBUG_API("<-XAObjectItfImpl_GetPriority");
        /* invalid parameter */
        return XA_RESULT_PARAMETER_INVALID;
    }
    *pPriority = pObjImp->priority;
    *pPreemptable = pObjImp->preemptable;

    DEBUG_API("<-XAObjectItfImpl_GetPriority");
    return XA_RESULT_SUCCESS;
}

XAresult XAObjectItfImpl_SetLossOfControlInterfaces(XAObjectItf self,
                                              XAint16 numInterfaces,
                                              XAInterfaceID *pInterfaceIDs,
                                              XAboolean enabled)
{
    XAObjectItfImpl* pObjImp = (XAObjectItfImpl*)(*self);
    XAint32 itfIndex = 0;
    XAObjItfMapEntry *mapEntry = NULL;
    DEBUG_API("->XAObjectItfImpl_SetLossOfControlInterfaces");

    if( !pObjImp || pObjImp != pObjImp->self || !pInterfaceIDs )
    {
        DEBUG_ERR("XA_RESULT_PARAMETER_INVALID");
        DEBUG_API("<-XAObjectItfImpl_SetLossOfControlInterfaces");
        /* invalid parameter */
        return XA_RESULT_PARAMETER_INVALID;
    }
    if( pInterfaceIDs )
    {
        for(itfIndex = 0; itfIndex < numInterfaces; itfIndex++)
        {
            mapEntry = XAObjectItfImpl_GetItfEntry(self, pInterfaceIDs[itfIndex]);
            if( mapEntry )
            {
                mapEntry->locEnabled = enabled;
            }
        }
    }

    DEBUG_API("<-XAObjectItfImpl_SetLossOfControlInterfaces");
    return XA_RESULT_SUCCESS;
}

/**
 * XAObjectItfImpl -specific methods
 **/

/*
 * Allocate and init new object itf instance
 */
XAresult XAObjectItfImpl_Init(XAObjectItfImpl* self,
                              XAuint32 itfCount,
                              const XAInterfaceID** itfIIDs,
                              xaDoRealizeImpl doRealizeImpl,
                              xaDoResumeImpl doResumeImpl,
                              xaFreeResourcesImpl freeResourcesImpl)
{
    XAuint32 i = 0;
    DEBUG_API("->XAObjectItfImpl_Init");

    assert( self && itfIIDs && doRealizeImpl && doResumeImpl && freeResourcesImpl );

    self->interfaceMap =
       (XAObjItfMapEntry*)calloc(itfCount, sizeof(XAObjItfMapEntry));
    if( !self->interfaceMap )
    {
        free(self);
        DEBUG_ERR("XA_RESULT_MEMORY_FAILURE");
        DEBUG_API("<-XAObjectItfImpl_Init");
        return XA_RESULT_MEMORY_FAILURE;
    }
    if( XAImpl_CreateThreadHandle(&(self->asyncThr)) != XA_RESULT_SUCCESS )
    {
        free(self);
        DEBUG_ERR("XA_RESULT_MEMORY_FAILURE");
        DEBUG_API("<-XAObjectItfImpl_Init");
        return XA_RESULT_MEMORY_FAILURE;
    }
    for(i=0;i<itfCount;i++)
    {
        self->interfaceMap[i].mapIdx = i;
        self->interfaceMap[i].iid = *(itfIIDs[i]);
        self->interfaceMap[i].pItf = NULL;
        self->interfaceMap[i].locEnabled = XA_BOOLEAN_FALSE;
        self->interfaceMap[i].required = XA_BOOLEAN_FALSE;
        self->interfaceMap[i].isDynamic = XA_BOOLEAN_FALSE;
    }
    self->interfaceMap[0].pItf = self;
    self->interfaceMap[0].required = XA_BOOLEAN_TRUE;

    self->interfaceCount = itfCount;
    self->priority = XA_PRIORITY_NORMAL;
    self->preemptable = XA_BOOLEAN_FALSE;
    self->state = XA_OBJECT_STATE_UNREALIZED;
    self->callBack = NULL;
    self->context = NULL;
    self->asyncOngoing = XA_BOOLEAN_FALSE;
    self->cbPtrToSelf = NULL;

    self->DoRealizeImpl = doRealizeImpl;
    self->DoResumeImpl = doResumeImpl;
    self->FreeResourcesImpl = freeResourcesImpl;

    /* init itf default implementation */
    self->itf.Realize = XAObjectItfImpl_Realize;
    self->itf.Resume = XAObjectItfImpl_Resume;
    self->itf.GetState = XAObjectItfImpl_GetState;
    self->itf.GetInterface = XAObjectItfImpl_GetInterface;
    self->itf.RegisterCallback = XAObjectItfImpl_RegisterCallback;
    self->itf.AbortAsyncOperation = XAObjectItfImpl_AbortAsyncOperation;
    self->itf.Destroy = XAObjectItfImpl_Destroy;
    self->itf.SetPriority = XAObjectItfImpl_SetPriority;
    self->itf.GetPriority = XAObjectItfImpl_GetPriority;
    self->itf.SetLossOfControlInterfaces  = XAObjectItfImpl_SetLossOfControlInterfaces;
    self->self = self;

    DEBUG_API("<-XAObjectItfImpl_Init");
    return XA_RESULT_SUCCESS;
}

/*
 * Asynchronous invocation of Realize
 */
void* XAObjectItfImpl_AsyncRealize(void* args)
{
    XAresult retval = XA_RESULT_SUCCESS;
    XAObjectItfImpl* pObjImp = (XAObjectItfImpl*)(*(XAObjectItf)(args));
    DEBUG_API("->XAObjectItfImpl_AsyncRealize");

    if( pObjImp && pObjImp == pObjImp->self)
    {
        /* Check if the object is in unrealized state */
        if(pObjImp->state != XA_OBJECT_STATE_UNREALIZED)
        {
            retval = XA_RESULT_PRECONDITIONS_VIOLATED;
        }
        else if( pObjImp->DoRealizeImpl )
        {
            retval = pObjImp->DoRealizeImpl((XAObjectItf)(args));
        }
        if( pObjImp->callBack )
        {
            pObjImp->callBack(pObjImp->cbPtrToSelf, pObjImp->context,
                              XA_OBJECT_EVENT_ASYNC_TERMINATION,
                              retval, pObjImp->state, NULL);
        }
        pObjImp->asyncOngoing = XA_BOOLEAN_FALSE;
        XAImpl_ExitThread(pObjImp->asyncThr);
    }
    else
    {
        DEBUG_API("XAObjectItfImpl_AsyncRealize: INVALID args");
    }
    

    DEBUG_API("<-XAObjectItfImpl_AsyncRealize");
    return NULL;
}


/*
 * Asynchronous invocation of Resume
 */
void* XAObjectItfImpl_AsyncResume(void* args)
{
    XAresult retval = XA_RESULT_SUCCESS;
    XAObjectItfImpl* pObjImp = (XAObjectItfImpl*)(*(XAObjectItf)(args));
    DEBUG_API("->XAObjectItfImpl_AsyncResume");

    if( pObjImp && pObjImp == pObjImp->self )
    {
        if( pObjImp->DoResumeImpl )
        {
            retval = pObjImp->DoResumeImpl((XAObjectItf)(args));
        }
        if( pObjImp->callBack )
        {
            pObjImp->callBack(pObjImp->cbPtrToSelf, pObjImp->context,
                              XA_OBJECT_EVENT_ASYNC_TERMINATION,
                              retval, pObjImp->state, NULL);
        }
        pObjImp->asyncOngoing = XA_BOOLEAN_FALSE;
        XAImpl_ExitThread(pObjImp->asyncThr);
    }
    else
    {
        DEBUG_API("XAObjectItfImpl_AsyncResume: INVALID args");
    }
    

    DEBUG_API("<-XAObjectItfImpl_AsyncResume");
    return NULL;
}

XAObjItfMapEntry* XAObjectItfImpl_GetItfEntry(const XAObjectItf self,
                                              const XAInterfaceID iid)
{
    XAuint32 mapIndex = 0;
    XAObjectItfImpl* pObjImp = (XAObjectItfImpl*)(*self);
    DEBUG_API("->XAObjectItfImpl_GetItfEntry");

    if( pObjImp &&
       (pObjImp == pObjImp->self) &&
        pObjImp->interfaceMap &&
        iid )
    {
        /* Check interface */
        for(mapIndex = 0; mapIndex < pObjImp->interfaceCount; mapIndex++)
        {
            if(XACommon_EqualIIds(pObjImp->interfaceMap[mapIndex].iid, iid))
            {
                DEBUG_API("<-XAObjectItfImpl_GetItfEntry");
                return &(pObjImp->interfaceMap[mapIndex]);
            }
        }
    }

    DEBUG_API("<-XAObjectItfImpl_GetItfEntry");
    return NULL;
}