<commit_before>/*
** See Copyright Notice in LICENSE.
**/
#include "luno.hxx"

#include <cppuhelper/typeprovider.hxx>

#include <com/sun/star/beans/MethodConcept.hpp>
#include <com/sun/star/reflection/ParamMode.hpp>

using com::sun::star::beans::UnknownPropertyException;
using com::sun::star::beans::XIntrospectionAccess;

using namespace com::sun::star::lang;
using namespace com::sun::star::reflection;
using namespace com::sun::star::script;
using namespace com::sun::star::uno;

using namespace rtl;

#define OUSTRTOASCII(s) OUStringToOString(s, RTL_TEXTENCODING_ASCII_US).getStr()

#define LUNO_ADAPTER_PUSH_WRAPPED(ref) \
    LUNO_PUSH_REG_WRAPPED(); \
    lua_rawgeti(L, -1, ref); \
    lua_replace(L, -2)

#define LUNO_ADAPTER_PUSH_ADAPTERS(ref) \
    LUNO_PUSH_REG_ADAPTERS(); \
    lua_rawgeti(L, -1, ref); \
    lua_replace(L, -2)

namespace luno
{

/** Wraps table at index.
*/
LunoAdapter::LunoAdapter(lua_State *L_, const int index,
                        const Any &aTypes, const Any &aImpleId)
    : L(L_),
      m_WrappedRef(0),
      m_AdapterRef(0),
      m_Types(aTypes),
      m_ImpleId(aImpleId)
{
    const int top = lua_gettop(L);
    // push wrapped value to wrapped
    LUNO_PUSH_REG_WRAPPED();
    lua_pushvalue(L, index);
    m_WrappedRef = luaL_ref(L, -2);

    LUNO_PUSH_REG_ADAPTERS();
    lua_pushlightuserdata(L, this);
    m_AdapterRef = luaL_ref(L, -2);

    lua_settop(L, top);
}

LunoAdapter::~LunoAdapter()
{
    const int top = lua_gettop(L);
    if (m_WrappedRef)
    {
        LUNO_PUSH_REG_WRAPPED();
        luaL_unref(L, -1, m_WrappedRef);
        m_WrappedRef = 0;
    }
    if (m_AdapterRef)
    {
        LUNO_PUSH_REG_ADAPTERS();
        luaL_unref(L, -1, m_AdapterRef);
        m_AdapterRef = 0;
    }
    lua_settop(L, top);
}

LunoAdapter *LunoAdapter::create(lua_State *L_, const int index,
                            const Sequence< Type > &aTypes, const Sequence< sal_Int8 > &aImpleId)
{
    // ToDo get types and id at first request
    Any aTypes_;
    Any aImpleId_;
    aTypes_ <<= aTypes;
    aImpleId_ <<= aImpleId;

    return new LunoAdapter(L_, index, aTypes_, aImpleId_);
}

Sequence< sal_Int16 > LunoAdapter::getOutParamIndexes(const OUString &aName)
        throw (RuntimeException)
{
    Sequence< sal_Int16 > ret;

    Runtime runtime;
    Reference< XInterface > rAdapter(
        runtime.getImple()->xAdapterFactory->createAdapter(this, getWrappedTypes()));
    Reference< XIntrospectionAccess > xIntrospectionAcc(
        runtime.getImple()->xIntrospection->inspect(makeAny(rAdapter)));
    if (!xIntrospectionAcc.is())
        throw RuntimeException(
            OUSTRCONST("Failed to create adapter."), Reference< XInterface >());

    Reference< XIdlMethod > xIdlMethod(
        xIntrospectionAcc->getMethod(aName, com::sun::star::beans::MethodConcept::ALL));
    if (!xIdlMethod.is())
        throw RuntimeException(
            OUSTRCONST("Failed to get reflection for ") + aName, Reference< XInterface >());

    const Sequence< ParamInfo > aInfos(xIdlMethod->getParameterInfos());
    const ParamInfo *pInfos = aInfos.getConstArray();

    const int length = aInfos.getLength();
    int out = 0;
    int i = 0;
    for (i = 0; i < length; ++i)
    {
        if (pInfos[i].aMode != ParamMode_IN)
            ++out;
    }
    if (out)
    {
        sal_Int16 j = 0;
        ret.realloc(out);
        sal_Int16 *pOutIndexes = ret.getArray();
        for (i = 0; i < length; ++i)
        {
            if (pInfos[i].aMode != ParamMode_IN)
            {
                pOutIndexes[j] = i;
                ++j;
            }
        }
    }
    return ret;
}

Reference< XIntrospectionAccess > LunoAdapter::getIntrospection()
    throw (RuntimeException)
{
    return Reference< XIntrospectionAccess >();
}

Sequence< Type > LunoAdapter::getWrappedTypes() const
{
    Sequence< Type > aTypes;
    m_Types >>= aTypes;
    return aTypes;
}

// Call lua_gettable in safe mode
static int luno_gettable(lua_State *L)
{
    // 1: table, 2: key
    lua_pushvalue(L, 2); // key
    lua_gettable(L, 1);
    return 1;
}

#define THROW_ON_ERROR(error) \
    if (error) \
    { \
        size_t length; \
        const char *message = lua_tolstring(L, -1, &length); \
        const OUString aMessage(message, length, RTL_TEXTENCODING_UTF8); \
        lua_pop(L, 1); \
        throw RuntimeException(aMessage, Reference< XInterface >()); \
    }

#define CHECK_WRAPPED(ref) \
    if (!ref) \
        throw RuntimeException(OUSTRCONST("Nothing wrapped"), Reference< XInterface >())

Any LunoAdapter::invoke(const OUString &aName, const Sequence< Any > &aParams,
                    Sequence< sal_Int16 > &aOutParamIndex, Sequence< Any > &aOutParam)
    throw (IllegalArgumentException, CannotConvertException,
            InvocationTargetException,  RuntimeException)
{
    static const OUString aNameGetSomething(RTL_CONSTASCII_USTRINGPARAM("getSomething"));
    static const OUString aNameGetTypes(RTL_CONSTASCII_USTRINGPARAM("getTypes"));
    static const OUString aNameGetImplementationId(RTL_CONSTASCII_USTRINGPARAM("getImplementationId"));

    const int nParams = (int)aParams.getLength();
    if (!nParams)
    {
        // return cached value
        if (aName.equals(aNameGetTypes))
            return m_Types;
        else if (aName.equals(aNameGetImplementationId))
            return m_ImpleId;
    }
    else if (nParams == 1 && aName.equals(aNameGetSomething))
    {
        Sequence< sal_Int8 > id;
        if (aParams[0] >>= id)
            return makeAny(getSomething(id));
    }

    Any retAny;
    const int top = lua_gettop(L);
    try
    {
        CHECK_WRAPPED(m_WrappedRef);

        Runtime runtime;

        LUNO_ADAPTER_PUSH_WRAPPED(m_WrappedRef); // reuse
        // find function to call with error checking
        lua_pushcfunction(L, luno_gettable);
        lua_pushvalue(L, -2); // wrapped
        lua_pushstring(L, OUSTRTOASCII(aName));
        const int e = lua_pcall(L, 2, 1, 0);
        THROW_ON_ERROR(e);

        if (!lua_isfunction(L, -1))
        {
            // ToDo check is callable?
            lua_settop(L, top);
            throw RuntimeException(
                OUSTRCONST("Method not found: ") + aName, Reference< XInterface >());
        }
        lua_insert(L, top + 1); // wrapped - func -> func - wrapped

        // push arguments
        const Any *pParams = aParams.getConstArray();
        for (int i = 0; i < nParams; ++i)
            runtime.anyToLua(L, pParams[i]);

        // call, obj + params, var args
        const int error = lua_pcall(L, nParams + 1, LUA_MULTRET, 0);
        if (error)
        {
            // ToDo test throw exception from Lua
            if (error == LUA_ERRRUN)
            {
                if (lua_isuserdata(L, -1))
                {
                    LunoAdapted *p = luno_proxy_getudata(L, -1, LUNO_META_STRUCT);
                    if (p != NULL && p->Wrapped.getValueTypeClass() == TypeClass_EXCEPTION)
                    {
                        lua_settop(L, top);
                        throw InvocationTargetException(OUString(),
                                    Reference< XInterface >(), p->Wrapped);
                    }
                }
                size_t length;
                const char *message = lua_tolstring(L, -1, &length);
                throw RuntimeException(OUString(message, length, RTL_TEXTENCODING_UTF8),
                            Reference< XInterface >());
            }
            else
            {
                // ToDo LUA_ERRGCMM
                size_t length;
                const char *s = lua_tolstring(L, -1, &length);
                throw RuntimeException(
                    OUString(s, length, RTL_TEXTENCODING_UTF8), Reference< XInterface >());
            }
        }
        // ignore normal return value and wrapped obj
        const int nOut = lua_gettop(L) - top - 1;

        if (lua_gettop(L) - top > 0)
            retAny = runtime.luaToAny(L, top + 1);

        if (nOut > 1)
        {
            aOutParamIndex = getOutParamIndexes(aName);
            const int nOutParams = (int)aOutParamIndex.getLength();
            if (nOut != nOutParams)
                throw RuntimeException(
                    OUSTRCONST("luno: illegal number of out values for method: ") + aName,
                    Reference< XInterface >());

            aOutParam.realloc(nOutParams);
            for (int i = 0; i < nOutParams; ++i)
                aOutParam[i] = runtime.luaToAny(L, top + 1 + i);
        }
        lua_settop(L, top);
    }
    catch (RuntimeException &e)
    {
        lua_settop(L, top);
        throw;
    }
    return retAny;
}

// Call lua_settable in safe mode
static int luno_settable(lua_State *L)
{
    // i: table, 2: key, 3: value
    lua_pushvalue(L, 2); // key
    lua_pushvalue(L, 3); // value
    lua_settable(L, 1);
    return 0;
}

void LunoAdapter::setValue(const OUString &aName, const Any &aValue)
    throw (UnknownPropertyException, CannotConvertException,
            InvocationTargetException, RuntimeException)
{
    CHECK_WRAPPED(m_WrappedRef);

    lua_pushcfunction(L, luno_settable);
    LUNO_ADAPTER_PUSH_WRAPPED(m_WrappedRef);
    lua_pushstring(L, OUSTRTOASCII(aName));

    try
    {
        Runtime runtime;
        runtime.anyToLua(L, aValue);
    }
    catch (RuntimeException &e)
    {
        lua_pop(L, 3);
        throw;
    }

    const int e = lua_pcall(L, 3, 1, 0);
    THROW_ON_ERROR(e);
}

Any LunoAdapter::getValue(const OUString &aName)
    throw (UnknownPropertyException, RuntimeException)
{
    CHECK_WRAPPED(m_WrappedRef);

    const int top = lua_gettop(L);
    Any a;

    lua_pushcfunction(L, luno_gettable);
    LUNO_ADAPTER_PUSH_WRAPPED(m_WrappedRef);
    lua_pushstring(L, OUSTRTOASCII(aName));

    const int e = lua_pcall(L, 2, 1, 0);
    THROW_ON_ERROR(e);

    Runtime runtime;
    try
    {
        a = runtime.luaToAny(L, -1);
    }
    catch (RuntimeException &e)
    {
        lua_settop(L, top);
        throw;
    }
    lua_pop(L, 1); // result
    return a;
}

sal_Bool LunoAdapter::hasMethod(const OUString &aName)
    throw (RuntimeException)
{
    sal_Bool b = sal_False;
    CHECK_WRAPPED(m_WrappedRef);

    lua_pushcfunction(L, luno_gettable);
    LUNO_ADAPTER_PUSH_WRAPPED(m_WrappedRef);
    lua_pushstring(L, OUSTRTOASCII(aName));

    const int e = lua_pcall(L, 2, 1, 0);
    THROW_ON_ERROR(e);

    if (!lua_isfunction(L, -1))
        b = sal_True;
    lua_pop(L, 1); // value
    return b;
}

sal_Bool LunoAdapter::hasProperty(const OUString &aName)
    throw (RuntimeException)
{
    CHECK_WRAPPED(m_WrappedRef);

    sal_Bool b = sal_False;
    lua_pushcfunction(L, luno_gettable);
    LUNO_ADAPTER_PUSH_WRAPPED(m_WrappedRef);
    lua_pushstring(L, OUSTRTOASCII(aName));

    const int e = lua_pcall(L, 2, 1, 0);
    THROW_ON_ERROR(e);

    if (!lua_isnil(L, -1))
        b = sal_True;
    lua_pop(L, 1); // value
    return b;
}

static cppu::OImplementationId g_Id(sal_False);

Sequence< sal_Int8 > LunoAdapter::getUnoTunnelImplementationId()
{
    return g_Id.getImplementationId();
}

sal_Int64 LunoAdapter::getSomething(const Sequence< sal_Int8 > &aIdentifier)
    throw (RuntimeException)
{
    if (aIdentifier == g_Id.getImplementationId())
        return reinterpret_cast< sal_Int64 >(this);
    return 0;
}

} // luno
<commit_msg>Fix extract exception from material holder<commit_after>/*
** See Copyright Notice in LICENSE.
**/
#include "luno.hxx"

#include <cppuhelper/typeprovider.hxx>

#include <com/sun/star/beans/MethodConcept.hpp>
#include <com/sun/star/reflection/ParamMode.hpp>

using com::sun::star::beans::UnknownPropertyException;
using com::sun::star::beans::XIntrospectionAccess;

using namespace com::sun::star::lang;
using namespace com::sun::star::reflection;
using namespace com::sun::star::script;
using namespace com::sun::star::uno;

using namespace rtl;

#define OUSTRTOASCII(s) OUStringToOString(s, RTL_TEXTENCODING_ASCII_US).getStr()

#define LUNO_ADAPTER_PUSH_WRAPPED(ref) \
    LUNO_PUSH_REG_WRAPPED(); \
    lua_rawgeti(L, -1, ref); \
    lua_replace(L, -2)

#define LUNO_ADAPTER_PUSH_ADAPTERS(ref) \
    LUNO_PUSH_REG_ADAPTERS(); \
    lua_rawgeti(L, -1, ref); \
    lua_replace(L, -2)

namespace luno
{

/** Wraps table at index.
*/
LunoAdapter::LunoAdapter(lua_State *L_, const int index,
                        const Any &aTypes, const Any &aImpleId)
    : L(L_),
      m_WrappedRef(0),
      m_AdapterRef(0),
      m_Types(aTypes),
      m_ImpleId(aImpleId)
{
    const int top = lua_gettop(L);
    // push wrapped value to wrapped
    LUNO_PUSH_REG_WRAPPED();
    lua_pushvalue(L, index);
    m_WrappedRef = luaL_ref(L, -2);

    LUNO_PUSH_REG_ADAPTERS();
    lua_pushlightuserdata(L, this);
    m_AdapterRef = luaL_ref(L, -2);

    lua_settop(L, top);
}

LunoAdapter::~LunoAdapter()
{
    const int top = lua_gettop(L);
    if (m_WrappedRef)
    {
        LUNO_PUSH_REG_WRAPPED();
        luaL_unref(L, -1, m_WrappedRef);
        m_WrappedRef = 0;
    }
    if (m_AdapterRef)
    {
        LUNO_PUSH_REG_ADAPTERS();
        luaL_unref(L, -1, m_AdapterRef);
        m_AdapterRef = 0;
    }
    lua_settop(L, top);
}

LunoAdapter *LunoAdapter::create(lua_State *L_, const int index,
                            const Sequence< Type > &aTypes, const Sequence< sal_Int8 > &aImpleId)
{
    // ToDo get types and id at first request
    Any aTypes_;
    Any aImpleId_;
    aTypes_ <<= aTypes;
    aImpleId_ <<= aImpleId;

    return new LunoAdapter(L_, index, aTypes_, aImpleId_);
}

Sequence< sal_Int16 > LunoAdapter::getOutParamIndexes(const OUString &aName)
        throw (RuntimeException)
{
    Sequence< sal_Int16 > ret;

    Runtime runtime;
    Reference< XInterface > rAdapter(
        runtime.getImple()->xAdapterFactory->createAdapter(this, getWrappedTypes()));
    Reference< XIntrospectionAccess > xIntrospectionAcc(
        runtime.getImple()->xIntrospection->inspect(makeAny(rAdapter)));
    if (!xIntrospectionAcc.is())
        throw RuntimeException(
            OUSTRCONST("Failed to create adapter."), Reference< XInterface >());

    Reference< XIdlMethod > xIdlMethod(
        xIntrospectionAcc->getMethod(aName, com::sun::star::beans::MethodConcept::ALL));
    if (!xIdlMethod.is())
        throw RuntimeException(
            OUSTRCONST("Failed to get reflection for ") + aName, Reference< XInterface >());

    const Sequence< ParamInfo > aInfos(xIdlMethod->getParameterInfos());
    const ParamInfo *pInfos = aInfos.getConstArray();

    const int length = aInfos.getLength();
    int out = 0;
    int i = 0;
    for (i = 0; i < length; ++i)
    {
        if (pInfos[i].aMode != ParamMode_IN)
            ++out;
    }
    if (out)
    {
        sal_Int16 j = 0;
        ret.realloc(out);
        sal_Int16 *pOutIndexes = ret.getArray();
        for (i = 0; i < length; ++i)
        {
            if (pInfos[i].aMode != ParamMode_IN)
            {
                pOutIndexes[j] = i;
                ++j;
            }
        }
    }
    return ret;
}

Reference< XIntrospectionAccess > LunoAdapter::getIntrospection()
    throw (RuntimeException)
{
    return Reference< XIntrospectionAccess >();
}

Sequence< Type > LunoAdapter::getWrappedTypes() const
{
    Sequence< Type > aTypes;
    m_Types >>= aTypes;
    return aTypes;
}

// Call lua_gettable in safe mode
static int luno_gettable(lua_State *L)
{
    // 1: table, 2: key
    lua_pushvalue(L, 2); // key
    lua_gettable(L, 1);
    return 1;
}

#define THROW_ON_ERROR(error) \
    if (error) \
    { \
        size_t length; \
        const char *message = lua_tolstring(L, -1, &length); \
        const OUString aMessage(message, length, RTL_TEXTENCODING_UTF8); \
        lua_pop(L, 1); \
        throw RuntimeException(aMessage, Reference< XInterface >()); \
    }

#define CHECK_WRAPPED(ref) \
    if (!ref) \
        throw RuntimeException(OUSTRCONST("Nothing wrapped"), Reference< XInterface >())

Any LunoAdapter::invoke(const OUString &aName, const Sequence< Any > &aParams,
                    Sequence< sal_Int16 > &aOutParamIndex, Sequence< Any > &aOutParam)
    throw (IllegalArgumentException, CannotConvertException,
            InvocationTargetException,  RuntimeException)
{
    static const OUString aNameGetSomething(RTL_CONSTASCII_USTRINGPARAM("getSomething"));
    static const OUString aNameGetTypes(RTL_CONSTASCII_USTRINGPARAM("getTypes"));
    static const OUString aNameGetImplementationId(RTL_CONSTASCII_USTRINGPARAM("getImplementationId"));

    const int nParams = (int)aParams.getLength();
    if (!nParams)
    {
        // return cached value
        if (aName.equals(aNameGetTypes))
            return m_Types;
        else if (aName.equals(aNameGetImplementationId))
            return m_ImpleId;
    }
    else if (nParams == 1 && aName.equals(aNameGetSomething))
    {
        Sequence< sal_Int8 > id;
        if (aParams[0] >>= id)
            return makeAny(getSomething(id));
    }

    Any retAny;
    const int top = lua_gettop(L);
    try
    {
        CHECK_WRAPPED(m_WrappedRef);

        Runtime runtime;

        LUNO_ADAPTER_PUSH_WRAPPED(m_WrappedRef); // reuse
        // find function to call with error checking
        lua_pushcfunction(L, luno_gettable);
        lua_pushvalue(L, -2); // wrapped
        lua_pushstring(L, OUSTRTOASCII(aName));
        const int e = lua_pcall(L, 2, 1, 0);
        THROW_ON_ERROR(e);

        if (!lua_isfunction(L, -1))
        {
            // ToDo check is callable?
            lua_settop(L, top);
            throw RuntimeException(
                OUSTRCONST("Method not found: ") + aName, Reference< XInterface >());
        }
        lua_insert(L, top + 1); // wrapped - func -> func - wrapped

        // push arguments
        const Any *pParams = aParams.getConstArray();
        for (int i = 0; i < nParams; ++i)
            runtime.anyToLua(L, pParams[i]);

        // call, obj + params, var args
        const int error = lua_pcall(L, nParams + 1, LUA_MULTRET, 0);
        if (error)
        {
            // ToDo test throw exception from Lua
            if (error == LUA_ERRRUN)
            {
                if (lua_isuserdata(L, -1))
                {
                    LunoAdapted *p = luno_proxy_getudata(L, -1, LUNO_META_STRUCT);
                    if (p != NULL && p->Wrapped.getValueTypeClass() == TypeClass_EXCEPTION)
                    {
                        lua_settop(L, top);
                        Exception e;
                        p->Wrapped >>= e;
                        throw InvocationTargetException(e.Message,
                                    Reference< XInterface >(), p->Wrapped);
                    }
                }
                size_t length;
                const char *message = lua_tolstring(L, -1, &length);
                throw RuntimeException(OUString(message, length, RTL_TEXTENCODING_UTF8),
                            Reference< XInterface >());
            }
            else
            {
                // ToDo LUA_ERRGCMM
                size_t length;
                const char *s = lua_tolstring(L, -1, &length);
                throw RuntimeException(
                    OUString(s, length, RTL_TEXTENCODING_UTF8), Reference< XInterface >());
            }
        }
        // ignore normal return value and wrapped obj
        const int nOut = lua_gettop(L) - top - 1;

        if (lua_gettop(L) - top > 0)
            retAny = runtime.luaToAny(L, top + 1);

        if (nOut > 1)
        {
            aOutParamIndex = getOutParamIndexes(aName);
            const int nOutParams = (int)aOutParamIndex.getLength();
            if (nOut != nOutParams)
                throw RuntimeException(
                    OUSTRCONST("luno: illegal number of out values for method: ") + aName,
                    Reference< XInterface >());

            aOutParam.realloc(nOutParams);
            for (int i = 0; i < nOutParams; ++i)
                aOutParam[i] = runtime.luaToAny(L, top + 1 + i);
        }
        lua_settop(L, top);
    }
    catch (RuntimeException &e)
    {
        lua_settop(L, top);
        throw;
    }
    return retAny;
}

// Call lua_settable in safe mode
static int luno_settable(lua_State *L)
{
    // i: table, 2: key, 3: value
    lua_pushvalue(L, 2); // key
    lua_pushvalue(L, 3); // value
    lua_settable(L, 1);
    return 0;
}

void LunoAdapter::setValue(const OUString &aName, const Any &aValue)
    throw (UnknownPropertyException, CannotConvertException,
            InvocationTargetException, RuntimeException)
{
    CHECK_WRAPPED(m_WrappedRef);

    lua_pushcfunction(L, luno_settable);
    LUNO_ADAPTER_PUSH_WRAPPED(m_WrappedRef);
    lua_pushstring(L, OUSTRTOASCII(aName));

    try
    {
        Runtime runtime;
        runtime.anyToLua(L, aValue);
    }
    catch (RuntimeException &e)
    {
        lua_pop(L, 3);
        throw;
    }

    const int e = lua_pcall(L, 3, 1, 0);
    THROW_ON_ERROR(e);
}

Any LunoAdapter::getValue(const OUString &aName)
    throw (UnknownPropertyException, RuntimeException)
{
    CHECK_WRAPPED(m_WrappedRef);

    const int top = lua_gettop(L);
    Any a;

    lua_pushcfunction(L, luno_gettable);
    LUNO_ADAPTER_PUSH_WRAPPED(m_WrappedRef);
    lua_pushstring(L, OUSTRTOASCII(aName));

    const int e = lua_pcall(L, 2, 1, 0);
    THROW_ON_ERROR(e);

    Runtime runtime;
    try
    {
        a = runtime.luaToAny(L, -1);
    }
    catch (RuntimeException &e)
    {
        lua_settop(L, top);
        throw;
    }
    lua_pop(L, 1); // result
    return a;
}

sal_Bool LunoAdapter::hasMethod(const OUString &aName)
    throw (RuntimeException)
{
    sal_Bool b = sal_False;
    CHECK_WRAPPED(m_WrappedRef);

    lua_pushcfunction(L, luno_gettable);
    LUNO_ADAPTER_PUSH_WRAPPED(m_WrappedRef);
    lua_pushstring(L, OUSTRTOASCII(aName));

    const int e = lua_pcall(L, 2, 1, 0);
    THROW_ON_ERROR(e);

    if (!lua_isfunction(L, -1))
        b = sal_True;
    lua_pop(L, 1); // value
    return b;
}

sal_Bool LunoAdapter::hasProperty(const OUString &aName)
    throw (RuntimeException)
{
    CHECK_WRAPPED(m_WrappedRef);

    sal_Bool b = sal_False;
    lua_pushcfunction(L, luno_gettable);
    LUNO_ADAPTER_PUSH_WRAPPED(m_WrappedRef);
    lua_pushstring(L, OUSTRTOASCII(aName));

    const int e = lua_pcall(L, 2, 1, 0);
    THROW_ON_ERROR(e);

    if (!lua_isnil(L, -1))
        b = sal_True;
    lua_pop(L, 1); // value
    return b;
}

static cppu::OImplementationId g_Id(sal_False);

Sequence< sal_Int8 > LunoAdapter::getUnoTunnelImplementationId()
{
    return g_Id.getImplementationId();
}

sal_Int64 LunoAdapter::getSomething(const Sequence< sal_Int8 > &aIdentifier)
    throw (RuntimeException)
{
    if (aIdentifier == g_Id.getImplementationId())
        return reinterpret_cast< sal_Int64 >(this);
    return 0;
}

} // luno
<|endoftext|>


<commit_before>/**
 * @author pinkasfeld joseph
 * Copyright (c) Aldebaran Robotics 2010, 2011 All Rights Reserved.
 */

#include "allaser.h"

#include <iostream>
#include <alcommon/alproxy.h>
#include <alproxies/almemoryproxy.h>
#include <boost/shared_ptr.hpp>
#include <alcommon/albroker.h>
#include <alcommon/almodule.h>
#include <sstream>

#include <pthread.h>
#include <signal.h>
#include <cmath>

#include <qi/log.hpp>

#if defined (__linux__)
#include <sys/prctl.h>
#endif

extern "C" {
# include "urg_ctrl.h"
# include "scip_handler.h"
}

#define MODE_ON 0
#define MODE_OFF 1
#define SEND_MODE_ON 2
#define SEND_MODE_OFF 3

#define MIDDLE_ANGLE 384
#define DEFAULT_MIN_ANGLE 43
#define DEFAULT_MAX_ANGLE 725
#define MIN_ANGLE_LASER 43
#define MAX_ANGLE_LASER 725
#define RESOLUTION_LASER 1024
#define MIN_LENGTH_LASER 20
#define MAX_LENGTH_LASER 5600

#include <sys/time.h>

using namespace AL;
using namespace std;
pthread_t urgThreadId;
boost::shared_ptr<ALMemoryProxy> gSTM;
static int mode = MODE_ON;
static urg_t urg;
static int angle_min = DEFAULT_MIN_ANGLE;
static int angle_max = DEFAULT_MAX_ANGLE;
static int length_min = MIN_LENGTH_LASER;
static int length_max = MAX_LENGTH_LASER;

static void urg_exit(urg_t *urg, const char *message) {
  qiLogInfo("hardware.allaser", "%s: %s\n", message, urg_error(urg));
  urg_disconnect(urg);
  qiLogInfo("hardware.allaser", "urg_exit\n");
  pthread_exit((void *)NULL);
}

#define URG_DEFAULT_SPEED (19200)
#define URG_FAST_SPEED (500000)

void * urgThread(void * arg) {

#if defined (__linux__)
  // thread name
  prctl(PR_SET_NAME, "ALLaser::urgThread", 0, 0, 0);
#endif

  ALValue urgdata;
  long *data = NULL;
  int data_max;
  int ret;
  int n;
  int i,imemory,refTime,end,sampleTime, beginThread;
  std::string valueName="Device/Laser/Value";

  /* Connection */

  connectToLaser();

  /* Reserve the Receive data buffer */
  data_max = urg_dataMax(&urg);
  data = (long*)malloc(sizeof(long) * data_max);
  if (data == NULL) {
    perror("data buffer");
    pthread_exit((void *)NULL);
  }
  /* prepare ALValue for ALMemory*/
  urgdata.arraySetSize(data_max);
  for (i=0; i< data_max;i++)
  {
    urgdata[i].arraySetSize(4);
    urgdata[i][0]= (int)0;
    urgdata[i][1]= (double)0.0;
    urgdata[i][2]= (int)0;
    urgdata[i][3]= (int)0;
  }
  /* insert ALvalue in ALMemory*/

  gSTM->insertData(valueName,urgdata);

  gSTM->insertData("Device/Laser/LaserEnable",(bool)1);
  gSTM->insertData("Device/Laser/MinAngle",(float)((2.0 * M_PI)*(DEFAULT_MIN_ANGLE - MIDDLE_ANGLE) / RESOLUTION_LASER));
  gSTM->insertData("Device/Laser/MaxAngle",(float)((2.0 * M_PI)*(DEFAULT_MAX_ANGLE - MIDDLE_ANGLE) / RESOLUTION_LASER));
  gSTM->insertData("Device/Laser/MinLength",(float)(length_min));
  gSTM->insertData("Device/Laser/MaxLength",(float)(length_max));

  printf("ALLASER Running\n");

  while(1)
  {
    if(mode==SEND_MODE_ON){
      ret = urg_laserOn(&urg);
      if (ret < 0) {
        urg_exit(&urg, "urg_requestData()");
      }
      mode=MODE_ON;
      /* Connection */
      connectToLaser();
    }
    if(mode==SEND_MODE_OFF){
      scip_qt(&urg.serial_, NULL, ScipNoWaitReply);
      mode=MODE_OFF;
    }
    if(mode==MODE_ON){
      /* Request Data using GD-Command */
      ret = urg_requestData(&urg, URG_GD, angle_min, angle_max);
      if (ret < 0) {
        urg_exit(&urg, "urg_requestData()");
      }

      refTime = getLocalTime();
      /* Obtain Data */
      n = urg_receiveData(&urg, data, data_max);
      if (n < 0) {
        urg_exit(&urg, "urg_receiveData()");
      }
      end= getLocalTime();
      sampleTime=end-refTime;

      imemory=0;
      for (i = 0; i < n; ++i) {
        int x, y;
        double angle=index2rad(i);
        int length = data[i];

        if((length>=length_min)&&(length<=length_max)){
          x = (int)((double)length * cos(angle));
          y = (int)((double)length * sin(angle));
          urgdata[imemory][0]= length;
          urgdata[imemory][1]= angle;
          urgdata[imemory][2]= x;
          urgdata[imemory][3]= y;
          imemory++;
        }
      }
      for(;imemory<data_max;imemory++){
        urgdata[imemory][0]= 0;
        urgdata[imemory][1]= 0;
        urgdata[imemory][2]= 0;
        urgdata[imemory][3]= 0;
      }
      gSTM->insertData(valueName,urgdata);
      usleep(1000);
    }else{
      usleep(10000);
    }
  }
  urg_disconnect(&urg);

  free(data);
}

//______________________________________________
// constructor
//______________________________________________
ALLaser::ALLaser(boost::shared_ptr<ALBroker> pBroker, const std::string& pName ): ALModule(pBroker, pName )
{
  setModuleDescription( "Allow control over Hokuyo laser when available on Nao's head." );

  functionName("laserOFF", "ALLaser", "Disable laser light");
  BIND_METHOD( ALLaser::laserOFF );

  functionName("laserON", "ALLaser", "Enable laser light and sampling");
  BIND_METHOD( ALLaser::laserON );

  functionName("setOpeningAngle", "ALLaser", "Set openning angle of the laser");
  addParam("angle_min_f", "float containing the min value in rad, this value must be upper than -2.35619449 ");
  addParam("angle_max_f", "float containing the max value in rad, this value must be lower than 2.092349795 ");
  addMethodExample( "python",
        "# Set the opening angle at -90/90 degres\n"
        "laser = ALProxy(\"ALLaser\",\"127.0.0.1\",9559)\n"
        "laser.setOpeningAngle(-1.570796327,1.570796327)\n"
      );
  BIND_METHOD( ALLaser::setOpeningAngle );

  functionName("setDetectingLength", "ALLaser", "Set detection threshold of the laser");
  addParam("length_min_l", "int containing the min length that the laser will detect(mm), this value must be upper than 20 mm");
  addParam("length_max_l", "int containing the max length that the laser will detect(mm), this value must be lower than 5600 mm");
  addMethodExample( "python",
        "# Set detection threshold at 500/3000 mm\n"
        "laser = ALProxy(\"ALLaser\",\"127.0.0.1\",9559)\n"
        "laser.setDetectingLength(500,3000)\n"
      );
  BIND_METHOD( ALLaser::setDetectingLength );

  // get broker on DCM and ALMemory
  try {
    gSTM = getParentBroker()->getMemoryProxy();
  } catch(ALError& e) {
    qiLogError("hardware.allaser") << "Could not connect to Memory. Error: " << e.what() << std::endl;
  }

  pthread_create(&urgThreadId, NULL, urgThread, NULL);
}

//______________________________________________
// destructor
//______________________________________________
ALLaser::~ALLaser()
{
  pthread_cancel(urgThreadId);
}

void ALLaser::laserOFF(void){
  mode = SEND_MODE_OFF;
  gSTM->insertData("Device/Laser/LaserEnable",(bool)0);
}

void ALLaser::laserON(void){
  mode = SEND_MODE_ON;
  gSTM->insertData("Device/Laser/LaserEnable",(bool)1);
}

void ALLaser::setOpeningAngle(const AL::ALValue& angle_min_f, const AL::ALValue& angle_max_f){
  angle_min = MIDDLE_ANGLE + (int)(RESOLUTION_LASER*(float)angle_min_f / (2.0 * M_PI));
  angle_max = MIDDLE_ANGLE + (int)(RESOLUTION_LASER*(float)angle_max_f / (2.0 * M_PI));
  if(angle_min<MIN_ANGLE_LASER) angle_min = MIN_ANGLE_LASER;
  if(angle_max>MAX_ANGLE_LASER) angle_max = MAX_ANGLE_LASER;
  if(angle_min>=angle_max){
    angle_min = MIN_ANGLE_LASER;
    angle_max = MAX_ANGLE_LASER;
  }
  gSTM->insertData("Device/Laser/MinAngle",(float)((2.0 * M_PI) *(angle_min - MIDDLE_ANGLE) / RESOLUTION_LASER));
  gSTM->insertData("Device/Laser/MaxAngle",(float)((2.0 * M_PI) *(angle_max - MIDDLE_ANGLE) / RESOLUTION_LASER));
}

void ALLaser::setDetectingLength(const AL::ALValue& length_min_l,const AL::ALValue& length_max_l){
  length_min=(int)length_min_l;
  length_max=(int)length_max_l;
  if(length_min<MIN_LENGTH_LASER) length_min = MIN_LENGTH_LASER;
  if(length_max>MAX_LENGTH_LASER) length_min = MAX_LENGTH_LASER;
  if(length_min>=length_max){
    length_min = MIN_LENGTH_LASER;
    length_max = MAX_LENGTH_LASER;
  }
  gSTM->insertData("Device/Laser/MinLength",(int)length_min);
  gSTM->insertData("Device/Laser/MaxLength",(int)length_max);
}

//_________________________________________________
// Service functions
//_________________________________________________

void connectToLaser(void){
  //const char device[] = "COM3"; /* Example when using Windows  */
  const char deviceACM[] = "/dev/ttyACM0"; /* Example when using Linux  */
  const char deviceUSB[] = "/dev/ttyUSB0"; /* Example when using Linux  */
  int ret;

  ret = urg_connect(&urg, deviceUSB, URG_DEFAULT_SPEED);
  if (ret < 0)
  {
    std::stringstream ss;
    ss << "Connection failure to " << deviceUSB << " at " << URG_DEFAULT_SPEED << ". " << urg_error(&urg);
    qiLogDebug("hardware.allaser") << ss.str() << std::endl;

    ret = urg_connect(&urg, deviceUSB, URG_FAST_SPEED);
    if (ret < 0)
    {
      std::stringstream ss;
      ss << "Connection failure to " << deviceUSB << " at " << URG_FAST_SPEED << ". " << urg_error(&urg);
      qiLogDebug("hardware.allaser") << ss.str() << std::endl;

      ret = urg_connect(&urg, deviceACM, URG_DEFAULT_SPEED);
      if (ret < 0)
      {
	    std::stringstream ss;
	    ss << "Connection failure to " << deviceACM << " at " << URG_DEFAULT_SPEED << ". " << urg_error(&urg);
	    qiLogDebug("hardware.allaser") << ss.str() << std::endl;

        ret = urg_connect(&urg, deviceACM, URG_FAST_SPEED);
        if (ret < 0)
        {
	      std::stringstream ss;
	      ss << "Connection failure to " << deviceACM << " at " << URG_FAST_SPEED << ". " << urg_error(&urg);
	      qiLogDebug("hardware.allaser") << ss.str() << std::endl;

          //rtprintf("ALLaser : Fail connecting to %s at %d: %s\n",deviceACM,URG_FAST_SPEED, urg_error(&urg));
          pthread_exit((void *)NULL);
        }
      }
      else
      {
        scip_ss(&urg.serial_, URG_FAST_SPEED);
        urg_disconnect(&urg);
        ret = urg_connect(&urg, deviceACM, URG_FAST_SPEED);
        if (ret < 0)
        {
	      std::stringstream ss;
	      ss << "Disconnect failure from " << deviceACM << " at " << URG_FAST_SPEED << ". " << urg_error(&urg);
	      qiLogDebug("hardware.allaser") << ss.str() << std::endl;

          pthread_exit((void *)NULL);
        }
      }
    }
  }
  else
  {
    /*switch to full speed*/
    scip_ss(&urg.serial_, URG_FAST_SPEED);
    urg_disconnect(&urg);
    ret = urg_connect(&urg, deviceUSB, URG_FAST_SPEED);
    if (ret < 0)
    {
	  std::stringstream ss;
	  ss << "Disconnect failure from " << deviceUSB << " at " << URG_FAST_SPEED << ". " << urg_error(&urg);
	  qiLogDebug("hardware.allaser") << ss.str() << std::endl;

      pthread_exit((void *)NULL);
    }
  }
}

unsigned int getLocalTime(void){
  struct timeval tv;
  unsigned int val;

  gettimeofday(&tv, NULL);

  val = (unsigned int)((unsigned int)(tv.tv_usec/1000) + (unsigned int)(tv.tv_sec*1000));

  // Time in ms
  return val;
}

double index2rad(int index){

  double radian = (2.0 * M_PI) *
                  (index - MIDDLE_ANGLE + angle_min) / RESOLUTION_LASER;

  return radian;
}
<commit_msg>ALLASER: added separate functions to connect to laser via USB and ACM<commit_after>/**
 * @author pinkasfeld joseph
 * Copyright (c) Aldebaran Robotics 2010, 2011 All Rights Reserved.
 */

#include "allaser.h"

#include <iostream>
#include <alcommon/alproxy.h>
#include <alproxies/almemoryproxy.h>
#include <boost/shared_ptr.hpp>
#include <alcommon/albroker.h>
#include <alcommon/almodule.h>
#include <sstream>

#include <pthread.h>
#include <signal.h>
#include <cmath>

#include <qi/log.hpp>

#if defined (__linux__)
#include <sys/prctl.h>
#endif

extern "C" {
# include "urg_ctrl.h"
# include "scip_handler.h"
}

#define MODE_ON 0
#define MODE_OFF 1
#define SEND_MODE_ON 2
#define SEND_MODE_OFF 3

#define MIDDLE_ANGLE 384
#define DEFAULT_MIN_ANGLE 43
#define DEFAULT_MAX_ANGLE 725
#define MIN_ANGLE_LASER 43
#define MAX_ANGLE_LASER 725
#define RESOLUTION_LASER 1024
#define MIN_LENGTH_LASER 20
#define MAX_LENGTH_LASER 5600

#include <sys/time.h>

using namespace AL;
using namespace std;
pthread_t urgThreadId;
boost::shared_ptr<ALMemoryProxy> gSTM;
static int mode = MODE_ON;
static urg_t urg;
static int angle_min = DEFAULT_MIN_ANGLE;
static int angle_max = DEFAULT_MAX_ANGLE;
static int length_min = MIN_LENGTH_LASER;
static int length_max = MAX_LENGTH_LASER;

static void urg_exit(urg_t *urg, const char *message) {
  qiLogInfo("hardware.allaser", "%s: %s\n", message, urg_error(urg));
  urg_disconnect(urg);
  qiLogInfo("hardware.allaser", "urg_exit\n");
  pthread_exit((void *)NULL);
}

#define URG_DEFAULT_SPEED (19200)
#define URG_FAST_SPEED (500000)

void * urgThread(void * arg) {

#if defined (__linux__)
  // thread name
  prctl(PR_SET_NAME, "ALLaser::urgThread", 0, 0, 0);
#endif

  ALValue urgdata;
  long *data = NULL;
  int data_max;
  int ret;
  int n;
  int i,imemory,refTime,end,sampleTime, beginThread;
  std::string valueName="Device/Laser/Value";

  /* Connection */

  connectToLaser();

  /* Reserve the Receive data buffer */
  data_max = urg_dataMax(&urg);
  data = (long*)malloc(sizeof(long) * data_max);
  if (data == NULL) {
    perror("data buffer");
    pthread_exit((void *)NULL);
  }
  /* prepare ALValue for ALMemory*/
  urgdata.arraySetSize(data_max);
  for (i=0; i< data_max;i++)
  {
    urgdata[i].arraySetSize(4);
    urgdata[i][0]= (int)0;
    urgdata[i][1]= (double)0.0;
    urgdata[i][2]= (int)0;
    urgdata[i][3]= (int)0;
  }
  /* insert ALvalue in ALMemory*/

  gSTM->insertData(valueName,urgdata);

  gSTM->insertData("Device/Laser/LaserEnable",(bool)1);
  gSTM->insertData("Device/Laser/MinAngle",(float)((2.0 * M_PI)*(DEFAULT_MIN_ANGLE - MIDDLE_ANGLE) / RESOLUTION_LASER));
  gSTM->insertData("Device/Laser/MaxAngle",(float)((2.0 * M_PI)*(DEFAULT_MAX_ANGLE - MIDDLE_ANGLE) / RESOLUTION_LASER));
  gSTM->insertData("Device/Laser/MinLength",(float)(length_min));
  gSTM->insertData("Device/Laser/MaxLength",(float)(length_max));

  printf("ALLASER Running\n");

  while(1)
  {
    if(mode==SEND_MODE_ON){
      ret = urg_laserOn(&urg);
      if (ret < 0) {
        urg_exit(&urg, "urg_requestData()");
      }
      mode=MODE_ON;
      /* Connection */
      connectToLaser();
    }
    if(mode==SEND_MODE_OFF){
      scip_qt(&urg.serial_, NULL, ScipNoWaitReply);
      mode=MODE_OFF;
    }
    if(mode==MODE_ON){
      /* Request Data using GD-Command */
      ret = urg_requestData(&urg, URG_GD, angle_min, angle_max);
      if (ret < 0) {
        urg_exit(&urg, "urg_requestData()");
      }

      refTime = getLocalTime();
      /* Obtain Data */
      n = urg_receiveData(&urg, data, data_max);
      if (n < 0) {
        urg_exit(&urg, "urg_receiveData()");
      }
      end= getLocalTime();
      sampleTime=end-refTime;

      imemory=0;
      for (i = 0; i < n; ++i) {
        int x, y;
        double angle=index2rad(i);
        int length = data[i];

        if((length>=length_min)&&(length<=length_max)){
          x = (int)((double)length * cos(angle));
          y = (int)((double)length * sin(angle));
          urgdata[imemory][0]= length;
          urgdata[imemory][1]= angle;
          urgdata[imemory][2]= x;
          urgdata[imemory][3]= y;
          imemory++;
        }
      }
      for(;imemory<data_max;imemory++){
        urgdata[imemory][0]= 0;
        urgdata[imemory][1]= 0;
        urgdata[imemory][2]= 0;
        urgdata[imemory][3]= 0;
      }
      gSTM->insertData(valueName,urgdata);
      usleep(1000);
    }else{
      usleep(10000);
    }
  }
  urg_disconnect(&urg);

  free(data);
}

//______________________________________________
// constructor
//______________________________________________
ALLaser::ALLaser(boost::shared_ptr<ALBroker> pBroker, const std::string& pName ): ALModule(pBroker, pName )
{
  setModuleDescription( "Allow control over Hokuyo laser when available on Nao's head." );

  functionName("laserOFF", "ALLaser", "Disable laser light");
  BIND_METHOD( ALLaser::laserOFF );

  functionName("laserON", "ALLaser", "Enable laser light and sampling");
  BIND_METHOD( ALLaser::laserON );

  functionName("setOpeningAngle", "ALLaser", "Set openning angle of the laser");
  addParam("angle_min_f", "float containing the min value in rad, this value must be upper than -2.35619449 ");
  addParam("angle_max_f", "float containing the max value in rad, this value must be lower than 2.092349795 ");
  addMethodExample( "python",
        "# Set the opening angle at -90/90 degres\n"
        "laser = ALProxy(\"ALLaser\",\"127.0.0.1\",9559)\n"
        "laser.setOpeningAngle(-1.570796327,1.570796327)\n"
      );
  BIND_METHOD( ALLaser::setOpeningAngle );

  functionName("setDetectingLength", "ALLaser", "Set detection threshold of the laser");
  addParam("length_min_l", "int containing the min length that the laser will detect(mm), this value must be upper than 20 mm");
  addParam("length_max_l", "int containing the max length that the laser will detect(mm), this value must be lower than 5600 mm");
  addMethodExample( "python",
        "# Set detection threshold at 500/3000 mm\n"
        "laser = ALProxy(\"ALLaser\",\"127.0.0.1\",9559)\n"
        "laser.setDetectingLength(500,3000)\n"
      );
  BIND_METHOD( ALLaser::setDetectingLength );

  // get broker on DCM and ALMemory
  try {
    gSTM = getParentBroker()->getMemoryProxy();
  } catch(ALError& e) {
    qiLogError("hardware.allaser") << "Could not connect to Memory. Error: " << e.what() << std::endl;
  }

  pthread_create(&urgThreadId, NULL, urgThread, NULL);
}

//______________________________________________
// destructor
//______________________________________________
ALLaser::~ALLaser()
{
  pthread_cancel(urgThreadId);
}

void ALLaser::laserOFF(void){
  mode = SEND_MODE_OFF;
  gSTM->insertData("Device/Laser/LaserEnable",(bool)0);
}

void ALLaser::laserON(void){
  mode = SEND_MODE_ON;
  gSTM->insertData("Device/Laser/LaserEnable",(bool)1);
}

void ALLaser::setOpeningAngle(const AL::ALValue& angle_min_f, const AL::ALValue& angle_max_f){
  angle_min = MIDDLE_ANGLE + (int)(RESOLUTION_LASER*(float)angle_min_f / (2.0 * M_PI));
  angle_max = MIDDLE_ANGLE + (int)(RESOLUTION_LASER*(float)angle_max_f / (2.0 * M_PI));
  if(angle_min<MIN_ANGLE_LASER) angle_min = MIN_ANGLE_LASER;
  if(angle_max>MAX_ANGLE_LASER) angle_max = MAX_ANGLE_LASER;
  if(angle_min>=angle_max){
    angle_min = MIN_ANGLE_LASER;
    angle_max = MAX_ANGLE_LASER;
  }
  gSTM->insertData("Device/Laser/MinAngle",(float)((2.0 * M_PI) *(angle_min - MIDDLE_ANGLE) / RESOLUTION_LASER));
  gSTM->insertData("Device/Laser/MaxAngle",(float)((2.0 * M_PI) *(angle_max - MIDDLE_ANGLE) / RESOLUTION_LASER));
}

void ALLaser::setDetectingLength(const AL::ALValue& length_min_l,const AL::ALValue& length_max_l){
  length_min=(int)length_min_l;
  length_max=(int)length_max_l;
  if(length_min<MIN_LENGTH_LASER) length_min = MIN_LENGTH_LASER;
  if(length_max>MAX_LENGTH_LASER) length_min = MAX_LENGTH_LASER;
  if(length_min>=length_max){
    length_min = MIN_LENGTH_LASER;
    length_max = MAX_LENGTH_LASER;
  }
  gSTM->insertData("Device/Laser/MinLength",(int)length_min);
  gSTM->insertData("Device/Laser/MaxLength",(int)length_max);
}

//_________________________________________________
// Service functions
//_________________________________________________

int connectToLaserViaUSB(void) {
  int success = -1;
  const char deviceUSB[] = "/dev/ttyUSB0"; /* Example when using Linux  */
  // Try to connect at low speed.
  success = urg_connect(&urg, deviceUSB, URG_DEFAULT_SPEED);
  if (success < 0) {
    std::stringstream ss;
    ss << "Connection failure to " << deviceUSB << " at " << URG_DEFAULT_SPEED << ". " << urg_error(&urg);
    qiLogDebug("hardware.allaser") << ss.str() << std::endl;
    return success;
  }
  else {
    // Try to switch to full speed.
    scip_ss(&urg.serial_, URG_FAST_SPEED);
    urg_disconnect(&urg);
    success = urg_connect(&urg, deviceUSB, URG_FAST_SPEED);
    if (success < 0) {
      std::stringstream ss;
      ss << "Connection failure to " << deviceUSB << " at " << URG_FAST_SPEED << ". " << urg_error(&urg);
      qiLogDebug("hardware.allaser") << ss.str() << std::endl;
      // Fall back to low speed.
      success = urg_connect(&urg, deviceUSB, URG_DEFAULT_SPEED);
      return success;
    }
    else {
      return success;
    }
  }
}

int connectToLaserViaACM(void) {
  int success = -1;
  const char deviceACM[] = "/dev/ttyACM0"; /* Example when using Linux  */
  success = urg_connect(&urg, deviceACM, URG_DEFAULT_SPEED);
  if (success < 0) {
    std::stringstream ss;
    ss << "Connection failure to " << deviceACM << " at " << URG_DEFAULT_SPEED << ". " << urg_error(&urg);
    qiLogDebug("hardware.allaser") << ss.str() << std::endl;
    return success;
  }
  else {
    // Try to switch to full speed.
    scip_ss(&urg.serial_, URG_FAST_SPEED);
    urg_disconnect(&urg);
    success = urg_connect(&urg, deviceACM, URG_FAST_SPEED);
    if (success < 0)
    {
      std::stringstream ss;
      ss << "Connection failure from " << deviceACM << " at " << URG_FAST_SPEED << ". " << urg_error(&urg);
      qiLogDebug("hardware.allaser") << ss.str() << std::endl;
      // Fall back to low speed.
      success = urg_connect(&urg, deviceACM, URG_DEFAULT_SPEED);
      return success;
    }
    else {
      return success;
    }
  }
}

void connectToLaser(void){
  //const char device[] = "COM3"; /* Example when using Windows  */
  const char deviceACM[] = "/dev/ttyACM0"; /* Example when using Linux  */
  const char deviceUSB[] = "/dev/ttyUSB0"; /* Example when using Linux  */
  int ret;

  ret = urg_connect(&urg, deviceUSB, URG_DEFAULT_SPEED);
  if (ret < 0)
  {
    std::stringstream ss;
    ss << "Connection failure to " << deviceUSB << " at " << URG_DEFAULT_SPEED << ". " << urg_error(&urg);
    qiLogDebug("hardware.allaser") << ss.str() << std::endl;

    ret = urg_connect(&urg, deviceUSB, URG_FAST_SPEED);
    if (ret < 0)
    {
      std::stringstream ss;
      ss << "Connection failure to " << deviceUSB << " at " << URG_FAST_SPEED << ". " << urg_error(&urg);
      qiLogDebug("hardware.allaser") << ss.str() << std::endl;

      ret = urg_connect(&urg, deviceACM, URG_DEFAULT_SPEED);
      if (ret < 0)
      {
	    std::stringstream ss;
	    ss << "Connection failure to " << deviceACM << " at " << URG_DEFAULT_SPEED << ". " << urg_error(&urg);
	    qiLogDebug("hardware.allaser") << ss.str() << std::endl;

        ret = urg_connect(&urg, deviceACM, URG_FAST_SPEED);
        if (ret < 0)
        {
	      std::stringstream ss;
	      ss << "Connection failure to " << deviceACM << " at " << URG_FAST_SPEED << ". " << urg_error(&urg);
	      qiLogDebug("hardware.allaser") << ss.str() << std::endl;

          //rtprintf("ALLaser : Fail connecting to %s at %d: %s\n",deviceACM,URG_FAST_SPEED, urg_error(&urg));
          pthread_exit((void *)NULL);
        }
      }
      else
      {
        scip_ss(&urg.serial_, URG_FAST_SPEED);
        urg_disconnect(&urg);
        ret = urg_connect(&urg, deviceACM, URG_FAST_SPEED);
        if (ret < 0)
        {
	      std::stringstream ss;
	      ss << "Disconnect failure from " << deviceACM << " at " << URG_FAST_SPEED << ". " << urg_error(&urg);
	      qiLogDebug("hardware.allaser") << ss.str() << std::endl;

          pthread_exit((void *)NULL);
        }
      }
    }
  }
  else
  {
    /*switch to full speed*/
    scip_ss(&urg.serial_, URG_FAST_SPEED);
    urg_disconnect(&urg);
    ret = urg_connect(&urg, deviceUSB, URG_FAST_SPEED);
    if (ret < 0)
    {
	  std::stringstream ss;
	  ss << "Disconnect failure from " << deviceUSB << " at " << URG_FAST_SPEED << ". " << urg_error(&urg);
	  qiLogDebug("hardware.allaser") << ss.str() << std::endl;

      pthread_exit((void *)NULL);
    }
  }
}

unsigned int getLocalTime(void){
  struct timeval tv;
  unsigned int val;

  gettimeofday(&tv, NULL);

  val = (unsigned int)((unsigned int)(tv.tv_usec/1000) + (unsigned int)(tv.tv_sec*1000));

  // Time in ms
  return val;
}

double index2rad(int index){

  double radian = (2.0 * M_PI) *
                  (index - MIDDLE_ANGLE + angle_min) / RESOLUTION_LASER;

  return radian;
}
<|endoftext|>


<commit_before>#include "internal.hpp"

#include "clause.hpp"
#include "iterator.hpp"
#include "proof.hpp"
#include "macros.hpp"
#include "message.hpp"

#include <algorithm>

namespace CaDiCaL {

/*------------------------------------------------------------------------*/

void Internal::learn_empty_clause () {
  assert (!unsat);
  LOG ("learned empty clause");
  if (proof) proof->trace_empty_clause ();
  unsat = true;
}

void Internal::learn_unit_clause (int lit) {
  LOG ("learned unit clause %d", lit);
  if (proof) proof->trace_unit_clause (lit);
  iterating = true;
  stats.fixed++;
}

/*------------------------------------------------------------------------*/

// Important variables recently used in conflict analysis are 'bumped',
// which means to move them to the front of the VMTF decision queue.  The
// 'bumped' time stamp is updated accordingly.  It is used to determine
// whether the 'queue.assigned' pointer has to be moved in 'unassign'.

void Internal::bump_variable (Var * v) {
  if (!v->next) return;
  if (queue.assigned == v) queue.assigned = v->prev ? v->prev : v->next;
  queue.dequeue (v), queue.enqueue (v);
  v->bumped = ++stats.bumped;
  int idx = var2idx (v);
  if (!vals[idx]) queue.assigned = v;
  LOG ("VMTF bumped and moved to front %d", idx);
}

// Initially we proposed to bump the variable in the current 'bumped' stamp
// order only.  This maintains the current order between bumped variables.
// On few benchmarks this however lead to a large number of propagations per
// seconds, which can be reduced by an order of magnitude by focusing
// somewhat on recently assigned variables more, particularly in this
// situation.  This can easily be achieved by using the sum of the 'bumped'
// time stamp and trail height 'trail' for comparison.  Note that 'bumped'
// is always increasing and gets really large, while 'trail' can never be
// larger than the number of variables, so there is likely a potential for
// further optimization.

struct bump_earlier {
  Internal * internal;
  bump_earlier (Internal * s) : internal (s) { }
  bool operator () (int a, int b) {
    Var & u = internal->var (a), & v = internal->var (b);
    return u.bumped + u.trail < v.bumped + v.trail;
  }
};

void Internal::bump_variables () {
  START (bump);
  reverse (seen.begin (), seen.end ());
  stable_sort (seen.begin (), seen.end (), bump_earlier (this));
  for (const_int_iterator i = seen.begin (); i != seen.end (); i++)
    bump_variable (&var (*i));
  STOP (bump);
}

/*------------------------------------------------------------------------*/

// Clause activity is replaced by a move to front scheme as well with
// 'resolved' as time stamp.  Only long and high glue clauses are stamped
// since small or low glue clauses are kept anyhow (and do not actually have
// a 'resolved' field).  We keep the relative order of bumped clauses by
// sorting them first.

void Internal::bump_resolved_clauses () {
  START (bump);
  sort (resolved.begin (), resolved.end (), resolved_earlier ());
  for (const_clause_iterator i = resolved.begin (); i != resolved.end (); i++)
    (*i)->resolved () = ++stats.resolved;
  STOP (bump);
  resolved.clear ();
}

void Internal::resolve_clause (Clause * c) {
  if (!c->redundant) return;
  if (c->size <= opts.keepsize) return;
  if (c->glue <= opts.keepglue) return;
  assert (c->extended);
  resolved.push_back (c);
}

/*------------------------------------------------------------------------*/

// During conflict analysis literals not seen yet either become part of the
// first-uip clauses (if on lower decision level), are dropped (if fixed),
// or are resolved away (if on the current decision level and different from
// the first UIP).  At the same time we update the number of seen literals on
// a decision level and the smallest trail position of a seen literal for
// each decision level.  This both helps conflict clause minimization.  The
// number of seen levels is the glucose level (also called glue, or LBD).

inline bool Internal::analyze_literal (int lit) {
  Var & v = var (lit);
  if (v.seen) return false;
  if (!v.level) return false;
  assert (val (lit) < 0);
  if (v.level < level) clause.push_back (lit);
  Level & l = control[v.level];
  if (!l.seen++) {
    LOG ("found new level %d contributing to conflict", v.level);
    levels.push_back (v.level);
  }
  if (v.trail < l.trail) l.trail = v.trail;
  v.seen = true;
  seen.push_back (lit);
  LOG ("analyzed literal %d assigned at level %d", lit, v.level);
  return v.level == level;
}

/*------------------------------------------------------------------------*/

void Internal::clear_seen () {
  for (const_int_iterator i = seen.begin (); i != seen.end (); i++)
    var (*i).seen = false;
  seen.clear ();
}

void Internal::clear_levels () {
  for (const_int_iterator i = levels.begin (); i != levels.end (); i++)
    control[*i].reset ();
  levels.clear ();
}

/*------------------------------------------------------------------------*/

// By sorting the first UIP clause literals, we establish the invariant that
// the two watched literals are on the largest decision highest level.

struct trail_greater {
  Internal * internal;
  trail_greater (Internal * s) : internal (s) { }
  bool operator () (int a, int b) {
    return internal->var (a).trail > internal->var (b).trail;
  }
};

void Internal::analyze () {
  assert (conflict);
  if (!level) { learn_empty_clause (); conflict = 0; return; }

  START (analyze);

  // First derive the first UIP clause.
  //
  Clause * reason = conflict;
  LOG (reason, "analyzing conflict");
  resolve_clause (reason);
  int open = 0, uip = 0;
  const_int_iterator i = trail.end ();
  for (;;) {
    const const_literal_iterator end = reason->end ();
    const_literal_iterator j = reason->begin ();
    while (j != end)
      if (analyze_literal (*j++))
	open++;
    while (!var (uip = *--i).seen)
      ;
    if (!--open) break;
    reason = var (uip).reason;
    LOG (reason, "analyzing %d reason", uip);
  }
  LOG ("first UIP %d", uip);
  clause.push_back (-uip);
  check_clause ();

  // Update glue statistics.
  //
  bump_resolved_clauses ();
  const int glue = (int) levels.size ();
  LOG ("1st UIP clause of size %d and glue %d", (int) clause.size (), glue);
  UPDATE_AVG (fast_glue_avg, glue);
  UPDATE_AVG (slow_glue_avg, glue);

  if (opts.minimize) minimize_clause ();	// minimize clause

  stats.units += (clause.size () == 1);
  stats.binaries += (clause.size () == 2);

  bump_variables ();                         // Update decision heuristics.

  // Determine back jump level, backtrack and assign flipped literal.
  //
  Clause * driving_clause = 0;
  int jump = 0;
  if (clause.size () > 1) {
    sort (clause.begin (), clause.end (), trail_greater (this));
    driving_clause = new_learned_clause (glue);
    jump = var (clause[1]).level;
  }
  UPDATE_AVG (jump_avg, jump);
  backtrack (jump);
  assign (-uip, driving_clause);

  // Clean up.
  //
  clear_seen ();
  clause.clear ();
  clear_levels ();
  conflict = 0;

  STOP (analyze);
}

// We wait reporting a learned unit until propagation of that unit is
// completed.  Otherwise the 'i' report line might prematurely give the
// number of remaining variables.

void Internal::iterate () { iterating = false; report ('i'); }

};
<commit_msg>moved variable bumping thus same as 015<commit_after>#include "internal.hpp"

#include "clause.hpp"
#include "iterator.hpp"
#include "proof.hpp"
#include "macros.hpp"
#include "message.hpp"

#include <algorithm>

namespace CaDiCaL {

/*------------------------------------------------------------------------*/

void Internal::learn_empty_clause () {
  assert (!unsat);
  LOG ("learned empty clause");
  if (proof) proof->trace_empty_clause ();
  unsat = true;
}

void Internal::learn_unit_clause (int lit) {
  LOG ("learned unit clause %d", lit);
  if (proof) proof->trace_unit_clause (lit);
  iterating = true;
  stats.fixed++;
}

/*------------------------------------------------------------------------*/

// Important variables recently used in conflict analysis are 'bumped',
// which means to move them to the front of the VMTF decision queue.  The
// 'bumped' time stamp is updated accordingly.  It is used to determine
// whether the 'queue.assigned' pointer has to be moved in 'unassign'.

void Internal::bump_variable (Var * v) {
  if (!v->next) return;
  if (queue.assigned == v) queue.assigned = v->prev ? v->prev : v->next;
  queue.dequeue (v), queue.enqueue (v);
  v->bumped = ++stats.bumped;
  int idx = var2idx (v);
  if (!vals[idx]) queue.assigned = v;
  LOG ("VMTF bumped and moved to front %d", idx);
}

// Initially we proposed to bump the variable in the current 'bumped' stamp
// order only.  This maintains the current order between bumped variables.
// On few benchmarks this however lead to a large number of propagations per
// seconds, which can be reduced by an order of magnitude by focusing
// somewhat on recently assigned variables more, particularly in this
// situation.  This can easily be achieved by using the sum of the 'bumped'
// time stamp and trail height 'trail' for comparison.  Note that 'bumped'
// is always increasing and gets really large, while 'trail' can never be
// larger than the number of variables, so there is likely a potential for
// further optimization.

struct bump_earlier {
  Internal * internal;
  bump_earlier (Internal * s) : internal (s) { }
  bool operator () (int a, int b) {
    Var & u = internal->var (a), & v = internal->var (b);
    return u.bumped + u.trail < v.bumped + v.trail;
  }
};

void Internal::bump_variables () {
  START (bump);
  sort (seen.begin (), seen.end (), bump_earlier (this));
  for (const_int_iterator i = seen.begin (); i != seen.end (); i++)
    bump_variable (&var (*i));
  STOP (bump);
}

/*------------------------------------------------------------------------*/

// Clause activity is replaced by a move to front scheme as well with
// 'resolved' as time stamp.  Only long and high glue clauses are stamped
// since small or low glue clauses are kept anyhow (and do not actually have
// a 'resolved' field).  We keep the relative order of bumped clauses by
// sorting them first.

void Internal::bump_resolved_clauses () {
  START (bump);
  sort (resolved.begin (), resolved.end (), resolved_earlier ());
  for (const_clause_iterator i = resolved.begin (); i != resolved.end (); i++)
    (*i)->resolved () = ++stats.resolved;
  STOP (bump);
  resolved.clear ();
}

void Internal::resolve_clause (Clause * c) {
  if (!c->redundant) return;
  if (c->size <= opts.keepsize) return;
  if (c->glue <= opts.keepglue) return;
  assert (c->extended);
  resolved.push_back (c);
}

/*------------------------------------------------------------------------*/

// During conflict analysis literals not seen yet either become part of the
// first-uip clauses (if on lower decision level), are dropped (if fixed),
// or are resolved away (if on the current decision level and different from
// the first UIP).  At the same time we update the number of seen literals on
// a decision level and the smallest trail position of a seen literal for
// each decision level.  This both helps conflict clause minimization.  The
// number of seen levels is the glucose level (also called glue, or LBD).

inline bool Internal::analyze_literal (int lit) {
  Var & v = var (lit);
  if (v.seen) return false;
  if (!v.level) return false;
  assert (val (lit) < 0);
  if (v.level < level) clause.push_back (lit);
  Level & l = control[v.level];
  if (!l.seen++) {
    LOG ("found new level %d contributing to conflict", v.level);
    levels.push_back (v.level);
  }
  if (v.trail < l.trail) l.trail = v.trail;
  v.seen = true;
  seen.push_back (lit);
  LOG ("analyzed literal %d assigned at level %d", lit, v.level);
  return v.level == level;
}

/*------------------------------------------------------------------------*/

void Internal::clear_seen () {
  for (const_int_iterator i = seen.begin (); i != seen.end (); i++)
    var (*i).seen = false;
  seen.clear ();
}

void Internal::clear_levels () {
  for (const_int_iterator i = levels.begin (); i != levels.end (); i++)
    control[*i].reset ();
  levels.clear ();
}

/*------------------------------------------------------------------------*/

// By sorting the first UIP clause literals, we establish the invariant that
// the two watched literals are on the largest decision highest level.

struct trail_greater {
  Internal * internal;
  trail_greater (Internal * s) : internal (s) { }
  bool operator () (int a, int b) {
    return internal->var (a).trail > internal->var (b).trail;
  }
};

void Internal::analyze () {
  assert (conflict);
  if (!level) { learn_empty_clause (); conflict = 0; return; }

  START (analyze);

  // First derive the first UIP clause.
  //
  Clause * reason = conflict;
  LOG (reason, "analyzing conflict");
  resolve_clause (reason);
  int open = 0, uip = 0;
  const_int_iterator i = trail.end ();
  for (;;) {
    const const_literal_iterator end = reason->end ();
    const_literal_iterator j = reason->begin ();
    while (j != end)
      if (analyze_literal (*j++))
	open++;
    while (!var (uip = *--i).seen)
      ;
    if (!--open) break;
    reason = var (uip).reason;
    LOG (reason, "analyzing %d reason", uip);
  }
  LOG ("first UIP %d", uip);
  clause.push_back (-uip);
  check_clause ();

  // Update glue statistics.
  //
  bump_resolved_clauses ();
  const int glue = (int) levels.size ();
  LOG ("1st UIP clause of size %d and glue %d", (int) clause.size (), glue);
  UPDATE_AVG (fast_glue_avg, glue);
  UPDATE_AVG (slow_glue_avg, glue);

  if (opts.minimize) minimize_clause ();	// minimize clause

  stats.units += (clause.size () == 1);
  stats.binaries += (clause.size () == 2);

  // Determine back jump level, backtrack and assign flipped literal.
  //
  Clause * driving_clause = 0;
  int jump = 0;
  if (clause.size () > 1) {
    sort (clause.begin (), clause.end (), trail_greater (this));
    driving_clause = new_learned_clause (glue);
    jump = var (clause[1]).level;
  }
  UPDATE_AVG (jump_avg, jump);
  backtrack (jump);
  assign (-uip, driving_clause);

  bump_variables ();                         // Update decision heuristics.

  // Clean up.
  //
  clear_seen ();
  clause.clear ();
  clear_levels ();
  conflict = 0;

  STOP (analyze);
}

// We wait reporting a learned unit until propagation of that unit is
// completed.  Otherwise the 'i' report line might prematurely give the
// number of remaining variables.

void Internal::iterate () { iterating = false; report ('i'); }

};
<|endoftext|>


<commit_before>//  Copyright 2020 Tangent Animation
//
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
//  including without limitation, as related to merchantability and fitness
//  for a particular purpose.
//
//  In no event shall any copyright holder be liable for any damages of any kind
//  arising from the use of this software, whether in contract, tort or otherwise.
//  See the License for the specific language governing permissions and
//  limitations under the License.

#include "renderPass.h"

#include "camera.h"
#include "renderBuffer.h"
#include "renderParam.h"
#include "utils.h"

#include <render/camera.h>
#include <render/scene.h>
#include <render/session.h>
#include <util/util_types.h>

#include <pxr/base/tf/staticTokens.h>
#include <pxr/imaging/hd/camera.h>
#include <pxr/imaging/hd/renderPassState.h>

PXR_NAMESPACE_OPEN_SCOPE

// clang-format off
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-variable"
#endif
TF_DEFINE_PRIVATE_TOKENS(_tokens,
    (color)
    (depth)
);
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
// clang-format on

HdCyclesRenderPass::HdCyclesRenderPass(HdCyclesRenderDelegate* delegate,
                                       HdRenderIndex* index,
                                       HdRprimCollection const& collection)
    : HdRenderPass(index, collection)
    , m_delegate(delegate)
{
}

HdCyclesRenderPass::~HdCyclesRenderPass() {}

void
HdCyclesRenderPass::_Execute(HdRenderPassStateSharedPtr const& renderPassState,
                             TfTokenVector const& renderTags)
{
    auto* renderParam = reinterpret_cast<HdCyclesRenderParam*>(
        m_delegate->GetRenderParam());

    HdRenderPassAovBindingVector aovBindings = renderPassState->GetAovBindings();

    if (renderParam->GetAovBindings() != aovBindings) {
        renderParam->SetAovBindings(aovBindings);
        if(!aovBindings.empty()) {
            renderParam->SetDisplayAov(aovBindings[0]);
        }
    }

    const auto vp = renderPassState->GetViewport();

    GfMatrix4d projMtx = renderPassState->GetProjectionMatrix();
    GfMatrix4d viewMtx = renderPassState->GetWorldToViewMatrix();

    m_isConverged = renderParam->IsConverged();

    // XXX: Need to cast away constness to process updated camera params since
    // the Hydra camera doesn't update the Cycles camera directly.
    HdCyclesCamera* hdCam = const_cast<HdCyclesCamera*>(
        dynamic_cast<HdCyclesCamera const*>(renderPassState->GetCamera()));

    ccl::Camera* active_camera = renderParam->GetCyclesSession()->scene->camera;

    bool shouldUpdate = false;

    if (projMtx != m_projMtx || viewMtx != m_viewMtx) {
        m_projMtx = projMtx;
        m_viewMtx = viewMtx;

        const float fov_rad = atan(1.0f / m_projMtx[1][1]) * 2.0f;
        hdCam->SetFOV(fov_rad);

        shouldUpdate = true;
    }

    if(!shouldUpdate)
        shouldUpdate = hdCam->IsDirty();

    if (shouldUpdate) {
        hdCam->ApplyCameraSettings(active_camera);

        // Needed for now, as houdini looks through a generated camera
        // and doesn't copy the projection type (as of 18.0.532)
        bool is_ortho = round(m_projMtx[3][3]) == 1.0;

        if (is_ortho) {
            active_camera->type = ccl::CameraType::CAMERA_ORTHOGRAPHIC;
        } else
            active_camera->type = ccl::CameraType::CAMERA_PERSPECTIVE;

        active_camera->tag_update();

        // DirectReset here instead of Interrupt for faster IPR camera orbits
        renderParam->DirectReset();
    }

    const auto width     = static_cast<int>(vp[2]);
    const auto height    = static_cast<int>(vp[3]);

    if (width != m_width || height != m_height) {
        m_width                 = width;
        m_height                = height;

        // TODO: Due to the startup flow of Cycles, this gets called after a tiled render
        // has already started. Sometimes causing the original tiled render to complete
        // before actually rendering at the appropriate size. This seems to be a Cycles
        // issue, however the startup flow of HdCycles has LOTS of room for improvement...
        renderParam->SetViewport(m_width, m_height);

        // TODO: This is very hacky... But stops the tiled render double render issue...
        if (renderParam->IsTiledRender()) {
            renderParam->StartRender();
        }

        renderParam->Interrupt();
    }

    // Tiled renders early out because we do the blitting on render tile callback
    if (renderParam->IsTiledRender())
        return;

    if (!renderParam->GetCyclesSession())
        return;

    if (!renderParam->GetCyclesScene())
        return;

    ccl::DisplayBuffer* display = renderParam->GetCyclesSession()->display;

    if (!display)
        return;

    renderParam->GetCyclesSession()->acquire_display();
    HdFormat colorFormat = display->half_float ? HdFormatFloat16Vec4
                                               : HdFormatUNorm8Vec4;

    unsigned char* hpixels
        = (display->half_float)
              ? (unsigned char*)display->rgba_half.host_pointer
              : (unsigned char*)display->rgba_byte.host_pointer;

    if (!hpixels) {
        renderParam->GetCyclesSession()->release_display();
        return;
    }

    int w = display->draw_width;
    int h = display->draw_height;

    if (w == 0 || h == 0) {
        renderParam->GetCyclesSession()->release_display();
        return;
    }

    // Blit
    if (!aovBindings.empty()) {
        // Blit from the framebuffer to currently selected aovs...
        for (auto& aov : aovBindings) {
            if (!TF_VERIFY(aov.renderBuffer != nullptr)) {
                continue;
            }

            auto* rb = static_cast<HdCyclesRenderBuffer*>(aov.renderBuffer);
            rb->SetConverged(m_isConverged);

            // Needed as a stopgap, because Houdini dellocates renderBuffers
            // when changing render settings. This causes the current blit to
            // fail (Probably can be fixed with proper render thread management)
            if (!rb->WasUpdated()) {
                if (aov.aovName == renderParam->GetDisplayAovToken()) {
                    rb->Blit(colorFormat, w, h, 0, w,
                             reinterpret_cast<uint8_t*>(hpixels));
                }
            } else {
                rb->SetWasUpdated(false);
            }
        }
    }

    renderParam->GetCyclesSession()->release_display();
}

PXR_NAMESPACE_CLOSE_SCOPE
<commit_msg>Changed logic to use Cycles lock<commit_after>//  Copyright 2020 Tangent Animation
//
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
//  including without limitation, as related to merchantability and fitness
//  for a particular purpose.
//
//  In no event shall any copyright holder be liable for any damages of any kind
//  arising from the use of this software, whether in contract, tort or otherwise.
//  See the License for the specific language governing permissions and
//  limitations under the License.

#include "renderPass.h"

#include "camera.h"
#include "renderBuffer.h"
#include "renderParam.h"
#include "utils.h"

#include <render/camera.h>
#include <render/scene.h>
#include <render/session.h>
#include <util/util_types.h>

#include <pxr/base/tf/staticTokens.h>
#include <pxr/imaging/hd/camera.h>
#include <pxr/imaging/hd/renderPassState.h>

PXR_NAMESPACE_OPEN_SCOPE

// clang-format off
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-variable"
#endif
TF_DEFINE_PRIVATE_TOKENS(_tokens,
    (color)
    (depth)
);
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
// clang-format on

HdCyclesRenderPass::HdCyclesRenderPass(HdCyclesRenderDelegate* delegate,
                                       HdRenderIndex* index,
                                       HdRprimCollection const& collection)
    : HdRenderPass(index, collection)
    , m_delegate(delegate)
{
}

HdCyclesRenderPass::~HdCyclesRenderPass() {}

void
HdCyclesRenderPass::_Execute(HdRenderPassStateSharedPtr const& renderPassState,
                             TfTokenVector const& renderTags)
{
    auto* renderParam = reinterpret_cast<HdCyclesRenderParam*>(
        m_delegate->GetRenderParam());

    HdRenderPassAovBindingVector aovBindings = renderPassState->GetAovBindings();

    if (renderParam->GetAovBindings() != aovBindings) {
        renderParam->SetAovBindings(aovBindings);
        if(!aovBindings.empty()) {
            renderParam->SetDisplayAov(aovBindings[0]);
        }
    }

    const auto vp = renderPassState->GetViewport();

    GfMatrix4d projMtx = renderPassState->GetProjectionMatrix();
    GfMatrix4d viewMtx = renderPassState->GetWorldToViewMatrix();

    m_isConverged = renderParam->IsConverged();

    // XXX: Need to cast away constness to process updated camera params since
    // the Hydra camera doesn't update the Cycles camera directly.
    HdCyclesCamera* hdCam = const_cast<HdCyclesCamera*>(
        dynamic_cast<HdCyclesCamera const*>(renderPassState->GetCamera()));

    ccl::Camera* active_camera = renderParam->GetCyclesSession()->scene->camera;

    bool shouldUpdate = false;

    if (projMtx != m_projMtx || viewMtx != m_viewMtx) {
        m_projMtx = projMtx;
        m_viewMtx = viewMtx;

        const float fov_rad = atan(1.0f / m_projMtx[1][1]) * 2.0f;
        hdCam->SetFOV(fov_rad);

        shouldUpdate = true;
    }

    if(!shouldUpdate)
        shouldUpdate = hdCam->IsDirty();

    if (shouldUpdate) {
        hdCam->ApplyCameraSettings(active_camera);

        // Needed for now, as houdini looks through a generated camera
        // and doesn't copy the projection type (as of 18.0.532)
        bool is_ortho = round(m_projMtx[3][3]) == 1.0;

        if (is_ortho) {
            active_camera->type = ccl::CameraType::CAMERA_ORTHOGRAPHIC;
        } else
            active_camera->type = ccl::CameraType::CAMERA_PERSPECTIVE;

        active_camera->tag_update();

        // DirectReset here instead of Interrupt for faster IPR camera orbits
        renderParam->DirectReset();
    }

    const auto width     = static_cast<int>(vp[2]);
    const auto height    = static_cast<int>(vp[3]);

    if (width != m_width || height != m_height) {
        m_width                 = width;
        m_height                = height;

        // TODO: Due to the startup flow of Cycles, this gets called after a tiled render
        // has already started. Sometimes causing the original tiled render to complete
        // before actually rendering at the appropriate size. This seems to be a Cycles
        // issue, however the startup flow of HdCycles has LOTS of room for improvement...
        renderParam->SetViewport(m_width, m_height);

        // TODO: This is very hacky... But stops the tiled render double render issue...
        if (renderParam->IsTiledRender()) {
            renderParam->StartRender();
        }

        renderParam->Interrupt();
    }

    // Tiled renders early out because we do the blitting on render tile callback
    if (renderParam->IsTiledRender())
        return;

    if (!renderParam->GetCyclesSession())
        return;

    if (!renderParam->GetCyclesScene())
        return;

    ccl::DisplayBuffer* display = renderParam->GetCyclesSession()->display;

    if (!display)
        return;

    ccl::thread_scoped_lock display_lock = renderParam->GetCyclesSession()->acquire_display_lock();

    HdFormat colorFormat = display->half_float ? HdFormatFloat16Vec4
                                               : HdFormatUNorm8Vec4;

    unsigned char* hpixels
        = (display->half_float)
              ? (unsigned char*)display->rgba_half.host_pointer
              : (unsigned char*)display->rgba_byte.host_pointer;

    if (!hpixels)
        return;

    int w = display->draw_width;
    int h = display->draw_height;

    if (w == 0 || h == 0)
        return;

    // Blit
    if (!aovBindings.empty()) {
        // Blit from the framebuffer to currently selected aovs...
        for (auto& aov : aovBindings) {
            if (!TF_VERIFY(aov.renderBuffer != nullptr)) {
                continue;
            }

            auto* rb = static_cast<HdCyclesRenderBuffer*>(aov.renderBuffer);
            rb->SetConverged(m_isConverged);

            // Needed as a stopgap, because Houdini dellocates renderBuffers
            // when changing render settings. This causes the current blit to
            // fail (Probably can be fixed with proper render thread management)
            if (!rb->WasUpdated()) {
                if (aov.aovName == renderParam->GetDisplayAovToken()) {
                    rb->Blit(colorFormat, w, h, 0, w,
                             reinterpret_cast<uint8_t*>(hpixels));
                }
            } else {
                rb->SetWasUpdated(false);
            }
        }
    }
}

PXR_NAMESPACE_CLOSE_SCOPE
<|endoftext|>


<commit_before>/*=============================================================================
Copyright (C) 2021 yumetodo <yume-wikijp@live.jp>
Distributed under the Boost Software License, Version 1.0.
(See http://www.boost.org/LICENSE_1_0.txt)
=============================================================================*/
#ifndef YUMETODO_INFERIOR_IOTA_VIEW_HPP_
#define YUMETODO_INFERIOR_IOTA_VIEW_HPP_
#include <cstddef>
#include <iterator>
namespace inferior {
	namespace ranges {
		namespace detail {
			template<typename T, std::enable_if_t<std::is_arithmetic<T>::value, nullptr_t> = nullptr>
			class iota_view_iterator {
			private:
				T i;
			public:
				using iterator_category = std::random_access_iterator_tag;
				using iterator_concept = std::random_access_iterator_tag;
				using value_type = T;
				using difference_type = std::ptrdiff_t;
				using pointer = T*;
				using reference = T;

				constexpr iota_view_iterator() : i() { }
				constexpr iota_view_iterator(T n) : i(n) { }
				constexpr iota_view_iterator& operator=(const iota_view_iterator& o) noexcept {
					i = o.i;
					return *this;
				}
				constexpr bool operator == (const iota_view_iterator& rhs) const noexcept { return i == rhs.i; }
				constexpr bool operator != (const iota_view_iterator& rhs) const noexcept { return i != rhs.i; }
				constexpr T operator * () const noexcept { return i; }
				constexpr T operator[](difference_type n) const noexcept { return static_cast<T>(i + n); }
				constexpr iota_view_iterator operator+(difference_type n) const noexcept { return{ static_cast<T>(i + n) }; }
				constexpr iota_view_iterator operator-(difference_type n) const noexcept { return{ static_cast<T>(i - n) }; }
				constexpr difference_type operator-(const iota_view_iterator& it) const noexcept { return static_cast<difference_type>(i - it.i); }
				constexpr bool operator<(const iota_view_iterator& n) const noexcept { return i < n.i; }
				constexpr bool operator<=(const iota_view_iterator& n) const noexcept { return i <= n.i; }
				constexpr bool operator>(const iota_view_iterator& n) const noexcept { return i > n.i; }
				constexpr bool operator>=(const iota_view_iterator& n) const noexcept { return i >= n.i; }
				constexpr iota_view_iterator& operator += (iota_view_iterator it) noexcept {
					i = static_cast<T>(i + it.i);
					return *this;
				}
				constexpr iota_view_iterator& operator -= (iota_view_iterator it) noexcept {
					i = static_cast<T>(i - it.i);
					return *this;
				}
				constexpr iota_view_iterator& operator ++ () noexcept {
					++i;
					return *this;
				}
				constexpr iota_view_iterator operator ++ (int) noexcept {
					auto t = *this;
					++i;
					return t;
				}
				constexpr iota_view_iterator& operator -- () noexcept {
					--i;
					return *this;
				}
				constexpr iota_view_iterator operator -- (int) noexcept {
					auto t = *this;
					--i;
					return t;
				}
			};
			template<typename T>
			constexpr iota_view_iterator<T> operator+(typename iota_view_iterator<T>::difference_type n, const iota_view_iterator<T>& it) noexcept { return static_cast<T>(it + n); }
		}
		template<typename T, std::enable_if_t<std::is_arithmetic<T>::value, nullptr_t> = nullptr>
		class iota_view {
		public:
			using value_type = std::remove_cv_t<T>;
			using iterator = detail::iota_view_iterator<value_type>;
		private:
			value_type begin_, end_;
		public:
			constexpr iota_view(T n) : begin_(0), end_(n) {}
			constexpr iota_view(T begin, T end) : begin_(begin), end_(end) {}
			constexpr iterator begin() const noexcept {
				return{ begin_ };
			}
			constexpr iterator end() const noexcept {
				return{ end_ };
			}
		};

		namespace views {
			template<typename T, std::enable_if_t<std::is_arithmetic<T>::value, nullptr_t> = nullptr>
			constexpr iota_view<T> iota(const T& begin, const T& end) noexcept {
				return{ begin, end };
			}
		}
	}
	namespace views = ranges::views;
}
#endif //YUMETODO_INFERIOR_IOTA_VIEW_HPP_
<commit_msg>fix(iota_view): fix compile error in gcc<commit_after>/*=============================================================================
Copyright (C) 2021 yumetodo <yume-wikijp@live.jp>
Distributed under the Boost Software License, Version 1.0.
(See http://www.boost.org/LICENSE_1_0.txt)
=============================================================================*/
#ifndef YUMETODO_INFERIOR_IOTA_VIEW_HPP_
#define YUMETODO_INFERIOR_IOTA_VIEW_HPP_
#include <cstddef>
#include <iterator>
namespace inferior {
	namespace ranges {
		namespace detail {
			template<typename T, std::enable_if_t<std::is_arithmetic<T>::value, std::nullptr_t> = nullptr>
			class iota_view_iterator {
			private:
				T i;
			public:
				using iterator_category = std::random_access_iterator_tag;
				using iterator_concept = std::random_access_iterator_tag;
				using value_type = T;
				using difference_type = std::ptrdiff_t;
				using pointer = T*;
				using reference = T;

				iota_view_iterator() = default;
				constexpr iota_view_iterator(T n) noexcept : i(n) { }
				iota_view_iterator(const iota_view_iterator&) = default;
				iota_view_iterator(iota_view_iterator&&) = default;
				iota_view_iterator& operator=(const iota_view_iterator&) = default;
				iota_view_iterator& operator=(iota_view_iterator&&) = default;
				constexpr bool operator == (const iota_view_iterator& rhs) const noexcept { return i == rhs.i; }
				constexpr bool operator != (const iota_view_iterator& rhs) const noexcept { return i != rhs.i; }
				constexpr T operator * () const noexcept { return i; }
				constexpr T operator[](difference_type n) const noexcept { return static_cast<T>(i + n); }
				constexpr iota_view_iterator operator+(difference_type n) const noexcept { return{ static_cast<T>(i + n) }; }
				constexpr iota_view_iterator operator-(difference_type n) const noexcept { return{ static_cast<T>(i - n) }; }
				constexpr difference_type operator-(const iota_view_iterator& it) const noexcept { return static_cast<difference_type>(i - it.i); }
				constexpr bool operator<(const iota_view_iterator& n) const noexcept { return i < n.i; }
				constexpr bool operator<=(const iota_view_iterator& n) const noexcept { return i <= n.i; }
				constexpr bool operator>(const iota_view_iterator& n) const noexcept { return i > n.i; }
				constexpr bool operator>=(const iota_view_iterator& n) const noexcept { return i >= n.i; }
				constexpr iota_view_iterator& operator += (iota_view_iterator it) noexcept {
					i = static_cast<T>(i + it.i);
					return *this;
				}
				constexpr iota_view_iterator& operator -= (iota_view_iterator it) noexcept {
					i = static_cast<T>(i - it.i);
					return *this;
				}
				constexpr iota_view_iterator& operator ++ () noexcept {
					++i;
					return *this;
				}
				constexpr iota_view_iterator operator ++ (int) noexcept {
					auto t = *this;
					++i;
					return t;
				}
				constexpr iota_view_iterator& operator -- () noexcept {
					--i;
					return *this;
				}
				constexpr iota_view_iterator operator -- (int) noexcept {
					auto t = *this;
					--i;
					return t;
				}
			};
			template<typename T>
			constexpr iota_view_iterator<T> operator+(typename iota_view_iterator<T>::difference_type n, const iota_view_iterator<T>& it) noexcept { return static_cast<T>(it + n); }
		}
		template<typename T, std::enable_if_t<std::is_arithmetic<T>::value, std::nullptr_t> = nullptr>
		class iota_view {
		public:
			using value_type = std::remove_cv_t<T>;
			using iterator = detail::iota_view_iterator<value_type>;
		private:
			value_type begin_, end_;
		public:
			constexpr iota_view(T n) : begin_(0), end_(n) {}
			constexpr iota_view(T begin, T end) : begin_(begin), end_(end) {}
			constexpr iterator begin() const noexcept {
				return{ begin_ };
			}
			constexpr iterator end() const noexcept {
				return{ end_ };
			}
		};

		namespace views {
			template<typename T, std::enable_if_t<std::is_arithmetic<T>::value, std::nullptr_t> = nullptr>
			constexpr iota_view<T> iota(const T& begin, const T& end) noexcept {
				return{ begin, end };
			}
		}
	}
	namespace views = ranges::views;
}
#endif //YUMETODO_INFERIOR_IOTA_VIEW_HPP_
<|endoftext|>


<commit_before>/**
 * \file TransverseMercator.hpp
 *
 * Copyright (c) Charles Karney (2008) <charles@karney.com>
 * and licensed under the LGPL.
 **********************************************************************/

#if !defined(TRANSVERSEMERCATOR_HPP)
#define TRANSVERSEMERCATOR_HPP "$Id$"

#include <cmath>

namespace GeographicLib {

  class TransverseMercator {
  private:
    const double _a, _f, _k0, _e2, _e, _e2m, _e1,  _n, _a1,
      _h1, _h2, _h3, _h4,
      _h1p, _h2p, _h3p, _h4p,
      _tol;
    const int _numit;
#if defined(_MSC_VER)
    // These have poor relative accuracy near x = 0.  However, for mapping
    // applications, we only need good absolute accuracy.
    // For small arguments we would write
    //
    // asinh(x) = asin(x) -x^3/3-5*x^7/56-63*x^11/1408-143*x^15/5120 ...
    // atanh(x) = atan(x) +2*x^3/3+2*x^7/7+2*x^11/11+2*x^15/15
    //
    // The accuracy of asinh is also bad for large negative arguments.  This is
    // easy to fix in the definition of asinh.  Instead we call these functions
    // with positive arguments and enforce the correct parity separately.
    static inline double asinh(double x) { return log(x + sqrt(1 + x * x)); }
    static inline double atanh(double x) { return log((1 + x)/(1 - x))/2; }
#endif
    double Convergence(double phi, double l) const;
    double Scale(double phi, double l) const;
  public:
    TransverseMercator(double a, double f, double k0);
    void Forward(double lon0, double lat, double lon,
		 double& x, double& y, double& gamma, double& k) const;
    void Reverse(double lon0, double x, double y,
		 double& lat, double& lon, double& gamma, double& k) const;
    // Specialization for WGS84 ellipsoid and UTM scale factor
    const static TransverseMercator UTM;
  };

}

#endif
<commit_msg>Add closing namespace comment<commit_after>/**
 * \file TransverseMercator.hpp
 *
 * Copyright (c) Charles Karney (2008) <charles@karney.com>
 * and licensed under the LGPL.
 **********************************************************************/

#if !defined(TRANSVERSEMERCATOR_HPP)
#define TRANSVERSEMERCATOR_HPP "$Id$"

#include <cmath>

namespace GeographicLib {

  class TransverseMercator {
  private:
    const double _a, _f, _k0, _e2, _e, _e2m, _e1,  _n, _a1,
      _h1, _h2, _h3, _h4,
      _h1p, _h2p, _h3p, _h4p,
      _tol;
    const int _numit;
#if defined(_MSC_VER)
    // These have poor relative accuracy near x = 0.  However, for mapping
    // applications, we only need good absolute accuracy.
    // For small arguments we would write
    //
    // asinh(x) = asin(x) -x^3/3-5*x^7/56-63*x^11/1408-143*x^15/5120 ...
    // atanh(x) = atan(x) +2*x^3/3+2*x^7/7+2*x^11/11+2*x^15/15
    //
    // The accuracy of asinh is also bad for large negative arguments.  This is
    // easy to fix in the definition of asinh.  Instead we call these functions
    // with positive arguments and enforce the correct parity separately.
    static inline double asinh(double x) { return log(x + sqrt(1 + x * x)); }
    static inline double atanh(double x) { return log((1 + x)/(1 - x))/2; }
#endif
    double Convergence(double phi, double l) const;
    double Scale(double phi, double l) const;
  public:
    TransverseMercator(double a, double f, double k0);
    void Forward(double lon0, double lat, double lon,
		 double& x, double& y, double& gamma, double& k) const;
    void Reverse(double lon0, double x, double y,
		 double& lat, double& lon, double& gamma, double& k) const;
    // Specialization for WGS84 ellipsoid and UTM scale factor
    const static TransverseMercator UTM;
  };

} // namespace GeographicLib

#endif
<|endoftext|>