<commit_before>/*
 * Copyright (C) 2015 Luke San Antonio
 * All rights reserved.
 */
#include "sdl_helper.h"
#include "common/log.h"
#include "common/debugging.h"
namespace redc
{
  SDL_Init_Lock::SDL_Init_Lock(SDL_Init_Lock&& l) : window(l.window),
                                                    gl_context(l.gl_context)
  {
    l.window = nullptr;
    l.gl_context = nullptr;
  }

  SDL_Init_Lock& SDL_Init_Lock::operator=(SDL_Init_Lock&& l)
  {
    window = l.window;
    gl_context = l.gl_context;

    l.window = nullptr;
    l.gl_context = nullptr;

    return *this;
  }

  SDL_Init_Lock::~SDL_Init_Lock()
  {
    // If we don't have both for any reason, don't bother deallocating either.
    if(window && gl_context)
    {
      // That way, if we accidentally partially move we won't do the aggressive
      // SDL_Quit call.

      SDL_GL_DeleteContext(gl_context);
      SDL_DestroyWindow(window);
      SDL_Quit();
    }
  }

  SDL_Init_Lock init_sdl(std::string title, Vec<int> res, bool fullscreen,
                         bool vsync)
  {
    // Initialize SDL

    if(SDL_Init(SDL_INIT_VIDEO))
    {
      log_e("Failed to init SDL");
      return {};
    }

    SDL_version version;
    SDL_GetVersion(&version);

    log_i("Initialized SDL %.%.%", version.major, version.minor, version.patch);

    // Initialize window

    int flags = SDL_WINDOW_OPENGL;
    if(fullscreen) flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;

    SDL_Init_Lock ret;

    ret.window = SDL_CreateWindow(title.c_str(), SDL_WINDOWPOS_UNDEFINED,
                                  SDL_WINDOWPOS_UNDEFINED, res.x, res.y,
                                  flags);
    if(!ret.window)
    {
      SDL_Quit();
      log_e("Failed to initialize SDL for resolution %x%", res.x, res.y);
      return ret;
    }

    // Initialize OpenGL context

    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK,
                        SDL_GL_CONTEXT_PROFILE_CORE);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS,
                        SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG);
    SDL_GL_SetAttribute(SDL_GL_FRAMEBUFFER_SRGB_CAPABLE, 1);

    ret.gl_context = SDL_GL_CreateContext(ret.window);
    SDL_GL_MakeCurrent(ret.window, ret.gl_context);

    // Set vsync setting
    int sync_interval = 0;
    if(vsync) sync_interval = 1;
    if(SDL_GL_SetSwapInterval(sync_interval) == -1)
    {
      // Shit, failed to set that
      log_w("Failed to set swap interval: %", SDL_GetError());
    }

    gladLoadGLLoader((GLADloadproc) SDL_GL_GetProcAddress);

    int opengl_maj, opengl_min;
    glGetIntegerv(GL_MAJOR_VERSION, &opengl_maj);
    glGetIntegerv(GL_MINOR_VERSION, &opengl_min);
    log_i("OpenGL core profile %.%", opengl_maj, opengl_min);

    GLint front_type = 0;
    glGetFramebufferAttachmentParameteriv(
      GL_DRAW_FRAMEBUFFER, GL_BACK_LEFT,
      GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING, &front_type
    );
    std::string framebuf_string("Unknown type");
    switch(front_type)
    {
    case GL_LINEAR:
      framebuf_string = "RGB";
      break;
    case GL_SRGB:
      framebuf_string = "sRGB";
      break;
    default:
      REDC_UNREACHABLE_MSG("Invalid framebuffer type");
    }
    log_d("Using % framebuffer", framebuf_string);

    return ret;
  }
}
<commit_msg>Don't be so picky about our OpenGL context<commit_after>/*
 * Copyright (C) 2015 Luke San Antonio
 * All rights reserved.
 */
#include "sdl_helper.h"
#include "common/log.h"
#include "common/debugging.h"
namespace redc
{
  SDL_Init_Lock::SDL_Init_Lock(SDL_Init_Lock&& l) : window(l.window),
                                                    gl_context(l.gl_context)
  {
    l.window = nullptr;
    l.gl_context = nullptr;
  }

  SDL_Init_Lock& SDL_Init_Lock::operator=(SDL_Init_Lock&& l)
  {
    window = l.window;
    gl_context = l.gl_context;

    l.window = nullptr;
    l.gl_context = nullptr;

    return *this;
  }

  SDL_Init_Lock::~SDL_Init_Lock()
  {
    // If we don't have both for any reason, don't bother deallocating either.
    if(window && gl_context)
    {
      // That way, if we accidentally partially move we won't do the aggressive
      // SDL_Quit call.

      SDL_GL_DeleteContext(gl_context);
      SDL_DestroyWindow(window);
      SDL_Quit();
    }
  }

  SDL_Init_Lock init_sdl(std::string title, Vec<int> res, bool fullscreen,
                         bool vsync)
  {
    // Initialize SDL

    if(SDL_Init(SDL_INIT_VIDEO))
    {
      log_e("Failed to init SDL");
      return {};
    }

    SDL_version version;
    SDL_GetVersion(&version);

    log_i("Initialized SDL %.%.%", version.major, version.minor, version.patch);

    // Initialize window

    int flags = SDL_WINDOW_OPENGL;
    if(fullscreen) flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;

    SDL_Init_Lock ret;

    ret.window = SDL_CreateWindow(title.c_str(), SDL_WINDOWPOS_UNDEFINED,
                                  SDL_WINDOWPOS_UNDEFINED, res.x, res.y,
                                  flags);
    if(!ret.window)
    {
      SDL_Quit();
      log_e("Failed to initialize SDL for resolution %x%", res.x, res.y);
      return ret;
    }

    // Initialize OpenGL context

    SDL_GL_SetAttribute(SDL_GL_FRAMEBUFFER_SRGB_CAPABLE, 1);

    ret.gl_context = SDL_GL_CreateContext(ret.window);
    if(ret.gl_context == NULL)
    {
      log_e("Failed to create OpenGL context: %", SDL_GetError());
    }

    SDL_GL_MakeCurrent(ret.window, ret.gl_context);

    // Set vsync setting
    int sync_interval = 0;
    if(vsync) sync_interval = 1;
    if(SDL_GL_SetSwapInterval(sync_interval) == -1)
    {
      // Shit, failed to set that
      log_w("Failed to set swap interval: %", SDL_GetError());
    }

    gladLoadGLLoader((GLADloadproc) SDL_GL_GetProcAddress);

    int opengl_maj, opengl_min;
    glGetIntegerv(GL_MAJOR_VERSION, &opengl_maj);
    glGetIntegerv(GL_MINOR_VERSION, &opengl_min);
    log_i("OpenGL core profile %.%", opengl_maj, opengl_min);

    GLint front_type = 0;
    glGetFramebufferAttachmentParameteriv(
      GL_DRAW_FRAMEBUFFER, GL_BACK_LEFT,
      GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING, &front_type
    );
    std::string framebuf_string("Unknown type");
    switch(front_type)
    {
    case GL_LINEAR:
      framebuf_string = "RGB";
      break;
    case GL_SRGB:
      framebuf_string = "sRGB";
      break;
    default:
      REDC_UNREACHABLE_MSG("Invalid framebuffer type");
    }
    log_d("Using % framebuffer", framebuf_string);

    return ret;
  }
}
<|endoftext|>


<commit_before>////////////////////////////////////
// @file main.cc
// @brief Morse code generator
// @author Mamoru Kaminaga
// @date 2016-05-15 12:08:31
// Copyright 2016 Mamoru Kaminaga
////////////////////////////////////
#include <wchar.h>
#include <windows.h>
#include <stdio.h>
#include "common.h"
#include "morse_player.h"
#include "resource.h"
#define WINDOW_STYLE    (WS_POPUP|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX)
enum OPTIONS {
  OPTION_HELP = 0,
  OPTION_STRING,
  OPTION_NOWINDOW,
  OPTION_NOSOUND,
  OPTION_WPM,
  OPTION_PARIS,
  ELEMNUM_OPTIONS, // Array size.
};
const wchar_t kOptions[ELEMNUM_OPTIONS][16] = {
  L"-help",        // OPTION_HELP
  L"-s",           // OPTION_STRING
  L"-nowindow",    // OPTION_NOWINDOW
  L"-nosound",     // OPTION_NOSOUND
  L"-wpm",         // OPTION_WPM
  L"-paris",       // OPTION_PARIS
};
const wchar_t kHelp[ELEMNUM_OPTIONS][64] = {
  L"Show help",                        // OPTION_HELP
  L"Input string to be morse signal",  // OPTION_STRING
  L"Not show output console",          // OPTION_NOWINDOW
  L"Not play midi sound",              // OPTION_NOSOUND
  L"Set WPM, default is 20",           // OPTION_WPM
  L"Set PARIS, default is 20",         // OPTION_PARIS
};
bool help_required = false;
bool no_console = false;
bool no_sound = false;
bool play_command_line_string = false;
int string_argc_offset = 0;
void ShowAndPlay(MorsePlayer* morse_player, wchar_t charactor);
bool CreateInvisibleWindow(HINSTANCE instance_handle);
int WINAPI wWinMain(HINSTANCE instance_handle, HINSTANCE not_used,
                    LPTSTR cmd_lind, int cmd_show) {
  // Prevent warnings for unreferenced parameters.
  UNREFERENCED_PARAMETER(instance_handle);
  UNREFERENCED_PARAMETER(not_used);
  UNREFERENCED_PARAMETER(cmd_lind);
  UNREFERENCED_PARAMETER(cmd_show);
  //
  MorsePlayer morse_player;
  morse_player.Initialize();
  morse_player.dot_len_ = 60;
  // Command line is processed.
  for (int i = 1; i < __argc; ++i) {
    for (int j = 0; j < ELEMNUM_OPTIONS; ++j) {
      if (wcscmp(__wargv[i], kOptions[j]) == 0) {
        switch (j) {
          case OPTION_HELP:
            help_required = true;
            break;
          case OPTION_NOWINDOW:
            no_console = true;
            break;
          case OPTION_NOSOUND:
            no_sound = true;
            break;
          case OPTION_WPM:  // Same as OPTION_PARIS
          case OPTION_PARIS:
            /* wpm (paris) -> dot millis */
            morse_player.dot_len_ = 60000 / (_wtoi(__wargv[i + 1]) * 50);
            break;
          case OPTION_STRING:
            play_command_line_string = true;
            string_argc_offset = i + 1;
          default:
            break;
        }
      }
    }
  }
  // Win32 Console is initialized.
  if (!no_console) {
		if (!AttachConsole(ATTACH_PARENT_PROCESS)) AllocConsole();
    freopen("CON", "r", stdin);
    freopen("CON", "w", stdout);
  }
  // Argument num error check done.
  if (__argc <= 1) {
    if (no_console) {
      DialogError(L"No arguments specified");
      return -1;
    } else {
      PrintError(L"No arguments specified");
      goto ERROR_EXIT;
    }
  }
  // Help option process.
  if (help_required) {
    if (no_console) {
      DialogError(L"You must not set -nowindow option to show help");
      return 0;
    } else {
      wprintf(APP_NAME);
      wprintf(L"\n");
      wprintf(L"options:\n");
      for (int i = 0; i < ELEMNUM_OPTIONS; ++i) {
        wprintf(L"%s:\t%s\n", kOptions[i], kHelp[i]);
      }
      goto ERROR_EXIT;
    }
  }
  // String error.
  if (play_command_line_string == false) {
    if (no_console) {
      DialogError(L"No input string");
      return -1;
    } else {
      PrintError(L"No input string");
      goto ERROR_EXIT;
    }
  }
  // Morse generated
  int length = 0;
  for (int i = string_argc_offset; i < __argc; ++i) {
    length = wcslen(__wargv[i]);
    for (int j = 0; j < length; ++j) {
      ShowAndPlay(&morse_player, __wargv[i][j]);
      ShowAndPlay(&morse_player, L' ');
    }
    if (i != (__argc - 1)) {  // Word separator.
      ShowAndPlay(&morse_player, L' ');
      ShowAndPlay(&morse_player, L' ');
      ShowAndPlay(&morse_player, L' ');
    }
  }
  // Finalize console.
  if (!no_console) {
    system("PAUSE");
    FreeConsole();
  }
  morse_player.Finalize();
  return 0;
ERROR_EXIT:
  if (!no_console) {
    system("PAUSE");
    FreeConsole();
  }
  morse_player.Finalize();
  return -1;
}
void ShowAndPlay(MorsePlayer* morse_player, wchar_t charactor) {
  int morse_code = 0;
  switch (charactor) {
    case L'a': case L'A': morse_code = MORSE_A; break;
    case L'b': case L'B': morse_code = MORSE_B; break;
    case L'c': case L'C': morse_code = MORSE_C; break;
    case L'd': case L'D': morse_code = MORSE_D; break;
    case L'e': case L'E': morse_code = MORSE_E; break;
    case L'f': case L'F': morse_code = MORSE_F; break;
    case L'g': case L'G': morse_code = MORSE_G; break;
    case L'h': case L'H': morse_code = MORSE_H; break;
    case L'i': case L'I': morse_code = MORSE_I; break;
    case L'j': case L'J': morse_code = MORSE_J; break;
    case L'k': case L'K': morse_code = MORSE_K; break;
    case L'l': case L'L': morse_code = MORSE_L; break;
    case L'm': case L'M': morse_code = MORSE_M; break;
    case L'n': case L'N': morse_code = MORSE_N; break;
    case L'o': case L'O': morse_code = MORSE_O; break;
    case L'p': case L'P': morse_code = MORSE_P; break;
    case L'q': case L'Q': morse_code = MORSE_Q; break;
    case L'r': case L'R': morse_code = MORSE_R; break;
    case L's': case L'S': morse_code = MORSE_S; break;
    case L't': case L'T': morse_code = MORSE_T; break;
    case L'u': case L'U': morse_code = MORSE_U; break;
    case L'v': case L'V': morse_code = MORSE_V; break;
    case L'w': case L'W': morse_code = MORSE_W; break;
    case L'x': case L'X': morse_code = MORSE_X; break;
    case L'y': case L'Y': morse_code = MORSE_Y; break;
    case L'z': case L'Z': morse_code = MORSE_Z; break;
    case L'1': morse_code = MORSE_1; break;
    case L'2': morse_code = MORSE_2; break;
    case L'3': morse_code = MORSE_3; break;
    case L'4': morse_code = MORSE_4; break;
    case L'5': morse_code = MORSE_5; break;
    case L'6': morse_code = MORSE_6; break;
    case L'7': morse_code = MORSE_7; break;
    case L'8': morse_code = MORSE_8; break;
    case L'9': morse_code = MORSE_9; break;
    case L'0': morse_code = MORSE_0; break;
    case L'.': morse_code = MORSE_PER; break;
    case L',': morse_code = MORSE_COM; break;
    case L'?': morse_code = MORSE_QUE; break;
    case L'-': morse_code = MORSE_HIF; break;
    case L'/': morse_code = MORSE_SLA; break;
    case L'@': morse_code = MORSE_ATM; break;
    case L' ': morse_code = MORSE_SPACE; break;
    default: morse_code = MORSE_UNKNOWN; break;
  }
  // Morse shown to console.
  if (!no_console) morse_player->ShowSimbol(morse_code);
  // Sound played by device.
  if (!no_sound) morse_player->PlaySound(morse_code);
}
// Void callback function.
LRESULT CALLBACK WndProc(HWND wnd, UINT msg, WPARAM wp, LPARAM lp) {
  // Prevent warnings for unreferenced parameters.
  UNREFERENCED_PARAMETER(wnd);
  UNREFERENCED_PARAMETER(wp);
  UNREFERENCED_PARAMETER(lp);
  switch (msg) {
    case WM_DESTROY:
      PostQuitMessage(0);
      break;
    default:
      break;
  }
  return DefWindowProc(wnd, msg, wp, lp);
}
// Window is required to set icom on win32 application.
bool CreateInvisibleWindow(HINSTANCE instance_handle) {
  WNDCLASSEX wcex;
  // Window class registered.
  memset(&wcex, 0, sizeof(wcex));
  wcex.cbSize = sizeof(wcex);
  wcex.style = CS_HREDRAW | CS_VREDRAW;
  wcex.lpfnWndProc = WndProc;
  wcex.cbClsExtra = 0;
  wcex.cbWndExtra = 0;
  wcex.hInstance = instance_handle;
  wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
  wcex.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
  wcex.lpszMenuName = NULL;
  wcex.lpszClassName = APP_NAME;
  wcex.hIcon = LoadIcon(instance_handle, MAKEINTRESOURCE(IDI_ICON1));
  wcex.hIconSm = LoadIcon(instance_handle, MAKEINTRESOURCE(IDI_ICON1));
  if (RegisterClassEx(&wcex) == 0) return false;
  // Invisible window created.
  HWND window_handle = CreateWindow(APP_NAME, APP_NAME, WINDOW_STYLE,
                                    CW_USEDEFAULT, CW_USEDEFAULT, 256, 256,
                                    NULL, NULL, instance_handle, NULL);
  if (window_handle == NULL) return false;
  return true;
}
<commit_msg>CreateInvisibleWindow is called now<commit_after>////////////////////////////////////
// @file main.cc
// @brief Morse code generator
// @author Mamoru Kaminaga
// @date 2016-05-15 12:08:31
// Copyright 2016 Mamoru Kaminaga
////////////////////////////////////
#include <wchar.h>
#include <windows.h>
#include <stdio.h>
#include "common.h"
#include "morse_player.h"
#include "resource.h"
#define WINDOW_STYLE    (WS_POPUP|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX)
enum OPTIONS {
  OPTION_HELP = 0,
  OPTION_STRING,
  OPTION_NOWINDOW,
  OPTION_NOSOUND,
  OPTION_WPM,
  OPTION_PARIS,
  ELEMNUM_OPTIONS, // Array size.
};
const wchar_t kOptions[ELEMNUM_OPTIONS][16] = {
  L"-help",        // OPTION_HELP
  L"-s",           // OPTION_STRING
  L"-nowindow",    // OPTION_NOWINDOW
  L"-nosound",     // OPTION_NOSOUND
  L"-wpm",         // OPTION_WPM
  L"-paris",       // OPTION_PARIS
};
const wchar_t kHelp[ELEMNUM_OPTIONS][64] = {
  L"Show help",                        // OPTION_HELP
  L"Input string to be morse signal",  // OPTION_STRING
  L"Not show output console",          // OPTION_NOWINDOW
  L"Not play midi sound",              // OPTION_NOSOUND
  L"Set WPM, default is 20",           // OPTION_WPM
  L"Set PARIS, default is 20",         // OPTION_PARIS
};
bool help_required = false;
bool no_console = false;
bool no_sound = false;
bool play_command_line_string = false;
int string_argc_offset = 0;
void ShowAndPlay(MorsePlayer* morse_player, wchar_t charactor);
bool CreateInvisibleWindow(HINSTANCE instance_handle);
int WINAPI wWinMain(HINSTANCE instance_handle, HINSTANCE not_used,
                    LPTSTR cmd_lind, int cmd_show) {
  // Prevent warnings for unreferenced parameters.
  UNREFERENCED_PARAMETER(instance_handle);
  UNREFERENCED_PARAMETER(not_used);
  UNREFERENCED_PARAMETER(cmd_lind);
  UNREFERENCED_PARAMETER(cmd_show);
  //
  CreateInvisibleWindow(instance_handle);
  //
  MorsePlayer morse_player;
  morse_player.Initialize();
  morse_player.dot_len_ = 60;
  // Command line is processed.
  for (int i = 1; i < __argc; ++i) {
    for (int j = 0; j < ELEMNUM_OPTIONS; ++j) {
      if (wcscmp(__wargv[i], kOptions[j]) == 0) {
        switch (j) {
          case OPTION_HELP:
            help_required = true;
            break;
          case OPTION_NOWINDOW:
            no_console = true;
            break;
          case OPTION_NOSOUND:
            no_sound = true;
            break;
          case OPTION_WPM:  // Same as OPTION_PARIS
          case OPTION_PARIS:
            /* wpm (paris) -> dot millis */
            morse_player.dot_len_ = 60000 / (_wtoi(__wargv[i + 1]) * 50);
            break;
          case OPTION_STRING:
            play_command_line_string = true;
            string_argc_offset = i + 1;
          default:
            break;
        }
      }
    }
  }
  // Win32 Console is initialized.
  if (!no_console) {
		if (!AttachConsole(ATTACH_PARENT_PROCESS)) AllocConsole();
    freopen("CON", "r", stdin);
    freopen("CON", "w", stdout);
  }
  // Argument num error check done.
  if (__argc <= 1) {
    if (no_console) {
      DialogError(L"No arguments specified");
      return -1;
    } else {
      PrintError(L"No arguments specified");
      goto ERROR_EXIT;
    }
  }
  // Help option process.
  if (help_required) {
    if (no_console) {
      DialogError(L"You must not set -nowindow option to show help");
      return 0;
    } else {
      wprintf(APP_NAME);
      wprintf(L"\n");
      wprintf(L"options:\n");
      for (int i = 0; i < ELEMNUM_OPTIONS; ++i) {
        wprintf(L"%s:\t%s\n", kOptions[i], kHelp[i]);
      }
      goto ERROR_EXIT;
    }
  }
  // String error.
  if (play_command_line_string == false) {
    if (no_console) {
      DialogError(L"No input string");
      return -1;
    } else {
      PrintError(L"No input string");
      goto ERROR_EXIT;
    }
  }
  // Morse generated
  int length = 0;
  for (int i = string_argc_offset; i < __argc; ++i) {
    length = wcslen(__wargv[i]);
    for (int j = 0; j < length; ++j) {
      ShowAndPlay(&morse_player, __wargv[i][j]);
      ShowAndPlay(&morse_player, L' ');
    }
    if (i != (__argc - 1)) {  // Word separator.
      ShowAndPlay(&morse_player, L' ');
      ShowAndPlay(&morse_player, L' ');
      ShowAndPlay(&morse_player, L' ');
    }
  }
  // Finalize console.
  if (!no_console) {
    system("PAUSE");
    FreeConsole();
  }
  morse_player.Finalize();
  return 0;
ERROR_EXIT:
  if (!no_console) {
    system("PAUSE");
    FreeConsole();
  }
  morse_player.Finalize();
  return -1;
}
void ShowAndPlay(MorsePlayer* morse_player, wchar_t charactor) {
  int morse_code = 0;
  switch (charactor) {
    case L'a': case L'A': morse_code = MORSE_A; break;
    case L'b': case L'B': morse_code = MORSE_B; break;
    case L'c': case L'C': morse_code = MORSE_C; break;
    case L'd': case L'D': morse_code = MORSE_D; break;
    case L'e': case L'E': morse_code = MORSE_E; break;
    case L'f': case L'F': morse_code = MORSE_F; break;
    case L'g': case L'G': morse_code = MORSE_G; break;
    case L'h': case L'H': morse_code = MORSE_H; break;
    case L'i': case L'I': morse_code = MORSE_I; break;
    case L'j': case L'J': morse_code = MORSE_J; break;
    case L'k': case L'K': morse_code = MORSE_K; break;
    case L'l': case L'L': morse_code = MORSE_L; break;
    case L'm': case L'M': morse_code = MORSE_M; break;
    case L'n': case L'N': morse_code = MORSE_N; break;
    case L'o': case L'O': morse_code = MORSE_O; break;
    case L'p': case L'P': morse_code = MORSE_P; break;
    case L'q': case L'Q': morse_code = MORSE_Q; break;
    case L'r': case L'R': morse_code = MORSE_R; break;
    case L's': case L'S': morse_code = MORSE_S; break;
    case L't': case L'T': morse_code = MORSE_T; break;
    case L'u': case L'U': morse_code = MORSE_U; break;
    case L'v': case L'V': morse_code = MORSE_V; break;
    case L'w': case L'W': morse_code = MORSE_W; break;
    case L'x': case L'X': morse_code = MORSE_X; break;
    case L'y': case L'Y': morse_code = MORSE_Y; break;
    case L'z': case L'Z': morse_code = MORSE_Z; break;
    case L'1': morse_code = MORSE_1; break;
    case L'2': morse_code = MORSE_2; break;
    case L'3': morse_code = MORSE_3; break;
    case L'4': morse_code = MORSE_4; break;
    case L'5': morse_code = MORSE_5; break;
    case L'6': morse_code = MORSE_6; break;
    case L'7': morse_code = MORSE_7; break;
    case L'8': morse_code = MORSE_8; break;
    case L'9': morse_code = MORSE_9; break;
    case L'0': morse_code = MORSE_0; break;
    case L'.': morse_code = MORSE_PER; break;
    case L',': morse_code = MORSE_COM; break;
    case L'?': morse_code = MORSE_QUE; break;
    case L'-': morse_code = MORSE_HIF; break;
    case L'/': morse_code = MORSE_SLA; break;
    case L'@': morse_code = MORSE_ATM; break;
    case L' ': morse_code = MORSE_SPACE; break;
    default: morse_code = MORSE_UNKNOWN; break;
  }
  // Morse shown to console.
  if (!no_console) morse_player->ShowSimbol(morse_code);
  // Sound played by device.
  if (!no_sound) morse_player->PlaySound(morse_code);
}
// Void callback function.
LRESULT CALLBACK WndProc(HWND wnd, UINT msg, WPARAM wp, LPARAM lp) {
  // Prevent warnings for unreferenced parameters.
  UNREFERENCED_PARAMETER(wnd);
  UNREFERENCED_PARAMETER(wp);
  UNREFERENCED_PARAMETER(lp);
  switch (msg) {
    case WM_DESTROY:
      PostQuitMessage(0);
      break;
    default:
      break;
  }
  return DefWindowProc(wnd, msg, wp, lp);
}
// Window is required to set icom on win32 application.
bool CreateInvisibleWindow(HINSTANCE instance_handle) {
  WNDCLASSEX wcex;
  // Window class registered.
  memset(&wcex, 0, sizeof(wcex));
  wcex.cbSize = sizeof(wcex);
  wcex.style = CS_HREDRAW | CS_VREDRAW;
  wcex.lpfnWndProc = WndProc;
  wcex.cbClsExtra = 0;
  wcex.cbWndExtra = 0;
  wcex.hInstance = instance_handle;
  wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
  wcex.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
  wcex.lpszMenuName = NULL;
  wcex.lpszClassName = APP_NAME;
  wcex.hIcon = LoadIcon(instance_handle, MAKEINTRESOURCE(IDI_ICON1));
  wcex.hIconSm = LoadIcon(instance_handle, MAKEINTRESOURCE(IDI_ICON1));
  if (RegisterClassEx(&wcex) == 0) return false;
  // Invisible window created.
  HWND window_handle = CreateWindow(APP_NAME, APP_NAME, WINDOW_STYLE,
                                    CW_USEDEFAULT, CW_USEDEFAULT, 256, 256,
                                    NULL, NULL, instance_handle, NULL);
  if (window_handle == NULL) return false;
  return true;
}
<|endoftext|>


<commit_before>// Lecture d'un fichier Rtstruct et conversion en vtkImageData, sortie en VTI
// \author Olivier Saut
#include <vector>
#include <map>

#include <vtkVersion.h>
// * Lecture du RTStruct
#include <vtkCellData.h>
#include <vtkGDCMPolyDataReader.h>
#include <vtkPolyDataWriter.h>
#include <vtkAppendPolyData.h>
#include <vtkSmartPointer.h>
#include <vtkXMLPolyDataWriter.h>
#include <vtkLinearExtrusionFilter.h>
#include <vtkImageGaussianSmooth.h>

// Ecriture en ImageData
#include <vtkPointData.h>
#include <vtkImageData.h>
#include <vtkXMLImageDataWriter.h>
#include <vtkPolyDataToImageStencil.h>
#include <vtkImageStencil.h>

std::string getPrefix(std::string str) {
    std::string relName=str.substr(str.find_last_of("/")+1);
    std::string prefix=relName.substr(0,relName.find_last_of("."));
    return prefix;
}

void stripSpace(std::string &str) {
    std::string resStr="";
        for (int i=0;i<str.length();++i) {
                if (str[i]!=' ')
                    resStr+=str[i];
                else
                    resStr+='_';
        }
    str=resStr;
}

void save_VTP_as_image(std::string name, vtkSmartPointer<vtkPolyData> polygon, std::string outDir) {
    vtkSmartPointer<vtkLinearExtrusionFilter> extrude=vtkSmartPointer<vtkLinearExtrusionFilter>::New();
    if(vtkVersion::GetVTKMajorVersion()>=6)
#if VTK_MAJOR_VERSION >= 6
        extrude->SetInputData(polygon);
#else
        extrude->SetInput(polygon);
#endif
    extrude->SetScaleFactor(12);
    extrude->SetExtrusionTypeToNormalExtrusion();
    extrude->SetVector(0,0,1);

    // ***
    // * Prparation de l'image
    // ***
    vtkSmartPointer<vtkImageData> image = vtkSmartPointer<vtkImageData>::New();
    double bounds[6]; polygon->GetBounds(bounds);
    double spacing[3] = {2, 2, 2};
    image->SetSpacing(spacing);

    int dim[3];
    for (int i = 0; i < 3; i++)
    {
        dim[i] = static_cast<int>(ceil(1.2*(bounds[i * 2 + 1] - bounds[i * 2]) / spacing[i]));
    }

    // dim[2]=1; Pour slectionner une tranche
    std::cout << "\t\tDimensions = " <<  dim[0] << "x" << dim[1] << "x" << dim[2] << std::endl;
    image->SetDimensions(dim);
    image->SetExtent(0, dim[0] - 1, 0, dim[1] - 1, 0, dim[2] - 1);

    double origin[3];
    // offset ?
    origin[0] = bounds[0] -0.1*(bounds[1]-bounds[0]); // spacing[0] / 2;
    origin[1] = bounds[2] -0.1*(bounds[3]-bounds[2]);//+ spacing[1] / 2;
    origin[2] = bounds[4] -0.1*(bounds[5]-bounds[4]);//+ spacing[2] / 2;
    std::cout <<  "\t\tOrigine = (" << origin[0] << ", " << origin[1] << ", " << origin[2] << ")" << std::endl;
    image->SetOrigin(origin);
#if VTK_MAJOR_VERSION >= 6
    image->AllocateScalars(VTK_FLOAT,1);
#else
    image->SetScalarTypeToFloat();
    image->AllocateScalars();
#endif
    // fill the image with foreground voxels:
    float inval = 255.0;
    float outval = 0;
    vtkIdType count = image->GetNumberOfPoints();
    for (vtkIdType i = 0; i < count; ++i)
    {
        image->GetPointData()->GetScalars()->SetTuple1(i, inval);
    }

    // ***
    // * Conversion
    // ***
    // On clippe l'image avec le polydata
    vtkSmartPointer<vtkPolyDataToImageStencil> conv=vtkSmartPointer<vtkPolyDataToImageStencil>::New();
#if VTK_MAJOR_VERSION >= 6
        conv->SetInputData(extrude->GetOutput());
#else
        conv->SetInput(extrude->GetOutput());
#endif

    conv->SetOutputOrigin(origin);
    conv->SetOutputSpacing(spacing);
    conv->SetTolerance(1e-6);
    conv->SetOutputWholeExtent(image->GetExtent());
    conv->Update();

    vtkSmartPointer<vtkImageStencil> stenc=vtkSmartPointer<vtkImageStencil>::New();
#if VTK_MAJOR_VERSION >= 6
        stenc->SetInputData(image);
        stenc->SetStencilData(conv->GetOutput());
#else
        stenc->SetInput(image);
        stenc->SetStencil(conv->GetOutput());
#endif
    stenc->ReverseStencilOff();
    stenc->SetBackgroundValue(outval);
    stenc->Update();

    // ***
    // * Ecriture sur le disque
    // ***

     // Lissage pour un joli rsultat
    vtkSmartPointer<vtkImageGaussianSmooth> gaussianSmoothFilter = vtkSmartPointer<vtkImageGaussianSmooth>::New();
    gaussianSmoothFilter->SetInputConnection(stenc->GetOutputPort());
    gaussianSmoothFilter->SetStandardDeviation(4.0);
    gaussianSmoothFilter->Update(); gaussianSmoothFilter->UpdateWholeExtent();

    // Ecriture en tant qu'image
    vtkSmartPointer<vtkXMLImageDataWriter> ww=vtkSmartPointer<vtkXMLImageDataWriter>::New();
    ww->SetFileName(std::string(outDir+"/"+name+".vti").c_str());
#if VTK_MAJOR_VERSION >= 6
        ww->SetInputData(gaussianSmoothFilter->GetOutput());
#else
        ww->SetInput(gaussianSmoothFilter->GetOutput());
#endif
    ww->Write();

}

// \brief Prend en argument le nom du fichier RTStruct
int main(int argc, char *argv[])
{
    if( argc < 2 )
    {
        std::cerr << argv[0] << " input.dcm (outdir)\n";
        return 1;
    }

    // ***
    // * Lecture de la structure
    // ***
    const char * filename = argv[1];
    vtkSmartPointer<vtkGDCMPolyDataReader> reader = vtkSmartPointer<vtkGDCMPolyDataReader>::New();
    reader->SetFileName( filename );
    reader->Update();

    std::string outDir = (argc>2) ? argv[2] : ".";

    vtkSmartPointer<vtkAppendPolyData> append = vtkSmartPointer<vtkAppendPolyData>::New();

    vtkSmartPointer<vtkXMLPolyDataWriter> writer = vtkSmartPointer<vtkXMLPolyDataWriter>::New();
    char fname[300]; std::string prefix=getPrefix(filename);
    int n = reader->GetNumberOfOutputPorts();
    std::map<std::string, vtkSmartPointer<vtkPolyData> > listePolys;
    for(int i = 0; i < n; ++i) {
        std::string port_name="";
        const int num_arrays_cell=reader->GetOutput(i)->GetCellData()->GetNumberOfArrays();
        if(num_arrays_cell>0)
            port_name= std::string(reader->GetOutput(i)->GetCellData()->GetArrayName(0));
        const int num_arrays_point=reader->GetOutput(i)->GetPointData()->GetNumberOfArrays();
        if(num_arrays_point>0)
            port_name= std::string(reader->GetOutput(i)->GetPointData()->GetArrayName(0));
        stripSpace(port_name);
        snprintf(fname, 300, "%s/%d-%s.vtp", outDir.data(), i, port_name.c_str());

        writer->SetFileName(fname);
#if VTK_MAJOR_VERSION >= 6
        writer->SetInputData(reader->GetOutput(i));
#else
        writer->SetInput(reader->GetOutput(i));
#endif
        listePolys.insert(std::pair<std::string, vtkSmartPointer<vtkPolyData> > (port_name, reader->GetOutput(i)));
        writer->Write();

#if VTK_MAJOR_VERSION >= 6
        append->AddInputData( reader->GetOutput(i) );
#else
        append->AddInput( reader->GetOutput(i) );
#endif
    }

    std::map<std::string, vtkSmartPointer<vtkPolyData> >::const_iterator it;
    for(it=listePolys.begin(); it!= listePolys.end();++it) {
        if(it->first != "") {
            std::cout << "\tSaving " << it->first << "..." << std::endl;
            save_VTP_as_image(it->first, it->second, outDir);
        }
    }

    return 0;
}
<commit_msg>Typo, an old if was preventing a connexion to extrude<commit_after>// Lecture d'un fichier Rtstruct et conversion en vtkImageData, sortie en VTI
// \author Olivier Saut
#include <vector>
#include <map>

#include <vtkVersion.h>
// * Lecture du RTStruct
#include <vtkCellData.h>
#include <vtkGDCMPolyDataReader.h>
#include <vtkPolyDataWriter.h>
#include <vtkAppendPolyData.h>
#include <vtkSmartPointer.h>
#include <vtkXMLPolyDataWriter.h>
#include <vtkLinearExtrusionFilter.h>
#include <vtkImageGaussianSmooth.h>

// Ecriture en ImageData
#include <vtkPointData.h>
#include <vtkImageData.h>
#include <vtkXMLImageDataWriter.h>
#include <vtkPolyDataToImageStencil.h>
#include <vtkImageStencil.h>

std::string getPrefix(std::string str) {
    std::string relName=str.substr(str.find_last_of("/")+1);
    std::string prefix=relName.substr(0,relName.find_last_of("."));
    return prefix;
}

void stripSpace(std::string &str) {
    std::string resStr="";
        for (int i=0;i<str.length();++i) {
                if (str[i]!=' ')
                    resStr+=str[i];
                else
                    resStr+='_';
        }
    str=resStr;
}

void save_VTP_as_image(std::string name, vtkSmartPointer<vtkPolyData> polygon, std::string outDir) {
    vtkSmartPointer<vtkLinearExtrusionFilter> extrude=vtkSmartPointer<vtkLinearExtrusionFilter>::New();
#if VTK_MAJOR_VERSION >= 6
        extrude->SetInputData(polygon);
#else
        extrude->SetInput(polygon);
#endif
    extrude->SetScaleFactor(12);
    extrude->SetExtrusionTypeToNormalExtrusion();
    extrude->SetVector(0,0,1);

    // ***
    // * Prparation de l'image
    // ***
    vtkSmartPointer<vtkImageData> image = vtkSmartPointer<vtkImageData>::New();
    double bounds[6]; polygon->GetBounds(bounds);
    double spacing[3] = {2, 2, 2};
    image->SetSpacing(spacing);

    int dim[3];
    for (int i = 0; i < 3; i++)
    {
        dim[i] = static_cast<int>(ceil(1.2*(bounds[i * 2 + 1] - bounds[i * 2]) / spacing[i]));
    }

    // dim[2]=1; Pour slectionner une tranche
    std::cout << "\t\tDimensions = " <<  dim[0] << "x" << dim[1] << "x" << dim[2] << std::endl;
    image->SetDimensions(dim);
    image->SetExtent(0, dim[0] - 1, 0, dim[1] - 1, 0, dim[2] - 1);

    double origin[3];
    // offset ?
    origin[0] = bounds[0] -0.1*(bounds[1]-bounds[0]); // spacing[0] / 2;
    origin[1] = bounds[2] -0.1*(bounds[3]-bounds[2]);//+ spacing[1] / 2;
    origin[2] = bounds[4] -0.1*(bounds[5]-bounds[4]);//+ spacing[2] / 2;
    std::cout <<  "\t\tOrigine = (" << origin[0] << ", " << origin[1] << ", " << origin[2] << ")" << std::endl;
    image->SetOrigin(origin);
#if VTK_MAJOR_VERSION >= 6
    image->AllocateScalars(VTK_FLOAT,1);
#else
    image->SetScalarTypeToFloat();
    image->AllocateScalars();
#endif
    // fill the image with foreground voxels:
    float inval = 255.0;
    float outval = 0;
    vtkIdType count = image->GetNumberOfPoints();
    for (vtkIdType i = 0; i < count; ++i)
    {
        image->GetPointData()->GetScalars()->SetTuple1(i, inval);
    }

    // ***
    // * Conversion
    // ***
    // On clippe l'image avec le polydata
    vtkSmartPointer<vtkPolyDataToImageStencil> conv=vtkSmartPointer<vtkPolyDataToImageStencil>::New();
#if VTK_MAJOR_VERSION >= 6
        conv->SetInputData(extrude->GetOutput());
#else
        conv->SetInput(extrude->GetOutput());
#endif

    conv->SetOutputOrigin(origin);
    conv->SetOutputSpacing(spacing);
    conv->SetTolerance(1e-6);
    conv->SetOutputWholeExtent(image->GetExtent());
    conv->Update();

    vtkSmartPointer<vtkImageStencil> stenc=vtkSmartPointer<vtkImageStencil>::New();
#if VTK_MAJOR_VERSION >= 6
        stenc->SetInputData(image);
        stenc->SetStencilData(conv->GetOutput());
#else
        stenc->SetInput(image);
        stenc->SetStencil(conv->GetOutput());
#endif
    stenc->ReverseStencilOff();
    stenc->SetBackgroundValue(outval);
    stenc->Update();

    // ***
    // * Ecriture sur le disque
    // ***

     // Lissage pour un joli rsultat
    vtkSmartPointer<vtkImageGaussianSmooth> gaussianSmoothFilter = vtkSmartPointer<vtkImageGaussianSmooth>::New();
    gaussianSmoothFilter->SetInputConnection(stenc->GetOutputPort());
    gaussianSmoothFilter->SetStandardDeviation(4.0);
    gaussianSmoothFilter->Update(); gaussianSmoothFilter->UpdateWholeExtent();

    // Ecriture en tant qu'image
    vtkSmartPointer<vtkXMLImageDataWriter> ww=vtkSmartPointer<vtkXMLImageDataWriter>::New();
    ww->SetFileName(std::string(outDir+"/"+name+".vti").c_str());
#if VTK_MAJOR_VERSION >= 6
        ww->SetInputData(gaussianSmoothFilter->GetOutput());
#else
        ww->SetInput(gaussianSmoothFilter->GetOutput());
#endif
    ww->Write();

}

// \brief Prend en argument le nom du fichier RTStruct
int main(int argc, char *argv[])
{
    if( argc < 2 )
    {
        std::cerr << argv[0] << " input.dcm (outdir)\n";
        return 1;
    }

    // ***
    // * Lecture de la structure
    // ***
    const char * filename = argv[1];
    vtkSmartPointer<vtkGDCMPolyDataReader> reader = vtkSmartPointer<vtkGDCMPolyDataReader>::New();
    reader->SetFileName( filename );
    reader->Update();

    std::string outDir = (argc>2) ? argv[2] : ".";

    vtkSmartPointer<vtkAppendPolyData> append = vtkSmartPointer<vtkAppendPolyData>::New();

    vtkSmartPointer<vtkXMLPolyDataWriter> writer = vtkSmartPointer<vtkXMLPolyDataWriter>::New();
    char fname[300]; std::string prefix=getPrefix(filename);
    int n = reader->GetNumberOfOutputPorts();
    std::map<std::string, vtkSmartPointer<vtkPolyData> > listePolys;
    for(int i = 0; i < n; ++i) {
        std::string port_name="";
        const int num_arrays_cell=reader->GetOutput(i)->GetCellData()->GetNumberOfArrays();
        if(num_arrays_cell>0)
            port_name= std::string(reader->GetOutput(i)->GetCellData()->GetArrayName(0));
        const int num_arrays_point=reader->GetOutput(i)->GetPointData()->GetNumberOfArrays();
        if(num_arrays_point>0)
            port_name= std::string(reader->GetOutput(i)->GetPointData()->GetArrayName(0));
        stripSpace(port_name);
        snprintf(fname, 300, "%s/%d-%s.vtp", outDir.data(), i, port_name.c_str());

        writer->SetFileName(fname);
#if VTK_MAJOR_VERSION >= 6
        writer->SetInputData(reader->GetOutput(i));
#else
        writer->SetInput(reader->GetOutput(i));
#endif
        listePolys.insert(std::pair<std::string, vtkSmartPointer<vtkPolyData> > (port_name, reader->GetOutput(i)));
        writer->Write();

#if VTK_MAJOR_VERSION >= 6
        append->AddInputData( reader->GetOutput(i) );
#else
        append->AddInput( reader->GetOutput(i) );
#endif
    }

    std::map<std::string, vtkSmartPointer<vtkPolyData> >::const_iterator it;
    for(it=listePolys.begin(); it!= listePolys.end();++it) {
        if(it->first != "") {
            std::cout << "\tSaving " << it->first << "..." << std::endl;
            save_VTP_as_image(it->first, it->second, outDir);
        }
    }

    return 0;
}
<|endoftext|>


<commit_before>#include <unistd.h>
#include <iostream>
#include <fstream>
#include <sstream>
#include <time.h>
#include <string.h>
using namespace std;

#include <FL/Fl.H>
#include <FL/Fl_Double_Window.H>
#include <FL/Fl_Output.H>
#include <FL/Fl_Box.H>
#include <FL/Fl_Button.H>
#include <FL/Fl_Value_Slider.H>
#include <FL/Fl_File_Chooser.H>
#include "Fl_Rotated_Text/Fl_Rotated_Text.H"
#include "cartesian/Cartesian.H"

#include "cvFltkWidget.hh"
#include "ffmpegInterface.hh"
#include "cameraSource.hh"

extern "C"
{
#include "wormProcessing.h"
}

#define DATA_FRAME_RATE_FPS     (1.0 / 15.0) /* I collect at 15 seconds per frame */
#define SETUP_FRAME_RATE_FPS    5
#define CIRCLE_RADIUS           50
#define CIRCLE_COLOR            CV_RGB(0xFF, 0, 0)
#define POINTED_CIRCLE_COLOR    CV_RGB(0, 0xFF, 0)

#define FRAME_W       480
#define FRAME_H       480
#define CROP_RECT     cvRect(80, 0, FRAME_W, FRAME_H)
#define WINDOW_W      1000
#define WINDOW_H      (FRAME_H + PLOT_H + X_AXIS_HEIGHT + AXIS_EXTRA_SPACE)
#define BUTTON_W      180
#define BUTTON_H      30
#define PLOT_W        (WINDOW_W - (Y_AXIS_WIDTH + AXIS_EXTRA_SPACE))
#define PLOT_H        400
#define X_AXIS_HEIGHT 30
#define Y_AXIS_WIDTH  80
#define ACCUM_W       180
#define ACCUM_H       BUTTON_H

// due to a bug (most likely), the axis aren't drawn completely inside their box. Thus I leave a bit
// of extra space to see the labels
#define AXIS_EXTRA_SPACE 40

#define AM_READING_CAMERA (dynamic_cast<CameraSource*>(source) != NULL)

static FrameSource*  source;
static CvFltkWidget* widgetImage;
static Fl_Button*    goResetButton;
static Ca_Canvas*    plot = NULL;
static Ca_X_Axis*    Xaxis;
static Ca_Y_Axis*    Yaxis;

static Fl_Output* leftAccum;
static Fl_Output* rightAccum;
static double     leftAccumValue  = 0.0;
static double     rightAccumValue = 0.0;

// the analysis could be idle, running, or idle examining data (STOPPED)
static enum { RESET, RUNNING, STOPPED } analysisState;

static int           numPoints;
static Ca_LinePoint* lastLeftPoint       = NULL;
static Ca_LinePoint* lastRightPoint      = NULL;
static CvPoint       leftCircleCenter    = cvPoint(-1, -1);
static CvPoint       rightCircleCenter   = cvPoint(-1, -1);
static CvPoint       pointedCircleCenter = cvPoint(-1, -1);

#define HAVE_LEFT_CIRCLE    (leftCircleCenter .x > 0 && leftCircleCenter .y > 0)
#define HAVE_RIGHT_CIRCLE   (rightCircleCenter.x > 0 && rightCircleCenter.y > 0)
#define HAVE_CIRCLES        (HAVE_LEFT_CIRCLE && HAVE_RIGHT_CIRCLE)
#define HAVE_POINTED_CIRCLE (pointedCircleCenter.x > 0 && pointedCircleCenter.y > 0)

static void setStoppedAnalysis(void);

static bool gotNewFrame(IplImage* buffer, uint64_t timestamp_us __attribute__((unused)))
{
    if(buffer == NULL)
    {
        if(!AM_READING_CAMERA)
        {
            // error ocurred reading the stored video. I likely reached the end of the file. I stop
            // the analysis if I'm running it and rewind the stream
            source->restartStream();
            if(analysisState == RUNNING)
            {
                goResetButton->value(0);
                setStoppedAnalysis();
            }
            return true;
        }
        return false;
    }

    cvMerge(buffer, buffer, buffer, NULL, *widgetImage);

    const CvMat* result = isolateWorms(buffer);
    cvSetImageCOI(*widgetImage, 1);
    cvCopy(result, *widgetImage);
    cvSetImageCOI(*widgetImage, 0);

    if(HAVE_LEFT_CIRCLE)
        cvCircle(*widgetImage, leftCircleCenter,    CIRCLE_RADIUS, CIRCLE_COLOR, 1, 8);

    if(HAVE_RIGHT_CIRCLE)
        cvCircle(*widgetImage, rightCircleCenter,   CIRCLE_RADIUS, CIRCLE_COLOR, 1, 8);

    if(HAVE_POINTED_CIRCLE)
        cvCircle(*widgetImage, pointedCircleCenter, CIRCLE_RADIUS, POINTED_CIRCLE_COLOR, 1, 8);

    // This critical section is likely larger than it needs to be, but this keeps me safe. The
    // analysis state can change in the FLTK thread, so I err on the side of safety
    Fl::lock();
    {
        if(analysisState == RUNNING)
        {
            double minutes = (double)numPoints / DATA_FRAME_RATE_FPS / 60.0;
            double leftOccupancy, rightOccupancy;
            computeWormOccupancy(result, &leftCircleCenter, &rightCircleCenter,
                                 CIRCLE_RADIUS,
                                 &leftOccupancy, &rightOccupancy);

            Yaxis->rescale(CA_WHEN_MAX, fmax(leftOccupancy, rightOccupancy) );

            lastLeftPoint  = new Ca_LinePoint(lastLeftPoint,
                                              minutes,
                                              leftOccupancy,  1,FL_RED,   CA_NO_POINT);
            lastRightPoint = new Ca_LinePoint(lastRightPoint,
                                              minutes,
                                              rightOccupancy, 1,FL_GREEN, CA_NO_POINT);
            Xaxis->maximum(minutes);
            numPoints++;

            leftAccumValue  += leftOccupancy  / DATA_FRAME_RATE_FPS;
            rightAccumValue += rightOccupancy / DATA_FRAME_RATE_FPS;
            char results[128];
            snprintf(results, sizeof(results), "%.3f", leftAccumValue);
            leftAccum->value(results);
            snprintf(results, sizeof(results), "%.3f", rightAccumValue);
            rightAccum->value(results);
        }

        widgetImage->redrawNewFrame();
    }

    if(!AM_READING_CAMERA && analysisState != RUNNING)
    {
        Fl::unlock();

        // reading from a video file and not actually running the analysis yet. In this case I
        // rewind back to the beginning and delay, to force a reasonable refresh rate
        source->restartStream();

        struct timespec tv;
        tv.tv_sec  = 0;
        tv.tv_nsec = 1e9 / SETUP_FRAME_RATE_FPS;
        nanosleep(&tv, NULL);
    }
    else
        Fl::unlock();

    return true;
}

static void widgetImageCallback(Fl_Widget* widget __attribute__((unused)), void* cookie __attribute__((unused)))
{
    if(Fl::event() == FL_LEAVE)
    {
        // I want to make sure to never miss this, so I handle it unconditionally
        pointedCircleCenter.x = pointedCircleCenter.y = -1;
        return;
    }

    if(analysisState == RUNNING)
    {
        pointedCircleCenter.x = pointedCircleCenter.y = -1;
        return;
    }

    bool onLeftHalf = (Fl::event_x() - widget->x()) < FRAME_W/2;
    switch(Fl::event())
    {
    case FL_MOVE:
        pointedCircleCenter.x = Fl::event_x() - widget->x();
        pointedCircleCenter.y = Fl::event_y() - widget->y();
        break;

    case FL_LEAVE:
        pointedCircleCenter.x = pointedCircleCenter.y = -1;
        break;

    case FL_PUSH:
        if(onLeftHalf)
        {
            leftCircleCenter.x = Fl::event_x() - widget->x();
            leftCircleCenter.y = Fl::event_y() - widget->y();
        }
        else
        {
            rightCircleCenter.x = Fl::event_x() - widget->x();
            rightCircleCenter.y = Fl::event_y() - widget->y();
        }

        pointedCircleCenter.x = pointedCircleCenter.y = -1;
        break;

    default: ;
    }

    if(HAVE_CIRCLES && analysisState == RESET)
        goResetButton->activate();
}

static void setResetAnalysis(void)
{
    goResetButton->labelfont(FL_HELVETICA_BOLD);
    goResetButton->labelcolor(FL_RED);
    goResetButton->type(FL_TOGGLE_BUTTON);
    goResetButton->label("Analyze");

    numPoints       = 0;
    if(plot) plot->clear();
    lastLeftPoint   = lastRightPoint = NULL;
    leftAccumValue  = 0.0;
    rightAccumValue = 0.0;
    leftAccum ->value("0.0");
    rightAccum->value("0.0");

    if(!AM_READING_CAMERA)
        source->restartStream();

    analysisState = RESET;
}

static void setRunningAnalysis(void)
{
    goResetButton->labelfont(FL_HELVETICA);
    goResetButton->labelcolor(FL_BLACK);
    goResetButton->type(FL_TOGGLE_BUTTON);
    goResetButton->label("Stop analysis");

    pointedCircleCenter.x = pointedCircleCenter.y = -1;

    analysisState = RUNNING;
}

static void setStoppedAnalysis(void)
{
    goResetButton->labelfont(FL_HELVETICA);
    goResetButton->labelcolor(FL_BLACK);
    goResetButton->type(FL_NORMAL_BUTTON);
    goResetButton->label("Reset analysis data");

    analysisState = STOPPED;
}

static void pressedGoReset(Fl_Widget* widget __attribute__((unused)), void* cookie __attribute__((unused)))
{
    if     (analysisState == RUNNING) setStoppedAnalysis();
    else if(analysisState == STOPPED) setResetAnalysis();
    else                              setRunningAnalysis();
}

int main(int argc, char* argv[])
{
    Fl::lock();
    Fl::visual(FL_RGB);

    // open the first source. If there's an argument, assume it's an input video. Otherwise, try
    // reading a camera
    if(argc >= 2) source = new FFmpegDecoder(argv[1], FRAMESOURCE_GRAYSCALE, false, CROP_RECT);
    else          source = new CameraSource (FRAMESOURCE_GRAYSCALE, false, 0, CROP_RECT);

    if(! *source)
    {
        fprintf(stderr, "couldn't open source\n");
        delete source;
        return 0;
    }

    Fl_Double_Window* window =
        new Fl_Double_Window(WINDOW_W, WINDOW_H, "Wormtracker 3");
    widgetImage = new CvFltkWidget(0, 0, source->w(), source->h(),
                                   WIDGET_COLOR);

    widgetImage->callback(widgetImageCallback);

    goResetButton = new Fl_Button( widgetImage->w(), 0, BUTTON_W, BUTTON_H);
    goResetButton->callback(pressedGoReset);
    goResetButton->deactivate();

    plot = new Ca_Canvas( Y_AXIS_WIDTH + AXIS_EXTRA_SPACE, widgetImage->y() + widgetImage->h(),
                          PLOT_W, PLOT_H,
                          "Worm occupancy");
    plot->align(FL_ALIGN_TOP);

    // This is extremely important for some reason. Without it the plots do not refresh property and
    // there're artifacts every time the plot is resized
    plot->box(FL_DOWN_BOX);

    Xaxis = new Ca_X_Axis(plot->x(), plot->y() + plot->h(), plot->w(), X_AXIS_HEIGHT, "Minutes");
    Xaxis->align(FL_ALIGN_BOTTOM);
    Xaxis->minimum(0);
    Xaxis->maximum(1);
    Xaxis->label_format("%g");
    Xaxis->major_step(10);
    Xaxis->label_step(10);
    Xaxis->axis_color(FL_BLACK);
    Xaxis->axis_align(CA_BOTTOM | CA_LINE);

    Yaxis = new Ca_Y_Axis(AXIS_EXTRA_SPACE, plot->y(), Y_AXIS_WIDTH, plot->h());
    Fl_Rotated_Text YaxisLabel("occupancy ratio", FL_HELVETICA, 14, 0, 1);
    Yaxis->image(&YaxisLabel);
    Yaxis->minimum(0);
    Yaxis->maximum(0.01);
    Yaxis->align(FL_ALIGN_LEFT);
    Yaxis->axis_align(CA_LEFT | CA_LINE);
    Yaxis->axis_color(FL_BLACK);

    leftAccum  = new Fl_Output(widgetImage->x() + widgetImage->w(), goResetButton->y() + goResetButton->h(),
                              ACCUM_W, ACCUM_H, "Left accumulator (occupancy-seconds)");
    rightAccum = new Fl_Output(leftAccum->x(), leftAccum->y() + leftAccum->h(),
                              ACCUM_W, ACCUM_H, "Right accumulator (occupancy-seconds)");
    leftAccum ->align(FL_ALIGN_RIGHT);
    rightAccum->align(FL_ALIGN_RIGHT);
    leftAccum ->labelcolor(FL_RED);
    rightAccum->labelcolor(FL_GREEN);

    window->end();
    window->show();

    processingInit(source->w(), source->h());

    setResetAnalysis();

    // I read the data with a tiny delay. This makes sure that I skip old frames (only an issue if I
    // can't keep up with the data rate), but yet got as fast as I can
    IplImage* buffer = cvCreateImage(cvSize(source->w(), source->h()), IPL_DEPTH_8U, 1);

    // If reading from a stored video file, go as fast as possible
    if(AM_READING_CAMERA) source->startSourceThread(&gotNewFrame, 1e6/DATA_FRAME_RATE_FPS, buffer);
    else                  source->startSourceThread(&gotNewFrame, 0,                       buffer);

    while (Fl::wait())
    {
    }

    Fl::unlock();

    delete source;
    delete window;
    cvReleaseImage(&buffer);

    processingCleanup();
    return 0;
}
<commit_msg>I'm now opening a specific camera, as given on the cmdline<commit_after>#include <unistd.h>
#include <iostream>
#include <fstream>
#include <sstream>
#include <time.h>
#include <string.h>
#include <assert.h>
using namespace std;

#include <FL/Fl.H>
#include <Fl/fl_ask.H>
#include <FL/Fl_Double_Window.H>
#include <FL/Fl_Output.H>
#include <FL/Fl_Box.H>
#include <FL/Fl_Button.H>
#include <FL/Fl_Value_Slider.H>
#include <FL/Fl_File_Chooser.H>
#include "Fl_Rotated_Text/Fl_Rotated_Text.H"
#include "cartesian/Cartesian.H"

#include "cvFltkWidget.hh"
#include "ffmpegInterface.hh"
#include "cameraSource.hh"

extern "C"
{
#include "wormProcessing.h"
}

#define DATA_FRAME_RATE_FPS     (1.0 / 15.0) /* I collect at 15 seconds per frame */
#define SETUP_FRAME_RATE_FPS    5
#define CIRCLE_RADIUS           50
#define CIRCLE_COLOR            CV_RGB(0xFF, 0, 0)
#define POINTED_CIRCLE_COLOR    CV_RGB(0, 0xFF, 0)

#define FRAME_W       480
#define FRAME_H       480
#define CROP_RECT     cvRect(80, 0, FRAME_W, FRAME_H)
#define WINDOW_W      1000
#define WINDOW_H      (FRAME_H + PLOT_H + X_AXIS_HEIGHT + AXIS_EXTRA_SPACE)
#define BUTTON_W      180
#define BUTTON_H      30
#define PLOT_W        (WINDOW_W - (Y_AXIS_WIDTH + AXIS_EXTRA_SPACE))
#define PLOT_H        400
#define X_AXIS_HEIGHT 30
#define Y_AXIS_WIDTH  80
#define ACCUM_W       180
#define ACCUM_H       BUTTON_H

// due to a bug (most likely), the axis aren't drawn completely inside their box. Thus I leave a bit
// of extra space to see the labels
#define AXIS_EXTRA_SPACE 40

#define AM_READING_CAMERA (dynamic_cast<CameraSource*>(source) != NULL)

static FrameSource*  source;
static CvFltkWidget* widgetImage;
static Fl_Button*    goResetButton;
static Ca_Canvas*    plot = NULL;
static Ca_X_Axis*    Xaxis;
static Ca_Y_Axis*    Yaxis;

static Fl_Output* leftAccum;
static Fl_Output* rightAccum;
static double     leftAccumValue  = 0.0;
static double     rightAccumValue = 0.0;

// the analysis could be idle, running, or idle examining data (STOPPED)
static enum { RESET, RUNNING, STOPPED } analysisState;

static int           numPoints;
static Ca_LinePoint* lastLeftPoint       = NULL;
static Ca_LinePoint* lastRightPoint      = NULL;
static CvPoint       leftCircleCenter    = cvPoint(-1, -1);
static CvPoint       rightCircleCenter   = cvPoint(-1, -1);
static CvPoint       pointedCircleCenter = cvPoint(-1, -1);

#define HAVE_LEFT_CIRCLE    (leftCircleCenter .x > 0 && leftCircleCenter .y > 0)
#define HAVE_RIGHT_CIRCLE   (rightCircleCenter.x > 0 && rightCircleCenter.y > 0)
#define HAVE_CIRCLES        (HAVE_LEFT_CIRCLE && HAVE_RIGHT_CIRCLE)
#define HAVE_POINTED_CIRCLE (pointedCircleCenter.x > 0 && pointedCircleCenter.y > 0)

static void setStoppedAnalysis(void);

static bool gotNewFrame(IplImage* buffer, uint64_t timestamp_us __attribute__((unused)))
{
    if(buffer == NULL)
    {
        if(!AM_READING_CAMERA)
        {
            // error ocurred reading the stored video. I likely reached the end of the file. I stop
            // the analysis if I'm running it and rewind the stream
            source->restartStream();
            if(analysisState == RUNNING)
            {
                goResetButton->value(0);
                setStoppedAnalysis();
            }
            return true;
        }
        return false;
    }

    cvMerge(buffer, buffer, buffer, NULL, *widgetImage);

    const CvMat* result = isolateWorms(buffer);
    cvSetImageCOI(*widgetImage, 1);
    cvCopy(result, *widgetImage);
    cvSetImageCOI(*widgetImage, 0);

    if(HAVE_LEFT_CIRCLE)
        cvCircle(*widgetImage, leftCircleCenter,    CIRCLE_RADIUS, CIRCLE_COLOR, 1, 8);

    if(HAVE_RIGHT_CIRCLE)
        cvCircle(*widgetImage, rightCircleCenter,   CIRCLE_RADIUS, CIRCLE_COLOR, 1, 8);

    if(HAVE_POINTED_CIRCLE)
        cvCircle(*widgetImage, pointedCircleCenter, CIRCLE_RADIUS, POINTED_CIRCLE_COLOR, 1, 8);

    // This critical section is likely larger than it needs to be, but this keeps me safe. The
    // analysis state can change in the FLTK thread, so I err on the side of safety
    Fl::lock();
    {
        if(analysisState == RUNNING)
        {
            double minutes = (double)numPoints / DATA_FRAME_RATE_FPS / 60.0;
            double leftOccupancy, rightOccupancy;
            computeWormOccupancy(result, &leftCircleCenter, &rightCircleCenter,
                                 CIRCLE_RADIUS,
                                 &leftOccupancy, &rightOccupancy);

            Yaxis->rescale(CA_WHEN_MAX, fmax(leftOccupancy, rightOccupancy) );

            lastLeftPoint  = new Ca_LinePoint(lastLeftPoint,
                                              minutes,
                                              leftOccupancy,  1,FL_RED,   CA_NO_POINT);
            lastRightPoint = new Ca_LinePoint(lastRightPoint,
                                              minutes,
                                              rightOccupancy, 1,FL_GREEN, CA_NO_POINT);
            Xaxis->maximum(minutes);
            numPoints++;

            leftAccumValue  += leftOccupancy  / DATA_FRAME_RATE_FPS;
            rightAccumValue += rightOccupancy / DATA_FRAME_RATE_FPS;
            char results[128];
            snprintf(results, sizeof(results), "%.3f", leftAccumValue);
            leftAccum->value(results);
            snprintf(results, sizeof(results), "%.3f", rightAccumValue);
            rightAccum->value(results);
        }

        widgetImage->redrawNewFrame();
    }

    if(!AM_READING_CAMERA && analysisState != RUNNING)
    {
        Fl::unlock();

        // reading from a video file and not actually running the analysis yet. In this case I
        // rewind back to the beginning and delay, to force a reasonable refresh rate
        source->restartStream();

        struct timespec tv;
        tv.tv_sec  = 0;
        tv.tv_nsec = 1e9 / SETUP_FRAME_RATE_FPS;
        nanosleep(&tv, NULL);
    }
    else
        Fl::unlock();

    return true;
}

static void widgetImageCallback(Fl_Widget* widget __attribute__((unused)), void* cookie __attribute__((unused)))
{
    if(Fl::event() == FL_LEAVE)
    {
        // I want to make sure to never miss this, so I handle it unconditionally
        pointedCircleCenter.x = pointedCircleCenter.y = -1;
        return;
    }

    if(analysisState == RUNNING)
    {
        pointedCircleCenter.x = pointedCircleCenter.y = -1;
        return;
    }

    bool onLeftHalf = (Fl::event_x() - widget->x()) < FRAME_W/2;
    switch(Fl::event())
    {
    case FL_MOVE:
        pointedCircleCenter.x = Fl::event_x() - widget->x();
        pointedCircleCenter.y = Fl::event_y() - widget->y();
        break;

    case FL_LEAVE:
        pointedCircleCenter.x = pointedCircleCenter.y = -1;
        break;

    case FL_PUSH:
        if(onLeftHalf)
        {
            leftCircleCenter.x = Fl::event_x() - widget->x();
            leftCircleCenter.y = Fl::event_y() - widget->y();
        }
        else
        {
            rightCircleCenter.x = Fl::event_x() - widget->x();
            rightCircleCenter.y = Fl::event_y() - widget->y();
        }

        pointedCircleCenter.x = pointedCircleCenter.y = -1;
        break;

    default: ;
    }

    if(HAVE_CIRCLES && analysisState == RESET)
        goResetButton->activate();
}

static void setResetAnalysis(void)
{
    goResetButton->labelfont(FL_HELVETICA_BOLD);
    goResetButton->labelcolor(FL_RED);
    goResetButton->type(FL_TOGGLE_BUTTON);
    goResetButton->label("Analyze");

    numPoints       = 0;
    if(plot) plot->clear();
    lastLeftPoint   = lastRightPoint = NULL;
    leftAccumValue  = 0.0;
    rightAccumValue = 0.0;
    leftAccum ->value("0.0");
    rightAccum->value("0.0");

    if(!AM_READING_CAMERA)
        source->restartStream();

    analysisState = RESET;
}

static void setRunningAnalysis(void)
{
    goResetButton->labelfont(FL_HELVETICA);
    goResetButton->labelcolor(FL_BLACK);
    goResetButton->type(FL_TOGGLE_BUTTON);
    goResetButton->label("Stop analysis");

    pointedCircleCenter.x = pointedCircleCenter.y = -1;

    analysisState = RUNNING;
}

static void setStoppedAnalysis(void)
{
    goResetButton->labelfont(FL_HELVETICA);
    goResetButton->labelcolor(FL_BLACK);
    goResetButton->type(FL_NORMAL_BUTTON);
    goResetButton->label("Reset analysis data");

    analysisState = STOPPED;
}

static void pressedGoReset(Fl_Widget* widget __attribute__((unused)), void* cookie __attribute__((unused)))
{
    if     (analysisState == RUNNING) setStoppedAnalysis();
    else if(analysisState == STOPPED) setResetAnalysis();
    else                              setRunningAnalysis();
}

int main(int argc, char* argv[])
{
    Fl::lock();
    Fl::visual(FL_RGB);

    // To load a video file, the last cmdline argument must be the file.
    // To read a camera, the last cmdline argument must be 0x..., we use it as the camera GUID
    // Otherwise we try to load any camera
    if(argc < 2)
    {
        source = new CameraSource (FRAMESOURCE_GRAYSCALE, false, 0, CROP_RECT);
    }
    else if(strncmp(argv[argc-1], "0x", 2) == 0)
    {
        assert(sizeof(long long unsigned int) == sizeof(uint64_t));

        uint64_t guid;
        sscanf(&argv[argc-1][2], "%llx", (long long unsigned int*)&guid);
        source = new CameraSource(FRAMESOURCE_GRAYSCALE, false, guid, CROP_RECT);
    }
    else
        source = new FFmpegDecoder(argv[argc-1], FRAMESOURCE_GRAYSCALE, false, CROP_RECT);

    if(! *source)
    {
        fprintf(stderr, "couldn't open source\n");
        delete source;
        return 0;
    }

    Fl_Double_Window* window =
        new Fl_Double_Window(WINDOW_W, WINDOW_H, "Wormtracker 3");
    widgetImage = new CvFltkWidget(0, 0, source->w(), source->h(),
                                   WIDGET_COLOR);

    widgetImage->callback(widgetImageCallback);

    goResetButton = new Fl_Button( widgetImage->w(), 0, BUTTON_W, BUTTON_H);
    goResetButton->callback(pressedGoReset);
    goResetButton->deactivate();

    plot = new Ca_Canvas( Y_AXIS_WIDTH + AXIS_EXTRA_SPACE, widgetImage->y() + widgetImage->h(),
                          PLOT_W, PLOT_H,
                          "Worm occupancy");
    plot->align(FL_ALIGN_TOP);

    // This is extremely important for some reason. Without it the plots do not refresh property and
    // there're artifacts every time the plot is resized
    plot->box(FL_DOWN_BOX);

    Xaxis = new Ca_X_Axis(plot->x(), plot->y() + plot->h(), plot->w(), X_AXIS_HEIGHT, "Minutes");
    Xaxis->align(FL_ALIGN_BOTTOM);
    Xaxis->minimum(0);
    Xaxis->maximum(1);
    Xaxis->label_format("%g");
    Xaxis->major_step(10);
    Xaxis->label_step(10);
    Xaxis->axis_color(FL_BLACK);
    Xaxis->axis_align(CA_BOTTOM | CA_LINE);

    Yaxis = new Ca_Y_Axis(AXIS_EXTRA_SPACE, plot->y(), Y_AXIS_WIDTH, plot->h());
    Fl_Rotated_Text YaxisLabel("occupancy ratio", FL_HELVETICA, 14, 0, 1);
    Yaxis->image(&YaxisLabel);
    Yaxis->minimum(0);
    Yaxis->maximum(0.01);
    Yaxis->align(FL_ALIGN_LEFT);
    Yaxis->axis_align(CA_LEFT | CA_LINE);
    Yaxis->axis_color(FL_BLACK);

    leftAccum  = new Fl_Output(widgetImage->x() + widgetImage->w(), goResetButton->y() + goResetButton->h(),
                              ACCUM_W, ACCUM_H, "Left accumulator (occupancy-seconds)");
    rightAccum = new Fl_Output(leftAccum->x(), leftAccum->y() + leftAccum->h(),
                              ACCUM_W, ACCUM_H, "Right accumulator (occupancy-seconds)");
    leftAccum ->align(FL_ALIGN_RIGHT);
    rightAccum->align(FL_ALIGN_RIGHT);
    leftAccum ->labelcolor(FL_RED);
    rightAccum->labelcolor(FL_GREEN);

    window->end();
    window->show();

    processingInit(source->w(), source->h());

    setResetAnalysis();

    // I read the data with a tiny delay. This makes sure that I skip old frames (only an issue if I
    // can't keep up with the data rate), but yet got as fast as I can
    IplImage* buffer = cvCreateImage(cvSize(source->w(), source->h()), IPL_DEPTH_8U, 1);

    // If reading from a stored video file, go as fast as possible
    if(AM_READING_CAMERA) source->startSourceThread(&gotNewFrame, 1e6/DATA_FRAME_RATE_FPS, buffer);
    else                  source->startSourceThread(&gotNewFrame, 0,                       buffer);

    while (Fl::wait())
    {
    }

    Fl::unlock();

    delete source;
    delete window;
    cvReleaseImage(&buffer);

    processingCleanup();
    return 0;
}
<|endoftext|>


<commit_before>/*Code by Dmitry Khovratovich, 2016
CC0 license
*/

#include "pow.h"
#include "blake/blake2.h"
#include <algorithm>

static uint64_t rdtsc(void) {
#ifdef _MSC_VER
    return __rdtsc();
#else
#if defined(__amd64__) || defined(__x86_64__)
    uint64_t rax, rdx;
    __asm__ __volatile__("rdtsc" : "=a"(rax), "=d"(rdx) : : );
    return (rdx << 32) | rax;
#elif defined(__i386__) || defined(__i386) || defined(__X86__)
    uint64_t rax;
    __asm__ __volatile__("rdtsc" : "=A"(rax) : : );
    return rax;
#else
#error "Not implemented!"
#endif
#endif
}

using namespace _POW;
using namespace std;

void Equihash::InitializeMemory()
{
    uint32_t  tuple_n = ((uint32_t)1) << (n / (k + 1));
    Tuple default_tuple(k); // k blocks to store (one left for index)
    std::vector<Tuple> def_tuples(LIST_LENGTH, default_tuple);
    tupleList = std::vector<std::vector<Tuple>>(tuple_n, def_tuples);
    filledList= std::vector<unsigned>(tuple_n, 0);
    solutions.resize(0);
    forks.resize(0);
}

void Equihash::PrintTuples(FILE* fp) {
    unsigned count = 0;
    for (unsigned i = 0; i < tupleList.size(); ++i) {
        for (unsigned m = 0; m < filledList[i]; ++m) {
            fprintf(fp, "[%d][%d]:", i,m);
            for (unsigned j = 0; j < tupleList[i][m].blocks.size(); ++j)
                fprintf(fp, " %x ", tupleList[i][m].blocks[j]);
            fprintf(fp, " || %x", tupleList[i][m].reference);
            fprintf(fp, " |||| ");
        }
        count += filledList[i];
        fprintf(fp, "\n");
    }
    fprintf(fp, "TOTAL: %d elements printed", count);
}

void Equihash::FillMemory(uint32_t length) //works for k<=7
{
    uint32_t input[SEED_LENGTH + 2];
    for (unsigned i = 0; i < SEED_LENGTH; ++i)
        input[i] = seed[i];
    input[SEED_LENGTH] = nonce;
    input[SEED_LENGTH + 1] = 0;
    uint32_t buf[MAX_N / 4];
    for (unsigned i = 0; i < length; ++i, ++input[SEED_LENGTH + 1]) {
        blake2b((uint8_t*)buf, &input, NULL, sizeof(buf), sizeof(input), 0);
        uint32_t index = buf[0] >> (32 - n / (k + 1));
        unsigned count = filledList[index];
        if (count < LIST_LENGTH) {
            for (unsigned j = 1; j < (k + 1); ++j) {
                //select j-th block of n/(k+1) bits
                tupleList[index][count].blocks[j - 1] = buf[j] >> (32 - n / (k + 1));
            }
            tupleList[index][count].reference = i;
            filledList[index]++;
        }
    }
}

std::vector<Input> Equihash::ResolveTreeByLevel(Fork fork, unsigned level) {
    if (level == 0)
        return std::vector<Input>{fork.ref1, fork.ref2};
    auto v1 = ResolveTreeByLevel(forks[level - 1][fork.ref1], level - 1);
    auto v2 = ResolveTreeByLevel(forks[level - 1][fork.ref2], level - 1);
    v1.insert(v1.end(), v2.begin(), v2.end());
    return v1;
}

std::vector<Input> Equihash::ResolveTree(Fork fork) {
    return ResolveTreeByLevel(fork, forks.size());
}

void Equihash::ResolveCollisions(bool store) {
    const unsigned tableLength = tupleList.size();  //number of rows in the hashtable
    const unsigned maxNewCollisions = tupleList.size()*FORK_MULTIPLIER;  //max number of collisions to be found
    const unsigned newBlocks = tupleList[0][0].blocks.size() - 1;// number of blocks in the future collisions
    std::vector<Fork> newForks(maxNewCollisions); //list of forks created at this step
    auto tableRow = vector<Tuple>(LIST_LENGTH, Tuple(newBlocks)); //Row in the hash table
    vector<vector<Tuple>> collisionList(tableLength,tableRow);
    std::vector<unsigned> newFilledList(tableLength,0);  //number of entries in rows
    uint32_t newColls = 0; //collision counter
    for (unsigned i = 0; i < tableLength; ++i) {
        for (unsigned j = 0; j < filledList[i]; ++j)        {
            for (unsigned m = j + 1; m < filledList[i]; ++m) {   //Collision
                //New index
                uint32_t newIndex = tupleList[i][j].blocks[0] ^ tupleList[i][m].blocks[0];
                Fork newFork = Fork(tupleList[i][j].reference, tupleList[i][m].reference);
                //Check if we get a solution
                if (store) {  //last step
                    if (newIndex == 0) {//Solution
                        std::vector<Input> solution_inputs = ResolveTree(newFork);
                        solutions.push_back(Proof(n, k, seed, nonce, solution_inputs));
                    }
                }
                else {         //Resolve
                    if (newFilledList[newIndex] < LIST_LENGTH && newColls < maxNewCollisions) {
                        for (unsigned l = 0; l < newBlocks; ++l) {
                            collisionList[newIndex][newFilledList[newIndex]].blocks[l]
                                = tupleList[i][j].blocks[l+1] ^ tupleList[i][m].blocks[l+1];
                        }
                        newForks[newColls] = newFork;
                        collisionList[newIndex][newFilledList[newIndex]].reference = newColls;
                        newFilledList[newIndex]++;
                        newColls++;
                    }//end of adding collision
                }
            }
        }//end of collision for i
    }
    forks.push_back(newForks);
    std::swap(tupleList, collisionList);
    std::swap(filledList, newFilledList);
}

Proof Equihash::FindProof(){
    FILE* fp = fopen("proof.log", "w+");
    fclose(fp);
    this->nonce = 1;
    while (nonce < MAX_NONCE) {
        nonce++;
        printf("Testing nonce %d\n", nonce);
        uint64_t start_cycles = rdtsc();
        InitializeMemory(); //allocate
        FillMemory(5UL << (n / (k + 1)-1));   //fill with hashes
        uint64_t fill_end = rdtsc();
        printf("Filling %2.2f  Mcycles \n", (double)(fill_end - start_cycles) / (1UL << 20));
        /*fp = fopen("proof.log", "a+");
        fprintf(fp, "\n===MEMORY FILLED:\n");
        PrintTuples(fp);
        fclose(fp);*/
        for (unsigned i = 1; i <= k; ++i) {
            uint64_t resolve_start = rdtsc();
            bool to_store = (i == k);
            ResolveCollisions(to_store); //XOR collisions, concatenate indices and shift
            uint64_t resolve_end = rdtsc();
            printf("Resolving %2.2f  Mcycles \n", (double)(resolve_end - resolve_start) / (1UL << 20));
           /* fp = fopen("proof.log", "a+");
            fprintf(fp, "\n===RESOLVED AFTER STEP %d:\n", i);
            PrintTuples(fp);
            fclose(fp);*/
        }
        uint64_t stop_cycles = rdtsc();

        double  mcycles_d = (double)(stop_cycles - start_cycles) / (1UL << 20);
        uint32_t kbytes = (tupleList.size()*LIST_LENGTH*k*sizeof(uint32_t)) / (1UL << 10);
        printf("Time spent for n=%d k=%d  %d KiB: %2.2f  Mcycles \n",
            n, k, kbytes,
            mcycles_d);

        //Duplicate check
        for (unsigned i = 0; i < solutions.size(); ++i) {
            auto vec = solutions[i].inputs;
            std::sort(vec.begin(), vec.end());
            bool dup = false;
            for (unsigned k = 0; k < vec.size() - 1; ++k) {
                if (vec[k] == vec[k + 1])
                    dup = true;
            }
            if (!dup)
                return solutions[i];
        }
    }
    return Proof(n, k, seed, nonce, std::vector<uint32_t>());
}

bool Proof::Test()
{
    uint32_t input[SEED_LENGTH + 2];
    for (unsigned i = 0; i < SEED_LENGTH; ++i)
        input[i] = seed[i];
    input[SEED_LENGTH] = nonce;
    input[SEED_LENGTH + 1] = 0;
    uint32_t buf[MAX_N / 4];
    std::vector<uint32_t> blocks(k+1,0);
    for (unsigned i = 0; i < inputs.size(); ++i) {
        input[SEED_LENGTH + 1] = inputs[i];
        blake2b((uint8_t*)buf, &input, NULL, sizeof(buf), sizeof(input), 0);
        for (unsigned j = 0; j < (k + 1); ++j) {
            //select j-th block of n/(k+1) bits
            blocks[j] ^= buf[j] >> (32 - n / (k + 1));
        }
    }
    bool b = true;
    for (unsigned j = 0; j < (k + 1); ++j) {
        b &= (blocks[j] == 0);
    }
    if (b && inputs.size()!=0)    {
        printf("Solution found:\n");
        for (unsigned i = 0; i < inputs.size(); ++i) {
            printf(" %x ", inputs[i]);
        }
        printf("\n");
    }
    return b;
}<commit_msg>Too big lists created<commit_after>/*Code by Dmitry Khovratovich, 2016
CC0 license
*/

#include "pow.h"
#include "blake/blake2.h"
#include <algorithm>

static uint64_t rdtsc(void) {
#ifdef _MSC_VER
    return __rdtsc();
#else
#if defined(__amd64__) || defined(__x86_64__)
    uint64_t rax, rdx;
    __asm__ __volatile__("rdtsc" : "=a"(rax), "=d"(rdx) : : );
    return (rdx << 32) | rax;
#elif defined(__i386__) || defined(__i386) || defined(__X86__)
    uint64_t rax;
    __asm__ __volatile__("rdtsc" : "=A"(rax) : : );
    return rax;
#else
#error "Not implemented!"
#endif
#endif
}

using namespace _POW;
using namespace std;

void Equihash::InitializeMemory()
{
    uint32_t  tuple_n = ((uint32_t)1) << (n / (k + 1));
    Tuple default_tuple(k); // k blocks to store (one left for index)
    std::vector<Tuple> def_tuples(LIST_LENGTH, default_tuple);
    tupleList = std::vector<std::vector<Tuple>>(tuple_n, def_tuples);
    filledList= std::vector<unsigned>(tuple_n, 0);
    solutions.resize(0);
    forks.resize(0);
}

void Equihash::PrintTuples(FILE* fp) {
    unsigned count = 0;
    for (unsigned i = 0; i < tupleList.size(); ++i) {
        for (unsigned m = 0; m < filledList[i]; ++m) {
            fprintf(fp, "[%d][%d]:", i,m);
            for (unsigned j = 0; j < tupleList[i][m].blocks.size(); ++j)
                fprintf(fp, " %x ", tupleList[i][m].blocks[j]);
            fprintf(fp, " || %x", tupleList[i][m].reference);
            fprintf(fp, " |||| ");
        }
        count += filledList[i];
        fprintf(fp, "\n");
    }
    fprintf(fp, "TOTAL: %d elements printed", count);
}

void Equihash::FillMemory(uint32_t length) //works for k<=7
{
    uint32_t input[SEED_LENGTH + 2];
    for (unsigned i = 0; i < SEED_LENGTH; ++i)
        input[i] = seed[i];
    input[SEED_LENGTH] = nonce;
    input[SEED_LENGTH + 1] = 0;
    uint32_t buf[MAX_N / 4];
    for (unsigned i = 0; i < length; ++i, ++input[SEED_LENGTH + 1]) {
        blake2b((uint8_t*)buf, &input, NULL, sizeof(buf), sizeof(input), 0);
        uint32_t index = buf[0] >> (32 - n / (k + 1));
        unsigned count = filledList[index];
        if (count < LIST_LENGTH) {
            for (unsigned j = 1; j < (k + 1); ++j) {
                //select j-th block of n/(k+1) bits
                tupleList[index][count].blocks[j - 1] = buf[j] >> (32 - n / (k + 1));
            }
            tupleList[index][count].reference = i;
            filledList[index]++;
        }
    }
}

std::vector<Input> Equihash::ResolveTreeByLevel(Fork fork, unsigned level) {
    if (level == 0)
        return std::vector<Input>{fork.ref1, fork.ref2};
    auto v1 = ResolveTreeByLevel(forks[level - 1][fork.ref1], level - 1);
    auto v2 = ResolveTreeByLevel(forks[level - 1][fork.ref2], level - 1);
    v1.insert(v1.end(), v2.begin(), v2.end());
    return v1;
}

std::vector<Input> Equihash::ResolveTree(Fork fork) {
    return ResolveTreeByLevel(fork, forks.size());
}

void Equihash::ResolveCollisions(bool store) {
    const unsigned tableLength = tupleList.size();  //number of rows in the hashtable
    const unsigned maxNewCollisions = tupleList.size()*FORK_MULTIPLIER;  //max number of collisions to be found
    const unsigned newBlocks = tupleList[0][0].blocks.size() - 1;// number of blocks in the future collisions
    std::vector<Fork> newForks(maxNewCollisions); //list of forks created at this step
    auto tableRow = vector<Tuple>(LIST_LENGTH, Tuple(newBlocks)); //Row in the hash table
    vector<vector<Tuple>> collisionList(tableLength,tableRow);
    std::vector<unsigned> newFilledList(tableLength,0);  //number of entries in rows
    uint32_t newColls = 0; //collision counter
    for (unsigned i = 0; i < tableLength; ++i) {
        for (unsigned j = 0; j < filledList[i]; ++j)        {
            for (unsigned m = j + 1; m < filledList[i]; ++m) {   //Collision
                //New index
                uint32_t newIndex = tupleList[i][j].blocks[0] ^ tupleList[i][m].blocks[0];
                Fork newFork = Fork(tupleList[i][j].reference, tupleList[i][m].reference);
                //Check if we get a solution
                if (store) {  //last step
                    if (newIndex == 0) {//Solution
                        std::vector<Input> solution_inputs = ResolveTree(newFork);
                        solutions.push_back(Proof(n, k, seed, nonce, solution_inputs));
                    }
                }
                else {         //Resolve
                    if (newFilledList[newIndex] < LIST_LENGTH && newColls < maxNewCollisions) {
                        for (unsigned l = 0; l < newBlocks; ++l) {
                            collisionList[newIndex][newFilledList[newIndex]].blocks[l]
                                = tupleList[i][j].blocks[l+1] ^ tupleList[i][m].blocks[l+1];
                        }
                        newForks[newColls] = newFork;
                        collisionList[newIndex][newFilledList[newIndex]].reference = newColls;
                        newFilledList[newIndex]++;
                        newColls++;
                    }//end of adding collision
                }
            }
        }//end of collision for i
    }
    forks.push_back(newForks);
    std::swap(tupleList, collisionList);
    std::swap(filledList, newFilledList);
}

Proof Equihash::FindProof(){
    FILE* fp = fopen("proof.log", "w+");
    fclose(fp);
    this->nonce = 1;
    while (nonce < MAX_NONCE) {
        nonce++;
        printf("Testing nonce %d\n", nonce);
        uint64_t start_cycles = rdtsc();
        InitializeMemory(); //allocate
        FillMemory(4UL << (n / (k + 1)-1));   //fill with hashes
        uint64_t fill_end = rdtsc();
        printf("Filling %2.2f  Mcycles \n", (double)(fill_end - start_cycles) / (1UL << 20));
        /*fp = fopen("proof.log", "a+");
        fprintf(fp, "\n===MEMORY FILLED:\n");
        PrintTuples(fp);
        fclose(fp);*/
        for (unsigned i = 1; i <= k; ++i) {
            uint64_t resolve_start = rdtsc();
            bool to_store = (i == k);
            ResolveCollisions(to_store); //XOR collisions, concatenate indices and shift
            uint64_t resolve_end = rdtsc();
            printf("Resolving %2.2f  Mcycles \n", (double)(resolve_end - resolve_start) / (1UL << 20));
           /* fp = fopen("proof.log", "a+");
            fprintf(fp, "\n===RESOLVED AFTER STEP %d:\n", i);
            PrintTuples(fp);
            fclose(fp);*/
        }
        uint64_t stop_cycles = rdtsc();

        double  mcycles_d = (double)(stop_cycles - start_cycles) / (1UL << 20);
        uint32_t kbytes = (tupleList.size()*LIST_LENGTH*k*sizeof(uint32_t)) / (1UL << 10);
        printf("Time spent for n=%d k=%d  %d KiB: %2.2f  Mcycles \n",
            n, k, kbytes,
            mcycles_d);

        //Duplicate check
        for (unsigned i = 0; i < solutions.size(); ++i) {
            auto vec = solutions[i].inputs;
            std::sort(vec.begin(), vec.end());
            bool dup = false;
            for (unsigned k = 0; k < vec.size() - 1; ++k) {
                if (vec[k] == vec[k + 1])
                    dup = true;
            }
            if (!dup)
                return solutions[i];
        }
    }
    return Proof(n, k, seed, nonce, std::vector<uint32_t>());
}

bool Proof::Test()
{
    uint32_t input[SEED_LENGTH + 2];
    for (unsigned i = 0; i < SEED_LENGTH; ++i)
        input[i] = seed[i];
    input[SEED_LENGTH] = nonce;
    input[SEED_LENGTH + 1] = 0;
    uint32_t buf[MAX_N / 4];
    std::vector<uint32_t> blocks(k+1,0);
    for (unsigned i = 0; i < inputs.size(); ++i) {
        input[SEED_LENGTH + 1] = inputs[i];
        blake2b((uint8_t*)buf, &input, NULL, sizeof(buf), sizeof(input), 0);
        for (unsigned j = 0; j < (k + 1); ++j) {
            //select j-th block of n/(k+1) bits
            blocks[j] ^= buf[j] >> (32 - n / (k + 1));
        }
    }
    bool b = true;
    for (unsigned j = 0; j < (k + 1); ++j) {
        b &= (blocks[j] == 0);
    }
    if (b && inputs.size()!=0)    {
        printf("Solution found:\n");
        for (unsigned i = 0; i < inputs.size(); ++i) {
            printf(" %x ", inputs[i]);
        }
        printf("\n");
    }
    return b;
}
<|endoftext|>


<commit_before>/*  Copyright (c) MediaArea.net SARL. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license that can
 *  be found in the License.html file in the root of the source tree.
 */

//---------------------------------------------------------------------------
#ifdef __BORLANDC__
    #pragma hdrstop
#endif
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
#include "Common/Core.h"
#include "Help.h"
#include "Config.h"
//---------------------------------------------------------------------------

//***************************************************************************
//
//***************************************************************************
//---------------------------------------------------------------------------
String Program_Name = __T("MediaInfo");

void Set_Program_Name(const String &Name)
{
    Program_Name = Name;
    #if defined(_MSC_VER)
        Program_Name = Program_Name.substr(Program_Name.rfind('\\')+1);
        Program_Name = Program_Name.substr(0, Program_Name.find('.'));
    #else
        Program_Name = Program_Name.substr(Program_Name.rfind('/')+1);
    #endif
}

//---------------------------------------------------------------------------
int Help()
{
    STRINGOUT(String(__T("Usage: \" [-Options...] FileName1 [Filename2...]\"")).insert(8, Program_Name));
    TEXTOUT("");
    TEXTOUT("Options:");
    TEXTOUT("--Help, -h");
    TEXTOUT("                    Display this help and exit");
    TEXTOUT("--Help-Output");
    TEXTOUT("                    Display help for Output= option");
    TEXTOUT("--Help-AnOption");
    TEXTOUT("                    Display help for \"AnOption\"");
    TEXTOUT("--Version");
    TEXTOUT("                    Display MediaInfo version and exit");
    TEXTOUT("");
    TEXTOUT("--Full , -f");
    TEXTOUT("                    Full information Display (all internal tags)");
    TEXTOUT("--Output=HTML");
    TEXTOUT("                    Full information Display with HTML tags");
    TEXTOUT("--Output=XML");
    TEXTOUT("                    Full information Display with XML tags");
    TEXTOUT("--Output=EBUCore");
    TEXTOUT("                    Full information Display with EBUCore compliant XML tags");
    TEXTOUT("--Output=PBCore");
    TEXTOUT("                    Full information Display with PBCore compliant XML tags");
    TEXTOUT("--Output=PBCore2");
    TEXTOUT("                    Full information Display with PBCore 2.0 compliant XML tags");
    TEXTOUT("--AcquisitionDataOutputMode=segmentParameter");
    TEXTOUT("                    Display Acquisition Data by segment then parameter (EBUCore output)");
    TEXTOUT("--AcquisitionDataOutputMode=parameterSegment");
    TEXTOUT("                    Display Acquisition Data by parameter then segment (EBUCore output)");
    TEXTOUT("--ExternalMetadata=...");
    TEXTOUT("                    Add external metadata to the output (EBUCore output)");
    TEXTOUT("--ExternalMetadataConfig=...");
    TEXTOUT("                    Output template for external metadata (EBUCore output)");
    TEXTOUT("--Info-Parameters");
    TEXTOUT("                    Display list of Inform= parameters");
    TEXTOUT("");
    TEXTOUT("--Language=raw");
    TEXTOUT("                    Display non-translated unique identifiers (internal text)");
    TEXTOUT("--Details=1");
    TEXTOUT("                    Display mediatrace info");
    TEXTOUT("--File_TestContinuousFileNames=0");
    TEXTOUT("                    Disable image sequence detection");
    TEXTOUT("--LogFile=...");
    TEXTOUT("                    Save the output in the specified file");
    TEXTOUT("--BOM");
    TEXTOUT("                    Byte order mark for UTF-8 output");
    TEXTOUT("");
    TEXTOUT("--Ssl_CertificateFileName=...");
    TEXTOUT("                    File name of the SSL certificate.");
    TEXTOUT("                    The default format is \"PEM\" and can be changed");
    TEXTOUT("                    with --Ssl_CertificateFormat.");
    TEXTOUT("--Ssl_CertificateFormat=...");
    TEXTOUT("                    File format of the SSL certificate.");
    TEXTOUT("                    Supported formats are \"PEM\" and \"DER\"");
    TEXTOUT("--Ssl_PrivateKeyFileName=...");
    TEXTOUT("                    File name of the SSL private key.");
    TEXTOUT("                    The default format is \"PEM\" and can be changed");
    TEXTOUT("                    with --Ssl_PrivateKeyFormat.");
    TEXTOUT("                    Note: private key with a password is not supported.");
    TEXTOUT("--Ssl_PrivateKeyFormat=...");
    TEXTOUT("                    File format of the SSL private key.");
    TEXTOUT("                    Supported formats are \"PEM\" and \"DER\"");
    TEXTOUT("--Ssl_CertificateAuthorityFileName=...");
    TEXTOUT("                    File name of the SSL certificate authorities");
    TEXTOUT("                    to verify the peer with.");
    TEXTOUT("--Ssl_CertificateAuthorityPath=...");
    TEXTOUT("                    Path of the SSL certificate authorities");
    TEXTOUT("                    to verify the peer with.");
    TEXTOUT("--Ssl_CertificateRevocationListFileName=...");
    TEXTOUT("                    File name of the SSL certificate revocation list.");
    TEXTOUT("                    The format is \"PEM\"");
    TEXTOUT("--Ssl_IgnoreSecurity=...");
    TEXTOUT("                    Does not verify the authenticity of the peer's certificate");
    TEXTOUT("                    Use it at your own risks");
    TEXTOUT("--Ssh_PublicKeyFileName=...");
    TEXTOUT("                    File name of the SSH private key.");
    TEXTOUT("                    Default is $HOME/.ssh/id_rsa.pub or $HOME/.ssh/id_dsa.pub");
    TEXTOUT("                    if the HOME environment variable is set, and just");
    TEXTOUT("                    \"id_rsa.pub\" or \"id_dsa.pub\" in the current directory");
    TEXTOUT("                    if HOME is not set.");
    TEXTOUT("                    Note: you need to set both public and private key.");
    TEXTOUT("--Ssh_PrivateKeyFileName=...");
    TEXTOUT("                    File name of the SSH private key.");
    TEXTOUT("                    Default is $HOME/.ssh/id_rsa or $HOME/.ssh/id_dsa");
    TEXTOUT("                    if the HOME environment variable is set, and just");
    TEXTOUT("                    \"id_rsa\" or \"id_dsa\" in the current directory");
    TEXTOUT("                    if HOME is not set.");
    TEXTOUT("                    Note: you need to set both public and private key.");
    TEXTOUT("                    Note: private key with a password is not supported.");
    TEXTOUT("--Ssh_KnownHostsFileName=...");
    TEXTOUT("                    File name of the known hosts");
    TEXTOUT("                    The format is the OpenSSH file format (libssh2)");
    TEXTOUT("                    Default is $HOME/.ssh/known_hosts");
    TEXTOUT("                    if the HOME environment variable is set, and just");
    TEXTOUT("                    \"known_hosts\" in the current directory");
    TEXTOUT("                    if HOME is not set.");
    TEXTOUT("--Ssh_IgnoreSecurity");
    TEXTOUT("                    Does not verify the authenticity of the peer");
    TEXTOUT("                    (you don't need to accept the key with ssh first)");
    TEXTOUT("                    Use it at your own risks");

    return MI_OK;
}

//---------------------------------------------------------------------------
int Help_Nothing()
{
    STRINGOUT(String(__T("Usage: \" [-Options...] FileName1 [Filename2...]\"")).insert(8, Program_Name));
    STRINGOUT(String(__T("\" --Help\" for displaying more information")).insert(1, Program_Name));

    return MI_OK;
}

//---------------------------------------------------------------------------
int Help_Output()
{
    TEXTOUT("--Output=...  Specify a template (BETA)");
    STRINGOUT(String(__T("Usage: \" --Output=[xxx;]Text FileName\"")).insert(8, Program_Name));
    TEXTOUT("");
    TEXTOUT("xxx can be: General, Video, Audio, Text, Chapter, Image, Menu");
    TEXTOUT("Text can be the template text, or a filename");
    TEXTOUT("     Filename must be in the form file://filename");
    TEXTOUT("");
    TEXTOUT("See --Info-Parameters for available parameters in the text");
    TEXTOUT("(Parameters must be surrounded by \"%\" sign)");
    TEXTOUT("");
    STRINGOUT(String(__T("Usage: \" --Output=Video;%AspectRatio% FileName\"")).insert(8, Program_Name));
    TEXTOUT("");
    STRINGOUT(String(__T("Usage: \" --Output=Video;file://Video.txt FileName\"")).insert(8, Program_Name));
    TEXTOUT("and Video.txt contains ");
    TEXTOUT("\"%DisplayAspectRatio%\"        for Video Aspect Ratio.");
    TEXTOUT("");
    STRINGOUT(String(__T("Usage: \" --Output=file://Text.txt FileName\"")).insert(8, Program_Name));
    TEXTOUT("and Text.txt contains");
    TEXTOUT("\"Video;%DisplayAspectRatio%\"  for Video Aspect Ratio.");
    TEXTOUT("\"Audio;%Format%\"              for Audio Format.");

    return MI_ERROR;
}

//---------------------------------------------------------------------------
int Usage()
{
    Help_Nothing();
    return MI_ERROR;
}
<commit_msg>Help.cpp - adds OLDXML option<commit_after>/*  Copyright (c) MediaArea.net SARL. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license that can
 *  be found in the License.html file in the root of the source tree.
 */

//---------------------------------------------------------------------------
#ifdef __BORLANDC__
    #pragma hdrstop
#endif
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
#include "Common/Core.h"
#include "Help.h"
#include "Config.h"
//---------------------------------------------------------------------------

//***************************************************************************
//
//***************************************************************************
//---------------------------------------------------------------------------
String Program_Name = __T("MediaInfo");

void Set_Program_Name(const String &Name)
{
    Program_Name = Name;
    #if defined(_MSC_VER)
        Program_Name = Program_Name.substr(Program_Name.rfind('\\')+1);
        Program_Name = Program_Name.substr(0, Program_Name.find('.'));
    #else
        Program_Name = Program_Name.substr(Program_Name.rfind('/')+1);
    #endif
}

//---------------------------------------------------------------------------
int Help()
{
    STRINGOUT(String(__T("Usage: \" [-Options...] FileName1 [Filename2...]\"")).insert(8, Program_Name));
    TEXTOUT("");
    TEXTOUT("Options:");
    TEXTOUT("--Help, -h");
    TEXTOUT("                    Display this help and exit");
    TEXTOUT("--Help-Output");
    TEXTOUT("                    Display help for Output= option");
    TEXTOUT("--Help-AnOption");
    TEXTOUT("                    Display help for \"AnOption\"");
    TEXTOUT("--Version");
    TEXTOUT("                    Display MediaInfo version and exit");
    TEXTOUT("");
    TEXTOUT("--Full , -f");
    TEXTOUT("                    Full information Display (all internal tags)");
    TEXTOUT("--Output=HTML");
    TEXTOUT("                    Full information Display with HTML tags");
    TEXTOUT("--Output=XML");
    TEXTOUT("                    Full information Display with XML tags");
    TEXTOUT("--Output=OLDXML");
    TEXTOUT("                    Full information Display with XML tags using the older MediaInfo schema");
    TEXTOUT("--Output=EBUCore");
    TEXTOUT("                    Full information Display with EBUCore compliant XML tags");
    TEXTOUT("--Output=PBCore");
    TEXTOUT("                    Full information Display with PBCore compliant XML tags");
    TEXTOUT("--Output=PBCore2");
    TEXTOUT("                    Full information Display with PBCore 2.0 compliant XML tags");
    TEXTOUT("--AcquisitionDataOutputMode=segmentParameter");
    TEXTOUT("                    Display Acquisition Data by segment then parameter (EBUCore output)");
    TEXTOUT("--AcquisitionDataOutputMode=parameterSegment");
    TEXTOUT("                    Display Acquisition Data by parameter then segment (EBUCore output)");
    TEXTOUT("--ExternalMetadata=...");
    TEXTOUT("                    Add external metadata to the output (EBUCore output)");
    TEXTOUT("--ExternalMetadataConfig=...");
    TEXTOUT("                    Output template for external metadata (EBUCore output)");
    TEXTOUT("--Info-Parameters");
    TEXTOUT("                    Display list of Inform= parameters");
    TEXTOUT("");
    TEXTOUT("--Language=raw");
    TEXTOUT("                    Display non-translated unique identifiers (internal text)");
    TEXTOUT("--Details=1");
    TEXTOUT("                    Display mediatrace info");
    TEXTOUT("--File_TestContinuousFileNames=0");
    TEXTOUT("                    Disable image sequence detection");
    TEXTOUT("--LogFile=...");
    TEXTOUT("                    Save the output in the specified file");
    TEXTOUT("--BOM");
    TEXTOUT("                    Byte order mark for UTF-8 output");
    TEXTOUT("");
    TEXTOUT("--Ssl_CertificateFileName=...");
    TEXTOUT("                    File name of the SSL certificate.");
    TEXTOUT("                    The default format is \"PEM\" and can be changed");
    TEXTOUT("                    with --Ssl_CertificateFormat.");
    TEXTOUT("--Ssl_CertificateFormat=...");
    TEXTOUT("                    File format of the SSL certificate.");
    TEXTOUT("                    Supported formats are \"PEM\" and \"DER\"");
    TEXTOUT("--Ssl_PrivateKeyFileName=...");
    TEXTOUT("                    File name of the SSL private key.");
    TEXTOUT("                    The default format is \"PEM\" and can be changed");
    TEXTOUT("                    with --Ssl_PrivateKeyFormat.");
    TEXTOUT("                    Note: private key with a password is not supported.");
    TEXTOUT("--Ssl_PrivateKeyFormat=...");
    TEXTOUT("                    File format of the SSL private key.");
    TEXTOUT("                    Supported formats are \"PEM\" and \"DER\"");
    TEXTOUT("--Ssl_CertificateAuthorityFileName=...");
    TEXTOUT("                    File name of the SSL certificate authorities");
    TEXTOUT("                    to verify the peer with.");
    TEXTOUT("--Ssl_CertificateAuthorityPath=...");
    TEXTOUT("                    Path of the SSL certificate authorities");
    TEXTOUT("                    to verify the peer with.");
    TEXTOUT("--Ssl_CertificateRevocationListFileName=...");
    TEXTOUT("                    File name of the SSL certificate revocation list.");
    TEXTOUT("                    The format is \"PEM\"");
    TEXTOUT("--Ssl_IgnoreSecurity=...");
    TEXTOUT("                    Does not verify the authenticity of the peer's certificate");
    TEXTOUT("                    Use it at your own risks");
    TEXTOUT("--Ssh_PublicKeyFileName=...");
    TEXTOUT("                    File name of the SSH private key.");
    TEXTOUT("                    Default is $HOME/.ssh/id_rsa.pub or $HOME/.ssh/id_dsa.pub");
    TEXTOUT("                    if the HOME environment variable is set, and just");
    TEXTOUT("                    \"id_rsa.pub\" or \"id_dsa.pub\" in the current directory");
    TEXTOUT("                    if HOME is not set.");
    TEXTOUT("                    Note: you need to set both public and private key.");
    TEXTOUT("--Ssh_PrivateKeyFileName=...");
    TEXTOUT("                    File name of the SSH private key.");
    TEXTOUT("                    Default is $HOME/.ssh/id_rsa or $HOME/.ssh/id_dsa");
    TEXTOUT("                    if the HOME environment variable is set, and just");
    TEXTOUT("                    \"id_rsa\" or \"id_dsa\" in the current directory");
    TEXTOUT("                    if HOME is not set.");
    TEXTOUT("                    Note: you need to set both public and private key.");
    TEXTOUT("                    Note: private key with a password is not supported.");
    TEXTOUT("--Ssh_KnownHostsFileName=...");
    TEXTOUT("                    File name of the known hosts");
    TEXTOUT("                    The format is the OpenSSH file format (libssh2)");
    TEXTOUT("                    Default is $HOME/.ssh/known_hosts");
    TEXTOUT("                    if the HOME environment variable is set, and just");
    TEXTOUT("                    \"known_hosts\" in the current directory");
    TEXTOUT("                    if HOME is not set.");
    TEXTOUT("--Ssh_IgnoreSecurity");
    TEXTOUT("                    Does not verify the authenticity of the peer");
    TEXTOUT("                    (you don't need to accept the key with ssh first)");
    TEXTOUT("                    Use it at your own risks");

    return MI_OK;
}

//---------------------------------------------------------------------------
int Help_Nothing()
{
    STRINGOUT(String(__T("Usage: \" [-Options...] FileName1 [Filename2...]\"")).insert(8, Program_Name));
    STRINGOUT(String(__T("\" --Help\" for displaying more information")).insert(1, Program_Name));

    return MI_OK;
}

//---------------------------------------------------------------------------
int Help_Output()
{
    TEXTOUT("--Output=...  Specify a template (BETA)");
    STRINGOUT(String(__T("Usage: \" --Output=[xxx;]Text FileName\"")).insert(8, Program_Name));
    TEXTOUT("");
    TEXTOUT("xxx can be: General, Video, Audio, Text, Chapter, Image, Menu");
    TEXTOUT("Text can be the template text, or a filename");
    TEXTOUT("     Filename must be in the form file://filename");
    TEXTOUT("");
    TEXTOUT("See --Info-Parameters for available parameters in the text");
    TEXTOUT("(Parameters must be surrounded by \"%\" sign)");
    TEXTOUT("");
    STRINGOUT(String(__T("Usage: \" --Output=Video;%AspectRatio% FileName\"")).insert(8, Program_Name));
    TEXTOUT("");
    STRINGOUT(String(__T("Usage: \" --Output=Video;file://Video.txt FileName\"")).insert(8, Program_Name));
    TEXTOUT("and Video.txt contains ");
    TEXTOUT("\"%DisplayAspectRatio%\"        for Video Aspect Ratio.");
    TEXTOUT("");
    STRINGOUT(String(__T("Usage: \" --Output=file://Text.txt FileName\"")).insert(8, Program_Name));
    TEXTOUT("and Text.txt contains");
    TEXTOUT("\"Video;%DisplayAspectRatio%\"  for Video Aspect Ratio.");
    TEXTOUT("\"Audio;%Format%\"              for Audio Format.");

    return MI_ERROR;
}

//---------------------------------------------------------------------------
int Usage()
{
    Help_Nothing();
    return MI_ERROR;
}
<|endoftext|>