<commit_before>/*!
 * This file is part of CameraPlus.
 *
 * Copyright (C) 2012-2013 Mohammed Sameer <msameer@foolab.org>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "qtcamanalysisbin.h"
#include <QStringList>
#include <QDebug>
#include <QHash>

#define FACTORY_NAME(x) gst_plugin_feature_get_name(GST_PLUGIN_FEATURE(gst_element_get_factory(x)))

static QtCamAnalysisBinPrivate *qt_cam_analysis_bin_create(const QStringList& factories,
							   const char *name);
static QtCamAnalysisBinPrivate *qt_cam_analysis_bin_create(GstElement *child,
							   const char *name);

class QtCamAnalysisBinPrivate {
public:
  QtCamAnalysisBinPrivate() :
    bin(0),
    probe(0),
    queuePad(0) {

  }

  static gboolean block_buffers(GstPad *pad, GstMiniObject *o) {
    Q_UNUSED(pad);
    Q_UNUSED(o);

    // Drop data
    return FALSE;
  }

  GstElement *bin;
  gulong probe;
  GstPad *queuePad;
  QMultiHash<QString, GstElement *> elements;
};

QtCamAnalysisBin::QtCamAnalysisBin(QtCamAnalysisBinPrivate *d) :
  d_ptr(d) {
  gst_object_ref(d_ptr->bin);
}

QtCamAnalysisBin::~QtCamAnalysisBin() {
  d_ptr->elements.clear();

  setBlocked(false);
  gst_object_unref(GST_OBJECT(d_ptr->queuePad));
  gst_object_unref(d_ptr->bin);
  delete d_ptr; d_ptr = 0;
}

void QtCamAnalysisBin::setBlocked(bool blocked) {
  if (blocked == isBlocked()) {
    return;
  }

  if (blocked) {
    d_ptr->probe = gst_pad_add_buffer_probe(d_ptr->queuePad,
					    G_CALLBACK(QtCamAnalysisBinPrivate::block_buffers),
					    d_ptr);
  }
  else {
    gst_pad_remove_data_probe(d_ptr->queuePad, d_ptr->probe);
    d_ptr->probe = 0;
  }
}

bool QtCamAnalysisBin::isBlocked() const {
  return d_ptr->probe != 0;
}

GstElement *QtCamAnalysisBin::bin() {
  return d_ptr->bin;
}

QtCamAnalysisBin *QtCamAnalysisBin::create(const QStringList& factories, const char *name) {
  QList<GstElement *> elements;
  if (factories.isEmpty()) {
    return 0;
  }

  QtCamAnalysisBinPrivate *d = qt_cam_analysis_bin_create(factories, name);
  if (!d) {
    return 0;
  }

  return new QtCamAnalysisBin(d);
}

QtCamAnalysisBinPrivate *qt_cam_analysis_bin_create(const QStringList& factories,
						    const char *name) {

  if (factories.isEmpty()) {
    return 0;
  }

  GstElement *bin = 0;
  QHash<QString, GstElement *> elements;
  QList<GstElement *> added;

  bin = gst_bin_new("analysis-bin-bin");

  foreach (const QString& factory, factories) {
    GstElement *element = gst_element_factory_make(factory.toUtf8().constData(), NULL);
    if (!element) {
      qWarning() << "Failed to create element" << factory;
      continue;
    }

    if (!gst_bin_add(GST_BIN(bin), element)) {
      qWarning() << "Failed to add element" << factory << "to bin";
      gst_object_unref(element);
    }

    elements.insert(factory, element);
    added << element;
  }

  if (added.size() > 1) {
    for (int x = 1; x < added.count(); x++) {
      GstElement *elem = added[x];
      GstElement *prev = added[x - 1];

      if (!gst_element_link(prev, elem)) {
	qWarning() << "Failed to link" << FACTORY_NAME(prev) << "and" << FACTORY_NAME(elem);
      }
    }
  }

  GstPad *pad = gst_element_get_static_pad(added.first(), "sink");
  gst_element_add_pad(bin, gst_ghost_pad_new("sink", pad));
  gst_object_unref(GST_OBJECT(pad));

  pad = gst_element_get_static_pad(added.last(), "src");
  gst_element_add_pad(bin, gst_ghost_pad_new("src", pad));
  gst_object_unref(GST_OBJECT(pad));

  QtCamAnalysisBinPrivate *d = qt_cam_analysis_bin_create(bin, name);
  if (!d) {
    return 0;
  }

  d->elements = elements;

  return d;
}

/*
 *       -- identity -- ghost pad
 * tee -
 *       -- queue -- copy -- filters -- fakesink
 */
QtCamAnalysisBinPrivate *qt_cam_analysis_bin_create(GstElement *child, const char *name) {
  GstPad *pad = 0;
  GstPad *queuePad = 0;
  QtCamAnalysisBinPrivate *d = 0;

  GstElement *bin = gst_bin_new(name);

  GstElement *tee = gst_element_factory_make("tee", "analysis-bin-tee");
  GstElement *queue = gst_element_factory_make("queue", "analysis-bin-queue");
  GstElement *fakesink = gst_element_factory_make("fakesink", "analysis-bin-fakesink");
  GstElement *copy = gst_element_factory_make("copy", "analysis-bin-copy");
  GstElement *identity = gst_element_factory_make("identity", "analysis-bin-identity");

  if (!bin || !tee || !queue || !fakesink || !copy || !identity) {
    qWarning() << "Failed to create some elements";
    goto free_and_out;
  }

  gst_bin_add_many(GST_BIN(bin), tee, queue, copy, fakesink, child, identity, NULL);

  g_object_set(tee, "silent", TRUE, NULL);
  g_object_set(queue, "silent", TRUE, "leaky", 2, "max-size-buffers", 1, NULL);
  g_object_set(fakesink, "silent", TRUE, "sync", FALSE, "async", FALSE, NULL);
  g_object_set(identity, "silent", TRUE, "signal-handoffs", FALSE, NULL);

  gst_element_link(tee, identity);
  gst_element_link(tee, queue);
  gst_element_link(queue, copy);
  gst_element_link(copy, child);
  gst_element_link(child, fakesink);

  pad = gst_element_get_static_pad(tee, "sink");
  gst_element_add_pad(bin, gst_ghost_pad_new("sink", pad));
  gst_object_unref(GST_OBJECT(pad));

  pad = gst_element_get_static_pad(identity, "src");
  gst_element_add_pad(bin, gst_ghost_pad_new("src", pad));
  gst_object_unref(GST_OBJECT(pad));

  pad = gst_element_get_static_pad(tee, "src0");
  g_object_set(tee, "alloc-pad", pad, NULL);
  gst_object_unref(GST_OBJECT(pad));

  queuePad = gst_element_get_static_pad(queue, "src");

  d = new QtCamAnalysisBinPrivate;
  d->queuePad = queuePad;
  d->bin = bin;
  return d;

 free_and_out:
  if (bin) {
    gst_object_unref(bin);
  }
  else {
    gst_object_unref(child);
  }

  if (tee) {
    gst_object_unref(tee);
  }

  if (queue) {
    gst_object_unref(queue);
  }

  if (copy) {
    gst_object_unref(copy);
  }

  if (identity) {
    gst_object_unref(identity);
  }

  if (fakesink) {
    gst_object_unref(fakesink);
  }

  return 0;
}

QList<GstElement *> QtCamAnalysisBin::lookup(const QString& factory) {
  if (d_ptr->elements.contains(factory)) {
    return d_ptr->elements.values(factory);
  }

  return QList<GstElement *>();
}
<commit_msg>Return NULL if we cannot create any elements<commit_after>/*!
 * This file is part of CameraPlus.
 *
 * Copyright (C) 2012-2013 Mohammed Sameer <msameer@foolab.org>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "qtcamanalysisbin.h"
#include <QStringList>
#include <QDebug>
#include <QHash>

#define FACTORY_NAME(x) gst_plugin_feature_get_name(GST_PLUGIN_FEATURE(gst_element_get_factory(x)))

static QtCamAnalysisBinPrivate *qt_cam_analysis_bin_create(const QStringList& factories,
							   const char *name);
static QtCamAnalysisBinPrivate *qt_cam_analysis_bin_create(GstElement *child,
							   const char *name);

class QtCamAnalysisBinPrivate {
public:
  QtCamAnalysisBinPrivate() :
    bin(0),
    probe(0),
    queuePad(0) {

  }

  static gboolean block_buffers(GstPad *pad, GstMiniObject *o) {
    Q_UNUSED(pad);
    Q_UNUSED(o);

    // Drop data
    return FALSE;
  }

  GstElement *bin;
  gulong probe;
  GstPad *queuePad;
  QMultiHash<QString, GstElement *> elements;
};

QtCamAnalysisBin::QtCamAnalysisBin(QtCamAnalysisBinPrivate *d) :
  d_ptr(d) {
  gst_object_ref(d_ptr->bin);
}

QtCamAnalysisBin::~QtCamAnalysisBin() {
  d_ptr->elements.clear();

  setBlocked(false);
  gst_object_unref(GST_OBJECT(d_ptr->queuePad));
  gst_object_unref(d_ptr->bin);
  delete d_ptr; d_ptr = 0;
}

void QtCamAnalysisBin::setBlocked(bool blocked) {
  if (blocked == isBlocked()) {
    return;
  }

  if (blocked) {
    d_ptr->probe = gst_pad_add_buffer_probe(d_ptr->queuePad,
					    G_CALLBACK(QtCamAnalysisBinPrivate::block_buffers),
					    d_ptr);
  }
  else {
    gst_pad_remove_data_probe(d_ptr->queuePad, d_ptr->probe);
    d_ptr->probe = 0;
  }
}

bool QtCamAnalysisBin::isBlocked() const {
  return d_ptr->probe != 0;
}

GstElement *QtCamAnalysisBin::bin() {
  return d_ptr->bin;
}

QtCamAnalysisBin *QtCamAnalysisBin::create(const QStringList& factories, const char *name) {
  QList<GstElement *> elements;
  if (factories.isEmpty()) {
    return 0;
  }

  QtCamAnalysisBinPrivate *d = qt_cam_analysis_bin_create(factories, name);
  if (!d) {
    return 0;
  }

  return new QtCamAnalysisBin(d);
}

QtCamAnalysisBinPrivate *qt_cam_analysis_bin_create(const QStringList& factories,
						    const char *name) {

  if (factories.isEmpty()) {
    return 0;
  }

  GstElement *bin = 0;
  QHash<QString, GstElement *> elements;
  QList<GstElement *> added;

  bin = gst_bin_new("analysis-bin-bin");

  foreach (const QString& factory, factories) {
    GstElement *element = gst_element_factory_make(factory.toUtf8().constData(), NULL);
    if (!element) {
      qWarning() << "Failed to create element" << factory;
      continue;
    }

    if (!gst_bin_add(GST_BIN(bin), element)) {
      qWarning() << "Failed to add element" << factory << "to bin";
      gst_object_unref(element);
    }

    elements.insert(factory, element);
    added << element;
  }

  if (added.isEmpty()) {
    gst_object_unref (bin);

    return 0;
  }

  if (added.size() > 1) {
    for (int x = 1; x < added.count(); x++) {
      GstElement *elem = added[x];
      GstElement *prev = added[x - 1];

      if (!gst_element_link(prev, elem)) {
	qWarning() << "Failed to link" << FACTORY_NAME(prev) << "and" << FACTORY_NAME(elem);
      }
    }
  }

  GstPad *pad = gst_element_get_static_pad(added.first(), "sink");
  gst_element_add_pad(bin, gst_ghost_pad_new("sink", pad));
  gst_object_unref(GST_OBJECT(pad));

  pad = gst_element_get_static_pad(added.last(), "src");
  gst_element_add_pad(bin, gst_ghost_pad_new("src", pad));
  gst_object_unref(GST_OBJECT(pad));

  QtCamAnalysisBinPrivate *d = qt_cam_analysis_bin_create(bin, name);
  if (!d) {
    return 0;
  }

  d->elements = elements;

  return d;
}

/*
 *       -- identity -- ghost pad
 * tee -
 *       -- queue -- copy -- filters -- fakesink
 */
QtCamAnalysisBinPrivate *qt_cam_analysis_bin_create(GstElement *child, const char *name) {
  GstPad *pad = 0;
  GstPad *queuePad = 0;
  QtCamAnalysisBinPrivate *d = 0;

  GstElement *bin = gst_bin_new(name);

  GstElement *tee = gst_element_factory_make("tee", "analysis-bin-tee");
  GstElement *queue = gst_element_factory_make("queue", "analysis-bin-queue");
  GstElement *fakesink = gst_element_factory_make("fakesink", "analysis-bin-fakesink");
  GstElement *copy = gst_element_factory_make("copy", "analysis-bin-copy");
  GstElement *identity = gst_element_factory_make("identity", "analysis-bin-identity");

  if (!bin || !tee || !queue || !fakesink || !copy || !identity) {
    qWarning() << "Failed to create some elements";
    goto free_and_out;
  }

  gst_bin_add_many(GST_BIN(bin), tee, queue, copy, fakesink, child, identity, NULL);

  g_object_set(tee, "silent", TRUE, NULL);
  g_object_set(queue, "silent", TRUE, "leaky", 2, "max-size-buffers", 1, NULL);
  g_object_set(fakesink, "silent", TRUE, "sync", FALSE, "async", FALSE, NULL);
  g_object_set(identity, "silent", TRUE, "signal-handoffs", FALSE, NULL);

  gst_element_link(tee, identity);
  gst_element_link(tee, queue);
  gst_element_link(queue, copy);
  gst_element_link(copy, child);
  gst_element_link(child, fakesink);

  pad = gst_element_get_static_pad(tee, "sink");
  gst_element_add_pad(bin, gst_ghost_pad_new("sink", pad));
  gst_object_unref(GST_OBJECT(pad));

  pad = gst_element_get_static_pad(identity, "src");
  gst_element_add_pad(bin, gst_ghost_pad_new("src", pad));
  gst_object_unref(GST_OBJECT(pad));

  pad = gst_element_get_static_pad(tee, "src0");
  g_object_set(tee, "alloc-pad", pad, NULL);
  gst_object_unref(GST_OBJECT(pad));

  queuePad = gst_element_get_static_pad(queue, "src");

  d = new QtCamAnalysisBinPrivate;
  d->queuePad = queuePad;
  d->bin = bin;
  return d;

 free_and_out:
  if (bin) {
    gst_object_unref(bin);
  }
  else {
    gst_object_unref(child);
  }

  if (tee) {
    gst_object_unref(tee);
  }

  if (queue) {
    gst_object_unref(queue);
  }

  if (copy) {
    gst_object_unref(copy);
  }

  if (identity) {
    gst_object_unref(identity);
  }

  if (fakesink) {
    gst_object_unref(fakesink);
  }

  return 0;
}

QList<GstElement *> QtCamAnalysisBin::lookup(const QString& factory) {
  if (d_ptr->elements.contains(factory)) {
    return d_ptr->elements.values(factory);
  }

  return QList<GstElement *>();
}
<|endoftext|>


<commit_before>#include "graphics.h"
#include "compiler.h"
#include "memory.h"
#include "resources.h"
#include "glinit.h"
#include "vector.h"
#include "print.h"

#include <cstddef>
#include <cstdint>

#define OBJECT_UNIFORM_BINDING_INDEX 0

namespace
{
#if PRINT_ENABLED
#define PRINT_INFO_LOG(a, b, c) print_info_log (a, b, c)
  inline void print_info_log (GLuint object,
                              PFNGLGETSHADERIVPROC glGet__iv,
                              PFNGLGETSHADERINFOLOGPROC glGet__InfoLog)
  {
    if (PRINT_ENABLED) {
      GLint log_length;
      glGet__iv (object, GL_INFO_LOG_LENGTH, & log_length);
      char * log = (char *) allocate_internal (log_length + 1);
      if (log) {
        glGet__InfoLog (object, log_length, NULL, log);
        log [log_length] = '\0';
        if (log [0]) print (log);
        deallocate (log);
      }
    }
  }
#else
#define PRINT_INFO_LOG(a, b, c)
#endif

  GLuint make_shader (GLenum type, int resource_id)
  {
    const char * text;
    GLint size;
    get_resource_data (resource_id, text, size);

    GLint id = glCreateShader (type);
    glShaderSource (id, 1, & text, & size);
    glCompileShader (id);
    GLint status = 0;
    glGetShaderiv (id, GL_COMPILE_STATUS, & status);
#if PRINT_ENABLED
    switch (resource_id) {
    case IDR_VERTEX_SHADER: std::cout << "Vertex "; break;
    case IDR_FRAGMENT_SHADER: std::cout << "Fragment "; break;
    case IDR_GEOMETRY_SHADER: std::cout << "Geometry "; break;
    default: ;
    }
    std::cout << "Shader compilation " << (status ? "succeeded." : "failed.") << std::endl;
    PRINT_INFO_LOG (id, glGetShaderiv, glGetShaderInfoLog);
#endif
    return status ? id : 0;
  }
}

static const int attribute_id_x = 0;

unsigned make_vao (unsigned N, const float (* vertices) [4], const unsigned (* indices) [6])
{
  unsigned vao_id;
  glGenVertexArrays (1, & vao_id);
  glBindVertexArray (vao_id);
  GLuint buffer_ids [2];
  glGenBuffers (2, buffer_ids);
  glBindBuffer (GL_ARRAY_BUFFER, buffer_ids [0]);
  glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, buffer_ids [1]);
  glBufferData (GL_ARRAY_BUFFER, (N + 2) * 4 * sizeof (float), vertices, GL_STATIC_DRAW);
  glBufferData (GL_ELEMENT_ARRAY_BUFFER, 6 * N * sizeof (unsigned), indices, GL_STATIC_DRAW);
  glVertexAttribPointer (attribute_id_x, 4, GL_FLOAT, GL_FALSE, 0, 0);
  glEnableVertexAttribArray (attribute_id_x);
  return vao_id;
}

namespace
{
  // Align x upwards to given alignment (which must be a power of 2). Store the result in y.
  template <typename Dest, typename Source>
  inline void align_up (Dest & y, Source x, std::intptr_t alignment)
  {
    y = (Dest) ((((std::intptr_t) (x)) + (alignment - 1)) & - alignment);
  }
}

uniform_buffer_t::~uniform_buffer_t ()
{
  //glDeleteBuffers (1, & m_id);
  deallocate (m_memory);
}

bool uniform_buffer_t::initialize ()
{
  GLint max_size, align;
  glGetIntegerv (GL_MAX_UNIFORM_BLOCK_SIZE, & max_size);
  glGetIntegerv (GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, & align);
  // Align client-side buffer to at least 64 bytes, to avoid straddling cache lines.
  align = align > 64 ? align : 64;
  m_size = max_size;
  m_memory = allocate_internal (m_size + align);
  if (! m_memory) return false;
  align_up (m_begin, m_memory, align);
  align_up (m_stride, sizeof (object_data_t), align);
  glGenBuffers (1, & m_id);
  return true;
}

void uniform_buffer_t::bind ()
{
  glBindBuffer (GL_UNIFORM_BUFFER, m_id);
}

void uniform_buffer_t::update ()
{
  // Create a buffer, orphaning any previous buffer.
  glBufferData (GL_UNIFORM_BUFFER, m_size, nullptr, GL_DYNAMIC_DRAW);
  // Upload the buffer data.
  glBufferSubData (GL_UNIFORM_BUFFER, 0, m_size, m_begin);
}

bool initialize_graphics (program_t & program)
{
  glEnable (GL_DEPTH_CLAMP);
  glEnable (GL_CULL_FACE);
  glEnable (GL_BLEND);
  glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  return program.initialize ();
}

void program_t::set_view (const float (& view) [4],
                          float width, float height,
                          const float (& colours) [4] [4],
                          float fog_near, float fog_far,
                          float line_width_extra, float line_sharpness)
{
  glViewport (0, 0, width, height);

  const float (& ambient) [4] = colours [0];
  const float (& background) [4] = colours [1];
  const float (& line_colour) [4] = colours [2];
  const float (& specular) [4] = colours [3];

  glClearColor (background [0], background [1], background [2], 0.0f);

  float z1 = view [0];  // z coord of screen (front of tank) (a negative number)
  float z2 = view [1];  // z coord of back of tank (a negative number) (|z2| > |z1|)
  float x1 = view [2];  // x coord of right edge of screen (and of front-right edge of tank)
  float y1 = view [3];  // y coord of top edge of screen (and of front-top edge of tank)
  float zd = z1 - z2;   // tank depth

  // Fog is linear in z-distance.
  float fogn = 1.0f - fog_near;
  float fogf = 1.0f - fog_far;
  float fogd = fogn - fogf;
  float fog1 = fogd / zd;
  float fog0 = fogf - fog1 * z2;

  float line0 = -0.5f * line_width_extra * line_sharpness;
  float line1 = line_sharpness;

  // Data blocks in layout std140.

  struct fragment_data_t
  {
    GLfloat l [4] [4];  // vec3 [4],  light positions
    GLfloat a [4];      // vec3,      ambient reflection (rgb)
    GLfloat b [4];      // vec3,      background (rgb)
    GLfloat c [4];      // vec4,      line colour (rgba)
    GLfloat r [4];      // vec4,      xyz: specular reflection (rgb); w: exponent
    GLfloat f [4];      // vec4,      coefficients for line width and fog
  };

  struct geometry_data_t
  {
    GLfloat p [4] [4];  // mat4,      projection matrix
    GLfloat q [4];      // vec3,      pixel scale of normalized device coordinates
  };

  ALIGNED16 fragment_data_t fragment_data = {
    {
      { -0.6f * x1, -0.2f * y1, z1 + y1, 0.0f, },
      { -0.2f * x1, +0.6f * y1, z1 + x1, 0.0f, },
      { +0.2f * x1, -0.6f * y1, z1 + y1, 0.0f, },
      { +0.6f * x1, +0.2f * y1, z1 + x1, 0.0f, },
    },
    { 0, 0, 0, 0, },
    { 0, 0, 0, 0, },
    { 0, 0, 0, 0, },
    { 0, 0, 0, 0, },
    { line0, line1, fog0, fog1, }
  };

  store4f (fragment_data.a, load4f (ambient));
  store4f (fragment_data.b, load4f (background));
  store4f (fragment_data.c, load4f (line_colour));
  store4f (fragment_data.r, load4f (specular));

  ALIGNED16 geometry_data_t geometry_data = {
    {
      { -z1/x1,     0,       0,          0, },
      {    0,    -z1/y1,     0,          0, },
      {    0,       0,    -(z1+z2)/zd,  -1, },
      {    0,       0,     2*z1*z2/zd,   0, },
    },
    { width / 2.0f, height / 2.0f, 0, 0, },
  };

  // Descriptions of the data blocks.

  struct block_descriptor_t
  {
    const char * name;
    GLvoid * data;
    GLsizeiptr size;
  };

  block_descriptor_t blocks [] = {
    { "F", & fragment_data, sizeof fragment_data, },
    { "G", & geometry_data, sizeof geometry_data, },
  };
  GLuint block_count = sizeof blocks / sizeof blocks [0];

  // Create a uniform buffer big enough for all the data blocks.

  GLuint max_block_size = 0;
  for (std::size_t n = 0; n != block_count; ++ n)
    if (max_block_size < blocks [n].size)
      max_block_size = blocks [n].size;

  GLint align;
  glGetIntegerv (GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, & align);

  GLuint buffer_size, buffer_stride;
  align_up (buffer_stride, max_block_size, align);
  buffer_size = block_count * buffer_stride;

  GLuint buf_id;
  glGenBuffers (1, & buf_id);
  glBindBuffer (GL_UNIFORM_BUFFER, buf_id);
  glBufferData (GL_UNIFORM_BUFFER, buffer_size, nullptr, GL_STATIC_DRAW);

  // Copy each data block to a buffer range and bind the range to the named shader uniform block.

  for (std::size_t n = 0; n != block_count; ++ n) {
    glBufferSubData (GL_UNIFORM_BUFFER, n * buffer_stride, blocks [n].size, blocks [n].data);
    GLuint block_index = glGetUniformBlockIndex (id, blocks [n].name);
    GLuint binding_index = n + 1;
    glUniformBlockBinding (id, block_index, binding_index);
    glBindBufferRange (GL_UNIFORM_BUFFER, binding_index, buf_id, n * buffer_stride, blocks [n].size);
  }

  uniform_buffer.bind ();
}

bool program_t::initialize ()
{
  if (! uniform_buffer.initialize ()) return false;

  GLint status = 0;
  GLuint vshader_id = make_shader (GL_VERTEX_SHADER, IDR_VERTEX_SHADER);
  GLuint gshader_id = make_shader (GL_GEOMETRY_SHADER, IDR_GEOMETRY_SHADER);
  GLuint fshader_id = make_shader (GL_FRAGMENT_SHADER, IDR_FRAGMENT_SHADER);
  if (vshader_id && gshader_id && fshader_id) {
    id = glCreateProgram ();
    if (id) {
      glAttachShader (id, vshader_id);
      glAttachShader (id, gshader_id);
      glAttachShader (id, fshader_id);
      glBindAttribLocation (id, attribute_id_x, "x");
      glLinkProgram (id);
      glGetProgramiv (id, GL_LINK_STATUS, & status);
#if PRINT_ENABLED
      std::cout << "Shader program linking " << (status ? "succeeded." : "failed.") << std::endl;
      PRINT_INFO_LOG (id, glGetProgramiv, glGetProgramInfoLog);
#endif
      glDetachShader (id, fshader_id);
      glDetachShader (id, gshader_id);
      glDetachShader (id, vshader_id);
    }
  }
  if (fshader_id) glDeleteShader (fshader_id);
  if (gshader_id) glDeleteShader (gshader_id);
  if (vshader_id) glDeleteShader (vshader_id);

  if (! status) {
    //if (id) glDeleteProgram (id);
    return false;
  }

  // Binding for Uniform block "H".
  GLuint object_uniform_block_index = glGetUniformBlockIndex (id, "H");
  glUniformBlockBinding (id, object_uniform_block_index, OBJECT_UNIFORM_BINDING_INDEX);
  glUseProgram (id);

  return true;
}

void clear ()
{
  glClear (GL_COLOR_BUFFER_BIT);
}

void paint (unsigned N,
            unsigned vao_id,
            GLuint uniform_buffer_id,
            std::ptrdiff_t uniform_buffer_offset)
{
  const unsigned block_size = sizeof (object_data_t);
  glBindVertexArray (vao_id);
  glBindBufferRange (GL_UNIFORM_BUFFER, OBJECT_UNIFORM_BINDING_INDEX, uniform_buffer_id, uniform_buffer_offset, block_size);
  glCullFace (GL_FRONT);
  glDrawElements (GL_TRIANGLES_ADJACENCY, N * 6, GL_UNSIGNED_INT, nullptr);
  glCullFace (GL_BACK);
  glDrawElements (GL_TRIANGLES_ADJACENCY, N * 6, GL_UNSIGNED_INT, nullptr);
}
<commit_msg>graphics.cpp: use signed intger type to avoid a "comparing signed and unsigned" warning.<commit_after>#include "graphics.h"
#include "compiler.h"
#include "memory.h"
#include "resources.h"
#include "glinit.h"
#include "vector.h"
#include "print.h"

#include <cstddef>
#include <cstdint>

#define OBJECT_UNIFORM_BINDING_INDEX 0

namespace
{
#if PRINT_ENABLED
#define PRINT_INFO_LOG(a, b, c) print_info_log (a, b, c)
  inline void print_info_log (GLuint object,
                              PFNGLGETSHADERIVPROC glGet__iv,
                              PFNGLGETSHADERINFOLOGPROC glGet__InfoLog)
  {
    if (PRINT_ENABLED) {
      GLint log_length;
      glGet__iv (object, GL_INFO_LOG_LENGTH, & log_length);
      char * log = (char *) allocate_internal (log_length + 1);
      if (log) {
        glGet__InfoLog (object, log_length, NULL, log);
        log [log_length] = '\0';
        if (log [0]) print (log);
        deallocate (log);
      }
    }
  }
#else
#define PRINT_INFO_LOG(a, b, c)
#endif

  GLuint make_shader (GLenum type, int resource_id)
  {
    const char * text;
    GLint size;
    get_resource_data (resource_id, text, size);

    GLint id = glCreateShader (type);
    glShaderSource (id, 1, & text, & size);
    glCompileShader (id);
    GLint status = 0;
    glGetShaderiv (id, GL_COMPILE_STATUS, & status);
#if PRINT_ENABLED
    switch (resource_id) {
    case IDR_VERTEX_SHADER: std::cout << "Vertex "; break;
    case IDR_FRAGMENT_SHADER: std::cout << "Fragment "; break;
    case IDR_GEOMETRY_SHADER: std::cout << "Geometry "; break;
    default: ;
    }
    std::cout << "Shader compilation " << (status ? "succeeded." : "failed.") << std::endl;
    PRINT_INFO_LOG (id, glGetShaderiv, glGetShaderInfoLog);
#endif
    return status ? id : 0;
  }
}

static const int attribute_id_x = 0;

unsigned make_vao (unsigned N, const float (* vertices) [4], const unsigned (* indices) [6])
{
  unsigned vao_id;
  glGenVertexArrays (1, & vao_id);
  glBindVertexArray (vao_id);
  GLuint buffer_ids [2];
  glGenBuffers (2, buffer_ids);
  glBindBuffer (GL_ARRAY_BUFFER, buffer_ids [0]);
  glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, buffer_ids [1]);
  glBufferData (GL_ARRAY_BUFFER, (N + 2) * 4 * sizeof (float), vertices, GL_STATIC_DRAW);
  glBufferData (GL_ELEMENT_ARRAY_BUFFER, 6 * N * sizeof (unsigned), indices, GL_STATIC_DRAW);
  glVertexAttribPointer (attribute_id_x, 4, GL_FLOAT, GL_FALSE, 0, 0);
  glEnableVertexAttribArray (attribute_id_x);
  return vao_id;
}

namespace
{
  // Align x upwards to given alignment (which must be a power of 2). Store the result in y.
  template <typename Dest, typename Source>
  inline void align_up (Dest & y, Source x, std::intptr_t alignment)
  {
    y = (Dest) ((((std::intptr_t) (x)) + (alignment - 1)) & - alignment);
  }
}

uniform_buffer_t::~uniform_buffer_t ()
{
  //glDeleteBuffers (1, & m_id);
  deallocate (m_memory);
}

bool uniform_buffer_t::initialize ()
{
  GLint max_size, align;
  glGetIntegerv (GL_MAX_UNIFORM_BLOCK_SIZE, & max_size);
  glGetIntegerv (GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, & align);
  // Align client-side buffer to at least 64 bytes, to avoid straddling cache lines.
  align = align > 64 ? align : 64;
  m_size = max_size;
  m_memory = allocate_internal (m_size + align);
  if (! m_memory) return false;
  align_up (m_begin, m_memory, align);
  align_up (m_stride, sizeof (object_data_t), align);
  glGenBuffers (1, & m_id);
  return true;
}

void uniform_buffer_t::bind ()
{
  glBindBuffer (GL_UNIFORM_BUFFER, m_id);
}

void uniform_buffer_t::update ()
{
  // Create a buffer, orphaning any previous buffer.
  glBufferData (GL_UNIFORM_BUFFER, m_size, nullptr, GL_DYNAMIC_DRAW);
  // Upload the buffer data.
  glBufferSubData (GL_UNIFORM_BUFFER, 0, m_size, m_begin);
}

bool initialize_graphics (program_t & program)
{
  glEnable (GL_DEPTH_CLAMP);
  glEnable (GL_CULL_FACE);
  glEnable (GL_BLEND);
  glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  return program.initialize ();
}

void program_t::set_view (const float (& view) [4],
                          float width, float height,
                          const float (& colours) [4] [4],
                          float fog_near, float fog_far,
                          float line_width_extra, float line_sharpness)
{
  glViewport (0, 0, width, height);

  const float (& ambient) [4] = colours [0];
  const float (& background) [4] = colours [1];
  const float (& line_colour) [4] = colours [2];
  const float (& specular) [4] = colours [3];

  glClearColor (background [0], background [1], background [2], 0.0f);

  float z1 = view [0];  // z coord of screen (front of tank) (a negative number)
  float z2 = view [1];  // z coord of back of tank (a negative number) (|z2| > |z1|)
  float x1 = view [2];  // x coord of right edge of screen (and of front-right edge of tank)
  float y1 = view [3];  // y coord of top edge of screen (and of front-top edge of tank)
  float zd = z1 - z2;   // tank depth

  // Fog is linear in z-distance.
  float fogn = 1.0f - fog_near;
  float fogf = 1.0f - fog_far;
  float fogd = fogn - fogf;
  float fog1 = fogd / zd;
  float fog0 = fogf - fog1 * z2;

  float line0 = -0.5f * line_width_extra * line_sharpness;
  float line1 = line_sharpness;

  // Data blocks in layout std140.

  struct fragment_data_t
  {
    GLfloat l [4] [4];  // vec3 [4],  light positions
    GLfloat a [4];      // vec3,      ambient reflection (rgb)
    GLfloat b [4];      // vec3,      background (rgb)
    GLfloat c [4];      // vec4,      line colour (rgba)
    GLfloat r [4];      // vec4,      xyz: specular reflection (rgb); w: exponent
    GLfloat f [4];      // vec4,      coefficients for line width and fog
  };

  struct geometry_data_t
  {
    GLfloat p [4] [4];  // mat4,      projection matrix
    GLfloat q [4];      // vec3,      pixel scale of normalized device coordinates
  };

  ALIGNED16 fragment_data_t fragment_data = {
    {
      { -0.6f * x1, -0.2f * y1, z1 + y1, 0.0f, },
      { -0.2f * x1, +0.6f * y1, z1 + x1, 0.0f, },
      { +0.2f * x1, -0.6f * y1, z1 + y1, 0.0f, },
      { +0.6f * x1, +0.2f * y1, z1 + x1, 0.0f, },
    },
    { 0, 0, 0, 0, },
    { 0, 0, 0, 0, },
    { 0, 0, 0, 0, },
    { 0, 0, 0, 0, },
    { line0, line1, fog0, fog1, }
  };

  store4f (fragment_data.a, load4f (ambient));
  store4f (fragment_data.b, load4f (background));
  store4f (fragment_data.c, load4f (line_colour));
  store4f (fragment_data.r, load4f (specular));

  ALIGNED16 geometry_data_t geometry_data = {
    {
      { -z1/x1,     0,       0,          0, },
      {    0,    -z1/y1,     0,          0, },
      {    0,       0,    -(z1+z2)/zd,  -1, },
      {    0,       0,     2*z1*z2/zd,   0, },
    },
    { width / 2.0f, height / 2.0f, 0, 0, },
  };

  // Descriptions of the data blocks.

  struct block_descriptor_t
  {
    const char * name;
    GLvoid * data;
    GLsizeiptr size;
  };

  block_descriptor_t blocks [] = {
    { "F", & fragment_data, sizeof fragment_data, },
    { "G", & geometry_data, sizeof geometry_data, },
  };
  GLuint block_count = sizeof blocks / sizeof blocks [0];

  // Create a uniform buffer big enough for all the data blocks.

  GLsizeiptr max_block_size = 0;
  for (std::size_t n = 0; n != block_count; ++ n)
    if (max_block_size < blocks [n].size)
      max_block_size = blocks [n].size;

  GLint align;
  glGetIntegerv (GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, & align);

  GLuint buffer_size, buffer_stride;
  align_up (buffer_stride, max_block_size, align);
  buffer_size = block_count * buffer_stride;

  GLuint buf_id;
  glGenBuffers (1, & buf_id);
  glBindBuffer (GL_UNIFORM_BUFFER, buf_id);
  glBufferData (GL_UNIFORM_BUFFER, buffer_size, nullptr, GL_STATIC_DRAW);

  // Copy each data block to a buffer range and bind the range to the named shader uniform block.

  for (std::size_t n = 0; n != block_count; ++ n) {
    glBufferSubData (GL_UNIFORM_BUFFER, n * buffer_stride, blocks [n].size, blocks [n].data);
    GLuint block_index = glGetUniformBlockIndex (id, blocks [n].name);
    GLuint binding_index = n + 1;
    glUniformBlockBinding (id, block_index, binding_index);
    glBindBufferRange (GL_UNIFORM_BUFFER, binding_index, buf_id, n * buffer_stride, blocks [n].size);
  }

  uniform_buffer.bind ();
}

bool program_t::initialize ()
{
  if (! uniform_buffer.initialize ()) return false;

  GLint status = 0;
  GLuint vshader_id = make_shader (GL_VERTEX_SHADER, IDR_VERTEX_SHADER);
  GLuint gshader_id = make_shader (GL_GEOMETRY_SHADER, IDR_GEOMETRY_SHADER);
  GLuint fshader_id = make_shader (GL_FRAGMENT_SHADER, IDR_FRAGMENT_SHADER);
  if (vshader_id && gshader_id && fshader_id) {
    id = glCreateProgram ();
    if (id) {
      glAttachShader (id, vshader_id);
      glAttachShader (id, gshader_id);
      glAttachShader (id, fshader_id);
      glBindAttribLocation (id, attribute_id_x, "x");
      glLinkProgram (id);
      glGetProgramiv (id, GL_LINK_STATUS, & status);
#if PRINT_ENABLED
      std::cout << "Shader program linking " << (status ? "succeeded." : "failed.") << std::endl;
      PRINT_INFO_LOG (id, glGetProgramiv, glGetProgramInfoLog);
#endif
      glDetachShader (id, fshader_id);
      glDetachShader (id, gshader_id);
      glDetachShader (id, vshader_id);
    }
  }
  if (fshader_id) glDeleteShader (fshader_id);
  if (gshader_id) glDeleteShader (gshader_id);
  if (vshader_id) glDeleteShader (vshader_id);

  if (! status) {
    //if (id) glDeleteProgram (id);
    return false;
  }

  // Binding for Uniform block "H".
  GLuint object_uniform_block_index = glGetUniformBlockIndex (id, "H");
  glUniformBlockBinding (id, object_uniform_block_index, OBJECT_UNIFORM_BINDING_INDEX);
  glUseProgram (id);

  return true;
}

void clear ()
{
  glClear (GL_COLOR_BUFFER_BIT);
}

void paint (unsigned N,
            unsigned vao_id,
            GLuint uniform_buffer_id,
            std::ptrdiff_t uniform_buffer_offset)
{
  const unsigned block_size = sizeof (object_data_t);
  glBindVertexArray (vao_id);
  glBindBufferRange (GL_UNIFORM_BUFFER, OBJECT_UNIFORM_BINDING_INDEX, uniform_buffer_id, uniform_buffer_offset, block_size);
  glCullFace (GL_FRONT);
  glDrawElements (GL_TRIANGLES_ADJACENCY, N * 6, GL_UNSIGNED_INT, nullptr);
  glCullFace (GL_BACK);
  glDrawElements (GL_TRIANGLES_ADJACENCY, N * 6, GL_UNSIGNED_INT, nullptr);
}
<|endoftext|>


<commit_before>// Copyright (c) 2014 Joseph D Poirier
// Distributable under the terms of The New BSD License
// that can be found in the LICENSE file.

#ifdef _WIN32 /* this is set for 64 bit as well */
# define WIN32_LEAN_AND_MEAN
# include <windows.h>
#endif

#ifdef _APPLE_
#include <OpenGl/gl.h>
#else
#include <GL/gl.h>
#endif

#include <math.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>

#include "XPLMDefs.h"
#include "XPLMPlugin.h"
#include "XPLMProcessing.h"
#include "XPLMDataAccess.h"
#include "XPLMUtilities.h"
#include "XPLMDisplay.h"
#include "XPLMGraphics.h"

#include "defs.h"
#include "commviewer.h"

static int CommandHandler(XPLMCommandRef inCommand,
                          XPLMCommandPhase inPhase,
                          void* inRefcon);

static void DrawWindowCallback(XPLMWindowID inWindowID,
                               void* inRefcon);

static void HandleKeyCallback(XPLMWindowID inWindowID,
                              char inKey,
                              XPLMKeyFlags inFlags,
                              char inVirtualKey,
                              void* inRefcon,
                              int losingFocus);

static int HandleMouseCallback(XPLMWindowID inWindowID,
                               int x,
                               int y,
                               XPLMMouseStatus inMouse,
                               void* inRefcon);

static void HotKeyCallback(void* inRefcon);

static XPLMWindowID gWindow = NULL;
static bool gPluginEnabled = false;
static int gPlaneLoaded = 0;
static const float FL_CB_INTERVAL = -1.0;
static bool gPTT_On = false;
static XPLMHotKeyID gHotKey = NULL;

#define WINDOW_WIDTH (200)
#define WINDOW_HEIGHT (40)
static int gWinPosX;
static int gWinPosY;
static int gLastMouseX;
static int gLastMouseY;

// general & misc
enum {
    PLUGIN_PLANE_ID = 0,
    CMD_CONTACT_ATC,
};

// Command Refs
#define sCONTACT_ATC   "sim/operation/contact_atc"

XPLMDataRef avionics_power_on_dataref;
XPLMDataRef audio_selection_com1_dataref;
XPLMDataRef audio_selection_com2_dataref;

#ifdef TOGGLE_TEST_FEATURE
XPLMDataRef window_ice_dataref;

XPLMDataRef artificial_stability_on_dataref;
XPLMDataRef artificial_stability_pitch_on_dataref;
XPLMDataRef artificial_stability_roll_on_dataref;
#endif

XPLMDataRef panel_visible_win_t_dataref;

/*
 *
 *
 */
PLUGIN_API int XPluginStart(char* outName, char* outSig, char* outDesc) {

    LPRINTF("CommView Plugin: XPluginStart\n");
    strcpy(outName, "CommViewer");
    strcpy(outSig , "jdp.comm.view");
    strcpy(outDesc, "CommView Plugin.");

    // sim/cockpit/switches/audio_panel_out

    // sim/cockpit2/radios/actuators/audio_com_selection
    // sim/cockpit2/radios/actuators/audio_selection_com1 int   y   boolean is com1 selected for listening
    // sim/cockpit2/radios/actuators/audio_selection_com2 int   y   boolean is com2 selected for listening
    // sim/cockpit2/radios/actuators/com1_power int y   boolean Com radio 1 off or on, 0 or 1.
    // sim/cockpit2/radios/actuators/com2_power int y   boolean Com radio 2 off or on, 0 or 1.

    //avionics_power_on_dataref = XPLMFindDataRef("sim/cockpit2/switches/avionics_power_on");
    //LPRINTF("CommView Plugin: data/command refs initialized\n");

    audio_selection_com1_dataref = XPLMFindDataRef("sim/cockpit2/radios/actuators/audio_selection_com1");
    audio_selection_com2_dataref = XPLMFindDataRef("sim/cockpit2/radios/actuators/audio_selection_com2");

#ifdef TOGGLE_TEST_FEATURE
    artificial_stability_on_dataref = XPLMFindDataRef("sim/cockpit2/switches/artificial_stability_on");
    artificial_stability_pitch_on_dataref = XPLMFindDataRef("sim/cockpit2/switches/artificial_stability_pitch_on");
    artificial_stability_roll_on_dataref = XPLMFindDataRef("sim/cockpit2/switches/artificial_stability_roll_on");
    XPLMSetDatai(artificial_stability_on_dataref, 1);
    XPLMSetDatai(artificial_stability_pitch_on_dataref, 1);
    XPLMSetDatai(artificial_stability_roll_on_dataref, 1);
#endif

    XPLMCommandRef cmd_ref;
    cmd_ref = XPLMCreateCommand(sCONTACT_ATC, "Contact ATC");
    XPLMRegisterCommandHandler(cmd_ref, CommandHandler, CMD_HNDLR_EPILOG, (void*)CMD_CONTACT_ATC);

    // XPLMRegisterFlightLoopCallback(FlightLoopCallback, FL_CB_INTERVAL, NULL);
    panel_visible_win_t_dataref = XPLMFindDataRef("sim/graphics/view/panel_visible_win_t");

    int top = (int)XPLMGetDataf(panel_visible_win_t_dataref);
    gWinPosX = 0;
    gWinPosY = top - 200;
    gWindow = XPLMCreateWindow(gWinPosX,                // left
                               gWinPosY,                // top
                               gWinPosX+WINDOW_WIDTH,   // right
                               gWinPosY-WINDOW_HEIGHT,  // bottom
                               true,                    // is visible
                               DrawWindowCallback,
                               HandleKeyCallback,
                               HandleMouseCallback,
                               NULL);                   // Refcon

#ifdef TOGGLE_TEST_FEATURE
    //gHotKey = XPLMRegisterHotKey(XPLM_VK_F3,
    //                             xplm_DownFlag,
    //                             "Toggle Window Ice",
    //                             HotKeyCallback,
    //                             NULL);
#endif

    LPRINTF("CommView Plugin: startup completed\n");

    return PROCESSED_EVENT;
}

#ifdef TOGGLE_TEST_FEATURE
/*
 *
 *
 */
void HotKeyCallback(void* inRefcon) {
    static bool isSaved = false;

    if (isSaved) {
        isSaved = false;
    } else {
        isSaved = true;
    }
}
#endif

/*
 *
 *
 */
float FlightLoopCallback(float inElapsedSinceLastCall,
                         float inElapsedTimeSinceLastFlightLoop,
                         int inCounter,
                         void* inRefcon) {

//   if ((gFlCbCnt % PANEL_CHECK_INTERVAL) == 0) {
//   }

    if (!gPluginEnabled) {

    }

    return 1.0;
}

/*
 *
 *
 */
int CommandHandler(XPLMCommandRef inCommand,
                   XPLMCommandPhase inPhase,
                   void* inRefcon) {

//    if ((gFlCbCnt % PANEL_CHECK_INTERVAL) == 0) {
//    }
//    if (!gPluginEnabled) {
//        return IGNORED_EVENT;
//    }

    switch (reinterpret_cast<uint32_t>(inRefcon)) {
    case CMD_CONTACT_ATC:
        switch (inPhase) {
        case xplm_CommandBegin:
        case xplm_CommandContinue:
            gPTT_On = true;
            break;
        case xplm_CommandEnd:
            gPTT_On = false;
            break;
        default:
            break;
        }
        break;
    default:
        break;
    }

    return IGNORED_EVENT;
}

/*
 *
 */
PLUGIN_API void XPluginStop(void) {

    gPluginEnabled = false;
    //XPLMUnregisterFlightLoopCallback(FlightLoopCallback, NULL);
    LPRINTF("CommView Plugin: XPluginStop\n");
}

/*
 *
 */
PLUGIN_API void XPluginDisable(void) {

    gPluginEnabled = false;
    LPRINTF("CommView Plugin: XPluginDisable\n");
}

/*
 *
 */
PLUGIN_API int XPluginEnable(void) {

    gPluginEnabled = true;
    LPRINTF("CommView Plugin: XPluginEnable\n");

    return PROCESSED_EVENT;
}

/*
 *
 */
PLUGIN_API void XPluginReceiveMessage(XPLMPluginID inFrom,
                                      long inMsg,
                                      void* inParam) {

    if (inFrom == XPLM_PLUGIN_XPLANE) {
        int inparam = reinterpret_cast<int>(inParam);
        switch (inMsg) {
        case XPLM_MSG_PLANE_LOADED:
            if (inparam != PLUGIN_PLANE_ID || gPlaneLoaded) { break; }
            LPRINTF("CommView Plugin: XPluginReceiveMessage XPLM_MSG_PLANE_LOADED\n");
            break;
        case XPLM_MSG_AIRPORT_LOADED:
            LPRINTF("CommView Plugin: XPluginReceiveMessage XPLM_MSG_AIRPORT_LOADED\n");
            break;
        case XPLM_MSG_SCENERY_LOADED:
            LPRINTF("CommView Plugin: XPluginReceiveMessage XPLM_MSG_SCENERY_LOADED\n");
            break;
        case XPLM_MSG_AIRPLANE_COUNT_CHANGED:
            LPRINTF("CommView Plugin: XPluginReceiveMessage XPLM_MSG_AIRPLANE_COUNT_CHANGED\n");
            break;
        // XXX: system state and procedure, what's difference between an unloaded and crashed plane?
        case XPLM_MSG_PLANE_CRASHED:
            if ((int)inParam != PLUGIN_PLANE_ID) { break; }
            LPRINTF("CommView Plugin: XPluginReceiveMessage XPLM_MSG_PLANE_CRASHED\n");
            break;
        case XPLM_MSG_PLANE_UNLOADED:
            if ((int)inParam != PLUGIN_PLANE_ID) { break; }
            LPRINTF("CommView Plugin: XPluginReceiveMessage XPLM_MSG_PLANE_UNLOADED\n");
            break;
        default: // unknown
            break;
        } // switch (inMsg)
    } // if (inFrom == XPLM_PLUGIN_XPLANE)
}

/*
 *
 *
 */
void DrawWindowCallback(XPLMWindowID inWindowID, void* inRefcon) {

    int left;
    int top;
    int right;
    int bottom;
    static char str[100];
    static float color[] = {1.0, 1.0, 1.0};  // RGB White

    //int top = (int)XPLMGetDataf(panel_visible_win_t_dataref);
    //XPLMDrawTranslucentDarkBox(0, top-200, 300, top-200-50);

    // location of the window and draw the window
    XPLMGetWindowGeometry(inWindowID, &left, &top, &right, &bottom);
    XPLMDrawTranslucentDarkBox(left, top, right, bottom);

    // put the text into the window, NULL indicates no word wrap
#if 1
    sprintf(str,"%s\t\t\tCOM1: %d\t\t\tCOM2: %d",
        (char*)(gPTT_On ? "PTT: ON" : "PTT: OFF"),
        XPLMGetDatai(audio_selection_com1_dataref),
        XPLMGetDatai(audio_selection_com2_dataref));

    XPLMDrawString(color, left+5, top-20, str, NULL, xplmFont_Basic);
#else
     XPLMDrawString(color,
                    left+5,
                    top,
                    (char*)(gCounter ? "PTT: ON" : "PTT: OFF"),
                    NULL,
                    xplmFont_Basic);
#endif
    //glDisable(GL_TEXTURE_2D);
    //glColor3f(0.7, 0.7, 0.7);
    //glBegin(GL_LINES);
    //    glVertex2i(right-1, top-1);
    //    glVertex2i(right-7, top-7);
    //    glVertex2i(right-7, top-1);
    //    glVertex2i(right-1, top-7);
    //glEnd();
    //glEnable(GL_TEXTURE_2D);
}

/*
 *
 *
 */
void HandleKeyCallback(XPLMWindowID inWindowID,
                         char inKey,
                         XPLMKeyFlags inFlags,
                         char inVirtualKey,
                         void* inRefcon,
                         int losingFocus) {

    // nothing to do here
}

/*
 *
 *
 */
 #define COMS_UNCHANGED (0)
 #define COM1_CHANGED   (1)
 #define COM2_CHANGED   (2)
int HandleMouseCallback(XPLMWindowID inWindowID,
                        int x,
                        int y,
                        XPLMMouseStatus inMouse,
                        void* inRefcon) {

    static int com_changed = COMS_UNCHANGED;
    static int MouseDownX;
    static int MouseDownY;

    switch (inMouse) {
    case xplm_MouseDown:
        // if ((x >= gWinPosX+WINDOW_WIDTH-8) &&
        //     (x <= gWinPosX+WINDOW_WIDTH) &&
        //     (y <= gWinPosY) && (y >= gWinPosY-8)) {
        //         windowCloseRequest = 1;
        //     } else {
                MouseDownX = gLastMouseX = x;
                MouseDownY = gLastMouseY = y;
        // }
        break;
    case xplm_MouseDrag:
        // this event fires while xplm_MouseDown
        // and whether the window is being dragged or not
        gWinPosX += (x - gLastMouseX);
        gWinPosY += (y - gLastMouseY);
        XPLMSetWindowGeometry(gWindow,
                              gWinPosX,
                              gWinPosY,
                              gWinPosX+WINDOW_WIDTH,
                              gWinPosY-WINDOW_HEIGHT);
        gLastMouseX = x;
        gLastMouseY = y;
        break;
    case xplm_MouseUp:
        if (MouseDownX == x && MouseDownY == y) {
            int com1 = XPLMGetDatai(audio_selection_com1_dataref);
            int com2 = XPLMGetDatai(audio_selection_com2_dataref);

            if (com1 && com2 && com_changed) {
                switch (com_changed) {
                case COM1_CHANGED:
                    XPLMSetDatai(audio_selection_com1_dataref, 0);
                    break;
                case COM2_CHANGED:
                    XPLMSetDatai(audio_selection_com2_dataref, 0);
                    break;
                default:
                    break;
                }
                com_changed = COMS_UNCHANGED;
            } else if (!com1 && com2) {
                com_changed = COM1_CHANGED;
                XPLMSetDatai(audio_selection_com1_dataref, 1);
            }  else if (com1 && !com2) {
                com_changed = COM2_CHANGED;
                XPLMSetDatai(audio_selection_com2_dataref, 1);
            }
        }
        break;
    } // switch (inMouse)

    return PROCESSED_EVENT;
}
<commit_msg>sync plugin name to strings, remove magic numbers<commit_after>// Copyright (c) 2014 Joseph D Poirier
// Distributable under the terms of The New BSD License
// that can be found in the LICENSE file.

#ifdef _WIN32 /* this is set for 64 bit as well */
# define WIN32_LEAN_AND_MEAN
# include <windows.h>
#endif

#ifdef _APPLE_
#include <OpenGl/gl.h>
#else
#include <GL/gl.h>
#endif

#include <math.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>

#include "XPLMDefs.h"
#include "XPLMPlugin.h"
#include "XPLMProcessing.h"
#include "XPLMDataAccess.h"
#include "XPLMUtilities.h"
#include "XPLMDisplay.h"
#include "XPLMGraphics.h"

#include "defs.h"
#include "commviewer.h"

static int CommandHandler(XPLMCommandRef inCommand,
                          XPLMCommandPhase inPhase,
                          void* inRefcon);

static void DrawWindowCallback(XPLMWindowID inWindowID,
                               void* inRefcon);

static void HandleKeyCallback(XPLMWindowID inWindowID,
                              char inKey,
                              XPLMKeyFlags inFlags,
                              char inVirtualKey,
                              void* inRefcon,
                              int losingFocus);

static int HandleMouseCallback(XPLMWindowID inWindowID,
                               int x,
                               int y,
                               XPLMMouseStatus inMouse,
                               void* inRefcon);

static void HotKeyCallback(void* inRefcon);

static XPLMWindowID gWindow = NULL;
static bool gPluginEnabled = false;
static int gPlaneLoaded = 0;
static const float FL_CB_INTERVAL = -1.0;
static bool gPTT_On = false;
static XPLMHotKeyID gHotKey = NULL;

#define WINDOW_WIDTH (200)
#define WINDOW_HEIGHT (40)
static int gWinPosX;
static int gWinPosY;
static int gLastMouseX;
static int gLastMouseY;

// general & misc
enum {
    PLUGIN_PLANE_ID = 0,
    CMD_CONTACT_ATC,
};

// Command Refs
#define sCONTACT_ATC   "sim/operation/contact_atc"

XPLMDataRef avionics_power_on_dataref;
XPLMDataRef audio_selection_com1_dataref;
XPLMDataRef audio_selection_com2_dataref;

#ifdef TOGGLE_TEST_FEATURE
XPLMDataRef window_ice_dataref;

XPLMDataRef artificial_stability_on_dataref;
XPLMDataRef artificial_stability_pitch_on_dataref;
XPLMDataRef artificial_stability_roll_on_dataref;
#endif

XPLMDataRef panel_visible_win_t_dataref;

/*
 *
 *
 */
PLUGIN_API int XPluginStart(char* outName, char* outSig, char* outDesc) {

    LPRINTF("CommView Plugin: XPluginStart\n");
    strcpy(outName, "CommViewer");
    strcpy(outSig , "jdp.comm.viewer");
    strcpy(outDesc, "CommViewer Plugin.");

    // sim/cockpit/switches/audio_panel_out

    // sim/cockpit2/radios/actuators/audio_com_selection
    // sim/cockpit2/radios/actuators/audio_selection_com1 int   y   boolean is com1 selected for listening
    // sim/cockpit2/radios/actuators/audio_selection_com2 int   y   boolean is com2 selected for listening
    // sim/cockpit2/radios/actuators/com1_power int y   boolean Com radio 1 off or on, 0 or 1.
    // sim/cockpit2/radios/actuators/com2_power int y   boolean Com radio 2 off or on, 0 or 1.

    //avionics_power_on_dataref = XPLMFindDataRef("sim/cockpit2/switches/avionics_power_on");
    //LPRINTF("CommView Plugin: data/command refs initialized\n");

    audio_selection_com1_dataref = XPLMFindDataRef("sim/cockpit2/radios/actuators/audio_selection_com1");
    audio_selection_com2_dataref = XPLMFindDataRef("sim/cockpit2/radios/actuators/audio_selection_com2");

#ifdef TOGGLE_TEST_FEATURE
    artificial_stability_on_dataref = XPLMFindDataRef("sim/cockpit2/switches/artificial_stability_on");
    artificial_stability_pitch_on_dataref = XPLMFindDataRef("sim/cockpit2/switches/artificial_stability_pitch_on");
    artificial_stability_roll_on_dataref = XPLMFindDataRef("sim/cockpit2/switches/artificial_stability_roll_on");
    XPLMSetDatai(artificial_stability_on_dataref, 1);
    XPLMSetDatai(artificial_stability_pitch_on_dataref, 1);
    XPLMSetDatai(artificial_stability_roll_on_dataref, 1);
#endif

    XPLMCommandRef cmd_ref;
    cmd_ref = XPLMCreateCommand(sCONTACT_ATC, "Contact ATC");
    XPLMRegisterCommandHandler(cmd_ref,
                               CommandHandler,
                               CMD_HNDLR_EPILOG,
                               (void*)CMD_CONTACT_ATC);

    // XPLMRegisterFlightLoopCallback(FlightLoopCallback, FL_CB_INTERVAL, NULL);
    panel_visible_win_t_dataref = XPLMFindDataRef("sim/graphics/view/panel_visible_win_t");

    int top = (int)XPLMGetDataf(panel_visible_win_t_dataref);
    gWinPosX = 0;
    gWinPosY = top - 200;
    gWindow = XPLMCreateWindow(gWinPosX,                // left
                               gWinPosY,                // top
                               gWinPosX+WINDOW_WIDTH,   // right
                               gWinPosY-WINDOW_HEIGHT,  // bottom
                               true,                    // is visible
                               DrawWindowCallback,
                               HandleKeyCallback,
                               HandleMouseCallback,
                               NULL);                   // Refcon

#ifdef TOGGLE_TEST_FEATURE
    //gHotKey = XPLMRegisterHotKey(XPLM_VK_F3,
    //                             xplm_DownFlag,
    //                             "Toggle Window Ice",
    //                             HotKeyCallback,
    //                             NULL);
#endif

    LPRINTF("CommView Plugin: startup completed\n");

    return PROCESSED_EVENT;
}

#ifdef TOGGLE_TEST_FEATURE
/*
 *
 *
 */
void HotKeyCallback(void* inRefcon) {
    static bool isSaved = false;

    if (isSaved) {
        isSaved = false;
    } else {
        isSaved = true;
    }
}
#endif

/*
 *
 *
 */
float FlightLoopCallback(float inElapsedSinceLastCall,
                         float inElapsedTimeSinceLastFlightLoop,
                         int inCounter,
                         void* inRefcon) {

//   if ((gFlCbCnt % PANEL_CHECK_INTERVAL) == 0) {
//   }

    if (!gPluginEnabled) {

    }

    return 1.0;
}

/*
 *
 *
 */
int CommandHandler(XPLMCommandRef inCommand,
                   XPLMCommandPhase inPhase,
                   void* inRefcon) {

//    if ((gFlCbCnt % PANEL_CHECK_INTERVAL) == 0) {
//    }
//    if (!gPluginEnabled) {
//        return IGNORED_EVENT;
//    }

    switch (reinterpret_cast<uint32_t>(inRefcon)) {
    case CMD_CONTACT_ATC:
        switch (inPhase) {
        case xplm_CommandBegin:
        case xplm_CommandContinue:
            gPTT_On = true;
            break;
        case xplm_CommandEnd:
            gPTT_On = false;
            break;
        default:
            break;
        }
        break;
    default:
        break;
    }

    return IGNORED_EVENT;
}

/*
 *
 */
PLUGIN_API void XPluginStop(void) {

    gPluginEnabled = false;
    //XPLMUnregisterFlightLoopCallback(FlightLoopCallback, NULL);
    LPRINTF("CommView Plugin: XPluginStop\n");
}

/*
 *
 */
PLUGIN_API void XPluginDisable(void) {

    gPluginEnabled = false;
    LPRINTF("CommView Plugin: XPluginDisable\n");
}

/*
 *
 */
PLUGIN_API int XPluginEnable(void) {

    gPluginEnabled = true;
    LPRINTF("CommView Plugin: XPluginEnable\n");

    return PROCESSED_EVENT;
}

/*
 *
 */
PLUGIN_API void XPluginReceiveMessage(XPLMPluginID inFrom,
                                      long inMsg,
                                      void* inParam) {

    if (inFrom == XPLM_PLUGIN_XPLANE) {
        int inparam = reinterpret_cast<int>(inParam);
        switch (inMsg) {
        case XPLM_MSG_PLANE_LOADED:
            if (inparam != PLUGIN_PLANE_ID || gPlaneLoaded) { break; }
            LPRINTF("CommView Plugin: XPluginReceiveMessage XPLM_MSG_PLANE_LOADED\n");
            break;
        case XPLM_MSG_AIRPORT_LOADED:
            LPRINTF("CommView Plugin: XPluginReceiveMessage XPLM_MSG_AIRPORT_LOADED\n");
            break;
        case XPLM_MSG_SCENERY_LOADED:
            LPRINTF("CommView Plugin: XPluginReceiveMessage XPLM_MSG_SCENERY_LOADED\n");
            break;
        case XPLM_MSG_AIRPLANE_COUNT_CHANGED:
            LPRINTF("CommView Plugin: XPluginReceiveMessage XPLM_MSG_AIRPLANE_COUNT_CHANGED\n");
            break;
        // XXX: system state and procedure, what's difference between an unloaded and crashed plane?
        case XPLM_MSG_PLANE_CRASHED:
            if ((int)inParam != PLUGIN_PLANE_ID) { break; }
            LPRINTF("CommView Plugin: XPluginReceiveMessage XPLM_MSG_PLANE_CRASHED\n");
            break;
        case XPLM_MSG_PLANE_UNLOADED:
            if ((int)inParam != PLUGIN_PLANE_ID) { break; }
            LPRINTF("CommView Plugin: XPluginReceiveMessage XPLM_MSG_PLANE_UNLOADED\n");
            break;
        default: // unknown
            break;
        } // switch (inMsg)
    } // if (inFrom == XPLM_PLUGIN_XPLANE)
}

/*
 *
 *
 */
void DrawWindowCallback(XPLMWindowID inWindowID, void* inRefcon) {

    int left;
    int top;
    int right;
    int bottom;
    static char str[100];
    static float color[] = {1.0, 1.0, 1.0};  // RGB White

    //int top = (int)XPLMGetDataf(panel_visible_win_t_dataref);
    //XPLMDrawTranslucentDarkBox(0, top-200, 300, top-200-50);

    // location of the window and draw the window
    XPLMGetWindowGeometry(inWindowID, &left, &top, &right, &bottom);
    XPLMDrawTranslucentDarkBox(left, top, right, bottom);

    // text to window, NULL indicates no word wrap
    sprintf(str,"%s\t\t\tCOM1: %d\t\t\tCOM2: %d",
        (char*)(gPTT_On ? "PTT: ON" : "PTT: OFF"),
        XPLMGetDatai(audio_selection_com1_dataref),
        XPLMGetDatai(audio_selection_com2_dataref));
    XPLMDrawString(color, left+5, top-20, str, NULL, xplmFont_Basic);

    //glDisable(GL_TEXTURE_2D);
    //glColor3f(0.7, 0.7, 0.7);
    //glBegin(GL_LINES);
    //    glVertex2i(right-1, top-1);
    //    glVertex2i(right-7, top-7);
    //    glVertex2i(right-7, top-1);
    //    glVertex2i(right-1, top-7);
    //glEnd();
    //glEnable(GL_TEXTURE_2D);
}

/*
 *
 *
 */
void HandleKeyCallback(XPLMWindowID inWindowID,
                         char inKey,
                         XPLMKeyFlags inFlags,
                         char inVirtualKey,
                         void* inRefcon,
                         int losingFocus) {

    // nothing to do here
}

/*
 *
 *
 */
 #define COMS_UNCHANGED     (0)
 #define COM1_CHANGED       (1)
 #define COM2_CHANGED       (2)
 #define COMM_UNSELECTED    (0)
 #define COMM_SELECTED      (1)
int HandleMouseCallback(XPLMWindowID inWindowID,
                        int x,
                        int y,
                        XPLMMouseStatus inMouse,
                        void* inRefcon) {

    static int com_changed = COMS_UNCHANGED;
    static int MouseDownX;
    static int MouseDownY;

    switch (inMouse) {
    case xplm_MouseDown:
        // if ((x >= gWinPosX+WINDOW_WIDTH-8) &&
        //     (x <= gWinPosX+WINDOW_WIDTH) &&
        //     (y <= gWinPosY) && (y >= gWinPosY-8)) {
        //         windowCloseRequest = 1;
        //     } else {
                MouseDownX = gLastMouseX = x;
                MouseDownY = gLastMouseY = y;
        // }
        break;
    case xplm_MouseDrag:
        // this event fires while xplm_MouseDown
        // and whether the window is being dragged or not
        gWinPosX += (x - gLastMouseX);
        gWinPosY += (y - gLastMouseY);
        XPLMSetWindowGeometry(gWindow,
                              gWinPosX,
                              gWinPosY,
                              gWinPosX+WINDOW_WIDTH,
                              gWinPosY-WINDOW_HEIGHT);
        gLastMouseX = x;
        gLastMouseY = y;
        break;
    case xplm_MouseUp:
        if (MouseDownX == x && MouseDownY == y) {
            int com1 = XPLMGetDatai(audio_selection_com1_dataref);
            int com2 = XPLMGetDatai(audio_selection_com2_dataref);

            if (com1 && com2 && com_changed) {
                switch (com_changed) {
                case COM1_CHANGED:
                    XPLMSetDatai(audio_selection_com1_dataref, COMM_UNSELECTED);
                    break;
                case COM2_CHANGED:
                    XPLMSetDatai(audio_selection_com2_dataref, COMM_UNSELECTED);
                    break;
                default:
                    break;
                }
                com_changed = COMS_UNCHANGED;
            } else if (!com1 && com2) {
                com_changed = COM1_CHANGED;
                XPLMSetDatai(audio_selection_com1_dataref, COMM_SELECTED);
            }  else if (com1 && !com2) {
                com_changed = COM2_CHANGED;
                XPLMSetDatai(audio_selection_com2_dataref, COMM_SELECTED);
            }
        }
        break;
    } // switch (inMouse)

    return PROCESSED_EVENT;
}
<|endoftext|>


<commit_before>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ash/wm/gestures/shelf_gesture_handler.h"

#include "ash/root_window_controller.h"
#include "ash/shelf_types.h"
#include "ash/shell.h"
#include "ash/shell_delegate.h"
#include "ash/system/status_area_widget.h"
#include "ash/wm/gestures/tray_gesture_handler.h"
#include "ash/wm/shelf_layout_manager.h"
#include "ash/wm/window_util.h"
#include "ui/aura/window.h"
#include "ui/compositor/layer.h"
#include "ui/compositor/scoped_layer_animation_settings.h"
#include "ui/gfx/transform.h"
#include "ui/views/widget/widget.h"

namespace {

// A ShelfResetHandler auto-hides the shelf as soon as the user interacts with
// any non-shelf part of the system. The ShelfResetHandler manages its own
// lifetime.
class ShelfResetHandler : public ui::EventHandler,
                          public ash::internal::ShelfLayoutManager::Observer {
 public:
  explicit ShelfResetHandler(ash::internal::ShelfLayoutManager* shelf)
      : shelf_(shelf) {
    shelf_->AddObserver(this);
    ash::Shell::GetInstance()->AddPreTargetHandler(this);
  }

 private:
  virtual ~ShelfResetHandler() {
    ash::Shell::GetInstance()->RemovePreTargetHandler(this);
    shelf_->RemoveObserver(this);
  }

  void ResetShelfState() {
    shelf_->SetAutoHideBehavior(ash::SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
    delete this;
  }

  void DecideShelfVisibility(const gfx::Point& location) {
    // For the rest of the mouse events, ignore if the event happens inside the
    // shelf.
    views::Widget* widget = shelf_->launcher_widget();
    if (widget &&
        widget->GetWindowBoundsInScreen().Contains(location)) {
      return;
    }

    widget = shelf_->status_area_widget();
    if (widget &&
        widget->GetWindowBoundsInScreen().Contains(location)) {
      return;
    }

    ResetShelfState();
  }

  // Overridden from ui::EventHandler:
  virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE {
    ResetShelfState();
  }

  virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE {
    // Ignore all mouse move events.
    if (event->type() == ui::ET_MOUSE_PRESSED ||
        event->type() == ui::ET_MOUSE_RELEASED) {
      DecideShelfVisibility(event->root_location());
    }
  }

  virtual void OnTouchEvent(ui::TouchEvent* event) OVERRIDE {
    DecideShelfVisibility(event->root_location());
  }

  virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE {
    DecideShelfVisibility(event->root_location());
  }

  // Overridden from ash::internal::ShelfLayoutManager::Observer:
  virtual void WillDeleteShelf() OVERRIDE {
    delete this;
  }

  ash::internal::ShelfLayoutManager* shelf_;

  DISALLOW_COPY_AND_ASSIGN(ShelfResetHandler);
};

}  // namespace

namespace ash {
namespace internal {

ShelfGestureHandler::ShelfGestureHandler()
    : drag_in_progress_(false) {
}

ShelfGestureHandler::~ShelfGestureHandler() {
}

bool ShelfGestureHandler::ProcessGestureEvent(const ui::GestureEvent& event) {
  Shell* shell = Shell::GetInstance();
  if (!shell->delegate()->IsUserLoggedIn() ||
      shell->delegate()->IsScreenLocked()) {
    // The gestures are disabled in the lock/login screen.
    return false;
  }

  // The gesture are disabled for fullscreen windows.
  aura::Window* active = wm::GetActiveWindow();
  if (active && wm::IsWindowFullscreen(active))
    return false;

  // TODO(oshima): Find the root window controller from event's location.
  ShelfLayoutManager* shelf = Shell::GetPrimaryRootWindowController()->shelf();
  if (event.type() == ui::ET_GESTURE_SCROLL_BEGIN) {
    drag_in_progress_ = true;
    shelf->StartGestureDrag(event);
    return true;
  }

  if (!drag_in_progress_)
    return false;

  if (event.type() == ui::ET_GESTURE_SCROLL_UPDATE) {
    if (tray_handler_.get()) {
      if (!tray_handler_->UpdateGestureDrag(event))
        tray_handler_.reset();
    } else if (shelf->UpdateGestureDrag(event) ==
        ShelfLayoutManager::DRAG_TRAY) {
      tray_handler_.reset(new TrayGestureHandler());
    }

    return true;
  }

  drag_in_progress_ = false;

  if (event.type() == ui::ET_GESTURE_SCROLL_END ||
      event.type() == ui::ET_SCROLL_FLING_START) {
    if (tray_handler_.get()) {
      tray_handler_->CompleteGestureDrag(event);
      tray_handler_.reset();
    }

    ShelfVisibilityState old_state = shelf->visibility_state();
    shelf->CompleteGestureDrag(event);
    ShelfVisibilityState new_state = shelf->visibility_state();
    if (new_state != old_state && new_state == SHELF_VISIBLE)
      new ShelfResetHandler(shelf);
    return true;
  }

  // Unexpected event. Reset the state and let the event fall through.
  shelf->CancelGestureDrag();
  return false;
}

}  // namespace internal
}  // namespace ash
<commit_msg>ash: Fix hiding the shelf after a gesture-drag to reveal it.<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ash/wm/gestures/shelf_gesture_handler.h"

#include "ash/root_window_controller.h"
#include "ash/shelf_types.h"
#include "ash/shell.h"
#include "ash/shell_delegate.h"
#include "ash/system/status_area_widget.h"
#include "ash/wm/gestures/tray_gesture_handler.h"
#include "ash/wm/shelf_layout_manager.h"
#include "ash/wm/window_util.h"
#include "ui/aura/window.h"
#include "ui/compositor/layer.h"
#include "ui/compositor/scoped_layer_animation_settings.h"
#include "ui/gfx/transform.h"
#include "ui/views/widget/widget.h"

namespace {

// A ShelfResetHandler auto-hides the shelf as soon as the user interacts with
// any non-shelf part of the system. The ShelfResetHandler manages its own
// lifetime.
class ShelfResetHandler : public ui::EventHandler,
                          public ash::internal::ShelfLayoutManager::Observer {
 public:
  explicit ShelfResetHandler(ash::internal::ShelfLayoutManager* shelf)
      : shelf_(shelf) {
    shelf_->AddObserver(this);
    ash::Shell::GetInstance()->AddPreTargetHandler(this);
  }

 private:
  virtual ~ShelfResetHandler() {
    ash::Shell::GetInstance()->RemovePreTargetHandler(this);
    shelf_->RemoveObserver(this);
  }

  void ResetShelfState() {
    shelf_->SetAutoHideBehavior(ash::SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
    delete this;
  }

  bool ShelfIsEventTarget(const ui::Event& event) {
    aura::Window* target = static_cast<aura::Window*>(event.target());
    views::Widget* widget = shelf_->launcher_widget();
    if (widget && widget->GetNativeWindow() == target)
      return true;
    widget = shelf_->status_area_widget();
    if (widget && widget->GetNativeWindow() == target)
      return true;
    return false;
  }

  void DecideShelfVisibility(const gfx::Point& location) {
    // For the rest of the mouse events, ignore if the event happens inside the
    // shelf.
    views::Widget* widget = shelf_->launcher_widget();
    if (widget &&
        widget->GetWindowBoundsInScreen().Contains(location)) {
      return;
    }

    widget = shelf_->status_area_widget();
    if (widget &&
        widget->GetWindowBoundsInScreen().Contains(location)) {
      return;
    }

    ResetShelfState();
  }

  // Overridden from ui::EventHandler:
  virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE {
    if (!ShelfIsEventTarget(*event))
      ResetShelfState();
  }

  virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE {
    // Ignore all mouse move events.
    if (event->type() == ui::ET_MOUSE_PRESSED ||
        event->type() == ui::ET_MOUSE_RELEASED) {
      DecideShelfVisibility(event->root_location());
    }
  }

  virtual void OnTouchEvent(ui::TouchEvent* event) OVERRIDE {
    if (!ShelfIsEventTarget(*event))
      DecideShelfVisibility(event->root_location());
  }

  virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE {
    if (!ShelfIsEventTarget(*event))
      DecideShelfVisibility(event->root_location());
  }

  // Overridden from ash::internal::ShelfLayoutManager::Observer:
  virtual void WillDeleteShelf() OVERRIDE {
    delete this;
  }

  ash::internal::ShelfLayoutManager* shelf_;

  DISALLOW_COPY_AND_ASSIGN(ShelfResetHandler);
};

}  // namespace

namespace ash {
namespace internal {

ShelfGestureHandler::ShelfGestureHandler()
    : drag_in_progress_(false) {
}

ShelfGestureHandler::~ShelfGestureHandler() {
}

bool ShelfGestureHandler::ProcessGestureEvent(const ui::GestureEvent& event) {
  Shell* shell = Shell::GetInstance();
  if (!shell->delegate()->IsUserLoggedIn() ||
      shell->delegate()->IsScreenLocked()) {
    // The gestures are disabled in the lock/login screen.
    return false;
  }

  // The gesture are disabled for fullscreen windows.
  aura::Window* active = wm::GetActiveWindow();
  if (active && wm::IsWindowFullscreen(active))
    return false;

  // TODO(oshima): Find the root window controller from event's location.
  ShelfLayoutManager* shelf = Shell::GetPrimaryRootWindowController()->shelf();
  if (event.type() == ui::ET_GESTURE_SCROLL_BEGIN) {
    drag_in_progress_ = true;
    shelf->StartGestureDrag(event);
    return true;
  }

  if (!drag_in_progress_)
    return false;

  if (event.type() == ui::ET_GESTURE_SCROLL_UPDATE) {
    if (tray_handler_.get()) {
      if (!tray_handler_->UpdateGestureDrag(event))
        tray_handler_.reset();
    } else if (shelf->UpdateGestureDrag(event) ==
        ShelfLayoutManager::DRAG_TRAY) {
      tray_handler_.reset(new TrayGestureHandler());
    }

    return true;
  }

  drag_in_progress_ = false;

  if (event.type() == ui::ET_GESTURE_SCROLL_END ||
      event.type() == ui::ET_SCROLL_FLING_START) {
    if (tray_handler_.get()) {
      tray_handler_->CompleteGestureDrag(event);
      tray_handler_.reset();
    }

    ShelfVisibilityState old_state = shelf->visibility_state();
    shelf->CompleteGestureDrag(event);
    ShelfVisibilityState new_state = shelf->visibility_state();
    if (new_state != old_state && new_state == SHELF_VISIBLE)
      new ShelfResetHandler(shelf);
    return true;
  }

  // Unexpected event. Reset the state and let the event fall through.
  shelf->CancelGestureDrag();
  return false;
}

}  // namespace internal
}  // namespace ash
<|endoftext|>


<commit_before>/*
 lib/src/CurlReceiver.hpp

Copyright (c) 2015, Elecard Multimedia School
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.

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 FILES                                                   *
*******************************************************************/
#include "CurlReceiver.hpp"

/******************************************************************
* STATIC DATA                                                     *
*******************************************************************/
static IHTTPReceiver *l_inst = nullptr; //TODO: move this somewhere

/******************************************************************
* EXPORTED TYPEDEFS                            [for headers only] *
*******************************************************************/
IHTTPReceiver *IHTTPReceiver::Instance(void)
{
	if(l_inst == nullptr) {
		//only curl support now
		l_inst = new CurlReceiver();
	}
	return l_inst;
}

bool IHTTPReceiver::SetInstance(IHTTPReceiver *inst)
{
	if(l_inst == nullptr) {
		delete l_inst;
	}
	l_inst = inst;
}

CurlReceiver::CurlReceiver()
{
	m_curl = NULL;
	m_callback = NULL;
}

CurlReceiver::~CurlReceiver()
{
	Release();
}

bool CurlReceiver::Init()
{
	bool initialized = false;
	m_curl = curl_easy_init();

	if (m_curl)
		initialized = true;

	return initialized;
}

bool CurlReceiver::Release()
{
	curl_easy_cleanup(m_curl);
	return true;
}

bool CurlReceiver::Get(std::string url, IHTTPCallback *callback)
{
	bool res = false;
	m_callback = callback;
	if (m_curl){
		FILE *file;
		CURLcode performed;

		char out_file_name[FILENAME_MAX] = "DownloadFile.mpd";
		file = fopen(out_file_name, "wb");
		curl_easy_setopt(m_curl, CURLOPT_URL, &url);
		curl_easy_setopt(m_curl, CURLOPT_WRITEFUNCTION, NULL); //TODO: add callback function.
								// It should return number of bytes;
								// Now it uses function by default;
		curl_easy_setopt(m_curl, CURLOPT_WRITEDATA, file);

		if (curl_easy_perform(m_curl) == 0) {
			res = true;
		}
		fclose(file);
	}

	return res;
}

<commit_msg>[*] fixed Get method<commit_after>/*
 lib/src/CurlReceiver.hpp

Copyright (c) 2015, Elecard Multimedia School
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.

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 FILES                                                   *
*******************************************************************/
#include "CurlReceiver.hpp"

/******************************************************************
* STATIC DATA                                                     *
*******************************************************************/
static IHTTPReceiver *l_inst = nullptr; //TODO: move this somewhere

/******************************************************************
* EXPORTED TYPEDEFS                            [for headers only] *
*******************************************************************/
IHTTPReceiver *IHTTPReceiver::Instance(void)
{
	if(l_inst == nullptr) {
		//only curl support now
		l_inst = new CurlReceiver();
	}
	return l_inst;
}

bool IHTTPReceiver::SetInstance(IHTTPReceiver *inst)
{
	if(l_inst == nullptr) {
		delete l_inst;
	}
	l_inst = inst;
}

CurlReceiver::CurlReceiver()
{
	m_curl = NULL;
	m_callback = NULL;
}

CurlReceiver::~CurlReceiver()
{
	Release();
}

bool CurlReceiver::Init()
{
	bool initialized = false;
	m_curl = curl_easy_init();

	if (m_curl)
		initialized = true;

	return initialized;
}

bool CurlReceiver::Release()
{
	curl_easy_cleanup(m_curl);
	return true;
}

bool CurlReceiver::Get(std::string url, IHTTPCallback *callback)
{
	bool res = false;
	m_callback = callback;
	if (m_curl){
		FILE *file;
		CURLcode performed;

		char* m_url = new char[url.size() + 1];
		std::copy(url.begin(), url.end(), m_url);
		m_url[url.size()] = '\0';

		char out_file_name[FILENAME_MAX] = "DownloadFile.mpd";
		file = fopen(out_file_name, "wb");
		curl_easy_setopt(m_curl, CURLOPT_URL, m_url);
		curl_easy_setopt(m_curl, CURLOPT_WRITEFUNCTION, NULL); //TODO: add callback function.
								// It should return number of bytes;
								// Now it uses function by default;
		curl_easy_setopt(m_curl, CURLOPT_WRITEDATA, file);

		if (curl_easy_perform(m_curl) == 0) {
			res = true;
		}
		delete[] m_url;
		fclose(file);
	}

	return res;
}

<|endoftext|>


<commit_before>#include <cstdio>

using namespace std;

int main() {
    int c, n, i, sum;

    scanf("%d", &c);

    while (c--) {
        sum = 0;
        scanf("%d", &n);

        for (i = 0; i < n; i++) {
            if (i % 2 == 0) sum++;
            else sum--;
        }

        printf("%d\n", sum);
    }
    return 0;
}
<commit_msg>Refatora 1866.<commit_after>#include <cstdio>

using namespace std;

int main() {
    int c, n;

    scanf("%d", &c);

    while (c--) {
        scanf("%d", &n);

        if (n % 2 == 0) puts("0");
        else puts("1");
    }
    return 0;
}
<|endoftext|>