khronosfws/openmax_al/src/common/xadynintmgmtitf.c
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Fri, 16 Apr 2010 15:29:42 +0300
changeset 12 5a06f39ad45b
child 25 6f7ceef7b1d1
permissions -rw-r--r--
Revision: 201011 Kit: 201015

/*
* 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 <stdlib.h>
#include <assert.h>

#include "openmaxalwrapper.h"
#include "xadynintmgmtitf.h"
#include "xadebug.h"

/* XADIMItfImpl* GetImpl(XADIMItf self)
 * Description: Validate interface pointer and cast it to implementation pointer.
 */
static XADIMItfImpl* GetImpl(XADynamicInterfaceManagementItf self)
{
    if( self )
    {
        XADIMItfImpl* impl = (XADIMItfImpl*)(*self);
        if( impl && (impl == impl->self) )
        {
            return impl;
        }
    }
    return NULL;
}

/**
 * Base Interface XADynamicInterfaceManagementItf implementation
 **/

/* XAresult XADIMItfImpl_AddInterface
 * Optionally asynchronous method for exposing an interface on an object.
 */
XAresult XADIMItfImpl_AddInterface(XADynamicInterfaceManagementItf self,
                                   const XAInterfaceID iid,
                                   XAboolean async)
{
    XADIMItfImpl* impl = GetImpl(self);
    XAresult retval = XA_RESULT_SUCCESS;
    DEBUG_API("->XADIMItfImpl_AddInterface");
    if( !impl )
    {
        DEBUG_ERR("XA_RESULT_PARAMETER_INVALID");
        DEBUG_API("<-XADIMItfImpl_AddInterface");
        return XA_RESULT_PARAMETER_INVALID;
    }

    if( async )
    {
        /* invoke asynchronously */
        /* check if another async operation is processed */
        if(impl->asyncOngoing)
        {
            /* abort ongoing operation */
            XAImpl_CancelThread(impl->asyncThr);
        }
        impl->asyncOngoing = XA_BOOLEAN_TRUE;
        impl->asyncID = iid;
        if(XAImpl_StartThread(impl->asyncThr, NULL,
                &XADIMItfImpl_AsyncAddItf,(void*)(self)))
        {
            impl->asyncOngoing = XA_BOOLEAN_FALSE;
            retval = XA_RESULT_RESOURCE_ERROR;
        }
        else
        {
            retval = XA_RESULT_SUCCESS;
        }
    }
    else
    {
        /* invoke synchronously */
        retval = XADIMItfImpl_DoAddItf(impl, iid);
    }

    DEBUG_API_A1("<-XADIMItfImpl_AddInterface %lu", retval);
    return retval;
}

/* XAresult XADIMItfImpl_RemoveInterface
 * Synchronous method for removing a dynamically exposed interface on an object.
 */
XAresult XADIMItfImpl_RemoveInterface(XADynamicInterfaceManagementItf self,
                                          const XAInterfaceID iid)
{
    XADIMItfImpl* impl = GetImpl(self);
    XAresult retval = XA_RESULT_SUCCESS;
    DEBUG_API("->XADIMItfImpl_RemoveInterface");

    if( impl )
    {
        XAObjItfMapEntry *mapEntry = NULL;
        if(impl->parent)
        {
            mapEntry = XAObjectItfImpl_GetItfEntry(impl->parent, iid);
        }
        if( mapEntry && mapEntry->isDynamic )
        {
            if( (mapEntry->pItf) )
            {
                if( impl->DoRemoveItfImpl )
                {
                    retval = impl->DoRemoveItfImpl(impl->parent, mapEntry);
                }
                else
                {
                    DEBUG_ERR("XADIMItfImpl_RemoveInterface: Object has specified dynamic itfs but not implemented DoRemoveItfImpl!!!");
                    retval = XA_RESULT_INTERNAL_ERROR;
                }
            }
            else
            {
                DEBUG_ERR("XADIMItfImpl_RemoveInterface interface not exposed");
                retval = XA_RESULT_PRECONDITIONS_VIOLATED;
            }
        }
        else /*( mapEntry && mapEntry->isDynamic )*/
        {   /* interface is not supported for dynamic management */
            DEBUG_ERR("XADIMItfImpl_RemoveInterface interface not supported");
            retval = XA_RESULT_FEATURE_UNSUPPORTED;
        }
    }
    else
    {
        retval = XA_RESULT_PARAMETER_INVALID;
        DEBUG_ERR("XADIMItfImpl_RemoveInterface: INVALID args");
    }

    DEBUG_API_A1("<-XADIMItfImpl_RemoveInterface %lu", retval);
    return retval;
}

/* XAresult XADIMItfImpl_ResumeInterface
 * Optionally asynchronous method for resuming a dynamically exposed interface on the object.
 */
XAresult XADIMItfImpl_ResumeInterface(XADynamicInterfaceManagementItf self,
                                      const XAInterfaceID iid,
                                      XAboolean async)
{
    XADIMItfImpl* impl = GetImpl(self);
    XAresult retval = XA_RESULT_SUCCESS;
    DEBUG_API("->XADIMItfImpl_ResumeInterface");

    if( !impl )
    {
        DEBUG_ERR("XA_RESULT_PARAMETER_INVALID");
        DEBUG_API("<-XADIMItfImpl_ResumeInterface");
        return XA_RESULT_PARAMETER_INVALID;
    }

    if( async )
    {
        /* invoke asynchronously */
        /* check if another async operation is processed */
        if(impl->asyncOngoing)
        {
            /* abort ongoing operation */
            XAImpl_CancelThread(impl->asyncThr);
        }
        impl->asyncOngoing = XA_BOOLEAN_TRUE;
        impl->asyncID = iid;
        if(XAImpl_StartThread(impl->asyncThr, NULL,
                &XADIMItfImpl_AsyncResumeItf,(void*)(self)))
        {
            impl->asyncOngoing = XA_BOOLEAN_FALSE;
            retval = XA_RESULT_RESOURCE_ERROR;
        }
        else
        {
            retval = XA_RESULT_SUCCESS;
        }
    }
    else
    {
        /* invoke synchronously */
        retval = XADIMItfImpl_DoResumeItf(impl, iid);
    }

    DEBUG_API_A1("<-XADIMItfImpl_ResumeInterface %lu", retval);
    return retval;
}

/* XAresult XADIMItfImpl_RegisterCallback
 * Registers a callback on the object
 */
XAresult XADIMItfImpl_RegisterCallback(XADynamicInterfaceManagementItf self,
                                       xaDynamicInterfaceManagementCallback callback,
                                       void * pContext)
{
    XADIMItfImpl* impl = GetImpl(self);
    DEBUG_API("->XADIMItfImpl_RegisterCallback");

    if( !impl )
    {
        DEBUG_ERR("XA_RESULT_PARAMETER_INVALID");
        DEBUG_API("<-XADIMItfImpl_RegisterCallback");
        return XA_RESULT_PARAMETER_INVALID;
    }
    impl->dimCb = callback;
    impl->dimCbContext = pContext;
    impl->dimCbPtrToSelf = self;

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

/**
 * XADIMItfImpl -specific methods
 **/

/* XADIMItfImpl* XADIMItfImpl_Create()
 * Description: Allocate and initialize DIMItfImpl
 */
XADIMItfImpl* XADIMItfImpl_Create()
{
    XADIMItfImpl *self = (XADIMItfImpl*)calloc(1,sizeof(XADIMItfImpl));
    DEBUG_API("->XADIMItfImpl_Create");

    if( self )
    {
        /* init itf default implementation */
        self->itf.AddInterface = XADIMItfImpl_AddInterface;
        self->itf.RemoveInterface = XADIMItfImpl_RemoveInterface;
        self->itf.ResumeInterface = XADIMItfImpl_ResumeInterface;
        self->itf.RegisterCallback = XADIMItfImpl_RegisterCallback;

        /* init variables */
        self->asyncOngoing = XA_BOOLEAN_FALSE;
        self->dimCbPtrToSelf = NULL;

        self->self = self;
        if( XAImpl_CreateThreadHandle(&(self->asyncThr)) != XA_RESULT_SUCCESS )
        {
            free(self);
            self = NULL;
        }
    }
    DEBUG_API("<-XADIMItfImpl_Create");
    return self;
}

/* void XADIMItfImpl_Free(XADIMItfImpl* self)
 * Description: Free all resources reserved at XADIMItfImpl_Create
 */
void XADIMItfImpl_Free(XADIMItfImpl* self)
{
    DEBUG_API("->XADIMItfImpl_Free");
    assert(self==self->self);
    XAImpl_DeleteThreadHandle(self->asyncThr);
    free(self);
    DEBUG_API("<-XADIMItfImpl_Free");
}

/* void XADIMItfImpl_Init
 * Description: Initialize DIM interface. Mandatory to call if dynamic
 * interfaces are supported by object.
 */
void XADIMItfImpl_Init( XADIMItfImpl* self,
                           XAObjectItf parent,
                           xaDoAddItfImpl doAdd,
                           xaDoResumeItfImpl doResume,
                           xaDoRemoveItfImpl doRemove)
{
    DEBUG_API("->XADIMItfImpl_Init");

    assert(self==self->self && parent && doAdd && doResume && doRemove);
    self->parent = parent;
    self->DoAddItfImpl = doAdd;
    self->DoResumeItfImpl = doResume;
    self->DoRemoveItfImpl = doRemove;

    DEBUG_API("<-XADIMItfImpl_Init");
}

/* void XADIMItfImpl_SendCbEvent
 * Description: Object can use this method to send resource events
 */
void XADIMItfImpl_SendCbEvent( XADIMItfImpl* self,
                                   XAuint32 event,
                                   XAresult result,
                                   const XAInterfaceID iid )
{
    DEBUG_API("->XADIMItfImpl_SendCbEvent");
    if( self->dimCb )
     {
        self->dimCb((XADynamicInterfaceManagementItf)(self), self->dimCbContext,
                      event, result, iid);
     }
    DEBUG_API("<-XADIMItfImpl_SendCbEvent");
}

/* void* XADIMItfImpl_AsyncAddItf
 * Description: Launch AddItf from async thread.
 */
void* XADIMItfImpl_AsyncAddItf(void* args)
{
    XAresult retval = XA_RESULT_SUCCESS;
    XADIMItfImpl* impl = GetImpl(args);
    DEBUG_API("->XADIMItfImpl_AsyncAddItf");

    if( impl )
    {
        retval = XADIMItfImpl_DoAddItf(impl, impl->asyncID);
        if( impl->dimCb )
        {
            impl->dimCb((XADynamicInterfaceManagementItf)(args), impl->dimCbContext,
                         XA_DYNAMIC_ITF_EVENT_ASYNC_TERMINATION, retval, impl->asyncID);
        }
        impl->asyncOngoing = XA_BOOLEAN_FALSE;
        XAImpl_ExitThread(impl->asyncThr);
    }
    else
    {
        DEBUG_ERR("XADIMItfImpl_AsyncAddItf: INVALID args");
    }
    

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

/* XAresult XADIMItfImpl_DoAddItf
 * Description: Handle Itf dynamic addition and call object-specific parts.
 *              Launched either from async thread or directly.
 */
XAresult XADIMItfImpl_DoAddItf(XADIMItfImpl* impl,
                                const XAInterfaceID iid)
{
    XAresult retval = XA_RESULT_SUCCESS;
    DEBUG_API("->XADIMItfImpl_DoAddItf");

    if( impl )
    {
        XAObjItfMapEntry *mapEntry = NULL;
        if(impl->parent)
        {
            mapEntry = XAObjectItfImpl_GetItfEntry(impl->parent, iid);
        }
        if( mapEntry && mapEntry->isDynamic )
        {
            if( !(mapEntry->pItf) )
            {
                if( impl->DoAddItfImpl )
                {
                    retval = impl->DoAddItfImpl(impl->parent, mapEntry);
                }
                else
                {
                    DEBUG_ERR("XADIMItfImpl_DoAddItf: Object has specified dynamic itfs but not implemented DoAddItfImpl!!!");
                    retval = XA_RESULT_INTERNAL_ERROR;
                }
            }
            else
            {
                DEBUG_ERR("XADIMItfImpl_DoAddItf interface already exposed");
                retval = XA_RESULT_PRECONDITIONS_VIOLATED;
            }
        }
        else /*( mapEntry && mapEntry->isDynamic )*/
        {   /* interface is not supported for dynamic management */
            DEBUG_ERR("XADIMItfImpl_DoAddItf interface not supported");
            retval = XA_RESULT_FEATURE_UNSUPPORTED;
        }
    }
    else
    {
        retval = XA_RESULT_INTERNAL_ERROR;
        DEBUG_ERR("XADIMItfImpl_DoAddItf: INVALID args");
    }

    DEBUG_API("<-XADIMItfImpl_DoAddItf");
    return retval;
}

/* void* XADIMItfImpl_AsyncResumeItf
 * Description: Launch ResumeItf from async thread.
 */
void* XADIMItfImpl_AsyncResumeItf(void* args)
{
    XAresult retval = XA_RESULT_SUCCESS;
    XADIMItfImpl* impl = GetImpl(args);
    DEBUG_API("->XADIMItfImpl_AsyncResumeItf");

    if( impl )
    {
        retval = XADIMItfImpl_DoResumeItf(impl, impl->asyncID);
        if( impl->dimCb )
        {
            impl->dimCb((XADynamicInterfaceManagementItf)(args), impl->dimCbContext,
                         XA_DYNAMIC_ITF_EVENT_ASYNC_TERMINATION, retval, impl->asyncID);
        }
        impl->asyncOngoing = XA_BOOLEAN_FALSE;
        XAImpl_ExitThread(impl->asyncThr);
    }
    else
    {
        DEBUG_ERR("XADIMItfImpl_AsyncResumeItf: INVALID args");
    }
    

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

/* void XADIMItfImpl_DoResumeItf
 * Description: Handle Itf dynamic resuming and call object-specific parts.
 *              Launched either from async thread or directly.
 */
XAresult XADIMItfImpl_DoResumeItf(XADIMItfImpl* impl,
                                const XAInterfaceID iid)
{
    XAresult retval = XA_RESULT_SUCCESS;
    DEBUG_API("->XADIMItfImpl_DoResumeItf");

    if( impl )
    {
        XAObjItfMapEntry *mapEntry = XAObjectItfImpl_GetItfEntry(impl->parent, iid);
        if( mapEntry && mapEntry->isDynamic )
        {
            if( (!mapEntry->pItf) )
            {
                if( impl->DoResumeItfImpl )
                {
                    retval = impl->DoResumeItfImpl(impl->parent, mapEntry);
                }
                else
                {
                    DEBUG_ERR("XADIMItfImpl_DoResumeItf: Object has specified dynamic itfs but not implemented DoResumeItfImpl!!!");
                    retval = XA_RESULT_INTERNAL_ERROR;
                }
            }
            else
            {
                DEBUG_ERR("XADIMItfImpl_DoResumeItf interface already exposed");
                retval = XA_RESULT_PRECONDITIONS_VIOLATED;
            }
        }
        else /*( mapEntry && mapEntry->isDynamic )*/
        {   /* interface is not supported for dynamic management */
            DEBUG_ERR("XADIMItfImpl_DoResumeItf interface not supported");
            retval = XA_RESULT_FEATURE_UNSUPPORTED;
        }
    }
    else
    {
        retval = XA_RESULT_INTERNAL_ERROR;
        DEBUG_ERR("XADIMItfImpl_DoResumeItf: INVALID args");
    }

    DEBUG_API("<-XADIMItfImpl_DoResumeItf");
    return retval;
}