<commit_before>
#include <osmesa.h>
#include <conio.h>
#include <dpmi.h>
#include <go32.h>
#include <sys/movedata.h>
#include <pc.h>
#include <sys/farptr.h>
#include <bios.h>
#include <sys/nearptr.h>

#include <cstdlib>
#include <cstdio>
#include <functional>
#include <cmath>
#include <algorithm>
#include <cmath>
#include <vector>
#include <cstring>
#include <memory>
#include <iostream>
#include <map>
#include <array>
#include <iostream>

#include <GL/gl.h>
#include <GL/glu.h>
#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtc/matrix_transform.hpp>

#include "NativeBitmap.h"
#include "SoundClip.h"
#include "SoundUtils.h"
#include "SoundListener.h"
#include "SoundEmitter.h"
#include "IFileLoaderDelegate.h"
#include "Vec2i.h"
#include "NativeBitmap.h"
#include "IMapElement.h"
#include "CTeam.h"
#include "CItem.h"
#include "CActor.h"
#include "CGameDelegate.h"
#include "CMap.h"
#include "IRenderer.h"
#include "CPlainFileLoader.h"
#include "NoudarDungeonSnapshot.h"
#include "GameNativeAPI.h"
#include "WindowOperations.h"
#include "Common.h"
#include "LoadPNG.h"
#include "DOSHacks.h"

const int bufferWidth = 64;
const int bufferHeight = 64;
const int screenWidth = 320;
const int screenHeight = 200;
bool done = false;
bool isActive = false;
long ms = 0;
bool automatic = false;
int imageBuffer[bufferWidth * bufferHeight];

std::function< std::string(std::string)> kDosLongFileNameTransformer = [](const std::string& filename ) {
  char c = 219;
  c = 176;
  c = 177;
  c = 178;
  c = '.';
  std::cout << c;
  std::cout.flush();

  auto dotPosition = std::find( std::begin(filename), std::end( filename), '.');
  auto indexDot =  std::distance( std::begin( filename ), dotPosition );
  auto extension = filename.substr( indexDot + 1, 3 );

  if ( indexDot >  8 ) {
    return filename.substr( 0, 6 ) + "~1." + extension;
  }

  if ( filename.length() - indexDot > 4 ) {
    return filename.substr( 0, indexDot ) + "~1." + extension;
  }

  return filename;
};

char readKbd() {
  unsigned char controlKbd;

  char lastKey = inportb(0x60);

  controlKbd = inportb(0x61);
  outportb( 0x61, controlKbd | 0x80 );
  outportb( 0x61, controlKbd );
  outportb( 0x20, inportb(0x20) );

  return lastKey;
}

void initMode13h() {
  __dpmi_regs reg;

  reg.x.ax = 0x13;
  __dpmi_int(0x10, &reg);

  outp(0x03c8, 0);

  for ( int r = 0; r < 4; ++r ) {
    for ( int g = 0; g < 4; ++g ) {
      for ( int b = 0; b < 4; ++b ) {
	outp(0x03c9, (r * (85) ) );
	outp(0x03c9, (g * (85) ) );
	outp(0x03c9, (b * (85) ) );
      }
    }
  }
}

unsigned char getPaletteEntry( int origin ) {
  unsigned char shade = 0;
  shade += (((((origin & 0x0000FF)      ) * 4  ) / 255 ) ) << 4;
  shade += (((((origin & 0x00FF00) >> 8 ) * 4  ) / 255 ) ) << 2;
  shade += (((((origin & 0xFF0000) >> 16) * 4  ) / 255 ) ) << 0;
  return shade;
}

void renderPalette() {
  _farsetsel(_dos_ds);

  for (int r = 0; r < 255; ++r) {
    for (int x = 0; x < 50; ++x) {

      int origin = r << 16;
      int shade = getPaletteEntry( origin );

      _farnspokeb(0xA0000 + (320 * x) + r, shade);
    }
  }

  for (int g = 0; g < 255; ++g) {
    for (int x = 50; x < 100; ++x) {
      int origin = g << 8;
      int shade = getPaletteEntry( origin );
      _farnspokeb(0xA0000 + (320 * x) + g, shade);
    }
  }

  for (int b = 0; b < 255; ++b) {
    for (int x = 100; x < 150; ++x) {
      int origin = b;
      int shade = getPaletteEntry( origin );
      _farnspokeb(0xA0000 + (320 * x) + b, shade);
    }
  }

  for (int b = 0; b < 255; ++b) {
    for (int x = 150; x < 200; ++x) {
      _farnspokeb(0xA0000 + (320 * x) + b, b);
    }
  }

  std::fill(std::end(imageBuffer) - (320 * 200), std::end(imageBuffer), 0x0);
}

void copyImageBufferToVideoMemory() {

  int offset = 0;

  unsigned char buffer[ screenWidth * screenHeight ];
  unsigned char bg =  getPaletteEntry( 0xFF0000 );
  memset( buffer, bg, screenWidth * screenHeight *sizeof(unsigned char));

  int origin = 0;
  int lastOrigin = -1;
  unsigned char shade = 0;

  for (int y = 0; y < (bufferHeight * 2 ); ++y) {
    for (int x = 0; x < (bufferWidth * 2); ++x) {

      offset = ((y/2) * (bufferWidth)) + (x/2);
      origin = imageBuffer[offset];

      if ( origin != lastOrigin ) {
	shade = getPaletteEntry( origin );
      }

      lastOrigin = origin;

      buffer[ ( y * screenWidth ) + (x + ( ( screenWidth - (2 * bufferWidth) ) / 2) ) ] = shade;
    }
  }

  dosmemput(buffer, screenWidth * screenHeight, 0xa0000);

  gotoxy(1, 18 );
  printf( "%s\n%d\n%ld", getCurrentObjectName().c_str(), getHP(), ms );

}

void exitToTextMode() {
  textmode(C80);
}

void initWindow() {
  OSMesaContext om = OSMesaCreateContext(OSMESA_RGBA, nullptr );
  OSMesaMakeCurrent(om, imageBuffer, GL_UNSIGNED_BYTE, bufferWidth, bufferHeight );
  OSMesaPixelStore( OSMESA_ROW_LENGTH, bufferWidth );
  OSMesaPixelStore( OSMESA_Y_UP, 0 );

  auto gVertexShader = "";
  auto gFragmentShader = "";
  auto fileLoader = std::make_shared<Knights::CPlainFileLoader>("res/");

  fileLoader->setFilenameTransformation(  kDosLongFileNameTransformer );
  setupGraphics(bufferWidth, bufferHeight, gVertexShader, gFragmentShader, fileLoader );

  auto soundListener = std::make_shared<odb::SoundListener>();

  std::vector<std::shared_ptr<odb::SoundEmitter>> sounds;

  setSoundEmitters(sounds, soundListener);
  initMode13h();
}

void tick() {
  ++ms;
  gameLoopTick(250);
  renderFrame(250);
  copyImageBufferToVideoMemory();
}

char read_char(void)
{
  union REGS regs;
  regs.x.ax = 0x0100; //DOS function 01h
  int86(0x21,&regs,&regs);

  return regs.x.ax;
}

void setMainLoop() {

  while (!done) {
    while (kbhit())
      switch (getch()) {
      case 27:
	done = true;
	break;
      case 'H':
      case 'w':
	moveUp();
	break;
      case 'P':
      case 's':
	moveDown();
	break;
      case 'd':
	moveRight();
	break;
      case 'a':
	moveLeft();
	break;
      case 'c':
	interact();
	break;
      case 'M':
      case 'e':
	rotateCameraRight();
	break;
      case 'K':
      case 'q':
	rotateCameraLeft();
	break;
      case 'z':
	cycleNextItem();
	break;
      case 'x':
	cyclePrevItem();
	break;

      case 'r':
	pickupItem();
	break;
      case 'f':
	dropItem();
	break;
      }
    tick();
  }
}

void destroyWindow() {
  shutdown();
  exitToTextMode();
  clrscr();
  std::cout << "Thank you for playing!" << std::endl;
}
<commit_msg>Better handle palette on DOS version<commit_after>
#include <osmesa.h>
#include <conio.h>
#include <dpmi.h>
#include <go32.h>
#include <sys/movedata.h>
#include <pc.h>
#include <sys/farptr.h>
#include <bios.h>
#include <sys/nearptr.h>

#include <cstdlib>
#include <cstdio>
#include <functional>
#include <cmath>
#include <algorithm>
#include <cmath>
#include <vector>
#include <cstring>
#include <memory>
#include <iostream>
#include <map>
#include <array>
#include <iostream>

#include <GL/gl.h>
#include <GL/glu.h>
#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtc/matrix_transform.hpp>

#include "NativeBitmap.h"
#include "SoundClip.h"
#include "SoundUtils.h"
#include "SoundListener.h"
#include "SoundEmitter.h"
#include "IFileLoaderDelegate.h"
#include "Vec2i.h"
#include "NativeBitmap.h"
#include "IMapElement.h"
#include "CTeam.h"
#include "CItem.h"
#include "CActor.h"
#include "CGameDelegate.h"
#include "CMap.h"
#include "IRenderer.h"
#include "CPlainFileLoader.h"
#include "NoudarDungeonSnapshot.h"
#include "GameNativeAPI.h"
#include "WindowOperations.h"
#include "Common.h"
#include "LoadPNG.h"
#include "DOSHacks.h"

const int bufferWidth = 64;
const int bufferHeight = 64;
const int screenWidth = 320;
const int screenHeight = 200;
bool done = false;
bool isActive = false;
long ms = 0;
bool automatic = false;
int imageBuffer[bufferWidth * bufferHeight];

std::function< std::string(std::string)> kDosLongFileNameTransformer = [](const std::string& filename ) {
  char c = 219;
  c = 176;
  c = 177;
  c = 178;
  c = '.';
  std::cout << c;
  std::cout.flush();

  auto dotPosition = std::find( std::begin(filename), std::end( filename), '.');
  auto indexDot =  std::distance( std::begin( filename ), dotPosition );
  auto extension = filename.substr( indexDot + 1, 3 );

  if ( indexDot >  8 ) {
    return filename.substr( 0, 6 ) + "~1." + extension;
  }

  if ( filename.length() - indexDot > 4 ) {
    return filename.substr( 0, indexDot ) + "~1." + extension;
  }

  return filename;
};

char readKbd() {
  unsigned char controlKbd;

  char lastKey = inportb(0x60);

  controlKbd = inportb(0x61);
  outportb( 0x61, controlKbd | 0x80 );
  outportb( 0x61, controlKbd );
  outportb( 0x20, inportb(0x20) );

  return lastKey;
}

void initMode13h() {
  __dpmi_regs reg;

  reg.x.ax = 0x13;
  __dpmi_int(0x10, &reg);

  outp(0x03c8, 0);

  for ( int r = 0; r < 4; ++r ) {
    for ( int g = 0; g < 4; ++g ) {
      for ( int b = 0; b < 4; ++b ) {
	outp(0x03c9, (r * (85) ) );
	outp(0x03c9, (g * (85) ) );
	outp(0x03c9, (b * (85) ) );
      }
    }
  }
}

unsigned char getPaletteEntry( int origin ) {
  return ((((((origin & 0x0000FF)      ) << 2 ) >> 8 ) ) << 4 )
    + ((((((origin & 0x00FF00) >> 8 ) << 2 ) >> 8 ) ) << 2 )
    + ((((((origin & 0xFF0000) >> 16) << 2 ) >> 8 ) ) << 0);
}

void renderPalette() {
  _farsetsel(_dos_ds);

  for (int r = 0; r < 255; ++r) {
    for (int x = 0; x < 50; ++x) {

      int origin = r << 16;
      int shade = getPaletteEntry( origin );

      _farnspokeb(0xA0000 + (320 * x) + r, shade);
    }
  }

  for (int g = 0; g < 255; ++g) {
    for (int x = 50; x < 100; ++x) {
      int origin = g << 8;
      int shade = getPaletteEntry( origin );
      _farnspokeb(0xA0000 + (320 * x) + g, shade);
    }
  }

  for (int b = 0; b < 255; ++b) {
    for (int x = 100; x < 150; ++x) {
      int origin = b;
      int shade = getPaletteEntry( origin );
      _farnspokeb(0xA0000 + (320 * x) + b, shade);
    }
  }

  for (int b = 0; b < 255; ++b) {
    for (int x = 150; x < 200; ++x) {
      _farnspokeb(0xA0000 + (320 * x) + b, b);
    }
  }

  std::fill(std::end(imageBuffer) - (320 * 200), std::end(imageBuffer), 0x0);
}

void copyImageBufferToVideoMemory() {

  int offset = 0;

  unsigned char buffer[ screenWidth * screenHeight ];
  unsigned char bg =  getPaletteEntry( 0xAA );
  memset( buffer, bg, screenWidth * screenHeight *sizeof(unsigned char));

  int origin = 0;
  int lastOrigin = -1;
  unsigned char shade = 0;

  for (int y = 0; y < (bufferHeight * 2 ); ++y) {
    for (int x = 0; x < (bufferWidth * 2); ++x) {

      offset = ((y/2) * (bufferWidth)) + (x/2);
      origin = imageBuffer[offset];

      if ( origin != lastOrigin ) {
	shade = getPaletteEntry( origin );
      }

      lastOrigin = origin;

      buffer[ ( y * screenWidth ) + (x + ( ( screenWidth - (2 * bufferWidth) ) / 2) ) ] = shade;
    }
  }

  dosmemput(buffer, screenWidth * screenHeight, 0xa0000);

  gotoxy(1, 18 );
  printf( "%s\n%d\n%ld", getCurrentObjectName().c_str(), getHP(), ms );

}

void exitToTextMode() {
  textmode(C80);
}

void initWindow() {
  OSMesaContext om = OSMesaCreateContext(OSMESA_RGBA, nullptr );
  OSMesaMakeCurrent(om, imageBuffer, GL_UNSIGNED_BYTE, bufferWidth, bufferHeight );
  OSMesaPixelStore( OSMESA_ROW_LENGTH, bufferWidth );
  OSMesaPixelStore( OSMESA_Y_UP, 0 );

  auto gVertexShader = "";
  auto gFragmentShader = "";
  auto fileLoader = std::make_shared<Knights::CPlainFileLoader>("res/");

  fileLoader->setFilenameTransformation(  kDosLongFileNameTransformer );
  setupGraphics(bufferWidth, bufferHeight, gVertexShader, gFragmentShader, fileLoader );

  auto soundListener = std::make_shared<odb::SoundListener>();

  std::vector<std::shared_ptr<odb::SoundEmitter>> sounds;

  setSoundEmitters(sounds, soundListener);
  initMode13h();
}

void tick() {
  ++ms;
  gameLoopTick(250);
  renderFrame(250);
  copyImageBufferToVideoMemory();
}

char read_char(void)
{
  union REGS regs;
  regs.x.ax = 0x0100; //DOS function 01h
  int86(0x21,&regs,&regs);

  return regs.x.ax;
}

void setMainLoop() {

  while (!done) {
    while (kbhit()) {
      switch (getch()) {
      case 27:
	done = true;
	break;
      case 'H':
      case 'w':
	moveUp();
	break;
      case 'P':
      case 's':
	moveDown();
	break;
      case 'd':
	moveRight();
	break;
      case 'a':
	moveLeft();
	break;
      case 'c':
	interact();
	break;
      case 'M':
      case 'e':
	rotateCameraRight();
	break;
      case 'K':
      case 'q':
	rotateCameraLeft();
	break;
      case 'z':
	cycleNextItem();
	break;
      case 'x':
	cyclePrevItem();
	break;

      case 'r':
	pickupItem();
	break;
      case 'f':
	dropItem();
	break;
      }
    }
    tick();
  }
}

void destroyWindow() {
  shutdown();
  exitToTextMode();
  clrscr();
  std::cout << "Thank you for playing!" << std::endl;
}
<|endoftext|>


<commit_before>// Copyright (c) 2017-2018 Intel Corporation
//
// 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.

#include <stdio.h>
#include "umc_defs.h"
#if defined (MFX_ENABLE_MPEG2_VIDEO_DECODE)

#include "umc_mpeg2_dec_hw.h"

#include "vaapi_ext_interface.h"

#ifdef _MSVC_LANG
#pragma warning(disable: 4244)
#endif

using namespace UMC;

///////////////////////////////////////////////////////////////////////////
// PackVA class

bool PackVA::SetVideoAccelerator(VideoAccelerator * va)
{
    m_va = va;
    if (!m_va)
    {
        va_mode = UNKNOWN;
        return true;
    }
    if ((m_va->m_Profile & VA_CODEC) != VA_MPEG2)
    {
        return false;
    }
    va_mode = m_va->m_Profile;
    IsProtectedBS = false;

    return true;
}

PackVA::~PackVA(void)
{
    if(pSliceInfoBuffer)
    {
        free(pSliceInfoBuffer);
        pSliceInfoBuffer = NULL;
    }
}

Status PackVA::InitBuffers(int size_bs, int size_sl)
{
    UMCVACompBuffer* CompBuf;
    if(va_mode != VA_VLD_L)
        return UMC_ERR_UNSUPPORTED;

    try
    {
        if (NULL == (vpPictureParam = (VAPictureParameterBufferMPEG2*)m_va->GetCompBuffer(VAPictureParameterBufferType, &CompBuf, sizeof (VAPictureParameterBufferMPEG2))))
            return UMC_ERR_ALLOC;

        if (va_mode == VA_VLD_L)
        {
            if (NULL == (pQmatrixData = (VAIQMatrixBufferMPEG2*)m_va->GetCompBuffer(VAIQMatrixBufferType, &CompBuf, sizeof (VAIQMatrixBufferMPEG2))))
                return UMC_ERR_ALLOC;

            int32_t prev_slice_size_getting = slice_size_getting;
            slice_size_getting = sizeof (VASliceParameterBufferMPEG2) * size_sl;

            if(NULL == pSliceInfoBuffer)
                pSliceInfoBuffer = (VASliceParameterBufferMPEG2*)malloc(slice_size_getting);
            else if (prev_slice_size_getting < slice_size_getting)
            {
                free(pSliceInfoBuffer);
                pSliceInfoBuffer = (VASliceParameterBufferMPEG2*)malloc(slice_size_getting);
            }

            if( NULL == pSliceInfoBuffer)
                return UMC_ERR_ALLOC;

            memset(pSliceInfoBuffer, 0, slice_size_getting);

            if (NULL == (pBitsreamData = (uint8_t*)m_va->GetCompBuffer(VASliceDataBufferType, &CompBuf, size_bs)))
                return UMC_ERR_ALLOC;

            CompBuf->SetPVPState(NULL, 0);

            bs_size_getting = CompBuf->GetBufferSize();
            pSliceInfo = pSliceInfoBuffer;

        }
    }
    catch(...)
    {
        return UMC_ERR_NOT_ENOUGH_BUFFER;
    }
    return UMC_OK;
}

Status
PackVA::SaveVLDParameters(
    sSequenceHeader*    sequenceHeader,
    sPictureHeader*     PictureHeader,
    uint8_t*              bs_start_ptr,
    sFrameBuffer*       frame_buffer,
    int32_t              task_num,
    int32_t              source_mb_height)
{
    (void)source_mb_height;

    int i;
    int NumOfItem;

    if(va_mode == VA_NO)
    {
        return UMC_OK;
    }

    int32_t numSlices = (int32_t)(pSliceInfo - pSliceInfoBuffer);
    for (int i = 1; i < numSlices; i++)
    {
        VASliceParameterBufferMPEG2 & slice = pSliceInfoBuffer[i];
        VASliceParameterBufferMPEG2 & prevSlice = pSliceInfoBuffer[i - 1];
        if (slice.slice_vertical_position == prevSlice.slice_vertical_position && slice.slice_horizontal_position == prevSlice.slice_horizontal_position)
        {
            // remove slice duplication
            memmove_s(&pSliceInfoBuffer[i - 1], (pSliceInfo - &pSliceInfoBuffer[i]) * sizeof(VASliceParameterBufferMPEG2),
                &pSliceInfoBuffer[i], (pSliceInfo - &pSliceInfoBuffer[i]) * sizeof(VASliceParameterBufferMPEG2));
            numSlices--;
            pSliceInfo--;
            i--;
        }
    }

    if(va_mode == VA_VLD_L)
    {
        int32_t size = 0;
        if(pSliceInfoBuffer < pSliceInfo)
            size = pSliceInfo[-1].slice_data_offset + pSliceInfo[-1].slice_data_size;
        MFX_INTERNAL_CPY((uint8_t*)pBitsreamData, bs_start_ptr, size);

        UMCVACompBuffer* CompBuf;
        m_va->GetCompBuffer(VASliceDataBufferType, &CompBuf);
        int32_t buffer_size = CompBuf->GetBufferSize();
        if(buffer_size > size)
            memset(pBitsreamData + size, 0, buffer_size - size);

        pQmatrixData->load_intra_quantiser_matrix = QmatrixData.load_intra_quantiser_matrix;
        pQmatrixData->load_non_intra_quantiser_matrix = QmatrixData.load_non_intra_quantiser_matrix;
        pQmatrixData->load_chroma_intra_quantiser_matrix = QmatrixData.load_chroma_intra_quantiser_matrix;
        pQmatrixData->load_chroma_non_intra_quantiser_matrix = QmatrixData.load_chroma_non_intra_quantiser_matrix;

        MFX_INTERNAL_CPY((uint8_t*)pQmatrixData->intra_quantiser_matrix, (uint8_t*)QmatrixData.intra_quantiser_matrix,
            sizeof(pQmatrixData->intra_quantiser_matrix));
        MFX_INTERNAL_CPY((uint8_t*)pQmatrixData->non_intra_quantiser_matrix, (uint8_t*)QmatrixData.non_intra_quantiser_matrix,
            sizeof(pQmatrixData->non_intra_quantiser_matrix));
        MFX_INTERNAL_CPY((uint8_t*)pQmatrixData->chroma_intra_quantiser_matrix, (uint8_t*)QmatrixData.chroma_intra_quantiser_matrix,
            sizeof(pQmatrixData->chroma_intra_quantiser_matrix));
        MFX_INTERNAL_CPY((uint8_t*)pQmatrixData->chroma_non_intra_quantiser_matrix, (uint8_t*)QmatrixData.chroma_non_intra_quantiser_matrix,
            sizeof(pQmatrixData->chroma_non_intra_quantiser_matrix));

        NumOfItem = (int)(pSliceInfo - pSliceInfoBuffer);

        VASliceParameterBufferMPEG2 *l_pSliceInfoBuffer = (VASliceParameterBufferMPEG2*)m_va->GetCompBuffer(
            VASliceParameterBufferType,
            &CompBuf,
            (int32_t) (sizeof (VASliceParameterBufferMPEG2))*NumOfItem);

        MFX_INTERNAL_CPY((uint8_t*)l_pSliceInfoBuffer, (uint8_t*)pSliceInfoBuffer,
            sizeof(VASliceParameterBufferMPEG2) * NumOfItem);

        m_va->GetCompBuffer(VASliceParameterBufferType,&CompBuf);
        CompBuf->SetNumOfItem(NumOfItem);
    }

    if (vpPictureParam)
    {
        int32_t pict_type = PictureHeader->picture_coding_type;
        VAPictureParameterBufferMPEG2 *pPictureParam = vpPictureParam;

        pPictureParam->horizontal_size = sequenceHeader->mb_width[task_num] * 16;
        pPictureParam->vertical_size = sequenceHeader->mb_height[task_num] * 16;

        //pPictureParam->forward_reference_picture = m_va->GetSurfaceID(prev_index);//prev_index;
        //pPictureParam->backward_reference_picture = m_va->GetSurfaceID(next_index);//next_index;
        int32_t f_ref_pic = VA_INVALID_SURFACE;

        if(pict_type == MPEG2_P_PICTURE)
        {
            if(m_va->GetSurfaceID(frame_buffer->frame_p_c_n[frame_buffer->frame_p_c_n[frame_buffer->curr_index[task_num]].prev_index].va_index) < 0)
            {
                f_ref_pic = m_va->GetSurfaceID(frame_buffer->frame_p_c_n[frame_buffer->curr_index[task_num]].va_index);
            }
            else
            {
                f_ref_pic = m_va->GetSurfaceID(frame_buffer->frame_p_c_n[frame_buffer->frame_p_c_n[frame_buffer->curr_index[task_num]].prev_index].va_index);
            }
        }
        else if(pict_type == MPEG2_B_PICTURE)
        {
            f_ref_pic = m_va->GetSurfaceID(frame_buffer->frame_p_c_n[frame_buffer->frame_p_c_n[frame_buffer->curr_index[task_num]].prev_index].va_index);
        }

        pPictureParam->forward_reference_picture = (pict_type == MPEG2_I_PICTURE)
            ? VA_INVALID_SURFACE
            : f_ref_pic;
        pPictureParam->backward_reference_picture = (pict_type == MPEG2_B_PICTURE)
            ? m_va->GetSurfaceID(frame_buffer->frame_p_c_n[frame_buffer->frame_p_c_n[frame_buffer->curr_index[task_num]].next_index].va_index)
            : VA_INVALID_SURFACE;

        // NOTE
        // It may occur that after Reset() B-frame is needed only in 1 reference frame for successful decoding,
        // however, we need to provide 2 surfaces.
        if (VA_INVALID_SURFACE == pPictureParam->forward_reference_picture)
            pPictureParam->forward_reference_picture = pPictureParam->backward_reference_picture;

        pPictureParam->picture_coding_type = PictureHeader->picture_coding_type;
        for(i=0, pPictureParam->f_code=0; i<4; i++)
        {
            pPictureParam->f_code |= (PictureHeader->f_code[i] << (12 - 4*i));
        }

        pPictureParam->picture_coding_extension.value = 0;
        pPictureParam->picture_coding_extension.bits.intra_dc_precision = PictureHeader->intra_dc_precision;
        pPictureParam->picture_coding_extension.bits.picture_structure = PictureHeader->picture_structure;
        pPictureParam->picture_coding_extension.bits.top_field_first = PictureHeader->top_field_first;
        pPictureParam->picture_coding_extension.bits.frame_pred_frame_dct = PictureHeader->frame_pred_frame_dct;
        pPictureParam->picture_coding_extension.bits.concealment_motion_vectors = PictureHeader->concealment_motion_vectors;
        pPictureParam->picture_coding_extension.bits.q_scale_type = PictureHeader->q_scale_type;
        pPictureParam->picture_coding_extension.bits.intra_vlc_format = PictureHeader->intra_vlc_format;
        pPictureParam->picture_coding_extension.bits.alternate_scan = PictureHeader->alternate_scan;
        pPictureParam->picture_coding_extension.bits.repeat_first_field = PictureHeader->repeat_first_field;
        pPictureParam->picture_coding_extension.bits.progressive_frame = PictureHeader->progressive_frame;
        pPictureParam->picture_coding_extension.bits.is_first_field = !((PictureHeader->picture_structure != FRAME_PICTURE)
                                            && (field_buffer_index == 1));
    }

    return UMC_OK;
}

Status
PackVA::SetBufferSize(
    int32_t          numMB,
    int             size_bs,
    int             size_sl)
{
    (void)size_bs;

        try
        {
            UMCVACompBuffer*  CompBuf  = NULL;

            m_va->GetCompBuffer(
                VAPictureParameterBufferType,
                &CompBuf,
                (int32_t)sizeof (VAPictureParameterBufferMPEG2));
            CompBuf->SetDataSize((int32_t) (sizeof (VAPictureParameterBufferMPEG2)));
            CompBuf->FirstMb = 0;
            CompBuf->NumOfMB = 0;

            if (va_mode == VA_VLD_W)
            {
                m_va->GetCompBuffer(
                    VAIQMatrixBufferType,
                    &CompBuf,
                    (int32_t)sizeof(VAIQMatrixBufferMPEG2));
                CompBuf->SetDataSize((int32_t)sizeof(VAIQMatrixBufferMPEG2));
                CompBuf->FirstMb = 0;
                CompBuf->NumOfMB = 0;

                m_va->GetCompBuffer(
                    VASliceParameterBufferType,
                    &CompBuf,
                    (int32_t)sizeof(VASliceParameterBufferMPEG2)*size_sl);
                CompBuf->SetDataSize((int32_t) ((uint8_t*)pSliceInfo - (uint8_t*)pSliceInfoBuffer));
                CompBuf->FirstMb = 0;
                CompBuf->NumOfMB = numMB;

                m_va->GetCompBuffer(
                    VASliceDataBufferType,
                    &CompBuf,
                    bs_size);
                CompBuf->SetDataSize(bs_size);
                CompBuf->FirstMb = 0;
                CompBuf->NumOfMB = numMB;
            }
        }
        catch (...)
        {
            return UMC_ERR_NOT_ENOUGH_BUFFER;
        }

    return UMC_OK;
}

#endif // MFX_ENABLE_MPEG2_VIDEO_DECODE
<commit_msg>mpeg2d: use std::copy instead of memmove<commit_after>// Copyright (c) 2017-2018 Intel Corporation
//
// 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.

#include <stdio.h>
#include "umc_defs.h"
#if defined (MFX_ENABLE_MPEG2_VIDEO_DECODE)

#include "umc_mpeg2_dec_hw.h"

#include "vaapi_ext_interface.h"

#ifdef _MSVC_LANG
#pragma warning(disable: 4244)
#endif

using namespace UMC;

///////////////////////////////////////////////////////////////////////////
// PackVA class

bool PackVA::SetVideoAccelerator(VideoAccelerator * va)
{
    m_va = va;
    if (!m_va)
    {
        va_mode = UNKNOWN;
        return true;
    }
    if ((m_va->m_Profile & VA_CODEC) != VA_MPEG2)
    {
        return false;
    }
    va_mode = m_va->m_Profile;
    IsProtectedBS = false;

    return true;
}

PackVA::~PackVA(void)
{
    if(pSliceInfoBuffer)
    {
        free(pSliceInfoBuffer);
        pSliceInfoBuffer = NULL;
    }
}

Status PackVA::InitBuffers(int size_bs, int size_sl)
{
    UMCVACompBuffer* CompBuf;
    if(va_mode != VA_VLD_L)
        return UMC_ERR_UNSUPPORTED;

    try
    {
        if (NULL == (vpPictureParam = (VAPictureParameterBufferMPEG2*)m_va->GetCompBuffer(VAPictureParameterBufferType, &CompBuf, sizeof (VAPictureParameterBufferMPEG2))))
            return UMC_ERR_ALLOC;

        if (va_mode == VA_VLD_L)
        {
            if (NULL == (pQmatrixData = (VAIQMatrixBufferMPEG2*)m_va->GetCompBuffer(VAIQMatrixBufferType, &CompBuf, sizeof (VAIQMatrixBufferMPEG2))))
                return UMC_ERR_ALLOC;

            int32_t prev_slice_size_getting = slice_size_getting;
            slice_size_getting = sizeof (VASliceParameterBufferMPEG2) * size_sl;

            if(NULL == pSliceInfoBuffer)
                pSliceInfoBuffer = (VASliceParameterBufferMPEG2*)malloc(slice_size_getting);
            else if (prev_slice_size_getting < slice_size_getting)
            {
                free(pSliceInfoBuffer);
                pSliceInfoBuffer = (VASliceParameterBufferMPEG2*)malloc(slice_size_getting);
            }

            if( NULL == pSliceInfoBuffer)
                return UMC_ERR_ALLOC;

            memset(pSliceInfoBuffer, 0, slice_size_getting);

            if (NULL == (pBitsreamData = (uint8_t*)m_va->GetCompBuffer(VASliceDataBufferType, &CompBuf, size_bs)))
                return UMC_ERR_ALLOC;

            CompBuf->SetPVPState(NULL, 0);

            bs_size_getting = CompBuf->GetBufferSize();
            pSliceInfo = pSliceInfoBuffer;

        }
    }
    catch(...)
    {
        return UMC_ERR_NOT_ENOUGH_BUFFER;
    }
    return UMC_OK;
}

Status
PackVA::SaveVLDParameters(
    sSequenceHeader*    sequenceHeader,
    sPictureHeader*     PictureHeader,
    uint8_t*              bs_start_ptr,
    sFrameBuffer*       frame_buffer,
    int32_t              task_num,
    int32_t              source_mb_height)
{
    (void)source_mb_height;

    int i;
    int NumOfItem;

    if(va_mode == VA_NO)
    {
        return UMC_OK;
    }

    int32_t numSlices = (int32_t)(pSliceInfo - pSliceInfoBuffer);
    for (int i = 1; i < numSlices; i++)
    {
        VASliceParameterBufferMPEG2 & slice = pSliceInfoBuffer[i];
        VASliceParameterBufferMPEG2 & prevSlice = pSliceInfoBuffer[i - 1];
        if (slice.slice_vertical_position == prevSlice.slice_vertical_position && slice.slice_horizontal_position == prevSlice.slice_horizontal_position)
        {
            // remove slice duplication
            std::copy(&pSliceInfoBuffer[i], pSliceInfo, &pSliceInfoBuffer[i-1]);
            numSlices--;
            pSliceInfo--;
            i--;
        }
    }

    if(va_mode == VA_VLD_L)
    {
        int32_t size = 0;
        if(pSliceInfoBuffer < pSliceInfo)
            size = pSliceInfo[-1].slice_data_offset + pSliceInfo[-1].slice_data_size;
        MFX_INTERNAL_CPY((uint8_t*)pBitsreamData, bs_start_ptr, size);

        UMCVACompBuffer* CompBuf;
        m_va->GetCompBuffer(VASliceDataBufferType, &CompBuf);
        int32_t buffer_size = CompBuf->GetBufferSize();
        if(buffer_size > size)
            memset(pBitsreamData + size, 0, buffer_size - size);

        pQmatrixData->load_intra_quantiser_matrix = QmatrixData.load_intra_quantiser_matrix;
        pQmatrixData->load_non_intra_quantiser_matrix = QmatrixData.load_non_intra_quantiser_matrix;
        pQmatrixData->load_chroma_intra_quantiser_matrix = QmatrixData.load_chroma_intra_quantiser_matrix;
        pQmatrixData->load_chroma_non_intra_quantiser_matrix = QmatrixData.load_chroma_non_intra_quantiser_matrix;

        MFX_INTERNAL_CPY((uint8_t*)pQmatrixData->intra_quantiser_matrix, (uint8_t*)QmatrixData.intra_quantiser_matrix,
            sizeof(pQmatrixData->intra_quantiser_matrix));
        MFX_INTERNAL_CPY((uint8_t*)pQmatrixData->non_intra_quantiser_matrix, (uint8_t*)QmatrixData.non_intra_quantiser_matrix,
            sizeof(pQmatrixData->non_intra_quantiser_matrix));
        MFX_INTERNAL_CPY((uint8_t*)pQmatrixData->chroma_intra_quantiser_matrix, (uint8_t*)QmatrixData.chroma_intra_quantiser_matrix,
            sizeof(pQmatrixData->chroma_intra_quantiser_matrix));
        MFX_INTERNAL_CPY((uint8_t*)pQmatrixData->chroma_non_intra_quantiser_matrix, (uint8_t*)QmatrixData.chroma_non_intra_quantiser_matrix,
            sizeof(pQmatrixData->chroma_non_intra_quantiser_matrix));

        NumOfItem = (int)(pSliceInfo - pSliceInfoBuffer);

        VASliceParameterBufferMPEG2 *l_pSliceInfoBuffer = (VASliceParameterBufferMPEG2*)m_va->GetCompBuffer(
            VASliceParameterBufferType,
            &CompBuf,
            (int32_t) (sizeof (VASliceParameterBufferMPEG2))*NumOfItem);

        MFX_INTERNAL_CPY((uint8_t*)l_pSliceInfoBuffer, (uint8_t*)pSliceInfoBuffer,
            sizeof(VASliceParameterBufferMPEG2) * NumOfItem);

        m_va->GetCompBuffer(VASliceParameterBufferType,&CompBuf);
        CompBuf->SetNumOfItem(NumOfItem);
    }

    if (vpPictureParam)
    {
        int32_t pict_type = PictureHeader->picture_coding_type;
        VAPictureParameterBufferMPEG2 *pPictureParam = vpPictureParam;

        pPictureParam->horizontal_size = sequenceHeader->mb_width[task_num] * 16;
        pPictureParam->vertical_size = sequenceHeader->mb_height[task_num] * 16;

        //pPictureParam->forward_reference_picture = m_va->GetSurfaceID(prev_index);//prev_index;
        //pPictureParam->backward_reference_picture = m_va->GetSurfaceID(next_index);//next_index;
        int32_t f_ref_pic = VA_INVALID_SURFACE;

        if(pict_type == MPEG2_P_PICTURE)
        {
            if(m_va->GetSurfaceID(frame_buffer->frame_p_c_n[frame_buffer->frame_p_c_n[frame_buffer->curr_index[task_num]].prev_index].va_index) < 0)
            {
                f_ref_pic = m_va->GetSurfaceID(frame_buffer->frame_p_c_n[frame_buffer->curr_index[task_num]].va_index);
            }
            else
            {
                f_ref_pic = m_va->GetSurfaceID(frame_buffer->frame_p_c_n[frame_buffer->frame_p_c_n[frame_buffer->curr_index[task_num]].prev_index].va_index);
            }
        }
        else if(pict_type == MPEG2_B_PICTURE)
        {
            f_ref_pic = m_va->GetSurfaceID(frame_buffer->frame_p_c_n[frame_buffer->frame_p_c_n[frame_buffer->curr_index[task_num]].prev_index].va_index);
        }

        pPictureParam->forward_reference_picture = (pict_type == MPEG2_I_PICTURE)
            ? VA_INVALID_SURFACE
            : f_ref_pic;
        pPictureParam->backward_reference_picture = (pict_type == MPEG2_B_PICTURE)
            ? m_va->GetSurfaceID(frame_buffer->frame_p_c_n[frame_buffer->frame_p_c_n[frame_buffer->curr_index[task_num]].next_index].va_index)
            : VA_INVALID_SURFACE;

        // NOTE
        // It may occur that after Reset() B-frame is needed only in 1 reference frame for successful decoding,
        // however, we need to provide 2 surfaces.
        if (VA_INVALID_SURFACE == pPictureParam->forward_reference_picture)
            pPictureParam->forward_reference_picture = pPictureParam->backward_reference_picture;

        pPictureParam->picture_coding_type = PictureHeader->picture_coding_type;
        for(i=0, pPictureParam->f_code=0; i<4; i++)
        {
            pPictureParam->f_code |= (PictureHeader->f_code[i] << (12 - 4*i));
        }

        pPictureParam->picture_coding_extension.value = 0;
        pPictureParam->picture_coding_extension.bits.intra_dc_precision = PictureHeader->intra_dc_precision;
        pPictureParam->picture_coding_extension.bits.picture_structure = PictureHeader->picture_structure;
        pPictureParam->picture_coding_extension.bits.top_field_first = PictureHeader->top_field_first;
        pPictureParam->picture_coding_extension.bits.frame_pred_frame_dct = PictureHeader->frame_pred_frame_dct;
        pPictureParam->picture_coding_extension.bits.concealment_motion_vectors = PictureHeader->concealment_motion_vectors;
        pPictureParam->picture_coding_extension.bits.q_scale_type = PictureHeader->q_scale_type;
        pPictureParam->picture_coding_extension.bits.intra_vlc_format = PictureHeader->intra_vlc_format;
        pPictureParam->picture_coding_extension.bits.alternate_scan = PictureHeader->alternate_scan;
        pPictureParam->picture_coding_extension.bits.repeat_first_field = PictureHeader->repeat_first_field;
        pPictureParam->picture_coding_extension.bits.progressive_frame = PictureHeader->progressive_frame;
        pPictureParam->picture_coding_extension.bits.is_first_field = !((PictureHeader->picture_structure != FRAME_PICTURE)
                                            && (field_buffer_index == 1));
    }

    return UMC_OK;
}

Status
PackVA::SetBufferSize(
    int32_t          numMB,
    int             size_bs,
    int             size_sl)
{
    (void)size_bs;

        try
        {
            UMCVACompBuffer*  CompBuf  = NULL;

            m_va->GetCompBuffer(
                VAPictureParameterBufferType,
                &CompBuf,
                (int32_t)sizeof (VAPictureParameterBufferMPEG2));
            CompBuf->SetDataSize((int32_t) (sizeof (VAPictureParameterBufferMPEG2)));
            CompBuf->FirstMb = 0;
            CompBuf->NumOfMB = 0;

            if (va_mode == VA_VLD_W)
            {
                m_va->GetCompBuffer(
                    VAIQMatrixBufferType,
                    &CompBuf,
                    (int32_t)sizeof(VAIQMatrixBufferMPEG2));
                CompBuf->SetDataSize((int32_t)sizeof(VAIQMatrixBufferMPEG2));
                CompBuf->FirstMb = 0;
                CompBuf->NumOfMB = 0;

                m_va->GetCompBuffer(
                    VASliceParameterBufferType,
                    &CompBuf,
                    (int32_t)sizeof(VASliceParameterBufferMPEG2)*size_sl);
                CompBuf->SetDataSize((int32_t) ((uint8_t*)pSliceInfo - (uint8_t*)pSliceInfoBuffer));
                CompBuf->FirstMb = 0;
                CompBuf->NumOfMB = numMB;

                m_va->GetCompBuffer(
                    VASliceDataBufferType,
                    &CompBuf,
                    bs_size);
                CompBuf->SetDataSize(bs_size);
                CompBuf->FirstMb = 0;
                CompBuf->NumOfMB = numMB;
            }
        }
        catch (...)
        {
            return UMC_ERR_NOT_ENOUGH_BUFFER;
        }

    return UMC_OK;
}

#endif // MFX_ENABLE_MPEG2_VIDEO_DECODE
<|endoftext|>


<commit_before>#include "sensorVariablesUpdater.h"

#include <utils/tracer.h>
#include <interpreterBase/robotModel/robotParts/scalarSensor.h>

static int const variableUpdateIntervalMs = 200;

using namespace interpreterCore::interpreter::details;
using namespace interpreterBase::robotModel;

SensorVariablesUpdater::SensorVariablesUpdater(
		RobotModelManagerInterface const &robotModelManager
		, utils::ExpressionsParser &parser
		)
	: mRobotModelManager(robotModelManager)
	, mParser(parser)
{
	mUpdateTimer.setInterval(variableUpdateIntervalMs);
	connect(&mUpdateTimer, &QTimer::timeout, this, &SensorVariablesUpdater::onTimerTimeout);
}

void SensorVariablesUpdater::run()
{
	resetVariables();

	for (robotParts::Device * const device : mRobotModelManager.model().configuration().devices()) {
		/// @todo: Works only with scalar sensors
		robotParts::ScalarSensor * const scalarSensor = dynamic_cast<robotParts::ScalarSensor *>(device);
		if (scalarSensor && !scalarSensor->port().reservedVariable().isEmpty()) {

			if (!scalarSensor->ready()) {
				/// @todo Error reporting
				continue;
			}

			connect(
					scalarSensor
					, &robotParts::ScalarSensor::newData
					, this
					, &SensorVariablesUpdater::onScalarSensorResponse
					, Qt::UniqueConnection
					);

			connect(
					scalarSensor
					, &robotParts::AbstractSensor::failure
					, this
					, &SensorVariablesUpdater::onFailure
					, Qt::UniqueConnection
					);

			scalarSensor->read();
		}
	}

	mUpdateTimer.start();
}

void SensorVariablesUpdater::suspend()
{
	mUpdateTimer.stop();
}

void SensorVariablesUpdater::onScalarSensorResponse(int reading)
{
	robotParts::ScalarSensor * const scalarSensor = dynamic_cast<robotParts::ScalarSensor *>(sender());
	if (!scalarSensor) {
		/// @todo Error reporting.
		return;
	}

	updateScalarSensorVariables(scalarSensor->port(), reading);
}

void SensorVariablesUpdater::onTimerTimeout()
{
	for (robotParts::Device * const device : mRobotModelManager.model().configuration().devices()) {
		robotParts::ScalarSensor * const scalarSensor = dynamic_cast<robotParts::ScalarSensor *>(device);
		if (scalarSensor && !scalarSensor->port().reservedVariable().isEmpty()) {

			if (!scalarSensor->ready()) {
				/// @todo Error reporting
				continue;
			}

			scalarSensor->read();
		}
	}
}

void SensorVariablesUpdater::onFailure()
{
	utils::Tracer::debug(utils::Tracer::autoupdatedSensorValues, "Interpreter::slotFailure", "");
}

void SensorVariablesUpdater::updateScalarSensorVariables(PortInfo const &sensorPortInfo, int reading)
{
	updateScalarSensorVariable(sensorPortInfo.reservedVariable(), reading);
}

void SensorVariablesUpdater::updateScalarSensorVariable(QString const &variable, int reading)
{
	mParser.mutableVariables()[variable] = new utils::Number(reading, utils::Number::intType);
	utils::Tracer::debug(
			utils::Tracer::autoupdatedSensorValues
			, "SensorVariablesUpdater::updateScalarSensorVariable"
			, variable + QString::number(reading)
			);
}

void SensorVariablesUpdater::resetVariables()
{
	for (robotParts::Device * const device : mRobotModelManager.model().configuration().devices()) {
		robotParts::ScalarSensor * const scalarSensor = dynamic_cast<robotParts::ScalarSensor *>(device);
		if (scalarSensor) {
			updateScalarSensorVariables(scalarSensor->port(), 0);
		}
	}
}
<commit_msg>Fixed too rare variable updates when interpreting on 2D model<commit_after>#include "sensorVariablesUpdater.h"

#include <utils/tracer.h>
#include <interpreterBase/robotModel/robotParts/scalarSensor.h>

static int const unrealUpdateInterval = 20;
static int const realUpdateInterval = 200;

using namespace interpreterCore::interpreter::details;
using namespace interpreterBase::robotModel;

SensorVariablesUpdater::SensorVariablesUpdater(
		RobotModelManagerInterface const &robotModelManager
		, utils::ExpressionsParser &parser
		)
	: mRobotModelManager(robotModelManager)
	, mParser(parser)
{
	connect(&mUpdateTimer, &QTimer::timeout, this, &SensorVariablesUpdater::onTimerTimeout);
}

void SensorVariablesUpdater::run()
{
	resetVariables();

	for (robotParts::Device * const device : mRobotModelManager.model().configuration().devices()) {
		/// @todo: Works only with scalar sensors
		robotParts::ScalarSensor * const scalarSensor = dynamic_cast<robotParts::ScalarSensor *>(device);
		if (scalarSensor && !scalarSensor->port().reservedVariable().isEmpty()) {

			if (!scalarSensor->ready()) {
				/// @todo Error reporting
				continue;
			}

			connect(
					scalarSensor
					, &robotParts::ScalarSensor::newData
					, this
					, &SensorVariablesUpdater::onScalarSensorResponse
					, Qt::UniqueConnection
					);

			connect(
					scalarSensor
					, &robotParts::AbstractSensor::failure
					, this
					, &SensorVariablesUpdater::onFailure
					, Qt::UniqueConnection
					);

			scalarSensor->read();
		}
	}

	int const variableUpdateInterval = mRobotModelManager.model().needsConnection()
			? realUpdateInterval : unrealUpdateInterval;
	mUpdateTimer.setInterval(variableUpdateInterval);
	mUpdateTimer.start();
}

void SensorVariablesUpdater::suspend()
{
	mUpdateTimer.stop();
}

void SensorVariablesUpdater::onScalarSensorResponse(int reading)
{
	robotParts::ScalarSensor * const scalarSensor = dynamic_cast<robotParts::ScalarSensor *>(sender());
	if (!scalarSensor) {
		/// @todo Error reporting.
		return;
	}

	updateScalarSensorVariables(scalarSensor->port(), reading);
}

void SensorVariablesUpdater::onTimerTimeout()
{
	for (robotParts::Device * const device : mRobotModelManager.model().configuration().devices()) {
		robotParts::ScalarSensor * const scalarSensor = dynamic_cast<robotParts::ScalarSensor *>(device);
		if (scalarSensor && !scalarSensor->port().reservedVariable().isEmpty()) {

			if (!scalarSensor->ready()) {
				/// @todo Error reporting
				continue;
			}

			scalarSensor->read();
		}
	}
}

void SensorVariablesUpdater::onFailure()
{
	utils::Tracer::debug(utils::Tracer::autoupdatedSensorValues, "Interpreter::slotFailure", "");
}

void SensorVariablesUpdater::updateScalarSensorVariables(PortInfo const &sensorPortInfo, int reading)
{
	updateScalarSensorVariable(sensorPortInfo.reservedVariable(), reading);
}

void SensorVariablesUpdater::updateScalarSensorVariable(QString const &variable, int reading)
{
	mParser.mutableVariables()[variable] = new utils::Number(reading, utils::Number::intType);
	utils::Tracer::debug(
			utils::Tracer::autoupdatedSensorValues
			, "SensorVariablesUpdater::updateScalarSensorVariable"
			, variable + QString::number(reading)
			);
}

void SensorVariablesUpdater::resetVariables()
{
	for (robotParts::Device * const device : mRobotModelManager.model().configuration().devices()) {
		robotParts::ScalarSensor * const scalarSensor = dynamic_cast<robotParts::ScalarSensor *>(device);
		if (scalarSensor) {
			updateScalarSensorVariables(scalarSensor->port(), 0);
		}
	}
}
<|endoftext|>


<commit_before>// For conditions of distribution and use, see copyright notice in license.txt

#include "StableHeaders.h"

#include <Poco/Logger.h>
#include <Poco/LoggingFactory.h>
#include <Poco/FormattingChannel.h>
#include <Poco/SplitterChannel.h>
#include <Poco/LocalDateTime.h>
#include "Poco/UnicodeConverter.h"

#include "Foundation.h"
#include "SceneManager.h"
#include "SceneEvents.h"

namespace Foundation
{
    const char *Framework::DEFAULT_EVENT_SUBSCRIBER_TREE_PATH = "./data/event_tree.xml";

    Framework::Framework() : exit_signal_(false)
    {
        ProfilerSection::SetProfiler(&profiler_);

        PROFILE(FW_Startup);
        application_ = ApplicationPtr(new Application(this));
        platform_ = PlatformPtr(new Platform(this));
		// Create config manager
		config_manager_ = ConfigurationManagerPtr(new ConfigurationManager(this));

        config_manager_->DeclareSetting(Framework::ConfigurationGroup(), std::string("version_major"), std::string("0"));
        config_manager_->DeclareSetting(Framework::ConfigurationGroup(), std::string("version_minor"), std::string("1"));
        config_manager_->DeclareSetting(Framework::ConfigurationGroup(), std::string("application_name"), std::string("realXtend"));
        config_manager_->DeclareSetting(Framework::ConfigurationGroup(), std::string("log_console"), bool(true));
        config_manager_->DeclareSetting(Framework::ConfigurationGroup(), std::string("log_level"), std::string("information"));

        platform_->PrepareApplicationDataDirectory(); // depends on config

        CreateLoggingSystem(); // depends on config and platform

        // create managers
        module_manager_ = ModuleManagerPtr(new ModuleManager(this));
        component_manager_ = ComponentManagerPtr(new ComponentManager(this));
        service_manager_ = ServiceManagerPtr(new ServiceManager(this));
        event_manager_ = EventManagerPtr(new EventManager(this));

        Scene::Events::RegisterSceneEvents(event_manager_);
    }

    Framework::~Framework()
    {
        default_scene_.reset();
        scenes_.clear();
        module_manager_.reset();

        Poco::Logger::shutdown();

        for (size_t i=0 ; i<log_channels_.size() ; ++i)
            log_channels_[i]->release();

        log_channels_.clear();
        log_formatter_->release();
    }

    void Framework::CreateLoggingSystem()
    {
        PROFILE(FW_CreateLoggingSystem);
        Poco::LoggingFactory *loggingfactory = new Poco::LoggingFactory();

        Poco::Channel *consolechannel = NULL;
        if (config_manager_->GetSetting<bool>(Framework::ConfigurationGroup(), "log_console"))
            consolechannel = loggingfactory->createChannel("ConsoleChannel");

        Poco::Channel *filechannel = loggingfactory->createChannel("FileChannel");

        std::wstring logfilepath_w = platform_->GetUserDocumentsDirectoryW();
        logfilepath_w += L"/" + Core::ToWString(config_manager_->GetSetting<std::string>(Framework::ConfigurationGroup(), "application_name")) + L".log";
        std::string logfilepath;
        Poco::UnicodeConverter::toUTF8(logfilepath_w, logfilepath);

        filechannel->setProperty("path",logfilepath);
        filechannel->setProperty("rotation","3M");
        filechannel->setProperty("archive","number");
        filechannel->setProperty("compress","false");

        Poco::SplitterChannel *splitterchannel = new Poco::SplitterChannel();
        if (consolechannel)
            splitterchannel->addChannel(consolechannel);
        splitterchannel->addChannel(filechannel);

        log_formatter_ = loggingfactory->createFormatter("PatternFormatter");
        log_formatter_->setProperty("pattern","%H:%M:%S [%s] %t");
        log_formatter_->setProperty("times","local");
        Poco::Channel *formatchannel = new Poco::FormattingChannel(log_formatter_,splitterchannel);

        try
        {
            Poco::Logger::create("",formatchannel,Poco::Message::PRIO_TRACE);
            Poco::Logger::create("Foundation",Poco::Logger::root().getChannel() ,Poco::Message::PRIO_TRACE);
        } catch (Poco::ExistsException)
        {
            assert (false && "Somewhere, a message is pushed to log before the logger is initialized.");
        }

        Poco::LocalDateTime *currenttime = new Poco::LocalDateTime();
        std::string timestring = boost::lexical_cast<std::string>(currenttime->day()) + "/";
        timestring.append(boost::lexical_cast<std::string>(currenttime->month()) + "/");
        timestring.append(boost::lexical_cast<std::string>(currenttime->year()) + " ");
        timestring.append(boost::lexical_cast<std::string>(currenttime->hour()) + ":");
        timestring.append(boost::lexical_cast<std::string>(currenttime->minute()) + ":");
        timestring.append(boost::lexical_cast<std::string>(currenttime->second()));

        try
        {
            Foundation::RootLogInfo("Log file opened on " + timestring);
        } catch(Poco::OpenFileException)
        {
            // Do not create the log file.
            splitterchannel->removeChannel(filechannel);
            Foundation::RootLogInfo("Poco::OpenFileException. Log file not created.");
        }

#ifndef _DEBUG
        // make it so debug messages are not logged in release mode
        std::string log_level = config_manager_->GetSetting<std::string>(Framework::ConfigurationGroup(), "log_level");
        Poco::Logger::get("Foundation").setLevel(log_level);
#endif

        if (consolechannel)
            log_channels_.push_back(consolechannel);
        log_channels_.push_back(filechannel);
        log_channels_.push_back(splitterchannel);
        log_channels_.push_back(formatchannel);

        delete currenttime;
        delete loggingfactory;
    }

    void Framework::PostInitialize()
    {
        PROFILE(FW_PostInitialize);

        LoadModules();

        // commands must be registered after modules are loaded and initialized
        RegisterConsoleCommands();

        // add event subscribers now, that all modules are loaded/initialized
        event_manager_->LoadEventSubscriberTree(DEFAULT_EVENT_SUBSCRIBER_TREE_PATH);
    }

    void Framework::Go()
    {
        PROFILE(FW_Go);
        PostInitialize();

        boost::timer timer;

        boost::weak_ptr<Foundation::RenderServiceInterface> renderer =
                    service_manager_->GetService<RenderServiceInterface>(Service::ST_Renderer);

        // main loop
        while (exit_signal_ == false)
        {
            PROFILE(MainLoop);

            double frametime = timer.elapsed();
            timer.restart();
            // do synchronized update for modules
            {
                PROFILE(FW_UpdateModules);
                module_manager_->UpdateModules(frametime);
            }

            // call asynchronous update on modules / do parallel tasks

            // synchronize shared data across modules
            //mChangeManager->_propagateChanges();

            // process delayed events

            {
               PROFILE(FW_ProcessDelayedEvents);
                event_manager_->ProcessDelayedEvents(frametime);
            }

            // if we have a renderer service, render now

            if (renderer.expired() == false)
            {
                PROFILE(FW_Render);
                renderer.lock()->Render();
            }

            // Reset profiling data
#ifdef PROFILING
            GetProfiler().Reset();
#endif
        }

         UnloadModules();
    }

    void Framework::LoadModules()
    {
        {
            PROFILE(FW_LoadModules);
            module_manager_->LoadAvailableModules();
        }
        {
            PROFILE(FW_InitializeModules);
            module_manager_->InitializeModules();
        }
    }

    void Framework::UnloadModules()
    {
        module_manager_->UninitializeModules();
        scenes_.clear();
        module_manager_->UnloadModules();
    }

    Scene::ScenePtr Framework::CreateScene(const std::string &name)
    {
        if (HasScene(name))
            return Scene::ScenePtr();

        Scene::ScenePtr new_scene = Scene::ScenePtr(new Scene::SceneManager(name, this));
        scenes_[name] = new_scene;

        return new_scene;
    }

    void Framework::RemoveScene(const std::string &name)
    {
        SceneMap::iterator scene = scenes_.find(name);
        if (scene != scenes_.end())
        {
            scenes_.erase(scene);
        }
    }
    Scene::ScenePtr Framework::GetScene(const std::string &name) const
    {
        SceneMap::const_iterator scene = scenes_.find(name);
        if (scene != scenes_.end())
            return scene->second;

        return Scene::ScenePtr();
    }

    Console::CommandResult Framework::ConsoleLoadModule(const Core::StringVector &params)
    {
        if (params.size() != 2 && params.size() != 1)
            return Console::ResultInvalidParameters();

        std::string lib = params[0];
        std::string entry = params[0];
        if (params.size() == 2)
            entry = params[1];

        bool result = module_manager_->LoadModuleByName(lib, entry);
        event_manager_->ValidateEventSubscriberTree();

        if (!result)
            return Console::ResultFailure("Library or module not found.");

        return Console::ResultSuccess("Module " + entry + " loaded.");
    }

    Console::CommandResult Framework::ConsoleUnloadModule(const Core::StringVector &params)
    {
        if (params.size() != 1)
            return Console::ResultInvalidParameters();

        bool result = false;
        if (module_manager_->HasModule(params[0]))
        {
            result = module_manager_->UnloadModuleByName(params[0]);
            event_manager_->ValidateEventSubscriberTree();
        }

        if (!result)
            return Console::ResultFailure("Module not found.");

        return Console::ResultSuccess("Module " + params[0] + " unloaded.");
    }

    Console::CommandResult Framework::ConsoleListModules(const Core::StringVector &params)
    {
        boost::shared_ptr<Console::ConsoleServiceInterface> console = GetService<Console::ConsoleServiceInterface>(Foundation::Service::ST_Console).lock();
        if (console)
        {
            console->Print("Loaded modules:");
            const ModuleManager::ModuleVector &modules = module_manager_->GetModuleList();
            for (size_t i = 0 ; i < modules.size() ; ++i)
            {
                console->Print(modules[i].module_->Name());
            }
        }

        return Console::ResultSuccess();
    }

    Console::CommandResult Framework::ConsoleSendEvent(const Core::StringVector &params)
    {
        if (params.size() != 2)
            return Console::ResultInvalidParameters();

        Core::event_category_id_t event_category = event_manager_->QueryEventCategory(params[0]);
        if (event_category == Core::IllegalEventCategory)
        {
            return Console::ResultFailure("Event category not found.");
        } else
        {
            event_manager_->SendEvent(
                event_category,
                Core::ParseString<Core::event_id_t>(params[1]),
                NULL);

            return Console::ResultSuccess();
        }
    }

    void PrintTimingsToConsole(const Console::ConsolePtr &console, const ProfilerNodeTree *node)
    {
        const ProfilerNode *timings_node = dynamic_cast<const ProfilerNode*>(node);

        static int level = -2;

        if (timings_node)
        {
            level += 2;
            assert (level >= 0);

            std::string timings;
            timings.append(level, ' ');
            timings += timings_node->Name();
            timings += ": called total " + Core::ToString(timings_node->num_called_total_);
            timings += ", elapsed total " + Core::ToString(timings_node->total_);
            timings += ", called " + Core::ToString(timings_node->num_called_);
            timings += ", elapsed " + Core::ToString(timings_node->elapsed_);

            double average = timings_node->num_called_total_ == 0 ? 0.0 : timings_node->total_ / timings_node->num_called_total_;
            timings += ", average " + Core::ToString(average);
            console->Print(timings);
        }

        const ProfilerNodeTree::NodeList &children = node->GetChildren();
        for (ProfilerNodeTree::NodeList::const_iterator it = children.begin() ;
             it != children.end() ;
             ++it)
        {
            PrintTimingsToConsole(console, *it);
        }
        if (timings_node)
        {
            level -= 2;
        }
    }

    Console::CommandResult Framework::ConsoleProfile(const Core::StringVector &params)
    {
        boost::shared_ptr<Console::ConsoleServiceInterface> console = GetService<Console::ConsoleServiceInterface>(Foundation::Service::ST_Console).lock();
        if (console)
        {
            Profiler &profiler = GetProfiler();
            ProfilerNodeTree *node = profiler.Lock().get();
            PrintTimingsToConsole(console, node);
            profiler.Release();
        }
        return Console::ResultSuccess();
    }

    void Framework::RegisterConsoleCommands()
    {
        boost::shared_ptr<Console::CommandService> console = GetService<Console::CommandService>(Foundation::Service::ST_ConsoleCommand).lock();
        if (console)
        {
            console->RegisterCommand(Console::CreateCommand("LoadModule",
                "Loads a module from shared library. Usage: LoadModule(lib, entry)",
                Console::Bind(this, &Framework::ConsoleLoadModule)));

            console->RegisterCommand(Console::CreateCommand("UnloadModule",
                "Unloads a module. Usage: UnloadModule(name)",
                Console::Bind(this, &Framework::ConsoleUnloadModule)));

            console->RegisterCommand(Console::CreateCommand("ListModules",
                "Lists all loaded modules.",
                Console::Bind(this, &Framework::ConsoleListModules)));

            console->RegisterCommand(Console::CreateCommand("SendEvent",
                "Sends an internal event. Only for events that contain no data. Usage: SendEvent(event category name, event id)",
                Console::Bind(this, &Framework::ConsoleSendEvent)));

            console->RegisterCommand(Console::CreateCommand("Profile",
                "Outputs profiling data. Usage: Profile() for full, or Profile(name) for specific profiling block",
                Console::Bind(this, &Framework::ConsoleProfile)));
        }
    }
}

<commit_msg>Fixed issue with 'MainLoop' profiling block not displaying proper timings.<commit_after>// For conditions of distribution and use, see copyright notice in license.txt

#include "StableHeaders.h"

#include <Poco/Logger.h>
#include <Poco/LoggingFactory.h>
#include <Poco/FormattingChannel.h>
#include <Poco/SplitterChannel.h>
#include <Poco/LocalDateTime.h>
#include "Poco/UnicodeConverter.h"

#include "Foundation.h"
#include "SceneManager.h"
#include "SceneEvents.h"

namespace Foundation
{
    const char *Framework::DEFAULT_EVENT_SUBSCRIBER_TREE_PATH = "./data/event_tree.xml";

    Framework::Framework() : exit_signal_(false)
    {
        ProfilerSection::SetProfiler(&profiler_);

        PROFILE(FW_Startup);
        application_ = ApplicationPtr(new Application(this));
        platform_ = PlatformPtr(new Platform(this));
		// Create config manager
		config_manager_ = ConfigurationManagerPtr(new ConfigurationManager(this));

        config_manager_->DeclareSetting(Framework::ConfigurationGroup(), std::string("version_major"), std::string("0"));
        config_manager_->DeclareSetting(Framework::ConfigurationGroup(), std::string("version_minor"), std::string("1"));
        config_manager_->DeclareSetting(Framework::ConfigurationGroup(), std::string("application_name"), std::string("realXtend"));
        config_manager_->DeclareSetting(Framework::ConfigurationGroup(), std::string("log_console"), bool(true));
        config_manager_->DeclareSetting(Framework::ConfigurationGroup(), std::string("log_level"), std::string("information"));

        platform_->PrepareApplicationDataDirectory(); // depends on config

        CreateLoggingSystem(); // depends on config and platform

        // create managers
        module_manager_ = ModuleManagerPtr(new ModuleManager(this));
        component_manager_ = ComponentManagerPtr(new ComponentManager(this));
        service_manager_ = ServiceManagerPtr(new ServiceManager(this));
        event_manager_ = EventManagerPtr(new EventManager(this));

        Scene::Events::RegisterSceneEvents(event_manager_);
    }

    Framework::~Framework()
    {
        default_scene_.reset();
        scenes_.clear();
        module_manager_.reset();

        Poco::Logger::shutdown();

        for (size_t i=0 ; i<log_channels_.size() ; ++i)
            log_channels_[i]->release();

        log_channels_.clear();
        log_formatter_->release();
    }

    void Framework::CreateLoggingSystem()
    {
        PROFILE(FW_CreateLoggingSystem);
        Poco::LoggingFactory *loggingfactory = new Poco::LoggingFactory();

        Poco::Channel *consolechannel = NULL;
        if (config_manager_->GetSetting<bool>(Framework::ConfigurationGroup(), "log_console"))
            consolechannel = loggingfactory->createChannel("ConsoleChannel");

        Poco::Channel *filechannel = loggingfactory->createChannel("FileChannel");

        std::wstring logfilepath_w = platform_->GetUserDocumentsDirectoryW();
        logfilepath_w += L"/" + Core::ToWString(config_manager_->GetSetting<std::string>(Framework::ConfigurationGroup(), "application_name")) + L".log";
        std::string logfilepath;
        Poco::UnicodeConverter::toUTF8(logfilepath_w, logfilepath);

        filechannel->setProperty("path",logfilepath);
        filechannel->setProperty("rotation","3M");
        filechannel->setProperty("archive","number");
        filechannel->setProperty("compress","false");

        Poco::SplitterChannel *splitterchannel = new Poco::SplitterChannel();
        if (consolechannel)
            splitterchannel->addChannel(consolechannel);
        splitterchannel->addChannel(filechannel);

        log_formatter_ = loggingfactory->createFormatter("PatternFormatter");
        log_formatter_->setProperty("pattern","%H:%M:%S [%s] %t");
        log_formatter_->setProperty("times","local");
        Poco::Channel *formatchannel = new Poco::FormattingChannel(log_formatter_,splitterchannel);

        try
        {
            Poco::Logger::create("",formatchannel,Poco::Message::PRIO_TRACE);
            Poco::Logger::create("Foundation",Poco::Logger::root().getChannel() ,Poco::Message::PRIO_TRACE);
        } catch (Poco::ExistsException)
        {
            assert (false && "Somewhere, a message is pushed to log before the logger is initialized.");
        }

        Poco::LocalDateTime *currenttime = new Poco::LocalDateTime();
        std::string timestring = boost::lexical_cast<std::string>(currenttime->day()) + "/";
        timestring.append(boost::lexical_cast<std::string>(currenttime->month()) + "/");
        timestring.append(boost::lexical_cast<std::string>(currenttime->year()) + " ");
        timestring.append(boost::lexical_cast<std::string>(currenttime->hour()) + ":");
        timestring.append(boost::lexical_cast<std::string>(currenttime->minute()) + ":");
        timestring.append(boost::lexical_cast<std::string>(currenttime->second()));

        try
        {
            Foundation::RootLogInfo("Log file opened on " + timestring);
        } catch(Poco::OpenFileException)
        {
            // Do not create the log file.
            splitterchannel->removeChannel(filechannel);
            Foundation::RootLogInfo("Poco::OpenFileException. Log file not created.");
        }

#ifndef _DEBUG
        // make it so debug messages are not logged in release mode
        std::string log_level = config_manager_->GetSetting<std::string>(Framework::ConfigurationGroup(), "log_level");
        Poco::Logger::get("Foundation").setLevel(log_level);
#endif

        if (consolechannel)
            log_channels_.push_back(consolechannel);
        log_channels_.push_back(filechannel);
        log_channels_.push_back(splitterchannel);
        log_channels_.push_back(formatchannel);

        delete currenttime;
        delete loggingfactory;
    }

    void Framework::PostInitialize()
    {
        PROFILE(FW_PostInitialize);

        LoadModules();

        // commands must be registered after modules are loaded and initialized
        RegisterConsoleCommands();

        // add event subscribers now, that all modules are loaded/initialized
        event_manager_->LoadEventSubscriberTree(DEFAULT_EVENT_SUBSCRIBER_TREE_PATH);
    }

    void Framework::Go()
    {
        PROFILE(FW_Go);
        PostInitialize();

        boost::timer timer;

        boost::weak_ptr<Foundation::RenderServiceInterface> renderer =
                    service_manager_->GetService<RenderServiceInterface>(Service::ST_Renderer);

        // main loop
        while (exit_signal_ == false)
        {
            {
                PROFILE(MainLoop);

                double frametime = timer.elapsed();
                timer.restart();
                // do synchronized update for modules
                {
                    PROFILE(FW_UpdateModules);
                    module_manager_->UpdateModules(frametime);
                }

                // call asynchronous update on modules / do parallel tasks

                // synchronize shared data across modules
                //mChangeManager->_propagateChanges();

                // process delayed events

                {
                   PROFILE(FW_ProcessDelayedEvents);
                    event_manager_->ProcessDelayedEvents(frametime);
                }

                // if we have a renderer service, render now

                if (renderer.expired() == false)
                {
                    PROFILE(FW_Render);
                    renderer.lock()->Render();
                }
            }

#ifdef PROFILING
            // Reset profiling data. Should be outside of any profiling blocks.
            GetProfiler().Reset();
#endif
        }

         UnloadModules();
    }

    void Framework::LoadModules()
    {
        {
            PROFILE(FW_LoadModules);
            module_manager_->LoadAvailableModules();
        }
        {
            PROFILE(FW_InitializeModules);
            module_manager_->InitializeModules();
        }
    }

    void Framework::UnloadModules()
    {
        module_manager_->UninitializeModules();
        scenes_.clear();
        module_manager_->UnloadModules();
    }

    Scene::ScenePtr Framework::CreateScene(const std::string &name)
    {
        if (HasScene(name))
            return Scene::ScenePtr();

        Scene::ScenePtr new_scene = Scene::ScenePtr(new Scene::SceneManager(name, this));
        scenes_[name] = new_scene;

        return new_scene;
    }

    void Framework::RemoveScene(const std::string &name)
    {
        SceneMap::iterator scene = scenes_.find(name);
        if (scene != scenes_.end())
        {
            scenes_.erase(scene);
        }
    }
    Scene::ScenePtr Framework::GetScene(const std::string &name) const
    {
        SceneMap::const_iterator scene = scenes_.find(name);
        if (scene != scenes_.end())
            return scene->second;

        return Scene::ScenePtr();
    }

    Console::CommandResult Framework::ConsoleLoadModule(const Core::StringVector &params)
    {
        if (params.size() != 2 && params.size() != 1)
            return Console::ResultInvalidParameters();

        std::string lib = params[0];
        std::string entry = params[0];
        if (params.size() == 2)
            entry = params[1];

        bool result = module_manager_->LoadModuleByName(lib, entry);
        event_manager_->ValidateEventSubscriberTree();

        if (!result)
            return Console::ResultFailure("Library or module not found.");

        return Console::ResultSuccess("Module " + entry + " loaded.");
    }

    Console::CommandResult Framework::ConsoleUnloadModule(const Core::StringVector &params)
    {
        if (params.size() != 1)
            return Console::ResultInvalidParameters();

        bool result = false;
        if (module_manager_->HasModule(params[0]))
        {
            result = module_manager_->UnloadModuleByName(params[0]);
            event_manager_->ValidateEventSubscriberTree();
        }

        if (!result)
            return Console::ResultFailure("Module not found.");

        return Console::ResultSuccess("Module " + params[0] + " unloaded.");
    }

    Console::CommandResult Framework::ConsoleListModules(const Core::StringVector &params)
    {
        boost::shared_ptr<Console::ConsoleServiceInterface> console = GetService<Console::ConsoleServiceInterface>(Foundation::Service::ST_Console).lock();
        if (console)
        {
            console->Print("Loaded modules:");
            const ModuleManager::ModuleVector &modules = module_manager_->GetModuleList();
            for (size_t i = 0 ; i < modules.size() ; ++i)
            {
                console->Print(modules[i].module_->Name());
            }
        }

        return Console::ResultSuccess();
    }

    Console::CommandResult Framework::ConsoleSendEvent(const Core::StringVector &params)
    {
        if (params.size() != 2)
            return Console::ResultInvalidParameters();

        Core::event_category_id_t event_category = event_manager_->QueryEventCategory(params[0]);
        if (event_category == Core::IllegalEventCategory)
        {
            return Console::ResultFailure("Event category not found.");
        } else
        {
            event_manager_->SendEvent(
                event_category,
                Core::ParseString<Core::event_id_t>(params[1]),
                NULL);

            return Console::ResultSuccess();
        }
    }

    void PrintTimingsToConsole(const Console::ConsolePtr &console, const ProfilerNodeTree *node)
    {
        const ProfilerNode *timings_node = dynamic_cast<const ProfilerNode*>(node);

        static int level = -2;

        if (timings_node)
        {
            level += 2;
            assert (level >= 0);

            std::string timings;
            timings.append(level, ' ');
            timings += timings_node->Name();
            timings += ": called total " + Core::ToString(timings_node->num_called_total_);
            timings += ", elapsed total " + Core::ToString(timings_node->total_);
            timings += ", called " + Core::ToString(timings_node->num_called_);
            timings += ", elapsed " + Core::ToString(timings_node->elapsed_);

            double average = timings_node->num_called_total_ == 0 ? 0.0 : timings_node->total_ / timings_node->num_called_total_;
            timings += ", average " + Core::ToString(average);
            console->Print(timings);
        }

        const ProfilerNodeTree::NodeList &children = node->GetChildren();
        for (ProfilerNodeTree::NodeList::const_iterator it = children.begin() ;
             it != children.end() ;
             ++it)
        {
            PrintTimingsToConsole(console, *it);
        }
        if (timings_node)
        {
            level -= 2;
        }
    }

    Console::CommandResult Framework::ConsoleProfile(const Core::StringVector &params)
    {
        boost::shared_ptr<Console::ConsoleServiceInterface> console = GetService<Console::ConsoleServiceInterface>(Foundation::Service::ST_Console).lock();
        if (console)
        {
            Profiler &profiler = GetProfiler();
            ProfilerNodeTree *node = profiler.Lock().get();
            PrintTimingsToConsole(console, node);
            profiler.Release();
        }
        return Console::ResultSuccess();
    }

    void Framework::RegisterConsoleCommands()
    {
        boost::shared_ptr<Console::CommandService> console = GetService<Console::CommandService>(Foundation::Service::ST_ConsoleCommand).lock();
        if (console)
        {
            console->RegisterCommand(Console::CreateCommand("LoadModule",
                "Loads a module from shared library. Usage: LoadModule(lib, entry)",
                Console::Bind(this, &Framework::ConsoleLoadModule)));

            console->RegisterCommand(Console::CreateCommand("UnloadModule",
                "Unloads a module. Usage: UnloadModule(name)",
                Console::Bind(this, &Framework::ConsoleUnloadModule)));

            console->RegisterCommand(Console::CreateCommand("ListModules",
                "Lists all loaded modules.",
                Console::Bind(this, &Framework::ConsoleListModules)));

            console->RegisterCommand(Console::CreateCommand("SendEvent",
                "Sends an internal event. Only for events that contain no data. Usage: SendEvent(event category name, event id)",
                Console::Bind(this, &Framework::ConsoleSendEvent)));

            console->RegisterCommand(Console::CreateCommand("Profile",
                "Outputs profiling data. Usage: Profile() for full, or Profile(name) for specific profiling block",
                Console::Bind(this, &Framework::ConsoleProfile)));
        }
    }
}

<|endoftext|>


<commit_before>// Copyright (c) 2012-2013 The PPCoin developers
// Copyright (c) 2014 The BlackCoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <boost/assign/list_of.hpp>

#include "pos.h"
#include "txdb.h"
#include "validation.h"
#include "arith_uint256.h"
#include "hash.h"
#include "timedata.h"
#include "chainparams.h"
#include "script/sign.h"
#include "consensus/consensus.h"

using namespace std;

// Stake Modifier (hash modifier of proof-of-stake):
// The purpose of stake modifier is to prevent a txout (coin) owner from
// computing future proof-of-stake generated by this txout at the time
// of transaction confirmation. To meet kernel protocol, the txout
// must hash with a future stake modifier to generate the proof.
uint256 ComputeStakeModifier(const CBlockIndex* pindexPrev, const uint256& kernel)
{
    if (!pindexPrev)
        return uint256();  // genesis block's modifier is 0

    CDataStream ss(SER_GETHASH, 0);
    ss << kernel << pindexPrev->nStakeModifier;
    return Hash(ss.begin(), ss.end());
}

// BlackCoin kernel protocol
// coinstake must meet hash target according to the protocol:
// kernel (input 0) must meet the formula
//     hash(nStakeModifier + blockFrom.nTime + txPrev.vout.hash + txPrev.vout.n + nTime) < bnTarget * nWeight
// this ensures that the chance of getting a coinstake is proportional to the
// amount of coins one owns.
// The reason this hash is chosen is the following:
//   nStakeModifier: scrambles computation to make it very difficult to precompute
//                   future proof-of-stake
//   blockFrom.nTime: slightly scrambles computation
//   txPrev.vout.hash: hash of txPrev, to reduce the chance of nodes
//                     generating coinstake at the same time
//   txPrev.vout.n: output number of txPrev, to reduce the chance of nodes
//                  generating coinstake at the same time
//   nTime: current timestamp
//   block/tx hash should not be used here as they can be generated in vast
//   quantities so as to generate blocks faster, degrading the system back into
//   a proof-of-work situation.
//
bool CheckStakeKernelHash(CBlockIndex* pindexPrev, unsigned int nBits, uint32_t blockFromTime, CAmount prevoutValue, const COutPoint& prevout, unsigned int nTimeBlock, uint256& hashProofOfStake, uint256& targetProofOfStake, bool fPrintProofOfStake)
{
    if (nTimeBlock < blockFromTime)  // Transaction timestamp violation
        return error("CheckStakeKernelHash() : nTime violation");

    // Base target
    arith_uint256 bnTarget;
    bnTarget.SetCompact(nBits);

    // Weighted target
    int64_t nValueIn = prevoutValue;
    arith_uint256 bnWeight = arith_uint256(nValueIn);
    bnTarget *= bnWeight;

    targetProofOfStake = ArithToUint256(bnTarget);

    uint256 nStakeModifier = pindexPrev->nStakeModifier;

    // Calculate hash
    CDataStream ss(SER_GETHASH, 0);
    ss << nStakeModifier;
    ss << blockFromTime << prevout.hash << prevout.n << nTimeBlock;
    hashProofOfStake = Hash(ss.begin(), ss.end());

    if (fPrintProofOfStake)
    {
        LogPrintf("CheckStakeKernelHash() : check modifier=%s nTimeBlockFrom=%u nPrevout=%u nTimeBlock=%u hashProof=%s\n",
            nStakeModifier.GetHex().c_str(),
            blockFromTime, prevout.n, nTimeBlock,
            hashProofOfStake.ToString());
    }

    // Now check if proof-of-stake hash meets target protocol
    if (UintToArith256(hashProofOfStake) > bnTarget)
        return false;

    if (fDebug && !fPrintProofOfStake)
    {
        LogPrintf("CheckStakeKernelHash() : check modifier=%s nTimeBlockFrom=%u nPrevout=%u nTimeBlock=%u hashProof=%s\n",
            nStakeModifier.GetHex().c_str(),
            blockFromTime, prevout.n, nTimeBlock,
            hashProofOfStake.ToString());
    }

    return true;
}

// Check kernel hash target and coinstake signature
bool CheckProofOfStake(CBlockIndex* pindexPrev, CValidationState& state, const CTransaction& tx, unsigned int nBits, uint32_t nTimeBlock, uint256& hashProofOfStake, uint256& targetProofOfStake, CCoinsViewCache& view)
{
    if (!tx.IsCoinStake())
        return error("CheckProofOfStake() : called on non-coinstake %s", tx.GetHash().ToString());

    // Kernel (input 0) must match the stake hash target (nBits)
    const CTxIn& txin = tx.vin[0];

    CCoins coinsPrev;
    if(!view.GetCoins(txin.prevout.hash, coinsPrev)){
        return false;
    }

    if(pindexPrev->nHeight + 1 - coinsPrev.nHeight < COINBASE_MATURITY){
        return false;
    }
    CBlockIndex* blockFrom = pindexPrev->GetAncestor(coinsPrev.nHeight);
    if(!blockFrom) {
        return false;
    }

    // Verify signature
    if (!VerifySignature(coinsPrev, txin.prevout.hash, tx, 0, SCRIPT_VERIFY_NONE))
        return state.DoS(100, error("CheckProofOfStake() : VerifySignature failed on coinstake %s", tx.GetHash().ToString()));

    if (!CheckStakeKernelHash(pindexPrev, nBits, blockFrom->nTime, coinsPrev.vout[txin.prevout.n].nValue, txin.prevout, nTimeBlock, hashProofOfStake, targetProofOfStake, fDebug))
        return state.DoS(1, error("CheckProofOfStake() : INFO: check kernel failed on coinstake %s, hashProof=%s", tx.GetHash().ToString(), hashProofOfStake.ToString())); // may occur during initial download or if behind on block chain sync

    return true;
}

// Check whether the coinstake timestamp meets protocol
bool CheckCoinStakeTimestamp(uint32_t nTimeBlock)
{
    return (nTimeBlock & STAKE_TIMESTAMP_MASK) == 0;
}

bool CheckKernel(CBlockIndex* pindexPrev, unsigned int nBits, uint32_t nTimeBlock, const COutPoint& prevout, CCoinsViewCache& view)
{
    std::map<COutPoint, CStakeCache> tmp;
    return CheckKernel(pindexPrev, nBits, nTimeBlock, prevout, view, tmp);
}

bool CheckKernel(CBlockIndex* pindexPrev, unsigned int nBits, uint32_t nTimeBlock, const COutPoint& prevout, CCoinsViewCache& view, const std::map<COutPoint, CStakeCache>& cache)
{
    uint256 hashProofOfStake, targetProofOfStake;
    auto it=cache.find(prevout);
    if(it == cache.end()) {
        //not found in cache (shouldn't happen during staking, only during verification which does not use cache)
        CCoins coinsPrev;
        if(!view.GetCoins(prevout.hash, coinsPrev)){
            return false;
        }

        if(pindexPrev->nHeight + 1 - coinsPrev.nHeight < COINBASE_MATURITY){
            return false;
        }
        CBlockIndex* blockFrom = pindexPrev->GetAncestor(coinsPrev.nHeight);
        if(!blockFrom) {
            return false;
        }
        if(!coinsPrev.IsAvailable(prevout.n)){
            return false;
        }

        return CheckStakeKernelHash(pindexPrev, nBits, blockFrom->nTime, coinsPrev.vout[prevout.n].nValue, prevout,
                                    nTimeBlock, hashProofOfStake, targetProofOfStake);
    }else{
        //found in cache
        const CStakeCache& stake = it->second;
        if(CheckStakeKernelHash(pindexPrev, nBits, stake.blockFromTime, stake.amount, prevout,
                                    nTimeBlock, hashProofOfStake, targetProofOfStake)){
            //Cache could potentially cause false positive stakes in the event of deep reorgs, so check without cache also
            return CheckKernel(pindexPrev, nBits, nTimeBlock, prevout, view);
        }
    }
    return false;
}

void CacheKernel(std::map<COutPoint, CStakeCache>& cache, const COutPoint& prevout, CBlockIndex* pindexPrev, CCoinsViewCache& view){
    if(cache.find(prevout) != cache.end()){
        //already in cache
        return;
    }

    CCoins coinsPrev;
    if(!view.GetCoins(prevout.hash, coinsPrev)){
        return;
    }

    if(pindexPrev->nHeight + 1 - coinsPrev.nHeight < COINBASE_MATURITY){
        return;
    }
    CBlockIndex* blockFrom = pindexPrev->GetAncestor(coinsPrev.nHeight);
    if(!blockFrom) {
        return;
    }

    CStakeCache c(blockFrom->nTime, coinsPrev.vout[prevout.n].nValue);
    cache.insert({prevout, c});
}

<commit_msg>Replace false returns with DoS errors<commit_after>// Copyright (c) 2012-2013 The PPCoin developers
// Copyright (c) 2014 The BlackCoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <boost/assign/list_of.hpp>

#include "pos.h"
#include "txdb.h"
#include "validation.h"
#include "arith_uint256.h"
#include "hash.h"
#include "timedata.h"
#include "chainparams.h"
#include "script/sign.h"
#include "consensus/consensus.h"

using namespace std;

// Stake Modifier (hash modifier of proof-of-stake):
// The purpose of stake modifier is to prevent a txout (coin) owner from
// computing future proof-of-stake generated by this txout at the time
// of transaction confirmation. To meet kernel protocol, the txout
// must hash with a future stake modifier to generate the proof.
uint256 ComputeStakeModifier(const CBlockIndex* pindexPrev, const uint256& kernel)
{
    if (!pindexPrev)
        return uint256();  // genesis block's modifier is 0

    CDataStream ss(SER_GETHASH, 0);
    ss << kernel << pindexPrev->nStakeModifier;
    return Hash(ss.begin(), ss.end());
}

// BlackCoin kernel protocol
// coinstake must meet hash target according to the protocol:
// kernel (input 0) must meet the formula
//     hash(nStakeModifier + blockFrom.nTime + txPrev.vout.hash + txPrev.vout.n + nTime) < bnTarget * nWeight
// this ensures that the chance of getting a coinstake is proportional to the
// amount of coins one owns.
// The reason this hash is chosen is the following:
//   nStakeModifier: scrambles computation to make it very difficult to precompute
//                   future proof-of-stake
//   blockFrom.nTime: slightly scrambles computation
//   txPrev.vout.hash: hash of txPrev, to reduce the chance of nodes
//                     generating coinstake at the same time
//   txPrev.vout.n: output number of txPrev, to reduce the chance of nodes
//                  generating coinstake at the same time
//   nTime: current timestamp
//   block/tx hash should not be used here as they can be generated in vast
//   quantities so as to generate blocks faster, degrading the system back into
//   a proof-of-work situation.
//
bool CheckStakeKernelHash(CBlockIndex* pindexPrev, unsigned int nBits, uint32_t blockFromTime, CAmount prevoutValue, const COutPoint& prevout, unsigned int nTimeBlock, uint256& hashProofOfStake, uint256& targetProofOfStake, bool fPrintProofOfStake)
{
    if (nTimeBlock < blockFromTime)  // Transaction timestamp violation
        return error("CheckStakeKernelHash() : nTime violation");

    // Base target
    arith_uint256 bnTarget;
    bnTarget.SetCompact(nBits);

    // Weighted target
    int64_t nValueIn = prevoutValue;
    arith_uint256 bnWeight = arith_uint256(nValueIn);
    bnTarget *= bnWeight;

    targetProofOfStake = ArithToUint256(bnTarget);

    uint256 nStakeModifier = pindexPrev->nStakeModifier;

    // Calculate hash
    CDataStream ss(SER_GETHASH, 0);
    ss << nStakeModifier;
    ss << blockFromTime << prevout.hash << prevout.n << nTimeBlock;
    hashProofOfStake = Hash(ss.begin(), ss.end());

    if (fPrintProofOfStake)
    {
        LogPrintf("CheckStakeKernelHash() : check modifier=%s nTimeBlockFrom=%u nPrevout=%u nTimeBlock=%u hashProof=%s\n",
            nStakeModifier.GetHex().c_str(),
            blockFromTime, prevout.n, nTimeBlock,
            hashProofOfStake.ToString());
    }

    // Now check if proof-of-stake hash meets target protocol
    if (UintToArith256(hashProofOfStake) > bnTarget)
        return false;

    if (fDebug && !fPrintProofOfStake)
    {
        LogPrintf("CheckStakeKernelHash() : check modifier=%s nTimeBlockFrom=%u nPrevout=%u nTimeBlock=%u hashProof=%s\n",
            nStakeModifier.GetHex().c_str(),
            blockFromTime, prevout.n, nTimeBlock,
            hashProofOfStake.ToString());
    }

    return true;
}

// Check kernel hash target and coinstake signature
bool CheckProofOfStake(CBlockIndex* pindexPrev, CValidationState& state, const CTransaction& tx, unsigned int nBits, uint32_t nTimeBlock, uint256& hashProofOfStake, uint256& targetProofOfStake, CCoinsViewCache& view)
{
    if (!tx.IsCoinStake())
        return error("CheckProofOfStake() : called on non-coinstake %s", tx.GetHash().ToString());s

    // Kernel (input 0) must match the stake hash target (nBits)
    const CTxIn& txin = tx.vin[0];

    CCoins coinsPrev;
    if(!view.GetCoins(txin.prevout.hash, coinsPrev)){
        return state.DoS(100, error("CheckProofOfStake() : Stake prevout does not exist %s", txin.prevout.hash.ToString()));
    }

    if(pindexPrev->nHeight + 1 - coinsPrev.nHeight < COINBASE_MATURITY){
        return state.DoS(100, error("CheckProofOfStake() : Stake prevout is not mature, expecting %i and only matured to %i", COINBASE_MATURITY, pindexPrev->nHeight + 1 - coinsPrev.nHeight));
    }
    CBlockIndex* blockFrom = pindexPrev->GetAncestor(coinsPrev.nHeight);
    if(!blockFrom) {
        return state.DoS(100, error("CheckProofOfStake() : Block at height %i for prevout can not be loaded", coinsPrev.nHeight));
    }

    // Verify signature
    if (!VerifySignature(coinsPrev, txin.prevout.hash, tx, 0, SCRIPT_VERIFY_NONE))
        return state.DoS(100, error("CheckProofOfStake() : VerifySignature failed on coinstake %s", tx.GetHash().ToString()));

    if (!CheckStakeKernelHash(pindexPrev, nBits, blockFrom->nTime, coinsPrev.vout[txin.prevout.n].nValue, txin.prevout, nTimeBlock, hashProofOfStake, targetProofOfStake, fDebug))
        return state.DoS(1, error("CheckProofOfStake() : INFO: check kernel failed on coinstake %s, hashProof=%s", tx.GetHash().ToString(), hashProofOfStake.ToString())); // may occur during initial download or if behind on block chain sync

    return true;
}

// Check whether the coinstake timestamp meets protocol
bool CheckCoinStakeTimestamp(uint32_t nTimeBlock)
{
    return (nTimeBlock & STAKE_TIMESTAMP_MASK) == 0;
}

bool CheckKernel(CBlockIndex* pindexPrev, unsigned int nBits, uint32_t nTimeBlock, const COutPoint& prevout, CCoinsViewCache& view)
{
    std::map<COutPoint, CStakeCache> tmp;
    return CheckKernel(pindexPrev, nBits, nTimeBlock, prevout, view, tmp);
}

bool CheckKernel(CBlockIndex* pindexPrev, unsigned int nBits, uint32_t nTimeBlock, const COutPoint& prevout, CCoinsViewCache& view, const std::map<COutPoint, CStakeCache>& cache)
{
    uint256 hashProofOfStake, targetProofOfStake;
    auto it=cache.find(prevout);
    if(it == cache.end()) {
        //not found in cache (shouldn't happen during staking, only during verification which does not use cache)
        CCoins coinsPrev;
        if(!view.GetCoins(prevout.hash, coinsPrev)){
            return false;
        }

        if(pindexPrev->nHeight + 1 - coinsPrev.nHeight < COINBASE_MATURITY){
            return false;
        }
        CBlockIndex* blockFrom = pindexPrev->GetAncestor(coinsPrev.nHeight);
        if(!blockFrom) {
            return false;
        }
        if(!coinsPrev.IsAvailable(prevout.n)){
            return false;
        }

        return CheckStakeKernelHash(pindexPrev, nBits, blockFrom->nTime, coinsPrev.vout[prevout.n].nValue, prevout,
                                    nTimeBlock, hashProofOfStake, targetProofOfStake);
    }else{
        //found in cache
        const CStakeCache& stake = it->second;
        if(CheckStakeKernelHash(pindexPrev, nBits, stake.blockFromTime, stake.amount, prevout,
                                    nTimeBlock, hashProofOfStake, targetProofOfStake)){
            //Cache could potentially cause false positive stakes in the event of deep reorgs, so check without cache also
            return CheckKernel(pindexPrev, nBits, nTimeBlock, prevout, view);
        }
    }
    return false;
}

void CacheKernel(std::map<COutPoint, CStakeCache>& cache, const COutPoint& prevout, CBlockIndex* pindexPrev, CCoinsViewCache& view){
    if(cache.find(prevout) != cache.end()){
        //already in cache
        return;
    }

    CCoins coinsPrev;
    if(!view.GetCoins(prevout.hash, coinsPrev)){
        return;
    }

    if(pindexPrev->nHeight + 1 - coinsPrev.nHeight < COINBASE_MATURITY){
        return;
    }
    CBlockIndex* blockFrom = pindexPrev->GetAncestor(coinsPrev.nHeight);
    if(!blockFrom) {
        return;
    }

    CStakeCache c(blockFrom->nTime, coinsPrev.vout[prevout.n].nValue);
    cache.insert({prevout, c});
}

<|endoftext|>