<commit_before>#include <getopt.h>
#include <QApplication>
#include <QMessageBox>
#include <QWidget>
#include <QDir>

#include <glib-object.h>
#include <cstdio>

#include "i18n.h"
#include "crash-handler.h"
#include "utils/utils.h"
#include "utils/process.h"
#include "utils/uninstall-helpers.h"
#include "shared-application.h"
#include "ui/proxy-style.h"
#include "seafile-applet.h"
#include "QtAwesome.h"
#include "open-local-helper.h"
#if defined(Q_OS_MAC)
#include "application.h"
#endif

#define APPNAME "seafile-applet"

namespace {
void initGlib()
{
#if !GLIB_CHECK_VERSION(2, 35, 0)
    g_type_init();
#endif
#if !GLIB_CHECK_VERSION(2, 31, 0)
    g_thread_init(NULL);
#endif
}

void initBreakpad()
{
#ifdef SEAFILE_CLIENT_HAS_CRASH_REPORTER
    // if we have built with breakpad, load it in run time
    Breakpad::CrashHandler::instance()->Init(
        QDir(defaultCcnetDir()).absoluteFilePath("crash-applet"));
#endif
}

void setupFontFix()
{
#if QT_VERSION < QT_VERSION_CHECK(5, 3, 2) && defined(Q_OS_MAC)
    // Text in buttons and drop-downs looks misaligned in osx 10.10,
    // fixed in qt5.3.2
    // https://bugreports.qt-project.org/browse/QTBUG-40833
    if ( QSysInfo::MacintoshVersion > QSysInfo::MV_10_8 ) {
        QFont::insertSubstitution(".Helvetica Neue DeskInterface", "Helvetica Neue");
    }
#endif // QT_VERSION_CHECK(5, 3, 2)
}

void setupHIDPIFix()
{
#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0)
    // enable builtin retina mode
    // http://blog.qt.digia.com/blog/2013/04/25/retina-display-support-for-mac-os-ios-and-x11/
    // https://qt.gitorious.org/qt/qtbase/source/a3cb057c3d5c9ed2c12fb7542065c3d667be38b7:src/gui/image/qicon.cpp#L1028-1043
    qApp->setAttribute(Qt::AA_UseHighDpiPixmaps);
#endif

#if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0) && !defined(Q_OS_MAC)
    // Enable HDPI auto detection.
    // See http://blog.qt.io/blog/2016/01/26/high-dpi-support-in-qt-5-6/
    qApp->setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
}

void setupSettingDomain()
{
    // see QSettings documentation
    QCoreApplication::setOrganizationName(getBrand());
    QCoreApplication::setOrganizationDomain("seafile.com");
    QCoreApplication::setApplicationName(QString("%1 Client").arg(getBrand()));
}

void handleCommandLineOption(int argc, char *argv[])
{
    int c;
    static const char *short_options = "KDXc:d:f:";
    static const struct option long_options[] = {
        { "config-dir", required_argument, NULL, 'c' },
        { "data-dir", required_argument, NULL, 'd' },
        { "stop", no_argument, NULL, 'K' },
        { "delay", no_argument, NULL, 'D' },
        { "remove-user-data", no_argument, NULL, 'X' },
        { "open-local-file", no_argument, NULL, 'f' },
        { "stdout", no_argument, NULL, 'l' },
        { NULL, 0, NULL, 0, },
    };

    while ((c = getopt_long (argc, argv, short_options,
                             long_options, NULL)) != EOF) {
        switch (c) {
        case 'c':
            g_setenv ("CCNET_CONF_DIR", optarg, 1);
            break;
        case 'd':
            g_setenv ("SEAFILE_DATA_DIR", optarg, 1);
            break;
        case 'l':
            g_setenv ("LOG_STDOUT", "", 1);
            break;
        case 'K':
            do_stop();
            exit(0);
        case 'D':
            msleep(1000);
            break;
        case 'X':
            do_remove_user_data();
            exit(0);
        case 'f':
            OpenLocalHelper::instance()->handleOpenLocalFromCommandLine(optarg);
            break;
        default:
            exit(1);
        }
    }

}

} // anonymous namespace

int main(int argc, char *argv[])
{
    int ret = 0;

    // call glib's init functions
    initGlib();

    // initialize breakpad if enabled
    initBreakpad();

    // Apply hidpi support
    setupHIDPIFix();

#if defined(Q_OS_WIN32)
    // change the current directory
    QDir::setCurrent(QApplication::applicationDirPath());
    QCoreApplication::addLibraryPath("./");
#endif

    // TODO imple if we have to restart the application
    // the manual at http://qt-project.org/wiki/ApplicationRestart
#if defined(Q_OS_MAC)
    Application app(argc, argv);
#else
    QApplication app(argc, argv);
#endif

    // don't quit even if the last windows is closed
    app.setQuitOnLastWindowClosed(false);

    // apply some ui fixes for mac
    setupFontFix();

    // set the domains of settings
    setupSettingDomain();

    // initialize i18n settings
    I18NHelper::getInstance()->init();

    // initialize style settings
    app.setStyle(new SeafileProxyStyle());

    // handle with the command arguments
    handleCommandLineOption(argc, argv);

    // count if we have any instance running now. if more than one, exit
    if (count_process(APPNAME) > 1) {
        // have we activated it ? exit
        if (SharedApplication::activate())
            return 0;
        if (QMessageBox::No == QMessageBox::warning(NULL, getBrand(),
                QObject::tr("Found another running process of %1, kill it and start a new one?").arg(getBrand()),
                QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes)) {
            return -1;
        }

        // sleep 9 * 100ms to await the os completing the operation
        do_stop();
        int n = 10;
        while(--n >0 && count_process(APPNAME) > 1)
            msleep(100);

        // force shutdown it
        if (count_process(APPNAME) > 1) {
            shutdown_process(APPNAME);
            msleep(100);
        }

        // count if we still have any instance running now. if more than one, exit
        if (count_process(APPNAME) > 1) {
            QMessageBox::critical(NULL, getBrand(),
                QObject::tr("Unable to start %1 due to the failure of shutting down the previous process").arg(getBrand()),
                QMessageBox::Ok);
            return -1;
        }
    }

    // init qtawesome component
    awesome = new QtAwesome(qApp);
    awesome->initFontAwesome();

    // start applet
    SeafileApplet mApplet;
    seafApplet = &mApplet;
    seafApplet->start();

    // start qt eventloop
    ret = app.exec();

    return ret;
}
<commit_msg>Fixed a qt warning.<commit_after>#include <getopt.h>
#include <QApplication>
#include <QMessageBox>
#include <QWidget>
#include <QDir>

#include <glib-object.h>
#include <cstdio>

#include "i18n.h"
#include "crash-handler.h"
#include "utils/utils.h"
#include "utils/process.h"
#include "utils/uninstall-helpers.h"
#include "shared-application.h"
#include "ui/proxy-style.h"
#include "seafile-applet.h"
#include "QtAwesome.h"
#include "open-local-helper.h"
#if defined(Q_OS_MAC)
#include "application.h"
#endif

#define APPNAME "seafile-applet"

namespace {
void initGlib()
{
#if !GLIB_CHECK_VERSION(2, 35, 0)
    g_type_init();
#endif
#if !GLIB_CHECK_VERSION(2, 31, 0)
    g_thread_init(NULL);
#endif
}

void initBreakpad()
{
#ifdef SEAFILE_CLIENT_HAS_CRASH_REPORTER
    // if we have built with breakpad, load it in run time
    Breakpad::CrashHandler::instance()->Init(
        QDir(defaultCcnetDir()).absoluteFilePath("crash-applet"));
#endif
}

void setupFontFix()
{
#if QT_VERSION < QT_VERSION_CHECK(5, 3, 2) && defined(Q_OS_MAC)
    // Text in buttons and drop-downs looks misaligned in osx 10.10,
    // fixed in qt5.3.2
    // https://bugreports.qt-project.org/browse/QTBUG-40833
    if ( QSysInfo::MacintoshVersion > QSysInfo::MV_10_8 ) {
        QFont::insertSubstitution(".Helvetica Neue DeskInterface", "Helvetica Neue");
    }
#endif // QT_VERSION_CHECK(5, 3, 2)
}

void setupHIDPIFix()
{
#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0)
    // enable builtin retina mode
    // http://blog.qt.digia.com/blog/2013/04/25/retina-display-support-for-mac-os-ios-and-x11/
    // https://qt.gitorious.org/qt/qtbase/source/a3cb057c3d5c9ed2c12fb7542065c3d667be38b7:src/gui/image/qicon.cpp#L1028-1043
    qApp->setAttribute(Qt::AA_UseHighDpiPixmaps);
#endif

#if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0) && !defined(Q_OS_MAC)
    // Enable HDPI auto detection.
    // See http://blog.qt.io/blog/2016/01/26/high-dpi-support-in-qt-5-6/
    qApp->setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
}

void setupSettingDomain()
{
    // see QSettings documentation
    QCoreApplication::setOrganizationName(getBrand());
    QCoreApplication::setOrganizationDomain("seafile.com");
    QCoreApplication::setApplicationName(QString("%1 Client").arg(getBrand()));
}

void handleCommandLineOption(int argc, char *argv[])
{
    int c;
    static const char *short_options = "KDXc:d:f:";
    static const struct option long_options[] = {
        { "config-dir", required_argument, NULL, 'c' },
        { "data-dir", required_argument, NULL, 'd' },
        { "stop", no_argument, NULL, 'K' },
        { "delay", no_argument, NULL, 'D' },
        { "remove-user-data", no_argument, NULL, 'X' },
        { "open-local-file", no_argument, NULL, 'f' },
        { "stdout", no_argument, NULL, 'l' },
        { NULL, 0, NULL, 0, },
    };

    while ((c = getopt_long (argc, argv, short_options,
                             long_options, NULL)) != EOF) {
        switch (c) {
        case 'c':
            g_setenv ("CCNET_CONF_DIR", optarg, 1);
            break;
        case 'd':
            g_setenv ("SEAFILE_DATA_DIR", optarg, 1);
            break;
        case 'l':
            g_setenv ("LOG_STDOUT", "", 1);
            break;
        case 'K':
            do_stop();
            exit(0);
        case 'D':
            msleep(1000);
            break;
        case 'X':
            do_remove_user_data();
            exit(0);
        case 'f':
            OpenLocalHelper::instance()->handleOpenLocalFromCommandLine(optarg);
            break;
        default:
            exit(1);
        }
    }

}

} // anonymous namespace

int main(int argc, char *argv[])
{
    int ret = 0;

    // call glib's init functions
    initGlib();

    // initialize breakpad if enabled
    initBreakpad();

    // Apply hidpi support
    setupHIDPIFix();

#if defined(Q_OS_WIN32)
    // When the user start seafile applet from the windows "Start" menu, the
    // working directory is set to the parent folder of the seafile-applet.exe.
    // See https://github.com/haiwen/seafile/blob/v6.0.1/msi/seafile.wxs#L60
    //
    // Sometimes the seafile-applet program would abort with error messgages
    // "can't find qt plugin windows dll". So here we add current directory to
    // the library path, hopefully fixing that problem.
    QCoreApplication::addLibraryPath(".\\");
#endif

    // TODO imple if we have to restart the application
    // the manual at http://qt-project.org/wiki/ApplicationRestart
#if defined(Q_OS_MAC)
    Application app(argc, argv);
#else
    QApplication app(argc, argv);
#endif

    // don't quit even if the last windows is closed
    app.setQuitOnLastWindowClosed(false);

    // apply some ui fixes for mac
    setupFontFix();

    // set the domains of settings
    setupSettingDomain();

    // initialize i18n settings
    I18NHelper::getInstance()->init();

    // initialize style settings
    app.setStyle(new SeafileProxyStyle());

    // handle with the command arguments
    handleCommandLineOption(argc, argv);

    // count if we have any instance running now. if more than one, exit
    if (count_process(APPNAME) > 1) {
        // have we activated it ? exit
        if (SharedApplication::activate())
            return 0;
        if (QMessageBox::No == QMessageBox::warning(NULL, getBrand(),
                QObject::tr("Found another running process of %1, kill it and start a new one?").arg(getBrand()),
                QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes)) {
            return -1;
        }

        // sleep 9 * 100ms to await the os completing the operation
        do_stop();
        int n = 10;
        while(--n >0 && count_process(APPNAME) > 1)
            msleep(100);

        // force shutdown it
        if (count_process(APPNAME) > 1) {
            shutdown_process(APPNAME);
            msleep(100);
        }

        // count if we still have any instance running now. if more than one, exit
        if (count_process(APPNAME) > 1) {
            QMessageBox::critical(NULL, getBrand(),
                QObject::tr("Unable to start %1 due to the failure of shutting down the previous process").arg(getBrand()),
                QMessageBox::Ok);
            return -1;
        }
    }

    // init qtawesome component
    awesome = new QtAwesome(qApp);
    awesome->initFontAwesome();

    // start applet
    SeafileApplet mApplet;
    seafApplet = &mApplet;
    seafApplet->start();

    // start qt eventloop
    ret = app.exec();

    return ret;
}
<|endoftext|>


<commit_before>/// \file    main.cpp

#include <cstdlib>

int main(int argc, char* argv[])
{
  return EXIT_SUCCESS;
}

// vim:set et ts=2 sw=2 sts=2:

<commit_msg>Add testing code to main<commit_after>/// \file    main.cpp

#include <cstdlib>

#define DOCTEST_CONFIG_IMPLEMENT
#include "doctest.h"

int main(int argc, char* argv[])
{
  ////////////////////////////// Testing Stuff ////
  doctest::Context context;                      //
  context.setOption("no-breaks", true);          //
  context.applyCommandLine(argc, argv);          //
  auto test_results = context.run();             //
  if (context.shouldExit()) return test_results; //
  /////////////////////////////////////////////////

  // My code here

  return EXIT_SUCCESS + test_results;
}

// vim:set et ts=2 sw=2 sts=2:

<|endoftext|>


<commit_before>#include "cpp_std_11.hpp"

#include <SFML/Graphics.hpp>
#include <iostream>
#include "gamescreenstate.hpp"
#include "menuscreenstate.hpp"
#include "screenstack.hpp"
#include "resourcemanager.hpp"
#include "scene.hpp"
#include "lamp.hpp"

int main(int argc, char** argv)
{
	sf::RenderWindow window;
	sf::String window_title = "Ludum Dare 35";
	sf::VideoMode window_mode (800,600);

	window.create(window_mode, window_title);
	window.setFramerateLimit(60);

	ScreenStack screenStack;
	screenStack.registerState(ScreenState::Menu, make_unique<MenuScreenState>());
//	screenStack.registerState(ScreenState::Game, make_unique<GameScreenState>());

//	screenStack.pushState(ScreenState::Game);
	screenStack.pushState(ScreenState::Menu);

	Scene scene;
	Lamp(sf::Color::Blue,10.f,0.f,6.f).attachParent(scene.getRootNode());

	sf::Event event;
	sf::Clock clock;

	while (window.isOpen()) {
	    while (window.pollEvent(event)) {
	        if (event.type == sf::Event::Closed)
                window.close();
            else
				//menu_screen_state.event(window, event);
                screenStack.onEvent(window, event);
	    }

	    window.clear();
	    screenStack.onDraw(window);
		//menu_screen_state.render(window);
	    window.display();
	    window.draw(scene);
		//screenStack.window_update(window);
		screenStack.onUpdate(clock.getElapsedTime());
		//menu_screen_state.update(clock.getElapsedTime());
        clock.restart();

	}
}
<commit_msg>quelques ajouts<commit_after>#include "cpp_std_11.hpp"

#include <SFML/Graphics.hpp>
#include <iostream>

#include "gamescreenstate.hpp"
#include "menuscreenstate.hpp"
#include "screenstack.hpp"
#include "resourcemanager.hpp"
#include "scene.hpp"
#include "lamp.hpp"
/*
#include <sstream>
int main()
{
    SmokeShape shape_ref;
    shape_ref.m_Shape.setRadius(10.f);

    Scene scene;

    sf::Text text;
    text.setPosition({50.f,90.f});

    ParticleEmitter<SmokeShape> p(shape_ref, scene.getRootNode());
    p.setFrequency(60);
    p.setNumberOfParticles(60);
    p.setNumberOfParticlesMax(100);
    p.setPosition({400.f, 300.f});
    sf::RenderWindow window({800,600}, "toto");
*/

int main(int argc, char** argv)
{
	sf::RenderWindow window;
	sf::String window_title = "Ludum Dare 35";
	sf::VideoMode window_mode (800,600);

	window.create(window_mode, window_title);
	window.setFramerateLimit(60);

	ScreenStack screenStack;
	screenStack.registerState(ScreenState::Menu, make_unique<MenuScreenState>());
//	screenStack.registerState(ScreenState::Game, make_unique<GameScreenState>());

//	screenStack.pushState(ScreenState::Game);
	screenStack.pushState(ScreenState::Menu);

	Scene scene;
	Lamp(sf::Color::Blue,10.f,0.f,6.f).attachParent(scene.getRootNode());

	sf::Event event;
	sf::Clock clock;

	while (window.isOpen()) {
	    while (window.pollEvent(event)) {
	        if (event.type == sf::Event::Closed)
                window.close();
            else
				//menu_screen_state.event(window, event);
                screenStack.onEvent(window, event);
	    }

	    window.clear();
	    screenStack.onDraw(window);
		//menu_screen_state.render(window);
	    window.display();
	    window.draw(scene);
		//screenStack.window_update(window);
		screenStack.onUpdate(clock.getElapsedTime());
		//menu_screen_state.update(clock.getElapsedTime());
        clock.restart();

	}
}
<|endoftext|>


<commit_before>// texture.cpp
// OpenGL texture classes

// Copyright 2015 Matthew Chandler

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

// TODO: replace glm:: data to openGL with glm::value_ptr?

#include "texture.hpp"

#include <GL/glew.h>
#include <SFML/Graphics.hpp>

std::unordered_map<std::string, std::weak_ptr<Texture>> Texture::_allocated_tex;

Texture::~Texture()
{
    glDeleteTextures(1, &_texid);
    _allocated_tex.erase(_key);
}

GLuint Texture::get_id() const
{
    return  _texid;
}

Texture::Texture()
{
    glGenTextures(1, &_texid);
}

std::shared_ptr<Texture_2D> Texture_2D::create(const std::string & filename)
{
    std::string key = std::string("2D:") + filename;

    if(Texture::_allocated_tex.count(key) > 0)
    {
        return std::dynamic_pointer_cast<Texture_2D>(Texture::_allocated_tex[key].lock());
    }
    else
    {
        std::shared_ptr<Texture_2D> ret(new Texture_2D(filename));
        ret->_key = key;
        Texture::_allocated_tex[key] = ret;
        return ret;
    }
}

Texture_2D::Texture_2D(const std::string & filename)
{
    glBindTexture(GL_TEXTURE_2D, _texid);

    sf::Image img;
    if(!img.loadFromFile(filename))
    {
        throw std::ios_base::failure(std::string("Error reading image file: ") + filename);
    }

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, img.getSize().x, img.getSize().y,
        0, GL_RGBA, GL_UNSIGNED_BYTE, img.getPixelsPtr());

    set_properties();
}

Texture_2D::Texture_2D(const glm::vec4 & color, const GLint width, const GLint height)
{
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height,
        0, GL_RGBA, GL_FLOAT, &color[0]);

    set_properties();
}

void Texture_2D::set_properties() const
{
    glGenerateMipmap(GL_TEXTURE_2D);

    // set params
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
}

std::shared_ptr<Texture_2D> Texture_2D::diffuse_fallback()
{
    static std::shared_ptr<Texture_2D> fallback;
    if(!fallback)
    {
        fallback.reset(new Texture_2D(glm::vec4(1.0f, 1.0f, 1.0f, 1.0f), 1, 1));
    }
    return fallback;
}

std::shared_ptr<Texture_2D> Texture_2D::normal_fallback()
{
    static std::shared_ptr<Texture_2D> fallback;
    if(!fallback)
    {
        fallback.reset(new Texture_2D(glm::vec4(0.0f, 0.0f, 1.0f, 1.0f), 1, 1));
    }
    return fallback;
}

std::shared_ptr<Texture_2D> Texture_2D::emissive_fallback()
{
    static std::shared_ptr<Texture_2D> fallback;
    if(!fallback)
    {
        fallback.reset(new Texture_2D(glm::vec4(0.0f, 0.0f, 0.0f, 1.0f), 1, 1));
    }
    return fallback;
}

void Texture_2D::bind() const
{
    glBindTexture(GL_TEXTURE_2D, _texid);
}

std::shared_ptr<Texture_cubemap> Texture_cubemap::create(const std::string & left_fname, const std::string & right_fname,
    const std::string & back_fname, const std::string & front_fname,
    const std::string & down_fname, const std::string & up_fname)
{
    std::string key = std::string("CUBE:") +
        left_fname + ";" + right_fname + ";" +
        back_fname + ";" + front_fname + ";" +
        down_fname + ";" + up_fname;

    if(Texture::_allocated_tex.count(key) > 0)
    {
        return std::dynamic_pointer_cast<Texture_cubemap>(Texture::_allocated_tex[key].lock());
    }
    else
    {
        std::shared_ptr<Texture_cubemap> ret(new Texture_cubemap(left_fname, right_fname,
                back_fname, front_fname,
                down_fname, up_fname));
        ret->_key = key;
        Texture::_allocated_tex[key] = ret;
        return ret;
    }
}

// create a cubemap texture from 6 filenames
Texture_cubemap::Texture_cubemap(const std::string & left_fname, const std::string & right_fname,
    const std::string & back_fname, const std::string & front_fname,
    const std::string & down_fname, const std::string & up_fname)
{
    glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS); // TODO: should this be enabled at higher scope?

    // create array of pairs: filename with type enum
    std::vector<std::pair<std::string, GLenum>> filenames =
    {
        std::make_pair(left_fname, GL_TEXTURE_CUBE_MAP_NEGATIVE_X),
        std::make_pair(right_fname, GL_TEXTURE_CUBE_MAP_POSITIVE_X),
        std::make_pair(back_fname, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z),
        std::make_pair(front_fname, GL_TEXTURE_CUBE_MAP_POSITIVE_Z),
        std::make_pair(down_fname, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y),
        std::make_pair(up_fname, GL_TEXTURE_CUBE_MAP_POSITIVE_Y)
    };

    glBindTexture(GL_TEXTURE_CUBE_MAP, _texid);

    for(const auto & filename: filenames)
    {
        // load each file
        sf::Image img;
        if(!img.loadFromFile(filename.first))
        {
            throw std::ios_base::failure(std::string("Error reading image file: ") + filename.first);
        }

        // send data to OpenGL
        glTexImage2D(filename.second, 0, GL_RGBA8, img.getSize().x, img.getSize().y,
            0, GL_RGBA, GL_UNSIGNED_BYTE, img.getPixelsPtr());
    }

    set_properties();
}

Texture_cubemap::Texture_cubemap(const glm::vec4 & color, const GLint width, const GLint height)
{
    std::vector<GLenum> sides =
    {
        GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
        GL_TEXTURE_CUBE_MAP_POSITIVE_X,
        GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
        GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
        GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
        GL_TEXTURE_CUBE_MAP_POSITIVE_Y
    };

    for(const auto & side: sides)
    {
        glTexImage2D(side, 0, GL_RGBA8, width, height,
            0, GL_RGBA, GL_FLOAT, &color[0]);
    }

    set_properties();
}

void Texture_cubemap::set_properties() const
{
    // set params
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BASE_LEVEL, 0);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, 0);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
}

std::shared_ptr<Texture_cubemap> Texture_cubemap::env_fallback()
{
    static std::shared_ptr<Texture_cubemap> fallback;
    if(!fallback)
    {
        fallback.reset(new Texture_cubemap(glm::vec4(1.0f, 1.0f, 1.0f, 1.0f), 1, 1));
    }
    return fallback;
}

void Texture_cubemap::bind() const
{
    glBindTexture(GL_TEXTURE_CUBE_MAP, _texid);
}
<commit_msg>fix textures being overwritten by fallbacks<commit_after>// texture.cpp
// OpenGL texture classes

// Copyright 2015 Matthew Chandler

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

// TODO: replace glm:: data to openGL with glm::value_ptr?

#include "texture.hpp"

#include <GL/glew.h>
#include <SFML/Graphics.hpp>

std::unordered_map<std::string, std::weak_ptr<Texture>> Texture::_allocated_tex;

Texture::~Texture()
{
    glDeleteTextures(1, &_texid);
    _allocated_tex.erase(_key);
}

GLuint Texture::get_id() const
{
    return  _texid;
}

Texture::Texture()
{
    glGenTextures(1, &_texid);
}

std::shared_ptr<Texture_2D> Texture_2D::create(const std::string & filename)
{
    std::string key = std::string("2D:") + filename;

    if(Texture::_allocated_tex.count(key) > 0)
    {
        return std::dynamic_pointer_cast<Texture_2D>(Texture::_allocated_tex[key].lock());
    }
    else
    {
        std::shared_ptr<Texture_2D> ret(new Texture_2D(filename));
        ret->_key = key;
        Texture::_allocated_tex[key] = ret;
        return ret;
    }
}

Texture_2D::Texture_2D(const std::string & filename)
{
    glBindTexture(GL_TEXTURE_2D, _texid);

    sf::Image img;
    if(!img.loadFromFile(filename))
    {
        throw std::ios_base::failure(std::string("Error reading image file: ") + filename);
    }

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, img.getSize().x, img.getSize().y,
        0, GL_RGBA, GL_UNSIGNED_BYTE, img.getPixelsPtr());

    set_properties();
}

Texture_2D::Texture_2D(const glm::vec4 & color, const GLint width, const GLint height)
{
    glBindTexture(GL_TEXTURE_2D, _texid);

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height,
        0, GL_RGBA, GL_FLOAT, &color[0]);

    set_properties();
}

void Texture_2D::set_properties() const
{
    glGenerateMipmap(GL_TEXTURE_2D);

    // set params
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
}

std::shared_ptr<Texture_2D> Texture_2D::diffuse_fallback()
{
    static std::shared_ptr<Texture_2D> fallback;
    if(!fallback)
    {
        fallback.reset(new Texture_2D(glm::vec4(1.0f, 1.0f, 1.0f, 1.0f), 1, 1));
    }
    return fallback;
}

std::shared_ptr<Texture_2D> Texture_2D::normal_fallback()
{
    static std::shared_ptr<Texture_2D> fallback;
    if(!fallback)
    {
        fallback.reset(new Texture_2D(glm::vec4(0.0f, 0.0f, 1.0f, 1.0f), 1, 1));
    }
    return fallback;
}

std::shared_ptr<Texture_2D> Texture_2D::emissive_fallback()
{
    static std::shared_ptr<Texture_2D> fallback;
    if(!fallback)
    {
        fallback.reset(new Texture_2D(glm::vec4(0.0f, 0.0f, 0.0f, 1.0f), 1, 1));
    }
    return fallback;
}

void Texture_2D::bind() const
{
    glBindTexture(GL_TEXTURE_2D, _texid);
}

std::shared_ptr<Texture_cubemap> Texture_cubemap::create(const std::string & left_fname, const std::string & right_fname,
    const std::string & back_fname, const std::string & front_fname,
    const std::string & down_fname, const std::string & up_fname)
{
    std::string key = std::string("CUBE:") +
        left_fname + ";" + right_fname + ";" +
        back_fname + ";" + front_fname + ";" +
        down_fname + ";" + up_fname;

    if(Texture::_allocated_tex.count(key) > 0)
    {
        return std::dynamic_pointer_cast<Texture_cubemap>(Texture::_allocated_tex[key].lock());
    }
    else
    {
        std::shared_ptr<Texture_cubemap> ret(new Texture_cubemap(left_fname, right_fname,
                back_fname, front_fname,
                down_fname, up_fname));
        ret->_key = key;
        Texture::_allocated_tex[key] = ret;
        return ret;
    }
}

// create a cubemap texture from 6 filenames
Texture_cubemap::Texture_cubemap(const std::string & left_fname, const std::string & right_fname,
    const std::string & back_fname, const std::string & front_fname,
    const std::string & down_fname, const std::string & up_fname)
{
    glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS); // TODO: should this be enabled at higher scope?

    // create array of pairs: filename with type enum
    std::vector<std::pair<std::string, GLenum>> filenames =
    {
        std::make_pair(left_fname, GL_TEXTURE_CUBE_MAP_NEGATIVE_X),
        std::make_pair(right_fname, GL_TEXTURE_CUBE_MAP_POSITIVE_X),
        std::make_pair(back_fname, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z),
        std::make_pair(front_fname, GL_TEXTURE_CUBE_MAP_POSITIVE_Z),
        std::make_pair(down_fname, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y),
        std::make_pair(up_fname, GL_TEXTURE_CUBE_MAP_POSITIVE_Y)
    };

    glBindTexture(GL_TEXTURE_CUBE_MAP, _texid);

    for(const auto & filename: filenames)
    {
        // load each file
        sf::Image img;
        if(!img.loadFromFile(filename.first))
        {
            throw std::ios_base::failure(std::string("Error reading image file: ") + filename.first);
        }

        // send data to OpenGL
        glTexImage2D(filename.second, 0, GL_RGBA8, img.getSize().x, img.getSize().y,
            0, GL_RGBA, GL_UNSIGNED_BYTE, img.getPixelsPtr());
    }

    set_properties();
}

Texture_cubemap::Texture_cubemap(const glm::vec4 & color, const GLint width, const GLint height)
{
    std::vector<GLenum> sides =
    {
        GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
        GL_TEXTURE_CUBE_MAP_POSITIVE_X,
        GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
        GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
        GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
        GL_TEXTURE_CUBE_MAP_POSITIVE_Y
    };

    for(const auto & side: sides)
    {
        glTexImage2D(side, 0, GL_RGBA8, width, height,
            0, GL_RGBA, GL_FLOAT, &color[0]);
    }

    set_properties();
}

void Texture_cubemap::set_properties() const
{
    // set params
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BASE_LEVEL, 0);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, 0);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
}

std::shared_ptr<Texture_cubemap> Texture_cubemap::env_fallback()
{
    static std::shared_ptr<Texture_cubemap> fallback;
    if(!fallback)
    {
        fallback.reset(new Texture_cubemap(glm::vec4(1.0f, 1.0f, 1.0f, 1.0f), 1, 1));
    }
    return fallback;
}

void Texture_cubemap::bind() const
{
    glBindTexture(GL_TEXTURE_CUBE_MAP, _texid);
}
<|endoftext|>


<commit_before>#include <cstdio>
#include <cstdlib>
#include <cctype>
#include <cstring>
#include <unistd.h>
#include <vector>
#include <string>
#include <iostream>

#include "functions.h"

int main(int argc, char** argv)
{
  // hold a raw line of input
  std::string line;

  // print welcome message and prompt
  printf("Welcome to rshell!\n");

  while (true)
  {
    // holds a single command and its arguments
    Command cmd;
    // holds multiple commands
    std::vector<Command> cmds;

    // print prompt and get a line of text (done in condition)
    printf("$ ");
    getline(std::cin, line);

    // look for comments
    if (line.find("#") != std::string::npos)
    {
      // remove them if necessary (they're useless)
      line = line.substr(0, line.find("#"));
    }

    // remove leading whitespace
    while (line.size() > 0 && (line[0] == ' ' || line[0] == ';'))
    {
      line = line.substr(1, line.size() - 1);
    }

    // adding this makes parsing easier
    line += "; ";

    if (std::cin.fail())
    {
      printf("\nGoodbye!\n");
      exit(0);
    }

    int mode = GETWORD;
    unsigned begin = 0;

    // prepare cmd
    cmd.connector = NONE;

    // syntax error flag
    bool se = false;

    // starts with a connector? I don't think so
    if (line.size() > 0 && isConn(line[0]) && line[0] != ';')
    {
      se = true;
    }

    // handle the input
    for(unsigned i = 0; i < line.size() && !se; ++i)
    {
      bool con   = isConn(line[i]);
      bool space = isspace(line[i]);

      // if we're getting a word and there's a whitespace or connector here
      if (mode == GETWORD && (space || con))
      {
        // chunk the last term and throw it into the vector
        char* c = stocstr(line.substr(begin, i - begin));
        if (strlen(c) > 0)
        {
          cmd.args.push_back(c);
        }
        else
        {
          // only happens when nothing is entered. breaks so nothing more happens
          break;
        }

        if (space)
        {
          mode = TRIMSPACE;
        }
        else // it's a connector
        {
          handleCon(cmds, cmd, line, mode, begin, i, se);
        }
      }
      else if (mode == TRIMSPACE && (!space || con))
      {
        if (con && cmd.args.empty())
        {
          if (line[i] != ';')
          {
            se = true;
          }
        }
        else if (con)
        {
          handleCon(cmds, cmd, line, mode, begin, i, se);
        }
        else
        {
          mode = GETWORD;
          begin = i;
        }
      }
      else if (mode == HANDLESEMI && line[i] != ';')
      {
        if (isConn(line[i]))
        {
          se = true;
        }
        else if (isspace(line[i]))
        {
          mode = TRIMSPACE;
        }
        else // it's a word
        {
          mode = GETWORD;
          begin = i;
        }
      }
    }

    // if the last command has a continuation connector, syntax error
    if (cmds.size() > 0 && (cmds[cmds.size() - 1].connector == AND
                        ||  cmds[cmds.size() - 1].connector == OR))
    {
      se = true;
    }

    // if there was a syntax error
    if (se)
    {
      printf("Syntax error\n");
      continue;
    }

    // now to execute all the commands
    for(unsigned i = 0; i < cmds.size(); ++i)
    {
      int exitStatus = 0;
      char* arg = cmds[i].args[0];
      char** argv = new char*[cmds[i].args.size()];
      for(unsigned j = 0; j < cmds[i].args.size(); ++j)
      {
        argv[j] = cmds[i].args[j];
      }

      // arg and argv are now prepared
      pid_t pid = fork();
      if (pid == -1)
      {
        perror("fork");
        exit(1);
      }
      else if (pid == 0) // child process
      {
        if (execvp(arg, argv) == -1)
        {
          // if there's a return value, there was a problem
          // -1 indicates a problem, specifically
          perror("execvp");
          exit(1);
        }
      }
      else // parent process
      {
        if (waitpid(pid, &exitStatus, 0) == -1)
        {
          perror("waitpid");
          exit(1);
        }
      }
      if (!exitStatus) // all is good (0)
      {
        while (i < cmds.size() && cmds[i].connector == OR)
        {
          ++i;
        }
      }
      else // last command failed
      {
        while (i < cmds.size() && cmds[i].connector == AND)
        {
          ++i;
        }
      }
    }

    /* debugging code
    for(unsigned i = 0; i < cmds.size(); ++i)
    {
      printf("Command %u:\n", i);
      for(unsigned j = 0; j < cmds[i].args.size(); ++j)
      {
        printf("\t\"%s\"\n", cmds[i].args[j]);
      }
      switch(cmds[i].connector)
      {
        case AND:
          printf("\t&&\n");
          break;
        case OR:
          printf("\t||\n");
          break;
        case SEMI:
          printf("\t;\n");
          break;
        case NONE:
          printf("\tNo connector\n");
          break;
        default:
          printf("\tERROR: no valid connector specified\n");
      }
    }
    */

    // deallocate allocated memory
    for(unsigned i = 0; i < cmds.size(); ++i)
    {
      for(unsigned j = 0; j < cmds[i].args.size(); ++j)
      {
        delete[] cmds[i].args[j];
      }
    }
  }
  return 0;
}

<commit_msg>added libraries to avoid compiler error<commit_after>#include <cstdio>
#include <cstdlib>
#include <cctype>
#include <cstring>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <vector>
#include <string>
#include <iostream>

#include "functions.h"

int main(int argc, char** argv)
{
  // hold a raw line of input
  std::string line;

  // print welcome message and prompt
  printf("Welcome to rshell!\n");

  while (true)
  {
    // holds a single command and its arguments
    Command cmd;
    // holds multiple commands
    std::vector<Command> cmds;

    // print prompt and get a line of text (done in condition)
    printf("$ ");
    getline(std::cin, line);

    // look for comments
    if (line.find("#") != std::string::npos)
    {
      // remove them if necessary (they're useless)
      line = line.substr(0, line.find("#"));
    }

    // remove leading whitespace
    while (line.size() > 0 && (line[0] == ' ' || line[0] == ';'))
    {
      line = line.substr(1, line.size() - 1);
    }

    // adding this makes parsing easier
    line += "; ";

    if (std::cin.fail())
    {
      printf("\nGoodbye!\n");
      exit(0);
    }

    int mode = GETWORD;
    unsigned begin = 0;

    // prepare cmd
    cmd.connector = NONE;

    // syntax error flag
    bool se = false;

    // starts with a connector? I don't think so
    if (line.size() > 0 && isConn(line[0]) && line[0] != ';')
    {
      se = true;
    }

    // handle the input
    for(unsigned i = 0; i < line.size() && !se; ++i)
    {
      bool con   = isConn(line[i]);
      bool space = isspace(line[i]);

      // if we're getting a word and there's a whitespace or connector here
      if (mode == GETWORD && (space || con))
      {
        // chunk the last term and throw it into the vector
        char* c = stocstr(line.substr(begin, i - begin));
        if (strlen(c) > 0)
        {
          cmd.args.push_back(c);
        }
        else
        {
          // only happens when nothing is entered. breaks so nothing more happens
          break;
        }

        if (space)
        {
          mode = TRIMSPACE;
        }
        else // it's a connector
        {
          handleCon(cmds, cmd, line, mode, begin, i, se);
        }
      }
      else if (mode == TRIMSPACE && (!space || con))
      {
        if (con && cmd.args.empty())
        {
          if (line[i] != ';')
          {
            se = true;
          }
        }
        else if (con)
        {
          handleCon(cmds, cmd, line, mode, begin, i, se);
        }
        else
        {
          mode = GETWORD;
          begin = i;
        }
      }
      else if (mode == HANDLESEMI && line[i] != ';')
      {
        if (isConn(line[i]))
        {
          se = true;
        }
        else if (isspace(line[i]))
        {
          mode = TRIMSPACE;
        }
        else // it's a word
        {
          mode = GETWORD;
          begin = i;
        }
      }
    }

    // if the last command has a continuation connector, syntax error
    if (cmds.size() > 0 && (cmds[cmds.size() - 1].connector == AND
                        ||  cmds[cmds.size() - 1].connector == OR))
    {
      se = true;
    }

    // if there was a syntax error
    if (se)
    {
      printf("Syntax error\n");
      continue;
    }

    // now to execute all the commands
    for(unsigned i = 0; i < cmds.size(); ++i)
    {
      int exitStatus = 0;
      char* arg = cmds[i].args[0];
      char** argv = new char*[cmds[i].args.size()];
      for(unsigned j = 0; j < cmds[i].args.size(); ++j)
      {
        argv[j] = cmds[i].args[j];
      }

      // arg and argv are now prepared
      pid_t pid = fork();
      if (pid == -1)
      {
        perror("fork");
        exit(1);
      }
      else if (pid == 0) // child process
      {
        if (execvp(arg, argv) == -1)
        {
          // if there's a return value, there was a problem
          // -1 indicates a problem, specifically
          perror("execvp");
          exit(1);
        }
      }
      else // parent process
      {
        if (waitpid(pid, &exitStatus, 0) == -1)
        {
          perror("waitpid");
          exit(1);
        }
      }
      if (!exitStatus) // all is good (0)
      {
        while (i < cmds.size() && cmds[i].connector == OR)
        {
          ++i;
        }
      }
      else // last command failed
      {
        while (i < cmds.size() && cmds[i].connector == AND)
        {
          ++i;
        }
      }
    }

    /* debugging code
    for(unsigned i = 0; i < cmds.size(); ++i)
    {
      printf("Command %u:\n", i);
      for(unsigned j = 0; j < cmds[i].args.size(); ++j)
      {
        printf("\t\"%s\"\n", cmds[i].args[j]);
      }
      switch(cmds[i].connector)
      {
        case AND:
          printf("\t&&\n");
          break;
        case OR:
          printf("\t||\n");
          break;
        case SEMI:
          printf("\t;\n");
          break;
        case NONE:
          printf("\tNo connector\n");
          break;
        default:
          printf("\tERROR: no valid connector specified\n");
      }
    }
    */

    // deallocate allocated memory
    for(unsigned i = 0; i < cmds.size(); ++i)
    {
      for(unsigned j = 0; j < cmds[i].args.size(); ++j)
      {
        delete[] cmds[i].args[j];
      }
    }
  }
  return 0;
}

<|endoftext|>


<commit_before>#include "Arduino.h"

#include <SPI.h>
#include <Wire.h>

#include "LowPower.h"

#include "cc1101_868_3.h"

class SPITransaction {
 public:
  SPITransaction(int slave_select_pin)
      : slave_select_pin_(slave_select_pin) {
    digitalWrite(slave_select_pin_, LOW);
    SPI.beginTransaction(SPISettings(50000, MSBFIRST, SPI_MODE0));
  }

  ~SPITransaction() {
    digitalWrite(slave_select_pin_, HIGH);
    SPI.endTransaction();
  }

 private:
  const int slave_select_pin_;
};

class SHT31D {
  static const uint8_t kSensorAddress = 0x44;
  static const uint16_t kSoftReset = 0x30a2;
  static const uint16_t kReadSensor = 0x2400;

 public:
  void Init() {
    WriteCommand(kSoftReset);
    delay(10);
  }

  struct Reading {
    float temperature;
    float humidity;

    Reading(float temperature, float humidity)
        : temperature(temperature),
          humidity(humidity) {}
  };

 private:
  static float ConvertTemperature(uint16_t raw_temp) {
    return -45 + 175 * (float(raw_temp) / 0xffff);
  }

  static float ConvertHumidity(uint16_t raw_humidity) {
    return 100 * (float(raw_humidity) / 0xffff);
  }

  static bool WriteCommand(uint16_t command) {
    Wire.beginTransmission(kSensorAddress);
    Wire.write(command >> 8);
    Wire.write(command & 0xff);
    return Wire.endTransmission() == 0;
  }

 public:
  Reading ReadTemperatureAndHumidity() {
    WriteCommand(kReadSensor);
    delay(500);
    Wire.requestFrom(kSensorAddress, uint8_t(6));
    if (Wire.available() == 6) {
      uint16_t raw_temp = (Wire.read() << 8) | (Wire.read() & 0xff);
      uint8_t temp_crc = Wire.read();
      uint16_t raw_humidity = (Wire.read() << 8) | (Wire.read() & 0xff);
      uint8_t humidity_crc = Wire.read();
      return Reading(ConvertTemperature(raw_temp), ConvertHumidity(raw_humidity));
    }
    Serial.println("Failed to read sensor");
    return Reading(0.0f, 0.0f);
  }
};

class CC1101 {
 private:
  const int kSlaveSelectPin = 10;
  const int kGDO0Pin = 5;
  const int kGDO2Pin = 6;

  const byte kWriteSingleByte = 0x00;
  const byte kWriteBurst = 0x40;
  const byte kReadBurst = 0xc0;
  const byte kReadSingleByte = 0x80;

  const byte kSRES = 0x30;
  const byte kSTX = 0x35;
  const byte kSFTX = 0x3b;
  const byte kSIDLE = 0x36;

  const byte kIOCFG0Config = 0x07;
  const byte kIOCFG1Config = 0x2e;
  const byte kIOCFG2Config = 0x06;

  const byte kIOCFG0 = 0x02;
  const byte kIOCFG1 = 0x01;
  const byte kIOCFG2 = 0x00;

  const byte kTXFIFO = 0x3f;

  const byte kFIFOTHR = 0x03;
  const byte kSYNC1 = 0x04;
  const byte kSYNC0 = 0x05;

  const byte kPKTLEN = 0x06;
  const byte kPKTCTRL1 = 0x07;
  const byte kPKTCTRL0 = 0x08;

  const byte kADDR = 0x09;

  const byte kCHANNR = 0x0a;
  const byte kFSCTRL1 = 0x0b;
  const byte kFSCTRL0 = 0x0c;

  const byte kFREQ2 = 0x0d;
  const byte kFREQ1 = 0x0e;
  const byte kFREQ0 = 0x0f;

  const byte kMDMCFG4 = 0x10;
  const byte kMDMCFG3 = 0x11;
  const byte kMDMCFG2 = 0x12;
  const byte kMDMCFG1 = 0x13;
  const byte kMDMCFG0 = 0x14;

  const byte kDEVIATN = 0x15;

  const byte kMCSM2 = 0x16;
  const byte kMCSM1 = 0x17;
  const byte kMCSM0 = 0x18;

  const byte kFOCCFG = 0x19;
  const byte kBSCFG = 0x1a;

  const byte kAGCCTRL2 = 0x1b;
  const byte kAGCCTRL1 = 0x1c;
  const byte kAGCCTRL0 = 0x1d;

  const byte kFREND1 = 0x21;
  const byte kFREND0 = 0x22;

  const byte kFSCAL3 = 0x23;
  const byte kFSCAL2 = 0x24;
  const byte kFSCAL1 = 0x25;
  const byte kFSCAL0 = 0x26;

  const byte kFSTEST = 0x29;
  const byte kTEST2 = 0x2c;
  const byte kTEST1 = 0x2d;
  const byte kTEST0 = 0x2e;

  byte ReadRegister(byte addr) {
    SPITransaction transaction(kSlaveSelectPin);

    SPI.transfer(addr | kReadSingleByte);
    byte reply = SPI.transfer(0x00);

    return reply;
  }

  void WriteByte(byte address, byte data) {
    SPITransaction transaction(kSlaveSelectPin);
    SPI.transfer(address | kWriteSingleByte);
    SPI.transfer(data);
  }

  void Strobe(byte command) {
    SPITransaction transaction(kSlaveSelectPin);
    SPI.transfer(command);
  }

  void WriteBurst(byte address, byte* data, int length) {
    SPITransaction transaction(kSlaveSelectPin);
    SPI.transfer(address | kWriteBurst);
    for (int i = 0; i < length; ++i) {
      data[i] = SPI.transfer(data[i]);
    }
  }

  void ReadBurst(byte address, byte* buffer, int length) {
    SPITransaction transaction(kSlaveSelectPin);
    SPI.transfer(address | kReadBurst);
    for (int i = 0; i < length; ++i) {
      buffer[i] = SPI.transfer(0x00);
    }
  }

 public:
  void SendPacket(byte* buffer, byte length) {
    Serial.println("Sending packet");
    WriteByte(kTXFIFO, length);
    WriteBurst(kTXFIFO, buffer, length);
    // Send the packet.
    Strobe(kSTX);

    // Wait for sync word to transmit.
    while(!digitalRead(kGDO2Pin)) {}
    // Wait for packet to be sent.
    while(digitalRead(kGDO2Pin)) {}

    // Return to idle state.
    Strobe(kSIDLE);
    // Flush the TXFIFO buffer.
    Strobe(kSFTX);
    Serial.println("Sent packet");
  }

  void Reset() {
    pinMode(kGDO0Pin, INPUT);
    pinMode(kGDO2Pin, INPUT);
    pinMode(kSlaveSelectPin, OUTPUT);

    Strobe(kSRES);
    delay(100);

    WriteByte(kFSCTRL1, FSCTRL1);
    WriteByte(kFSCTRL0, FSCTRL0);

    WriteByte(kFREQ2, FREQ2);
    WriteByte(kFREQ1, FREQ1);
    WriteByte(kFREQ0, FREQ0);

    WriteByte(kMDMCFG4, MDMCFG4);
    WriteByte(kMDMCFG3, MDMCFG3);
    WriteByte(kMDMCFG2, MDMCFG2);
    WriteByte(kMDMCFG1, MDMCFG1);
    WriteByte(kMDMCFG0, MDMCFG0);

    WriteByte(kCHANNR, CHANNR);
    WriteByte(kDEVIATN, DEVIATN);
    WriteByte(kFREND1, FREND1);
    WriteByte(kFREND0, FREND0);
    WriteByte(kMCSM2, MCSM2);
    WriteByte(kMCSM1, MCSM1);
    WriteByte(kMCSM0, MCSM0);
    WriteByte(kFOCCFG, FOCCFG);
    WriteByte(kBSCFG, BSCFG);

    WriteByte(kAGCCTRL2, AGCCTRL2);
    WriteByte(kAGCCTRL1, AGCCTRL1);
    WriteByte(kAGCCTRL0, AGCCTRL0);

    WriteByte(kFSCAL3, FSCAL3);
    WriteByte(kFSCAL2, FSCAL2);
    WriteByte(kFSCAL1, FSCAL1);
    WriteByte(kFSCAL0, FSCAL0);

    WriteByte(kFSTEST, FSTEST);
    WriteByte(kTEST2, TEST2);
    WriteByte(kTEST1, TEST1);
    WriteByte(kTEST0, TEST0);

    WriteByte(kIOCFG0, kIOCFG0Config);
    WriteByte(kIOCFG1, kIOCFG1Config);
    WriteByte(kIOCFG2, kIOCFG2Config);

    WriteByte(kPKTCTRL1, PKTCTRL1);
    WriteByte(kPKTCTRL0, PKTCTRL0);

    WriteByte(kADDR, ADDR);

    WriteByte(kPKTLEN, PKTLEN);

    WriteByte(kSYNC1, 0x42);
    WriteByte(kSYNC0, 0x42);

    Serial.print(ReadRegister(0xf0));
    Serial.print(ReadRegister(0xf1));
  }
};

static SHT31D sensor;
static CC1101 radio;

void setup() {
  Serial.begin(115200);

  Wire.begin();
  SPI.begin();

  sensor.Init();
  radio.Reset();

  delay(100);
}

void loop() {
  Serial.write("Hello world!\n");

  SHT31D::Reading reading = sensor.ReadTemperatureAndHumidity();
  Serial.print(reading.temperature);
  Serial.println();
  Serial.print(reading.humidity);
  Serial.println();

  uint16_t temp = uint16_t(reading.temperature * 100.0f);
  uint16_t humidity = uint16_t(reading.humidity * 100.0f);

  byte packet[] = {byte(temp >> 8), byte(temp & 0xff), byte(humidity >> 8), byte(humidity & 0xff)};
  radio.SendPacket(packet, sizeof(packet));

  // Sleep for 32s in low power mode.
  LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);
  LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);
  LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);
  LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);
}<commit_msg>Factor out sending packets.<commit_after>#include "Arduino.h"

#include <SPI.h>
#include <Wire.h>

#include "LowPower.h"

#include "cc1101_868_3.h"

class SPITransaction {
 public:
  SPITransaction(int slave_select_pin)
      : slave_select_pin_(slave_select_pin) {
    digitalWrite(slave_select_pin_, LOW);
    SPI.beginTransaction(SPISettings(50000, MSBFIRST, SPI_MODE0));
  }

  ~SPITransaction() {
    digitalWrite(slave_select_pin_, HIGH);
    SPI.endTransaction();
  }

 private:
  const int slave_select_pin_;
};

class SHT31D {
  static const uint8_t kSensorAddress = 0x44;
  static const uint16_t kSoftReset = 0x30a2;
  static const uint16_t kReadSensor = 0x2400;

 public:
  void Init() {
    WriteCommand(kSoftReset);
    delay(10);
  }

  struct Reading {
    float temperature;
    float humidity;

    Reading(float temperature, float humidity)
        : temperature(temperature),
          humidity(humidity) {}
  };

 private:
  static float ConvertTemperature(uint16_t raw_temp) {
    return -45 + 175 * (float(raw_temp) / 0xffff);
  }

  static float ConvertHumidity(uint16_t raw_humidity) {
    return 100 * (float(raw_humidity) / 0xffff);
  }

  static bool WriteCommand(uint16_t command) {
    Wire.beginTransmission(kSensorAddress);
    Wire.write(command >> 8);
    Wire.write(command & 0xff);
    return Wire.endTransmission() == 0;
  }

 public:
  Reading ReadTemperatureAndHumidity() {
    WriteCommand(kReadSensor);
    delay(500);
    Wire.requestFrom(kSensorAddress, uint8_t(6));
    if (Wire.available() == 6) {
      uint16_t raw_temp = (Wire.read() << 8) | (Wire.read() & 0xff);
      uint8_t temp_crc = Wire.read();
      uint16_t raw_humidity = (Wire.read() << 8) | (Wire.read() & 0xff);
      uint8_t humidity_crc = Wire.read();
      return Reading(ConvertTemperature(raw_temp), ConvertHumidity(raw_humidity));
    }
    Serial.println("Failed to read sensor");
    return Reading(0.0f, 0.0f);
  }
};

class CC1101 {
 private:
  const int kSlaveSelectPin = 10;
  const int kGDO0Pin = 5;
  const int kGDO2Pin = 6;

  const byte kWriteSingleByte = 0x00;
  const byte kWriteBurst = 0x40;
  const byte kReadBurst = 0xc0;
  const byte kReadSingleByte = 0x80;

  const byte kSRES = 0x30;
  const byte kSTX = 0x35;
  const byte kSFTX = 0x3b;
  const byte kSIDLE = 0x36;

  const byte kIOCFG0Config = 0x07;
  const byte kIOCFG1Config = 0x2e;
  const byte kIOCFG2Config = 0x06;

  const byte kIOCFG0 = 0x02;
  const byte kIOCFG1 = 0x01;
  const byte kIOCFG2 = 0x00;

  const byte kTXFIFO = 0x3f;

  const byte kFIFOTHR = 0x03;
  const byte kSYNC1 = 0x04;
  const byte kSYNC0 = 0x05;

  const byte kPKTLEN = 0x06;
  const byte kPKTCTRL1 = 0x07;
  const byte kPKTCTRL0 = 0x08;

  const byte kADDR = 0x09;

  const byte kCHANNR = 0x0a;
  const byte kFSCTRL1 = 0x0b;
  const byte kFSCTRL0 = 0x0c;

  const byte kFREQ2 = 0x0d;
  const byte kFREQ1 = 0x0e;
  const byte kFREQ0 = 0x0f;

  const byte kMDMCFG4 = 0x10;
  const byte kMDMCFG3 = 0x11;
  const byte kMDMCFG2 = 0x12;
  const byte kMDMCFG1 = 0x13;
  const byte kMDMCFG0 = 0x14;

  const byte kDEVIATN = 0x15;

  const byte kMCSM2 = 0x16;
  const byte kMCSM1 = 0x17;
  const byte kMCSM0 = 0x18;

  const byte kFOCCFG = 0x19;
  const byte kBSCFG = 0x1a;

  const byte kAGCCTRL2 = 0x1b;
  const byte kAGCCTRL1 = 0x1c;
  const byte kAGCCTRL0 = 0x1d;

  const byte kFREND1 = 0x21;
  const byte kFREND0 = 0x22;

  const byte kFSCAL3 = 0x23;
  const byte kFSCAL2 = 0x24;
  const byte kFSCAL1 = 0x25;
  const byte kFSCAL0 = 0x26;

  const byte kFSTEST = 0x29;
  const byte kTEST2 = 0x2c;
  const byte kTEST1 = 0x2d;
  const byte kTEST0 = 0x2e;

  byte ReadRegister(byte addr) {
    SPITransaction transaction(kSlaveSelectPin);

    SPI.transfer(addr | kReadSingleByte);
    byte reply = SPI.transfer(0x00);

    return reply;
  }

  void WriteByte(byte address, byte data) {
    SPITransaction transaction(kSlaveSelectPin);
    SPI.transfer(address | kWriteSingleByte);
    SPI.transfer(data);
  }

  void Strobe(byte command) {
    SPITransaction transaction(kSlaveSelectPin);
    SPI.transfer(command);
  }

  void WriteBurst(byte address, byte* data, int length) {
    SPITransaction transaction(kSlaveSelectPin);
    SPI.transfer(address | kWriteBurst);
    for (int i = 0; i < length; ++i) {
      data[i] = SPI.transfer(data[i]);
    }
  }

  void ReadBurst(byte address, byte* buffer, int length) {
    SPITransaction transaction(kSlaveSelectPin);
    SPI.transfer(address | kReadBurst);
    for (int i = 0; i < length; ++i) {
      buffer[i] = SPI.transfer(0x00);
    }
  }

 public:
  void SendPacket(byte* buffer, byte length) {
    Serial.println("Sending packet");
    WriteByte(kTXFIFO, length);
    WriteBurst(kTXFIFO, buffer, length);
    // Send the packet.
    Strobe(kSTX);

    // Wait for sync word to transmit.
    while(!digitalRead(kGDO2Pin)) {}
    // Wait for packet to be sent.
    while(digitalRead(kGDO2Pin)) {}

    // Return to idle state.
    Strobe(kSIDLE);
    // Flush the TXFIFO buffer.
    Strobe(kSFTX);
    Serial.println("Sent packet");
  }

  void Reset() {
    pinMode(kGDO0Pin, INPUT);
    pinMode(kGDO2Pin, INPUT);
    pinMode(kSlaveSelectPin, OUTPUT);

    Strobe(kSRES);
    delay(100);

    WriteByte(kFSCTRL1, FSCTRL1);
    WriteByte(kFSCTRL0, FSCTRL0);

    WriteByte(kFREQ2, FREQ2);
    WriteByte(kFREQ1, FREQ1);
    WriteByte(kFREQ0, FREQ0);

    WriteByte(kMDMCFG4, MDMCFG4);
    WriteByte(kMDMCFG3, MDMCFG3);
    WriteByte(kMDMCFG2, MDMCFG2);
    WriteByte(kMDMCFG1, MDMCFG1);
    WriteByte(kMDMCFG0, MDMCFG0);

    WriteByte(kCHANNR, CHANNR);
    WriteByte(kDEVIATN, DEVIATN);
    WriteByte(kFREND1, FREND1);
    WriteByte(kFREND0, FREND0);
    WriteByte(kMCSM2, MCSM2);
    WriteByte(kMCSM1, MCSM1);
    WriteByte(kMCSM0, MCSM0);
    WriteByte(kFOCCFG, FOCCFG);
    WriteByte(kBSCFG, BSCFG);

    WriteByte(kAGCCTRL2, AGCCTRL2);
    WriteByte(kAGCCTRL1, AGCCTRL1);
    WriteByte(kAGCCTRL0, AGCCTRL0);

    WriteByte(kFSCAL3, FSCAL3);
    WriteByte(kFSCAL2, FSCAL2);
    WriteByte(kFSCAL1, FSCAL1);
    WriteByte(kFSCAL0, FSCAL0);

    WriteByte(kFSTEST, FSTEST);
    WriteByte(kTEST2, TEST2);
    WriteByte(kTEST1, TEST1);
    WriteByte(kTEST0, TEST0);

    WriteByte(kIOCFG0, kIOCFG0Config);
    WriteByte(kIOCFG1, kIOCFG1Config);
    WriteByte(kIOCFG2, kIOCFG2Config);

    WriteByte(kPKTCTRL1, PKTCTRL1);
    WriteByte(kPKTCTRL0, PKTCTRL0);

    WriteByte(kADDR, ADDR);

    WriteByte(kPKTLEN, PKTLEN);

    WriteByte(kSYNC1, 0x42);
    WriteByte(kSYNC0, 0x42);

    Serial.print(ReadRegister(0xf0));
    Serial.print(ReadRegister(0xf1));
  }
};

static SHT31D sensor;
static CC1101 radio;

void setup() {
  Serial.begin(115200);

  Wire.begin();
  SPI.begin();

  sensor.Init();
  radio.Reset();

  delay(100);
}

void Send(uint16_t temp, uint16_t humidity) {
  byte packet[] = {byte(temp >> 8), byte(temp & 0xff), byte(humidity >> 8), byte(humidity & 0xff)};
  radio.SendPacket(packet, sizeof(packet));
}

void loop() {
  Serial.write("Hello world!\n");

  SHT31D::Reading reading = sensor.ReadTemperatureAndHumidity();
  Serial.print(reading.temperature);
  Serial.println();
  Serial.print(reading.humidity);
  Serial.println();

  uint16_t temp = uint16_t(reading.temperature * 100.0f);
  uint16_t humidity = uint16_t(reading.humidity * 100.0f);

  Send(temp, humidity);

  // Sleep for 32s in low power mode.
  LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);
  LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);
  LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);
  LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);
}<|endoftext|>


<commit_before>
#include "Globals.h"  // NOTE: MSVC stupidness requires this to be the same across all modules

#include "BuildInfo.h"
#include "Logger.h"
#include "MemorySettingsRepository.h"
#include "OSSupport/NetworkSingleton.h"
#include "OSSupport/MiniDumpWriter.h"
#include "OSSupport/StartAsService.h"
#include "Root.h"
#include "tclap/CmdLine.h"

#include <csignal>
#include <cstdlib>

/** If set to true, the protocols will log each player's incoming (C->S) communication to a per-connection logfile. */
bool g_ShouldLogCommIn;

/** If set to true, the protocols will log each player's outgoing (S->C) communication to a per-connection logfile. */
bool g_ShouldLogCommOut;

/** If set to true, binary will attempt to run as a service. */
bool g_RunAsService;

/** Global that registers itself as a last chance exception handler to write a minidump on crash. */
MiniDumpWriter g_MiniDumpWriter;

// Because SIG_DFL or SIG_IGN could be NULL instead of nullptr, we need to disable the Clang warning here
#ifdef __clang__
	#pragma clang diagnostic push
	#pragma clang diagnostic ignored "-Wunknown-warning-option"
	#pragma clang diagnostic ignored "-Wunknown-pragmas"
	#pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant"
#endif  // __clang__

static void NonCtrlHandler(int a_Signal)
{
	LOGD("Terminate event raised from std::signal");

	switch (a_Signal)
	{
		case SIGSEGV:
		{
			PrintStackTrace();

			LOGERROR("Failure report: \n\n"
			         "  :(   | Cuberite has encountered an error and needs to close\n"
			         "       | SIGSEGV: Segmentation fault\n"
			         "       |\n"
#ifdef BUILD_ID
			         "       | Cuberite " BUILD_SERIES_NAME " (id: " BUILD_ID ")\n"
			         "       | from commit " BUILD_COMMIT_ID "\n");
#endif

			std::signal(SIGSEGV, SIG_DFL);
			return;
		}
		case SIGABRT:
#ifdef SIGABRT_COMPAT
		case SIGABRT_COMPAT:
#endif
		{
			PrintStackTrace();

			LOGERROR("Failure report: \n\n"
			         "  :(   | Cuberite has encountered an error and needs to close\n"
			         "       | SIGABRT: Server self-terminated due to an internal fault\n"
			         "       |\n"
#ifdef BUILD_ID
			         "       | Cuberite " BUILD_SERIES_NAME " (id: " BUILD_ID ")\n"
			         "       | from commit " BUILD_COMMIT_ID "\n");
#endif

			std::signal(SIGSEGV, SIG_DFL);
			return;
		}
		case SIGINT:
		case SIGTERM:
		{
			// Server is shutting down, wait for it...
			cRoot::Stop();
			return;
		}
#ifdef SIGPIPE
		case SIGPIPE:
		{
			// Ignore (PR #2487)
			return;
		}
#endif
	}
}

#ifdef __clang__
	#pragma clang diagnostic pop
#endif  // __clang__

#ifdef _WIN32
// Handle CTRL events in windows, including console window close
static BOOL CtrlHandler(DWORD fdwCtrlType)
{
	cRoot::Stop();
	LOGD("Terminate event raised from the Windows CtrlHandler");

	// Delay as much as possible to try to get the server to shut down cleanly - 10 seconds given by Windows
	std::this_thread::sleep_for(std::chrono::seconds(10));

	// Returning from main() automatically aborts this handler thread

	return TRUE;
}
#endif

////////////////////////////////////////////////////////////////////////////////
// ParseArguments - Read the startup arguments and store into a settings object

static cMemorySettingsRepository ParseArguments(int argc, char ** argv)
{
	// Parse the comand line args:
	TCLAP::CmdLine cmd("Cuberite");
	TCLAP::ValueArg<int> slotsArg    ("s", "max-players",         "Maximum number of slots for the server to use, overrides setting in setting.ini", false, -1, "number", cmd);
	TCLAP::ValueArg<AString> confArg ("c", "config-file",         "Config file to use", false, "settings.ini", "string", cmd);
	TCLAP::MultiArg<int> portsArg    ("p", "port",                "The port number the server should listen to", false, "port", cmd);
	TCLAP::SwitchArg commLogArg      ("",  "log-comm",            "Log server client communications to file", cmd);
	TCLAP::SwitchArg commLogInArg    ("",  "log-comm-in",         "Log inbound server client communications to file", cmd);
	TCLAP::SwitchArg commLogOutArg   ("",  "log-comm-out",        "Log outbound server client communications to file", cmd);
	TCLAP::SwitchArg crashDumpFull   ("",  "crash-dump-full",     "Crashdumps created by the server will contain full server memory", cmd);
	TCLAP::SwitchArg crashDumpGlobals("",  "crash-dump-globals",  "Crashdumps created by the server will contain the global variables' values", cmd);
	TCLAP::SwitchArg noBufArg        ("",  "no-output-buffering", "Disable output buffering", cmd);
	TCLAP::SwitchArg noFileLogArg    ("",  "no-log-file",         "Disable logging to file", cmd);
	TCLAP::SwitchArg runAsServiceArg ("d", "service",             "Run as a service on Windows, or daemon on UNIX like systems", cmd);
	cmd.parse(argc, argv);

	// Copy the parsed args' values into a settings repository:
	cMemorySettingsRepository repo;
	if (confArg.isSet())
	{
		AString conf_file = confArg.getValue();
		repo.AddValue("Server", "ConfigFile", conf_file);
	}
	if (slotsArg.isSet())
	{
		int slots = slotsArg.getValue();
		repo.AddValue("Server", "MaxPlayers", static_cast<Int64>(slots));
	}
	if (portsArg.isSet())
	{
		for (auto port: portsArg.getValue())
		{
			repo.AddValue("Server", "Ports", std::to_string(port));
		}
	}
	if (noFileLogArg.getValue())
	{
		repo.AddValue("Server", "DisableLogFile", true);
	}
	if (commLogArg.getValue())
	{
		g_ShouldLogCommIn = true;
		g_ShouldLogCommOut = true;
	}
	else
	{
		g_ShouldLogCommIn = commLogInArg.getValue();
		g_ShouldLogCommOut = commLogOutArg.getValue();
	}
	if (noBufArg.getValue())
	{
		setvbuf(stdout, nullptr, _IONBF, 0);
	}
	repo.SetReadOnly();

	if (runAsServiceArg.getValue())
	{
		g_RunAsService = true;
	}

	// Apply the CrashDump flags for platforms that support them:
	if (crashDumpGlobals.getValue())
	{
		g_MiniDumpWriter.AddDumpFlags(MiniDumpFlags::WithDataSegments);
	}
	if (crashDumpFull.getValue())
	{
		g_MiniDumpWriter.AddDumpFlags(MiniDumpFlags::WithFullMemory);
	}

	return repo;
}

////////////////////////////////////////////////////////////////////////////////
// UniversalMain - Main startup logic for both standard running and as a service

static int UniversalMain(int argc, char * argv[], bool RunningAsService)
{
	// Initialize logging subsystem:
	cLogger::InitiateMultithreading();

	struct NetworkRAII
	{
		NetworkRAII()
		{
			// Initialize LibEvent:
			cNetworkSingleton::Get().Initialise();
		}

		~NetworkRAII()
		{
			// Shutdown all of LibEvent:
			cNetworkSingleton::Get().Terminate();
		}
	};

	try
	{
		// Make sure g_RunAsService is set correctly before checking it's value
		auto Settings = ParseArguments(argc, argv);

		// Attempt to run as a service
		if (!RunningAsService && g_RunAsService)
		{
			// This will either fork or call UniversalMain again:
			if (cStartAsService::MakeIntoService<&UniversalMain>())
			{
				return EXIT_SUCCESS;
			}
		}

		while (true)
		{
			NetworkRAII LibEvent;
			cRoot Root;

			if (!Root.Run(Settings))
			{
				break;
			}
		}

		return EXIT_SUCCESS;
	}
	catch (const fmt::format_error & Oops)
	{
		std::cerr << "Formatting exception: " << Oops.what() << '\n';
	}
	catch (const TCLAP::ArgException & Oops)
	{
		std::cerr << fmt::sprintf("Error reading command line {} for argument {}\n", Oops.error(), Oops.argId());
	}
	catch (const std::exception & Oops)
	{
		std::cerr << "Standard exception: " << Oops.what() << '\n';
	}
	catch (...)
	{
		std::cerr << "Unknown exception!\n";
	}

	return EXIT_FAILURE;
}

int main(int argc, char ** argv)
{
#if !defined(NDEBUG) && defined(_MSC_VER)
	_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);

	// _X: The simple built-in CRT leak finder - simply break when allocating the Nth block ({N} is listed in the leak output)
	// Only useful when the leak is in the same sequence all the time
	// _CrtSetBreakAlloc(85950);

#endif  // _DEBUG && _MSC_VER

	std::signal(SIGSEGV, NonCtrlHandler);
	std::signal(SIGTERM, NonCtrlHandler);
	std::signal(SIGINT,  NonCtrlHandler);
	std::signal(SIGABRT, NonCtrlHandler);
#ifdef SIGABRT_COMPAT
	std::signal(SIGABRT_COMPAT, NonCtrlHandler);
#endif
#ifdef SIGPIPE
	std::signal(SIGPIPE, SIG_IGN);
#endif

#ifdef _WIN32
	VERIFY(SetConsoleCtrlHandler(reinterpret_cast<PHANDLER_ROUTINE>(CtrlHandler), TRUE) == TRUE);
#endif

	return UniversalMain(argc, argv, false);
}
<commit_msg>Reformat messages in NonCtrlHandler<commit_after>
#include "Globals.h"  // NOTE: MSVC stupidness requires this to be the same across all modules

#include "BuildInfo.h"
#include "Logger.h"
#include "MemorySettingsRepository.h"
#include "OSSupport/NetworkSingleton.h"
#include "OSSupport/MiniDumpWriter.h"
#include "OSSupport/StartAsService.h"
#include "Root.h"
#include "tclap/CmdLine.h"

#include <csignal>
#include <cstdlib>

/** If set to true, the protocols will log each player's incoming (C->S) communication to a per-connection logfile. */
bool g_ShouldLogCommIn;

/** If set to true, the protocols will log each player's outgoing (S->C) communication to a per-connection logfile. */
bool g_ShouldLogCommOut;

/** If set to true, binary will attempt to run as a service. */
bool g_RunAsService;

/** Global that registers itself as a last chance exception handler to write a minidump on crash. */
MiniDumpWriter g_MiniDumpWriter;

// Because SIG_DFL or SIG_IGN could be NULL instead of nullptr, we need to disable the Clang warning here
#ifdef __clang__
	#pragma clang diagnostic push
	#pragma clang diagnostic ignored "-Wunknown-warning-option"
	#pragma clang diagnostic ignored "-Wunknown-pragmas"
	#pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant"
#endif  // __clang__

static void NonCtrlHandler(int a_Signal)
{
	LOGD("Terminate event raised from std::signal");

	switch (a_Signal)
	{
		case SIGSEGV:
		{
			PrintStackTrace();

			LOGERROR(
				"Failure report: \n\n"
				"  :(   | Cuberite has encountered an error and needs to close\n"
				"       | SIGSEGV: Segmentation fault\n"
				"       |\n"
#ifdef BUILD_ID
				"       | Cuberite " BUILD_SERIES_NAME " (id: " BUILD_ID ")\n"
				"       | from commit " BUILD_COMMIT_ID "\n"
#endif
			);

			std::signal(SIGSEGV, SIG_DFL);
			return;
		}
		case SIGABRT:
#ifdef SIGABRT_COMPAT
		case SIGABRT_COMPAT:
#endif
		{
			PrintStackTrace();

			LOGERROR(
				"Failure report: \n\n"
				"  :(   | Cuberite has encountered an error and needs to close\n"
				"       | SIGABRT: Server self-terminated due to an internal fault\n"
				"       |\n"
#ifdef BUILD_ID
				"       | Cuberite " BUILD_SERIES_NAME " (id: " BUILD_ID ")\n"
				"       | from commit " BUILD_COMMIT_ID "\n"
#endif
			);

			std::signal(SIGSEGV, SIG_DFL);
			return;
		}
		case SIGINT:
		case SIGTERM:
		{
			// Server is shutting down, wait for it...
			cRoot::Stop();
			return;
		}
#ifdef SIGPIPE
		case SIGPIPE:
		{
			// Ignore (PR #2487)
			return;
		}
#endif
	}
}

#ifdef __clang__
	#pragma clang diagnostic pop
#endif  // __clang__

#ifdef _WIN32
// Handle CTRL events in windows, including console window close
static BOOL CtrlHandler(DWORD fdwCtrlType)
{
	cRoot::Stop();
	LOGD("Terminate event raised from the Windows CtrlHandler");

	// Delay as much as possible to try to get the server to shut down cleanly - 10 seconds given by Windows
	std::this_thread::sleep_for(std::chrono::seconds(10));

	// Returning from main() automatically aborts this handler thread

	return TRUE;
}
#endif

////////////////////////////////////////////////////////////////////////////////
// ParseArguments - Read the startup arguments and store into a settings object

static cMemorySettingsRepository ParseArguments(int argc, char ** argv)
{
	// Parse the comand line args:
	TCLAP::CmdLine cmd("Cuberite");
	TCLAP::ValueArg<int> slotsArg    ("s", "max-players",         "Maximum number of slots for the server to use, overrides setting in setting.ini", false, -1, "number", cmd);
	TCLAP::ValueArg<AString> confArg ("c", "config-file",         "Config file to use", false, "settings.ini", "string", cmd);
	TCLAP::MultiArg<int> portsArg    ("p", "port",                "The port number the server should listen to", false, "port", cmd);
	TCLAP::SwitchArg commLogArg      ("",  "log-comm",            "Log server client communications to file", cmd);
	TCLAP::SwitchArg commLogInArg    ("",  "log-comm-in",         "Log inbound server client communications to file", cmd);
	TCLAP::SwitchArg commLogOutArg   ("",  "log-comm-out",        "Log outbound server client communications to file", cmd);
	TCLAP::SwitchArg crashDumpFull   ("",  "crash-dump-full",     "Crashdumps created by the server will contain full server memory", cmd);
	TCLAP::SwitchArg crashDumpGlobals("",  "crash-dump-globals",  "Crashdumps created by the server will contain the global variables' values", cmd);
	TCLAP::SwitchArg noBufArg        ("",  "no-output-buffering", "Disable output buffering", cmd);
	TCLAP::SwitchArg noFileLogArg    ("",  "no-log-file",         "Disable logging to file", cmd);
	TCLAP::SwitchArg runAsServiceArg ("d", "service",             "Run as a service on Windows, or daemon on UNIX like systems", cmd);
	cmd.parse(argc, argv);

	// Copy the parsed args' values into a settings repository:
	cMemorySettingsRepository repo;
	if (confArg.isSet())
	{
		AString conf_file = confArg.getValue();
		repo.AddValue("Server", "ConfigFile", conf_file);
	}
	if (slotsArg.isSet())
	{
		int slots = slotsArg.getValue();
		repo.AddValue("Server", "MaxPlayers", static_cast<Int64>(slots));
	}
	if (portsArg.isSet())
	{
		for (auto port: portsArg.getValue())
		{
			repo.AddValue("Server", "Ports", std::to_string(port));
		}
	}
	if (noFileLogArg.getValue())
	{
		repo.AddValue("Server", "DisableLogFile", true);
	}
	if (commLogArg.getValue())
	{
		g_ShouldLogCommIn = true;
		g_ShouldLogCommOut = true;
	}
	else
	{
		g_ShouldLogCommIn = commLogInArg.getValue();
		g_ShouldLogCommOut = commLogOutArg.getValue();
	}
	if (noBufArg.getValue())
	{
		setvbuf(stdout, nullptr, _IONBF, 0);
	}
	repo.SetReadOnly();

	if (runAsServiceArg.getValue())
	{
		g_RunAsService = true;
	}

	// Apply the CrashDump flags for platforms that support them:
	if (crashDumpGlobals.getValue())
	{
		g_MiniDumpWriter.AddDumpFlags(MiniDumpFlags::WithDataSegments);
	}
	if (crashDumpFull.getValue())
	{
		g_MiniDumpWriter.AddDumpFlags(MiniDumpFlags::WithFullMemory);
	}

	return repo;
}

////////////////////////////////////////////////////////////////////////////////
// UniversalMain - Main startup logic for both standard running and as a service

static int UniversalMain(int argc, char * argv[], bool RunningAsService)
{
	// Initialize logging subsystem:
	cLogger::InitiateMultithreading();

	struct NetworkRAII
	{
		NetworkRAII()
		{
			// Initialize LibEvent:
			cNetworkSingleton::Get().Initialise();
		}

		~NetworkRAII()
		{
			// Shutdown all of LibEvent:
			cNetworkSingleton::Get().Terminate();
		}
	};

	try
	{
		// Make sure g_RunAsService is set correctly before checking it's value
		auto Settings = ParseArguments(argc, argv);

		// Attempt to run as a service
		if (!RunningAsService && g_RunAsService)
		{
			// This will either fork or call UniversalMain again:
			if (cStartAsService::MakeIntoService<&UniversalMain>())
			{
				return EXIT_SUCCESS;
			}
		}

		while (true)
		{
			NetworkRAII LibEvent;
			cRoot Root;

			if (!Root.Run(Settings))
			{
				break;
			}
		}

		return EXIT_SUCCESS;
	}
	catch (const fmt::format_error & Oops)
	{
		std::cerr << "Formatting exception: " << Oops.what() << '\n';
	}
	catch (const TCLAP::ArgException & Oops)
	{
		std::cerr << fmt::sprintf("Error reading command line {} for argument {}\n", Oops.error(), Oops.argId());
	}
	catch (const std::exception & Oops)
	{
		std::cerr << "Standard exception: " << Oops.what() << '\n';
	}
	catch (...)
	{
		std::cerr << "Unknown exception!\n";
	}

	return EXIT_FAILURE;
}

int main(int argc, char ** argv)
{
#if !defined(NDEBUG) && defined(_MSC_VER)
	_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);

	// _X: The simple built-in CRT leak finder - simply break when allocating the Nth block ({N} is listed in the leak output)
	// Only useful when the leak is in the same sequence all the time
	// _CrtSetBreakAlloc(85950);

#endif  // _DEBUG && _MSC_VER

	std::signal(SIGSEGV, NonCtrlHandler);
	std::signal(SIGTERM, NonCtrlHandler);
	std::signal(SIGINT,  NonCtrlHandler);
	std::signal(SIGABRT, NonCtrlHandler);
#ifdef SIGABRT_COMPAT
	std::signal(SIGABRT_COMPAT, NonCtrlHandler);
#endif
#ifdef SIGPIPE
	std::signal(SIGPIPE, SIG_IGN);
#endif

#ifdef _WIN32
	VERIFY(SetConsoleCtrlHandler(reinterpret_cast<PHANDLER_ROUTINE>(CtrlHandler), TRUE) == TRUE);
#endif

	return UniversalMain(argc, argv, false);
}
<|endoftext|>


<commit_before>#include <Refal2.h>

using namespace Refal2;

typedef std::vector<std::string> CFileNames;

class CSourceFilesProcessor : private IErrorHandler {
public:
	static CProgramPtr Compile( const CFileNames& fileNames );
	static bool Check( const CFileNames& fileNames );

private:
	CScanner scanner;
	std::ifstream file;

	CSourceFilesProcessor( const CFileNames& fileNames );
	CSourceFilesProcessor( const CSourceFilesProcessor& );
	CSourceFilesProcessor& operator=( const CSourceFilesProcessor& );

	void processFile( const std::string& fileName );

	virtual void Error( const CError& error );
};

CProgramPtr CSourceFilesProcessor::Compile( const CFileNames& fileNames )
{
	CSourceFilesProcessor sourceFilesProcessor( fileNames );
	return sourceFilesProcessor.scanner.BuildProgram();
}

bool CSourceFilesProcessor::Check( const CFileNames& fileNames )
{
	CSourceFilesProcessor sourceFilesProcessor( fileNames );
	return sourceFilesProcessor.scanner.CheckProgram();
}

CSourceFilesProcessor::CSourceFilesProcessor( const CFileNames& fileNames )
{
	scanner.SetErrorHandler( this );
	bool success = true;
	for( CFileNames::const_iterator fileName = fileNames.begin();
		fileName != fileNames.end(); ++fileName )
	{
		processFile( *fileName );
		if( scanner.ErrorSeverity() == ES_FatalError ) {
			break;
		}
	}
}

void CSourceFilesProcessor::processFile( const std::string& fileName )
{
	file.open( fileName );
	if( file.good() ) {
		scanner.SetFileName( fileName );
		for( char c; file.get( c ); ) {
			scanner.AddChar( c );
		}
		if( scanner.ErrorSeverity() != ES_FatalError ) {
			scanner.AddEndOfFile();
		}
	} else {
		std::cerr << "Cannot open file: `" << fileName << "`." << std::endl;
	}
}

void CSourceFilesProcessor::Error( const CError& error )
{
	std::cerr << error.UserMessage() << std::endl;
	if( error.Severity() == ES_FatalError ) {
		file.clear( std::ios_base::eofbit );
	}
}

const char* const ExecutionResultStrings[] = {
	"ok",
	"recognition impossible",
	"call empty function",
	"lost function label",
	"wrong argument of embedded function"
};

const std::string SeparatorLine( 80, '-' );

int main( int argc, const char* argv[] )
{
	std::ios::sync_with_stdio( false );
	if( argc < 2 ) {
		std::cerr << "There are no source files." << std::endl;
		return 1;
	}

	CFileNames fileNames;
	for( int i = 1; i < argc; i++ ) {
		fileNames.push_back( argv[i] );
	}

	CProgramPtr program = CSourceFilesProcessor::Compile( fileNames );
	if( !static_cast<bool>( program ) ) {
		return 1;
	}

    CReceptaclePtr receptacle( new CReceptacle );
	CUnitList fieldOfView;
	CUnitNode* errorNode;
	TExecutionResult result =
		COperationsExecuter::Run( program, receptacle, fieldOfView, errorNode );

	std::cout << SeparatorLine << std::endl;
	std::cout << "Execution result: "
		<< ExecutionResultStrings[result] << "." << std::endl;
	if( !fieldOfView.IsEmpty() ) {
		std::cout << "Field of view: " << std::endl;
		CProgramPrintHelper programPrintHelper( program );
		//programPrintHelper.SetPrintLabelWithModule();
		fieldOfView.HandyPrint( std::cout, programPrintHelper );
	}
	if( !receptacle->IsEmpty() ) {
		if( !fieldOfView.IsEmpty() ) {
			std::cout << SeparatorLine << std::endl;
		}
		std::cout << "Receptacle: " << std::endl;
		CUnitList receptacleUnitList;
		receptacle->DigOutAll( receptacleUnitList );
		CProgramPrintHelper programPrintHelper( program );
		receptacleUnitList.HandyPrint( std::cout, programPrintHelper );
		std::cout << std::endl;
	}
	return 0;
}
<commit_msg>allow stdin as source<commit_after>#include <Refal2.h>

using namespace Refal2;

typedef std::vector<std::string> CFileNames;

class CSourceFilesProcessor : private IErrorHandler {
public:
	static CProgramPtr Compile( const CFileNames& fileNames );
	static bool Check( const CFileNames& fileNames );

private:
	CScanner scanner;
	std::ifstream file;

	CSourceFilesProcessor( const CFileNames& fileNames );
	CSourceFilesProcessor( const CSourceFilesProcessor& );
	CSourceFilesProcessor& operator=( const CSourceFilesProcessor& );

	void processFile( const std::string& fileName );

	virtual void Error( const CError& error );
};

CProgramPtr CSourceFilesProcessor::Compile( const CFileNames& fileNames )
{
	CSourceFilesProcessor sourceFilesProcessor( fileNames );
	return sourceFilesProcessor.scanner.BuildProgram();
}

bool CSourceFilesProcessor::Check( const CFileNames& fileNames )
{
	CSourceFilesProcessor sourceFilesProcessor( fileNames );
	return sourceFilesProcessor.scanner.CheckProgram();
}

CSourceFilesProcessor::CSourceFilesProcessor( const CFileNames& fileNames )
{
	scanner.SetErrorHandler( this );
	if( fileNames.empty() ) {
		for( char c; std::cin.get( c ); ) {
			scanner.AddChar( c );
		}
		if( scanner.ErrorSeverity() != ES_FatalError ) {
			scanner.AddEndOfFile();
		}
	} else {
		for( CFileNames::const_iterator fileName = fileNames.begin();
			fileName != fileNames.end(); ++fileName )
		{
			processFile( *fileName );
			if( scanner.ErrorSeverity() == ES_FatalError ) {
				break;
			}
		}
	}
}

void CSourceFilesProcessor::processFile( const std::string& fileName )
{
	file.open( fileName );
	if( file.good() ) {
		scanner.SetFileName( fileName );
		for( char c; file.get( c ); ) {
			scanner.AddChar( c );
		}
		if( scanner.ErrorSeverity() != ES_FatalError ) {
			scanner.AddEndOfFile();
		}
	} else {
		std::cerr << UtilityName << ": " << fileName
			<< ": No such file" << std::endl;
	}
}

void CSourceFilesProcessor::Error( const CError& error )
{
	std::cerr << error.UserMessage() << std::endl;
	if( error.Severity() == ES_FatalError ) {
		file.clear( std::ios_base::eofbit );
		std::cin.clear( std::ios_base::eofbit );
	}
}

const char* const ExecutionResultStrings[] = {
	"ok",
	"recognition impossible",
	"call empty function",
	"lost function label",
	"wrong argument of embedded function"
};

const std::string SeparatorLine( 80, '-' );

int main( int argc, const char* argv[] )
{
	std::ios::sync_with_stdio( false );

	CFileNames fileNames;
	for( int i = 1; i < argc; i++ ) {
		fileNames.push_back( argv[i] );
	}

	CProgramPtr program = CSourceFilesProcessor::Compile( fileNames );
	if( !static_cast<bool>( program ) ) {
		return 1;
	}

	CReceptaclePtr receptacle( new CReceptacle );
	CUnitList fieldOfView;
	CUnitNode* errorNode;
	TExecutionResult result =
		COperationsExecuter::Run( program, receptacle, fieldOfView, errorNode );

	std::cout << SeparatorLine << std::endl;
	std::cout << "Execution result: "
		<< ExecutionResultStrings[result] << "." << std::endl;
	if( !fieldOfView.IsEmpty() ) {
		std::cout << "Field of view: " << std::endl;
		CProgramPrintHelper programPrintHelper( program );
		//programPrintHelper.SetPrintLabelWithModule();
		fieldOfView.HandyPrint( std::cout, programPrintHelper );
	}
	if( !receptacle->IsEmpty() ) {
		if( !fieldOfView.IsEmpty() ) {
			std::cout << SeparatorLine << std::endl;
		}
		std::cout << "Receptacle: " << std::endl;
		CUnitList receptacleUnitList;
		receptacle->DigOutAll( receptacleUnitList );
		CProgramPrintHelper programPrintHelper( program );
		receptacleUnitList.HandyPrint( std::cout, programPrintHelper );
		std::cout << std::endl;
	}
	return 0;
}
<|endoftext|>


<commit_before>#include <cv.h>
#include <highgui.h>
#include <iostream>
#include <gflags/gflags.h>
#include <cstdlib>

using namespace std;
using namespace cv;

DEFINE_bool(display, true, "Display video in window.");
DEFINE_bool(quiet, false, "Suppress terminal output.");
DEFINE_string(save, "", "Save output to file.");
DEFINE_string(axis, "y", "Axis of rotation.");

enum axis_enum {
    AXIS_X,
    AXIS_Y,
    AXIS_T
};

typedef struct options_struct {
    enum axis_enum axis;
    Size size;
    int frame_count;
    VideoCapture *video_src;
    VideoWriter *video_dst;
} options_type;

options_type * create_options(int *argc, char ***argv) {
    google::ParseCommandLineFlags(argc, argv, true);
    options_type *o = (options_type *) calloc(1, sizeof(options_type));

    if (*argc != 2) {
        cout << "usage: " << *argv[0] << " input-video" << endl;
        free(o);
        return NULL;
    }

    // open input video
    string input_file = (*argv)[(*argc) - 1];
    o->video_src = new VideoCapture(input_file);
    if(!o->video_src->isOpened()) return NULL;

    // get axis
    if (FLAGS_axis == "x") {
        o->axis = AXIS_X;
    } else if (FLAGS_axis == "y") {
        o->axis = AXIS_Y;
    } else if (FLAGS_axis == "t") {
        o->axis = AXIS_T;
    } else {
        free(o);
        return NULL;
    }

    // get size of output video
    int width = o->video_src->get(CV_CAP_PROP_FRAME_WIDTH);
    int height = o->video_src->get(CV_CAP_PROP_FRAME_HEIGHT);
    int frame_count = o->video_src->get(CV_CAP_PROP_FRAME_COUNT);
    if (FLAGS_axis == "x") {
        o->size = Size(width, frame_count);
        o->frame_count = height;
    } else if (FLAGS_axis == "y") {
        o->size = Size(frame_count, height);
        o->frame_count = width;
    } else {
        free(o);
        return NULL;
    }

    // get output video
    if (!FLAGS_save.empty()) {
        o->video_dst = new VideoWriter;
        int ex = CV_FOURCC('I', 'Y', 'U', 'V');
        o->video_dst->open(
                FLAGS_save, ex,
                o->video_src->get(CV_CAP_PROP_FPS),
                o->size);
    }

    return o;

}

int main(int argc, char **argv) {

    options_type *o = create_options(&argc, &argv);

    Mat frame_in;
    *(o->video_src) >> frame_in;
    Mat frame_out(o->size, frame_in.type());

    if (FLAGS_display) {
        namedWindow(argv[0],CV_WINDOW_NORMAL);
        setWindowProperty(argv[0], CV_WND_PROP_FULLSCREEN, CV_WINDOW_FULLSCREEN);
    }

    int frame_count_src = o->video_src->get(CV_CAP_PROP_FRAME_COUNT);
    for (int j = 0; j < o->frame_count; j++) {

        // Output status to console
        if (!FLAGS_quiet)
            cout << "Frame " << j+1 << " of " << o->frame_count << "." << endl;

        // Create a new frame.
        o->video_src->set(CV_CAP_PROP_POS_FRAMES, 0);
        for (int i = 0; i < frame_count_src; i++) {
            *(o->video_src) >> frame_in;
            switch (o->axis) {
                case AXIS_X:
                    frame_in.row(j).copyTo(frame_out.row(i));
                    break;
                case AXIS_Y:
                    frame_in.col(j).copyTo(frame_out.col(i));
                    break;
                default:
                    cout << "UNIMPLEMENTED" << endl;
                    return -1;
            }
        }

        // Display window
        if (FLAGS_display) {
            imshow(argv[0], frame_out);
            waitKey(30);
        }

        // Save frame to file
        if (!FLAGS_save.empty())
            o->video_dst->write(frame_out);

    }

    delete o->video_src;
    delete o->video_dst;
    free(o);

    return 0;
}
<commit_msg>Added fps option, defaults to 24fps<commit_after>#include <cv.h>
#include <highgui.h>
#include <iostream>
#include <gflags/gflags.h>
#include <cstdlib>

using namespace std;
using namespace cv;

DEFINE_bool(display, true, "Display video in window.");
DEFINE_bool(quiet, false, "Suppress terminal output.");
DEFINE_string(save, "", "Save output to file.");
DEFINE_string(axis, "y", "Axis of rotation.");
DEFINE_double(fps, 24, "Frame per second for output.");

enum axis_enum {
    AXIS_X,
    AXIS_Y,
    AXIS_T
};

typedef struct options_struct {
    enum axis_enum axis;
    Size size;
    int frame_count;
    VideoCapture *video_src;
    VideoWriter *video_dst;
} options_type;

options_type * create_options(int *argc, char ***argv) {
    google::ParseCommandLineFlags(argc, argv, true);
    options_type *o = (options_type *) calloc(1, sizeof(options_type));

    if (*argc != 2) {
        cout << "usage: " << *argv[0] << " input-video" << endl;
        free(o);
        return NULL;
    }

    // open input video
    string input_file = (*argv)[(*argc) - 1];
    o->video_src = new VideoCapture(input_file);
    if(!o->video_src->isOpened()) return NULL;

    // get axis
    if (FLAGS_axis == "x") {
        o->axis = AXIS_X;
    } else if (FLAGS_axis == "y") {
        o->axis = AXIS_Y;
    } else if (FLAGS_axis == "t") {
        o->axis = AXIS_T;
    } else {
        free(o);
        return NULL;
    }

    // get size of output video
    int width = o->video_src->get(CV_CAP_PROP_FRAME_WIDTH);
    int height = o->video_src->get(CV_CAP_PROP_FRAME_HEIGHT);
    int frame_count = o->video_src->get(CV_CAP_PROP_FRAME_COUNT);
    if (FLAGS_axis == "x") {
        o->size = Size(width, frame_count);
        o->frame_count = height;
    } else if (FLAGS_axis == "y") {
        o->size = Size(frame_count, height);
        o->frame_count = width;
    } else {
        free(o);
        return NULL;
    }

    // get output video
    if (!FLAGS_save.empty()) {
        o->video_dst = new VideoWriter;
        int ex = CV_FOURCC('I', 'Y', 'U', 'V');
        o->video_dst->open(FLAGS_save, ex, FLAGS_fps, o->size);
    }

    return o;

}

int main(int argc, char **argv) {

    options_type *o = create_options(&argc, &argv);

    Mat frame_in;
    *(o->video_src) >> frame_in;
    Mat frame_out(o->size, frame_in.type());

    if (FLAGS_display) {
        namedWindow(argv[0],CV_WINDOW_NORMAL);
        setWindowProperty(argv[0], CV_WND_PROP_FULLSCREEN, CV_WINDOW_FULLSCREEN);
    }

    int frame_count_src = o->video_src->get(CV_CAP_PROP_FRAME_COUNT);
    for (int j = 0; j < o->frame_count; j++) {

        // Output status to console
        if (!FLAGS_quiet)
            cout << "Frame " << j+1 << " of " << o->frame_count << "." << endl;

        // Create a new frame.
        o->video_src->set(CV_CAP_PROP_POS_FRAMES, 0);
        for (int i = 0; i < frame_count_src; i++) {
            *(o->video_src) >> frame_in;
            switch (o->axis) {
                case AXIS_X:
                    frame_in.row(j).copyTo(frame_out.row(i));
                    break;
                case AXIS_Y:
                    frame_in.col(j).copyTo(frame_out.col(i));
                    break;
                default:
                    cout << "UNIMPLEMENTED" << endl;
                    return -1;
            }
        }

        // Display window
        if (FLAGS_display) {
            imshow(argv[0], frame_out);
            waitKey(30);
        }

        // Save frame to file
        if (!FLAGS_save.empty())
            o->video_dst->write(frame_out);

    }

    delete o->video_src;
    delete o->video_dst;
    free(o);

    return 0;
}
<|endoftext|>