<commit_before>// Copyright (c) 2010 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 "chrome/browser/hung_renderer_dialog.h"

#include <gtk/gtk.h>

#include "app/l10n_util.h"
#include "app/resource_bundle.h"
#include "base/process_util.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/browser_list.h"
#include "chrome/browser/gtk/gtk_util.h"
#include "chrome/browser/renderer_host/render_process_host.h"
#include "chrome/browser/renderer_host/render_view_host.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/common/logging_chrome.h"
#include "chrome/common/result_codes.h"
#include "gfx/gtk_util.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"

namespace {

// A wrapper class that represents the Gtk dialog.
class HungRendererDialogGtk {
 public:
  HungRendererDialogGtk();
  void ShowForTabContents(TabContents* hung_contents);
  void EndForTabContents(TabContents* hung_contents);

 private:
  // The GtkTreeView column ids.
  enum {
    COL_FAVICON,
    COL_TITLE,
    COL_COUNT,
  };

  // Create the gtk dialog and add the widgets.
  void Init();

  static void OnDialogResponseThunk(GtkDialog* dialog, gint response_id,
                                    HungRendererDialogGtk* dialog_gtk) {
    dialog_gtk->OnDialogResponse(response_id);
  }
  void OnDialogResponse(gint response_id);

  GtkDialog* dialog_;
  GtkListStore* model_;
  TabContents* contents_;

  DISALLOW_COPY_AND_ASSIGN(HungRendererDialogGtk);
};

// We only support showing one of these at a time per app.
HungRendererDialogGtk* g_instance = NULL;

// The response ID for the "Kill pages" button.  Anything positive should be
// fine (the built in GtkResponseTypes are negative numbers).
const int kKillPagesButtonResponse = 1;

HungRendererDialogGtk::HungRendererDialogGtk()
    : dialog_(NULL), model_(NULL), contents_(NULL) {
  Init();
}

void HungRendererDialogGtk::Init() {
  dialog_ = GTK_DIALOG(gtk_dialog_new_with_buttons(
      l10n_util::GetStringUTF8(IDS_BROWSER_HANGMONITOR_RENDERER_TITLE).c_str(),
      NULL,  // No parent because tabs can span multiple windows.
      GTK_DIALOG_NO_SEPARATOR,
      l10n_util::GetStringUTF8(IDS_BROWSER_HANGMONITOR_RENDERER_END).c_str(),
      kKillPagesButtonResponse,
      l10n_util::GetStringUTF8(IDS_BROWSER_HANGMONITOR_RENDERER_WAIT).c_str(),
      GTK_RESPONSE_OK,
      NULL));
  gtk_dialog_set_default_response(dialog_, GTK_RESPONSE_OK);
  g_signal_connect(dialog_, "response", G_CALLBACK(OnDialogResponseThunk),
                   this);

  // We have an hbox with the frozen icon on the left.  On the right,
  // we have a vbox with the unresponsive text on top and a table of
  // tabs on bottom.
  // ·-----------------------------------·
  // |·---------------------------------·|
  // ||·----·|·------------------------·||
  // |||icon|||                        |||
  // ||·----·|| The folowing page(s).. |||
  // ||      ||                        |||
  // ||      ||------------------------|||
  // ||      || table of tabs          |||
  // ||      |·------------------------·||
  // |·---------------------------------·|
  // |                                   |
  // |         kill button    wait button|
  // ·-----------------------------------·
  GtkWidget* contents_vbox = dialog_->vbox;
  gtk_box_set_spacing(GTK_BOX(contents_vbox), gtk_util::kContentAreaSpacing);

  GtkWidget* hbox = gtk_hbox_new(FALSE, 12);
  gtk_box_pack_start(GTK_BOX(contents_vbox), hbox, TRUE, TRUE, 0);

  // Wrap the icon in a vbox so it stays top aligned.
  GtkWidget* icon_vbox = gtk_vbox_new(FALSE, 0);
  gtk_box_pack_start(GTK_BOX(hbox), icon_vbox, FALSE, FALSE, 0);
  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
  GdkPixbuf* icon_pixbuf = rb.GetPixbufNamed(IDR_FROZEN_TAB_ICON);
  GtkWidget* icon = gtk_image_new_from_pixbuf(icon_pixbuf);
  gtk_box_pack_start(GTK_BOX(icon_vbox), icon, FALSE, FALSE, 0);

  GtkWidget* vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
  gtk_box_pack_start(GTK_BOX(hbox), vbox, TRUE, TRUE, 0);

  GtkWidget* text = gtk_label_new(
      l10n_util::GetStringUTF8(IDS_BROWSER_HANGMONITOR_RENDERER).c_str());
  gtk_label_set_line_wrap(GTK_LABEL(text), TRUE);
  gtk_box_pack_start(GTK_BOX(vbox), text, FALSE, FALSE, 0);

  GtkWidget* scroll_list = gtk_scrolled_window_new(NULL, NULL);
  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll_list),
      GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
  gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scroll_list),
                                      GTK_SHADOW_ETCHED_IN);
  gtk_box_pack_start(GTK_BOX(vbox), scroll_list, TRUE, TRUE, 0);

  // The list of hung tabs is GtkTreeView with a GtkListStore as the model.
  model_ = gtk_list_store_new(COL_COUNT, GDK_TYPE_PIXBUF, G_TYPE_STRING);
  GtkWidget* tree_view = gtk_tree_view_new_with_model(
      GTK_TREE_MODEL(model_));
  g_object_unref(model_);
  gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(tree_view), FALSE);
  GtkTreeViewColumn* column = gtk_tree_view_column_new();
  GtkCellRenderer* renderer = gtk_cell_renderer_pixbuf_new();
  gtk_tree_view_column_pack_start(column, renderer, FALSE);
  gtk_tree_view_column_add_attribute(column, renderer, "pixbuf", COL_FAVICON);
  renderer = gtk_cell_renderer_text_new();
  gtk_tree_view_column_pack_start(column, renderer, TRUE);
  gtk_tree_view_column_add_attribute(column, renderer, "text", COL_TITLE);

  gtk_tree_view_append_column(GTK_TREE_VIEW(tree_view), column);
  gtk_container_add(GTK_CONTAINER(scroll_list), tree_view);
}

void HungRendererDialogGtk::ShowForTabContents(TabContents* hung_contents) {
  DCHECK(hung_contents && dialog_);
  contents_ = hung_contents;
  gtk_list_store_clear(model_);

  GtkTreeIter tree_iter;
  for (TabContentsIterator it; !it.done(); ++it) {
    if (it->GetRenderProcessHost() == hung_contents->GetRenderProcessHost()) {
      gtk_list_store_append(model_, &tree_iter);
      std::string title = UTF16ToUTF8(it->GetTitle());
      if (title.empty())
        title = UTF16ToUTF8(TabContents::GetDefaultTitle());
      SkBitmap favicon = it->GetFavIcon();

      GdkPixbuf* pixbuf = NULL;
      if (favicon.width() > 0)
        pixbuf = gfx::GdkPixbufFromSkBitmap(&favicon);
      gtk_list_store_set(model_, &tree_iter,
          COL_FAVICON, pixbuf,
          COL_TITLE, title.c_str(),
          -1);
      if (pixbuf)
        g_object_unref(pixbuf);
    }
  }
  gtk_util::ShowDialog(GTK_WIDGET(dialog_));
}

void HungRendererDialogGtk::EndForTabContents(TabContents* contents) {
  DCHECK(contents);
  if (contents_ && contents_->GetRenderProcessHost() ==
      contents->GetRenderProcessHost()) {
    gtk_widget_hide(GTK_WIDGET(dialog_));
    // Since we're closing, we no longer need this TabContents.
    contents_ = NULL;
  }
}

// When the user clicks a button on the dialog or closes the dialog, this
// callback is called.
void HungRendererDialogGtk::OnDialogResponse(gint response_id) {
  DCHECK(g_instance == this);
  switch (response_id) {
    case kKillPagesButtonResponse:
      // Kill the process.
      base::KillProcess(contents_->GetRenderProcessHost()->GetHandle(),
                        ResultCodes::HUNG, false);
      break;

    case GTK_RESPONSE_OK:
    case GTK_RESPONSE_DELETE_EVENT:
      // Start waiting again for responsiveness.
      if (contents_ && contents_->render_view_host())
        contents_->render_view_host()->RestartHangMonitorTimeout();
      break;
    default:
      NOTREACHED();
  }

  gtk_widget_destroy(GTK_WIDGET(dialog_));
  delete g_instance;
  g_instance = NULL;
}

}  // namespace

namespace hung_renderer_dialog {

void ShowForTabContents(TabContents* contents) {
  if (!logging::DialogsAreSuppressed()) {
    if (!g_instance)
      g_instance = new HungRendererDialogGtk();
    g_instance->ShowForTabContents(contents);
  }
}

// static
void HideForTabContents(TabContents* contents) {
  if (!logging::DialogsAreSuppressed() && g_instance)
    g_instance->EndForTabContents(contents);
}

}  // namespace hung_renderer_dialog
<commit_msg>Fix crash in HungRendererDialogGtk when contents_ == NULL.<commit_after>// Copyright (c) 2010 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 "chrome/browser/hung_renderer_dialog.h"

#include <gtk/gtk.h>

#include "app/l10n_util.h"
#include "app/resource_bundle.h"
#include "base/process_util.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/browser_list.h"
#include "chrome/browser/gtk/gtk_util.h"
#include "chrome/browser/renderer_host/render_process_host.h"
#include "chrome/browser/renderer_host/render_view_host.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/common/logging_chrome.h"
#include "chrome/common/result_codes.h"
#include "gfx/gtk_util.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"

namespace {

// A wrapper class that represents the Gtk dialog.
class HungRendererDialogGtk {
 public:
  HungRendererDialogGtk();
  void ShowForTabContents(TabContents* hung_contents);
  void EndForTabContents(TabContents* hung_contents);

 private:
  // The GtkTreeView column ids.
  enum {
    COL_FAVICON,
    COL_TITLE,
    COL_COUNT,
  };

  // Create the gtk dialog and add the widgets.
  void Init();

  static void OnDialogResponseThunk(GtkDialog* dialog, gint response_id,
                                    HungRendererDialogGtk* dialog_gtk) {
    dialog_gtk->OnDialogResponse(response_id);
  }
  void OnDialogResponse(gint response_id);

  GtkDialog* dialog_;
  GtkListStore* model_;
  TabContents* contents_;

  DISALLOW_COPY_AND_ASSIGN(HungRendererDialogGtk);
};

// We only support showing one of these at a time per app.
HungRendererDialogGtk* g_instance = NULL;

// The response ID for the "Kill pages" button.  Anything positive should be
// fine (the built in GtkResponseTypes are negative numbers).
const int kKillPagesButtonResponse = 1;

HungRendererDialogGtk::HungRendererDialogGtk()
    : dialog_(NULL), model_(NULL), contents_(NULL) {
  Init();
}

void HungRendererDialogGtk::Init() {
  dialog_ = GTK_DIALOG(gtk_dialog_new_with_buttons(
      l10n_util::GetStringUTF8(IDS_BROWSER_HANGMONITOR_RENDERER_TITLE).c_str(),
      NULL,  // No parent because tabs can span multiple windows.
      GTK_DIALOG_NO_SEPARATOR,
      l10n_util::GetStringUTF8(IDS_BROWSER_HANGMONITOR_RENDERER_END).c_str(),
      kKillPagesButtonResponse,
      l10n_util::GetStringUTF8(IDS_BROWSER_HANGMONITOR_RENDERER_WAIT).c_str(),
      GTK_RESPONSE_OK,
      NULL));
  gtk_dialog_set_default_response(dialog_, GTK_RESPONSE_OK);
  g_signal_connect(dialog_, "response", G_CALLBACK(OnDialogResponseThunk),
                   this);

  // We have an hbox with the frozen icon on the left.  On the right,
  // we have a vbox with the unresponsive text on top and a table of
  // tabs on bottom.
  // ·-----------------------------------·
  // |·---------------------------------·|
  // ||·----·|·------------------------·||
  // |||icon|||                        |||
  // ||·----·|| The folowing page(s).. |||
  // ||      ||                        |||
  // ||      ||------------------------|||
  // ||      || table of tabs          |||
  // ||      |·------------------------·||
  // |·---------------------------------·|
  // |                                   |
  // |         kill button    wait button|
  // ·-----------------------------------·
  GtkWidget* contents_vbox = dialog_->vbox;
  gtk_box_set_spacing(GTK_BOX(contents_vbox), gtk_util::kContentAreaSpacing);

  GtkWidget* hbox = gtk_hbox_new(FALSE, 12);
  gtk_box_pack_start(GTK_BOX(contents_vbox), hbox, TRUE, TRUE, 0);

  // Wrap the icon in a vbox so it stays top aligned.
  GtkWidget* icon_vbox = gtk_vbox_new(FALSE, 0);
  gtk_box_pack_start(GTK_BOX(hbox), icon_vbox, FALSE, FALSE, 0);
  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
  GdkPixbuf* icon_pixbuf = rb.GetPixbufNamed(IDR_FROZEN_TAB_ICON);
  GtkWidget* icon = gtk_image_new_from_pixbuf(icon_pixbuf);
  gtk_box_pack_start(GTK_BOX(icon_vbox), icon, FALSE, FALSE, 0);

  GtkWidget* vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing);
  gtk_box_pack_start(GTK_BOX(hbox), vbox, TRUE, TRUE, 0);

  GtkWidget* text = gtk_label_new(
      l10n_util::GetStringUTF8(IDS_BROWSER_HANGMONITOR_RENDERER).c_str());
  gtk_label_set_line_wrap(GTK_LABEL(text), TRUE);
  gtk_box_pack_start(GTK_BOX(vbox), text, FALSE, FALSE, 0);

  GtkWidget* scroll_list = gtk_scrolled_window_new(NULL, NULL);
  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll_list),
      GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
  gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scroll_list),
                                      GTK_SHADOW_ETCHED_IN);
  gtk_box_pack_start(GTK_BOX(vbox), scroll_list, TRUE, TRUE, 0);

  // The list of hung tabs is GtkTreeView with a GtkListStore as the model.
  model_ = gtk_list_store_new(COL_COUNT, GDK_TYPE_PIXBUF, G_TYPE_STRING);
  GtkWidget* tree_view = gtk_tree_view_new_with_model(
      GTK_TREE_MODEL(model_));
  g_object_unref(model_);
  gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(tree_view), FALSE);
  GtkTreeViewColumn* column = gtk_tree_view_column_new();
  GtkCellRenderer* renderer = gtk_cell_renderer_pixbuf_new();
  gtk_tree_view_column_pack_start(column, renderer, FALSE);
  gtk_tree_view_column_add_attribute(column, renderer, "pixbuf", COL_FAVICON);
  renderer = gtk_cell_renderer_text_new();
  gtk_tree_view_column_pack_start(column, renderer, TRUE);
  gtk_tree_view_column_add_attribute(column, renderer, "text", COL_TITLE);

  gtk_tree_view_append_column(GTK_TREE_VIEW(tree_view), column);
  gtk_container_add(GTK_CONTAINER(scroll_list), tree_view);
}

void HungRendererDialogGtk::ShowForTabContents(TabContents* hung_contents) {
  DCHECK(hung_contents && dialog_);
  contents_ = hung_contents;
  gtk_list_store_clear(model_);

  GtkTreeIter tree_iter;
  for (TabContentsIterator it; !it.done(); ++it) {
    if (it->GetRenderProcessHost() == hung_contents->GetRenderProcessHost()) {
      gtk_list_store_append(model_, &tree_iter);
      std::string title = UTF16ToUTF8(it->GetTitle());
      if (title.empty())
        title = UTF16ToUTF8(TabContents::GetDefaultTitle());
      SkBitmap favicon = it->GetFavIcon();

      GdkPixbuf* pixbuf = NULL;
      if (favicon.width() > 0)
        pixbuf = gfx::GdkPixbufFromSkBitmap(&favicon);
      gtk_list_store_set(model_, &tree_iter,
          COL_FAVICON, pixbuf,
          COL_TITLE, title.c_str(),
          -1);
      if (pixbuf)
        g_object_unref(pixbuf);
    }
  }
  gtk_util::ShowDialog(GTK_WIDGET(dialog_));
}

void HungRendererDialogGtk::EndForTabContents(TabContents* contents) {
  DCHECK(contents);
  if (contents_ && contents_->GetRenderProcessHost() ==
      contents->GetRenderProcessHost()) {
    gtk_widget_hide(GTK_WIDGET(dialog_));
    // Since we're closing, we no longer need this TabContents.
    contents_ = NULL;
  }
}

// When the user clicks a button on the dialog or closes the dialog, this
// callback is called.
void HungRendererDialogGtk::OnDialogResponse(gint response_id) {
  DCHECK(g_instance == this);
  switch (response_id) {
    case kKillPagesButtonResponse:
      // Kill the process.
      if (contents_ && contents_->GetRenderProcessHost()) {
        base::KillProcess(contents_->GetRenderProcessHost()->GetHandle(),
                          ResultCodes::HUNG, false);
      }
      break;

    case GTK_RESPONSE_OK:
    case GTK_RESPONSE_DELETE_EVENT:
      // Start waiting again for responsiveness.
      if (contents_ && contents_->render_view_host())
        contents_->render_view_host()->RestartHangMonitorTimeout();
      break;
    default:
      NOTREACHED();
  }

  gtk_widget_destroy(GTK_WIDGET(dialog_));
  delete g_instance;
  g_instance = NULL;
}

}  // namespace

namespace hung_renderer_dialog {

void ShowForTabContents(TabContents* contents) {
  if (!logging::DialogsAreSuppressed()) {
    if (!g_instance)
      g_instance = new HungRendererDialogGtk();
    g_instance->ShowForTabContents(contents);
  }
}

// static
void HideForTabContents(TabContents* contents) {
  if (!logging::DialogsAreSuppressed() && g_instance)
    g_instance->EndForTabContents(contents);
}

}  // namespace hung_renderer_dialog
<|endoftext|>


<commit_before>/***************************************************************************
 *   Copyright (C) 2006-2008 by Rajko Albrecht                             *
 *   ral@alwins-world.de                                                   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.         *
 ***************************************************************************/

#include "svnqt/stringarray.hpp"
#include "svnqt/pool.hpp"

#include <svn_types.h>
// apr api
#include <apr_pools.h>
#include <apr_strings.h>

/*!
    \fn svn::StringArray::StringArray()
 */
 svn::StringArray::StringArray()
    :m_content()
{
    setNull(true);
}

/*!
    \fn svn::StringArray::StringArray(const QStringList&)
 */
svn::StringArray::StringArray(const QStringList&aList)
    :m_content(aList)
{
    setNull(false);
}

/*!
    \fn svn::StringArray::StringArray(const apr_array_header_t * apr_targets)
 */
svn::StringArray::StringArray(const apr_array_header_t * apr_targets)
    :m_content()
{
    int i;
    for (i = 0; i < apr_targets->nelts; i++)
    {
        const char ** target =
                &APR_ARRAY_IDX (apr_targets, i, const char *);

        m_content.push_back (QString::FROMUTF8(*target));
    }
}

/*!
    \fn svn::StringArray::size()const
 */
size_t svn::StringArray::size()const
{
    if (isNull()) {
        return 0;
    }
    return m_content.size ();
}

/*!
    \fn svn::StringArray::operator[](size_t which)
 */
const QString& svn::StringArray::operator[](size_t which)
{
    return m_content[which];
}

/*!
    \fn svn::StringArray::array (const Pool & pool) const
 */
apr_array_header_t * svn::StringArray::array (const Pool & pool) const
{
    if (isNull()) {
        return 0;
    }
    QStringList::const_iterator it;

    apr_pool_t *apr_pool = pool.pool ();
    apr_array_header_t *apr_targets =
            apr_array_make (apr_pool,m_content.size(),sizeof (const char *));

    for (it = m_content.begin (); it != m_content.end (); it++)
    {
        QByteArray s = (*it).TOUTF8();
        char * t2 = apr_pstrndup (apr_pool,s,s.size());

        (*((const char **) apr_array_push (apr_targets))) = t2;
    }
    return apr_targets;
}

bool svn::StringArray::isNull()const
{
    return m_isNull;
}

void svn::StringArray::setNull(bool _n)
{
    if (_n) {
        m_content.clear();
    }
    m_isNull = _n;
}
<commit_msg>- fix a crash on svn::diff. svn_client_diff4 doesn't accept a 0 as *diff_options<commit_after>/***************************************************************************
 *   Copyright (C) 2006-2008 by Rajko Albrecht                             *
 *   ral@alwins-world.de                                                   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.         *
 ***************************************************************************/

#include "svnqt/stringarray.hpp"
#include "svnqt/pool.hpp"

#include <svn_types.h>
// apr api
#include <apr_pools.h>
#include <apr_strings.h>

/*!
    \fn svn::StringArray::StringArray()
 */
 svn::StringArray::StringArray()
    :m_content()
{
    setNull(true);
}

/*!
    \fn svn::StringArray::StringArray(const QStringList&)
 */
svn::StringArray::StringArray(const QStringList&aList)
    :m_content(aList)
{
    setNull(false);
}

/*!
    \fn svn::StringArray::StringArray(const apr_array_header_t * apr_targets)
 */
svn::StringArray::StringArray(const apr_array_header_t * apr_targets)
    :m_content()
{
    int i;
    for (i = 0; i < apr_targets->nelts; i++)
    {
        const char ** target =
                &APR_ARRAY_IDX (apr_targets, i, const char *);

        m_content.push_back (QString::FROMUTF8(*target));
    }
}

/*!
    \fn svn::StringArray::size()const
 */
size_t svn::StringArray::size()const
{
    if (isNull()) {
        return 0;
    }
    return m_content.size ();
}

/*!
    \fn svn::StringArray::operator[](size_t which)
 */
const QString& svn::StringArray::operator[](size_t which)
{
    return m_content[which];
}

/*!
    \fn svn::StringArray::array (const Pool & pool) const
 */
apr_array_header_t * svn::StringArray::array (const Pool & pool) const
{
    apr_pool_t *apr_pool = pool.pool();
    apr_array_header_t *apr_targets;
    if (isNull()) {
        apr_targets = apr_array_make(apr_pool, 0, 0);
    } else {
        QStringList::const_iterator it;

        apr_targets =
                apr_array_make (apr_pool,m_content.size(),sizeof (const char *));

        for (it = m_content.begin (); it != m_content.end (); it++)
        {
            QByteArray s = (*it).TOUTF8();
            char * t2 = apr_pstrndup (apr_pool,s,s.size());

            (*((const char **) apr_array_push (apr_targets))) = t2;
        }
    }
    return apr_targets;
}

bool svn::StringArray::isNull()const
{
    return m_isNull;
}

void svn::StringArray::setNull(bool _n)
{
    if (_n) {
        m_content.clear();
    }
    m_isNull = _n;
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2013 Sacha Refshauge
 *
 */
// Blackberry implementation of the framework.

#include <pwd.h>
#include <unistd.h>
#include <string>

#include <bps/locale.h> // Get locale
#include "BlackberryMain.h"
#include "Core/Config.h"
#include "base/NKCodeFromBlackberry.h"

// Simple implementations of System functions

std::string System_GetProperty(SystemProperty prop) {
	switch (prop) {
	case SYSPROP_NAME: {
		std::string name = "Blackberry10:";
		return name + ((pixel_xres != pixel_yres) ? "Touch" : "QWERTY");
	}
	case SYSPROP_LANGREGION: {
		char *locale = 0;
		locale_get_locale(&locale);
		return std::string(locale);
	}
	default:
		return "";
	}
}

void SystemToast(const char *text) {
	dialog_instance_t dialog = 0;
	dialog_create_toast(&dialog);
	dialog_set_toast_message_text(dialog, text);
	dialog_set_toast_position(dialog, DIALOG_POSITION_TOP_CENTER);
	dialog_show(dialog);
}

void ShowAd(int x, int y, bool center_x) {
}

void ShowKeyboard() {
	virtualkeyboard_show();
}

void Vibrate(int length_ms) {
	// Vibration: intensity strength(1-100), duration ms(0-5000)
	// Intensity: LOW = 1, MEDIUM = 10, HIGH = 100
	switch (length_ms) {
	case -1: // Keyboard Tap
		vibration_request(VIBRATION_INTENSITY_LOW, 50);
		break;
	case -2: // Virtual Key
		vibration_request(VIBRATION_INTENSITY_LOW, 25);
		break;
	case -3: // Long Press
		vibration_request(VIBRATION_INTENSITY_LOW, 50);
		break;
	default:
		vibration_request(VIBRATION_INTENSITY_LOW, length_ms);
		break;
	}
}

void LaunchBrowser(const char *url)
{
	char* error;
	navigator_invoke(url, &error);
}

void LaunchMarket(const char *url)
{
	char* error;
	navigator_invoke(url, &error);
}

void LaunchEmail(const char *email_address)
{
	char* error;
	navigator_invoke((std::string("mailto:") + email_address).c_str(), &error);
}

InputState input_state;

void BlackberryMain::handleInput(screen_event_t screen_event)
{
	TouchInput input;
	KeyInput key;
	int val, buttons, pointerId;
	int pair[2];
	screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_TYPE, &val);
	screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_SOURCE_POSITION, pair);
	screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_TOUCH_ID, &pointerId);

	input_state.mouse_valid = true;
	switch(val)
	{
	// Touchscreen
	case SCREEN_EVENT_MTOUCH_TOUCH:
	case SCREEN_EVENT_MTOUCH_RELEASE: 	// Up, down
		input_state.pointer_down[pointerId] = (val == SCREEN_EVENT_MTOUCH_TOUCH);
		input_state.pointer_x[pointerId] = pair[0] * g_dpi_scale;
		input_state.pointer_y[pointerId] = pair[1] * g_dpi_scale;

		input.x = pair[0] * g_dpi_scale;
		input.y = pair[1] * g_dpi_scale;
		input.flags = (val == SCREEN_EVENT_MTOUCH_TOUCH) ? TOUCH_DOWN : TOUCH_UP;
		input.id = pointerId;
		NativeTouch(input);
		break;
	case SCREEN_EVENT_MTOUCH_MOVE:
		input_state.pointer_x[pointerId] = pair[0] * g_dpi_scale;
		input_state.pointer_y[pointerId] = pair[1] * g_dpi_scale;

		input.x = pair[0] * g_dpi_scale;
		input.y = pair[1] * g_dpi_scale;
		input.flags = TOUCH_MOVE;
		input.id = pointerId;
		NativeTouch(input);
		break;
	// Mouse, Simulator
    case SCREEN_EVENT_POINTER:
		screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_BUTTONS,
			&buttons);
		if (buttons == SCREEN_LEFT_MOUSE_BUTTON) { 			// Down
			input_state.pointer_x[pointerId] = pair[0] * g_dpi_scale;
			input_state.pointer_y[pointerId] = pair[1] * g_dpi_scale;
			input_state.pointer_down[pointerId] = true;

			input.x = pair[0] * g_dpi_scale;
			input.y = pair[1] * g_dpi_scale;
			input.flags = TOUCH_DOWN;
			input.id = pointerId;
			NativeTouch(input);
		} else if (input_state.pointer_down[pointerId]) {	// Up
			input_state.pointer_x[pointerId] = pair[0] * g_dpi_scale;
			input_state.pointer_y[pointerId] = pair[1] * g_dpi_scale;
			input_state.pointer_down[pointerId] = false;

			input.x = pair[0] * g_dpi_scale;
			input.y = pair[1] * g_dpi_scale;
			input.flags = TOUCH_UP;
			input.id = pointerId;
			NativeTouch(input);
		}
		break;
	// Keyboard
	case SCREEN_EVENT_KEYBOARD:
		int flags, value;
		screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_KEY_FLAGS, &flags);
		screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_KEY_SYM, &value);
		NativeKey(KeyInput(DEVICE_ID_KEYBOARD, KeyMapRawBlackberrytoNative.find(value)->second, (flags & KEY_DOWN) ? KEY_DOWN : KEY_UP));
		break;
	// Gamepad
	case SCREEN_EVENT_GAMEPAD:
	case SCREEN_EVENT_JOYSTICK:
		int analog0[3];
		screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_BUTTONS, &buttons);
		for (int i = 0; i < 32; i++) {
			int mask = 1 << i;
			if ((old_buttons & mask) != (buttons & mask))
				NativeKey(KeyInput(DEVICE_ID_PAD_0, KeyMapPadBlackberrytoNative.find(mask)->second, (buttons & mask) ? KEY_DOWN : KEY_UP));
		}
		if (!screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_ANALOG0, analog0)) {
			for (int i = 0; i < 2; i++) {
				AxisInput axis;
				axis.axisId = JOYSTICK_AXIS_X + i;
				// 1.2 to try to approximate the PSP's clamped rectangular range.
				axis.value = 1.2 * analog0[i] / 128.0f;
				if (axis.value > 1.0f) axis.value = 1.0f;
				if (axis.value < -1.0f) axis.value = -1.0f;
				axis.deviceId = DEVICE_ID_PAD_0;
				axis.flags = 0;
				NativeAxis(axis);
			}
		}
		old_buttons = buttons;
		break;
	case SCREEN_EVENT_DISPLAY:
		screen_display_t new_dpy = NULL;
		screen_get_event_property_pv(screen_event, SCREEN_PROPERTY_DISPLAY, (void **)&new_dpy);
		for (int i = 0; i < ndisplays; i++) {
			if (new_dpy != screen_dpy[i])
				continue;
			int active = 0;
			screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_ATTACHED, &active);
			if (active) {
				int size[2];
				screen_get_display_property_iv(screen_dpy[i], SCREEN_PROPERTY_SIZE, size);
				if (size[0] == 0 || size[1] == 0)
					active = 0;
			}
			if (active && !displays[i].attached)
				realiseDisplay(i);
			else if (!active && displays[i].attached && displays[i].realised)
				unrealiseDisplay(i);
			displays[i].attached = active;
		}
		break;
	}
}

void BlackberryMain::startMain(int argc, char *argv[]) {
	// Receive events from window manager
	screen_create_context(&screen_cxt, 0);
	// Initialise Blackberry Platform Services
	bps_initialize();
	// TODO: Enable/disable based on setting
	sensor_set_rate(SENSOR_TYPE_ACCELEROMETER, 25000);
	sensor_request_events(SENSOR_TYPE_ACCELEROMETER);

	net::Init();
	startDisplays();
	screen_request_events(screen_cxt);
	navigator_request_events(0);
	dialog_request_events(0);
	vibration_request_events(0);
	NativeInit(argc, (const char **)argv, "/accounts/1000/shared/misc/", "app/native/assets/", "BADCOFFEE");
	NativeInitGraphics();
	audio = new BlackberryAudio();
	runMain();
}

void BlackberryMain::runMain() {
	bool running = true;
	while (running) {
		input_state.mouse_valid = false;
		input_state.accelerometer_valid = false;
		while (true) {
			// Handle Blackberry events
			bps_event_t *event = NULL;
			bps_get_event(&event, 0);
			if (event == NULL)
				break; // Ran out of events
			int domain = bps_event_get_domain(event);
			if (domain == screen_get_domain()) {
				handleInput(screen_event_get_event(event));
			} else if (domain == navigator_get_domain()) {
				switch(bps_event_get_code(event))
				{
				case NAVIGATOR_BACK:
				case NAVIGATOR_SWIPE_DOWN:
					NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_ESCAPE, KEY_DOWN));
					break;
				case NAVIGATOR_EXIT:
					return;
				}
			} else if (domain == sensor_get_domain()) {
				if (SENSOR_ACCELEROMETER_READING == bps_event_get_code(event)) {
					float x, y, z;
					sensor_event_get_xyz(event, &x, &y, &z);
					if (pixel_xres == 1024 || pixel_xres == 720) // Q10 has this negative and reversed
					{
						input_state.acc.x = -y;
						input_state.acc.y = -x;
					} else {
						input_state.acc.x = x;
						input_state.acc.y = y;
					}
					input_state.acc.z = z;
				}
			}
		}
		UpdateInputState(&input_state);
		NativeUpdate(input_state);
		// Work in Progress
		// Currently: Render to HDMI port (eg. 1080p) when in game. Render to device when in menu.
		// Idea: Render to all displays. Controls go to internal, game goes to external(s).
		if (globalUIState == UISTATE_INGAME && !emulating)
		{
			emulating = true;
			switchDisplay(screen_emu);
			if (g_Config.iShowFPSCounter == 4) {
				int options = SCREEN_DEBUG_STATISTICS;
				screen_set_window_property_iv(screen_win[0], SCREEN_PROPERTY_DEBUG, &options);
			}
		} else if (globalUIState != UISTATE_INGAME && emulating) {
			emulating = false;
			switchDisplay(screen_ui);
		}
		NativeRender();
		EndInputState(&input_state);
		time_update();
		// This handles VSync
		if (emulating)
			eglSwapBuffers(egl_disp[screen_emu], egl_surf[screen_emu]);
		else
			eglSwapBuffers(egl_disp[screen_ui], egl_surf[screen_ui]);
	}
}

void BlackberryMain::endMain() {
	screen_stop_events(screen_cxt);
	bps_shutdown();
	NativeShutdownGraphics();
	delete audio;
	NativeShutdown();
	killDisplays();
	net::Shutdown();
	screen_destroy_context(screen_cxt);
}

// Entry Point
int main(int argc, char *argv[]) {
	delete new BlackberryMain(argc, argv);
	return 0;
}
<commit_msg>Check for Blackberry invocation in native instead of in NativeApp. Much cleaner.<commit_after>/*
 * Copyright (c) 2013 Sacha Refshauge
 *
 */
// Blackberry implementation of the framework.

#include <pwd.h>
#include <unistd.h>
#include <string>

#include <bps/locale.h>           // Get locale
#include <bps/navigator_invoke.h> // Receive invocation messages
#include "BlackberryMain.h"
#include "Core/Config.h"
#include "base/NKCodeFromBlackberry.h"

#include "UI/MiscScreens.h"

// Simple implementations of System functions

std::string System_GetProperty(SystemProperty prop) {
	switch (prop) {
	case SYSPROP_NAME: {
		std::string name = "Blackberry10:";
		return name + ((pixel_xres != pixel_yres) ? "Touch" : "QWERTY");
	}
	case SYSPROP_LANGREGION: {
		char *locale = 0;
		locale_get_locale(&locale);
		return std::string(locale);
	}
	default:
		return "";
	}
}

void SystemToast(const char *text) {
	dialog_instance_t dialog = 0;
	dialog_create_toast(&dialog);
	dialog_set_toast_message_text(dialog, text);
	dialog_set_toast_position(dialog, DIALOG_POSITION_TOP_CENTER);
	dialog_show(dialog);
}

void ShowAd(int x, int y, bool center_x) {
}

void ShowKeyboard() {
	virtualkeyboard_show();
}

void Vibrate(int length_ms) {
	// Vibration: intensity strength(1-100), duration ms(0-5000)
	// Intensity: LOW = 1, MEDIUM = 10, HIGH = 100
	switch (length_ms) {
	case -1: // Keyboard Tap
		vibration_request(VIBRATION_INTENSITY_LOW, 50);
		break;
	case -2: // Virtual Key
		vibration_request(VIBRATION_INTENSITY_LOW, 25);
		break;
	case -3: // Long Press
		vibration_request(VIBRATION_INTENSITY_LOW, 50);
		break;
	default:
		vibration_request(VIBRATION_INTENSITY_LOW, length_ms);
		break;
	}
}

void LaunchBrowser(const char *url)
{
	char* error;
	navigator_invoke(url, &error);
}

void LaunchMarket(const char *url)
{
	char* error;
	navigator_invoke(url, &error);
}

void LaunchEmail(const char *email_address)
{
	char* error;
	navigator_invoke((std::string("mailto:") + email_address).c_str(), &error);
}

InputState input_state;

void BlackberryMain::handleInput(screen_event_t screen_event)
{
	TouchInput input;
	KeyInput key;
	int val, buttons, pointerId;
	int pair[2];
	screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_TYPE, &val);
	screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_SOURCE_POSITION, pair);
	screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_TOUCH_ID, &pointerId);

	input_state.mouse_valid = true;
	switch(val)
	{
	// Touchscreen
	case SCREEN_EVENT_MTOUCH_TOUCH:
	case SCREEN_EVENT_MTOUCH_RELEASE: 	// Up, down
		input_state.pointer_down[pointerId] = (val == SCREEN_EVENT_MTOUCH_TOUCH);
		input_state.pointer_x[pointerId] = pair[0] * g_dpi_scale;
		input_state.pointer_y[pointerId] = pair[1] * g_dpi_scale;

		input.x = pair[0] * g_dpi_scale;
		input.y = pair[1] * g_dpi_scale;
		input.flags = (val == SCREEN_EVENT_MTOUCH_TOUCH) ? TOUCH_DOWN : TOUCH_UP;
		input.id = pointerId;
		NativeTouch(input);
		break;
	case SCREEN_EVENT_MTOUCH_MOVE:
		input_state.pointer_x[pointerId] = pair[0] * g_dpi_scale;
		input_state.pointer_y[pointerId] = pair[1] * g_dpi_scale;

		input.x = pair[0] * g_dpi_scale;
		input.y = pair[1] * g_dpi_scale;
		input.flags = TOUCH_MOVE;
		input.id = pointerId;
		NativeTouch(input);
		break;
	// Mouse, Simulator
    case SCREEN_EVENT_POINTER:
		screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_BUTTONS,
			&buttons);
		if (buttons == SCREEN_LEFT_MOUSE_BUTTON) { 			// Down
			input_state.pointer_x[pointerId] = pair[0] * g_dpi_scale;
			input_state.pointer_y[pointerId] = pair[1] * g_dpi_scale;
			input_state.pointer_down[pointerId] = true;

			input.x = pair[0] * g_dpi_scale;
			input.y = pair[1] * g_dpi_scale;
			input.flags = TOUCH_DOWN;
			input.id = pointerId;
			NativeTouch(input);
		} else if (input_state.pointer_down[pointerId]) {	// Up
			input_state.pointer_x[pointerId] = pair[0] * g_dpi_scale;
			input_state.pointer_y[pointerId] = pair[1] * g_dpi_scale;
			input_state.pointer_down[pointerId] = false;

			input.x = pair[0] * g_dpi_scale;
			input.y = pair[1] * g_dpi_scale;
			input.flags = TOUCH_UP;
			input.id = pointerId;
			NativeTouch(input);
		}
		break;
	// Keyboard
	case SCREEN_EVENT_KEYBOARD:
		int flags, value;
		screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_KEY_FLAGS, &flags);
		screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_KEY_SYM, &value);
		NativeKey(KeyInput(DEVICE_ID_KEYBOARD, KeyMapRawBlackberrytoNative.find(value)->second, (flags & KEY_DOWN) ? KEY_DOWN : KEY_UP));
		break;
	// Gamepad
	case SCREEN_EVENT_GAMEPAD:
	case SCREEN_EVENT_JOYSTICK:
		int analog0[3];
		screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_BUTTONS, &buttons);
		for (int i = 0; i < 32; i++) {
			int mask = 1 << i;
			if ((old_buttons & mask) != (buttons & mask))
				NativeKey(KeyInput(DEVICE_ID_PAD_0, KeyMapPadBlackberrytoNative.find(mask)->second, (buttons & mask) ? KEY_DOWN : KEY_UP));
		}
		if (!screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_ANALOG0, analog0)) {
			for (int i = 0; i < 2; i++) {
				AxisInput axis;
				axis.axisId = JOYSTICK_AXIS_X + i;
				// 1.2 to try to approximate the PSP's clamped rectangular range.
				axis.value = 1.2 * analog0[i] / 128.0f;
				if (axis.value > 1.0f) axis.value = 1.0f;
				if (axis.value < -1.0f) axis.value = -1.0f;
				axis.deviceId = DEVICE_ID_PAD_0;
				axis.flags = 0;
				NativeAxis(axis);
			}
		}
		old_buttons = buttons;
		break;
	case SCREEN_EVENT_DISPLAY:
		screen_display_t new_dpy = NULL;
		screen_get_event_property_pv(screen_event, SCREEN_PROPERTY_DISPLAY, (void **)&new_dpy);
		for (int i = 0; i < ndisplays; i++) {
			if (new_dpy != screen_dpy[i])
				continue;
			int active = 0;
			screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_ATTACHED, &active);
			if (active) {
				int size[2];
				screen_get_display_property_iv(screen_dpy[i], SCREEN_PROPERTY_SIZE, size);
				if (size[0] == 0 || size[1] == 0)
					active = 0;
			}
			if (active && !displays[i].attached)
				realiseDisplay(i);
			else if (!active && displays[i].attached && displays[i].realised)
				unrealiseDisplay(i);
			displays[i].attached = active;
		}
		break;
	}
}

void BlackberryMain::startMain(int argc, char *argv[]) {
	// Receive events from window manager
	screen_create_context(&screen_cxt, 0);
	// Initialise Blackberry Platform Services
	bps_initialize();
	// TODO: Enable/disable based on setting
	sensor_set_rate(SENSOR_TYPE_ACCELEROMETER, 25000);
	sensor_request_events(SENSOR_TYPE_ACCELEROMETER);

	net::Init();
	startDisplays();
	screen_request_events(screen_cxt);
	navigator_request_events(0);
	dialog_request_events(0);
	vibration_request_events(0);
	NativeInit(argc, (const char **)argv, "/accounts/1000/shared/misc/", "app/native/assets/", "BADCOFFEE");
	NativeInitGraphics();
	audio = new BlackberryAudio();
	runMain();
}

void BlackberryMain::runMain() {
	bool running = true;
	while (running) {
		input_state.mouse_valid = false;
		input_state.accelerometer_valid = false;
		while (true) {
			// Handle Blackberry events
			bps_event_t *event = NULL;
			bps_get_event(&event, 0);
			if (event == NULL)
				break; // Ran out of events
			int domain = bps_event_get_domain(event);
			if (domain == screen_get_domain()) {
				handleInput(screen_event_get_event(event));
			} else if (domain == navigator_get_domain()) {
				switch(bps_event_get_code(event))
				{
				case NAVIGATOR_INVOKE_TARGET:
					{
						const navigator_invoke_invocation_t *invoke = navigator_invoke_event_get_invocation(event);
						if(invoke) {
							boot_filename = navigator_invoke_invocation_get_uri(invoke)+7; // Remove file://
						}
					}
					break;
				case NAVIGATOR_BACK:
				case NAVIGATOR_SWIPE_DOWN:
					NativeKey(KeyInput(DEVICE_ID_KEYBOARD, NKCODE_ESCAPE, KEY_DOWN));
					break;
				case NAVIGATOR_EXIT:
					return;
				}
			} else if (domain == sensor_get_domain()) {
				if (SENSOR_ACCELEROMETER_READING == bps_event_get_code(event)) {
					float x, y, z;
					sensor_event_get_xyz(event, &x, &y, &z);
					if (pixel_xres == 1024 || pixel_xres == 720) // Q10 has this negative and reversed
					{
						input_state.acc.x = -y;
						input_state.acc.y = -x;
					} else {
						input_state.acc.x = x;
						input_state.acc.y = y;
					}
					input_state.acc.z = z;
				}
			}
		}
		UpdateInputState(&input_state);
		NativeUpdate(input_state);
		// Work in Progress
		// Currently: Render to HDMI port (eg. 1080p) when in game. Render to device when in menu.
		// Idea: Render to all displays. Controls go to internal, game goes to external(s).
		if (globalUIState == UISTATE_INGAME && !emulating)
		{
			emulating = true;
			switchDisplay(screen_emu);
			if (g_Config.iShowFPSCounter == 4) {
				int options = SCREEN_DEBUG_STATISTICS;
				screen_set_window_property_iv(screen_win[0], SCREEN_PROPERTY_DEBUG, &options);
			}
		} else if (globalUIState != UISTATE_INGAME && emulating) {
			emulating = false;
			switchDisplay(screen_ui);
		}
		NativeRender();
		EndInputState(&input_state);
		time_update();
		// This handles VSync
		if (emulating)
			eglSwapBuffers(egl_disp[screen_emu], egl_surf[screen_emu]);
		else
			eglSwapBuffers(egl_disp[screen_ui], egl_surf[screen_ui]);
	}
}

void BlackberryMain::endMain() {
	screen_stop_events(screen_cxt);
	bps_shutdown();
	NativeShutdownGraphics();
	delete audio;
	NativeShutdown();
	killDisplays();
	net::Shutdown();
	screen_destroy_context(screen_cxt);
}

// Entry Point
int main(int argc, char *argv[]) {
	delete new BlackberryMain(argc, argv);
	return 0;
}
<|endoftext|>


<commit_before>#ifndef _INCLUDED_INPUT_HPP
#define _INCLUDED_INPUT_HPP

#include <cstddef>
#include <cstdint>
#include <fstream>
#include <iostream>
#include <string>
#include <utility>
#include <vector>

#include <tudocomp/util.h>

#include <tudocomp/io/IOUtil.hpp>
#include <tudocomp/io/ViewStream.hpp>

namespace tudocomp {
namespace io {

    struct InputView;
    struct InputStream;

    /// Represents the input of an algorithm.
    ///
    /// Can be used as either a istream or a memory buffer
    /// with the as_stream or as_view methods.
    class Input {
        struct Variant {
            virtual std::unique_ptr<Variant> virtual_copy() = 0;
            virtual InputView as_view() = 0;
            virtual InputStream as_stream() = 0;
            virtual size_t size() = 0;
        };

        struct Memory: Variant {
            const uint8_t* ptr;
            size_t m_size;

            Memory(const uint8_t* ptr, size_t size): m_size(size) {
                this->ptr = ptr;
            }

            std::unique_ptr<Variant> virtual_copy() override {
                return std::make_unique<Memory>(ptr, m_size);
            }

            inline InputView as_view() override;
            inline InputStream as_stream() override;
            inline size_t size() override;
        };
        struct File: Variant {
            std::string path;
            size_t offset;

            File(std::string path, size_t offset) {
                this->path = path;
                this->offset = offset;
            }

            std::unique_ptr<Variant> virtual_copy() override {
                return std::make_unique<File>(path, offset);
            }

            inline InputView as_view() override;
            inline InputStream as_stream() override;
            inline size_t size() override;
        };

        friend class InputStream;
        friend class InputStreamInternal;
        friend class InputView;

        std::unique_ptr<Variant> m_data;

    public:
        struct Path { std::string path; };

        /// An empty Input
        inline Input():
            m_data(std::make_unique<Memory>(nullptr, 0)) {}

        /// Create an copy of the Input, with internal cursors
        /// set to the current position
        inline Input(const Input& other):
            m_data(std::move(other.m_data->virtual_copy())) {}

        /// Move constructor
        inline Input(Input&& other):
            m_data(std::move(other.m_data)) {}

        /// An Input referring to the contents of a file
        Input(Input::Path&& path):
            m_data(std::make_unique<File>(std::move(path.path), 0)) {}

        /// An Input referring to the contents of an vector
        Input(const std::vector<uint8_t>& buf):
            m_data(std::make_unique<Memory>(&buf[0], buf.size())) {}

        /// An Input referring to the contents of an string
        Input(const string_ref buf):
            m_data(std::make_unique<Memory>(
                    (const uint8_t*) &buf[0], buf.size())) {}

        Input& operator=(Input&& other) {
            m_data = std::move(other.m_data);
            return *this;
        }

        /// DEPRECATED
        static Input from_path(std::string path) {
            return Input(Path { path });
        }

        /// DEPRECATED
        static Input from_memory(const std::vector<uint8_t>& buf) {
            return Input(buf);
        }

        /// DEPRECATED
        static Input from_memory(const string_ref buf) {
            return Input(buf);
        }

        inline InputView as_view();
        inline InputStream as_stream();

        inline size_t size() {
            return m_data->size();
        }
    };

    class InputViewInternal {
        struct Variant {
            virtual string_ref view() = 0;
        };

        struct Memory: Variant {
            const uint8_t* ptr;
            size_t size;

            Memory(const uint8_t* ptr, size_t size) {
                this->ptr = ptr;
                this->size = size;
            }

            string_ref view() override {
                return string_ref {
                    (char*) ptr,
                    size
                };
            }
        };
        struct File: Variant {
            std::vector<uint8_t> buffer;

            File(std::vector<uint8_t>&& buffer_):
                buffer(std::move(buffer_)) {}

            string_ref view() override {
                return string_ref {
                    (char*) buffer.data(),
                    buffer.size()
                };
            }
        };

        std::unique_ptr<Variant> m_variant;

        friend class InputView;
        friend class Input;

        InputViewInternal(const InputViewInternal& other) = delete;
        InputViewInternal() = delete;

        InputViewInternal(InputViewInternal::Memory&& mem):
            m_variant(std::make_unique<Memory>(std::move(mem))) {}
        InputViewInternal(InputViewInternal::File&& s):
            m_variant(std::make_unique<File>(std::move(s))) {}
        InputViewInternal(InputViewInternal&& s):
            m_variant(std::move(s.m_variant)) {}
    };

    class InputView: InputViewInternal, public View {
        friend class Input;

        InputView(InputViewInternal&& mem):
            InputViewInternal(std::move(mem)),
            View(m_variant->view()) {}
    public:
        InputView(InputView&& mem):
            InputViewInternal(std::move(mem)),
            View(std::move(mem)) {}

        InputView(const InputView& other) = delete;
        InputView() = delete;
    };

    inline InputView Input::Memory::as_view() {
        Input::Memory mem2 = *this;

        // advance view into memory by its whole length
        ptr += m_size;
        m_size = 0;

        return InputView {
            InputView::Memory { mem2.ptr, mem2.m_size }
        };
    }

    inline InputView Input::File::as_view() {
        // read file into buffer starting at current offset
        auto buf = read_file_to_stl_byte_container<
            std::vector<uint8_t>>(path, offset);

        // We read the whole file, so skip it on next read.
        offset += buf.size();

        return InputView {
            InputView::File {
                std::move(buf)
            }
        };
    }

    inline InputView Input::as_view() {
        return m_data->as_view();
    }

    class InputStreamInternal {
        class Variant {
        public:
            virtual std::istream& stream() = 0;
            virtual ~Variant() {}
        };

        class Memory: public InputStreamInternal::Variant {
            ViewStream m_stream;

            Input::Memory* m_offset_back_ref;
            size_t m_start_pos;

            bool m_is_empty = false;

            friend class InputStreamInternal;

        public:
            Memory(const Memory& other) = delete;
            Memory() = delete;

            Memory(Memory&& other):
                m_stream(std::move(other.m_stream)),
                m_offset_back_ref(other.m_offset_back_ref),
                m_start_pos(other.m_start_pos) {
                other.m_is_empty = true;
            }

            Memory(ViewStream&& stream, Input::Memory* offset_back_ref):
                m_stream(std::move(stream))
            {
                m_offset_back_ref = offset_back_ref;
                m_start_pos = m_stream.stream().tellg();
            }
            virtual ~Memory() {
                if (!m_is_empty) {
                    size_t len = size_t(m_stream.stream().tellg()) - m_start_pos;
                    m_offset_back_ref->ptr += len;
                    m_offset_back_ref->m_size -= len;
                }
            }
            std::istream& stream() override {
                return m_stream.stream();
            }
        };
        class File: public InputStreamInternal::Variant {
            std::string m_path;
            std::unique_ptr<std::ifstream> m_stream;

            Input::File* m_offset_back_ref;
            size_t m_start_pos;

            friend class InputStreamInternal;
        public:
            File(const File& other) = delete;
            File() = delete;

            File(std::string&& path,
                 Input::File* offset_back_ref,
                 size_t offset)
            {
                m_path = path;
                m_stream = std::make_unique<std::ifstream>(
                    m_path, std::ios::in | std::ios::binary);
                m_stream->seekg(offset, std::ios::beg);
                m_start_pos = m_stream->tellg();
                m_offset_back_ref = offset_back_ref;
            }

            File(File&& other) {
                m_stream = std::move(other.m_stream);
                m_offset_back_ref = other.m_offset_back_ref;
                m_path = other.m_path;
                m_start_pos = other.m_start_pos;
            }

            virtual ~File() {
                if (m_stream != nullptr) {
                    auto len = size_t(m_stream->tellg()) - m_start_pos;
                    m_offset_back_ref->offset += len;
                }
            }

            std::istream& stream() override {
                return *m_stream;
            }
        };

        std::unique_ptr<InputStreamInternal::Variant> m_variant;

        friend class InputStream;
        friend class Input;

        InputStreamInternal(const InputStreamInternal& other) = delete;
        InputStreamInternal() = delete;

        InputStreamInternal(InputStreamInternal::Memory&& mem):
            m_variant(std::move(std::make_unique<InputStreamInternal::Memory>(std::move(mem)))) {}
        InputStreamInternal(InputStreamInternal::File&& f):
            m_variant(std::move(std::make_unique<InputStreamInternal::File>(std::move(f)))) {}
        InputStreamInternal(InputStreamInternal&& s):
            m_variant(std::move(s.m_variant)) {}

    };

    class InputStream: InputStreamInternal, public std::istream {
        friend class Input;

        InputStream(InputStreamInternal&& mem):
            InputStreamInternal(std::move(mem)),
            std::istream(m_variant->stream().rdbuf()) {}
    public:
        InputStream(InputStream&& mem):
            InputStreamInternal(std::move(mem)),
            std::istream(mem.rdbuf()) {}

        InputStream(const InputStream& other) = delete;
        InputStream() = delete;
    };

    inline InputStream Input::Memory::as_stream() {
        return InputStream {
            InputStream::Memory {
                ViewStream {
                    (char*)ptr,
                    m_size
                },
                this
            }
        };
    }

    inline InputStream Input::File::as_stream() {
        return InputStream {
            InputStream::File {
                std::string(path),
                this,
                offset,
            }
        };
    }

    inline InputStream Input::as_stream() {
        return m_data->as_stream();
    }

    inline size_t Input::Memory::size() {
        return m_size;
    }

    inline size_t Input::File::size() {
        return read_file_size(path) - offset;
    }

}}

#endif

<commit_msg>Doxygen for Input.hpp #17468<commit_after>#ifndef _INCLUDED_INPUT_HPP
#define _INCLUDED_INPUT_HPP

#include <cstddef>
#include <cstdint>
#include <fstream>
#include <iostream>
#include <string>
#include <utility>
#include <vector>

#include <tudocomp/util.h>

#include <tudocomp/io/IOUtil.hpp>
#include <tudocomp/io/ViewStream.hpp>

namespace tudocomp {
namespace io {

    struct InputView;
    struct InputStream;

    /// \brief An abstraction layer for algorithm input.
    ///
    /// This class serves as a generic abstraction over different sources of
    /// input: memory, files or streams. It provides two ways of handling the
    /// input: \e streams or \e views. While a view allows random access on all
    /// of the input, it requires the entire input to be stored in memory.
    /// Streaming, on the other hand, is used for character-wise reading
    /// without the ability to rewind (online).
    class Input {
        struct Variant {
            virtual std::unique_ptr<Variant> virtual_copy() = 0;
            virtual InputView as_view() = 0;
            virtual InputStream as_stream() = 0;
            virtual size_t size() = 0;
        };

        struct Memory: Variant {
            const uint8_t* ptr;
            size_t m_size;

            Memory(const uint8_t* ptr, size_t size): m_size(size) {
                this->ptr = ptr;
            }

            std::unique_ptr<Variant> virtual_copy() override {
                return std::make_unique<Memory>(ptr, m_size);
            }

            inline InputView as_view() override;
            inline InputStream as_stream() override;
            inline size_t size() override;
        };
        struct File: Variant {
            std::string path;
            size_t offset;

            File(std::string path, size_t offset) {
                this->path = path;
                this->offset = offset;
            }

            std::unique_ptr<Variant> virtual_copy() override {
                return std::make_unique<File>(path, offset);
            }

            inline InputView as_view() override;
            inline InputStream as_stream() override;
            inline size_t size() override;
        };

        friend class InputStream;
        friend class InputStreamInternal;
        friend class InputView;

        std::unique_ptr<Variant> m_data;

    public:
        /// \brief Represents a file path.
        ///
        /// Pass a Path instance to the respective constructor in order to
        /// create an input from the file pointed to by the path.
        struct Path {
            /// The path string.
            std::string path;
        };

        /// \brief Constructs an empty input.
        inline Input():
            m_data(std::make_unique<Memory>(nullptr, 0)) {}

        /// \brief Constructs an input from another input, retaining its
        /// internal state ("cursor").
        ///
        /// Use this in combination with streams to store a rewind point.
        ///
        /// \param other The input to copy.
        inline Input(const Input& other):
            m_data(std::move(other.m_data->virtual_copy())) {}

        /// \brief Move constructor.
        inline Input(Input&& other):
            m_data(std::move(other.m_data)) {}

        /// \brief Constructs a file input reading from the file at the given
        /// path.
        ///
        /// \param path The path to the input file.
        Input(Input::Path&& path):
            m_data(std::make_unique<File>(std::move(path.path), 0)) {}

        /// \brief Constructs an input reading from the specified byte buffer.
        ///
        /// \param buf The input byte buffer.
        Input(const std::vector<uint8_t>& buf):
            m_data(std::make_unique<Memory>(&buf[0], buf.size())) {}

        /// \brief Constructs an input reading from a string in memory.
        ///
        /// \param buf The input string.
        Input(const string_ref buf):
            m_data(std::make_unique<Memory>(
                    (const uint8_t*) &buf[0], buf.size())) {}

        /// \brief Move operator.
        Input& operator=(Input&& other) {
            m_data = std::move(other.m_data);
            return *this;
        }

        /// \deprecated Use the respective constructor instead.
        /// \brief Constructs a file input reading from the file at the given
        /// path.
        ///
        /// \param path The path to the input file.
        static Input from_path(std::string path) {
            return Input(Path { path });
        }

        /// \deprecated Use the respective constructor instead.
        /// \brief Constructs a file input reading from a byte buffer.
        ///
        /// \param buf The input byte buffer.
        static Input from_memory(const std::vector<uint8_t>& buf) {
            return Input(buf);
        }

        /// \deprecated Use the respective constructor instead.
        /// \brief Constructs a file input reading from a string in memory.
        ///
        /// \param buf The input string.
        static Input from_memory(const string_ref buf) {
            return Input(buf);
        }

        /// \brief Provides a view on the input that allows for random access.
        ///
        /// This will store the entire input in memory, ie a file or stream
        /// will be fully read in order to provide the view.
        ///
        /// \return A random access view on the input.
        inline InputView as_view();

        /// \brief Creates a stream that allows for character-wise reading of
        /// the input.
        ///
        /// \return A character stream for the input.
        inline InputStream as_stream();

        /// \brief Yields the total amount of characters in the input.
        ///
        /// \return The total amount of characters in the input.
        inline size_t size() {
            return m_data->size();
        }
    };

    /// \cond INTERNAL
    class InputViewInternal {
        struct Variant {
            virtual string_ref view() = 0;
        };

        struct Memory: Variant {
            const uint8_t* ptr;
            size_t size;

            Memory(const uint8_t* ptr, size_t size) {
                this->ptr = ptr;
                this->size = size;
            }

            string_ref view() override {
                return string_ref {
                    (char*) ptr,
                    size
                };
            }
        };
        struct File: Variant {
            std::vector<uint8_t> buffer;

            File(std::vector<uint8_t>&& buffer_):
                buffer(std::move(buffer_)) {}

            string_ref view() override {
                return string_ref {
                    (char*) buffer.data(),
                    buffer.size()
                };
            }
        };

        std::unique_ptr<Variant> m_variant;

        friend class InputView;
        friend class Input;

        InputViewInternal(const InputViewInternal& other) = delete;
        InputViewInternal() = delete;

        InputViewInternal(InputViewInternal::Memory&& mem):
            m_variant(std::make_unique<Memory>(std::move(mem))) {}
        InputViewInternal(InputViewInternal::File&& s):
            m_variant(std::make_unique<File>(std::move(s))) {}
        InputViewInternal(InputViewInternal&& s):
            m_variant(std::move(s.m_variant)) {}
    };
    /// \endcond

    /// \brief Provides a view on the input that allows for random access.
    ///
    /// \sa View.
    class InputView: InputViewInternal, public View {
        friend class Input;

        InputView(InputViewInternal&& mem):
            InputViewInternal(std::move(mem)),
            View(m_variant->view()) {}
    public:
        /// Move constructor.
        InputView(InputView&& mem):
            InputViewInternal(std::move(mem)),
            View(std::move(mem)) {}

        /// Copy constructor (deleted).
        InputView(const InputView& other) = delete;

        /// Default constructor (deleted).
        InputView() = delete;
    };

    inline InputView Input::Memory::as_view() {
        Input::Memory mem2 = *this;

        // advance view into memory by its whole length
        ptr += m_size;
        m_size = 0;

        return InputView {
            InputView::Memory { mem2.ptr, mem2.m_size }
        };
    }

    inline InputView Input::File::as_view() {
        // read file into buffer starting at current offset
        auto buf = read_file_to_stl_byte_container<
            std::vector<uint8_t>>(path, offset);

        // We read the whole file, so skip it on next read.
        offset += buf.size();

        return InputView {
            InputView::File {
                std::move(buf)
            }
        };
    }

    inline InputView Input::as_view() {
        return m_data->as_view();
    }

    /// \cond INTERNAL
    class InputStreamInternal {
        class Variant {
        public:
            virtual std::istream& stream() = 0;
            virtual ~Variant() {}
        };

        class Memory: public InputStreamInternal::Variant {
            ViewStream m_stream;

            Input::Memory* m_offset_back_ref;
            size_t m_start_pos;

            bool m_is_empty = false;

            friend class InputStreamInternal;

        public:
            Memory(const Memory& other) = delete;
            Memory() = delete;

            Memory(Memory&& other):
                m_stream(std::move(other.m_stream)),
                m_offset_back_ref(other.m_offset_back_ref),
                m_start_pos(other.m_start_pos) {
                other.m_is_empty = true;
            }

            Memory(ViewStream&& stream, Input::Memory* offset_back_ref):
                m_stream(std::move(stream))
            {
                m_offset_back_ref = offset_back_ref;
                m_start_pos = m_stream.stream().tellg();
            }
            virtual ~Memory() {
                if (!m_is_empty) {
                    size_t len = size_t(m_stream.stream().tellg()) - m_start_pos;
                    m_offset_back_ref->ptr += len;
                    m_offset_back_ref->m_size -= len;
                }
            }
            std::istream& stream() override {
                return m_stream.stream();
            }
        };
        class File: public InputStreamInternal::Variant {
            std::string m_path;
            std::unique_ptr<std::ifstream> m_stream;

            Input::File* m_offset_back_ref;
            size_t m_start_pos;

            friend class InputStreamInternal;
        public:
            File(const File& other) = delete;
            File() = delete;

            File(std::string&& path,
                 Input::File* offset_back_ref,
                 size_t offset)
            {
                m_path = path;
                m_stream = std::make_unique<std::ifstream>(
                    m_path, std::ios::in | std::ios::binary);
                m_stream->seekg(offset, std::ios::beg);
                m_start_pos = m_stream->tellg();
                m_offset_back_ref = offset_back_ref;
            }

            File(File&& other) {
                m_stream = std::move(other.m_stream);
                m_offset_back_ref = other.m_offset_back_ref;
                m_path = other.m_path;
                m_start_pos = other.m_start_pos;
            }

            virtual ~File() {
                if (m_stream != nullptr) {
                    auto len = size_t(m_stream->tellg()) - m_start_pos;
                    m_offset_back_ref->offset += len;
                }
            }

            std::istream& stream() override {
                return *m_stream;
            }
        };

        std::unique_ptr<InputStreamInternal::Variant> m_variant;

        friend class InputStream;
        friend class Input;

        InputStreamInternal(const InputStreamInternal& other) = delete;
        InputStreamInternal() = delete;

        InputStreamInternal(InputStreamInternal::Memory&& mem):
            m_variant(std::move(std::make_unique<InputStreamInternal::Memory>(std::move(mem)))) {}
        InputStreamInternal(InputStreamInternal::File&& f):
            m_variant(std::move(std::make_unique<InputStreamInternal::File>(std::move(f)))) {}
        InputStreamInternal(InputStreamInternal&& s):
            m_variant(std::move(s.m_variant)) {}

    };
    /// \endcond

   /// \brief Provides a character stream of the underlying input.
    class InputStream: InputStreamInternal, public std::istream {
        friend class Input;

        InputStream(InputStreamInternal&& mem):
            InputStreamInternal(std::move(mem)),
            std::istream(m_variant->stream().rdbuf()) {}
    public:
        /// Move constructor.
        InputStream(InputStream&& mem):
            InputStreamInternal(std::move(mem)),
            std::istream(mem.rdbuf()) {}

        /// Copy constructor (deleted).
        InputStream(const InputStream& other) = delete;

        /// Default constructor (deleted).
        InputStream() = delete;
    };

    inline InputStream Input::Memory::as_stream() {
        return InputStream {
            InputStream::Memory {
                ViewStream {
                    (char*)ptr,
                    m_size
                },
                this
            }
        };
    }

    inline InputStream Input::File::as_stream() {
        return InputStream {
            InputStream::File {
                std::string(path),
                this,
                offset,
            }
        };
    }

    inline InputStream Input::as_stream() {
        return m_data->as_stream();
    }

    inline size_t Input::Memory::size() {
        return m_size;
    }

    inline size_t Input::File::size() {
        return read_file_size(path) - offset;
    }

}}

#endif

<|endoftext|>


<commit_before>#include <iostream>

#include <SFML/Graphics.hpp>
#include "game.h"

Game::Game():
    playing(true),
    screen(sf::VideoMode(800, 600), "Dune 2 - The Maker", sf::Style::Close),
    map(nullptr)
    //map_camera(nullptr),
    //unitRepository(nullptr)
{
    screen.setFramerateLimit(IDEAL_FPS);
    screen.setMouseCursorVisible(false);

    if (!init()){
        std::cerr << "Failed to initialized game.";
        playing = false;
    }
}

int Game::execute() {

  while(playing) {
    sf::Event event;
    while(screen.pollEvent(event)) {
      onEvent(event);
    }

    updateState();
    render();
  }

  return 0;
}

bool Game::init() {
  if (!terrain.loadFromFile("graphics/terrain.png")) {
    std::cout << "Failed to read graphics/terrain.png data" << std::endl;
    return false;
  }

  sf::Image temp;
  if (!temp.loadFromFile("graphics/shroud_edges.bmp")) {
    std::cout << "Failed to read graphics/shroud_edges.bmp data" << std::endl;
    return false;
  }

  temp.createMaskFromColor(sf::Color(255, 0, 255));
  shroud_edges.loadFromImage(temp);

  map.reset(new Map(terrain, shroud_edges));
  map->load("maps/4PL_Mountains.ini");

  camera.reset({0,0,800,600});
  screen.setView(camera);

  //init a trike
  sf::Image trikeImage;
  trikeImage.loadFromFile("graphics/Unit_Trike.bmp");
  trikeImage.createMaskFromColor(sf::Color(0,0,0));
  sf::Texture* trikeTexture = new sf::Texture; //yes we are leaking! Player should own this
  trikeTexture->loadFromImage(trikeImage);

  sf::Image trikeShadowImage;
  trikeShadowImage.loadFromFile("graphics/Unit_Trike_s.bmp");
  trikeShadowImage.createMaskFromColor(sf::Color(255,0,255));
  sf::Texture* trikeShadowTexture = new sf::Texture; //yes we are leaking! Player should own this
  trikeShadowTexture->loadFromImage(trikeShadowImage);

  sf::Image selectedImage;
  selectedImage.loadFromFile("graphics/selected.bmp");
  selectedImage.createMaskFromColor(sf::Color(255, 0, 255));
  sf::Texture* selectedTexture = new sf::Texture; //more leaks!
  selectedTexture->loadFromImage(selectedImage);
  units.emplace_back(new Unit(*trikeTexture, *trikeShadowTexture, *selectedTexture, 256, 256, 0));

  //remove shroud here
  map->removeShroud(static_cast<sf::Vector2i>(units[0]->getPosition()), 10);

  //shroud_edges_shadow = Surface::load("graphics/shroud_edges_shadow.bmp");

  //if (shroud_edges_shadow == NULL) {
    //cout << "Failed to read graphics/shroud_edges_shadow.bmp data" << endl;
    //return false;
  //}

  //mouse.init(screen);

  //map_camera.reset(new MapCamera(0, 0, screen, &map));
  //map.load("maps/4PL_Mountains.ini");
  //unitRepository.reset(new UnitRepository(&map));

  ////init two players
  //int idCount = 0;
  //players.emplace_back(House::Sardaukar, idCount++);
  //players.emplace_back(House::Harkonnen, idCount++);

  //units.emplace_back(unitRepository->create(UNIT_FRIGATE, House::Sardaukar, 3, 3, 10, SUBCELL_CENTER, players[0]));
  //units.emplace_back(unitRepository->create(UNIT_TRIKE, House::Sardaukar, 8, 8, 3, SUBCELL_CENTER, players[0]));

  //// soldiers
  //units.emplace_back(unitRepository->create(UNIT_SOLDIER, House::Sardaukar, 14, 14, 3, SUBCELL_CENTER, players[0]));
  //units.emplace_back(unitRepository->create(UNIT_SOLDIER, House::Sardaukar, 14, 14, 3, SUBCELL_UPLEFT, players[0]));
  //units.emplace_back(unitRepository->create(UNIT_SOLDIER, House::Sardaukar, 14, 14, 3, SUBCELL_UPRIGHT, players[0]));
  //units.emplace_back(unitRepository->create(UNIT_SOLDIER, House::Sardaukar, 14, 14, 3, SUBCELL_DOWNLEFT, players[0]));
  //units.emplace_back(unitRepository->create(UNIT_SOLDIER, House::Sardaukar, 14, 14, 3, SUBCELL_DOWNRIGHT, players[0]));

  //units.emplace_back(unitRepository->create(UNIT_SOLDIER, House::Harkonnen, 18, 8, 3, SUBCELL_CENTER, players[1]));
  //units.emplace_back(unitRepository->create(UNIT_SOLDIER, House::Harkonnen, 18, 8, 3, SUBCELL_UPLEFT, players[1]));
  //units.emplace_back(unitRepository->create(UNIT_SOLDIER, House::Harkonnen, 18, 8, 3, SUBCELL_UPRIGHT, players[1]));
  //units.emplace_back(unitRepository->create(UNIT_SOLDIER, House::Harkonnen, 18, 8, 3, SUBCELL_DOWNLEFT, players[1]));
  //units.emplace_back(unitRepository->create(UNIT_SOLDIER, House::Harkonnen, 18, 8, 3, SUBCELL_DOWNRIGHT, players[1]));

  return true;
}

void Game::onEvent(sf::Event event) {

  switch (event.type){
    case sf::Event::Closed:
      playing = false; break;
    case sf::Event::KeyPressed:
      switch (event.key.code) {
        case sf::Keyboard::Q:
          playing = false; break;
        default:
          break;
      }
      break;
  case sf::Event::MouseButtonPressed:
      switch (event.mouseButton.button){
      case sf::Mouse::Left:{
          sf::Vector2f toSet = screen.mapPixelToCoords(sf::Vector2i(event.mouseButton.x, event.mouseButton.y));
          box.setTopLeft(toSet);
          break;
      }
      default:
          break;
      }
      break;
  case sf::Event::MouseButtonReleased:
      switch (event.mouseButton.button){
      case sf::Mouse::Left:
          for (auto& unit : units){
              if (box.intersects(unit->getBounds())){
                  unit->select();
                  mouse.setType(Mouse::Type::Move); //at least one unit selected...
              }
          }
          for (auto& unit : units){
              if (unit->is_selected()) unit->order_move(screen.mapPixelToCoords(static_cast<sf::Vector2i>(mouse.getPosition())));
          }
          box.clear();
          break;
      case sf::Mouse::Right:
          //deselect all units
          for (auto& unit : units){
              unit->unselect();
              mouse.setType(Mouse::Type::Default);
          }
      default:
          break;
      }
    default:
      break;
  }

  //mouse.onEvent(event);
  //keyboard.onEvent(event);

  //map_camera->onEvent(event);

  //if (event->type == SDL_USEREVENT) {
    //if (event->user.code == D2TM_SELECT) {
      //std::unique_ptr<D2TMSelectStruct> s(static_cast<D2TMSelectStruct*>(event->user.data1));

      //Point p = map_camera->toWorldCoordinates(s->screen_position);

      //if (mouse.is_pointing()) {
        //Unit* selected_unit = NULL;
        //for (auto& unit : units){
            //if (unit->is_point_within(p)){
                //selected_unit = unit.get();
                //break;
            //}

        //}
        //if (selected_unit != NULL) {
          //deselectAllUnits();
          //selected_unit->select();
          //mouse.state_order_move();
        //}
      //}
    //} else if (event->user.code == D2TM_DESELECT) {
      //mouse.state_pointing();
      //deselectAllUnits();
    //} else if (event->user.code == D2TM_BOX_SELECT) {
      //std::unique_ptr<D2TMBoxSelectStruct> s(static_cast<D2TMBoxSelectStruct*>(event->user.data1));

      //Rectangle rectangle = map_camera->toWorldCoordinates(s->rectangle);

      //if (mouse.is_pointing()) {
        //mouse.state_pointing();

        //deselectAllUnits();
        //for (auto& unit : units){
            //if (unit->is_within(rectangle)){
                //unit->select();
                //mouse.state_order_move();
            //}
        //}
      //}
    //} else if (event->user.code == D2TM_MOVE_UNIT) {
      //std::unique_ptr<D2TMMoveUnitStruct> s(static_cast<D2TMMoveUnitStruct*>(event->user.data1));
      //Point p = map_camera->toWorldCoordinates(s->screen_position);

      //for (auto& unit : units){
          //if (unit->is_selected())
              //unit->order_move(p);
      //}
    //}

  //}

}

void Game::render() {
  screen.clear();

  screen.draw(*map);

  for (const auto& unit : units)
      screen.draw(*unit);

  map->drawShrouded(screen, sf::RenderStates::Default);

  screen.draw(box);

  screen.draw(mouse);

  screen.display();
}

void Game::updateState() {
  static const float cameraSpeed = 10.f;
  float vec_x = 0.f, vec_y = 0.f;
  if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up)) vec_y -= cameraSpeed;
  if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down)) vec_y += cameraSpeed;
  if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left)) vec_x -= cameraSpeed;
  if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right)) vec_x += cameraSpeed;

  camera.move(vec_x, vec_y);
  screen.setView(camera);

  if (sf::Mouse::isButtonPressed(sf::Mouse::Left))
      box.setBottomRight(screen.mapPixelToCoords(sf::Mouse::getPosition(screen)));

  mouse.setPosition(screen.mapPixelToCoords(sf::Mouse::getPosition(screen)));

  //keyboard.updateState();
  //mouse.updateState();
  //map_camera->updateState();

  for (auto& unit: units){
      unit->updateState();
  }
}

//void Game::deselectAllUnits() {
    //for (auto& unit : units)
        //unit->unselect();
//}

//bool Game::playerHasUnits(const Player &player) const
//{
    //for (const auto& unit : units){
        //if (unit->getOwner()==player)
            //return true; //unit belonging to player found
    //}
    //return false;
//}

<commit_msg>request antialising level 8<commit_after>#include <iostream>

#include <SFML/Graphics.hpp>
#include "game.h"

Game::Game():
    playing(true),
    screen(),
    map(nullptr)
    //map_camera(nullptr),
    //unitRepository(nullptr)
{
    sf::ContextSettings settings;
    settings.antialiasingLevel = 8;
    screen.create(sf::VideoMode(800, 600), "Dune 2 - The Maker", sf::Style::Close, settings);
    screen.setFramerateLimit(IDEAL_FPS);
    screen.setMouseCursorVisible(false);

    if (!init()){
        std::cerr << "Failed to initialized game.";
        playing = false;
    }
}

int Game::execute() {

  while(playing) {
    sf::Event event;
    while(screen.pollEvent(event)) {
      onEvent(event);
    }

    updateState();
    render();
  }

  return 0;
}

bool Game::init() {
  if (!terrain.loadFromFile("graphics/terrain.png")) {
    std::cout << "Failed to read graphics/terrain.png data" << std::endl;
    return false;
  }

  sf::Image temp;
  if (!temp.loadFromFile("graphics/shroud_edges.bmp")) {
    std::cout << "Failed to read graphics/shroud_edges.bmp data" << std::endl;
    return false;
  }

  temp.createMaskFromColor(sf::Color(255, 0, 255));
  shroud_edges.loadFromImage(temp);

  map.reset(new Map(terrain, shroud_edges));
  map->load("maps/4PL_Mountains.ini");

  camera.reset({0,0,800,600});
  screen.setView(camera);

  //init a trike
  sf::Image trikeImage;
  trikeImage.loadFromFile("graphics/Unit_Trike.bmp");
  trikeImage.createMaskFromColor(sf::Color(0,0,0));
  sf::Texture* trikeTexture = new sf::Texture; //yes we are leaking! Player should own this
  trikeTexture->loadFromImage(trikeImage);

  sf::Image trikeShadowImage;
  trikeShadowImage.loadFromFile("graphics/Unit_Trike_s.bmp");
  trikeShadowImage.createMaskFromColor(sf::Color(255,0,255));
  sf::Texture* trikeShadowTexture = new sf::Texture; //yes we are leaking! Player should own this
  trikeShadowTexture->loadFromImage(trikeShadowImage);

  sf::Image selectedImage;
  selectedImage.loadFromFile("graphics/selected.bmp");
  selectedImage.createMaskFromColor(sf::Color(255, 0, 255));
  sf::Texture* selectedTexture = new sf::Texture; //more leaks!
  selectedTexture->loadFromImage(selectedImage);
  units.emplace_back(new Unit(*trikeTexture, *trikeShadowTexture, *selectedTexture, 256, 256, 0));

  //remove shroud here
  map->removeShroud(static_cast<sf::Vector2i>(units[0]->getPosition()), 10);

  //shroud_edges_shadow = Surface::load("graphics/shroud_edges_shadow.bmp");

  //if (shroud_edges_shadow == NULL) {
    //cout << "Failed to read graphics/shroud_edges_shadow.bmp data" << endl;
    //return false;
  //}

  //mouse.init(screen);

  //map_camera.reset(new MapCamera(0, 0, screen, &map));
  //map.load("maps/4PL_Mountains.ini");
  //unitRepository.reset(new UnitRepository(&map));

  ////init two players
  //int idCount = 0;
  //players.emplace_back(House::Sardaukar, idCount++);
  //players.emplace_back(House::Harkonnen, idCount++);

  //units.emplace_back(unitRepository->create(UNIT_FRIGATE, House::Sardaukar, 3, 3, 10, SUBCELL_CENTER, players[0]));
  //units.emplace_back(unitRepository->create(UNIT_TRIKE, House::Sardaukar, 8, 8, 3, SUBCELL_CENTER, players[0]));

  //// soldiers
  //units.emplace_back(unitRepository->create(UNIT_SOLDIER, House::Sardaukar, 14, 14, 3, SUBCELL_CENTER, players[0]));
  //units.emplace_back(unitRepository->create(UNIT_SOLDIER, House::Sardaukar, 14, 14, 3, SUBCELL_UPLEFT, players[0]));
  //units.emplace_back(unitRepository->create(UNIT_SOLDIER, House::Sardaukar, 14, 14, 3, SUBCELL_UPRIGHT, players[0]));
  //units.emplace_back(unitRepository->create(UNIT_SOLDIER, House::Sardaukar, 14, 14, 3, SUBCELL_DOWNLEFT, players[0]));
  //units.emplace_back(unitRepository->create(UNIT_SOLDIER, House::Sardaukar, 14, 14, 3, SUBCELL_DOWNRIGHT, players[0]));

  //units.emplace_back(unitRepository->create(UNIT_SOLDIER, House::Harkonnen, 18, 8, 3, SUBCELL_CENTER, players[1]));
  //units.emplace_back(unitRepository->create(UNIT_SOLDIER, House::Harkonnen, 18, 8, 3, SUBCELL_UPLEFT, players[1]));
  //units.emplace_back(unitRepository->create(UNIT_SOLDIER, House::Harkonnen, 18, 8, 3, SUBCELL_UPRIGHT, players[1]));
  //units.emplace_back(unitRepository->create(UNIT_SOLDIER, House::Harkonnen, 18, 8, 3, SUBCELL_DOWNLEFT, players[1]));
  //units.emplace_back(unitRepository->create(UNIT_SOLDIER, House::Harkonnen, 18, 8, 3, SUBCELL_DOWNRIGHT, players[1]));

  return true;
}

void Game::onEvent(sf::Event event) {

  switch (event.type){
    case sf::Event::Closed:
      playing = false; break;
    case sf::Event::KeyPressed:
      switch (event.key.code) {
        case sf::Keyboard::Q:
          playing = false; break;
        default:
          break;
      }
      break;
  case sf::Event::MouseButtonPressed:
      switch (event.mouseButton.button){
      case sf::Mouse::Left:{
          sf::Vector2f toSet = screen.mapPixelToCoords(sf::Vector2i(event.mouseButton.x, event.mouseButton.y));
          box.setTopLeft(toSet);
          break;
      }
      default:
          break;
      }
      break;
  case sf::Event::MouseButtonReleased:
      switch (event.mouseButton.button){
      case sf::Mouse::Left:
          for (auto& unit : units){
              if (box.intersects(unit->getBounds())){
                  unit->select();
                  mouse.setType(Mouse::Type::Move); //at least one unit selected...
              }
          }
          for (auto& unit : units){
              if (unit->is_selected()) unit->order_move(screen.mapPixelToCoords(static_cast<sf::Vector2i>(mouse.getPosition())));
          }
          box.clear();
          break;
      case sf::Mouse::Right:
          //deselect all units
          for (auto& unit : units){
              unit->unselect();
              mouse.setType(Mouse::Type::Default);
          }
      default:
          break;
      }
    default:
      break;
  }

  //mouse.onEvent(event);
  //keyboard.onEvent(event);

  //map_camera->onEvent(event);

  //if (event->type == SDL_USEREVENT) {
    //if (event->user.code == D2TM_SELECT) {
      //std::unique_ptr<D2TMSelectStruct> s(static_cast<D2TMSelectStruct*>(event->user.data1));

      //Point p = map_camera->toWorldCoordinates(s->screen_position);

      //if (mouse.is_pointing()) {
        //Unit* selected_unit = NULL;
        //for (auto& unit : units){
            //if (unit->is_point_within(p)){
                //selected_unit = unit.get();
                //break;
            //}

        //}
        //if (selected_unit != NULL) {
          //deselectAllUnits();
          //selected_unit->select();
          //mouse.state_order_move();
        //}
      //}
    //} else if (event->user.code == D2TM_DESELECT) {
      //mouse.state_pointing();
      //deselectAllUnits();
    //} else if (event->user.code == D2TM_BOX_SELECT) {
      //std::unique_ptr<D2TMBoxSelectStruct> s(static_cast<D2TMBoxSelectStruct*>(event->user.data1));

      //Rectangle rectangle = map_camera->toWorldCoordinates(s->rectangle);

      //if (mouse.is_pointing()) {
        //mouse.state_pointing();

        //deselectAllUnits();
        //for (auto& unit : units){
            //if (unit->is_within(rectangle)){
                //unit->select();
                //mouse.state_order_move();
            //}
        //}
      //}
    //} else if (event->user.code == D2TM_MOVE_UNIT) {
      //std::unique_ptr<D2TMMoveUnitStruct> s(static_cast<D2TMMoveUnitStruct*>(event->user.data1));
      //Point p = map_camera->toWorldCoordinates(s->screen_position);

      //for (auto& unit : units){
          //if (unit->is_selected())
              //unit->order_move(p);
      //}
    //}

  //}

}

void Game::render() {
  screen.clear();

  screen.draw(*map);

  for (const auto& unit : units)
      screen.draw(*unit);

  map->drawShrouded(screen, sf::RenderStates::Default);

  screen.draw(box);

  screen.draw(mouse);

  screen.display();
}

void Game::updateState() {
  static const float cameraSpeed = 10.f;
  float vec_x = 0.f, vec_y = 0.f;
  if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up)) vec_y -= cameraSpeed;
  if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down)) vec_y += cameraSpeed;
  if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left)) vec_x -= cameraSpeed;
  if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right)) vec_x += cameraSpeed;

  camera.move(vec_x, vec_y);
  screen.setView(camera);

  if (sf::Mouse::isButtonPressed(sf::Mouse::Left))
      box.setBottomRight(screen.mapPixelToCoords(sf::Mouse::getPosition(screen)));

  mouse.setPosition(screen.mapPixelToCoords(sf::Mouse::getPosition(screen)));

  //keyboard.updateState();
  //mouse.updateState();
  //map_camera->updateState();

  for (auto& unit: units){
      unit->updateState();
  }
}

//void Game::deselectAllUnits() {
    //for (auto& unit : units)
        //unit->unselect();
//}

//bool Game::playerHasUnits(const Player &player) const
//{
    //for (const auto& unit : units){
        //if (unit->getOwner()==player)
            //return true; //unit belonging to player found
    //}
    //return false;
//}

<|endoftext|>


<commit_before>#undef DEBUG
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/epoll.h>

//for connection to server
bool ready4data = false;//set to true when streaming starts
bool inited = false;
bool stopparsing = false;
timeval lastrec;

int CONN_fd = 0;
#include "../util/ddv_socket.cpp" //DDVTech Socket wrapper
#include "../util/flv_sock.cpp" //FLV parsing with SocketW
#include "parsechunks.cpp" //chunkstream parsing
#include "handshake.cpp" //handshaking

int server_socket = 0;

void termination_handler (int signum){
  if (server_socket == 0) return;
  close(server_socket);
  server_socket = 0;
}

int main(int argc, char ** argv){
  //setup signal handler
  struct sigaction new_action;
  new_action.sa_handler = termination_handler;
  sigemptyset (&new_action.sa_mask);
  new_action.sa_flags = 0;
  sigaction (SIGINT, &new_action, NULL);
  sigaction (SIGHUP, &new_action, NULL);
  sigaction (SIGTERM, &new_action, NULL);

  server_socket = DDV_Listen(1935);
  if ((argc < 2) || (argv[1] == "nd")){
    if (server_socket > 0){daemon(1, 0);}else{return 1;}
  }
  int status;
  while (server_socket > 0){
    waitpid((pid_t)-1, &status, WNOHANG);
    CONN_fd = DDV_Accept(server_socket);
    if (CONN_fd > 0){
      pid_t myid = fork();
      if (myid == 0){
        break;
      }else{
        printf("Spawned new process %i for handling socket %i\n", (int)myid, CONN_fd);
      }
    }
  }
  if (server_socket <= 0){
    return 0;
  }

  unsigned int ts;
  unsigned int fts = 0;
  unsigned int ftst;
  int ss;
  FLV_Pack * tag = 0;

  //first timestamp set
  firsttime = getNowMS();

  #ifdef DEBUG
  fprintf(stderr, "Doing handshake...\n");
  #endif
  if (doHandshake()){
    #ifdef DEBUG
    fprintf(stderr, "Handshake succcess!\n");
    #endif
  }else{
    #ifdef DEBUG
    fprintf(stderr, "Handshake fail!\n");
    #endif
    return 0;
  }
  #ifdef DEBUG
  fprintf(stderr, "Starting processing...\n");
  #endif

  int retval;
  int poller = epoll_create(1);
  int sspoller = epoll_create(1);
  struct epoll_event ev;
  ev.events = EPOLLIN;
  ev.data.fd = CONN_fd;
  epoll_ctl(poller, EPOLL_CTL_ADD, CONN_fd, &ev);
  struct epoll_event events[1];

  while (!socketError && !All_Hell_Broke_Loose){
    //only parse input if available or not yet init'ed
    //rightnow = getNowMS();
    retval = epoll_wait(poller, events, 1, 0);
    if ((retval > 0) || !ready4data || (snd_cnt - snd_window_at >= snd_window_size)){
      if (DDV_ready(CONN_fd)){
        parseChunk();
      }
    }
    if (ready4data){
      if (!inited){
        //we are ready, connect the socket!
        ss = DDV_OpenUnix(streamname);
        if (ss <= 0){
          #ifdef DEBUG
          fprintf(stderr, "Could not connect to server!\n");
          #endif
          return 0;
        }
        ev.events = EPOLLIN;
        ev.data.fd = ss;
        epoll_ctl(sspoller, EPOLL_CTL_ADD, ss, &ev);
        #ifdef DEBUG
        fprintf(stderr, "Everything connected, starting to send video data...\n");
        #endif
        inited = true;
      }

      retval = epoll_wait(poller, events, 1, 50);
      if ((retval > 0) && (DDV_ready(ss))){
        if (FLV_GetPacket(tag, ss)){//able to read a full packet?
          ts = tag->data[7] * 256*256*256;
          ts += tag->data[4] * 256*256;
          ts += tag->data[5] * 256;
          ts += tag->data[6];
          if (ts != 0){
            if (fts == 0){fts = ts;ftst = getNowMS();}
            ts -= fts;
            tag->data[7] = ts / (256*256*256);
            tag->data[4] = ts / (256*256);
            tag->data[5] = ts / 256;
            tag->data[6] = ts % 256;
            ts += ftst;
          }else{
            ftst = getNowMS();
            tag->data[7] = ftst / (256*256*256);
            tag->data[4] = ftst / (256*256);
            tag->data[5] = ftst / 256;
            tag->data[6] = ftst % 256;
          }
          SendMedia((unsigned char)tag->data[0], (unsigned char *)tag->data+11, tag->len-15, ts);
          #ifdef DEBUG
          fprintf(stderr, "Sent a tag to %i\n", CONN_fd);
          #endif
        }
      }
    }
    //send ACK if we received a whole window
    if (rec_cnt - rec_window_at > rec_window_size){
      rec_window_at = rec_cnt;
      SendCTL(3, rec_cnt);//send ack (msg 3)
    }
  }
  //#ifdef DEBUG
  if (socketError){fprintf(stderr, "socketError\n");}
  if (All_Hell_Broke_Loose){fprintf(stderr, "All Hell Broke Loose\n");}
  fprintf(stderr, "User %i disconnected.\n", CONN_fd);
  //#endif
  return 0;
}//main
<commit_msg>Minder debugging<commit_after>#undef DEBUG
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/epoll.h>

//for connection to server
bool ready4data = false;//set to true when streaming starts
bool inited = false;
bool stopparsing = false;
timeval lastrec;

int CONN_fd = 0;
#include "../util/ddv_socket.cpp" //DDVTech Socket wrapper
#include "../util/flv_sock.cpp" //FLV parsing with SocketW
#include "parsechunks.cpp" //chunkstream parsing
#include "handshake.cpp" //handshaking

int server_socket = 0;

void termination_handler (int signum){
  if (server_socket == 0) return;
  close(server_socket);
  server_socket = 0;
}

int main(int argc, char ** argv){
  //setup signal handler
  struct sigaction new_action;
  new_action.sa_handler = termination_handler;
  sigemptyset (&new_action.sa_mask);
  new_action.sa_flags = 0;
  sigaction (SIGINT, &new_action, NULL);
  sigaction (SIGHUP, &new_action, NULL);
  sigaction (SIGTERM, &new_action, NULL);

  server_socket = DDV_Listen(1935);
  if ((argc < 2) || (argv[1] == "nd")){
    if (server_socket > 0){daemon(1, 0);}else{return 1;}
  }
  int status;
  while (server_socket > 0){
    waitpid((pid_t)-1, &status, WNOHANG);
    CONN_fd = DDV_Accept(server_socket);
    if (CONN_fd > 0){
      pid_t myid = fork();
      if (myid == 0){
        break;
      }else{
        printf("Spawned new process %i for handling socket %i\n", (int)myid, CONN_fd);
      }
    }
  }
  if (server_socket <= 0){
    return 0;
  }

  unsigned int ts;
  unsigned int fts = 0;
  unsigned int ftst;
  int ss;
  FLV_Pack * tag = 0;

  //first timestamp set
  firsttime = getNowMS();

  #ifdef DEBUG
  fprintf(stderr, "Doing handshake...\n");
  #endif
  if (doHandshake()){
    #ifdef DEBUG
    fprintf(stderr, "Handshake succcess!\n");
    #endif
  }else{
    #ifdef DEBUG
    fprintf(stderr, "Handshake fail!\n");
    #endif
    return 0;
  }
  #ifdef DEBUG
  fprintf(stderr, "Starting processing...\n");
  #endif

  int retval;
  int poller = epoll_create(1);
  int sspoller = epoll_create(1);
  struct epoll_event ev;
  ev.events = EPOLLIN;
  ev.data.fd = CONN_fd;
  epoll_ctl(poller, EPOLL_CTL_ADD, CONN_fd, &ev);
  struct epoll_event events[1];

  while (!socketError && !All_Hell_Broke_Loose){
    //only parse input if available or not yet init'ed
    //rightnow = getNowMS();
    retval = epoll_wait(poller, events, 1, 0);
    if ((retval > 0) || !ready4data || (snd_cnt - snd_window_at >= snd_window_size)){
      if (DDV_ready(CONN_fd)){
        parseChunk();
      }
    }
    if (ready4data){
      if (!inited){
        //we are ready, connect the socket!
        ss = DDV_OpenUnix(streamname);
        if (ss <= 0){
          #ifdef DEBUG
          fprintf(stderr, "Could not connect to server!\n");
          #endif
          return 0;
        }
        ev.events = EPOLLIN;
        ev.data.fd = ss;
        epoll_ctl(sspoller, EPOLL_CTL_ADD, ss, &ev);
        #ifdef DEBUG
        fprintf(stderr, "Everything connected, starting to send video data...\n");
        #endif
        inited = true;
      }

      retval = epoll_wait(poller, events, 1, 50);
      if (DDV_ready(ss)){
        if (FLV_GetPacket(tag, ss)){//able to read a full packet?
          ts = tag->data[7] * 256*256*256;
          ts += tag->data[4] * 256*256;
          ts += tag->data[5] * 256;
          ts += tag->data[6];
          if (ts != 0){
            if (fts == 0){fts = ts;ftst = getNowMS();}
            ts -= fts;
            tag->data[7] = ts / (256*256*256);
            tag->data[4] = ts / (256*256);
            tag->data[5] = ts / 256;
            tag->data[6] = ts % 256;
            ts += ftst;
          }else{
            ftst = getNowMS();
            tag->data[7] = ftst / (256*256*256);
            tag->data[4] = ftst / (256*256);
            tag->data[5] = ftst / 256;
            tag->data[6] = ftst % 256;
          }
          SendMedia((unsigned char)tag->data[0], (unsigned char *)tag->data+11, tag->len-15, ts);
          #ifdef DEBUG
          fprintf(stderr, "Sent a tag to %i\n", CONN_fd);
          #endif
        }
      }
    }
    //send ACK if we received a whole window
    if (rec_cnt - rec_window_at > rec_window_size){
      rec_window_at = rec_cnt;
      SendCTL(3, rec_cnt);//send ack (msg 3)
    }
  }
  //#ifdef DEBUG
  if (socketError){fprintf(stderr, "socketError\n");}
  if (All_Hell_Broke_Loose){fprintf(stderr, "All Hell Broke Loose\n");}
  fprintf(stderr, "User %i disconnected.\n", CONN_fd);
  //#endif
  return 0;
}//main
<|endoftext|>