<commit_before>// Sh: A GPU metaprogramming language.
//
// Copyright (c) 2003 University of Waterloo Computer Graphics Laboratory
// Project administrator: Michael D. McCool
// Authors: Zheng Qin, Stefanus Du Toit, Kevin Moule, Tiberiu S. Popa,
//          Michael D. McCool
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must
// not claim that you wrote the original software. If you use this
// software in a product, an acknowledgment in the product documentation
// would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must
// not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//////////////////////////////////////////////////////////////////////////////
#include <iostream>
#include <fstream>
#include <wx/splitter.h>
#include <wx/colordlg.h>
#include <wx/treectrl.h>
#include <sh/ShObjMesh.hpp>
#include "ShrikeFrame.hpp"
#include "ShrikeCanvas.hpp"
#include "Shader.hpp"
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

using namespace SH;
using namespace ShUtil;

BEGIN_EVENT_TABLE(ShrikeFrame, wxFrame)
  EVT_MENU(SHRIKE_MENU_OPEN_MODEL, ShrikeFrame::openModel)
  EVT_MENU(SHRIKE_MENU_QUIT, ShrikeFrame::quit)
  EVT_MENU(SHRIKE_MENU_SHADER_PROPS, ShrikeFrame::shaderProps)
  EVT_MENU(SHRIKE_MENU_SHADER_SHOW_VSH, ShrikeFrame::showVsh)
  EVT_MENU(SHRIKE_MENU_SHADER_SHOW_FSH, ShrikeFrame::showFsh)
  EVT_MENU(SHRIKE_MENU_SHADER_SHOW_VSHIF, ShrikeFrame::showVshInterface)
  EVT_MENU(SHRIKE_MENU_SHADER_SHOW_FSHIF, ShrikeFrame::showFshInterface)
  EVT_MENU(SHRIKE_MENU_SHADER_REINIT, ShrikeFrame::reinit)
  EVT_MENU(SHRIKE_MENU_VIEW_RESET, ShrikeFrame::resetView)
  EVT_MENU(SHRIKE_MENU_VIEW_SCREENSHOT, ShrikeFrame::screenshot)
  EVT_MENU(SHRIKE_MENU_VIEW_BACKGROUND, ShrikeFrame::setBackground)
  EVT_MENU(SHRIKE_MENU_VIEW_FULLSCREEN, ShrikeFrame::fullscreen)
  EVT_MENU(SHRIKE_MENU_VIEW_WIREFRAME, ShrikeFrame::wireframe)
  EVT_MENU(SHRIKE_MENU_VIEW_FPS, ShrikeFrame::fps)
  EVT_CLOSE(ShrikeFrame::close)
  EVT_KEY_DOWN(ShrikeFrame::keyDown)
  //  EVT_LISTBOX(SHRIKE_LISTBOX_SHADERS, ShrikeFrame::onShaderSelect)
  EVT_TREE_SEL_CHANGED(SHRIKE_TREECTRL_SHADERS, ShrikeFrame::onShaderSelect)
END_EVENT_TABLE()

struct ShaderTreeData : public wxTreeItemData {
  ShaderTreeData(Shader* shader)
    : shader(shader)
  {
  }

  Shader* shader;
};

ShrikeFrame::ShrikeFrame()
  : wxFrame(0, -1, "Shrike", wxDefaultPosition, wxSize(600, 400)),
    m_shader(0), m_fullscreen(false), m_fps(false)
{
  m_instance = this;
  CreateStatusBar();

  GetStatusBar()->SetStatusText("Hold down shift to rotate the light instead of the camera.");

  // Setup menus

  wxMenu* fileMenu = new wxMenu();
  fileMenu->Append(SHRIKE_MENU_OPEN_MODEL, "&Open Model");
  fileMenu->AppendSeparator();
  fileMenu->Append(SHRIKE_MENU_QUIT, "&Quit");

  wxMenu* shaderMenu = new wxMenu();
  shaderMenu->Append(SHRIKE_MENU_SHADER_PROPS, "&Properties");
  shaderMenu->AppendSeparator();
  shaderMenu->Append(SHRIKE_MENU_SHADER_REINIT, "Re&initialize");
  shaderMenu->AppendSeparator();
  shaderMenu->Append(SHRIKE_MENU_SHADER_SHOW_VSHIF, "Show &vertex interface");
  shaderMenu->Append(SHRIKE_MENU_SHADER_SHOW_FSHIF, "Show &fragment interface");
  shaderMenu->AppendSeparator();
  shaderMenu->Append(SHRIKE_MENU_SHADER_SHOW_VSH, "Show &vertex assembly");
  shaderMenu->Append(SHRIKE_MENU_SHADER_SHOW_FSH, "Show &fragment assembly");

  wxMenu* viewMenu = new wxMenu();
  viewMenu->Append(SHRIKE_MENU_VIEW_RESET, "&Reset");
  viewMenu->Append(SHRIKE_MENU_VIEW_BACKGROUND, "Set &background colour...");
  viewMenu->AppendCheckItem(SHRIKE_MENU_VIEW_FULLSCREEN, "Fullscreen");
  viewMenu->AppendCheckItem(SHRIKE_MENU_VIEW_WIREFRAME, "&Wireframe");
  viewMenu->AppendCheckItem(SHRIKE_MENU_VIEW_FPS, "Show framerate");
  viewMenu->Append(SHRIKE_MENU_VIEW_SCREENSHOT, "Screenshot");

  wxMenuBar* menuBar = new wxMenuBar();
  menuBar->Append(fileMenu, "&File");
  menuBar->Append(shaderMenu, "&Shader");
  menuBar->Append(viewMenu, "&View");

  SetMenuBar(menuBar);

  m_hsplitter = new wxSplitterWindow(this, -1);

  m_shaderList = initShaderList(m_hsplitter);

  // Probably should do this somewhere else...
  ShObjMesh* model = 0;

  // TODO: FIXME
  std::ifstream infile(SHMEDIA_DIR "/objs/sphere50.obj");
  if (infile) {
    model = new ShObjMesh(infile);
  }

#if 0 // switch this on for fixed size separate preview window
  // TODO implement this properly in the GUI
  int width = 512 + 2;
  int height = 512 + 2;
  m_preview = new wxFrame(0, -1, "Shrike Preview", wxDefaultPosition, wxSize(width, height));
  m_canvas = new ShrikeCanvas(m_preview, model);
  m_panel = new UniformPanel(m_hsplitter);
  m_hsplitter->SplitVertically(m_shaderList, m_panel, 150);
  m_preview->Show();

#else
  m_right_window = new wxSplitterWindow(m_hsplitter, -1);
  m_canvas = new ShrikeCanvas(m_right_window, model);
  m_panel = new UniformPanel(m_right_window);
  m_hsplitter->SplitVertically(m_shaderList, m_right_window, 150);
  m_right_window->SplitHorizontally(m_canvas, m_panel, -100);
  m_right_window->SetMinimumPaneSize(40);
#endif

}

ShrikeFrame::~ShrikeFrame()
{
}

void ShrikeFrame::openModel(wxCommandEvent& event)
{
  wxFileDialog* dialog = new wxFileDialog(this, "Open Model",
                                          SHMEDIA_DIR "/objs", "",
                                          "OBJ Files (*.obj)|*.obj", wxOPEN);
  if (dialog->ShowModal() == wxID_OK) {
    std::ifstream infile(dialog->GetPath());
    if (infile) {
      ShObjMesh* model = new ShObjMesh(infile);
      m_canvas->setModel(model);
    } // TODO: Complain if opening file failed
  }
}

void ShrikeFrame::shaderProps(wxCommandEvent& event)
{
  if (!m_shader) return;
  if (m_shader->paramCount() == 0) return;
  ShrikePropsDialog dialog(this, m_shader);

  if (dialog.ShowModal() != wxID_OK) return;

  try {
    m_shader->init();
  } catch (const ShException& e) {
    std::cerr << e.message() << std::endl;
    return;
  }
  setShader(m_shader);
}

void ShrikeFrame::quit(wxCommandEvent& event)
{
  Destroy();
  //  Close(true);
}

void ShrikeFrame::close(wxCloseEvent& event)
{
  Destroy();
}

void ShrikeFrame::onShaderSelect(wxTreeEvent& event)
{
  wxTreeItemId item = event.GetItem();
  ShaderTreeData* data =
    dynamic_cast<ShaderTreeData*>(m_shaderList->GetItemData(item));
  if (!data) return;
  Shader* shader = data->shader;
  setShader(shader);
}

void ShrikeFrame::setShader(Shader* shader)
{
  m_canvas->SetCurrent();
  try {
    if (shader) shader->firstTimeInit();
  } catch (const ShException& e) {
    std::cerr << e.message() << std::endl;
    return;
  }
  if (shader) shader->bind();
  m_canvas->setShader(shader);
  m_canvas->render();
  m_panel->setShader(shader);
  m_shader = shader;
}

void ShrikeFrame::showVsh(wxCommandEvent& event)
{
  if (!m_shader) return;
  showProgram(m_shader->vertex(), "Vertex");
}

void ShrikeFrame::showFsh(wxCommandEvent& event)
{
  if (!m_shader) return;
  showProgram(m_shader->fragment(), "Fragment");
}

void ShrikeFrame::showVshInterface(wxCommandEvent& event)
{
  if (!m_shader) return;
  showInterface(m_shader->vertex(), "Vertex");
}

void ShrikeFrame::showFshInterface(wxCommandEvent& event)
{
  if (!m_shader) return;
  showInterface(m_shader->fragment(), "Fragment");
}

void ShrikeFrame::reinit(wxCommandEvent& event)
{
  if (!m_shader) return;
  try {
    m_shader->init();
  } catch (const ShException& e) {
    std::cerr << e.message() << std::endl;
    return;
  }
  setShader(m_shader);
}

void ShrikeFrame::resetView(wxCommandEvent& event)
{
  m_canvas->resetView();
}

void ShrikeFrame::setBackground(wxCommandEvent& event)
{
  wxColourDialog dialog(this);

  if (dialog.ShowModal() != wxID_OK) return;

  wxColour c = dialog.GetColourData().GetColour();
  m_canvas->setBackground(c.Red(), c.Green(), c.Blue());
}

void ShrikeFrame::showProgram(ShProgram program,
                              const std::string& name)
{
  if (!program.node()) return;
  if (!program.node()->code()) return;

  std::string title = name + " Shader Code";
  wxFrame* frame = new wxFrame(0, -1, title.c_str());

  wxTextCtrl* control = new wxTextCtrl(frame, -1, "",
                                       wxDefaultPosition,
                                       wxDefaultSize,
                                       wxTE_MULTILINE | wxTE_READONLY);

#ifndef NO_TEXT_WINDOW_STREAM
  std::ostream stream(control);
  program.node()->code()->print(stream);
#else
  std::ostringstream s;
  program.node()->code()->print(s);
  control->AppendText(s.str().c_str());
#endif

  frame->Show();
}

void ShrikeFrame::showInterface(ShProgram program,
                                const std::string& name)
{
  if (!program.node()) return;
  if (!program.node()->code()) return;

  std::string title = name + " Shader Interface";
  wxFrame* frame = new wxFrame(0, -1, title.c_str());

  wxTextCtrl* control = new wxTextCtrl(frame, -1, "",
                                       wxDefaultPosition,
                                       wxDefaultSize,
                                       wxTE_MULTILINE | wxTE_READONLY);

  control->AppendText(program.describe_interface().c_str());

  frame->Show();
}

void ShrikeFrame::fullscreen(wxCommandEvent& event)
{
  setFullscreen(event.IsChecked());
}

void ShrikeFrame::wireframe(wxCommandEvent& event)
{
  m_canvas->SetCurrent();

  if (event.IsChecked()) {
    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
  } else {
    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  }
}

void ShrikeFrame::setFullscreen(bool fs)
{
  ShowFullScreen(fs);
  if (fs) {
    m_hsplitter->Unsplit(m_shaderList);
  } else {
    if (!m_hsplitter->IsSplit()) {
      m_hsplitter->SplitVertically(m_shaderList, m_right_window,
                                   150);
      m_shaderList->Show();
    }
  }
  m_fullscreen = fs;
}

void ShrikeFrame::fps(wxCommandEvent& event)
{
  setFps(event.IsChecked());
}

void ShrikeFrame::setFps(bool fps)
{
  m_fps = fps;
  ShrikeCanvas::instance()->setShowFps(m_fps);
}

void ShrikeFrame::keyDown(wxKeyEvent& event)
{
  if (event.GetKeyCode() == WXK_ESCAPE) {
    if (m_fullscreen) {
      setFullscreen(false);
    }
  } else {
    event.Skip();
  }
}

ShrikeFrame* ShrikeFrame::instance()
{
  return m_instance;
}

void ShrikeFrame::screenshot(wxCommandEvent& event)
{
  wxFileDialog* dialog = new wxFileDialog(this, "Save Screenshot",
                                          ".", "",
                                          "PNG Files (*.png)|*.png", wxSAVE);
  if (dialog->ShowModal() == wxID_OK) {
    m_canvas->screenshot(dialog->GetPath().c_str());
  }
}

wxTreeCtrl* ShrikeFrame::initShaderList(wxWindow* parent)
{
  wxTreeCtrl* tree = new wxTreeCtrl(parent, SHRIKE_TREECTRL_SHADERS,
                                    wxDefaultPosition, wxDefaultSize,
                                    wxTR_HAS_BUTTONS | wxTR_HIDE_ROOT | wxTR_NO_LINES);

  wxTreeItemId root = tree->AddRoot("");

  std::map<std::string, wxTreeItemId> nodes;

  for (Shader::iterator I = Shader::begin(); I != Shader::end(); ++I) {
    Shader* shader = *I;
    std::list<std::string> nodelist;
    std::string name = shader->name();
    while (1) {
      std::string::size_type i = name.find(": ");
      if (i == std::string::npos) {
        nodelist.push_back(name);
        break;
      } else {
        nodelist.push_back(name.substr(0, i));
        name = name.substr(i + 2);
      }
    }

    wxTreeItemId last = root;
    std::string fullname;
    for (std::list<std::string>::iterator N = nodelist.begin();
         N != nodelist.end(); ++N) {
      std::list<std::string>::iterator M = N;
      ++M;
      std::string name = *N;
      if (!fullname.empty()) fullname += ":";
      fullname += name;
      ShaderTreeData* data = 0;
      if (M == nodelist.end()) data = new ShaderTreeData(shader);
      if (nodes.find(fullname) == nodes.end()) {
        nodes[fullname] = tree->AppendItem(last, name.c_str(), -1, -1,
                                           data);
      } else {
        if (data && tree->GetItemData(nodes[fullname]) == 0) {
          tree->SetItemData(nodes[fullname], data);
        }
      }
      last = nodes[fullname];
    }
  }

  tree->SortChildren(root);
  return tree;
}

ShrikeFrame* ShrikeFrame::m_instance = 0;

<commit_msg>Added plus/minus signs to top level shader list under Win32...<commit_after>// Sh: A GPU metaprogramming language.
//
// Copyright (c) 2003 University of Waterloo Computer Graphics Laboratory
// Project administrator: Michael D. McCool
// Authors: Zheng Qin, Stefanus Du Toit, Kevin Moule, Tiberiu S. Popa,
//          Michael D. McCool
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must
// not claim that you wrote the original software. If you use this
// software in a product, an acknowledgment in the product documentation
// would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must
// not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//////////////////////////////////////////////////////////////////////////////
#include <iostream>
#include <fstream>
#include <wx/splitter.h>
#include <wx/colordlg.h>
#include <wx/treectrl.h>
#include <sh/ShObjMesh.hpp>
#include "ShrikeFrame.hpp"
#include "ShrikeCanvas.hpp"
#include "Shader.hpp"
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

using namespace SH;
using namespace ShUtil;

BEGIN_EVENT_TABLE(ShrikeFrame, wxFrame)
  EVT_MENU(SHRIKE_MENU_OPEN_MODEL, ShrikeFrame::openModel)
  EVT_MENU(SHRIKE_MENU_QUIT, ShrikeFrame::quit)
  EVT_MENU(SHRIKE_MENU_SHADER_PROPS, ShrikeFrame::shaderProps)
  EVT_MENU(SHRIKE_MENU_SHADER_SHOW_VSH, ShrikeFrame::showVsh)
  EVT_MENU(SHRIKE_MENU_SHADER_SHOW_FSH, ShrikeFrame::showFsh)
  EVT_MENU(SHRIKE_MENU_SHADER_SHOW_VSHIF, ShrikeFrame::showVshInterface)
  EVT_MENU(SHRIKE_MENU_SHADER_SHOW_FSHIF, ShrikeFrame::showFshInterface)
  EVT_MENU(SHRIKE_MENU_SHADER_REINIT, ShrikeFrame::reinit)
  EVT_MENU(SHRIKE_MENU_VIEW_RESET, ShrikeFrame::resetView)
  EVT_MENU(SHRIKE_MENU_VIEW_SCREENSHOT, ShrikeFrame::screenshot)
  EVT_MENU(SHRIKE_MENU_VIEW_BACKGROUND, ShrikeFrame::setBackground)
  EVT_MENU(SHRIKE_MENU_VIEW_FULLSCREEN, ShrikeFrame::fullscreen)
  EVT_MENU(SHRIKE_MENU_VIEW_WIREFRAME, ShrikeFrame::wireframe)
  EVT_MENU(SHRIKE_MENU_VIEW_FPS, ShrikeFrame::fps)
  EVT_CLOSE(ShrikeFrame::close)
  EVT_KEY_DOWN(ShrikeFrame::keyDown)
  //  EVT_LISTBOX(SHRIKE_LISTBOX_SHADERS, ShrikeFrame::onShaderSelect)
  EVT_TREE_SEL_CHANGED(SHRIKE_TREECTRL_SHADERS, ShrikeFrame::onShaderSelect)
END_EVENT_TABLE()

struct ShaderTreeData : public wxTreeItemData {
  ShaderTreeData(Shader* shader)
    : shader(shader)
  {
  }

  Shader* shader;
};

ShrikeFrame::ShrikeFrame()
  : wxFrame(0, -1, "Shrike", wxDefaultPosition, wxSize(600, 400)),
    m_shader(0), m_fullscreen(false), m_fps(false)
{
  m_instance = this;
  CreateStatusBar();

  GetStatusBar()->SetStatusText("Hold down shift to rotate the light instead of the camera.");

  // Setup menus

  wxMenu* fileMenu = new wxMenu();
  fileMenu->Append(SHRIKE_MENU_OPEN_MODEL, "&Open Model");
  fileMenu->AppendSeparator();
  fileMenu->Append(SHRIKE_MENU_QUIT, "&Quit");

  wxMenu* shaderMenu = new wxMenu();
  shaderMenu->Append(SHRIKE_MENU_SHADER_PROPS, "&Properties");
  shaderMenu->AppendSeparator();
  shaderMenu->Append(SHRIKE_MENU_SHADER_REINIT, "Re&initialize");
  shaderMenu->AppendSeparator();
  shaderMenu->Append(SHRIKE_MENU_SHADER_SHOW_VSHIF, "Show &vertex interface");
  shaderMenu->Append(SHRIKE_MENU_SHADER_SHOW_FSHIF, "Show &fragment interface");
  shaderMenu->AppendSeparator();
  shaderMenu->Append(SHRIKE_MENU_SHADER_SHOW_VSH, "Show &vertex assembly");
  shaderMenu->Append(SHRIKE_MENU_SHADER_SHOW_FSH, "Show &fragment assembly");

  wxMenu* viewMenu = new wxMenu();
  viewMenu->Append(SHRIKE_MENU_VIEW_RESET, "&Reset");
  viewMenu->Append(SHRIKE_MENU_VIEW_BACKGROUND, "Set &background colour...");
  viewMenu->AppendCheckItem(SHRIKE_MENU_VIEW_FULLSCREEN, "Fullscreen");
  viewMenu->AppendCheckItem(SHRIKE_MENU_VIEW_WIREFRAME, "&Wireframe");
  viewMenu->AppendCheckItem(SHRIKE_MENU_VIEW_FPS, "Show framerate");
  viewMenu->Append(SHRIKE_MENU_VIEW_SCREENSHOT, "Screenshot");

  wxMenuBar* menuBar = new wxMenuBar();
  menuBar->Append(fileMenu, "&File");
  menuBar->Append(shaderMenu, "&Shader");
  menuBar->Append(viewMenu, "&View");

  SetMenuBar(menuBar);

  m_hsplitter = new wxSplitterWindow(this, -1);

  m_shaderList = initShaderList(m_hsplitter);

  // Probably should do this somewhere else...
  ShObjMesh* model = 0;

  // TODO: FIXME
  std::ifstream infile(SHMEDIA_DIR "/objs/sphere50.obj");
  if (infile) {
    model = new ShObjMesh(infile);
  }

#if 0 // switch this on for fixed size separate preview window
  // TODO implement this properly in the GUI
  int width = 512 + 2;
  int height = 512 + 2;
  m_preview = new wxFrame(0, -1, "Shrike Preview", wxDefaultPosition, wxSize(width, height));
  m_canvas = new ShrikeCanvas(m_preview, model);
  m_panel = new UniformPanel(m_hsplitter);
  m_hsplitter->SplitVertically(m_shaderList, m_panel, 150);
  m_preview->Show();

#else
  m_right_window = new wxSplitterWindow(m_hsplitter, -1);
  m_canvas = new ShrikeCanvas(m_right_window, model);
  m_panel = new UniformPanel(m_right_window);
  m_hsplitter->SplitVertically(m_shaderList, m_right_window, 150);
  m_right_window->SplitHorizontally(m_canvas, m_panel, -100);
  m_right_window->SetMinimumPaneSize(40);
#endif

}

ShrikeFrame::~ShrikeFrame()
{
}

void ShrikeFrame::openModel(wxCommandEvent& event)
{
  wxFileDialog* dialog = new wxFileDialog(this, "Open Model",
                                          SHMEDIA_DIR "/objs", "",
                                          "OBJ Files (*.obj)|*.obj", wxOPEN);
  if (dialog->ShowModal() == wxID_OK) {
    std::ifstream infile(dialog->GetPath());
    if (infile) {
      ShObjMesh* model = new ShObjMesh(infile);
      m_canvas->setModel(model);
    } // TODO: Complain if opening file failed
  }
}

void ShrikeFrame::shaderProps(wxCommandEvent& event)
{
  if (!m_shader) return;
  if (m_shader->paramCount() == 0) return;
  ShrikePropsDialog dialog(this, m_shader);

  if (dialog.ShowModal() != wxID_OK) return;

  try {
    m_shader->init();
  } catch (const ShException& e) {
    std::cerr << e.message() << std::endl;
    return;
  }
  setShader(m_shader);
}

void ShrikeFrame::quit(wxCommandEvent& event)
{
  Destroy();
  //  Close(true);
}

void ShrikeFrame::close(wxCloseEvent& event)
{
  Destroy();
}

void ShrikeFrame::onShaderSelect(wxTreeEvent& event)
{
  wxTreeItemId item = event.GetItem();
  ShaderTreeData* data =
    dynamic_cast<ShaderTreeData*>(m_shaderList->GetItemData(item));
  if (!data) return;
  Shader* shader = data->shader;
  setShader(shader);
}

void ShrikeFrame::setShader(Shader* shader)
{
  m_canvas->SetCurrent();
  try {
    if (shader) shader->firstTimeInit();
  } catch (const ShException& e) {
    std::cerr << e.message() << std::endl;
    return;
  }
  if (shader) shader->bind();
  m_canvas->setShader(shader);
  m_canvas->render();
  m_panel->setShader(shader);
  m_shader = shader;
}

void ShrikeFrame::showVsh(wxCommandEvent& event)
{
  if (!m_shader) return;
  showProgram(m_shader->vertex(), "Vertex");
}

void ShrikeFrame::showFsh(wxCommandEvent& event)
{
  if (!m_shader) return;
  showProgram(m_shader->fragment(), "Fragment");
}

void ShrikeFrame::showVshInterface(wxCommandEvent& event)
{
  if (!m_shader) return;
  showInterface(m_shader->vertex(), "Vertex");
}

void ShrikeFrame::showFshInterface(wxCommandEvent& event)
{
  if (!m_shader) return;
  showInterface(m_shader->fragment(), "Fragment");
}

void ShrikeFrame::reinit(wxCommandEvent& event)
{
  if (!m_shader) return;
  try {
    m_shader->init();
  } catch (const ShException& e) {
    std::cerr << e.message() << std::endl;
    return;
  }
  setShader(m_shader);
}

void ShrikeFrame::resetView(wxCommandEvent& event)
{
  m_canvas->resetView();
}

void ShrikeFrame::setBackground(wxCommandEvent& event)
{
  wxColourDialog dialog(this);

  if (dialog.ShowModal() != wxID_OK) return;

  wxColour c = dialog.GetColourData().GetColour();
  m_canvas->setBackground(c.Red(), c.Green(), c.Blue());
}

void ShrikeFrame::showProgram(ShProgram program,
                              const std::string& name)
{
  if (!program.node()) return;
  if (!program.node()->code()) return;

  std::string title = name + " Shader Code";
  wxFrame* frame = new wxFrame(0, -1, title.c_str());

  wxTextCtrl* control = new wxTextCtrl(frame, -1, "",
                                       wxDefaultPosition,
                                       wxDefaultSize,
                                       wxTE_MULTILINE | wxTE_READONLY);

#ifndef NO_TEXT_WINDOW_STREAM
  std::ostream stream(control);
  program.node()->code()->print(stream);
#else
  std::ostringstream s;
  program.node()->code()->print(s);
  control->AppendText(s.str().c_str());
#endif

  frame->Show();
}

void ShrikeFrame::showInterface(ShProgram program,
                                const std::string& name)
{
  if (!program.node()) return;
  if (!program.node()->code()) return;

  std::string title = name + " Shader Interface";
  wxFrame* frame = new wxFrame(0, -1, title.c_str());

  wxTextCtrl* control = new wxTextCtrl(frame, -1, "",
                                       wxDefaultPosition,
                                       wxDefaultSize,
                                       wxTE_MULTILINE | wxTE_READONLY);

  control->AppendText(program.describe_interface().c_str());

  frame->Show();
}

void ShrikeFrame::fullscreen(wxCommandEvent& event)
{
  setFullscreen(event.IsChecked());
}

void ShrikeFrame::wireframe(wxCommandEvent& event)
{
  m_canvas->SetCurrent();

  if (event.IsChecked()) {
    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
  } else {
    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  }
}

void ShrikeFrame::setFullscreen(bool fs)
{
  ShowFullScreen(fs);
  if (fs) {
    m_hsplitter->Unsplit(m_shaderList);
  } else {
    if (!m_hsplitter->IsSplit()) {
      m_hsplitter->SplitVertically(m_shaderList, m_right_window,
                                   150);
      m_shaderList->Show();
    }
  }
  m_fullscreen = fs;
}

void ShrikeFrame::fps(wxCommandEvent& event)
{
  setFps(event.IsChecked());
}

void ShrikeFrame::setFps(bool fps)
{
  m_fps = fps;
  ShrikeCanvas::instance()->setShowFps(m_fps);
}

void ShrikeFrame::keyDown(wxKeyEvent& event)
{
  if (event.GetKeyCode() == WXK_ESCAPE) {
    if (m_fullscreen) {
      setFullscreen(false);
    }
  } else {
    event.Skip();
  }
}

ShrikeFrame* ShrikeFrame::instance()
{
  return m_instance;
}

void ShrikeFrame::screenshot(wxCommandEvent& event)
{
  wxFileDialog* dialog = new wxFileDialog(this, "Save Screenshot",
                                          ".", "",
                                          "PNG Files (*.png)|*.png", wxSAVE);
  if (dialog->ShowModal() == wxID_OK) {
    m_canvas->screenshot(dialog->GetPath().c_str());
  }
}

wxTreeCtrl* ShrikeFrame::initShaderList(wxWindow* parent)
{
#ifndef WIN32
  wxTreeCtrl* tree = new wxTreeCtrl(parent, SHRIKE_TREECTRL_SHADERS,
                                    wxDefaultPosition, wxDefaultSize,
                                    wxTR_HAS_BUTTONS | wxTR_HIDE_ROOT | wxTR_NO_LINES);
#else
  wxTreeCtrl* tree = new wxTreeCtrl(parent, SHRIKE_TREECTRL_SHADERS,
                                    wxDefaultPosition, wxDefaultSize,
                                    wxTR_HAS_BUTTONS | wxTR_HIDE_ROOT | wxTR_LINES_AT_ROOT);
#endif

  wxTreeItemId root = tree->AddRoot("");

  std::map<std::string, wxTreeItemId> nodes;

  for (Shader::iterator I = Shader::begin(); I != Shader::end(); ++I) {
    Shader* shader = *I;
    std::list<std::string> nodelist;
    std::string name = shader->name();
    while (1) {
      std::string::size_type i = name.find(": ");
      if (i == std::string::npos) {
        nodelist.push_back(name);
        break;
      } else {
        nodelist.push_back(name.substr(0, i));
        name = name.substr(i + 2);
      }
    }

    wxTreeItemId last = root;
    std::string fullname;
    for (std::list<std::string>::iterator N = nodelist.begin();
         N != nodelist.end(); ++N) {
      std::list<std::string>::iterator M = N;
      ++M;
      std::string name = *N;
      if (!fullname.empty()) fullname += ":";
      fullname += name;
      ShaderTreeData* data = 0;
      if (M == nodelist.end()) data = new ShaderTreeData(shader);
      if (nodes.find(fullname) == nodes.end()) {
        nodes[fullname] = tree->AppendItem(last, name.c_str(), -1, -1,
                                           data);
      } else {
        if (data && tree->GetItemData(nodes[fullname]) == 0) {
          tree->SetItemData(nodes[fullname], data);
        }
      }
      last = nodes[fullname];
    }
  }

  tree->SortChildren(root);
  return tree;
}

ShrikeFrame* ShrikeFrame::m_instance = 0;

<|endoftext|>


<commit_before>//
// OCCAM
//
// Copyright (c) 2011-2012, SRI International
//
//  All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice, this
//   list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice,
//   this list of conditions and the following disclaimer in the documentation
//   and/or other materials provided with the distribution.
//
// * Neither the name of SRI International nor the names of its contributors may
//   be used to endorse or promote products derived from this software without
//   specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//

#include "llvm/IR/Function.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Value.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/ValueMap.h"
#include "llvm/Transforms/Utils/Cloning.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/IR/InstIterator.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Analysis/AliasAnalysis.h"

#include "llvm/ADT/ArrayRef.h"

#include "PrevirtTypes.h"
#include "Specializer.h"

#include <fstream>

using namespace llvm;

namespace previrt
{
  std::string
  specializeName(Function* f, std::vector<std::string>& args)
  {
    args.clear();
    //iam    std::string fn = f->getNameStr();
    std::string fn = f->getName().str();

    int idx = fn.find('(');
    if (idx != -1 && fn[fn.length()-1] == ')') {
      std::string base = fn.substr(0, idx);
      idx++;
      unsigned int st = idx;
      bool in_str = false;
      while (st < fn.length()-1) {
        idx = st;
        while (true) {
          if (fn[idx] == '"') {
            in_str = !in_str;
          } else if (!in_str) {
            if (fn[idx] == ',') {
              args.push_back(fn.substr(st, idx-st));
              break;
            } else if (fn[idx] == ')') {
              args.push_back(fn.substr(st, idx-st));
              break;
            }
          } else {
            if (fn[idx] == '\\') {
              idx += 2;
            }
          }
          idx++;
        }
        st = idx + 1;
      }
      return base;
    } else {
      unsigned alen = f->arg_size();
      args.reserve(alen);
      for (unsigned int i = 0; i < alen; ++i)
        args.push_back("?");
      //iam      return f->getNameStr();
      return f->getName().str();
    }
  }

  Function*
  specializeFunction(Function *f, Value*const* args)
  // make a copy of f
  // specialize on the arguments, a null means that that argument isn't known
  {
    assert(!f->isDeclaration());
    ValueToValueMapTy vmap;

    unsigned int i = 0;
    unsigned int j = 0;
    std::vector<std::string> argNames;

    std::string baseName = specializeName(f, argNames);

    for (Function::arg_iterator itr = f->arg_begin(); itr != f->arg_end(); itr++, i++) {
      while (argNames[j] != "?") j++;
      if (args[i] != NULL) {
        Value* arg = (Value*) &(*itr);

        assert(arg->getType() == args[i]->getType()
	       && "Specializing argument with concrete value of wrong type!");

        vmap.insert(typename ValueToValueMapTy::value_type (arg, args[i]));
        PrevirtType pt = PrevirtType::abstract(args[i]);
        argNames[j] = pt.to_string();
        /*
        if (const ConstantInt* ci = dyn_cast<const ConstantInt> (args[i])) {
          argNames[j] = ci->getValue().toString(10, true);
        } else if (const Constant* c = dyn_cast<const Constant>(args[i])) {
          if (c->isNullValue()) {
            argNames[j] = "null";
          } else {
            assert(false);
          }
        } else if (const )
        } else {
          assert(false);
        }
        */
      }
      j++;
    }
    assert (i == f->arg_size());

    baseName += "(";
    for (std::vector<std::string>::const_iterator it = argNames.begin(), be = argNames.begin(), en = argNames.end(); it != en; ++it) {
      if (it != be) baseName += ",";
      baseName += *it;
    }
    baseName += ")";

    Function *result = f->getParent()->getFunction(baseName);
    // If specialized function already exists, no reason
    // to create another one. In fact, can cause the process
    // to diverge. XXX This needs to be a more sophisticated
    // check
    if (!result) {
      ClonedCodeInfo info;
      result = llvm::CloneFunction(f, vmap, &info);
      result->setName(baseName);
    }
    return result;
  }

  Function*
  specializeFunction(Function *f, const std::vector<Value*>& args)
  {
    assert(!f->isDeclaration());
    assert(f->arg_size() == args.size());
    Function *nfunc = specializeFunction(f, args.data());

    // Debugging code for detecting some mis-specializations.
    // Requires #include "llvm/Analysis/Verifier.h"
    //errs() << "\nSpecializing " << f->getName() << "...\n";
    //errs() << "Verifying " << nfunc->getName() << "... ";
    //if (llvm::verifyFunction(*nfunc, llvm::ReturnStatusAction)) {
    //	errs() << "ok\n";
    //} else {
    //  errs() << "bad\n";
    //}

    return nfunc;
  }

  /*
   * Specialize a call site and return the new instruction
   */
  Instruction*
  specializeCallSite(Instruction* I,
      llvm::Function* nfunc, const std::vector<unsigned>& perm)
  {
    assert((nfunc->isVarArg() && nfunc->arg_size() <= perm.size())
        || (!nfunc->isVarArg() && nfunc->arg_size() == perm.size()));
    const size_t specialized_arg_count = perm.size(); //nfunc->arg_size();

    Instruction* newInst = NULL;
    if (CallInst* ci = dyn_cast<CallInst>(I)) {

      std::vector<Value*> newOperands;
      newOperands.reserve (specialized_arg_count);

      for (size_t j = 0; j < specialized_arg_count; ++j) {
        newOperands.push_back (ci->getArgOperand(perm[j]));
      }

      if (ci->hasName()) {
	newInst = CallInst::Create(nfunc, newOperands, ci->getName());
      } else {
	newInst = CallInst::Create(nfunc, newOperands);
      }
    } else if (InvokeInst* ci = dyn_cast<InvokeInst>(I)) {

      std::vector<Value*> newOperands;
      newOperands.reserve(specialized_arg_count);
      for (size_t j = 0; j < specialized_arg_count; ++j) {
        newOperands.push_back(ci->getArgOperand(perm[j]));
      }

      newInst = InvokeInst::Create(nfunc, ci->getNormalDest(),
				   ci->getUnwindDest(), newOperands, ci->getName());

    } else {
      assert(false && "specializeCallSite got non-callsite");
      return NULL; // Unreachable
    }

    return newInst;
  }

  bool checkAlias(Function * f, CallInst * ci, AAResults & AA){

      bool debug = false;
      if(debug) errs()<<"Checking Alias \n";

      for(unsigned int i = 0; i < ci->getNumOperands(); i++){
        Value * callArg = ci->getOperand(i);
        for(Function::arg_iterator itr = f->arg_begin(); itr != f->arg_end(); itr++, i++) {
          Value * funcArg = (Value*) &(*itr);
          if(!AA.isNoAlias(callArg, funcArg))
          {
             if(debug)
               errs()<<*callArg<<" and "<<*funcArg<<" may ALIAS **** \n";
             return true;
          }
        }
      }

      return false;
  }

  bool
  canSpecialize(Function* f, AAResults & AA)
  {
    if (f->isDeclaration())
      return false;

    bool canSpec = true;
    for (inst_iterator I = inst_begin(f), E = inst_end(f); I != E; ++I) {
      if (CallInst* ci = dyn_cast<CallInst>(&*I)) {
        if (ci->isInlineAsm()) {
          canSpec = canSpec & !checkAlias(f, ci, AA);
        }
      }
    }

    return canSpec;
  }

  GlobalVariable*
  materializeStringLiteral(llvm::Module& m, const char* data)
  {
    Constant* ary = llvm::ConstantDataArray::getString(m.getContext(), data, true);
    GlobalVariable* gv = new GlobalVariable(m, ary->getType(), true, GlobalValue::LinkageTypes::PrivateLinkage, ary, "");
    gv->setConstant(true);

    return gv;
  }

  Constant*
  charStarFromStringConstant(llvm::Module& m, llvm::Constant* v)
  {
    errs()<<"CHAR STAR \n\n\n\n\n" ;
    Constant* zero = ConstantInt::getSigned(IntegerType::getInt32Ty(m.getContext()), 0);
    Constant* args[2] = {zero, zero};
    ArrayRef<Constant*> ar_args(args, 2);
    Type * constantType = cast<PointerType>(v->getType()->getScalarType())
    ->getContainedType(0u);
    return ConstantExpr::getGetElementPtr(constantType, v, ar_args, false);
  }

}
<commit_msg>removed check for aliasing between formal arguments of function to be specialized and actual arguments to an asm inline within<commit_after>//
// OCCAM
//
// Copyright (c) 2011-2012, SRI International
//
//  All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice, this
//   list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice,
//   this list of conditions and the following disclaimer in the documentation
//   and/or other materials provided with the distribution.
//
// * Neither the name of SRI International nor the names of its contributors may
//   be used to endorse or promote products derived from this software without
//   specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//

#include "llvm/IR/Function.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Value.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/ValueMap.h"
#include "llvm/Transforms/Utils/Cloning.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/IR/InstIterator.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Analysis/AliasAnalysis.h"

#include "llvm/ADT/ArrayRef.h"

#include "PrevirtTypes.h"
#include "Specializer.h"

#include <fstream>

using namespace llvm;

namespace previrt
{
  std::string
  specializeName(Function* f, std::vector<std::string>& args)
  {
    args.clear();
    //iam    std::string fn = f->getNameStr();
    std::string fn = f->getName().str();

    int idx = fn.find('(');
    if (idx != -1 && fn[fn.length()-1] == ')') {
      std::string base = fn.substr(0, idx);
      idx++;
      unsigned int st = idx;
      bool in_str = false;
      while (st < fn.length()-1) {
        idx = st;
        while (true) {
          if (fn[idx] == '"') {
            in_str = !in_str;
          } else if (!in_str) {
            if (fn[idx] == ',') {
              args.push_back(fn.substr(st, idx-st));
              break;
            } else if (fn[idx] == ')') {
              args.push_back(fn.substr(st, idx-st));
              break;
            }
          } else {
            if (fn[idx] == '\\') {
              idx += 2;
            }
          }
          idx++;
        }
        st = idx + 1;
      }
      return base;
    } else {
      unsigned alen = f->arg_size();
      args.reserve(alen);
      for (unsigned int i = 0; i < alen; ++i)
        args.push_back("?");
      //iam      return f->getNameStr();
      return f->getName().str();
    }
  }

  Function*
  specializeFunction(Function *f, Value*const* args)
  // make a copy of f
  // specialize on the arguments, a null means that that argument isn't known
  {
    assert(!f->isDeclaration());
    ValueToValueMapTy vmap;

    unsigned int i = 0;
    unsigned int j = 0;
    std::vector<std::string> argNames;

    std::string baseName = specializeName(f, argNames);

    for (Function::arg_iterator itr = f->arg_begin(); itr != f->arg_end(); itr++, i++) {
      while (argNames[j] != "?") j++;
      if (args[i] != NULL) {
        Value* arg = (Value*) &(*itr);

        assert(arg->getType() == args[i]->getType()
	       && "Specializing argument with concrete value of wrong type!");

        vmap.insert(typename ValueToValueMapTy::value_type (arg, args[i]));
        PrevirtType pt = PrevirtType::abstract(args[i]);
        argNames[j] = pt.to_string();
        /*
        if (const ConstantInt* ci = dyn_cast<const ConstantInt> (args[i])) {
          argNames[j] = ci->getValue().toString(10, true);
        } else if (const Constant* c = dyn_cast<const Constant>(args[i])) {
          if (c->isNullValue()) {
            argNames[j] = "null";
          } else {
            assert(false);
          }
        } else if (const )
        } else {
          assert(false);
        }
        */
      }
      j++;
    }
    assert (i == f->arg_size());

    baseName += "(";
    for (std::vector<std::string>::const_iterator it = argNames.begin(), be = argNames.begin(), en = argNames.end(); it != en; ++it) {
      if (it != be) baseName += ",";
      baseName += *it;
    }
    baseName += ")";

    Function *result = f->getParent()->getFunction(baseName);
    // If specialized function already exists, no reason
    // to create another one. In fact, can cause the process
    // to diverge. XXX This needs to be a more sophisticated
    // check
    if (!result) {
      ClonedCodeInfo info;
      result = llvm::CloneFunction(f, vmap, &info);
      result->setName(baseName);
    }
    return result;
  }

  Function*
  specializeFunction(Function *f, const std::vector<Value*>& args)
  {
    assert(!f->isDeclaration());
    assert(f->arg_size() == args.size());
    Function *nfunc = specializeFunction(f, args.data());

    // Debugging code for detecting some mis-specializations.
    // Requires #include "llvm/Analysis/Verifier.h"
    //errs() << "\nSpecializing " << f->getName() << "...\n";
    //errs() << "Verifying " << nfunc->getName() << "... ";
    //if (llvm::verifyFunction(*nfunc, llvm::ReturnStatusAction)) {
    //	errs() << "ok\n";
    //} else {
    //  errs() << "bad\n";
    //}

    return nfunc;
  }

  /*
   * Specialize a call site and return the new instruction
   */
  Instruction*
  specializeCallSite(Instruction* I,
      llvm::Function* nfunc, const std::vector<unsigned>& perm)
  {
    assert((nfunc->isVarArg() && nfunc->arg_size() <= perm.size())
        || (!nfunc->isVarArg() && nfunc->arg_size() == perm.size()));
    const size_t specialized_arg_count = perm.size(); //nfunc->arg_size();

    Instruction* newInst = NULL;
    if (CallInst* ci = dyn_cast<CallInst>(I)) {

      std::vector<Value*> newOperands;
      newOperands.reserve (specialized_arg_count);

      for (size_t j = 0; j < specialized_arg_count; ++j) {
        newOperands.push_back (ci->getArgOperand(perm[j]));
      }

      if (ci->hasName()) {
	newInst = CallInst::Create(nfunc, newOperands, ci->getName());
      } else {
	newInst = CallInst::Create(nfunc, newOperands);
      }
    } else if (InvokeInst* ci = dyn_cast<InvokeInst>(I)) {

      std::vector<Value*> newOperands;
      newOperands.reserve(specialized_arg_count);
      for (size_t j = 0; j < specialized_arg_count; ++j) {
        newOperands.push_back(ci->getArgOperand(perm[j]));
      }

      newInst = InvokeInst::Create(nfunc, ci->getNormalDest(),
				   ci->getUnwindDest(), newOperands, ci->getName());

    } else {
      assert(false && "specializeCallSite got non-callsite");
      return NULL; // Unreachable
    }

    return newInst;
  }

  bool checkAlias(Function * f, CallInst * ci, AAResults & AA){

      bool debug = false;
      if(debug) errs()<<"Checking Alias \n";

      for(unsigned int i = 0; i < ci->getNumOperands(); i++){
        Value * callArg = ci->getOperand(i);
        for(Function::arg_iterator itr = f->arg_begin(); itr != f->arg_end(); itr++, i++) {
          Value * funcArg = (Value*) &(*itr);
          if(!AA.isNoAlias(callArg, funcArg))
          {
             if(debug)
               errs()<<*callArg<<" and "<<*funcArg<<" may ALIAS **** \n";
             return true;
          }
        }
      }

      return false;
  }

  bool
  canSpecialize(Function* f, AAResults & AA)
  {
    if (f->isDeclaration())
      return false;

    bool canSpec = true;
    for (inst_iterator I = inst_begin(f), E = inst_end(f); I != E; ++I) {
      if (CallInst* ci = dyn_cast<CallInst>(&*I)) {
        if (ci->isInlineAsm()) {
          // canSpec = canSpec & !checkAlias(f, ci, AA);
        }
      }
    }

    return canSpec;
  }

  GlobalVariable*
  materializeStringLiteral(llvm::Module& m, const char* data)
  {
    Constant* ary = llvm::ConstantDataArray::getString(m.getContext(), data, true);
    GlobalVariable* gv = new GlobalVariable(m, ary->getType(), true, GlobalValue::LinkageTypes::PrivateLinkage, ary, "");
    gv->setConstant(true);

    return gv;
  }

  Constant*
  charStarFromStringConstant(llvm::Module& m, llvm::Constant* v)
  {
    errs()<<"CHAR STAR \n\n\n\n\n" ;
    Constant* zero = ConstantInt::getSigned(IntegerType::getInt32Ty(m.getContext()), 0);
    Constant* args[2] = {zero, zero};
    ArrayRef<Constant*> ar_args(args, 2);
    Type * constantType = cast<PointerType>(v->getType()->getScalarType())
    ->getContainedType(0u);
    return ConstantExpr::getGetElementPtr(constantType, v, ar_args, false);
  }

}
<|endoftext|>


<commit_before>//
// Created by fred on 06/12/16.
//

#include "frnetlib/TcpListener.h"

namespace fr
{

    const int yes = 1;
    const int no = 0;

    Socket::Status TcpListener::listen(const std::string &port)
    {
        addrinfo *info;
        addrinfo hints;

        memset(&hints, 0, sizeof(addrinfo));

        hints.ai_family = ai_family;
        hints.ai_socktype = SOCK_STREAM; //TCP
        hints.ai_flags = AI_PASSIVE; //Have the IP filled in for us

        if(getaddrinfo(NULL, port.c_str(), &hints, &info) != 0)
        {
            return Socket::Status::Unknown;
        }
        //Try each of the results until we listen successfully
        addrinfo *c = nullptr;
        for(c = info; c != nullptr; c = c->ai_next)
        {
            //Attempt to connect
            if((socket_descriptor = socket(c->ai_family, c->ai_socktype, c->ai_protocol)) == INVALID_SOCKET)
            {
                continue;
            }
            //Set address re-use option
            if(setsockopt(socket_descriptor, SOL_SOCKET, SO_REUSEADDR, (char*)&yes, sizeof(int)) == SOCKET_ERROR)
            {
                continue;
            }

            //If it's an IPv6 interface, attempt to allow IPv4 connections
            if(c->ai_family == AF_INET6)
            {
                setsockopt(socket_descriptor, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&no, sizeof(no));
            }

            //Attempt to bind
            if(bind(socket_descriptor, c->ai_addr, c->ai_addrlen) == SOCKET_ERROR)
            {
                closesocket(socket_descriptor);
                continue;
            }
            break;
        }

        //Check that we've actually bound
        if(c == nullptr)
        {
            return Socket::Status::BindFailed;
        }

        //We're done with this now, cleanup
        freeaddrinfo(info);

        //Listen to socket
        if(::listen(socket_descriptor, 10) == SOCKET_ERROR)
        {
            return Socket::ListenFailed;
        }
        return Socket::Success;
    }

    Socket::Status TcpListener::accept(Socket &client_)
    {
        //Cast to TcpSocket. Will throw bad cast on failure.
        TcpSocket &client = dynamic_cast<TcpSocket&>(client_);

        //Prepare to wait for the client
        sockaddr_storage client_addr;
        int client_descriptor;
        char client_printable_addr[INET6_ADDRSTRLEN];

        //Accept one
        socklen_t client_addr_len = sizeof client_addr;
        client_descriptor = ::accept(socket_descriptor, (sockaddr*)&client_addr, &client_addr_len);
        if(client_descriptor == SOCKET_ERROR)
            return Socket::Unknown;

        //Get printable address. If we failed then set it as just 'unknown'
        int err = getnameinfo((sockaddr*)&client_addr, client_addr_len, client_printable_addr, sizeof(client_printable_addr), 0,0,NI_NUMERICHOST);
        if(err != 0)
            strcpy(client_printable_addr, "unknown");

        //Set client data
        client.set_descriptor(client_descriptor);
        client.set_remote_address(client_printable_addr);

        return Socket::Success;
    }

    void TcpListener::shutdown()
    {
        ::shutdown(socket_descriptor, 0);
    }
}<commit_msg>Cast fix<commit_after>//
// Created by fred on 06/12/16.
//

#include "frnetlib/TcpListener.h"

namespace fr
{

    const int yes = 1;
    const int no = 0;

    Socket::Status TcpListener::listen(const std::string &port)
    {
        addrinfo *info;
        addrinfo hints;

        memset(&hints, 0, sizeof(addrinfo));

        hints.ai_family = ai_family;
        hints.ai_socktype = SOCK_STREAM; //TCP
        hints.ai_flags = AI_PASSIVE; //Have the IP filled in for us

        if(getaddrinfo(NULL, port.c_str(), &hints, &info) != 0)
        {
            return Socket::Status::Unknown;
        }
        //Try each of the results until we listen successfully
        addrinfo *c = nullptr;
        for(c = info; c != nullptr; c = c->ai_next)
        {
            //Attempt to connect
            if((socket_descriptor = socket(c->ai_family, c->ai_socktype, c->ai_protocol)) == INVALID_SOCKET)
            {
                continue;
            }
            //Set address re-use option
            if(setsockopt(socket_descriptor, SOL_SOCKET, SO_REUSEADDR, (char*)&yes, sizeof(int)) == SOCKET_ERROR)
            {
                continue;
            }

            //If it's an IPv6 interface, attempt to allow IPv4 connections
            if(c->ai_family == AF_INET6)
            {
                setsockopt(socket_descriptor, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&no, sizeof(no));
            }

            //Attempt to bind
            if(bind(socket_descriptor, c->ai_addr, c->ai_addrlen) == SOCKET_ERROR)
            {
                closesocket(socket_descriptor);
                continue;
            }
            break;
        }

        //Check that we've actually bound
        if(c == nullptr)
        {
            return Socket::Status::BindFailed;
        }

        //We're done with this now, cleanup
        freeaddrinfo(info);

        //Listen to socket
        if(::listen(socket_descriptor, 10) == SOCKET_ERROR)
        {
            return Socket::ListenFailed;
        }
        return Socket::Success;
    }

    Socket::Status TcpListener::accept(Socket &client_)
    {
        //Cast to TcpSocket. Will throw bad cast on failure.
        TcpSocket &client = dynamic_cast<TcpSocket&>(client_);

        //Prepare to wait for the client
        sockaddr_storage client_addr;
        int client_descriptor;
        char client_printable_addr[INET6_ADDRSTRLEN];

        //Accept one
        socklen_t client_addr_len = sizeof client_addr;
        client_descriptor = ::accept(socket_descriptor, (sockaddr*)&client_addr, &client_addr_len);
        if(client_descriptor == SOCKET_ERROR)
            return Socket::Unknown;

        //Get printable address. If we failed then set it as just 'unknown'
        int err = getnameinfo((sockaddr*)&client_addr, client_addr_len, client_printable_addr, sizeof(client_printable_addr), 0,0,NI_NUMERICHOST);
        if(err != 0)
            strcpy(client_printable_addr, "unknown");

        //Set client data
        client.set_descriptor(client_descriptor);
        client.set_remote_address(client_printable_addr);

        return Socket::Success;
    }

    void TcpListener::shutdown()
    {
        ::shutdown(socket_descriptor, 0);
    }
}<|endoftext|>


<commit_before>#include "../include/TgBotHelper.hpp"
#include "../include/CurlHelper.hpp"
#include <iostream>

tgb::TgBotHelper::TgBotHelper(std::string token)
: m_token{ token }
, m_lastRetrieved{ -1L }
{

}

void tgb::TgBotHelper::setOnNewMessageListener(std::function<void(const std::vector<Message> &messages)> onNewMessageListener)
{
	m_onNewMessageListener = onNewMessageListener;
}

bool tgb::TgBotHelper::sendMessage(const long chatId, const std::string message) const
{
	std::pair<std::string, bool> response{ CurlHelper::simplePost("https://api.telegram.org/bot" + m_token + "/sendMessage",
			"chat_id=" + std::to_string(chatId) + "&text=" + message) };
	bool success{ response.second };
	if (success)
	{
		// Post was successful
		nlohmann::json jsn = nlohmann::json::parse(response.first);
		// Check if bot api reports successfully processing , too
		success = jsn.value("ok", false);
	}
	return success;
}

bool tgb::TgBotHelper::sendPhoto(const long chatId, const std::string fileName) const
{

	std::string command{ "chat_id=" + std::to_string(chatId) + " -F photo='@" + fileName + "'" };
	std::cout << "Command: " << command << std::endl;
	std::pair<std::string, bool> response{ CurlHelper::simplePost("https://api.telegram.org/bot" + m_token + "/sendPhoto",
			command) };

	bool success{ response.second };
	if (success)
	{
		// Post was successful
		nlohmann::json jsn = nlohmann::json::parse(response.first);
		// Check if bot api reports successfully processing , too
		success = jsn.value("ok", false);
	}
	return success;
}

std::pair<std::vector<tgb::Message>, bool> tgb::TgBotHelper::getNewTextUpdates()
{
	// With specifying the last retrieved message + 1, we guarantee that we only get updates we dont have already get
	std::pair<std::string, bool> response{ CurlHelper::simplePost("https://api.telegram.org/bot" + m_token + "/getUpdates",
			"offset=" + std::to_string(m_lastRetrieved + 1)) };

	std::vector<Message> messages;
	bool success{ response.second };
	if (success)
	{
		// Post was successful
		nlohmann::json jsn = nlohmann::json::parse(response.first);
		// Check if bot api reports successfully processing , too
		success = jsn.value("ok", false);
		if (success)
		{
			// Get all resulting updates
			nlohmann::json::array_t resultArr = jsn.value("result", nlohmann::json::array_t());
			for (auto entry : resultArr)
			{

				long updateId{ entry.value("update_id", -1L) };
				// message
				nlohmann::json jsonMessage = entry.value("message", nlohmann::json());
				long messageId{ jsonMessage.value("message_id", -1L) };
				long date{ jsonMessage.value("date", -1L) };
				std::string text{ jsonMessage.value("text", "") };
				// message->chat
				std::shared_ptr<Message::Chat> chat{ getChatFromJson(jsonMessage) };

				// message->from.
				std::shared_ptr<Message::User> user{ getUserFromJson(jsonMessage) };

				messages.push_back({ messageId, date, text, std::move(chat), std::move(user) });

				// Make m_lastRetrieved update to actual update_id (When the update_id was in entry)
				if (updateId > -1)
				{
					m_lastRetrieved = updateId;
				}
			}
		}

	}
	return std::make_pair(messages, success);
}

void tgb::TgBotHelper::handleUpdates()
{
	std::pair<std::vector<Message>, bool> resultUpdates{ getNewTextUpdates() };
	std::vector<Message> messages{ resultUpdates.first };
	// Call the listener when there are new messages
	if (messages.size() > 0 && m_onNewMessageListener)
	{
		m_onNewMessageListener(messages);
	}
}

std::shared_ptr<tgb::Message::Chat> tgb::TgBotHelper::getChatFromJson(const nlohmann::json &json) const
{

	std::shared_ptr<Message::Chat> chat{ nullptr };
	if (json.count("from") > 0)
	{
		nlohmann::json jsonChat = json.value("chat", nlohmann::json());
		long id{ jsonChat.value("id", -1L) };
		std::string type{ jsonChat.value("type", "") };
		std::string title{ jsonChat.value("title", "") };
		std::string username{ jsonChat.value("username", "") };
		std::string firstName{ jsonChat.value("first_name", "") };
		std::string lastName{ jsonChat.value("last_name", "") };
		bool allMembersAdmins{ jsonChat.value("all_members_are_administrators", false) };
		chat = std::make_shared<Message::Chat>(id, type,
			title, username, firstName, lastName, allMembersAdmins);
	}
	return std::move(chat);

}

std::shared_ptr<tgb::Message::User> tgb::TgBotHelper::getUserFromJson(const nlohmann::json &json) const
{
	std::shared_ptr<Message::User> user{ nullptr };
	if (json.count("from") > 0)
	{
		nlohmann::json jsonFrom = json.value("from", nlohmann::json());
		long id{ jsonFrom.value("id", -1L) };
		std::string username{ jsonFrom.value("username", "") };
		std::string firstName{ jsonFrom.value("first_name", "") };
		std::string lastName{ jsonFrom.value("last_name", "") };
		user = std::make_shared<Message::User>(id, username,
			firstName, lastName);
	}
	return std::move(user);
}
<commit_msg>Implent method to send photo<commit_after>#include "../include/TgBotHelper.hpp"
#include "../include/CurlHelper.hpp"
#include <iostream>

tgb::TgBotHelper::TgBotHelper(std::string token)
: m_token{ token }
, m_lastRetrieved{ -1L }
{

}

void tgb::TgBotHelper::setOnNewMessageListener(std::function<void(const std::vector<Message> &messages)> onNewMessageListener)
{
	m_onNewMessageListener = onNewMessageListener;
}

bool tgb::TgBotHelper::sendMessage(const long chatId, const std::string message) const
{
	std::pair<std::string, bool> response{ CurlHelper::simplePost("https://api.telegram.org/bot" + m_token + "/sendMessage",
			"chat_id=" + std::to_string(chatId) + "&text=" + message) };
	bool success{ response.second };
	if (success)
	{
		// Post was successful
		nlohmann::json jsn = nlohmann::json::parse(response.first);
		// Check if bot api reports successfully processing , too
		success = jsn.value("ok", false);
	}
	return success;
}

bool tgb::TgBotHelper::sendPhoto(const long chatId, const std::string fileName) const
{
	std::pair<std::string, bool> response{ CurlHelper::fileFormPost("https://api.telegram.org/bot" + m_token +
			"/sendPhoto?chat_id=" +  std::to_string(chatId), "photo", fileName) };

	bool success{ response.second };
	if (success)
	{
		// Post was successful
		nlohmann::json jsn = nlohmann::json::parse(response.first);
		// Check if bot api reports successfully processing , too
		success = jsn.value("ok", false);
	}
	return success;
}

std::pair<std::vector<tgb::Message>, bool> tgb::TgBotHelper::getNewTextUpdates()
{
	// With specifying the last retrieved message + 1, we guarantee that we only get updates we dont have already get
	std::pair<std::string, bool> response{ CurlHelper::simplePost("https://api.telegram.org/bot" + m_token + "/getUpdates",
			"offset=" + std::to_string(m_lastRetrieved + 1)) };

	std::vector<Message> messages;
	bool success{ response.second };
	if (success)
	{
		// Post was successful
		nlohmann::json jsn = nlohmann::json::parse(response.first);
		// Check if bot api reports successfully processing , too
		success = jsn.value("ok", false);
		if (success)
		{
			// Get all resulting updates
			nlohmann::json::array_t resultArr = jsn.value("result", nlohmann::json::array_t());
			for (auto entry : resultArr)
			{

				long updateId{ entry.value("update_id", -1L) };
				// message
				nlohmann::json jsonMessage = entry.value("message", nlohmann::json());
				long messageId{ jsonMessage.value("message_id", -1L) };
				long date{ jsonMessage.value("date", -1L) };
				std::string text{ jsonMessage.value("text", "") };
				// message->chat
				std::shared_ptr<Message::Chat> chat{ getChatFromJson(jsonMessage) };

				// message->from.
				std::shared_ptr<Message::User> user{ getUserFromJson(jsonMessage) };

				messages.push_back({ messageId, date, text, std::move(chat), std::move(user) });

				// Make m_lastRetrieved update to actual update_id (When the update_id was in entry)
				if (updateId > -1)
				{
					m_lastRetrieved = updateId;
				}
			}
		}

	}
	return std::make_pair(messages, success);
}

void tgb::TgBotHelper::handleUpdates()
{
	std::pair<std::vector<Message>, bool> resultUpdates{ getNewTextUpdates() };
	std::vector<Message> messages{ resultUpdates.first };
	// Call the listener when there are new messages
	if (messages.size() > 0 && m_onNewMessageListener)
	{
		m_onNewMessageListener(messages);
	}
}

std::shared_ptr<tgb::Message::Chat> tgb::TgBotHelper::getChatFromJson(const nlohmann::json &json) const
{

	std::shared_ptr<Message::Chat> chat{ nullptr };
	if (json.count("from") > 0)
	{
		nlohmann::json jsonChat = json.value("chat", nlohmann::json());
		long id{ jsonChat.value("id", -1L) };
		std::string type{ jsonChat.value("type", "") };
		std::string title{ jsonChat.value("title", "") };
		std::string username{ jsonChat.value("username", "") };
		std::string firstName{ jsonChat.value("first_name", "") };
		std::string lastName{ jsonChat.value("last_name", "") };
		bool allMembersAdmins{ jsonChat.value("all_members_are_administrators", false) };
		chat = std::make_shared<Message::Chat>(id, type,
			title, username, firstName, lastName, allMembersAdmins);
	}
	return std::move(chat);

}

std::shared_ptr<tgb::Message::User> tgb::TgBotHelper::getUserFromJson(const nlohmann::json &json) const
{
	std::shared_ptr<Message::User> user{ nullptr };
	if (json.count("from") > 0)
	{
		nlohmann::json jsonFrom = json.value("from", nlohmann::json());
		long id{ jsonFrom.value("id", -1L) };
		std::string username{ jsonFrom.value("username", "") };
		std::string firstName{ jsonFrom.value("first_name", "") };
		std::string lastName{ jsonFrom.value("last_name", "") };
		user = std::make_shared<Message::User>(id, username,
			firstName, lastName);
	}
	return std::move(user);
}
<|endoftext|>


<commit_before>#pragma once

#include <vector>
#include <gtest/gtest.h>

#include "longestsubstrworep.hxx"

using std::vector;

namespace {
  class LongestSubStringWithoutRepetitionTest : public testing::Test
  {
  protected:
    LongestSubStringWithoutRepetitionTest(void) {}
    virtual ~LongestSubStringWithoutRepetitionTest(void) {}
    virtual void SetUp(void) {}
    virtual void TearDown(void) {}
  };

  TEST(LongestSubStringWithoutRepetitionTest, TwoSum1)
  {
    EXPECT_TRUE(false);
  }
}
<commit_msg>added two test cases<commit_after>#pragma once

#include <vector>
#include <string>
#include <gtest/gtest.h>

#include "longestsubstrworep.hxx"

using std::vector;

namespace {
  class LongestSubStringWithoutRepetitionTest : public testing::Test
  {
  protected:
    LongestSubStringWithoutRepetitionTest(void) {}
    virtual ~LongestSubStringWithoutRepetitionTest(void) {}
    virtual void SetUp(void) {}
    virtual void TearDown(void) {}
  };

  TEST(LongestSubStringWithoutRepetitionTest, LongestSub1)
  {
    const std::string input{"abcabcbb"};

    const auto actual = Solution{}.lengthOfLongestSubstring(input);
    decltype(actual) expected = 3;

    EXPECT_EQ(expected, actual);
  }

  TEST(LongestSubStringWithoutRepetitionTest, LongestSub2)
  {
    const std::string input{"bbbbb"};

    const auto actual = Solution{}.lengthOfLongestSubstring(input);
    decltype(actual) expected = 1;

    EXPECT_EQ(expected, actual);
  }

}
<|endoftext|>


<commit_before>// Copyright 2015 <Magazino GmbH>

#include <pylon_camera/pylon_camera_node.h>
#include <GenApi/GenApi.h>
#include <algorithm>
#include <cmath>
#include <vector>

namespace pylon_camera
{

PylonCameraNode::PylonCameraNode() :
        nh_("~"),
        pylon_camera_(NULL),
        pylon_camera_parameter_set_(),
        it_(new image_transport::ImageTransport(nh_)),
        img_raw_pub_(it_->advertiseCamera("image_raw", 10)),
        grab_images_raw_action_server_(nh_, "grab_images_raw",
            boost::bind(&PylonCameraNode::grabImagesRawActionExecuteCB, this, _1), false),
        set_sleeping_service_(nh_.advertiseService("set_sleeping_srv", &PylonCameraNode::setSleepingCallback, this)),
        target_brightness_(-42),
        brightness_service_running_(false),
        is_sleeping_(false)
{
    init();
}

bool PylonCameraNode::init()
{
    // Set parameter to open the desired camera
    if (!pylon_camera_parameter_set_.readFromRosParameterServer(nh_))
    {
        ROS_ERROR("Error reading PylonCameraParameterSet from ROS-Parameter-Server");
        ros::shutdown();
        return false;
    }

    if (!initAndRegister())
    {
        ros::shutdown();
        return false;
    }

    if (!startGrabbing())
    {
        ros::shutdown();
        return false;
    }
    return true;
}

void PylonCameraNode::spin()
{
    // images were published if subscribers are available or if someone calls the GrabImages Action
    if (getNumSubscribers() > 0 && !isSleeping())
    {
        try
        {
            checkForPylonAutoFunctionRunning();
        }
        catch (GenICam::AccessException &e)
        {
        }

        if (grabImage())
        {
            img_raw_pub_.publish(img_raw_msg_, cam_info_msg_);
        }
    }
}

bool PylonCameraNode::setDigitalOutputCB(const int& output_id,
                                         camera_control_msgs::SetBool::Request &req,
                                         camera_control_msgs::SetBool::Response &res)
{
    res.success = pylon_camera_->setUserOutput(output_id, req.data);
    return true;
}

const double& PylonCameraNode::desiredFrameRate() const
{
    return pylon_camera_parameter_set_.desired_frame_rate_;
}
const std::string& PylonCameraNode::cameraFrame() const
{
    return pylon_camera_parameter_set_.camera_frame_;
}
uint32_t PylonCameraNode::getNumSubscribers() const
{
    return img_raw_pub_.getNumSubscribers();
}

void PylonCameraNode::checkForPylonAutoFunctionRunning()
{
    brightness_service_running_ = pylon_camera_->isAutoBrightnessFunctionRunning();
}

bool PylonCameraNode::initAndRegister()
{
    set_exposure_service_ = nh_.advertiseService("set_exposure_srv",
                                                 &PylonCameraNode::setExposureCallback,
                                                 this);
    set_brightness_service_ = nh_.advertiseService("set_brightness_srv",
                                                   &PylonCameraNode::setBrightnessCallback,
                                                   this);

    pylon_camera_ = PylonCamera::create(pylon_camera_parameter_set_.device_user_id_);

    if (pylon_camera_ == NULL)
    {
        return false;
    }

    if (!pylon_camera_->registerCameraConfiguration(pylon_camera_parameter_set_))
    {
        ROS_ERROR("Error while registering the camera configuration");
        return false;
    }

    if (pylon_camera_->typeName() != "DART")
    {
        set_digital_output_1_service_ = nh_.advertiseService<camera_control_msgs::SetBool::Request, camera_control_msgs::SetBool::Response>(
                "set_output_1",
                boost::bind(&PylonCameraNode::setDigitalOutputCB, this, 1, _1, _2));
    }

    grab_images_raw_action_server_.start();
    return true;
}

bool PylonCameraNode::startGrabbing()
{
    if (!pylon_camera_->startGrabbing(pylon_camera_parameter_set_))
    {
        ROS_ERROR("Error while start grabbing");
        return false;
    }

    // Framrate Settings
    if (pylon_camera_->maxPossibleFramerate() < pylon_camera_parameter_set_.desired_frame_rate_)
    {
        ROS_INFO("Desired framerate %.2f is higher than max possible. Will limit framerate to: %.2f Hz",
                 pylon_camera_parameter_set_.desired_frame_rate_,
                 pylon_camera_->maxPossibleFramerate());
        pylon_camera_parameter_set_.desired_frame_rate_ = pylon_camera_->maxPossibleFramerate();
        nh_.setParam("desired_framerate", pylon_camera_->maxPossibleFramerate());
    }
    else if (pylon_camera_parameter_set_.desired_frame_rate_ == -1)
    {
        pylon_camera_parameter_set_.desired_frame_rate_ = pylon_camera_->maxPossibleFramerate();
        ROS_INFO("Max possible framerate is %.2f Hz", pylon_camera_->maxPossibleFramerate());
    }

    std_msgs::Header header;
    header.frame_id = pylon_camera_parameter_set_.camera_frame_;
    header.stamp = ros::Time::now();

    cam_info_msg_.header = header;
    cam_info_msg_.height = pylon_camera_->imageRows();
    cam_info_msg_.width = pylon_camera_->imageCols();
    cam_info_msg_.distortion_model = "plumb_bob";
    cam_info_msg_.binning_x = cam_info_msg_.binning_y = pylon_camera_parameter_set_.binning_;

    img_raw_msg_.header = header;
    // Encoding of pixels -- channel meaning, ordering, size
    // taken from the list of strings in include/sensor_msgs/image_encodings.h
    img_raw_msg_.encoding = pylon_camera_->imageEncoding();
    img_raw_msg_.height = pylon_camera_->imageRows();
    img_raw_msg_.width = pylon_camera_->imageCols();
    // step = full row length in bytes
    img_raw_msg_.step = img_raw_msg_.width * pylon_camera_->imagePixelDepth();
    // img_raw_msg_.data // actual matrix data, size is (step * rows)

    return true;
}

bool PylonCameraNode::grabImage()
{
    boost::lock_guard<boost::recursive_mutex> lock(grab_mutex_);
    if (!pylon_camera_->grab(img_raw_msg_.data))
    {
        if (pylon_camera_->isCamRemoved())
        {
            ROS_ERROR("Pylon Camera has been removed!");
            ros::shutdown();
        }
        else
        {
            ROS_WARN("Pylon Interface returned invalid image! Skipping");
        }
        return false;
    }
    img_raw_msg_.header.stamp = ros::Time::now();
    cam_info_msg_.header.stamp = img_raw_msg_.header.stamp;
    return true;
}

void PylonCameraNode::grabImagesRawActionExecuteCB(const camera_control_msgs::GrabImagesGoal::ConstPtr& goal)
{
    camera_control_msgs::GrabImagesResult result;
    camera_control_msgs::GrabImagesFeedback feedback;

    boost::lock_guard<boost::recursive_mutex> lock(grab_mutex_);

    result.images.resize(goal->target_values.size());
    result.reached_values.resize(goal->target_values.size());
    result.success = true;
    for (std::size_t i = 0; i < goal->target_values.size(); ++i)
    {
        // setGain(goal->gain);
        // setGamma(goal->gamma);
        if (goal->target_type == goal->EXPOSURE)
        {
            setExposure(goal->target_values[i], result.reached_values[i]);
        }
        if (goal->target_type == goal->BRIGHTNESS)
        {
            int reached_val;
            setBrightness(goal->target_values[i], reached_val);
            result.reached_values[i] = static_cast<float>(reached_val);
        }

        sensor_msgs::Image& img = result.images[i];
        img.encoding = pylon_camera_->imageEncoding();
        img.height = pylon_camera_->imageRows();
        img.width = pylon_camera_->imageCols();
        // step = full row length in bytes
        img.step = img.width * pylon_camera_->imagePixelDepth();

        if (!pylon_camera_->grab(img.data))
        {
            result.success = false;
        }
        img.header.stamp = ros::Time::now();
        img.header.frame_id = cameraFrame();
        feedback.curr_nr_images_taken = i+1;
        grab_images_raw_action_server_.publishFeedback(feedback);
    }

    if (!result.success)
    {
        result.images.clear();
    }

    grab_images_raw_action_server_.setSucceeded(result);
}

bool PylonCameraNode::setExposure(const float& target_exposure, float& reached_exposure)
{
    boost::lock_guard<boost::recursive_mutex> lock(grab_mutex_);
    if (!pylon_camera_->isReady())
    {
        ROS_WARN("Error in setExposure(): pylon_camera_ is not ready!");
        return false;
    }

    reached_exposure = getCurrentExposure();

    if (reached_exposure != target_exposure)
    {
        pylon_camera_->setExposure(target_exposure);
    }

    // wait for max 5s till the cam has updated the exposure
    ros::Rate r(10.0);
    ros::Time start = ros::Time::now();
    while (ros::ok())
    {
        reached_exposure = getCurrentExposure();

        bool success = fabs(reached_exposure - target_exposure) < pylon_camera_->exposureStep();

        if (success)
        {
            return true;
        }

        if (ros::Time::now() - start > ros::Duration(5.0))
        {
            ROS_ERROR("Error in setExposure(): Did not reach the desired brightness in time");
            return false;
        }
        r.sleep();
    }
    return true;
}

bool PylonCameraNode::setExposureCallback(camera_control_msgs::SetExposureSrv::Request &req,
                                          camera_control_msgs::SetExposureSrv::Response &res)
{
    res.success = setExposure(req.target_exposure, res.reached_exposure);
    return true;
}

bool PylonCameraNode::setBrightness(const int& target_brightness, int& reached_brightness)
{
    // Brightness Service can only work, if an image has already been grabbed (calc mean on current img)
    if (!pylon_camera_->isReady())
    {
        ros::Rate r(2.0);
        ros::Time start = ros::Time::now();
        while (ros::ok() && !pylon_camera_->isReady())
        {
            if (ros::Time::now() - start > ros::Duration(3.0))
            {
                ROS_ERROR("Pylon Interface has not yet grabbed an image, although waiting for 3 seconds!");
                return false;
            }
            ros::spinOnce();
            r.sleep();
        }
    }

    // Get actual image
    ros::spinOnce();

    int current_brightness = calcCurrentBrightness();

    ROS_INFO("New brightness request for brightness %i, current brightness = %i",
            target_brightness,
            current_brightness);

    target_brightness_ = target_brightness;
    brightness_service_running_ = true;

    if (current_brightness != target_brightness_)
    {
        boost::lock_guard<boost::recursive_mutex> lock(grab_mutex_);
        pylon_camera_->setBrightness(target_brightness_);
    }
    else
    {
        return true;
    }

    ros::Duration duration;
    if (target_brightness_ > 205)
    {
        // Need more time for great exposure values
        duration = ros::Duration(15.0);
    }
    else
    {
        duration = ros::Duration(5.0);
    }
    ros::Rate r(5.0);
    ros::Time start = ros::Time::now();
    while (ros::ok() && brightness_service_running_)
    {
        if (ros::Time::now() - start > duration)
        {
            ROS_ERROR("Did not reach the required brightness in time");
            brightness_service_running_ = false;
            return false;
        }
        ros::spinOnce();
        r.sleep();
    }

    reached_brightness = calcCurrentBrightness();

    return brightnessValidation(target_brightness);
}

bool PylonCameraNode::setBrightnessCallback(camera_control_msgs::SetBrightnessSrv::Request &req,
    camera_control_msgs::SetBrightnessSrv::Response &res)
{
    res.success = setBrightness(req.target_brightness, res.reached_brightness);
    return true;
}

bool PylonCameraNode::brightnessValidation(int target)
{
    int mean = calcCurrentBrightness();
    if (abs(target - mean) > 2)
    {
        return false;
    }
    return true;
}

int PylonCameraNode::calcCurrentBrightness()
{
    boost::lock_guard<boost::recursive_mutex> lock(grab_mutex_);
    int sum = std::accumulate(img_raw_msg_.data.begin(), img_raw_msg_.data.end(), 0);
    assert(img_raw_msg_.data.size() > 0);
    float mean = sum / img_raw_msg_.data.size();
    return static_cast<int>(mean);
}

float PylonCameraNode::getCurrentExposure()
{
    return pylon_camera_->currentExposure();
}

bool PylonCameraNode::setSleepingCallback(camera_control_msgs::SetSleepingSrv::Request &req,
    camera_control_msgs::SetSleepingSrv::Response &res)
{
    is_sleeping_ = req.set_sleeping;

    if (is_sleeping_)
    {
        ROS_INFO("Seting Pylon Camera Node to sleep...");
    }
    else
    {
        ROS_INFO("Pylon Camera Node continues grabbing");
    }

    res.success = true;
    return true;
}

bool PylonCameraNode::isSleeping()
{
    return is_sleeping_;
}

PylonCameraNode::~PylonCameraNode()
{
    delete pylon_camera_;
    pylon_camera_ = NULL;
    delete it_;
    it_ = NULL;
}

}  // namespace pylon_camera
<commit_msg>added lots of comments, initialized the camera_info_msg with zero-values<commit_after>// Copyright 2015 <Magazino GmbH>

#include <pylon_camera/pylon_camera_node.h>
#include <GenApi/GenApi.h>
#include <algorithm>
#include <cmath>
#include <vector>
#include "boost/multi_array.hpp"

namespace pylon_camera
{

PylonCameraNode::PylonCameraNode() :
        nh_("~"),
        pylon_camera_(NULL),
        pylon_camera_parameter_set_(),
        it_(new image_transport::ImageTransport(nh_)),
        img_raw_pub_(it_->advertiseCamera("image_raw", 10)),
        grab_images_raw_action_server_(nh_, "grab_images_raw",
            boost::bind(&PylonCameraNode::grabImagesRawActionExecuteCB, this, _1), false),
        set_sleeping_service_(nh_.advertiseService("set_sleeping_srv", &PylonCameraNode::setSleepingCallback, this)),
        target_brightness_(-42),
        brightness_service_running_(false),
        is_sleeping_(false)
{
    init();
}

bool PylonCameraNode::init()
{
    // Set parameter to open the desired camera
    if (!pylon_camera_parameter_set_.readFromRosParameterServer(nh_))
    {
        ROS_ERROR("Error reading PylonCameraParameterSet from ROS-Parameter-Server");
        ros::shutdown();
        return false;
    }

    if (!initAndRegister())
    {
        ros::shutdown();
        return false;
    }

    if (!startGrabbing())
    {
        ros::shutdown();
        return false;
    }
    return true;
}

void PylonCameraNode::spin()
{
    // images were published if subscribers are available or if someone calls the GrabImages Action
    if (getNumSubscribers() > 0 && !isSleeping())
    {
        try
        {
            checkForPylonAutoFunctionRunning();
        }
        catch (GenICam::AccessException &e)
        {
        }

        if (grabImage())
        {
            img_raw_pub_.publish(img_raw_msg_, cam_info_msg_);
        }
    }
}

bool PylonCameraNode::setDigitalOutputCB(const int& output_id,
                                         camera_control_msgs::SetBool::Request &req,
                                         camera_control_msgs::SetBool::Response &res)
{
    res.success = pylon_camera_->setUserOutput(output_id, req.data);
    return true;
}

const double& PylonCameraNode::desiredFrameRate() const
{
    return pylon_camera_parameter_set_.desired_frame_rate_;
}
const std::string& PylonCameraNode::cameraFrame() const
{
    return pylon_camera_parameter_set_.camera_frame_;
}
uint32_t PylonCameraNode::getNumSubscribers() const
{
    return img_raw_pub_.getNumSubscribers();
}

void PylonCameraNode::checkForPylonAutoFunctionRunning()
{
    brightness_service_running_ = pylon_camera_->isAutoBrightnessFunctionRunning();
}

bool PylonCameraNode::initAndRegister()
{
    set_exposure_service_ = nh_.advertiseService("set_exposure_srv",
                                                 &PylonCameraNode::setExposureCallback,
                                                 this);
    set_brightness_service_ = nh_.advertiseService("set_brightness_srv",
                                                   &PylonCameraNode::setBrightnessCallback,
                                                   this);

    pylon_camera_ = PylonCamera::create(pylon_camera_parameter_set_.device_user_id_);

    if (pylon_camera_ == NULL)
    {
        return false;
    }

    if (!pylon_camera_->registerCameraConfiguration(pylon_camera_parameter_set_))
    {
        ROS_ERROR("Error while registering the camera configuration");
        return false;
    }

    if (pylon_camera_->typeName() != "DART")
    {
        set_digital_output_1_service_ = nh_.advertiseService<camera_control_msgs::SetBool::Request, camera_control_msgs::SetBool::Response>(
                "set_output_1",
                boost::bind(&PylonCameraNode::setDigitalOutputCB, this, 1, _1, _2));
    }

    grab_images_raw_action_server_.start();
    return true;
}

bool PylonCameraNode::startGrabbing()
{
    if (!pylon_camera_->startGrabbing(pylon_camera_parameter_set_))
    {
        ROS_ERROR("Error while start grabbing");
        return false;
    }

    // Framrate Settings
    if (pylon_camera_->maxPossibleFramerate() < pylon_camera_parameter_set_.desired_frame_rate_)
    {
        ROS_INFO("Desired framerate %.2f is higher than max possible. Will limit framerate to: %.2f Hz",
                 pylon_camera_parameter_set_.desired_frame_rate_,
                 pylon_camera_->maxPossibleFramerate());
        pylon_camera_parameter_set_.desired_frame_rate_ = pylon_camera_->maxPossibleFramerate();
        nh_.setParam("desired_framerate", pylon_camera_->maxPossibleFramerate());
    }
    else if (pylon_camera_parameter_set_.desired_frame_rate_ == -1)
    {
        pylon_camera_parameter_set_.desired_frame_rate_ = pylon_camera_->maxPossibleFramerate();
        ROS_INFO("Max possible framerate is %.2f Hz", pylon_camera_->maxPossibleFramerate());
    }

    std_msgs::Header header;
    header.frame_id = pylon_camera_parameter_set_.camera_frame_;
    header.stamp = ros::Time::now();

    // http://www.ros.org/reps/rep-0104.html
    // If the camera is uncalibrated, the matrices D, K, R, P should be left zeroed out.
    // In particular, clients may assume that K[0] == 0.0 indicates an uncalibrated camera.
    cam_info_msg_.header = header;
    cam_info_msg_.height = pylon_camera_->imageRows();
    cam_info_msg_.width = pylon_camera_->imageCols();

    // The distortion model used. Supported models are listed in sensor_msgs/distortion_models.h.
    // For most cameras, "plumb_bob" - a simple model of radial and tangential distortion - is sufficient.
    // Empty D and distortion_model indicate that the CameraInfo cannot be used to rectify points or images,
    // either because the camera is not calibrated or because the rectified image was produced using an
    // unsupported distortion model, e.g. the proprietary one used by Bumblebee cameras
    // [http://www.ros.org/reps/rep-0104.html].
    cam_info_msg_.distortion_model = "";

    // The distortion parameters, size depending on the distortion model.
    // For "plumb_bob", the 5 parameters are: (k1, k2, t1, t2, k3) -> float64[] D.
    cam_info_msg_.D = std::vector<double>(5, 0.);

    // Intrinsic camera matrix for the raw (distorted) images.
    //     [fx  0 cx]
    // K = [ 0 fy cy]  --> 3x3 row-major matrix
    //     [ 0  0  1]
    // Projects 3D points in the camera coordinate frame to 2D pixel coordinates using the
    // focal lengths (fx, fy) and principal point (cx, cy).
    cam_info_msg_.K.assign(0.0);

    // Rectification matrix (stereo cameras only)
    // A rotation matrix aligning the camera coordinate system to the ideal stereo image plane so that
    // epipolar lines in both stereo images are parallel.
    cam_info_msg_.R.assign(0.0);

    // Projection/camera matrix
    //     [fx'  0  cx' Tx]
    // P = [ 0  fy' cy' Ty]  --> # 3x4 row-major matrix
    //     [ 0   0   1   0]
    // By convention, this matrix specifies the intrinsic (camera) matrix of the processed (rectified) image.
    // That is, the left 3x3 portion is the normal camera intrinsic matrix for the rectified image.
    // It projects 3D points in the camera coordinate frame to 2D pixel coordinates using the focal
    // lengths (fx', fy') and principal point (cx', cy') - these may differ from the values in K.
    // For monocular cameras, Tx = Ty = 0. Normally, monocular cameras will also have R = the identity
    // and P[1:3,1:3] = K.
    // For a stereo pair, the fourth column [Tx Ty 0]' is related to the position of the optical center of
    // The second camera in the first camera's frame. We assume Tz = 0 so both cameras are in the same
    // stereo image plane. The first camera always has Tx = Ty = 0. For the right (second) camera of a
    // horizontal stereo pair, Ty = 0 and Tx = -fx' * B, where B is the baseline between the cameras.
    // Given a 3D point [X Y Z]', the projection (x, y) of the point onto the rectified image is given by:
    // [u v w]' = P * [X Y Z 1]'
    //        x = u / w
    //        y = v / w
    //  This holds for both images of a stereo pair.
    cam_info_msg_.P.assign(0.0);

    // Binning refers here to any camera setting which combines rectangular neighborhoods of pixels into
    // larger "super-pixels." It reduces the resolution of the output image to
    // (width / binning_x) x (height / binning_y). The default values binning_x = binning_y = 0 is
    // considered the same as binning_x = binning_y = 1 (no subsampling).
    cam_info_msg_.binning_x = cam_info_msg_.binning_y = pylon_camera_parameter_set_.binning_;

    // Region of interest (subwindow of full camera resolution), given in full resolution (unbinned)
    // image coordinates. A particular ROI always denotes the same window of pixels on the camera sensor,
    // regardless of binning settings. The default setting of roi (all values 0) is considered the same as
    // full resolution (roi.width = width, roi.height = height).
    cam_info_msg_.roi.x_offset = cam_info_msg_.roi.y_offset = 0;
    cam_info_msg_.roi.height = cam_info_msg_.roi.width = 0;

    img_raw_msg_.header = header;
    // Encoding of pixels -- channel meaning, ordering, size
    // taken from the list of strings in include/sensor_msgs/image_encodings.h
    img_raw_msg_.encoding = pylon_camera_->imageEncoding();
    img_raw_msg_.height = pylon_camera_->imageRows();
    img_raw_msg_.width = pylon_camera_->imageCols();
    // step = full row length in bytes
    // img_raw_msg_.data // actual matrix data, size is (step * rows)
    img_raw_msg_.step = img_raw_msg_.width * pylon_camera_->imagePixelDepth();

    return true;
}

bool PylonCameraNode::grabImage()
{
    boost::lock_guard<boost::recursive_mutex> lock(grab_mutex_);
    if (!pylon_camera_->grab(img_raw_msg_.data))
    {
        if (pylon_camera_->isCamRemoved())
        {
            ROS_ERROR("Pylon Camera has been removed!");
            ros::shutdown();
        }
        else
        {
            ROS_WARN("Pylon Interface returned invalid image! Skipping");
        }
        return false;
    }
    img_raw_msg_.header.stamp = ros::Time::now();
    cam_info_msg_.header.stamp = img_raw_msg_.header.stamp;
    return true;
}

void PylonCameraNode::grabImagesRawActionExecuteCB(const camera_control_msgs::GrabImagesGoal::ConstPtr& goal)
{
    camera_control_msgs::GrabImagesResult result;
    camera_control_msgs::GrabImagesFeedback feedback;

    boost::lock_guard<boost::recursive_mutex> lock(grab_mutex_);

    result.images.resize(goal->target_values.size());
    result.reached_values.resize(goal->target_values.size());
    result.success = true;
    for (std::size_t i = 0; i < goal->target_values.size(); ++i)
    {
        // setGain(goal->gain);
        // setGamma(goal->gamma);
        if (goal->target_type == goal->EXPOSURE)
        {
            setExposure(goal->target_values[i], result.reached_values[i]);
        }
        if (goal->target_type == goal->BRIGHTNESS)
        {
            int reached_val;
            setBrightness(goal->target_values[i], reached_val);
            result.reached_values[i] = static_cast<float>(reached_val);
        }

        sensor_msgs::Image& img = result.images[i];
        img.encoding = pylon_camera_->imageEncoding();
        img.height = pylon_camera_->imageRows();
        img.width = pylon_camera_->imageCols();
        // step = full row length in bytes
        img.step = img.width * pylon_camera_->imagePixelDepth();

        if (!pylon_camera_->grab(img.data))
        {
            result.success = false;
        }
        img.header.stamp = ros::Time::now();
        img.header.frame_id = cameraFrame();
        feedback.curr_nr_images_taken = i+1;
        grab_images_raw_action_server_.publishFeedback(feedback);
    }

    if (!result.success)
    {
        result.images.clear();
    }

    grab_images_raw_action_server_.setSucceeded(result);
}

bool PylonCameraNode::setExposure(const float& target_exposure, float& reached_exposure)
{
    boost::lock_guard<boost::recursive_mutex> lock(grab_mutex_);
    if (!pylon_camera_->isReady())
    {
        ROS_WARN("Error in setExposure(): pylon_camera_ is not ready!");
        return false;
    }

    reached_exposure = getCurrentExposure();

    if (reached_exposure != target_exposure)
    {
        pylon_camera_->setExposure(target_exposure);
    }

    // wait for max 5s till the cam has updated the exposure
    ros::Rate r(10.0);
    ros::Time start = ros::Time::now();
    while (ros::ok())
    {
        reached_exposure = getCurrentExposure();

        bool success = fabs(reached_exposure - target_exposure) < pylon_camera_->exposureStep();

        if (success)
        {
            return true;
        }

        if (ros::Time::now() - start > ros::Duration(5.0))
        {
            ROS_ERROR("Error in setExposure(): Did not reach the desired brightness in time");
            return false;
        }
        r.sleep();
    }
    return true;
}

bool PylonCameraNode::setExposureCallback(camera_control_msgs::SetExposureSrv::Request &req,
                                          camera_control_msgs::SetExposureSrv::Response &res)
{
    res.success = setExposure(req.target_exposure, res.reached_exposure);
    return true;
}

bool PylonCameraNode::setBrightness(const int& target_brightness, int& reached_brightness)
{
    // Brightness Service can only work, if an image has already been grabbed (calc mean on current img)
    if (!pylon_camera_->isReady())
    {
        ros::Rate r(2.0);
        ros::Time start = ros::Time::now();
        while (ros::ok() && !pylon_camera_->isReady())
        {
            if (ros::Time::now() - start > ros::Duration(3.0))
            {
                ROS_ERROR("Pylon Interface has not yet grabbed an image, although waiting for 3 seconds!");
                return false;
            }
            ros::spinOnce();
            r.sleep();
        }
    }

    // Get actual image
    ros::spinOnce();

    int current_brightness = calcCurrentBrightness();

    ROS_INFO("New brightness request for brightness %i, current brightness = %i",
            target_brightness,
            current_brightness);

    target_brightness_ = target_brightness;
    brightness_service_running_ = true;

    if (current_brightness != target_brightness_)
    {
        boost::lock_guard<boost::recursive_mutex> lock(grab_mutex_);
        pylon_camera_->setBrightness(target_brightness_);
    }
    else
    {
        return true;
    }

    ros::Duration duration;
    if (target_brightness_ > 205)
    {
        // Need more time for great exposure values
        duration = ros::Duration(15.0);
    }
    else
    {
        duration = ros::Duration(5.0);
    }
    ros::Rate r(5.0);
    ros::Time start = ros::Time::now();
    while (ros::ok() && brightness_service_running_)
    {
        if (ros::Time::now() - start > duration)
        {
            ROS_ERROR("Did not reach the required brightness in time");
            brightness_service_running_ = false;
            return false;
        }
        ros::spinOnce();
        r.sleep();
    }

    reached_brightness = calcCurrentBrightness();

    return brightnessValidation(target_brightness);
}

bool PylonCameraNode::setBrightnessCallback(camera_control_msgs::SetBrightnessSrv::Request &req,
    camera_control_msgs::SetBrightnessSrv::Response &res)
{
    res.success = setBrightness(req.target_brightness, res.reached_brightness);
    return true;
}

bool PylonCameraNode::brightnessValidation(int target)
{
    int mean = calcCurrentBrightness();
    if (abs(target - mean) > 2)
    {
        return false;
    }
    return true;
}

int PylonCameraNode::calcCurrentBrightness()
{
    boost::lock_guard<boost::recursive_mutex> lock(grab_mutex_);
    int sum = std::accumulate(img_raw_msg_.data.begin(), img_raw_msg_.data.end(), 0);
    assert(img_raw_msg_.data.size() > 0);
    float mean = sum / img_raw_msg_.data.size();
    return static_cast<int>(mean);
}

float PylonCameraNode::getCurrentExposure()
{
    return pylon_camera_->currentExposure();
}

bool PylonCameraNode::setSleepingCallback(camera_control_msgs::SetSleepingSrv::Request &req,
    camera_control_msgs::SetSleepingSrv::Response &res)
{
    is_sleeping_ = req.set_sleeping;

    if (is_sleeping_)
    {
        ROS_INFO("Seting Pylon Camera Node to sleep...");
    }
    else
    {
        ROS_INFO("Pylon Camera Node continues grabbing");
    }

    res.success = true;
    return true;
}

bool PylonCameraNode::isSleeping()
{
    return is_sleeping_;
}

PylonCameraNode::~PylonCameraNode()
{
    delete pylon_camera_;
    pylon_camera_ = NULL;
    delete it_;
    it_ = NULL;
}

}  // namespace pylon_camera
<|endoftext|>