<commit_before>/*
  Copyright:    © 2018 SIL International.
  Description:  This is a test implementation of the keyboard processor API to
                enable testing API clients against a basic keyboard and give
                them something to link against and load.
                TODO: Add a mecahnism to trigger output of PERSIST_OPT &
                RESET_OPT actions items, options support and context matching.
  Create Date:  17 Oct 2018
  Authors:      Tim Eves (TSE)
  History:      17 Oct 2018 - TSE - Initial implementation.
*/

#include <keyboardprocessor.h>

#include "state.hpp"

namespace
{

// An table of VKEY to character sequence mappings, one per shift state.
// An empty string inidicates no mapping.
constexpr char const table[2][256][4] = {
  {
    "","","","","","","","","","\t","","","","\015","","",
    "","","","","","","","","","","","\033","","","","",
    " ","","","","","","","","","","","","","","","",
    "0","1","2","3","4","5","6","7","8","9","","","","","","",
    "","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o",
    "p","q","r","s","t","u","v","w","x","y","z","","","","","",
    "0","1","2","3","4","5","6","7","8","9","*","+","","-",".","/",
    "f1","f2","f3","f4","f5","f6","f7","f8","f9","f10","f11","f12","f13","f14","f15","f16",
    "f17","f18","f19","f20","f24","","","","","","","","","","","",
    "","","","","","","","","","","","","","","","",
    "","","","","","","","","","","","","","","","",
    "","","","","","","","","",";","=",",","-",".","/","`",
    "","","","","","","","","","","","","","","","",
    "","","","","","","","","","","[","\\","]","'","","",
    "","","","","","","","","","","","","","","","",
    "","","","","","","","","","","","","","","","",
  },
  {
    "","","","","","","","","","\t","","","","\015","","",
    "","","","","","","","","","","","\033","","","","",
    " ","","","","","","","","","","","","","","","",
    ")","!","@","#","$","%","^","&","*","(","","","","","","",
    "","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O",
    "P","Q","R","S","T","U","V","W","X","Y","Z","","","","","",
    "","","","","","","","","","","","","","","","",
    "","","","","","","","","","","","","","","","",
    "","","","","","","","","","","","","","","","",
    "","","","","","","","","","","","","","","","",
    "","","","","","","","","","","","","","","","",
    "","","","","","","","","",":","+","<","_",">","?","~",
    "","","","","","","","","","","","","","","","",
    "","","","","","","","","","","{","|","}","\"","","",
    "","","","","","","","","","","","","","","","",
    "","","","","","","","","","","","","","","","",
  }
};

constexpr km_kbp_attr const engine_attrs = {
  256,
  KM_KBP_LIB_CURRENT,
  KM_KBP_LIB_AGE,
  KM_KBP_LIB_REVISION,
  KM_KBP_TECH_UNSPECIFIED,
  "SIL International"
};

}

km_kbp_status km_kbp_process_event(km_kbp_state *state,
                          km_kbp_virtual_key vk, uint16_t modifier_state)
{
  try
  {
    state->actions.clear();

    switch (vk)
    {
      case KM_KBP_VKEY_BKSP:
        state->context().pop_back();
        state->actions.emplace_back(km_kbp_action_item {KM_KBP_IT_BACK, {0,}, {0}});
        state->actions.emplace_back(km_kbp_action_item {KM_KBP_IT_END, {0,}, {0}});
        break;

      default:
      {
        auto shift_state = modifier_state & KM_KBP_MODIFIER_SHIFT;
        // Only process further one of the shift states has something to output.
        if (table[0][vk][0] || table[1][vk][0])
        {
          auto char_seq = table[shift_state][vk];

          for (auto c = char_seq; *c; ++c)
          {
            km_kbp_usv usv = *c;
            state->context().emplace_back(km_kbp_context_item {KM_KBP_CT_CHAR,{0,},{usv}});
            state->actions.emplace_back(km_kbp_action_item {KM_KBP_IT_CHAR, {0,}, {usv}});
          }
          state->actions.emplace_back(km_kbp_action_item {KM_KBP_IT_END, {0,}, {0}});

          return KM_KBP_STATUS_OK;
        }

        // Both shift states output nothing, generate an alert.
        state->actions.emplace_back(km_kbp_action_item {KM_KBP_IT_ALERT, {0,}, {0}});
        state->actions.emplace_back(km_kbp_action_item {KM_KBP_IT_END, {0,}, {0}});
        break;
      }
    }
  }
  catch (std::bad_alloc)
  {
    state->actions.clear();
    return KM_KBP_STATUS_NO_MEM;
  }

  return KM_KBP_STATUS_OK;
}

km_kbp_attr const * km_kbp_get_engine_attrs()
{
  return &engine_attrs;
}
<commit_msg>Fix shift state to index calculation in dummy keyboard processor.<commit_after>/*
  Copyright:    © 2018 SIL International.
  Description:  This is a test implementation of the keyboard processor API to
                enable testing API clients against a basic keyboard and give
                them something to link against and load.
                TODO: Add a mecahnism to trigger output of PERSIST_OPT &
                RESET_OPT actions items, options support and context matching.
  Create Date:  17 Oct 2018
  Authors:      Tim Eves (TSE)
  History:      17 Oct 2018 - TSE - Initial implementation.
*/

#include <keyboardprocessor.h>

#include "state.hpp"

namespace
{

// An table of VKEY to character sequence mappings, one per shift state.
// An empty string inidicates no mapping.
constexpr char const table[2][256][4] = {
  {
    "","","","","","","","","","\t","","","","\015","","",
    "","","","","","","","","","","","\033","","","","",
    " ","","","","","","","","","","","","","","","",
    "0","1","2","3","4","5","6","7","8","9","","","","","","",
    "","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o",
    "p","q","r","s","t","u","v","w","x","y","z","","","","","",
    "0","1","2","3","4","5","6","7","8","9","*","+","","-",".","/",
    "f1","f2","f3","f4","f5","f6","f7","f8","f9","f10","f11","f12","f13","f14","f15","f16",
    "f17","f18","f19","f20","f24","","","","","","","","","","","",
    "","","","","","","","","","","","","","","","",
    "","","","","","","","","","","","","","","","",
    "","","","","","","","","",";","=",",","-",".","/","`",
    "","","","","","","","","","","","","","","","",
    "","","","","","","","","","","[","\\","]","'","","",
    "","","","","","","","","","","","","","","","",
    "","","","","","","","","","","","","","","","",
  },
  {
    "","","","","","","","","","\t","","","","\015","","",
    "","","","","","","","","","","","\033","","","","",
    " ","","","","","","","","","","","","","","","",
    ")","!","@","#","$","%","^","&","*","(","","","","","","",
    "","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O",
    "P","Q","R","S","T","U","V","W","X","Y","Z","","","","","",
    "","","","","","","","","","","","","","","","",
    "","","","","","","","","","","","","","","","",
    "","","","","","","","","","","","","","","","",
    "","","","","","","","","","","","","","","","",
    "","","","","","","","","","","","","","","","",
    "","","","","","","","","",":","+","<","_",">","?","~",
    "","","","","","","","","","","","","","","","",
    "","","","","","","","","","","{","|","}","\"","","",
    "","","","","","","","","","","","","","","","",
    "","","","","","","","","","","","","","","","",
  }
};

constexpr km_kbp_attr const engine_attrs = {
  256,
  KM_KBP_LIB_CURRENT,
  KM_KBP_LIB_AGE,
  KM_KBP_LIB_REVISION,
  KM_KBP_TECH_UNSPECIFIED,
  "SIL International"
};

}

km_kbp_status km_kbp_process_event(km_kbp_state *state,
                          km_kbp_virtual_key vk, uint16_t modifier_state)
{
  try
  {
    state->actions.clear();

    switch (vk)
    {
      case KM_KBP_VKEY_BKSP:
        state->context().pop_back();
        state->actions.emplace_back(km_kbp_action_item {KM_KBP_IT_BACK, {0,}, {0}});
        state->actions.emplace_back(km_kbp_action_item {KM_KBP_IT_END, {0,}, {0}});
        break;

      default:
      {
        auto shift_state = bool(modifier_state & KM_KBP_MODIFIER_SHIFT);
        // Only process further one of the shift states has something to output.
        if (table[0][vk][0] || table[1][vk][0])
        {
          auto char_seq = table[shift_state][vk];

          for (auto c = char_seq; *c; ++c)
          {
            km_kbp_usv usv = *c;
            state->context().emplace_back(km_kbp_context_item {KM_KBP_CT_CHAR,{0,},{usv}});
            state->actions.emplace_back(km_kbp_action_item {KM_KBP_IT_CHAR, {0,}, {usv}});
          }
          state->actions.emplace_back(km_kbp_action_item {KM_KBP_IT_END, {0,}, {0}});

          return KM_KBP_STATUS_OK;
        }

        // Both shift states output nothing, generate an alert.
        state->actions.emplace_back(km_kbp_action_item {KM_KBP_IT_ALERT, {0,}, {0}});
        state->actions.emplace_back(km_kbp_action_item {KM_KBP_IT_END, {0,}, {0}});
        break;
      }
    }
  }
  catch (std::bad_alloc)
  {
    state->actions.clear();
    return KM_KBP_STATUS_NO_MEM;
  }

  return KM_KBP_STATUS_OK;
}

km_kbp_attr const * km_kbp_get_engine_attrs()
{
  return &engine_attrs;
}
<|endoftext|>


<commit_before>#pragma once

#include <stdexcept>
#include <sstream>

#include "c.hxx"
#include "gl_type.hxx"

namespace wonder_rabbit_project
{
  namespace wonderland
  {
    namespace renderer
    {
      namespace glew
      {

        template < class T = void >
        auto get_error() -> gl_type::GLint
        { return c::glGetError(); }

        template < class T = void >
        inline auto is_no_error( const gl_type::GLint& v ) -> bool
        { return v == GL_NO_ERROR; }

        template < class T = void >
        inline auto is_error( const gl_type::GLint& v ) -> bool
        { return not is_no_error( v ); }

        template < class = void >
        inline auto test_error( const std::string& file = "?", const unsigned line = 0 ) -> void
        {
          auto e = get_error();

          if ( is_error( e ) )
          {
            std::stringstream message;
            message << "glGetError ( from " << file << " +" << line << " ) : " << e << " ";
            switch ( e )
            {
              case GL_INVALID_ENUM     : message << "GL_INVALID_ENUM";      break;
              case GL_INVALID_VALUE    : message << "GL_INVALID_VALUE";     break;
              case GL_INVALID_OPERATION: message << "GL_INVALID_OPERATION"; break;
              case GL_STACK_OVERFLOW   : message << "GL_STACK_OVERFLOW";    break;
              case GL_STACK_UNDERFLOW  : message << "GL_STACK_UNDERFLOW";   break;
              case GL_OUT_OF_MEMORY    : message << "GL_OUT_OF_MEMORY";     break;
            }
            throw std::runtime_error( message.str() );
          }
        }

      }
    }
  }
}<commit_msg>support GL_INVALID_FRAMEBUFFER_OPERAION and default error pattern.<commit_after>#pragma once

#include <stdexcept>
#include <sstream>
#include <iostream>

#include "c.hxx"
#include "gl_type.hxx"

namespace wonder_rabbit_project
{
  namespace wonderland
  {
    namespace renderer
    {
      namespace glew
      {

        template < class T = void >
        auto get_error() -> gl_type::GLint
        { return c::glGetError(); }

        template < class T = void >
        inline auto is_no_error( const gl_type::GLint& v ) -> bool
        { return v == GL_NO_ERROR; }

        template < class T = void >
        inline auto is_error( const gl_type::GLint& v ) -> bool
        { return not is_no_error( v ); }

        template < class = void >
        inline auto test_error( const std::string& file = "?", const unsigned line = 0 ) -> void
        {
          auto e = get_error();

          if ( is_error( e ) )
          {
            std::stringstream message;

            message << "glGetError ( from " << file << " +" << line << " ) : " << e << " ";

            switch ( e )
            {
              case GL_INVALID_ENUM     : message << "GL_INVALID_ENUM";      break;
              case GL_INVALID_VALUE    : message << "GL_INVALID_VALUE";     break;
              case GL_INVALID_OPERATION: message << "GL_INVALID_OPERATION"; break;
              case GL_STACK_OVERFLOW   : message << "GL_STACK_OVERFLOW";    break;
              case GL_STACK_UNDERFLOW  : message << "GL_STACK_UNDERFLOW";   break;
              case GL_OUT_OF_MEMORY    : message << "GL_OUT_OF_MEMORY";     break;
#ifdef GL_VERSION_3_0
              case GL_INVALID_FRAMEBUFFER_OPERATION: message << "GL_INVALID_FRAMEBUFFER_OPERATION"; break;
#endif
              default                  : message << std::to_string( e );
            }

            throw std::runtime_error( message.str() );
          }
        }
#ifndef _NDEBUG
  #define WRP_GLEW_TEST_ERROR wonder_rabbit_project::wonderland::renderer::glew::test_error( __FILE__, __LINE__ );
#else
  #define WRP_GLEW_TEST_ERROR
#endif

      }
    }
  }
}<|endoftext|>


<commit_before>//====== Copyright Valve Corporation, All rights reserved. =======

#include "openvroverlaycontroller.h"

#include <QOpenGLFramebufferObjectFormat>
#include <QOpenGLPaintDevice>
#include <QPainter>
#include <QtWidgets/QWidget>
#include <QMouseEvent>
#include <QtWidgets/QGraphicsSceneMouseEvent>
#include <QtWidgets/QApplication>
#include <QtWidgets/QGraphicsEllipseItem>
#include <QCursor>

using namespace vr;

//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
COpenVROverlayController *s_pSharedVRController = NULL;

COpenVROverlayController *COpenVROverlayController::SharedInstance()
{
	if ( !s_pSharedVRController )
	{
        s_pSharedVRController = new COpenVROverlayController();
	}
	return s_pSharedVRController;
}

//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
COpenVROverlayController::COpenVROverlayController()
	: BaseClass()
    , m_eLastHmdError( vr::VRInitError_None )
    , m_eCompositorError( vr::VRInitError_None )
    , m_eOverlayError( vr::VRInitError_None )
	, m_strVRDriver( "No Driver" )
	, m_strVRDisplay( "No Display" )
	, m_pOpenGLContext( NULL )
	, m_pScene( NULL )
	, m_pOffscreenSurface ( NULL )
	, m_pFbo( NULL )
	, m_pWidget( NULL )
	, m_pPumpEventsTimer( NULL )
	, m_lastMouseButtons( 0 )
	, m_ulOverlayHandle( vr::k_ulOverlayHandleInvalid )
	, m_bManualMouseHandling( false )
{
}

//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
COpenVROverlayController::~COpenVROverlayController()
{
}

//-----------------------------------------------------------------------------
// Purpose: Helper to get a string from a tracked device property and turn it
//			into a QString
//-----------------------------------------------------------------------------
QString GetTrackedDeviceString( vr::IVRSystem *pHmd, vr::TrackedDeviceIndex_t unDevice, vr::TrackedDeviceProperty prop )
{
	char buf[128];
	vr::TrackedPropertyError err;
	pHmd->GetStringTrackedDeviceProperty( unDevice, prop, buf, sizeof( buf ), &err );
	if( err != vr::TrackedProp_Success )
	{
		return QString( "Error Getting String: " ) + pHmd->GetPropErrorNameFromEnum( err );
	}
	else
	{
		return buf;
	}
}

//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool COpenVROverlayController::Init()
{
	bool bSuccess = true;

    m_strName = "systemoverlay";

	QStringList arguments = qApp->arguments();

	int nNameArg = arguments.indexOf( "-name" );
	if( nNameArg != -1 && nNameArg + 2 <= arguments.size() )
	{
		m_strName = arguments.at( nNameArg + 1 );
	}

	QSurfaceFormat format;
	format.setMajorVersion( 4 );
	format.setMinorVersion( 1 );
	format.setProfile( QSurfaceFormat::CompatibilityProfile );

	m_pOpenGLContext = new QOpenGLContext();
	m_pOpenGLContext->setFormat( format );
	bSuccess = m_pOpenGLContext->create();
	if( !bSuccess )
		return false;

	// create an offscreen surface to attach the context and FBO to
	m_pOffscreenSurface = new QOffscreenSurface();
	m_pOffscreenSurface->create();
	m_pOpenGLContext->makeCurrent( m_pOffscreenSurface );

	m_pScene = new QGraphicsScene();
	connect( m_pScene, SIGNAL(changed(const QList<QRectF>&)), this, SLOT( OnSceneChanged(const QList<QRectF>&)) );

	// Loading the OpenVR Runtime
	bSuccess = ConnectToVRRuntime();

    bSuccess = bSuccess && vr::VRCompositor() != NULL;

    if( vr::VROverlay() )
	{
        std::string sKey = std::string( "sample." ) + m_strName.toStdString();
        vr::VROverlayError overlayError = vr::VROverlay()->CreateDashboardOverlay( sKey.c_str(), m_strName.toStdString().c_str(), &m_ulOverlayHandle, &m_ulOverlayThumbnailHandle );
		bSuccess = bSuccess && overlayError == vr::VROverlayError_None;
	}

	if( bSuccess )
	{
        vr::VROverlay()->SetOverlayWidthInMeters( m_ulOverlayHandle, 1.5f );
        vr::VROverlay()->SetOverlayInputMethod( m_ulOverlayHandle, vr::VROverlayInputMethod_Mouse );

		m_pPumpEventsTimer = new QTimer( this );
		connect(m_pPumpEventsTimer, SIGNAL( timeout() ), this, SLOT( OnTimeoutPumpEvents() ) );
		m_pPumpEventsTimer->setInterval( 20 );
		m_pPumpEventsTimer->start();

	}
	return true;
}

//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void COpenVROverlayController::Shutdown()
{
	DisconnectFromVRRuntime();

	delete m_pScene;
	delete m_pFbo;
	delete m_pOffscreenSurface;

	if( m_pOpenGLContext )
	{
//		m_pOpenGLContext->destroy();
		delete m_pOpenGLContext;
		m_pOpenGLContext = NULL;
	}
}

//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void COpenVROverlayController::OnSceneChanged( const QList<QRectF>& )
{
	// skip rendering if the overlay isn't visible
    if( !vr::VROverlay() ||
        !vr::VROverlay()->IsOverlayVisible( m_ulOverlayHandle ) && !vr::VROverlay()->IsOverlayVisible( m_ulOverlayThumbnailHandle ) )
        return;

	m_pOpenGLContext->makeCurrent( m_pOffscreenSurface );
	m_pFbo->bind();

	QOpenGLPaintDevice device( m_pFbo->size() );
	QPainter painter( &device );

	m_pScene->render( &painter );

	m_pFbo->release();

	GLuint unTexture = m_pFbo->texture();
	if( unTexture != 0 )
	{
        vr::Texture_t texture = {(void*)unTexture, vr::API_OpenGL, vr::ColorSpace_Auto };
        vr::VROverlay()->SetOverlayTexture( m_ulOverlayHandle, &texture );
	}
}

//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void COpenVROverlayController::OnTimeoutPumpEvents()
{
    if( !vr::VRSystem() )
		return;

	if( m_bManualMouseHandling )
	{
		// tell OpenVR to make some events for us
		for( vr::TrackedDeviceIndex_t unDeviceId = 1; unDeviceId < vr::k_unControllerStateAxisCount; unDeviceId++ )
		{
            if( vr::VROverlay()->HandleControllerOverlayInteractionAsMouse( m_ulOverlayHandle, unDeviceId ) )
			{
				break;
			}
		}
	}

	vr::VREvent_t vrEvent;
    while( vr::VROverlay()->PollNextOverlayEvent( m_ulOverlayHandle, &vrEvent, sizeof( vrEvent )  ) )
	{
		switch( vrEvent.eventType )
		{
		case vr::VREvent_MouseMove:
			{
				QPointF ptNewMouse( vrEvent.data.mouse.x, vrEvent.data.mouse.y );
				QPoint ptGlobal = ptNewMouse.toPoint();
				QGraphicsSceneMouseEvent mouseEvent( QEvent::GraphicsSceneMouseMove );
				mouseEvent.setWidget( NULL );
				mouseEvent.setPos( ptNewMouse );
				mouseEvent.setScenePos( ptGlobal );
				mouseEvent.setScreenPos( ptGlobal );
				mouseEvent.setLastPos( m_ptLastMouse );
				mouseEvent.setLastScenePos( m_pWidget->mapToGlobal( m_ptLastMouse.toPoint() ) );
				mouseEvent.setLastScreenPos( m_pWidget->mapToGlobal( m_ptLastMouse.toPoint() ) );
				mouseEvent.setButtons( m_lastMouseButtons );
				mouseEvent.setButton( Qt::NoButton );
				mouseEvent.setModifiers( 0 );
				mouseEvent.setAccepted( false );

				m_ptLastMouse = ptNewMouse;
				QApplication::sendEvent( m_pScene, &mouseEvent );

				OnSceneChanged( QList<QRectF>() );
			}
			break;

		case vr::VREvent_MouseButtonDown:
			{
				Qt::MouseButton button = vrEvent.data.mouse.button == vr::VRMouseButton_Right ? Qt::RightButton : Qt::LeftButton;

				m_lastMouseButtons |= button;

				QPoint ptGlobal = m_ptLastMouse.toPoint();
				QGraphicsSceneMouseEvent mouseEvent( QEvent::GraphicsSceneMousePress );
				mouseEvent.setWidget( NULL );
				mouseEvent.setPos( m_ptLastMouse );
				mouseEvent.setButtonDownPos( button, m_ptLastMouse );
				mouseEvent.setButtonDownScenePos( button, ptGlobal);
				mouseEvent.setButtonDownScreenPos( button, ptGlobal );
				mouseEvent.setScenePos( ptGlobal );
				mouseEvent.setScreenPos( ptGlobal );
				mouseEvent.setLastPos( m_ptLastMouse );
				mouseEvent.setLastScenePos( ptGlobal );
				mouseEvent.setLastScreenPos( ptGlobal );
				mouseEvent.setButtons( m_lastMouseButtons );
				mouseEvent.setButton( button );
				mouseEvent.setModifiers( 0 );
				mouseEvent.setAccepted( false );

				QApplication::sendEvent( m_pScene, &mouseEvent );
			}
			break;

		case vr::VREvent_MouseButtonUp:
			{
				Qt::MouseButton button = vrEvent.data.mouse.button == vr::VRMouseButton_Right ? Qt::RightButton : Qt::LeftButton;
				m_lastMouseButtons &= ~button;

				QPoint ptGlobal = m_ptLastMouse.toPoint();
				QGraphicsSceneMouseEvent mouseEvent( QEvent::GraphicsSceneMouseRelease );
				mouseEvent.setWidget( NULL );
				mouseEvent.setPos( m_ptLastMouse );
				mouseEvent.setScenePos( ptGlobal );
				mouseEvent.setScreenPos( ptGlobal );
				mouseEvent.setLastPos( m_ptLastMouse );
				mouseEvent.setLastScenePos( ptGlobal );
				mouseEvent.setLastScreenPos( ptGlobal );
				mouseEvent.setButtons( m_lastMouseButtons );
				mouseEvent.setButton( button );
				mouseEvent.setModifiers( 0 );
				mouseEvent.setAccepted( false );

				QApplication::sendEvent(  m_pScene, &mouseEvent );
			}
			break;

		case vr::VREvent_OverlayShown:
			{
				m_pWidget->repaint();
			}
			break;

        case vr::VREvent_Quit:
            QApplication::exit();
            break;
		}
	}

    if( m_ulOverlayThumbnailHandle != vr::k_ulOverlayHandleInvalid )
    {
        while( vr::VROverlay()->PollNextOverlayEvent( m_ulOverlayThumbnailHandle, &vrEvent, sizeof( vrEvent)  ) )
        {
            switch( vrEvent.eventType )
            {
            case vr::VREvent_OverlayShown:
                {
                    m_pWidget->repaint();
                }
                break;
            }
        }
    }

}

//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void COpenVROverlayController::SetWidget( QWidget *pWidget )
{
	if( m_pScene )
	{
		// all of the mouse handling stuff requires that the widget be at 0,0
		pWidget->move( 0, 0 );
		m_pScene->addWidget( pWidget );
	}
	m_pWidget = pWidget;

	m_pFbo = new QOpenGLFramebufferObject( pWidget->width(), pWidget->height(), GL_TEXTURE_2D );

    if( vr::VROverlay() )
    {
        vr::HmdVector2_t vecWindowSize =
        {
            (float)pWidget->width(),
            (float)pWidget->height()
        };
        vr::VROverlay()->SetOverlayMouseScale( m_ulOverlayHandle, &vecWindowSize );
    }

}

//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool COpenVROverlayController::ConnectToVRRuntime()
{
    m_eLastHmdError = vr::VRInitError_None;
    vr::IVRSystem *pVRSystem = vr::VR_Init( &m_eLastHmdError, vr::VRApplication_Overlay );

    if ( m_eLastHmdError != vr::VRInitError_None )
	{
		m_strVRDriver = "No Driver";
		m_strVRDisplay = "No Display";
		return false;
	}

    m_strVRDriver = GetTrackedDeviceString(pVRSystem, vr::k_unTrackedDeviceIndex_Hmd, vr::Prop_TrackingSystemName_String);
    m_strVRDisplay = GetTrackedDeviceString(pVRSystem, vr::k_unTrackedDeviceIndex_Hmd, vr::Prop_SerialNumber_String);

	return true;
}

void COpenVROverlayController::DisconnectFromVRRuntime()
{
	vr::VR_Shutdown();
}

//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
QString COpenVROverlayController::GetVRDriverString()
{
	return m_strVRDriver;
}

//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
QString COpenVROverlayController::GetVRDisplayString()
{
	return m_strVRDisplay;
}

//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool COpenVROverlayController::BHMDAvailable()
{
    return vr::VRSystem() != NULL;
}

//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------

vr::HmdError COpenVROverlayController::GetLastHmdError()
{
	return m_eLastHmdError;
}

<commit_msg>updated helloworldoverlay to latest sdk<commit_after>//====== Copyright Valve Corporation, All rights reserved. =======

#include "openvroverlaycontroller.h"

#include <QOpenGLFramebufferObjectFormat>
#include <QOpenGLPaintDevice>
#include <QPainter>
#include <QtWidgets/QWidget>
#include <QMouseEvent>
#include <QtWidgets/QGraphicsSceneMouseEvent>
#include <QtWidgets/QApplication>
#include <QtWidgets/QGraphicsEllipseItem>
#include <QCursor>

using namespace vr;

//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
COpenVROverlayController *s_pSharedVRController = NULL;

COpenVROverlayController *COpenVROverlayController::SharedInstance()
{
	if ( !s_pSharedVRController )
	{
        s_pSharedVRController = new COpenVROverlayController();
	}
	return s_pSharedVRController;
}

//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
COpenVROverlayController::COpenVROverlayController()
	: BaseClass()
    , m_eLastHmdError( vr::VRInitError_None )
    , m_eCompositorError( vr::VRInitError_None )
    , m_eOverlayError( vr::VRInitError_None )
	, m_strVRDriver( "No Driver" )
	, m_strVRDisplay( "No Display" )
	, m_pOpenGLContext( NULL )
	, m_pScene( NULL )
	, m_pOffscreenSurface ( NULL )
	, m_pFbo( NULL )
	, m_pWidget( NULL )
	, m_pPumpEventsTimer( NULL )
	, m_lastMouseButtons( 0 )
	, m_ulOverlayHandle( vr::k_ulOverlayHandleInvalid )
	, m_bManualMouseHandling( false )
{
}

//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
COpenVROverlayController::~COpenVROverlayController()
{
}

//-----------------------------------------------------------------------------
// Purpose: Helper to get a string from a tracked device property and turn it
//			into a QString
//-----------------------------------------------------------------------------
QString GetTrackedDeviceString( vr::IVRSystem *pHmd, vr::TrackedDeviceIndex_t unDevice, vr::TrackedDeviceProperty prop )
{
	char buf[128];
	vr::TrackedPropertyError err;
	pHmd->GetStringTrackedDeviceProperty( unDevice, prop, buf, sizeof( buf ), &err );
	if( err != vr::TrackedProp_Success )
	{
		return QString( "Error Getting String: " ) + pHmd->GetPropErrorNameFromEnum( err );
	}
	else
	{
		return buf;
	}
}

//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool COpenVROverlayController::Init()
{
	bool bSuccess = true;

    m_strName = "systemoverlay";

	QStringList arguments = qApp->arguments();

	int nNameArg = arguments.indexOf( "-name" );
	if( nNameArg != -1 && nNameArg + 2 <= arguments.size() )
	{
		m_strName = arguments.at( nNameArg + 1 );
	}

	QSurfaceFormat format;
	format.setMajorVersion( 4 );
	format.setMinorVersion( 1 );
	format.setProfile( QSurfaceFormat::CompatibilityProfile );

	m_pOpenGLContext = new QOpenGLContext();
	m_pOpenGLContext->setFormat( format );
	bSuccess = m_pOpenGLContext->create();
	if( !bSuccess )
		return false;

	// create an offscreen surface to attach the context and FBO to
	m_pOffscreenSurface = new QOffscreenSurface();
	m_pOffscreenSurface->create();
	m_pOpenGLContext->makeCurrent( m_pOffscreenSurface );

	m_pScene = new QGraphicsScene();
	connect( m_pScene, SIGNAL(changed(const QList<QRectF>&)), this, SLOT( OnSceneChanged(const QList<QRectF>&)) );

	// Loading the OpenVR Runtime
	bSuccess = ConnectToVRRuntime();

    bSuccess = bSuccess && vr::VRCompositor() != NULL;

    if( vr::VROverlay() )
	{
        std::string sKey = std::string( "sample." ) + m_strName.toStdString();
        vr::VROverlayError overlayError = vr::VROverlay()->CreateDashboardOverlay( sKey.c_str(), m_strName.toStdString().c_str(), &m_ulOverlayHandle, &m_ulOverlayThumbnailHandle );
		bSuccess = bSuccess && overlayError == vr::VROverlayError_None;
	}

	if( bSuccess )
	{
        vr::VROverlay()->SetOverlayWidthInMeters( m_ulOverlayHandle, 1.5f );
        vr::VROverlay()->SetOverlayInputMethod( m_ulOverlayHandle, vr::VROverlayInputMethod_Mouse );

		m_pPumpEventsTimer = new QTimer( this );
		connect(m_pPumpEventsTimer, SIGNAL( timeout() ), this, SLOT( OnTimeoutPumpEvents() ) );
		m_pPumpEventsTimer->setInterval( 20 );
		m_pPumpEventsTimer->start();

	}
	return true;
}

//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void COpenVROverlayController::Shutdown()
{
	DisconnectFromVRRuntime();

	delete m_pScene;
	delete m_pFbo;
	delete m_pOffscreenSurface;

	if( m_pOpenGLContext )
	{
//		m_pOpenGLContext->destroy();
		delete m_pOpenGLContext;
		m_pOpenGLContext = NULL;
	}
}

//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void COpenVROverlayController::OnSceneChanged( const QList<QRectF>& )
{
	// skip rendering if the overlay isn't visible
    if( !vr::VROverlay() ||
        !vr::VROverlay()->IsOverlayVisible( m_ulOverlayHandle ) && !vr::VROverlay()->IsOverlayVisible( m_ulOverlayThumbnailHandle ) )
        return;

	m_pOpenGLContext->makeCurrent( m_pOffscreenSurface );
	m_pFbo->bind();

	QOpenGLPaintDevice device( m_pFbo->size() );
	QPainter painter( &device );

	m_pScene->render( &painter );

	m_pFbo->release();

	GLuint unTexture = m_pFbo->texture();
	if( unTexture != 0 )
	{
        vr::Texture_t texture = {(void*)unTexture, vr::TextureType_OpenGL, vr::ColorSpace_Auto };
        vr::VROverlay()->SetOverlayTexture( m_ulOverlayHandle, &texture );
	}
}

//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void COpenVROverlayController::OnTimeoutPumpEvents()
{
    if( !vr::VRSystem() )
		return;

	if( m_bManualMouseHandling )
	{
		// tell OpenVR to make some events for us
		for( vr::TrackedDeviceIndex_t unDeviceId = 1; unDeviceId < vr::k_unControllerStateAxisCount; unDeviceId++ )
		{
            if( vr::VROverlay()->HandleControllerOverlayInteractionAsMouse( m_ulOverlayHandle, unDeviceId ) )
			{
				break;
			}
		}
	}

	vr::VREvent_t vrEvent;
    while( vr::VROverlay()->PollNextOverlayEvent( m_ulOverlayHandle, &vrEvent, sizeof( vrEvent )  ) )
	{
		switch( vrEvent.eventType )
		{
		case vr::VREvent_MouseMove:
			{
				QPointF ptNewMouse( vrEvent.data.mouse.x, vrEvent.data.mouse.y );
				QPoint ptGlobal = ptNewMouse.toPoint();
				QGraphicsSceneMouseEvent mouseEvent( QEvent::GraphicsSceneMouseMove );
				mouseEvent.setWidget( NULL );
				mouseEvent.setPos( ptNewMouse );
				mouseEvent.setScenePos( ptGlobal );
				mouseEvent.setScreenPos( ptGlobal );
				mouseEvent.setLastPos( m_ptLastMouse );
				mouseEvent.setLastScenePos( m_pWidget->mapToGlobal( m_ptLastMouse.toPoint() ) );
				mouseEvent.setLastScreenPos( m_pWidget->mapToGlobal( m_ptLastMouse.toPoint() ) );
				mouseEvent.setButtons( m_lastMouseButtons );
				mouseEvent.setButton( Qt::NoButton );
				mouseEvent.setModifiers( 0 );
				mouseEvent.setAccepted( false );

				m_ptLastMouse = ptNewMouse;
				QApplication::sendEvent( m_pScene, &mouseEvent );

				OnSceneChanged( QList<QRectF>() );
			}
			break;

		case vr::VREvent_MouseButtonDown:
			{
				Qt::MouseButton button = vrEvent.data.mouse.button == vr::VRMouseButton_Right ? Qt::RightButton : Qt::LeftButton;

				m_lastMouseButtons |= button;

				QPoint ptGlobal = m_ptLastMouse.toPoint();
				QGraphicsSceneMouseEvent mouseEvent( QEvent::GraphicsSceneMousePress );
				mouseEvent.setWidget( NULL );
				mouseEvent.setPos( m_ptLastMouse );
				mouseEvent.setButtonDownPos( button, m_ptLastMouse );
				mouseEvent.setButtonDownScenePos( button, ptGlobal);
				mouseEvent.setButtonDownScreenPos( button, ptGlobal );
				mouseEvent.setScenePos( ptGlobal );
				mouseEvent.setScreenPos( ptGlobal );
				mouseEvent.setLastPos( m_ptLastMouse );
				mouseEvent.setLastScenePos( ptGlobal );
				mouseEvent.setLastScreenPos( ptGlobal );
				mouseEvent.setButtons( m_lastMouseButtons );
				mouseEvent.setButton( button );
				mouseEvent.setModifiers( 0 );
				mouseEvent.setAccepted( false );

				QApplication::sendEvent( m_pScene, &mouseEvent );
			}
			break;

		case vr::VREvent_MouseButtonUp:
			{
				Qt::MouseButton button = vrEvent.data.mouse.button == vr::VRMouseButton_Right ? Qt::RightButton : Qt::LeftButton;
				m_lastMouseButtons &= ~button;

				QPoint ptGlobal = m_ptLastMouse.toPoint();
				QGraphicsSceneMouseEvent mouseEvent( QEvent::GraphicsSceneMouseRelease );
				mouseEvent.setWidget( NULL );
				mouseEvent.setPos( m_ptLastMouse );
				mouseEvent.setScenePos( ptGlobal );
				mouseEvent.setScreenPos( ptGlobal );
				mouseEvent.setLastPos( m_ptLastMouse );
				mouseEvent.setLastScenePos( ptGlobal );
				mouseEvent.setLastScreenPos( ptGlobal );
				mouseEvent.setButtons( m_lastMouseButtons );
				mouseEvent.setButton( button );
				mouseEvent.setModifiers( 0 );
				mouseEvent.setAccepted( false );

				QApplication::sendEvent(  m_pScene, &mouseEvent );
			}
			break;

		case vr::VREvent_OverlayShown:
			{
				m_pWidget->repaint();
			}
			break;

        case vr::VREvent_Quit:
            QApplication::exit();
            break;
		}
	}

    if( m_ulOverlayThumbnailHandle != vr::k_ulOverlayHandleInvalid )
    {
        while( vr::VROverlay()->PollNextOverlayEvent( m_ulOverlayThumbnailHandle, &vrEvent, sizeof( vrEvent)  ) )
        {
            switch( vrEvent.eventType )
            {
            case vr::VREvent_OverlayShown:
                {
                    m_pWidget->repaint();
                }
                break;
            }
        }
    }

}

//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void COpenVROverlayController::SetWidget( QWidget *pWidget )
{
	if( m_pScene )
	{
		// all of the mouse handling stuff requires that the widget be at 0,0
		pWidget->move( 0, 0 );
		m_pScene->addWidget( pWidget );
	}
	m_pWidget = pWidget;

	m_pFbo = new QOpenGLFramebufferObject( pWidget->width(), pWidget->height(), GL_TEXTURE_2D );

    if( vr::VROverlay() )
    {
        vr::HmdVector2_t vecWindowSize =
        {
            (float)pWidget->width(),
            (float)pWidget->height()
        };
        vr::VROverlay()->SetOverlayMouseScale( m_ulOverlayHandle, &vecWindowSize );
    }

}

//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool COpenVROverlayController::ConnectToVRRuntime()
{
    m_eLastHmdError = vr::VRInitError_None;
    vr::IVRSystem *pVRSystem = vr::VR_Init( &m_eLastHmdError, vr::VRApplication_Overlay );

    if ( m_eLastHmdError != vr::VRInitError_None )
	{
		m_strVRDriver = "No Driver";
		m_strVRDisplay = "No Display";
		return false;
	}

    m_strVRDriver = GetTrackedDeviceString(pVRSystem, vr::k_unTrackedDeviceIndex_Hmd, vr::Prop_TrackingSystemName_String);
    m_strVRDisplay = GetTrackedDeviceString(pVRSystem, vr::k_unTrackedDeviceIndex_Hmd, vr::Prop_SerialNumber_String);

	return true;
}

void COpenVROverlayController::DisconnectFromVRRuntime()
{
	vr::VR_Shutdown();
}

//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
QString COpenVROverlayController::GetVRDriverString()
{
	return m_strVRDriver;
}

//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
QString COpenVROverlayController::GetVRDisplayString()
{
	return m_strVRDisplay;
}

//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool COpenVROverlayController::BHMDAvailable()
{
    return vr::VRSystem() != NULL;
}

//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------

vr::HmdError COpenVROverlayController::GetLastHmdError()
{
	return m_eLastHmdError;
}

<|endoftext|>


<commit_before>#include "ofApp.h"

//--------------------------------------------------------------
void ofApp::setup(){
    ofxWebUI &ui = ofxWebUI::ui();
    ui.setup("ofxWebUI Example");

    ofxWebUIOption o1 = ofxWebUIOption::createRangeOption(250, 1000, 2500);
    ui.bindParameter("x", ofxWebUITypeSlider, x, o1);

    ofxWebUIOption o2 = ofxWebUIOption::createRangeOption(-10000, 10000, 0);
    ui.bindParameter("property", ofxWebUITypeSlider, foo.p, o2);

    ofxWebUIOption o3 = ofxWebUIOption::rangeOption0_255(127);
    ui.bindParameter("r", ofxWebUITypeSlider, r, o3);
    ui.bindParameter("g", ofxWebUITypeSlider, g, o3);
    ui.bindParameter("b", ofxWebUITypeSlider, b, o3);

    vector<string> labels;
    labels.push_back("foo");
    labels.push_back("bar");
    labels.push_back("buz");
    ofxWebUIOption o4 = ofxWebUIOption::createSelectBoxOption(labels);
    ui.bindParameter("select", ofxWebUITypeSelect, select, o4);

    ui.runServer(true);
}

//--------------------------------------------------------------
void ofApp::update(){
    ofxWebUI::ui().update();
}

//--------------------------------------------------------------
void ofApp::draw(){
    ofBackground(r, g, b);

    ofDrawBitmapString("x: " + ofToString(x), ofPoint(10, 20));

    ofDrawBitmapString("property: " + ofToString(foo.p), ofPoint(10, 50));

    ofDrawBitmapString("r: " + ofToString((int)r), ofPoint(10, 80));
    ofDrawBitmapString("g: " + ofToString((int)g), ofPoint(10, 120));
    ofDrawBitmapString("b: " + ofToString((int)b), ofPoint(10, 140));

    ofDrawBitmapString("select: " + ofToString(select), ofPoint(10, 170));
}

//--------------------------------------------------------------
void ofApp::keyPressed(int key){
#if ENABLE_UNBIND
    if(key == 'r') {
        ofxWebUI::ui().unbindParameter("x");
    }
#endif
}

//--------------------------------------------------------------
void ofApp::keyReleased(int key){

}

//--------------------------------------------------------------
void ofApp::mouseMoved(int x, int y ){

}

//--------------------------------------------------------------
void ofApp::mouseDragged(int x, int y, int button){

}

//--------------------------------------------------------------
void ofApp::mousePressed(int x, int y, int button){

}

//--------------------------------------------------------------
void ofApp::mouseReleased(int x, int y, int button){

}

//--------------------------------------------------------------
void ofApp::windowResized(int w, int h){

}

//--------------------------------------------------------------
void ofApp::gotMessage(ofMessage msg){

}

//--------------------------------------------------------------
void ofApp::dragEvent(ofDragInfo dragInfo){

}
<commit_msg>fix crazy parameter<commit_after>#include "ofApp.h"

//--------------------------------------------------------------
void ofApp::setup(){
    ofxWebUI &ui = ofxWebUI::ui();
    ui.setup("ofxWebUI Example");

    ofxWebUIOption o1 = ofxWebUIOption::createRangeOption(100, 2500, 250);
    ui.bindParameter("x", ofxWebUITypeSlider, x, o1);

    ofxWebUIOption o2 = ofxWebUIOption::createRangeOption(-10000, 10000, 0);
    ui.bindParameter("property", ofxWebUITypeSlider, foo.p, o2);

    ofxWebUIOption o3 = ofxWebUIOption::rangeOption0_255(127);
    ui.bindParameter("r", ofxWebUITypeSlider, r, o3);
    ui.bindParameter("g", ofxWebUITypeSlider, g, o3);
    ui.bindParameter("b", ofxWebUITypeSlider, b, o3);

    vector<string> labels;
    labels.push_back("foo");
    labels.push_back("bar");
    labels.push_back("buz");
    ofxWebUIOption o4 = ofxWebUIOption::createSelectBoxOption(labels);
    ui.bindParameter("select", ofxWebUITypeSelect, select, o4);

    ui.runServer(true);
}

//--------------------------------------------------------------
void ofApp::update(){
    ofxWebUI::ui().update();
}

//--------------------------------------------------------------
void ofApp::draw(){
    ofBackground(r, g, b);

    ofDrawBitmapString("x: " + ofToString(x), ofPoint(10, 20));

    ofDrawBitmapString("property: " + ofToString(foo.p), ofPoint(10, 50));

    ofDrawBitmapString("r: " + ofToString((int)r), ofPoint(10, 80));
    ofDrawBitmapString("g: " + ofToString((int)g), ofPoint(10, 120));
    ofDrawBitmapString("b: " + ofToString((int)b), ofPoint(10, 140));

    ofDrawBitmapString("select: " + ofToString(select), ofPoint(10, 170));
}

//--------------------------------------------------------------
void ofApp::keyPressed(int key){
#if ENABLE_UNBIND
    if(key == 'r') {
        ofxWebUI::ui().unbindParameter("x");
    }
#endif
}

//--------------------------------------------------------------
void ofApp::keyReleased(int key){

}

//--------------------------------------------------------------
void ofApp::mouseMoved(int x, int y ){

}

//--------------------------------------------------------------
void ofApp::mouseDragged(int x, int y, int button){

}

//--------------------------------------------------------------
void ofApp::mousePressed(int x, int y, int button){

}

//--------------------------------------------------------------
void ofApp::mouseReleased(int x, int y, int button){

}

//--------------------------------------------------------------
void ofApp::windowResized(int w, int h){

}

//--------------------------------------------------------------
void ofApp::gotMessage(ofMessage msg){

}

//--------------------------------------------------------------
void ofApp::dragEvent(ofDragInfo dragInfo){

}
<|endoftext|>


<commit_before>/**
 * Copyright 2013 Da Zheng
 *
 * This file is part of SAFSlib.
 *
 * SAFSlib is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * SAFSlib is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with SAFSlib.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <numa.h>
#include <sys/mman.h>

#include "debugger.h"
#include "slab_allocator.h"

static atomic_number<size_t> tot_slab_size;
static atomic_flags<int> register_flag;

class debug_all_slab_task: public debug_task
{
public:
	void run() {
		printf("The size of all slab allocators: %ldMB\n",
				tot_slab_size.get() / 1024 / 1024);
	}
};

class debug_slab_alloc_task: public debug_task
{
	slab_allocator *alloc;
public:
	debug_slab_alloc_task(slab_allocator *alloc) {
		this->alloc = alloc;
	}

	void run() {
		printf("%s: obj size: %d, max size: %ldMB, curr size: %ldMB\n",
				alloc->get_name().c_str(), alloc->get_obj_size(),
				alloc->get_max_size() / 1024 / 1024,
				alloc->get_curr_size() / 1024 / 1024);
	}
};

slab_allocator::slab_allocator(const std::string &name, int _obj_size,
		long _increase_size, long _max_size, int _node_id,
		// We allow pages to be pinned when allocated.
		bool init, bool pinned, int _local_buf_size, bool _thread_safe): obj_size(
			_obj_size), increase_size(ROUNDUP_PAGE(_increase_size)),
		max_size(_max_size), node_id(_node_id), local_buf_size(_local_buf_size),
		thread_safe(_thread_safe)
#ifdef MEMCHECK
		   , allocator(obj_size)
#endif
{
	if (!register_flag.set_flag(0))
		debug.register_task(new debug_all_slab_task());
	debug.register_task(new debug_slab_alloc_task(this));
	// To make each name unique.
	this->name = name + "-" + itoa(alloc_counter.inc(1));
	this->init = init;
	this->pinned = pinned;
	assert((unsigned) obj_size >= sizeof(linked_obj));
	pthread_spin_init(&lock, PTHREAD_PROCESS_PRIVATE);
	pthread_key_create(&local_buf_key, NULL);
	pthread_key_create(&local_free_key, NULL);
}

void slab_allocator::free(char *obj)
{
	if (local_buf_size == 0) {
		slab_allocator::free(&obj, 1);
	}
	else {
		fifo_queue<char *> *local_free_refs
			= (fifo_queue<char *> *) pthread_getspecific(local_free_key);
		if (local_free_refs == NULL) {
			local_free_refs = fifo_queue<char *>::create(node_id, local_buf_size);
			pthread_setspecific(local_free_key, local_free_refs);
		}
		if (local_free_refs->is_full()) {
			char *objs[local_buf_size];
			int num = local_free_refs->fetch(objs, local_buf_size);
			slab_allocator::free(objs, num);
		}
		local_free_refs->push_back(obj);
	}
}

char *slab_allocator::alloc()
{
	if (local_buf_size == 0) {
		char *obj;
		int num = alloc(&obj, 1);
		if (num == 0)
			return NULL;
		else
			return obj;
	}
	else {
		fifo_queue<char *> *local_buf_refs
			= (fifo_queue<char *> *) pthread_getspecific(local_buf_key);
		if (local_buf_refs == NULL) {
			assert(node_id >= 0);
			local_buf_refs = fifo_queue<char *>::create(node_id, local_buf_size);
			pthread_setspecific(local_buf_key, local_buf_refs);
		}

		if (local_buf_refs->is_empty()) {
			char *objs[local_buf_size];
			int num = alloc(objs, local_buf_size);
			if (num == 0)
				return NULL;
			int num_added = local_buf_refs->add(objs, num);
			assert(num_added == num);
		}
		return local_buf_refs->pop_front();
	}
}

int slab_allocator::alloc(char **objs, int nobjs) {
#ifdef MEMCHECK
	for (int i = 0; i < nobjs; i++) {
		objs[i] = (char *) allocator.alloc(obj_size);
		if (init)
			memset(objs[i], 0, obj_size);
	}
	return nobjs;
#else
	int num = 0;

	while (true) {
		if (thread_safe)
			pthread_spin_lock(&lock);
		linked_obj *o = list.pop(nobjs - num);
		if (thread_safe)
			pthread_spin_unlock(&lock);
		while (o != NULL) {
			objs[num++] = (char *) o;
			o = o->get_next();
		}
		if (num == nobjs)
			break;

		// This piece of code shouldn't be executed very frequently,
		// otherwise, the performance can be pretty bad.
		if (thread_safe)
			pthread_spin_lock(&lock);
		if (curr_size.get() < max_size) {
			// We should increase the current size in advance, so other threads
			// can see what this thread is doing here.
			curr_size.inc(increase_size);
			tot_slab_size.inc(increase_size);
			if (thread_safe)
				pthread_spin_unlock(&lock);
			char *objs;
			if (node_id == -1)
				objs = (char *) numa_alloc_local(increase_size);
			else
				objs = (char *) numa_alloc_onnode(increase_size, node_id);
			assert(objs);
#ifdef USE_IOAT
			if (pinned) {
				int ret = mlock(objs, increase_size);
				if (ret < 0)
					perror("mlock");
				assert(ret == 0);
			}
#endif
			assert(((long) objs) % PAGE_SIZE == 0);
			if (init)
				memset(objs, 0, increase_size);
			linked_obj_list tmp_list;
			for (int i = 0; i < increase_size / obj_size; i++) {
				linked_obj *header = (linked_obj *) (objs
						+ obj_size * i);
				*header = linked_obj();
				tmp_list.add(header);
			}
			if (thread_safe)
				pthread_spin_lock(&lock);
			alloc_bufs.push_back(objs);
			list.add_list(&tmp_list);
			if (thread_safe)
				pthread_spin_unlock(&lock);
		}
		else {
			if (thread_safe)
				pthread_spin_unlock(&lock);
			// If we can't allocate all objects, then free all objects that
			// have been allocated, and return 0.
			free(objs, num);
			return 0;
		}
	}
	return nobjs;
#endif
}

slab_allocator::~slab_allocator()
{
	for (unsigned i = 0; i < alloc_bufs.size(); i++) {
#ifdef USE_IOAT
		if (pinned) {
#ifdef DEBUG
			printf("unpin buf %p of %ld bytes\n", alloc_bufs[i], increase_size);
#endif
			munlock(alloc_bufs[i], increase_size);
		}
#endif
		numa_free(alloc_bufs[i], increase_size);
	}
	pthread_spin_destroy(&lock);
}

void slab_allocator::free(char **objs, int nobjs) {
#ifdef MEMCHECK
	for (int i = 0; i < nobjs; i++)
		allocator.dealloc(objs[i]);
#else
	linked_obj_list tmp_list;
	for (int i = 0; i < nobjs; i++) {
		linked_obj *o = (linked_obj *) objs[i];
		*o = linked_obj();
		tmp_list.add(o);
	}
	if (thread_safe)
		pthread_spin_lock(&lock);
	list.add_list(&tmp_list);
	if (thread_safe)
		pthread_spin_unlock(&lock);
#endif
}

atomic_integer slab_allocator::alloc_counter;
<commit_msg>[SAFS]: print error msg when slab allocator fails to alloc memory.<commit_after>/**
 * Copyright 2013 Da Zheng
 *
 * This file is part of SAFSlib.
 *
 * SAFSlib is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * SAFSlib is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with SAFSlib.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <numa.h>
#include <sys/mman.h>

#include "debugger.h"
#include "slab_allocator.h"

static atomic_number<size_t> tot_slab_size;
static atomic_flags<int> register_flag;

class debug_all_slab_task: public debug_task
{
public:
	void run() {
		printf("The size of all slab allocators: %ldMB\n",
				tot_slab_size.get() / 1024 / 1024);
	}
};

class debug_slab_alloc_task: public debug_task
{
	slab_allocator *alloc;
public:
	debug_slab_alloc_task(slab_allocator *alloc) {
		this->alloc = alloc;
	}

	void run() {
		printf("%s: obj size: %d, max size: %ldMB, curr size: %ldMB\n",
				alloc->get_name().c_str(), alloc->get_obj_size(),
				alloc->get_max_size() / 1024 / 1024,
				alloc->get_curr_size() / 1024 / 1024);
	}
};

slab_allocator::slab_allocator(const std::string &name, int _obj_size,
		long _increase_size, long _max_size, int _node_id,
		// We allow pages to be pinned when allocated.
		bool init, bool pinned, int _local_buf_size, bool _thread_safe): obj_size(
			_obj_size), increase_size(ROUNDUP_PAGE(_increase_size)),
		max_size(_max_size), node_id(_node_id), local_buf_size(_local_buf_size),
		thread_safe(_thread_safe)
#ifdef MEMCHECK
		   , allocator(obj_size)
#endif
{
	if (!register_flag.set_flag(0))
		debug.register_task(new debug_all_slab_task());
	debug.register_task(new debug_slab_alloc_task(this));
	// To make each name unique.
	this->name = name + "-" + itoa(alloc_counter.inc(1));
	this->init = init;
	this->pinned = pinned;
	assert((unsigned) obj_size >= sizeof(linked_obj));
	pthread_spin_init(&lock, PTHREAD_PROCESS_PRIVATE);
	pthread_key_create(&local_buf_key, NULL);
	pthread_key_create(&local_free_key, NULL);
}

void slab_allocator::free(char *obj)
{
	if (local_buf_size == 0) {
		slab_allocator::free(&obj, 1);
	}
	else {
		fifo_queue<char *> *local_free_refs
			= (fifo_queue<char *> *) pthread_getspecific(local_free_key);
		if (local_free_refs == NULL) {
			local_free_refs = fifo_queue<char *>::create(node_id, local_buf_size);
			pthread_setspecific(local_free_key, local_free_refs);
		}
		if (local_free_refs->is_full()) {
			char *objs[local_buf_size];
			int num = local_free_refs->fetch(objs, local_buf_size);
			slab_allocator::free(objs, num);
		}
		local_free_refs->push_back(obj);
	}
}

char *slab_allocator::alloc()
{
	if (local_buf_size == 0) {
		char *obj;
		int num = alloc(&obj, 1);
		if (num == 0)
			return NULL;
		else
			return obj;
	}
	else {
		fifo_queue<char *> *local_buf_refs
			= (fifo_queue<char *> *) pthread_getspecific(local_buf_key);
		if (local_buf_refs == NULL) {
			assert(node_id >= 0);
			local_buf_refs = fifo_queue<char *>::create(node_id, local_buf_size);
			pthread_setspecific(local_buf_key, local_buf_refs);
		}

		if (local_buf_refs->is_empty()) {
			char *objs[local_buf_size];
			int num = alloc(objs, local_buf_size);
			if (num == 0)
				return NULL;
			int num_added = local_buf_refs->add(objs, num);
			assert(num_added == num);
		}
		return local_buf_refs->pop_front();
	}
}

int slab_allocator::alloc(char **objs, int nobjs) {
#ifdef MEMCHECK
	for (int i = 0; i < nobjs; i++) {
		objs[i] = (char *) allocator.alloc(obj_size);
		if (init)
			memset(objs[i], 0, obj_size);
	}
	return nobjs;
#else
	int num = 0;

	while (true) {
		if (thread_safe)
			pthread_spin_lock(&lock);
		linked_obj *o = list.pop(nobjs - num);
		if (thread_safe)
			pthread_spin_unlock(&lock);
		while (o != NULL) {
			objs[num++] = (char *) o;
			o = o->get_next();
		}
		if (num == nobjs)
			break;

		// This piece of code shouldn't be executed very frequently,
		// otherwise, the performance can be pretty bad.
		if (thread_safe)
			pthread_spin_lock(&lock);
		if (curr_size.get() < max_size) {
			// We should increase the current size in advance, so other threads
			// can see what this thread is doing here.
			curr_size.inc(increase_size);
			tot_slab_size.inc(increase_size);
			if (thread_safe)
				pthread_spin_unlock(&lock);
			char *objs;
			if (node_id == -1)
				objs = (char *) numa_alloc_local(increase_size);
			else
				objs = (char *) numa_alloc_onnode(increase_size, node_id);
			assert(objs);
#ifdef USE_IOAT
			if (pinned) {
				int ret = mlock(objs, increase_size);
				if (ret < 0)
					perror("mlock");
				assert(ret == 0);
			}
#endif
			assert(((long) objs) % PAGE_SIZE == 0);
			if (init)
				memset(objs, 0, increase_size);
			linked_obj_list tmp_list;
			for (int i = 0; i < increase_size / obj_size; i++) {
				linked_obj *header = (linked_obj *) (objs
						+ obj_size * i);
				*header = linked_obj();
				tmp_list.add(header);
			}
			if (thread_safe)
				pthread_spin_lock(&lock);
			alloc_bufs.push_back(objs);
			list.add_list(&tmp_list);
			if (thread_safe)
				pthread_spin_unlock(&lock);
		}
		else {
			if (thread_safe)
				pthread_spin_unlock(&lock);
			// If we can't allocate all objects, then free all objects that
			// have been allocated, and return 0.
			free(objs, num);
			fprintf(stderr, "the slab allocator %s uses %ld bytes\n",
					name.c_str(), get_curr_size());
			return 0;
		}
	}
	return nobjs;
#endif
}

slab_allocator::~slab_allocator()
{
	for (unsigned i = 0; i < alloc_bufs.size(); i++) {
#ifdef USE_IOAT
		if (pinned) {
#ifdef DEBUG
			printf("unpin buf %p of %ld bytes\n", alloc_bufs[i], increase_size);
#endif
			munlock(alloc_bufs[i], increase_size);
		}
#endif
		numa_free(alloc_bufs[i], increase_size);
	}
	pthread_spin_destroy(&lock);
}

void slab_allocator::free(char **objs, int nobjs) {
#ifdef MEMCHECK
	for (int i = 0; i < nobjs; i++)
		allocator.dealloc(objs[i]);
#else
	linked_obj_list tmp_list;
	for (int i = 0; i < nobjs; i++) {
		linked_obj *o = (linked_obj *) objs[i];
		*o = linked_obj();
		tmp_list.add(o);
	}
	if (thread_safe)
		pthread_spin_lock(&lock);
	list.add_list(&tmp_list);
	if (thread_safe)
		pthread_spin_unlock(&lock);
#endif
}

atomic_integer slab_allocator::alloc_counter;
<|endoftext|>


<commit_before>/*
   For more information, please see: http://software.sci.utah.edu

   The MIT License

   Copyright (c) 2014 Scientific Computing and Imaging Institute,
   University of Utah.

   Permission is hereby granted, free of charge, to any person obtaining a
   copy of this software and associated documentation files (the "Software"),
   to deal in the Software without restriction, including without limitation
   the rights to use, copy, modify, merge, publish, distribute, sublicense,
   and/or sell copies of the Software, and to permit persons to whom the
   Software is furnished to do so, subject to the following conditions:

   The above copyright notice and this permission notice shall be included
   in all copies or substantial portions of the Software.

   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
   THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
   DEALINGS IN THE SOFTWARE.
*/

/// \author James Hughes
/// \date   February 2014

#include "ESCoreBase.hpp"

namespace CPM_ES_NS {

EmptyComponentContainer ESCoreBase::mEmptyContainer;

bool ESCoreBase::hasComponentContainer(uint64_t componentID) const
{
  auto it = mComponents.find(componentID);
  if (it == mComponents.end())
    return false;
  else
    return true;
}

/// When called, ESCoreBase takes ownership of \p component.
/// Adds a new component to the system. If a component of the same
/// TypeID already exists, the request is ignored.
void ESCoreBase::addComponentContainer(BaseComponentContainer* componentCont, uint64_t componentID)
{
  auto it = mComponents.find(componentID);
  if (it == mComponents.end())
  {
    mComponents.insert(std::make_pair(componentID, componentCont));
  }
  else
  {
    std::cerr << "cpm-entity-system - Warning: Attempting to add pre-existing component container!" << std::endl;
    delete componentCont;
  }
}

/// Retrieves a base component container. Component is the output from
/// the TemplateID class.
BaseComponentContainer* ESCoreBase::getComponentContainer(uint64_t component)
{
  auto it = mComponents.find(component);
  if (it != mComponents.end())
    return (it->second);
  else
    return nullptr;
}

/// Clears out all component containers (deletes all entities).
void ESCoreBase::clearAllComponentContainers()
{
  for (auto iter = mComponents.begin(); iter != mComponents.end(); ++iter)
    iter->second->removeAll();
}

void ESCoreBase::deleteAllComponentContainers()
{
  for (auto iter = mComponents.begin(); iter != mComponents.end(); ++iter)
    delete iter->second;

  mComponents.clear();
}

/// Call this function at the beginning or end of every frame. It renormalizes
/// all your components (adds / removes components). To call a system, execute
/// the walkComponents function on BaseSystem. Most systems don't need a
/// stable sort. But if you need to guarantee the relative order of multiple
/// components with the same entity ID, use stable sort.
void ESCoreBase::renormalize(bool stableSort)
{
  for (auto iter = mComponents.begin(); iter != mComponents.end(); ++iter)
    iter->second->renormalize(stableSort);
}

/// Removes all components associated with entity.
void ESCoreBase::removeEntity(uint64_t entityID)
{
  for (auto iter = mComponents.begin(); iter != mComponents.end(); ++iter)
    iter->second->removeSequence(entityID);
}

void ESCoreBase::removeFirstComponent(uint64_t entityID, uint64_t compTemplateID)
{
  BaseComponentContainer* cont = getComponentContainer(compTemplateID);
  cont->removeFirstSequence(entityID);
}

void ESCoreBase::removeLastComponent(uint64_t entityID, uint64_t compTemplateID)
{
  BaseComponentContainer* cont = getComponentContainer(compTemplateID);
  cont->removeLastSequence(entityID);
}

void ESCoreBase::removeComponentAtIndex(uint64_t entityID, int32_t index, uint64_t templateID)
{
  BaseComponentContainer* cont = getComponentContainer(templateID);
  cont->removeSequenceWithIndex(entityID, index);
}

void ESCoreBase::removeAllComponents(uint64_t entityID, uint64_t compTemplateID)
{
  BaseComponentContainer* cont = getComponentContainer(compTemplateID);
  cont->removeSequence(entityID);
}

} // namespace CPM_ES_NS

<commit_msg>Get rid of unnecessary header.<commit_after>#include "ESCoreBase.hpp"

namespace CPM_ES_NS {

EmptyComponentContainer ESCoreBase::mEmptyContainer;

bool ESCoreBase::hasComponentContainer(uint64_t componentID) const
{
  auto it = mComponents.find(componentID);
  if (it == mComponents.end())
    return false;
  else
    return true;
}

/// When called, ESCoreBase takes ownership of \p component.
/// Adds a new component to the system. If a component of the same
/// TypeID already exists, the request is ignored.
void ESCoreBase::addComponentContainer(BaseComponentContainer* componentCont, uint64_t componentID)
{
  auto it = mComponents.find(componentID);
  if (it == mComponents.end())
  {
    mComponents.insert(std::make_pair(componentID, componentCont));
  }
  else
  {
    std::cerr << "cpm-entity-system - Warning: Attempting to add pre-existing component container!" << std::endl;
    delete componentCont;
  }
}

/// Retrieves a base component container. Component is the output from
/// the TemplateID class.
BaseComponentContainer* ESCoreBase::getComponentContainer(uint64_t component)
{
  auto it = mComponents.find(component);
  if (it != mComponents.end())
    return (it->second);
  else
    return nullptr;
}

/// Clears out all component containers (deletes all entities).
void ESCoreBase::clearAllComponentContainers()
{
  for (auto iter = mComponents.begin(); iter != mComponents.end(); ++iter)
    iter->second->removeAll();
}

void ESCoreBase::deleteAllComponentContainers()
{
  for (auto iter = mComponents.begin(); iter != mComponents.end(); ++iter)
    delete iter->second;

  mComponents.clear();
}

/// Call this function at the beginning or end of every frame. It renormalizes
/// all your components (adds / removes components). To call a system, execute
/// the walkComponents function on BaseSystem. Most systems don't need a
/// stable sort. But if you need to guarantee the relative order of multiple
/// components with the same entity ID, use stable sort.
void ESCoreBase::renormalize(bool stableSort)
{
  for (auto iter = mComponents.begin(); iter != mComponents.end(); ++iter)
    iter->second->renormalize(stableSort);
}

/// Removes all components associated with entity.
void ESCoreBase::removeEntity(uint64_t entityID)
{
  for (auto iter = mComponents.begin(); iter != mComponents.end(); ++iter)
    iter->second->removeSequence(entityID);
}

void ESCoreBase::removeFirstComponent(uint64_t entityID, uint64_t compTemplateID)
{
  BaseComponentContainer* cont = getComponentContainer(compTemplateID);
  cont->removeFirstSequence(entityID);
}

void ESCoreBase::removeLastComponent(uint64_t entityID, uint64_t compTemplateID)
{
  BaseComponentContainer* cont = getComponentContainer(compTemplateID);
  cont->removeLastSequence(entityID);
}

void ESCoreBase::removeComponentAtIndex(uint64_t entityID, int32_t index, uint64_t templateID)
{
  BaseComponentContainer* cont = getComponentContainer(templateID);
  cont->removeSequenceWithIndex(entityID, index);
}

void ESCoreBase::removeAllComponents(uint64_t entityID, uint64_t compTemplateID)
{
  BaseComponentContainer* cont = getComponentContainer(compTemplateID);
  cont->removeSequence(entityID);
}

} // namespace CPM_ES_NS

<|endoftext|>


<commit_before>/*
 * avsinfo main.cpp
 *  Shows informations of AviSynth script
 *  Copyright (C) 2010 janus_wel<janus.wel.3@gmail.com>
 *  see LICENSE for redistributing, modifying, and so on.
 * */

#include "../../include/avsutil.hpp"
#include "avsinfo.hpp"
#include "items.hpp"
#include "../../helper/tconv.hpp"

#include <iostream>
#include <iomanip>
#include <string>
#include <locale>
#include <memory>   // for std::auto_ptr
#include <bitset>

// using namespaces
using namespace std;
using namespace avsutil;
using namespace avsinfo::general;
using namespace avsinfo::items;

// forward declarations
template <typename T> void print_video_items(const video::item_t item, const T value);
template <typename T> void print_audio_items(const audio::item_t item, const T value);
const string readable_channles(const unsigned int channels);
const unsigned int calc_gcd(unsigned int a, unsigned int b);
const string width_to_height_ratio(const unsigned int width, const unsigned int height);

// constants
const unsigned int header_max = 20;
const char* header_delimeter = ": ";

// global objects
util::string::converter conv;
bool machine_flag = false;

int main(const int argc, const char* const argv[]) {
    // set global locale to use non-ascii characters for filenames
    locale::global(locale(""));

    string inputfile;
    bool no_options_flag = true;
    bitset<video::num> video_flags;
    bitset<audio::num> audio_flags;
    for (int i = 1; i < argc; ++i) {
        const string arg(argv[i]);
        if (arg == "-h" || arg == "--help") {
            usage(cout);
            return OK;
        }
        else if (arg == "-v" || arg == "--version") {
            version_license(cout);
            return OK;
        }
        else if (arg == "-m" || arg == "--machine") {
            machine_flag = true;
            continue;
        }
        else if (arg == "-a" || arg == "--all") {
            video_flags.set();
            audio_flags.set();
            no_options_flag = false;
            continue;
        }
        else if (arg == "-i" || arg == "--video") {
            video_flags.set();
            no_options_flag = false;
            continue;
        }
        else if (arg == "-u" || arg == "--audio") {
            audio_flags.set();
            no_options_flag = false;
            continue;
        }
        else if (arg[0] == '-') {
            cerr << "Unknown option: \"" << arg << '"' << endl;
            usage(cerr);
            return BAD_ARG;
        }
        else {
            if (no_options_flag) {
                video_flags.set();
                audio_flags.set();
            }
            inputfile = arg;
            break;
        }
    }

    if (inputfile.empty()) {
        cerr << "Specify <inputfile>." << endl;
        usage(cerr);
        return BAD_ARG;
    }

    // preparations
    auto_ptr<Avs> avs(CreateAvsObj(inputfile.c_str()));
    if (!avs->is_fine()) {
        cout << avs->errmsg() << endl;
        return BAD_AVS;
    }

    cout << left;

    // video stream items
    if (video_flags.any()) {
        auto_ptr<Video> video(avs->video());
        const VideoInfo vi = video->info();

        if (vi.exists) {
            using namespace avsinfo::items::video;

            if (video_flags[WIDTH])             print_video_items(WIDTH, vi.width);
            if (video_flags[HEIGHT])            print_video_items(HEIGHT, vi.height);
            if (video_flags[RATIO])             print_video_items(RATIO, width_to_height_ratio(vi.width, vi.height));
            if (video_flags[FPS])               print_video_items(FPS, vi.fps);
            if (video_flags[FPS_FRACTION]) {
                print_video_items(FPS_FRACTION, conv.strfrom(vi.fps_numerator) + '/' + conv.strfrom(vi.fps_denominator));
            }
            if (video_flags[VIDEO_TIME])        print_video_items(VIDEO_TIME, vi.time);
            if (video_flags[FRAMES])            print_video_items(FRAMES, vi.numof_frames);
            if (video_flags[COLOR_SPACE])       print_video_items(COLOR_SPACE, vi.color_space);
            if (video_flags[BPP])               print_video_items(BPP, vi.bpp);
            if (video_flags[INTERLACE_TYPE]) {
                if (machine_flag) print_video_items(INTERLACE_TYPE, vi.is_fieldbased);
                else print_video_items(INTERLACE_TYPE, (vi.is_fieldbased ? "field based" : "frame based"));
            }
            if (video_flags[FIELD_ORDER]) {
                if (machine_flag) print_video_items(FIELD_ORDER, vi.is_tff);
                else print_video_items(FIELD_ORDER, (vi.is_tff ? "top field first" : "bottom field first"));
            }
        }
        else {
            cerr << "<inputfile> has no video stream: " << inputfile << endl;
        }
    }

    // audio stream items
    if (audio_flags.any()) {
        auto_ptr<Audio> audio(avs->audio());
        const AudioInfo ai = audio->info();

        if (ai.exists) {
            using namespace avsinfo::items::audio;

            if (audio_flags[CHANNELS]) {
                if (machine_flag) print_audio_items(CHANNELS, ai.channels);
                else print_audio_items(CHANNELS, readable_channles(ai.channels));
            }
            if (audio_flags[BIT_DEPTH])     print_audio_items(BIT_DEPTH, ai.bit_depth);
            if (audio_flags[SAMPLE_TYPE]) {
                if (machine_flag) print_audio_items(SAMPLE_TYPE, ai.is_int);
                else print_audio_items(SAMPLE_TYPE, (ai.is_int ? "int" : "float"));
            }
            if (audio_flags[AUDIO_TIME])    print_audio_items(AUDIO_TIME, ai.time);
            if (audio_flags[SAMPLING_RATE]) {
                if (machine_flag) print_audio_items(SAMPLING_RATE, ai.sampling_rate);
                else print_audio_items(SAMPLING_RATE, static_cast<double>(ai.sampling_rate) / 1000);
            }
            if (audio_flags[SAMPLES])       print_audio_items(SAMPLES, ai.numof_samples);
            if (audio_flags[BLOCK_SIZE])    print_audio_items(BLOCK_SIZE, ai.block_size);
        }
        else {
            cerr << "<inputfile> has no audio stream: " << inputfile << endl;
        }
    }

    return OK;
}

// function definitions
template <typename T>
void print_video_items(const video::item_t item, const T value) {
    if (!machine_flag) cout << setw(header_max) << video::header[item] << header_delimeter;
    cout << value;
    if (!machine_flag) cout << video::unit[item];
    cout << endl;
}

template <typename T>
void print_audio_items(const audio::item_t item, const T value) {
    if (!machine_flag) cout << setw(header_max) << audio::header[item] << header_delimeter;
    cout << value;
    if (!machine_flag) cout << audio::unit[item];
    cout << endl;
}

const string readable_channles(const unsigned int channels) {
    switch (channels) {
        case 1:
            return string("mono");
        case 2:
            return string("stereo");
        case 6:
            return string("5.1ch");
        default:
            return conv.strfrom(channels) + "ch";
    }
}

// gcd is abbr for greatest common divisor
// Euclidean algorithm
const unsigned int calc_gcd(unsigned int a, unsigned int b) {
    if (b == 0) return a;
    for (;;) {
        a %= b;
        if (a == 0) return b;
        b %= a;
        if (b == 0) return a;
    }
}

const string width_to_height_ratio(const unsigned int width, const unsigned int height) {
    const unsigned int gcd = calc_gcd(width, height);
    return conv.strfrom(width/gcd) + ':' + conv.strfrom(height/gcd);
}

<commit_msg>Show color-space name<commit_after>/*
 * avsinfo main.cpp
 *  Shows informations of AviSynth script
 *  Copyright (C) 2010 janus_wel<janus.wel.3@gmail.com>
 *  see LICENSE for redistributing, modifying, and so on.
 * */

#include "../../include/avsutil.hpp"
#include "avsinfo.hpp"
#include "items.hpp"
#include "../../helper/tconv.hpp"

#include <iostream>
#include <iomanip>
#include <string>
#include <locale>
#include <memory>   // for std::auto_ptr
#include <bitset>

// using namespaces
using namespace std;
using namespace avsutil;
using namespace avsinfo::general;
using namespace avsinfo::items;

// forward declarations
template <typename T> void print_video_items(const video::item_t item, const T value);
template <typename T> void print_audio_items(const audio::item_t item, const T value);
const string readable_channles(const unsigned int channels);
const unsigned int calc_gcd(unsigned int a, unsigned int b);
const string width_to_height_ratio(const unsigned int width, const unsigned int height);

// constants
const unsigned int header_max = 20;
const char* header_delimeter = ": ";

// global objects
util::string::converter conv;
bool machine_flag = false;

int main(const int argc, const char* const argv[]) {
    // set global locale to use non-ascii characters for filenames
    locale::global(locale(""));

    string inputfile;
    bool no_options_flag = true;
    bitset<video::num> video_flags;
    bitset<audio::num> audio_flags;
    for (int i = 1; i < argc; ++i) {
        const string arg(argv[i]);
        if (arg == "-h" || arg == "--help") {
            usage(cout);
            return OK;
        }
        else if (arg == "-v" || arg == "--version") {
            version_license(cout);
            return OK;
        }
        else if (arg == "-m" || arg == "--machine") {
            machine_flag = true;
            continue;
        }
        else if (arg == "-a" || arg == "--all") {
            video_flags.set();
            audio_flags.set();
            no_options_flag = false;
            continue;
        }
        else if (arg == "-i" || arg == "--video") {
            video_flags.set();
            no_options_flag = false;
            continue;
        }
        else if (arg == "-u" || arg == "--audio") {
            audio_flags.set();
            no_options_flag = false;
            continue;
        }
        else if (arg[0] == '-') {
            cerr << "Unknown option: \"" << arg << '"' << endl;
            usage(cerr);
            return BAD_ARG;
        }
        else {
            if (no_options_flag) {
                video_flags.set();
                audio_flags.set();
            }
            inputfile = arg;
            break;
        }
    }

    if (inputfile.empty()) {
        cerr << "Specify <inputfile>." << endl;
        usage(cerr);
        return BAD_ARG;
    }

    // preparations
    auto_ptr<Avs> avs(CreateAvsObj(inputfile.c_str()));
    if (!avs->is_fine()) {
        cout << avs->errmsg() << endl;
        return BAD_AVS;
    }

    cout << left;

    // video stream items
    if (video_flags.any()) {
        auto_ptr<Video> video(avs->video());
        const VideoInfo vi = video->info();

        if (vi.exists) {
            using namespace avsinfo::items::video;

            if (video_flags[WIDTH])             print_video_items(WIDTH, vi.width);
            if (video_flags[HEIGHT])            print_video_items(HEIGHT, vi.height);
            if (video_flags[RATIO])             print_video_items(RATIO, width_to_height_ratio(vi.width, vi.height));
            if (video_flags[FPS])               print_video_items(FPS, vi.fps);
            if (video_flags[FPS_FRACTION]) {
                print_video_items(FPS_FRACTION, conv.strfrom(vi.fps_numerator) + '/' + conv.strfrom(vi.fps_denominator));
            }
            if (video_flags[VIDEO_TIME])        print_video_items(VIDEO_TIME, vi.time);
            if (video_flags[FRAMES])            print_video_items(FRAMES, vi.numof_frames);
            if (video_flags[COLOR_SPACE])       print_video_items(COLOR_SPACE, VideoInfo::fourcc_name(vi.color_space));
            if (video_flags[BPP])               print_video_items(BPP, vi.bpp);
            if (video_flags[INTERLACE_TYPE]) {
                if (machine_flag) print_video_items(INTERLACE_TYPE, vi.is_fieldbased);
                else print_video_items(INTERLACE_TYPE, (vi.is_fieldbased ? "field based" : "frame based"));
            }
            if (video_flags[FIELD_ORDER]) {
                if (machine_flag) print_video_items(FIELD_ORDER, vi.is_tff);
                else print_video_items(FIELD_ORDER, (vi.is_tff ? "top field first" : "bottom field first"));
            }
        }
        else {
            cerr << "<inputfile> has no video stream: " << inputfile << endl;
        }
    }

    // audio stream items
    if (audio_flags.any()) {
        auto_ptr<Audio> audio(avs->audio());
        const AudioInfo ai = audio->info();

        if (ai.exists) {
            using namespace avsinfo::items::audio;

            if (audio_flags[CHANNELS]) {
                if (machine_flag) print_audio_items(CHANNELS, ai.channels);
                else print_audio_items(CHANNELS, readable_channles(ai.channels));
            }
            if (audio_flags[BIT_DEPTH])     print_audio_items(BIT_DEPTH, ai.bit_depth);
            if (audio_flags[SAMPLE_TYPE]) {
                if (machine_flag) print_audio_items(SAMPLE_TYPE, ai.is_int);
                else print_audio_items(SAMPLE_TYPE, (ai.is_int ? "int" : "float"));
            }
            if (audio_flags[AUDIO_TIME])    print_audio_items(AUDIO_TIME, ai.time);
            if (audio_flags[SAMPLING_RATE]) {
                if (machine_flag) print_audio_items(SAMPLING_RATE, ai.sampling_rate);
                else print_audio_items(SAMPLING_RATE, static_cast<double>(ai.sampling_rate) / 1000);
            }
            if (audio_flags[SAMPLES])       print_audio_items(SAMPLES, ai.numof_samples);
            if (audio_flags[BLOCK_SIZE])    print_audio_items(BLOCK_SIZE, ai.block_size);
        }
        else {
            cerr << "<inputfile> has no audio stream: " << inputfile << endl;
        }
    }

    return OK;
}

// function definitions
template <typename T>
void print_video_items(const video::item_t item, const T value) {
    if (!machine_flag) cout << setw(header_max) << video::header[item] << header_delimeter;
    cout << value;
    if (!machine_flag) cout << video::unit[item];
    cout << endl;
}

template <typename T>
void print_audio_items(const audio::item_t item, const T value) {
    if (!machine_flag) cout << setw(header_max) << audio::header[item] << header_delimeter;
    cout << value;
    if (!machine_flag) cout << audio::unit[item];
    cout << endl;
}

const string readable_channles(const unsigned int channels) {
    switch (channels) {
        case 1:
            return string("mono");
        case 2:
            return string("stereo");
        case 6:
            return string("5.1ch");
        default:
            return conv.strfrom(channels) + "ch";
    }
}

// gcd is abbr for greatest common divisor
// Euclidean algorithm
const unsigned int calc_gcd(unsigned int a, unsigned int b) {
    if (b == 0) return a;
    for (;;) {
        a %= b;
        if (a == 0) return b;
        b %= a;
        if (b == 0) return a;
    }
}

const string width_to_height_ratio(const unsigned int width, const unsigned int height) {
    const unsigned int gcd = calc_gcd(width, height);
    return conv.strfrom(width/gcd) + ':' + conv.strfrom(height/gcd);
}

<|endoftext|>


<commit_before>/*
 * Copyright (c) 2005, Peter Sommerlad and IFS Institute for Software at HSR Rapperswil, Switzerland
 * All rights reserved.
 *
 * This library/application is free software; you can redistribute and/or modify it under the terms of
 * the license that is included with this library/application in the file license.txt.
 */

//--- interface include --------------------------------------------------------
#include "Application.h"

//--- standard modules used ----------------------------------------------------
#include "AppBooter.h"
#include "Registry.h"
#include "SysLog.h"
#include "Dbg.h"

//--- c-library modules used ---------------------------------------------------
#if !defined(WIN32)
// used for dynamic load of libraries
#include <dlfcn.h>
#endif

// initializing static variables
Anything Application::fgConfig(Storage::Global());
Mutex Application::fgConfigMutex("ApplicationConfig");

RegisterApplication(Application);

Application::Application(const char *appName)
	: HierarchConfNamed(appName)
{
	StartTrace1(Application.Ctor, "Name:<" << NotNull(appName) << ">");
}

Application::~Application()
{
	StartTrace(Application.Dtor);
}

// intialization - loads configuration based on instance's name
int Application::Init()
{
	StartTrace(Application.Init);

	CheckConfig("Application", true);
	TraceAny(fConfig, "Application config");

	return 0;
}

// doing the work
int Application::Run()
{
	StartTrace(Application.Run);
	SysLog::WriteToStderr("That all I'm doing ;-)\n");
	return 0;
}

// termination
int Application::Terminate(int val)
{
	StartTrace(Application.Terminate);

	SysLog::WriteToStderr(String("Terminating: <") << fName << ">\n");
	// Check if last instance has be terminated

	return val;
}

// Looks up key in the instance's store then config and finally in the global config
bool Application::DoLookup(const char *key, ROAnything &result, char delim, char indexdelim) const
{
	StartTrace(Application.Lookup);
	// lookup the application store
//	{
//		MutexEntry me((Mutex&)fStoreMutex);
//		ROAnything store(fStore);
//		if ( store.LookupPath(result, key, delim, indexdelim) )
//		{
//			return true;
//		}
//	}

	// have a lookup in the application config
	if ( HierarchConfNamed::DoLookup(key, result, delim, indexdelim) ) {
		return true;
	}

	// lookup the main process config
	ROAnything config(fgConfig);
	return config.LookupPath(result, key, delim, indexdelim);
}

void Application::InitializeGlobalConfig(Anything theConfiguration)
{
	StartTrace(Application.InitializeGlobalConfig);
	MutexEntry me(fgConfigMutex);
	me.Use();
	fgConfig = theConfiguration; // SOP: will deepclone if needed
}

ROAnything Application::GetConfig()
{
	StartTrace(Application.GetConfig);

	if ( fgConfig.IsNull() ) {
		MutexEntry me(fgConfigMutex);
		me.Use();
		static bool bootonce = false;
		if ( !bootonce && fgConfig.IsNull() ) {
			SysLog::Info("implicit Application booting");

			bootonce = true;
			AppBooter booter;
			Anything dummyargs;
			if (!booter.Boot(dummyargs)) {
				SysLog::Error("Application booting failed");
			}
		}
	}
	return fgConfig;
}

Application *Application::GetGlobalApplication(String &applicationName)
{
	StartTrace(Application.GetGlobalApplication);
	Application *application = 0;
	if (!fgConfig.IsNull()) {
		Anything applicationConf;

		if (fgConfig.LookupPath(applicationConf, "Application") ) {
			for (long i = 0, sz = applicationConf.GetSize() && !application; i < sz; ++i) {
				// iterate over the applicationname list
				applicationName = applicationConf[i].AsCharPtr(0);
				if ( applicationName.Length() > 0 ) {
					// return the first application object found by name
					application = Application::FindApplication(applicationName);
					break;
				}
			}
		} else {
			// if no application object is configured in the config any
			// return the first in the list
			RegistryIterator ri(Registry::GetRegistry("Application"), false);
			for ( ; ri.HasMore() && !application ; application = SafeCast(ri.Next(applicationName), Application));
		}
	}
	return application;
}

// GlobalInit: installs ressources shared among all instances
int Application::GlobalInit(int argc, char *argv[], const ROAnything config)
{
	StartTrace(Application.GlobalInit);

	return Init();	// Call instance init
}

int Application::GlobalRun()
{
	StartTrace(Application.GlobalRun);
	return Run();
}

// GlobalTerminate: frees ressources shared among all instances
int Application::GlobalTerminate(int val)
{
	StartTrace(Application.GlobalTerminate);

	return Terminate(val);
}
//
//void Application::PutInStore(const char *key, const Anything &a)
//{
//	MutexEntry me(fStoreMutex);me.Use();
//	fStore[key]= a;
//}
//
//void Application::RemoveFromStore(const char *key)
//{
//	MutexEntry me(fStoreMutex);me.Use();
//	fStore.Remove(key);
//}
//
//---- registry api
RegCacheImpl(Application);	// FindApplication()
<commit_msg>removed implicit checkconfig calls<commit_after>/*
 * Copyright (c) 2005, Peter Sommerlad and IFS Institute for Software at HSR Rapperswil, Switzerland
 * All rights reserved.
 *
 * This library/application is free software; you can redistribute and/or modify it under the terms of
 * the license that is included with this library/application in the file license.txt.
 */

//--- interface include --------------------------------------------------------
#include "Application.h"

//--- standard modules used ----------------------------------------------------
#include "AppBooter.h"
#include "Registry.h"
#include "SysLog.h"
#include "Dbg.h"

//--- c-library modules used ---------------------------------------------------
#if !defined(WIN32)
// used for dynamic load of libraries
#include <dlfcn.h>
#endif

// initializing static variables
Anything Application::fgConfig(Storage::Global());
Mutex Application::fgConfigMutex("ApplicationConfig");

RegisterApplication(Application);

Application::Application(const char *appName)
	: HierarchConfNamed(appName)
{
	StartTrace1(Application.Ctor, "Name:<" << NotNull(appName) << ">");
}

Application::~Application()
{
	StartTrace(Application.Dtor);
}

// intialization - loads configuration based on instance's name
int Application::Init()
{
	StartTrace(Application.Init);
	return 0;
}

// doing the work
int Application::Run()
{
	StartTrace(Application.Run);
	SysLog::WriteToStderr("That all I'm doing ;-)\n");
	return 0;
}

// termination
int Application::Terminate(int val)
{
	StartTrace(Application.Terminate);

	SysLog::WriteToStderr(String("Terminating: <") << fName << ">\n");
	// Check if last instance has be terminated

	return val;
}

// Looks up key in the instance's store then config and finally in the global config
bool Application::DoLookup(const char *key, ROAnything &result, char delim, char indexdelim) const
{
	StartTrace(Application.Lookup);

	// have a lookup in the application config
	if ( HierarchConfNamed::DoLookup(key, result, delim, indexdelim) ) {
		return true;
	}

	// lookup the main process config
	ROAnything config(fgConfig);
	return config.LookupPath(result, key, delim, indexdelim);
}

void Application::InitializeGlobalConfig(Anything theConfiguration)
{
	StartTrace(Application.InitializeGlobalConfig);
	MutexEntry me(fgConfigMutex);
	me.Use();
	fgConfig = theConfiguration; // SOP: will deepclone if needed
}

ROAnything Application::GetConfig()
{
	StartTrace(Application.GetConfig);

	if ( fgConfig.IsNull() ) {
		MutexEntry me(fgConfigMutex);
		me.Use();
		static bool bootonce = false;
		if ( !bootonce && fgConfig.IsNull() ) {
			SysLog::Info("implicit Application booting");

			bootonce = true;
			AppBooter booter;
			Anything dummyargs;
			if (!booter.Boot(dummyargs)) {
				SysLog::Error("Application booting failed");
			}
		}
	}
	return fgConfig;
}

Application *Application::GetGlobalApplication(String &applicationName)
{
	StartTrace(Application.GetGlobalApplication);
	Application *application = 0;
	if (!fgConfig.IsNull()) {
		Anything applicationConf;

		if (fgConfig.LookupPath(applicationConf, "Application") ) {
			for (long i = 0, sz = applicationConf.GetSize() && !application; i < sz; ++i) {
				// iterate over the applicationname list
				applicationName = applicationConf[i].AsCharPtr(0);
				if ( applicationName.Length() > 0 ) {
					// return the first application object found by name
					application = Application::FindApplication(applicationName);
					break;
				}
			}
		} else {
			// if no application object is configured in the config any
			// return the first in the list
			RegistryIterator ri(Registry::GetRegistry("Application"), false);
			for ( ; ri.HasMore() && !application ; application = SafeCast(ri.Next(applicationName), Application));
		}
	}
	return application;
}

// GlobalInit: installs ressources shared among all instances
int Application::GlobalInit(int argc, char *argv[], const ROAnything config)
{
	StartTrace(Application.GlobalInit);
	return Init();	// Call instance init
}

int Application::GlobalRun()
{
	StartTrace(Application.GlobalRun);
	return Run();
}

// GlobalTerminate: frees ressources shared among all instances
int Application::GlobalTerminate(int val)
{
	StartTrace(Application.GlobalTerminate);

	return Terminate(val);
}

//---- registry api
RegCacheImpl(Application);	// FindApplication()
<|endoftext|>