<commit_before>#include "operator.h"

#include <QPushButton>
#include <QJsonObject>
#include <QJsonDocument>
#include <QStandardPaths>

Operator::Operator(AdvancedView *advancedView, BasicView *basicView, CommandRunner *commandRunner,
                   ErrorMessage *errorMessage, ProgressWindow *progressWindow, Tray *tray,
                   HyperKit *hyperKit, Updater *updater, QStackedWidget *stackedWidget,
                   QDialog *parent)
{
    m_advancedView = advancedView;
    m_basicView = basicView;
    m_commandRunner = commandRunner;
    m_errorMessage = errorMessage;
    m_progressWindow = progressWindow;
    m_tray = tray;
    m_hyperKit = hyperKit;
    m_updater = updater;
    m_stackedWidget = stackedWidget;
    m_parent = parent;
    m_isBasicView = true;

    connect(m_basicView, &BasicView::start, this, &Operator::startMinikube);
    connect(m_basicView, &BasicView::stop, this, &Operator::stopMinikube);
    connect(m_basicView, &BasicView::pause, this, &Operator::pauseOrUnpauseMinikube);
    connect(m_basicView, &BasicView::delete_, this, &Operator::deleteMinikube);
    connect(m_basicView, &BasicView::refresh, this, &Operator::updateClusters);
    connect(m_basicView, &BasicView::dockerEnv, this, &Operator::dockerEnv);
    connect(m_basicView, &BasicView::ssh, this, &Operator::sshConsole);
    connect(m_basicView, &BasicView::dashboard, this, &Operator::dashboardBrowser);
    connect(m_basicView, &BasicView::advanced, this, &Operator::toAdvancedView);

    connect(m_advancedView, &AdvancedView::start, this, &Operator::startMinikube);
    connect(m_advancedView, &AdvancedView::stop, this, &Operator::stopMinikube);
    connect(m_advancedView, &AdvancedView::pause, this, &Operator::pauseOrUnpauseMinikube);
    connect(m_advancedView, &AdvancedView::delete_, this, &Operator::deleteMinikube);
    connect(m_advancedView, &AdvancedView::refresh, this, &Operator::updateClusters);
    connect(m_advancedView, &AdvancedView::dockerEnv, this, &Operator::dockerEnv);
    connect(m_advancedView, &AdvancedView::ssh, this, &Operator::sshConsole);
    connect(m_advancedView, &AdvancedView::dashboard, this, &Operator::dashboardBrowser);
    connect(m_advancedView, &AdvancedView::basic, this, &Operator::toBasicView);
    connect(m_advancedView, &AdvancedView::createCluster, this, &Operator::createCluster);
    connect(m_advancedView->clusterListView, SIGNAL(clicked(QModelIndex)), this,
            SLOT(updateButtons()));

    connect(m_commandRunner, &CommandRunner::startingExecution, this, &Operator::commandStarting);
    connect(m_commandRunner, &CommandRunner::executionEnded, this, &Operator::commandEnding);
    connect(m_commandRunner, &CommandRunner::output, this, &Operator::commandOutput);
    connect(m_commandRunner, &CommandRunner::error, this, &Operator::commandError);
    connect(m_commandRunner, &CommandRunner::updatedClusters, this, &Operator::clustersReceived);
    connect(m_commandRunner, &CommandRunner::startCommandStarting, this,
            &Operator::startCommandStarting);

    connect(m_progressWindow, &ProgressWindow::cancelled, this, &Operator::cancelCommand);

    connect(m_tray, &Tray::restoreWindow, this, &Operator::restoreWindow);
    connect(m_tray, &Tray::hideWindow, this, &Operator::hideWindow);
    connect(m_tray, &Tray::start, this, &Operator::startMinikube);
    connect(m_tray, &Tray::stop, this, &Operator::stopMinikube);
    connect(m_tray, &Tray::pauseOrUnpause, this, &Operator::pauseOrUnpauseMinikube);

    connect(m_hyperKit, &HyperKit::rerun, this, &Operator::createCluster);

    updateClusters();
}

QStringList Operator::getCurrentClusterFlags()
{
    return { "-p", selectedClusterName() };
}

void Operator::startMinikube()
{
    m_commandRunner->startMinikube(getCurrentClusterFlags());
}

void Operator::stopMinikube()
{
    m_commandRunner->stopMinikube(getCurrentClusterFlags());
}

void Operator::pauseOrUnpauseMinikube()
{
    Cluster cluster = selectedCluster();
    if (cluster.status() == "Paused") {
        unpauseMinikube();
        return;
    }
    pauseMinikube();
}

void Operator::pauseMinikube()
{
    m_commandRunner->pauseMinikube(getCurrentClusterFlags());
}

void Operator::unpauseMinikube()
{
    m_commandRunner->unpauseMinikube(getCurrentClusterFlags());
}

void Operator::deleteMinikube()
{
    m_commandRunner->deleteMinikube(getCurrentClusterFlags());
}

void Operator::createCluster(QStringList args)
{
    m_commandRunner->startMinikube(args);
}

void Operator::startCommandStarting()
{
    commandStarting();
    m_progressWindow->setText("Starting...");
    m_progressWindow->show();
}

void Operator::commandStarting()
{
    m_advancedView->showLoading();
    m_tray->disableActions();
    m_parent->setCursor(Qt::WaitCursor);
    disableButtons();
}

void Operator::disableButtons()
{
    if (m_isBasicView) {
        m_basicView->disableButtons();
    } else {
        m_advancedView->disableButtons();
    }
}

void Operator::commandEnding()
{
    m_progressWindow->done();
    updateClusters();
}

void Operator::toAdvancedView()
{
    m_isBasicView = false;
    m_stackedWidget->setCurrentIndex(1);
    m_parent->resize(670, 400);
    updateButtons();
}

void Operator::toBasicView()
{
    m_isBasicView = true;
    m_stackedWidget->setCurrentIndex(0);
    m_parent->resize(200, 300);
    updateButtons();
}

void Operator::updateClusters()
{
    m_commandRunner->requestClusters();
}

void Operator::clustersReceived(ClusterList clusterList)
{
    m_clusterList = clusterList;
    m_advancedView->updateClustersTable(m_clusterList);
    updateButtons();
    m_advancedView->hideLoading();
    m_parent->unsetCursor();
    m_updater->checkForUpdates();
}

void Operator::updateButtons()
{
    Cluster cluster = selectedCluster();
    if (m_isBasicView) {
        m_basicView->update(cluster);
    } else {
        m_advancedView->update(cluster);
    }
    m_tray->updateTrayActions(cluster);
    m_tray->updateStatus(cluster);
}

void Operator::restoreWindow()
{
    bool wasVisible = m_parent->isVisible();
    m_parent->showNormal();
    m_parent->activateWindow();
    if (wasVisible) {
        return;
    }
    if (m_commandRunner->isRunning())
        return;
    updateClusters();
}

void Operator::hideWindow()
{
    m_parent->hide();
}

void Operator::commandOutput(QString text)
{
    QStringList lines;
#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
    lines = text.split("\n", Qt::SkipEmptyParts);
#else
    lines = text.split("\n", QString::SkipEmptyParts);
#endif
    for (int i = 0; i < lines.size(); i++) {
        QJsonDocument json = QJsonDocument::fromJson(lines[i].toUtf8());
        QJsonObject object = json.object();
        QString type = object["type"].toString();
        if (type != "io.k8s.sigs.minikube.step") {
            return;
        }
        QJsonObject data = object["data"].toObject();
        QString stringStep = data["currentstep"].toString();
        int currStep = stringStep.toInt();
        QString totalString = data["totalsteps"].toString();
        int totalSteps = totalString.toInt();
        QString message = data["message"].toString();
        m_progressWindow->setBarMaximum(totalSteps);
        m_progressWindow->setBarValue(currStep);
        m_progressWindow->setText(message);
    }
}

void Operator::commandError(QStringList args, QString text)
{
#if __APPLE__
    if (m_hyperKit->hyperkitPermissionFix(args, text)) {
        return;
    }
#endif
    QStringList lines;
#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
    lines = text.split("\n", Qt::SkipEmptyParts);
#else
    lines = text.split("\n", QString::SkipEmptyParts);
#endif
    for (int i = 0; i < lines.size(); i++) {
        QString line = lines.at(i);
        QJsonParseError error;
        QJsonDocument json = QJsonDocument::fromJson(line.toUtf8(), &error);
        if (json.isNull() || !json.isObject()) {
            continue;
        }
        QJsonObject par = json.object();
        QJsonObject data = par["data"].toObject();
        if (!data.contains("exitcode")) {
            continue;
        }
        QString advice = data["advice"].toString();
        QString message = data["message"].toString();
        QString name = data["name"].toString();
        QString url = data["url"].toString();
        QString issues = data["issues"].toString();

        m_errorMessage->error(name, advice, message, url, issues);
        break;
    }
}

void Operator::cancelCommand()
{
    m_commandRunner->stopCommand();
}

QString Operator::selectedClusterName()
{
    if (m_isBasicView) {
        return "minikube";
    }
    return m_advancedView->selectedClusterName();
}

Cluster Operator::selectedCluster()
{
    QString clusterName = selectedClusterName();
    if (clusterName.isEmpty()) {
        return Cluster();
    }
    ClusterList clusters = m_clusterList;
    ClusterHash clusterHash;
    for (int i = 0; i < clusters.size(); i++) {
        Cluster cluster = clusters.at(i);
        clusterHash[cluster.name()] = cluster;
    }
    return clusterHash[clusterName];
}

static QString minikubePath()
{
    QString minikubePath = QStandardPaths::findExecutable("minikube");
    if (!minikubePath.isEmpty()) {
        return minikubePath;
    }
    QStringList path = { "/usr/local/bin" };
    return QStandardPaths::findExecutable("minikube", path);
}

void Operator::sshConsole()
{
    QString program = minikubePath();
    QString commandArgs = QString("ssh -p %1").arg(selectedClusterName());
    QString command = QString("%1 %2").arg(program, commandArgs);
#ifndef QT_NO_TERMWIDGET
    QMainWindow *mainWindow = new QMainWindow();
    int startnow = 0; // set shell program first

    QTermWidget *console = new QTermWidget(startnow);

    QFont font = QApplication::font();
    font.setFamily("Monospace");
    font.setPointSize(10);

    console->setTerminalFont(font);
    console->setColorScheme("Tango");
    console->setShellProgram(program);
    console->setArgs({ commandArgs });
    console->startShellProgram();

    QObject::connect(console, SIGNAL(finished()), mainWindow, SLOT(close()));

    mainWindow->setWindowTitle(nameLabel->text());
    mainWindow->resize(800, 400);
    mainWindow->setCentralWidget(console);
    mainWindow->show();
#elif __APPLE__
    QStringList arguments = { "-e", "tell app \"Terminal\"",
                              "-e", "do script \"" + command + "\"",
                              "-e", "activate",
                              "-e", "end tell" };
    QProcess *process = new QProcess(this);
    process->start("/usr/bin/osascript", arguments);
#else
    QString terminal = qEnvironmentVariable("TERMINAL");
    if (terminal.isEmpty()) {
        terminal = "x-terminal-emulator";
        if (QStandardPaths::findExecutable(terminal).isEmpty()) {
            terminal = "xterm";
        }
    }

    QProcess *process = new QProcess(this);
    process->start(QStandardPaths::findExecutable(terminal), { "-e", commmand });
#endif
}

void Operator::dockerEnv()
{
    QString program = minikubePath();
    QString commandArgs = QString("$(%1 -p %2 docker-env)").arg(program, selectedClusterName());
    QString command = QString("eval %1").arg(commandArgs);
#ifndef QT_NO_TERMWIDGET
    QMainWindow *mainWindow = new QMainWindow();
    int startnow = 0; // set shell program first

    QTermWidget *console = new QTermWidget(startnow);

    QFont font = QApplication::font();
    font.setFamily("Monospace");
    font.setPointSize(10);

    console->setTerminalFont(font);
    console->setColorScheme("Tango");
    console->setShellProgram("eval");
    console->setArgs({ commandArgs });
    console->startShellProgram();

    QObject::connect(console, SIGNAL(finished()), mainWindow, SLOT(close()));

    mainWindow->setWindowTitle(nameLabel->text());
    mainWindow->resize(800, 400);
    mainWindow->setCentralWidget(console);
    mainWindow->show();
#elif __APPLE__
    QStringList arguments = { "-e", "tell app \"Terminal\"",
                              "-e", "do script \"" + command + "\"",
                              "-e", "activate",
                              "-e", "end tell" };
    QProcess *process = new QProcess(this);
    process->start("/usr/bin/osascript", arguments);
#else
    QString terminal = qEnvironmentVariable("TERMINAL");
    if (terminal.isEmpty()) {
        terminal = "x-terminal-emulator";
        if (QStandardPaths::findExecutable(terminal).isEmpty()) {
            terminal = "xterm";
        }
    }

    QProcess *process = new QProcess(this);
    process->start(QStandardPaths::findExecutable(terminal), { "-e", command });
#endif
}

void Operator::dashboardBrowser()
{
    dashboardClose();

    QString program = minikubePath();
    QProcess *process = new QProcess(this);
    QStringList arguments = { "dashboard", "-p", selectedClusterName() };
    process->start(program, arguments);

    dashboardProcess = process;
    dashboardProcess->waitForStarted();
}

void Operator::dashboardClose()
{
    if (dashboardProcess) {
        dashboardProcess->terminate();
        dashboardProcess->waitForFinished();
    }
}
<commit_msg>fix GUI build for Linux & Windows<commit_after>#include "operator.h"

#include <QPushButton>
#include <QJsonObject>
#include <QJsonDocument>
#include <QStandardPaths>

Operator::Operator(AdvancedView *advancedView, BasicView *basicView, CommandRunner *commandRunner,
                   ErrorMessage *errorMessage, ProgressWindow *progressWindow, Tray *tray,
                   HyperKit *hyperKit, Updater *updater, QStackedWidget *stackedWidget,
                   QDialog *parent)
{
    m_advancedView = advancedView;
    m_basicView = basicView;
    m_commandRunner = commandRunner;
    m_errorMessage = errorMessage;
    m_progressWindow = progressWindow;
    m_tray = tray;
    m_hyperKit = hyperKit;
    m_updater = updater;
    m_stackedWidget = stackedWidget;
    m_parent = parent;
    m_isBasicView = true;

    connect(m_basicView, &BasicView::start, this, &Operator::startMinikube);
    connect(m_basicView, &BasicView::stop, this, &Operator::stopMinikube);
    connect(m_basicView, &BasicView::pause, this, &Operator::pauseOrUnpauseMinikube);
    connect(m_basicView, &BasicView::delete_, this, &Operator::deleteMinikube);
    connect(m_basicView, &BasicView::refresh, this, &Operator::updateClusters);
    connect(m_basicView, &BasicView::dockerEnv, this, &Operator::dockerEnv);
    connect(m_basicView, &BasicView::ssh, this, &Operator::sshConsole);
    connect(m_basicView, &BasicView::dashboard, this, &Operator::dashboardBrowser);
    connect(m_basicView, &BasicView::advanced, this, &Operator::toAdvancedView);

    connect(m_advancedView, &AdvancedView::start, this, &Operator::startMinikube);
    connect(m_advancedView, &AdvancedView::stop, this, &Operator::stopMinikube);
    connect(m_advancedView, &AdvancedView::pause, this, &Operator::pauseOrUnpauseMinikube);
    connect(m_advancedView, &AdvancedView::delete_, this, &Operator::deleteMinikube);
    connect(m_advancedView, &AdvancedView::refresh, this, &Operator::updateClusters);
    connect(m_advancedView, &AdvancedView::dockerEnv, this, &Operator::dockerEnv);
    connect(m_advancedView, &AdvancedView::ssh, this, &Operator::sshConsole);
    connect(m_advancedView, &AdvancedView::dashboard, this, &Operator::dashboardBrowser);
    connect(m_advancedView, &AdvancedView::basic, this, &Operator::toBasicView);
    connect(m_advancedView, &AdvancedView::createCluster, this, &Operator::createCluster);
    connect(m_advancedView->clusterListView, SIGNAL(clicked(QModelIndex)), this,
            SLOT(updateButtons()));

    connect(m_commandRunner, &CommandRunner::startingExecution, this, &Operator::commandStarting);
    connect(m_commandRunner, &CommandRunner::executionEnded, this, &Operator::commandEnding);
    connect(m_commandRunner, &CommandRunner::output, this, &Operator::commandOutput);
    connect(m_commandRunner, &CommandRunner::error, this, &Operator::commandError);
    connect(m_commandRunner, &CommandRunner::updatedClusters, this, &Operator::clustersReceived);
    connect(m_commandRunner, &CommandRunner::startCommandStarting, this,
            &Operator::startCommandStarting);

    connect(m_progressWindow, &ProgressWindow::cancelled, this, &Operator::cancelCommand);

    connect(m_tray, &Tray::restoreWindow, this, &Operator::restoreWindow);
    connect(m_tray, &Tray::hideWindow, this, &Operator::hideWindow);
    connect(m_tray, &Tray::start, this, &Operator::startMinikube);
    connect(m_tray, &Tray::stop, this, &Operator::stopMinikube);
    connect(m_tray, &Tray::pauseOrUnpause, this, &Operator::pauseOrUnpauseMinikube);

    connect(m_hyperKit, &HyperKit::rerun, this, &Operator::createCluster);

    updateClusters();
}

QStringList Operator::getCurrentClusterFlags()
{
    return { "-p", selectedClusterName() };
}

void Operator::startMinikube()
{
    m_commandRunner->startMinikube(getCurrentClusterFlags());
}

void Operator::stopMinikube()
{
    m_commandRunner->stopMinikube(getCurrentClusterFlags());
}

void Operator::pauseOrUnpauseMinikube()
{
    Cluster cluster = selectedCluster();
    if (cluster.status() == "Paused") {
        unpauseMinikube();
        return;
    }
    pauseMinikube();
}

void Operator::pauseMinikube()
{
    m_commandRunner->pauseMinikube(getCurrentClusterFlags());
}

void Operator::unpauseMinikube()
{
    m_commandRunner->unpauseMinikube(getCurrentClusterFlags());
}

void Operator::deleteMinikube()
{
    m_commandRunner->deleteMinikube(getCurrentClusterFlags());
}

void Operator::createCluster(QStringList args)
{
    m_commandRunner->startMinikube(args);
}

void Operator::startCommandStarting()
{
    commandStarting();
    m_progressWindow->setText("Starting...");
    m_progressWindow->show();
}

void Operator::commandStarting()
{
    m_advancedView->showLoading();
    m_tray->disableActions();
    m_parent->setCursor(Qt::WaitCursor);
    disableButtons();
}

void Operator::disableButtons()
{
    if (m_isBasicView) {
        m_basicView->disableButtons();
    } else {
        m_advancedView->disableButtons();
    }
}

void Operator::commandEnding()
{
    m_progressWindow->done();
    updateClusters();
}

void Operator::toAdvancedView()
{
    m_isBasicView = false;
    m_stackedWidget->setCurrentIndex(1);
    m_parent->resize(670, 400);
    updateButtons();
}

void Operator::toBasicView()
{
    m_isBasicView = true;
    m_stackedWidget->setCurrentIndex(0);
    m_parent->resize(200, 300);
    updateButtons();
}

void Operator::updateClusters()
{
    m_commandRunner->requestClusters();
}

void Operator::clustersReceived(ClusterList clusterList)
{
    m_clusterList = clusterList;
    m_advancedView->updateClustersTable(m_clusterList);
    updateButtons();
    m_advancedView->hideLoading();
    m_parent->unsetCursor();
    m_updater->checkForUpdates();
}

void Operator::updateButtons()
{
    Cluster cluster = selectedCluster();
    if (m_isBasicView) {
        m_basicView->update(cluster);
    } else {
        m_advancedView->update(cluster);
    }
    m_tray->updateTrayActions(cluster);
    m_tray->updateStatus(cluster);
}

void Operator::restoreWindow()
{
    bool wasVisible = m_parent->isVisible();
    m_parent->showNormal();
    m_parent->activateWindow();
    if (wasVisible) {
        return;
    }
    if (m_commandRunner->isRunning())
        return;
    updateClusters();
}

void Operator::hideWindow()
{
    m_parent->hide();
}

void Operator::commandOutput(QString text)
{
    QStringList lines;
#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
    lines = text.split("\n", Qt::SkipEmptyParts);
#else
    lines = text.split("\n", QString::SkipEmptyParts);
#endif
    for (int i = 0; i < lines.size(); i++) {
        QJsonDocument json = QJsonDocument::fromJson(lines[i].toUtf8());
        QJsonObject object = json.object();
        QString type = object["type"].toString();
        if (type != "io.k8s.sigs.minikube.step") {
            return;
        }
        QJsonObject data = object["data"].toObject();
        QString stringStep = data["currentstep"].toString();
        int currStep = stringStep.toInt();
        QString totalString = data["totalsteps"].toString();
        int totalSteps = totalString.toInt();
        QString message = data["message"].toString();
        m_progressWindow->setBarMaximum(totalSteps);
        m_progressWindow->setBarValue(currStep);
        m_progressWindow->setText(message);
    }
}

void Operator::commandError(QStringList args, QString text)
{
#if __APPLE__
    if (m_hyperKit->hyperkitPermissionFix(args, text)) {
        return;
    }
#endif
    QStringList lines;
#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
    lines = text.split("\n", Qt::SkipEmptyParts);
#else
    lines = text.split("\n", QString::SkipEmptyParts);
#endif
    for (int i = 0; i < lines.size(); i++) {
        QString line = lines.at(i);
        QJsonParseError error;
        QJsonDocument json = QJsonDocument::fromJson(line.toUtf8(), &error);
        if (json.isNull() || !json.isObject()) {
            continue;
        }
        QJsonObject par = json.object();
        QJsonObject data = par["data"].toObject();
        if (!data.contains("exitcode")) {
            continue;
        }
        QString advice = data["advice"].toString();
        QString message = data["message"].toString();
        QString name = data["name"].toString();
        QString url = data["url"].toString();
        QString issues = data["issues"].toString();

        m_errorMessage->error(name, advice, message, url, issues);
        break;
    }
}

void Operator::cancelCommand()
{
    m_commandRunner->stopCommand();
}

QString Operator::selectedClusterName()
{
    if (m_isBasicView) {
        return "minikube";
    }
    return m_advancedView->selectedClusterName();
}

Cluster Operator::selectedCluster()
{
    QString clusterName = selectedClusterName();
    if (clusterName.isEmpty()) {
        return Cluster();
    }
    ClusterList clusters = m_clusterList;
    ClusterHash clusterHash;
    for (int i = 0; i < clusters.size(); i++) {
        Cluster cluster = clusters.at(i);
        clusterHash[cluster.name()] = cluster;
    }
    return clusterHash[clusterName];
}

static QString minikubePath()
{
    QString minikubePath = QStandardPaths::findExecutable("minikube");
    if (!minikubePath.isEmpty()) {
        return minikubePath;
    }
    QStringList path = { "/usr/local/bin" };
    return QStandardPaths::findExecutable("minikube", path);
}

void Operator::sshConsole()
{
    QString program = minikubePath();
    QString commandArgs = QString("ssh -p %1").arg(selectedClusterName());
    QString command = QString("%1 %2").arg(program, commandArgs);
#ifndef QT_NO_TERMWIDGET
    QMainWindow *mainWindow = new QMainWindow();
    int startnow = 0; // set shell program first

    QTermWidget *console = new QTermWidget(startnow);

    QFont font = QApplication::font();
    font.setFamily("Monospace");
    font.setPointSize(10);

    console->setTerminalFont(font);
    console->setColorScheme("Tango");
    console->setShellProgram(program);
    console->setArgs({ commandArgs });
    console->startShellProgram();

    QObject::connect(console, SIGNAL(finished()), mainWindow, SLOT(close()));

    mainWindow->setWindowTitle(nameLabel->text());
    mainWindow->resize(800, 400);
    mainWindow->setCentralWidget(console);
    mainWindow->show();
#elif __APPLE__
    QStringList arguments = { "-e", "tell app \"Terminal\"",
                              "-e", "do script \"" + command + "\"",
                              "-e", "activate",
                              "-e", "end tell" };
    QProcess *process = new QProcess(this);
    process->start("/usr/bin/osascript", arguments);
#else
    QString terminal = qEnvironmentVariable("TERMINAL");
    if (terminal.isEmpty()) {
        terminal = "x-terminal-emulator";
        if (QStandardPaths::findExecutable(terminal).isEmpty()) {
            terminal = "xterm";
        }
    }

    QProcess *process = new QProcess(this);
    process->start(QStandardPaths::findExecutable(terminal), { "-e", command });
#endif
}

void Operator::dockerEnv()
{
    QString program = minikubePath();
    QString commandArgs = QString("$(%1 -p %2 docker-env)").arg(program, selectedClusterName());
    QString command = QString("eval %1").arg(commandArgs);
#ifndef QT_NO_TERMWIDGET
    QMainWindow *mainWindow = new QMainWindow();
    int startnow = 0; // set shell program first

    QTermWidget *console = new QTermWidget(startnow);

    QFont font = QApplication::font();
    font.setFamily("Monospace");
    font.setPointSize(10);

    console->setTerminalFont(font);
    console->setColorScheme("Tango");
    console->setShellProgram("eval");
    console->setArgs({ commandArgs });
    console->startShellProgram();

    QObject::connect(console, SIGNAL(finished()), mainWindow, SLOT(close()));

    mainWindow->setWindowTitle(nameLabel->text());
    mainWindow->resize(800, 400);
    mainWindow->setCentralWidget(console);
    mainWindow->show();
#elif __APPLE__
    QStringList arguments = { "-e", "tell app \"Terminal\"",
                              "-e", "do script \"" + command + "\"",
                              "-e", "activate",
                              "-e", "end tell" };
    QProcess *process = new QProcess(this);
    process->start("/usr/bin/osascript", arguments);
#else
    QString terminal = qEnvironmentVariable("TERMINAL");
    if (terminal.isEmpty()) {
        terminal = "x-terminal-emulator";
        if (QStandardPaths::findExecutable(terminal).isEmpty()) {
            terminal = "xterm";
        }
    }

    QProcess *process = new QProcess(this);
    process->start(QStandardPaths::findExecutable(terminal), { "-e", command });
#endif
}

void Operator::dashboardBrowser()
{
    dashboardClose();

    QString program = minikubePath();
    QProcess *process = new QProcess(this);
    QStringList arguments = { "dashboard", "-p", selectedClusterName() };
    process->start(program, arguments);

    dashboardProcess = process;
    dashboardProcess->waitForStarted();
}

void Operator::dashboardClose()
{
    if (dashboardProcess) {
        dashboardProcess->terminate();
        dashboardProcess->waitForFinished();
    }
}
<|endoftext|>


<commit_before>// @(#)root/g3d:$Name:  $:$Id: TTUBE.cxx,v 1.6 2004/09/14 15:15:46 brun Exp $
// Author: Nenad Buncic   18/09/95

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#include "TTUBE.h"
#include "TNode.h"
#include "TVirtualPad.h"
#include "TBuffer3D.h"
#include "TGeometry.h"

ClassImp(TTUBE)

//______________________________________________________________________________
// Begin_Html

 End_Html
// TUBE is a tube. It has 6 parameters:
//
//     - name       name of the shape
//     - title      shape's title
//     - material  (see TMaterial)
//     - rmin       inside radius
//     - rmax       outside radius
//     - dz         half length in z

//______________________________________________________________________________
TTUBE::TTUBE()
{
   // TUBE shape default constructor

   fCoTab = 0;
   fSiTab = 0;
   fAspectRatio =1;
}

//______________________________________________________________________________
TTUBE::TTUBE(const char *name, const char *title, const char *material, Float_t rmin, Float_t rmax, Float_t dz,Float_t aspect)
      : TShape(name, title,material)
{
   // TUBE shape normal constructor

   fRmin  = rmin;
   fRmax  = rmax;

   fDz   = dz;
   fNdiv = 0;

   fCoTab = 0;
   fSiTab = 0;

   fAspectRatio = aspect;

   MakeTableOfCoSin();
}

//______________________________________________________________________________
TTUBE::TTUBE(const char *name, const char *title, const char *material, Float_t rmax, Float_t dz)
      : TShape(name, title,material)
{
   // TUBE shape "simplified" constructor

   fRmin  = 0;
   fRmax  = rmax;

   fDz   = dz;
   fNdiv = 0;

   fCoTab = 0;
   fSiTab = 0;

   fAspectRatio = 1;

   MakeTableOfCoSin();
}

//______________________________________________________________________________
void TTUBE::MakeTableOfCoSin()
{
   const Double_t PI  = TMath::ATan(1) * 4.0;
   const Double_t TWOPI  =2*PI;

   Int_t j;
   Int_t n = GetNumberOfDivisions ();
   if (fCoTab)
      delete [] fCoTab; // Delete the old tab if any
      fCoTab = new Double_t [n];
   if (!fCoTab ) {
      Error("MakeTableOfCoSin()","No cos table done");
      return;
   }

   if (fSiTab) delete [] fSiTab; // Delete the old tab if any
   fSiTab = new Double_t [n];
   if (!fSiTab ) {
      Error("MakeTableOfCoSin()","No sin table done");
      return;
   }

   Double_t range = TWOPI;

   Double_t angstep = range/n;

   Double_t ph = 0;
   for (j = 0; j < n; j++) {
      ph = j*angstep;
      fCoTab[j] = TMath::Cos(ph);
      fSiTab[j] = TMath::Sin(ph);
   }
}

//______________________________________________________________________________
TTUBE::~TTUBE()
{
   // TUBE shape default destructor

   delete [] fCoTab;
   delete [] fSiTab;
}

//______________________________________________________________________________
Int_t TTUBE::DistancetoPrimitive(Int_t px, Int_t py)
{
   // Compute distance from point px,py to a TUBE
   //
   // Compute the closest distance of approach from point px,py to each
   // computed outline point of the TUBE.

   Int_t n = GetNumberOfDivisions();
   Int_t numPoints = n*4;
   return ShapeDistancetoPrimitive(numPoints,px,py);
}

//______________________________________________________________________________
void TTUBE::Paint(Option_t *option)
{
   // Paint this 3-D shape with its current attributes

   Int_t i, j, indx;
   Int_t n = GetNumberOfDivisions();
   Int_t NbPnts = 4*n;
   Int_t NbSegs = 8*n;
   Int_t NbPols = 4*n;
   TBuffer3D *buff = gPad->AllocateBuffer3D(3*NbPnts, 3*NbSegs, 6*NbPols);
   if (!buff) return;

   buff->fType = TBuffer3D::kTUBE;
   buff->fId   = this;

   // Fill gPad->fBuffer3D. Points coordinates are in Master space
   buff->fNbPnts = NbPnts;
   buff->fNbSegs = NbSegs;
   buff->fNbPols = NbPols;
   // In case of option "size" it is not necessary to fill the buffer
   if (buff->fOption == TBuffer3D::kSIZE) {
      buff->Paint(option);
      return;
   }

   SetPoints(buff->fPnts);

   TransformPoints(buff);

   // Basic colors: 0, 1, ... 7
   buff->fColor = GetLineColor();
   Int_t c = (((buff->fColor) %8) -1) * 4;
   if (c < 0) c = 0;

   for (i = 0; i < 4; i++) {
      for (j = 0; j < n; j++) {
         buff->fSegs[(i*n+j)*3  ] = c;
         buff->fSegs[(i*n+j)*3+1] = i*n+j;
         buff->fSegs[(i*n+j)*3+2] = i*n+j+1;
      }
      buff->fSegs[(i*n+j-1)*3+2] = i*n;
   }
   for (i = 4; i < 6; i++) {
      for (j = 0; j < n; j++) {
         buff->fSegs[(i*n+j)*3  ] = c+1;
         buff->fSegs[(i*n+j)*3+1] = (i-4)*n+j;
         buff->fSegs[(i*n+j)*3+2] = (i-2)*n+j;
      }
   }
   for (i = 6; i < 8; i++) {
      for (j = 0; j < n; j++) {
         buff->fSegs[(i*n+j)*3  ] = c;
         buff->fSegs[(i*n+j)*3+1] = 2*(i-6)*n+j;
         buff->fSegs[(i*n+j)*3+2] = (2*(i-6)+1)*n+j;
      }
   }

   indx = 0;
   i=0;
   for (j = 0; j < n; j++) {
      indx = 6*(i*n+j);
      buff->fPols[indx  ] = c;
      buff->fPols[indx+1] = 4;
      buff->fPols[indx+5] = i*n+j;
      buff->fPols[indx+4] = (4+i)*n+j;
      buff->fPols[indx+3] = (2+i)*n+j;
      buff->fPols[indx+2] = (4+i)*n+j+1;
   }
   buff->fPols[indx+2] = (4+i)*n;
   i=1;
   for (j = 0; j < n; j++) {
      indx = 6*(i*n+j);
      buff->fPols[indx  ] = c;
      buff->fPols[indx+1] = 4;
      buff->fPols[indx+2] = i*n+j;
      buff->fPols[indx+3] = (4+i)*n+j;
      buff->fPols[indx+4] = (2+i)*n+j;
      buff->fPols[indx+5] = (4+i)*n+j+1;
   }
   buff->fPols[indx+5] = (4+i)*n;
   i=2;
   for (j = 0; j < n; j++) {
      indx = 6*(i*n+j);
      buff->fPols[indx  ] = c+i;
      buff->fPols[indx+1] = 4;
      buff->fPols[indx+2] = (i-2)*2*n+j;
      buff->fPols[indx+3] = (4+i)*n+j;
      buff->fPols[indx+4] = ((i-2)*2+1)*n+j;
      buff->fPols[indx+5] = (4+i)*n+j+1;
   }
   buff->fPols[indx+5] = (4+i)*n;
   i=3;
   for (j = 0; j < n; j++) {
      indx = 6*(i*n+j);
      buff->fPols[indx  ] = c+i;
      buff->fPols[indx+1] = 4;
      buff->fPols[indx+5] = (i-2)*2*n+j;
      buff->fPols[indx+4] = (4+i)*n+j;
      buff->fPols[indx+3] = ((i-2)*2+1)*n+j;
      buff->fPols[indx+2] = (4+i)*n+j+1;
   }
   buff->fPols[indx+2] = (4+i)*n;

   // Paint gPad->fBuffer3D
   buff->Paint(option);
}

//______________________________________________________________________________
void TTUBE::SetNumberOfDivisions (Int_t ndiv)
{
   // Set number of divisions used to draw this tube

   fNdiv = ndiv;
   MakeTableOfCoSin();
}

//______________________________________________________________________________
void TTUBE::SetPoints(Double_t *buff)
{
   // Create TUBE points

   Int_t j, n;
   Int_t indx = 0;

   n = GetNumberOfDivisions();

   if (buff) {
      if (!fCoTab)   MakeTableOfCoSin();
      for (j = 0; j < n; j++) {
         buff[indx+6*n] = buff[indx] = fRmin * fCoTab[j];
         indx++;
         buff[indx+6*n] = buff[indx] = fAspectRatio*fRmin * fSiTab[j];
         indx++;
         buff[indx+6*n] = fDz;
         buff[indx]     =-fDz;
         indx++;
      }
      for (j = 0; j < n; j++) {
         buff[indx+6*n] = buff[indx] = fRmax * fCoTab[j];
         indx++;
         buff[indx+6*n] = buff[indx] = fAspectRatio*fRmax * fSiTab[j];
         indx++;
         buff[indx+6*n]= fDz;
         buff[indx]    =-fDz;
         indx++;
      }
   }
}

//______________________________________________________________________________
void TTUBE::Sizeof3D() const
{
   // Return total X3D needed by TNode::ls (when called with option "x")

   Int_t n = GetNumberOfDivisions();

   gSize3D.numPoints += n*4;
   gSize3D.numSegs   += n*8;
   gSize3D.numPolys  += n*4;
}

//______________________________________________________________________________
void TTUBE::Streamer(TBuffer &R__b)
{
   // Stream an object of class TTUBE.

   if (R__b.IsReading()) {
      UInt_t R__s, R__c;
      Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
      if (R__v > 2) {
         TTUBE::Class()->ReadBuffer(R__b, this, R__v, R__s, R__c);
         return;
      }
      //====process old versions before automatic schema evolution
      TShape::Streamer(R__b);
      R__b >> fRmin;
      R__b >> fRmax;
      R__b >> fDz;
      R__b >> fNdiv;
      if (R__v > 1) R__b >> fAspectRatio;
      R__b.CheckByteCount(R__s, R__c, TTUBE::IsA());
      //====end of old versions
   } else {
      TTUBE::Class()->WriteBuffer(R__b,this);
   }
}
<commit_msg>From Olivier: - TTUBE::Paint stamp the tube with kANY (we do not want to do further   optimization in the g3d package).<commit_after>// @(#)root/g3d:$Name:  $:$Id: TTUBE.cxx,v 1.7 2004/09/14 15:56:15 brun Exp $
// Author: Nenad Buncic   18/09/95

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#include "TTUBE.h"
#include "TNode.h"
#include "TVirtualPad.h"
#include "TBuffer3D.h"
#include "TGeometry.h"

ClassImp(TTUBE)

//______________________________________________________________________________
// Begin_Html

 End_Html
// TUBE is a tube. It has 6 parameters:
//
//     - name       name of the shape
//     - title      shape's title
//     - material  (see TMaterial)
//     - rmin       inside radius
//     - rmax       outside radius
//     - dz         half length in z

//______________________________________________________________________________
TTUBE::TTUBE()
{
   // TUBE shape default constructor

   fCoTab = 0;
   fSiTab = 0;
   fAspectRatio =1;
}

//______________________________________________________________________________
TTUBE::TTUBE(const char *name, const char *title, const char *material, Float_t rmin, Float_t rmax, Float_t dz,Float_t aspect)
      : TShape(name, title,material)
{
   // TUBE shape normal constructor

   fRmin  = rmin;
   fRmax  = rmax;

   fDz   = dz;
   fNdiv = 0;

   fCoTab = 0;
   fSiTab = 0;

   fAspectRatio = aspect;

   MakeTableOfCoSin();
}

//______________________________________________________________________________
TTUBE::TTUBE(const char *name, const char *title, const char *material, Float_t rmax, Float_t dz)
      : TShape(name, title,material)
{
   // TUBE shape "simplified" constructor

   fRmin  = 0;
   fRmax  = rmax;

   fDz   = dz;
   fNdiv = 0;

   fCoTab = 0;
   fSiTab = 0;

   fAspectRatio = 1;

   MakeTableOfCoSin();
}

//______________________________________________________________________________
void TTUBE::MakeTableOfCoSin()
{
   const Double_t PI  = TMath::ATan(1) * 4.0;
   const Double_t TWOPI  =2*PI;

   Int_t j;
   Int_t n = GetNumberOfDivisions ();
   if (fCoTab)
      delete [] fCoTab; // Delete the old tab if any
      fCoTab = new Double_t [n];
   if (!fCoTab ) {
      Error("MakeTableOfCoSin()","No cos table done");
      return;
   }

   if (fSiTab) delete [] fSiTab; // Delete the old tab if any
   fSiTab = new Double_t [n];
   if (!fSiTab ) {
      Error("MakeTableOfCoSin()","No sin table done");
      return;
   }

   Double_t range = TWOPI;

   Double_t angstep = range/n;

   Double_t ph = 0;
   for (j = 0; j < n; j++) {
      ph = j*angstep;
      fCoTab[j] = TMath::Cos(ph);
      fSiTab[j] = TMath::Sin(ph);
   }
}

//______________________________________________________________________________
TTUBE::~TTUBE()
{
   // TUBE shape default destructor

   delete [] fCoTab;
   delete [] fSiTab;
}

//______________________________________________________________________________
Int_t TTUBE::DistancetoPrimitive(Int_t px, Int_t py)
{
   // Compute distance from point px,py to a TUBE
   //
   // Compute the closest distance of approach from point px,py to each
   // computed outline point of the TUBE.

   Int_t n = GetNumberOfDivisions();
   Int_t numPoints = n*4;
   return ShapeDistancetoPrimitive(numPoints,px,py);
}

//______________________________________________________________________________
void TTUBE::Paint(Option_t *option)
{
   // Paint this 3-D shape with its current attributes

   Int_t i, j, indx;
   Int_t n = GetNumberOfDivisions();
   Int_t NbPnts = 4*n;
   Int_t NbSegs = 8*n;
   Int_t NbPols = 4*n;
   TBuffer3D *buff = gPad->AllocateBuffer3D(3*NbPnts, 3*NbSegs, 6*NbPols);
   if (!buff) return;

   buff->fType = TBuffer3D::kANY;
   buff->fId   = this;

   // Fill gPad->fBuffer3D. Points coordinates are in Master space
   buff->fNbPnts = NbPnts;
   buff->fNbSegs = NbSegs;
   buff->fNbPols = NbPols;
   // In case of option "size" it is not necessary to fill the buffer
   if (buff->fOption == TBuffer3D::kSIZE) {
      buff->Paint(option);
      return;
   }

   SetPoints(buff->fPnts);

   TransformPoints(buff);

   // Basic colors: 0, 1, ... 7
   buff->fColor = GetLineColor();
   Int_t c = (((buff->fColor) %8) -1) * 4;
   if (c < 0) c = 0;

   for (i = 0; i < 4; i++) {
      for (j = 0; j < n; j++) {
         buff->fSegs[(i*n+j)*3  ] = c;
         buff->fSegs[(i*n+j)*3+1] = i*n+j;
         buff->fSegs[(i*n+j)*3+2] = i*n+j+1;
      }
      buff->fSegs[(i*n+j-1)*3+2] = i*n;
   }
   for (i = 4; i < 6; i++) {
      for (j = 0; j < n; j++) {
         buff->fSegs[(i*n+j)*3  ] = c+1;
         buff->fSegs[(i*n+j)*3+1] = (i-4)*n+j;
         buff->fSegs[(i*n+j)*3+2] = (i-2)*n+j;
      }
   }
   for (i = 6; i < 8; i++) {
      for (j = 0; j < n; j++) {
         buff->fSegs[(i*n+j)*3  ] = c;
         buff->fSegs[(i*n+j)*3+1] = 2*(i-6)*n+j;
         buff->fSegs[(i*n+j)*3+2] = (2*(i-6)+1)*n+j;
      }
   }

   indx = 0;
   i=0;
   for (j = 0; j < n; j++) {
      indx = 6*(i*n+j);
      buff->fPols[indx  ] = c;
      buff->fPols[indx+1] = 4;
      buff->fPols[indx+5] = i*n+j;
      buff->fPols[indx+4] = (4+i)*n+j;
      buff->fPols[indx+3] = (2+i)*n+j;
      buff->fPols[indx+2] = (4+i)*n+j+1;
   }
   buff->fPols[indx+2] = (4+i)*n;
   i=1;
   for (j = 0; j < n; j++) {
      indx = 6*(i*n+j);
      buff->fPols[indx  ] = c;
      buff->fPols[indx+1] = 4;
      buff->fPols[indx+2] = i*n+j;
      buff->fPols[indx+3] = (4+i)*n+j;
      buff->fPols[indx+4] = (2+i)*n+j;
      buff->fPols[indx+5] = (4+i)*n+j+1;
   }
   buff->fPols[indx+5] = (4+i)*n;
   i=2;
   for (j = 0; j < n; j++) {
      indx = 6*(i*n+j);
      buff->fPols[indx  ] = c+i;
      buff->fPols[indx+1] = 4;
      buff->fPols[indx+2] = (i-2)*2*n+j;
      buff->fPols[indx+3] = (4+i)*n+j;
      buff->fPols[indx+4] = ((i-2)*2+1)*n+j;
      buff->fPols[indx+5] = (4+i)*n+j+1;
   }
   buff->fPols[indx+5] = (4+i)*n;
   i=3;
   for (j = 0; j < n; j++) {
      indx = 6*(i*n+j);
      buff->fPols[indx  ] = c+i;
      buff->fPols[indx+1] = 4;
      buff->fPols[indx+5] = (i-2)*2*n+j;
      buff->fPols[indx+4] = (4+i)*n+j;
      buff->fPols[indx+3] = ((i-2)*2+1)*n+j;
      buff->fPols[indx+2] = (4+i)*n+j+1;
   }
   buff->fPols[indx+2] = (4+i)*n;

   // Paint gPad->fBuffer3D
   buff->Paint(option);
}

//______________________________________________________________________________
void TTUBE::SetNumberOfDivisions (Int_t ndiv)
{
   // Set number of divisions used to draw this tube

   fNdiv = ndiv;
   MakeTableOfCoSin();
}

//______________________________________________________________________________
void TTUBE::SetPoints(Double_t *buff)
{
   // Create TUBE points

   Int_t j, n;
   Int_t indx = 0;

   n = GetNumberOfDivisions();

   if (buff) {
      if (!fCoTab)   MakeTableOfCoSin();
      for (j = 0; j < n; j++) {
         buff[indx+6*n] = buff[indx] = fRmin * fCoTab[j];
         indx++;
         buff[indx+6*n] = buff[indx] = fAspectRatio*fRmin * fSiTab[j];
         indx++;
         buff[indx+6*n] = fDz;
         buff[indx]     =-fDz;
         indx++;
      }
      for (j = 0; j < n; j++) {
         buff[indx+6*n] = buff[indx] = fRmax * fCoTab[j];
         indx++;
         buff[indx+6*n] = buff[indx] = fAspectRatio*fRmax * fSiTab[j];
         indx++;
         buff[indx+6*n]= fDz;
         buff[indx]    =-fDz;
         indx++;
      }
   }
}

//______________________________________________________________________________
void TTUBE::Sizeof3D() const
{
   // Return total X3D needed by TNode::ls (when called with option "x")

   Int_t n = GetNumberOfDivisions();

   gSize3D.numPoints += n*4;
   gSize3D.numSegs   += n*8;
   gSize3D.numPolys  += n*4;
}

//______________________________________________________________________________
void TTUBE::Streamer(TBuffer &R__b)
{
   // Stream an object of class TTUBE.

   if (R__b.IsReading()) {
      UInt_t R__s, R__c;
      Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
      if (R__v > 2) {
         TTUBE::Class()->ReadBuffer(R__b, this, R__v, R__s, R__c);
         return;
      }
      //====process old versions before automatic schema evolution
      TShape::Streamer(R__b);
      R__b >> fRmin;
      R__b >> fRmax;
      R__b >> fDz;
      R__b >> fNdiv;
      if (R__v > 1) R__b >> fAspectRatio;
      R__b.CheckByteCount(R__s, R__c, TTUBE::IsA());
      //====end of old versions
   } else {
      TTUBE::Class()->WriteBuffer(R__b,this);
   }
}
<|endoftext|>


<commit_before><commit_msg>fixed linux build error<commit_after><|endoftext|>


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

#include <TelepathyQt4/ChannelRequest>

#include "TelepathyQt4/_gen/cli-channel-request-body.hpp"
#include "TelepathyQt4/_gen/cli-channel-request.moc.hpp"
#include "TelepathyQt4/_gen/channel-request.moc.hpp"

#include "TelepathyQt4/debug-internal.h"

#include <TelepathyQt4/Account>
#include <TelepathyQt4/PendingFailure>
#include <TelepathyQt4/PendingReady>
#include <TelepathyQt4/PendingVoidMethodCall>

#include <QDateTime>

/**
 * \addtogroup clientsideproxies Client-side proxies
 *
 * Proxy objects representing remote service objects accessed via D-Bus.
 *
 * In addition to providing direct access to methods, signals and properties
 * exported by the remote objects, some of these proxies offer features like
 * automatic inspection of remote object capabilities, property tracking,
 * backwards compatibility helpers for older services and other utilities.
 */

/**
 * \defgroup clientchannelrequest ChannelRequest proxies
 * \ingroup clientsideproxies
 *
 * Proxy objects representing remote Telepathy Channel Requests and their
 * optional interfaces.
 */

namespace Tp
{

struct ChannelRequest::Private
{
    Private(ChannelRequest *parent);
    ~Private();

    static void introspectMain(Private *self);

    void extractMainProps(const QVariantMap &props);

    // Public object
    ChannelRequest *parent;

    // Instance of generated interface class
    Client::ChannelRequestInterface *baseInterface;

    // Optional interface proxies
    Client::DBus::PropertiesInterface *properties;

    ReadinessHelper *readinessHelper;

    // Introspection
    QStringList interfaces;
    AccountPtr account;
    QDateTime userActionTime;
    QString preferredHandler;
    QualifiedPropertyValueMapList requests;
};

ChannelRequest::Private::Private(ChannelRequest *parent)
    : parent(parent),
      baseInterface(new Client::ChannelRequestInterface(
                    parent->dbusConnection(), parent->busName(),
                    parent->objectPath(), parent)),
      properties(0),
      readinessHelper(parent->readinessHelper())
{
    debug() << "Creating new ChannelRequest:" << parent->objectPath();

    ReadinessHelper::Introspectables introspectables;

    // As ChannelRequest does not have predefined statuses let's simulate one (0)
    ReadinessHelper::Introspectable introspectableCore(
        QSet<uint>() << 0,                                           // makesSenseForStatuses
        Features(),                                                  // dependsOnFeatures
        QStringList(),                                               // dependsOnInterfaces
        (ReadinessHelper::IntrospectFunc) &Private::introspectMain,
        this);
    introspectables[FeatureCore] = introspectableCore;

    readinessHelper->addIntrospectables(introspectables);
}

ChannelRequest::Private::~Private()
{
}

void ChannelRequest::Private::introspectMain(ChannelRequest::Private *self)
{
    if (!self->properties) {
        self->properties = self->parent->propertiesInterface();
        Q_ASSERT(self->properties != 0);
    }

    self->parent->connect(self->baseInterface,
            SIGNAL(Failed(const QString &, const QString &)),
            SIGNAL(failed(const QString &, const QString &)));
    self->parent->connect(self->baseInterface,
            SIGNAL(Succeeded()),
            SIGNAL(succeeded()));

    debug() << "Calling Properties::GetAll(ChannelRequest)";
    QDBusPendingCallWatcher *watcher =
        new QDBusPendingCallWatcher(
                self->properties->GetAll(TELEPATHY_INTERFACE_CHANNEL_REQUEST),
                self->parent);
    // FIXME: This is a Qt bug fixed upstream, should be in the next Qt release.
    //        We should not need to check watcher->isFinished() here, remove the
    //        check when a fixed Qt version is released.
    if (watcher->isFinished()) {
        self->parent->gotMainProperties(watcher);
    } else {
        self->parent->connect(watcher,
                SIGNAL(finished(QDBusPendingCallWatcher*)),
                SLOT(gotMainProperties(QDBusPendingCallWatcher*)));
    }
}

void ChannelRequest::Private::extractMainProps(const QVariantMap &props)
{
    interfaces = qdbus_cast<QStringList>(props.value("Interfaces"));

    if (!account && props.contains("Account")) {
        QDBusObjectPath accountObjectPath =
            qdbus_cast<QDBusObjectPath>(props.value("Account"));
        account = Account::create(
                TELEPATHY_ACCOUNT_MANAGER_BUS_NAME,
                accountObjectPath.path());
    }

    // FIXME See http://bugs.freedesktop.org/show_bug.cgi?id=21690
    uint stamp = (uint) qdbus_cast<qlonglong>(props.value("UserActionTime"));
    if (stamp != 0) {
        userActionTime = QDateTime::fromTime_t(stamp);
    }

    preferredHandler = qdbus_cast<QString>(props.value("PreferredHandler"));
    requests = qdbus_cast<QualifiedPropertyValueMapList>(props.value("Requests"));
}

/**
 * \class ChannelRequest
 * \ingroup clientchannelrequest
 * \headerfile <TelepathyQt4/channel-request.h> <TelepathyQt4/ChannelRequest>
 *
 * High-level proxy object for accessing remote Telepathy ChannelRequest objects.
 */

const Feature ChannelRequest::FeatureCore = Feature(ChannelRequest::staticMetaObject.className(), 0, true);

ChannelRequestPtr ChannelRequest::create(const QString &objectPath,
        const QVariantMap &immutableProperties)
{
    return ChannelRequestPtr(new ChannelRequest(QDBusConnection::sessionBus(),
                objectPath, immutableProperties));
}

ChannelRequestPtr ChannelRequest::create(const QDBusConnection &bus,
        const QString &objectPath, const QVariantMap &immutableProperties)
{
    return ChannelRequestPtr(new ChannelRequest(bus, objectPath,
                immutableProperties));
}

ChannelRequest::ChannelRequest(const QDBusConnection &bus,
        const QString &objectPath, const QVariantMap &immutableProperties)
    : StatefulDBusProxy(bus,
            "org.freedesktop.Telepathy.ChannelDispatcher",
            objectPath),
      OptionalInterfaceFactory<ChannelRequest>(this),
      ReadyObject(this, FeatureCore),
      mPriv(new Private(this))
{
    mPriv->extractMainProps(immutableProperties);
}

/**
 * Class destructor.
 */
ChannelRequest::~ChannelRequest()
{
    delete mPriv;
}

QStringList ChannelRequest::interfaces() const
{
    return mPriv->interfaces;
}

AccountPtr ChannelRequest::account() const
{
    return mPriv->account;
}

QDateTime ChannelRequest::userActionTime() const
{
    return mPriv->userActionTime;
}

QString ChannelRequest::preferredHandler() const
{
    return mPriv->preferredHandler;
}

QualifiedPropertyValueMapList ChannelRequest::requests() const
{
    return mPriv->requests;
}

PendingOperation *ChannelRequest::cancel()
{
    return new PendingVoidMethodCall(this, mPriv->baseInterface->Cancel());
}

PendingOperation *ChannelRequest::proceed()
{
    return new PendingVoidMethodCall(this, mPriv->baseInterface->Proceed());
}

/**
 * Get the ChannelRequestInterface for this ChannelRequest class. This method is
 * protected since the convenience methods provided by this class should
 * always be used instead of the interface by users of the class.
 *
 * \return A pointer to the existing ChannelRequestInterface for this
 *         ChannelRequest
 */
Client::ChannelRequestInterface *ChannelRequest::baseInterface() const
{
    return mPriv->baseInterface;
}

void ChannelRequest::gotMainProperties(QDBusPendingCallWatcher *watcher)
{
    QDBusPendingReply<QVariantMap> reply = *watcher;
    QVariantMap props;

    if (!reply.isError()) {
        debug() << "Got reply to Properties::GetAll(ChannelRequest)";
        props = reply.value();

        mPriv->extractMainProps(props);

        if (mPriv->account) {
            connect(mPriv->account->becomeReady(),
                    SIGNAL(finished(Tp::PendingOperation *)),
                    SLOT(onAccountReady(Tp::PendingOperation *)));
        } else {
            warning() << "Properties.GetAll(ChannelRequest) is missing "
                "account property, ignoring";
            mPriv->readinessHelper->setIntrospectCompleted(FeatureCore, true);
        }
    }
    else {
        mPriv->readinessHelper->setIntrospectCompleted(FeatureCore,
                false, reply.error());
        warning().nospace() << "Properties::GetAll(ChannelRequest) failed with "
            << reply.error().name() << ": " << reply.error().message();
    }
}

void ChannelRequest::onAccountReady(PendingOperation *op)
{
    if (op->isError()) {
        warning() << "Unable to make account ready";
        mPriv->readinessHelper->setIntrospectCompleted(FeatureCore, false,
                op->errorName(), op->errorMessage());
        return;
    }
    mPriv->readinessHelper->setIntrospectCompleted(FeatureCore, true);
}

} // Tp
<commit_msg>ChannelRequest: Emit succeeded/failed even if not ready.<commit_after>/*
 * This file is part of TelepathyQt4
 *
 * Copyright (C) 2009 Collabora Ltd. <http://www.collabora.co.uk/>
 * Copyright (C) 2009 Nokia Corporation
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include <TelepathyQt4/ChannelRequest>

#include "TelepathyQt4/_gen/cli-channel-request-body.hpp"
#include "TelepathyQt4/_gen/cli-channel-request.moc.hpp"
#include "TelepathyQt4/_gen/channel-request.moc.hpp"

#include "TelepathyQt4/debug-internal.h"

#include <TelepathyQt4/Account>
#include <TelepathyQt4/PendingFailure>
#include <TelepathyQt4/PendingReady>
#include <TelepathyQt4/PendingVoidMethodCall>

#include <QDateTime>

/**
 * \addtogroup clientsideproxies Client-side proxies
 *
 * Proxy objects representing remote service objects accessed via D-Bus.
 *
 * In addition to providing direct access to methods, signals and properties
 * exported by the remote objects, some of these proxies offer features like
 * automatic inspection of remote object capabilities, property tracking,
 * backwards compatibility helpers for older services and other utilities.
 */

/**
 * \defgroup clientchannelrequest ChannelRequest proxies
 * \ingroup clientsideproxies
 *
 * Proxy objects representing remote Telepathy Channel Requests and their
 * optional interfaces.
 */

namespace Tp
{

struct ChannelRequest::Private
{
    Private(ChannelRequest *parent);
    ~Private();

    static void introspectMain(Private *self);

    void extractMainProps(const QVariantMap &props);

    // Public object
    ChannelRequest *parent;

    // Instance of generated interface class
    Client::ChannelRequestInterface *baseInterface;

    // Optional interface proxies
    Client::DBus::PropertiesInterface *properties;

    ReadinessHelper *readinessHelper;

    // Introspection
    QStringList interfaces;
    AccountPtr account;
    QDateTime userActionTime;
    QString preferredHandler;
    QualifiedPropertyValueMapList requests;
};

ChannelRequest::Private::Private(ChannelRequest *parent)
    : parent(parent),
      baseInterface(new Client::ChannelRequestInterface(
                    parent->dbusConnection(), parent->busName(),
                    parent->objectPath(), parent)),
      properties(0),
      readinessHelper(parent->readinessHelper())
{
    debug() << "Creating new ChannelRequest:" << parent->objectPath();

    parent->connect(baseInterface,
            SIGNAL(Failed(const QString &, const QString &)),
            SIGNAL(failed(const QString &, const QString &)));
    parent->connect(baseInterface,
            SIGNAL(Succeeded()),
            SIGNAL(succeeded()));

    ReadinessHelper::Introspectables introspectables;

    // As ChannelRequest does not have predefined statuses let's simulate one (0)
    ReadinessHelper::Introspectable introspectableCore(
        QSet<uint>() << 0,                                           // makesSenseForStatuses
        Features(),                                                  // dependsOnFeatures
        QStringList(),                                               // dependsOnInterfaces
        (ReadinessHelper::IntrospectFunc) &Private::introspectMain,
        this);
    introspectables[FeatureCore] = introspectableCore;

    readinessHelper->addIntrospectables(introspectables);
}

ChannelRequest::Private::~Private()
{
}

void ChannelRequest::Private::introspectMain(ChannelRequest::Private *self)
{
    if (!self->properties) {
        self->properties = self->parent->propertiesInterface();
        Q_ASSERT(self->properties != 0);
    }

    debug() << "Calling Properties::GetAll(ChannelRequest)";
    QDBusPendingCallWatcher *watcher =
        new QDBusPendingCallWatcher(
                self->properties->GetAll(TELEPATHY_INTERFACE_CHANNEL_REQUEST),
                self->parent);
    // FIXME: This is a Qt bug fixed upstream, should be in the next Qt release.
    //        We should not need to check watcher->isFinished() here, remove the
    //        check when a fixed Qt version is released.
    if (watcher->isFinished()) {
        self->parent->gotMainProperties(watcher);
    } else {
        self->parent->connect(watcher,
                SIGNAL(finished(QDBusPendingCallWatcher*)),
                SLOT(gotMainProperties(QDBusPendingCallWatcher*)));
    }
}

void ChannelRequest::Private::extractMainProps(const QVariantMap &props)
{
    interfaces = qdbus_cast<QStringList>(props.value("Interfaces"));

    if (!account && props.contains("Account")) {
        QDBusObjectPath accountObjectPath =
            qdbus_cast<QDBusObjectPath>(props.value("Account"));
        account = Account::create(
                TELEPATHY_ACCOUNT_MANAGER_BUS_NAME,
                accountObjectPath.path());
    }

    // FIXME See http://bugs.freedesktop.org/show_bug.cgi?id=21690
    uint stamp = (uint) qdbus_cast<qlonglong>(props.value("UserActionTime"));
    if (stamp != 0) {
        userActionTime = QDateTime::fromTime_t(stamp);
    }

    preferredHandler = qdbus_cast<QString>(props.value("PreferredHandler"));
    requests = qdbus_cast<QualifiedPropertyValueMapList>(props.value("Requests"));
}

/**
 * \class ChannelRequest
 * \ingroup clientchannelrequest
 * \headerfile <TelepathyQt4/channel-request.h> <TelepathyQt4/ChannelRequest>
 *
 * High-level proxy object for accessing remote Telepathy ChannelRequest objects.
 */

const Feature ChannelRequest::FeatureCore = Feature(ChannelRequest::staticMetaObject.className(), 0, true);

ChannelRequestPtr ChannelRequest::create(const QString &objectPath,
        const QVariantMap &immutableProperties)
{
    return ChannelRequestPtr(new ChannelRequest(QDBusConnection::sessionBus(),
                objectPath, immutableProperties));
}

ChannelRequestPtr ChannelRequest::create(const QDBusConnection &bus,
        const QString &objectPath, const QVariantMap &immutableProperties)
{
    return ChannelRequestPtr(new ChannelRequest(bus, objectPath,
                immutableProperties));
}

ChannelRequest::ChannelRequest(const QDBusConnection &bus,
        const QString &objectPath, const QVariantMap &immutableProperties)
    : StatefulDBusProxy(bus,
            "org.freedesktop.Telepathy.ChannelDispatcher",
            objectPath),
      OptionalInterfaceFactory<ChannelRequest>(this),
      ReadyObject(this, FeatureCore),
      mPriv(new Private(this))
{
    mPriv->extractMainProps(immutableProperties);
}

/**
 * Class destructor.
 */
ChannelRequest::~ChannelRequest()
{
    delete mPriv;
}

QStringList ChannelRequest::interfaces() const
{
    return mPriv->interfaces;
}

AccountPtr ChannelRequest::account() const
{
    return mPriv->account;
}

QDateTime ChannelRequest::userActionTime() const
{
    return mPriv->userActionTime;
}

QString ChannelRequest::preferredHandler() const
{
    return mPriv->preferredHandler;
}

QualifiedPropertyValueMapList ChannelRequest::requests() const
{
    return mPriv->requests;
}

PendingOperation *ChannelRequest::cancel()
{
    return new PendingVoidMethodCall(this, mPriv->baseInterface->Cancel());
}

PendingOperation *ChannelRequest::proceed()
{
    return new PendingVoidMethodCall(this, mPriv->baseInterface->Proceed());
}

/**
 * Get the ChannelRequestInterface for this ChannelRequest class. This method is
 * protected since the convenience methods provided by this class should
 * always be used instead of the interface by users of the class.
 *
 * \return A pointer to the existing ChannelRequestInterface for this
 *         ChannelRequest
 */
Client::ChannelRequestInterface *ChannelRequest::baseInterface() const
{
    return mPriv->baseInterface;
}

void ChannelRequest::gotMainProperties(QDBusPendingCallWatcher *watcher)
{
    QDBusPendingReply<QVariantMap> reply = *watcher;
    QVariantMap props;

    if (!reply.isError()) {
        debug() << "Got reply to Properties::GetAll(ChannelRequest)";
        props = reply.value();

        mPriv->extractMainProps(props);

        if (mPriv->account) {
            connect(mPriv->account->becomeReady(),
                    SIGNAL(finished(Tp::PendingOperation *)),
                    SLOT(onAccountReady(Tp::PendingOperation *)));
        } else {
            warning() << "Properties.GetAll(ChannelRequest) is missing "
                "account property, ignoring";
            mPriv->readinessHelper->setIntrospectCompleted(FeatureCore, true);
        }
    }
    else {
        mPriv->readinessHelper->setIntrospectCompleted(FeatureCore,
                false, reply.error());
        warning().nospace() << "Properties::GetAll(ChannelRequest) failed with "
            << reply.error().name() << ": " << reply.error().message();
    }
}

void ChannelRequest::onAccountReady(PendingOperation *op)
{
    if (op->isError()) {
        warning() << "Unable to make account ready";
        mPriv->readinessHelper->setIntrospectCompleted(FeatureCore, false,
                op->errorName(), op->errorMessage());
        return;
    }
    mPriv->readinessHelper->setIntrospectCompleted(FeatureCore, true);
}

} // Tp
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   OpenIGTLink Library
  Module:    $RCSfile: itkImage.h,v $
  Language:  C++
  Date:      $Date: 2008/01/13 19:48:38 $
  Version:   $Revision: 1.142 $

  Copyright (c) Insight Software Consortium. All rights reserved.

  This software is distributed WITHOUT ANY WARRANTY; without even
  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

#include "igtlServerSocket.h"
#include "igtlImageMessage.h"
#include "igtl_types.h"
#include "igtl_header.h"
#include "igtl_image.h"
#include "igtl_util.h"
#include "gtest/gtest.h"
#include "gmock/gmock.h"
#include "igtlutil/igtl_test_data_image.h"
using ::testing::_;
using ::testing::AtLeast;
using ::testing::Invoke;
using igtl::ServerSocket;
class ServerSocketMock :public ServerSocket {
public:
  ServerSocketMock() {
    // By default, all calls are delegated to the real object.
    ON_CALL(*this, CreateServer(_))
        .WillByDefault(Invoke(&real_, &ServerSocket::CreateServer));
    ON_CALL(*this, GetServerPort())
        .WillByDefault(Invoke(&real_, &ServerSocket::GetServerPort));
  }
  ~ServerSocketMock(){}
  MOCK_METHOD1(CreateServer, int(int port));
  MOCK_METHOD0(GetServerPort, int());
 private:
  ServerSocket real_;

};

TEST(ServerSocketTest, connection)
{
  ServerSocketMock mockServerSocket;
  const char*  hostname = "test";
  int port = 5;
  EXPECT_CALL(mockServerSocket, CreateServer(port)).Times(2);
  EXPECT_CALL(mockServerSocket, GetServerPort()).Times(1);
  mockServerSocket.GetServerPort();
  EXPECT_EQ(mockServerSocket.CreateServer(port),0);
  EXPECT_EQ(mockServerSocket.CreateServer(port),0);
}

int main(int argc, char **argv)
{
  testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}

<commit_msg>-contructor is protected, so an overloaded constructor is created for testing purpose<commit_after>/*=========================================================================

  Program:   OpenIGTLink Library
  Module:    $RCSfile: itkImage.h,v $
  Language:  C++
  Date:      $Date: 2008/01/13 19:48:38 $
  Version:   $Revision: 1.142 $

  Copyright (c) Insight Software Consortium. All rights reserved.

  This software is distributed WITHOUT ANY WARRANTY; without even
  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

#include "igtlServerSocket.h"
#include "igtlImageMessage.h"
#include "igtl_types.h"
#include "igtl_header.h"
#include "igtl_image.h"
#include "igtl_util.h"
#include "gtest/gtest.h"
#include "gmock/gmock.h"
#include "igtlutil/igtl_test_data_image.h"
using ::testing::_;
using ::testing::AtLeast;
using ::testing::Invoke;
using igtl::ServerSocket;
class ServerSocketMock :public ServerSocket {
public:
  ServerSocketMock(ServerSocket::Pointer pointer) {
    real_ = pointer;
    // By default, all calls are delegated to the real object.
    ON_CALL(*this, CreateServer(_))
        .WillByDefault(Invoke(real_.GetPointer(), &ServerSocket::CreateServer));
    ON_CALL(*this, GetServerPort())
        .WillByDefault(Invoke(real_.GetPointer(), &ServerSocket::GetServerPort));
  }
  ~ServerSocketMock(){};
  MOCK_METHOD1(CreateServer, int(int port));
  MOCK_METHOD0(GetServerPort, int());
 protected:
   ServerSocketMock();
 private:
   ServerSocket::Pointer real_;

};

TEST(ServerSocketTest, connection)
{
  ServerSocketMock mockServerSocket(ServerSocket::New());
  const char*  hostname = "test";
  int port = 5;
  EXPECT_CALL(mockServerSocket, CreateServer(port)).Times(2);
  EXPECT_CALL(mockServerSocket, GetServerPort()).Times(1);
  mockServerSocket.GetServerPort();
  EXPECT_EQ(mockServerSocket.CreateServer(port),0);
  EXPECT_EQ(mockServerSocket.CreateServer(port),0);
}

int main(int argc, char **argv)
{
  testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}

<|endoftext|>


<commit_before>#ifndef HEADER_AUDIOCPP
#define HEADER_AUDIOCPP

#include "MT2D/MT2D_Terminal_Define.h"

#ifdef _DEBUG
#include <stdio.h>
#endif
#ifdef SDL_USE_AUDIO
	#ifdef linux
		#include <SDL2/SDL.h>
		#include <SDL2/SDL_audio.h>
		#include <SDL2/SDL_mixer.h>
	#elif defined _WIN32
		#include <SDL.h>
		#include <SDL_mixer.h>
#endif
#include <queue>
#include <cmath>

extern bool nosound;

bool SDL_AUDIO_STARTED = false;
Mix_Music *SDL_mus = 0;
int music_loaded = 0;
Mix_Chunk *SDL_wav = 0;
int sound_loaded = 0;

extern char SDL_SOUND_TYPE;

void SDL_Start_Sound_System()
{
    if(SDL_SOUND_TYPE == -1){
		SDL_SOUND_TYPE = 1;
        if(SDL_Init(SDL_INIT_AUDIO) < 0){
            exit(1);
        }else{
            Mix_OpenAudio(22050,AUDIO_S16SYS,2,640);
            SDL_PauseAudio(0);
        }
    }
}

#ifdef _WIN32
Mix_Music *mus = 0;

Mix_Chunk *wav = 0;
#endif

void SDL_Close_Sound_System()
{
	if (SDL_SOUND_TYPE == 1) {
		while (Mix_Playing(0) != 0);
		Mix_FreeChunk(SDL_wav);
		Mix_FreeMusic(SDL_mus);
		Mix_CloseAudio();
		SDL_Quit();
	}
}

void SDL_Play_Music(char *Name){
	if (SDL_SOUND_TYPE == 1) {
#ifdef _DEBUG
		printf("Starting SDL Play music (%s)  \n", Name);
#endif
		if (Name) {
#ifdef _DEBUG
			printf("music loaded: %d \n", music_loaded);
#endif
			if (!music_loaded) {
#ifdef _DEBUG
				printf("Entrou no if\n");
#endif

				SDL_mus = Mix_LoadMUS(Name);
				if (!SDL_mus) {
#ifdef _DEBUG
					printf("Mix_LoadMUS(\"%s\")> %s\n", Name, Mix_GetError());
#endif
				}
				music_loaded = 1;
#ifdef _DEBUG
				printf("som na caixa\n");
#endif
				Mix_PlayMusic(SDL_mus, 10);
			}
			else {
				if (SDL_mus) {
					Mix_FreeMusic(SDL_mus);
				}
				SDL_mus = Mix_LoadMUS(Name);
				if (!SDL_mus) {
#ifdef _DEBUG
					printf("Mix_LoadMUS(\"%s\")> %s\n", Name, Mix_GetError());
#endif
				}
				music_loaded = 1;
				Mix_PlayMusic(SDL_mus, 10);
			}
		}
		else {
#ifdef _DEBUG
			printf("No music name received...\n");
#endif
		}
	}
}

void SDL_Play_Sound(char *Name){
	if (SDL_SOUND_TYPE == 1) {
		if (!sound_loaded) {
			sound_loaded = 1;
			SDL_wav = Mix_LoadWAV(Name);
			Mix_PlayChannel(0, SDL_wav, 0);
		}
		else {
			sound_loaded = 1;
			if (SDL_wav) {
				Mix_FreeChunk(SDL_wav);
			}
			SDL_wav = Mix_LoadWAV(Name);
			Mix_PlayChannel(0, SDL_wav, 0);
		}
	}
}

#else
//#warning define "SDL_USE_AUDIO" must be declared to use the SDL audio code
#endif

#endif
<commit_msg>-Audio Struct is now better with a better control to choise what sound should stop playing in case all the audio buffers are being used.<commit_after>#ifndef HEADER_AUDIOCPP
#define HEADER_AUDIOCPP

#include "MT2D/MT2D_Terminal_Define.h"

#ifdef _DEBUG
#include <stdio.h>
#endif
#ifdef SDL_USE_AUDIO
	#ifdef linux
		#include <SDL2/SDL.h>
		#include <SDL2/SDL_audio.h>
		#include <SDL2/SDL_mixer.h>
	#elif defined _WIN32
		#include <SDL.h>
		#include <SDL_mixer.h>
#endif
#include <queue>
#include <cmath>
#include <time.h>

extern bool nosound;

/**
	Private struct
**/
typedef struct MT2D_Audio_Buffer {
#ifdef SDL_USE_AUDIO
	bool SDL_AUDIO_STARTED;
	Mix_Music *SDL_music;
	int music_loaded;
	Mix_Chunk *SDL_Audio[8]; // we can play only max 8 audio files at the same time.
	time_t SDL_Audio_Started[8];
	int sound_loaded;
#endif
};

MT2D_Audio_Buffer SDL_ABuffer;
bool SDL_AUDIO_STARTED = false;

extern char SDL_SOUND_TYPE;

void SDL_Start_Sound_System()
{
	SDL_ABuffer.music_loaded = 0;
	for (int i = 0; i < 8; i++) {
		SDL_ABuffer.SDL_Audio[i] = 0;
		SDL_ABuffer.SDL_Audio_Started[i] = 0;
	}
	SDL_ABuffer.SDL_AUDIO_STARTED = 0;
	SDL_ABuffer.SDL_music = 0;
	SDL_ABuffer.sound_loaded = 0;

	if(SDL_SOUND_TYPE == -1){
		SDL_SOUND_TYPE = 1;
        if(SDL_Init(SDL_INIT_AUDIO) < 0){
            exit(1);
        }else{
            Mix_OpenAudio(22050,AUDIO_S16SYS,2,640);
            SDL_PauseAudio(0);
        }
    }
}

void SDL_Close_Sound_System()
{
	if (SDL_SOUND_TYPE == 1) {
		while (Mix_Playing(0) != 0);
		for (int i = 0; i < 8; i++) {
			if (SDL_ABuffer.SDL_Audio[0]) {
				Mix_FreeChunk(SDL_ABuffer.SDL_Audio[0]);
			}
		}
		Mix_FreeMusic(SDL_ABuffer.SDL_music);
		Mix_CloseAudio();
		SDL_Quit();
	}
}

void SDL_Clear_Audio_Buffer() {
	Mix_Chunk *MC;
	time_t NOW = clock();
	for (int i = 0; i < 8; i++) {
		if (SDL_ABuffer.SDL_Audio[i] != NULL && NOW-SDL_ABuffer.SDL_Audio_Started[i] > SDL_ABuffer.SDL_Audio[i]->alen) {
			//the sound has already played
			Mix_FreeChunk(SDL_ABuffer.SDL_Audio[i]);
			SDL_ABuffer.SDL_Audio[i] = 0;
			SDL_ABuffer.SDL_Audio_Started[i] = 0;
		}
	}
}

void SDL_Play_Music(char *Name){
	if (SDL_SOUND_TYPE == 1) {
#ifdef _DEBUG
		printf("Starting SDL Play music (%s)  \n", Name);
#endif
		if (Name) {
#ifdef _DEBUG
			printf("music loaded: %d \n", SDL_ABuffer.music_loaded);
#endif
			if (!SDL_ABuffer.music_loaded) {
#ifdef _DEBUG
				printf("Entrou no if\n");
#endif

				SDL_ABuffer.SDL_music = Mix_LoadMUS(Name);
				if (!SDL_ABuffer.SDL_music) {
#ifdef _DEBUG
					printf("Mix_LoadMUS(\"%s\")> %s\n", Name, Mix_GetError());
#endif
				}
				SDL_ABuffer.music_loaded = 1;
#ifdef _DEBUG
				printf("som na caixa\n");
#endif
				Mix_PlayMusic(SDL_ABuffer.SDL_music, 10);
			}
			else {
				if (SDL_ABuffer.SDL_music) {
					Mix_FreeMusic(SDL_ABuffer.SDL_music);
				}
				SDL_ABuffer.SDL_music = Mix_LoadMUS(Name);
				if (!SDL_ABuffer.SDL_music) {
#ifdef _DEBUG
					printf("Mix_LoadMUS(\"%s\")> %s\n", Name, Mix_GetError());
#endif
				}
				SDL_ABuffer.music_loaded = 1;
				Mix_PlayMusic(SDL_ABuffer.SDL_music, 10);
			}
		}
		else {
#ifdef _DEBUG
			printf("No music name received...\n");
#endif
		}
	}
}

void SDL_Play_Sound(char *Name){
	if (SDL_SOUND_TYPE == 1) {
		bool Played = 0;
 		int i = 0;
 		SDL_Clear_Audio_Buffer();
		for (; i < 8; i++) {
			if (SDL_ABuffer.SDL_Audio[i] == 0) {
				SDL_ABuffer.SDL_Audio[i] = Mix_LoadWAV(Name);
				Mix_PlayChannel(i, SDL_ABuffer.SDL_Audio[i], 0);
				SDL_ABuffer.SDL_Audio_Started[i] = clock();
				Played = true;
				i = 8;
			}

		}
		if (Played == false) {
			/*All the channels are in use so*/
			/*first we check this audio is already being played*/
			Mix_Chunk *Tmp = Mix_LoadWAV(Name);
			for (i = 0; i < 8; i++) {
				if (SDL_ABuffer.SDL_Audio[i]->volume == Tmp->volume &&
					SDL_ABuffer.SDL_Audio[i]->alen == Tmp->alen &&
					SDL_ABuffer.SDL_Audio[i]->allocated == Tmp->allocated) {
					Mix_FreeChunk(Tmp);
					Mix_PlayChannel(i, SDL_ABuffer.SDL_Audio[i], 0);
					SDL_ABuffer.SDL_Audio_Started[i] = clock();
					i = 8;
					Played = true;
				}
			}
			if (Played == false) {
				/*this file isnt being played, so lets replace the sound that were being played that is near to finish*/
         				int IdChannel = 0;
				time_t NOW = clock();
				int ShortestTime = SDL_ABuffer.SDL_Audio[0]->alen - (NOW - SDL_ABuffer.SDL_Audio_Started[0]);
				for (i = 1; i < 8; i++) {
					if (SDL_ABuffer.SDL_Audio[i]->alen - (NOW - SDL_ABuffer.SDL_Audio_Started[i]) < ShortestTime)
					{
						IdChannel = i;
						ShortestTime = SDL_ABuffer.SDL_Audio[i]->alen - (NOW - SDL_ABuffer.SDL_Audio_Started[i]);
					}
				}
				Mix_FreeChunk(SDL_ABuffer.SDL_Audio[IdChannel]);
				SDL_ABuffer.SDL_Audio[IdChannel] = Tmp;
				Mix_PlayChannel(IdChannel, SDL_ABuffer.SDL_Audio[IdChannel], 0);
				SDL_ABuffer.SDL_Audio_Started[IdChannel] = clock();
			}
		}
	}
}

#else
//#warning define "SDL_USE_AUDIO" must be declared to use the SDL audio code
#endif

#endif
<|endoftext|>


<commit_before>/*
	Copyright 2016 Jonathan Bayle, Thomas Medioni

	Licensed under the Apache License, Version 2.0 (the "License");
	you may not use this file except in compliance with the License.
	You may obtain a copy of the License at

	   http://www.apache.org/licenses/LICENSE-2.0

	Unless required by applicable law or agreed to in writing, software
	distributed under the License is distributed on an "AS IS" BASIS,
	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
	See the License for the specific language governing permissions and
	limitations under the License.
*/

#include "game.hpp"

#include <vivace/vivace.hpp>
#include "cyclist.hpp"
#include "food.hpp"
#include "map.hpp"
#include "competitors.hpp"
using namespace vivace;

#include <exception>
#include <iostream>
#include <string>
#include <sstream>
#include <ctime>

using namespace std;

#include <glm/glm.hpp>

using namespace glm;

Game::Game() : want_menu_(false), want_reload_(false)
{
    bg_colour = al_map_rgb(0, 0, 40);
    add(menu_);
    add(pause_);

	unique_ptr<Menu> submenu = make_map_selection_menu(this, &menu_);
	Menu* backup = submenu.get();
    menu_.add_entry("PLAY", std::move(submenu));
    menu_.add_entry("QUIT", [&]() { throw 1;});

    pause_.add_entry("RESUME", [&]() { pause_.activate(false);
                                       player_->set_pause(false);
                                       activate_all();});
    pause_.activate(false);
    gameover_ = std::unique_ptr<ALLEGRO_BITMAP, al_bitmap_deleter>(reinterpret_cast<ALLEGRO_BITMAP*>(al_img_loader("data/gameover.png")));
	menubg_ = std::shared_ptr<ALLEGRO_BITMAP>(reinterpret_cast<ALLEGRO_BITMAP*>(al_img_loader("data/menu.png")), al_bitmap_deleter());
	if (menubg_.get()) {
		menu_.set_background(menubg_, 2.f, 2.f);
		menu_.set_bg_col(al_map_rgb(215, 123, 186));
		menu_.set_entry_settings(500.f, 360.f, 2.f);
		backup->set_background(menubg_, 2.f, 2.f);
		backup->set_bg_col(al_map_rgb(215, 123, 186));
		backup->set_entry_settings(500.f, 360.f, 2.f);
		pause_.set_background(menubg_, 2.f, 2.f);
		pause_.set_bg_col(al_map_rgb(215, 123, 186));
		pause_.set_entry_settings(500.f, 360.f, 2.f);
	}

	gamewon_ = std::unique_ptr<ALLEGRO_BITMAP, al_bitmap_deleter>(reinterpret_cast<ALLEGRO_BITMAP*>(al_img_loader("data/victory.png")));
}

void Game::load_game(std::string map_name)
{
    auto it = std::begin(objects_);
    while (it != std::end(objects_))
    {
        remove((**it));
        it = objects_.erase(it);
    }

    auto drawmap_fct = [&]() {
        auto pos = level_->tracks[player_->get_track()].get_position(level_->tracks[2], player_->get_pos());
        al_draw_scaled_rotated_bitmap(level_->bitmap.get(),
            pos.x, // center x
            pos.y, // center y
            400,   // destination x
            450,   // destination y
            6.,    // xscale
            6.,    // yscale
            pos.p, // angle in rad
            0      // flags (flip)
            );
    al_draw_scaled_rotated_bitmap(layer_.get(),
            pos.x, // center x
            pos.y, // center y
            400,   // destination x
            450,   // destination y
            6.,    // xscale
            6.,    // yscale
            pos.p, // angle in rad
            0      // flags (flip)
            );
    };
    auto drawmap_object = std::make_unique<Drawable>(drawmap_fct);

    level_ = std::make_unique<map>(map_name.c_str());

    if (player_)
    {
        remove(*player_);
    }
    player_ = std::make_unique<PlayerCyclist>(level_->tracks[2].get_16px_percentage());
    add(*player_);
    add(*drawmap_object);
    objects_.emplace_back(std::move(drawmap_object));

    foodspawner_ = std::make_unique<FoodSpawner>(*player_, *level_);
    foodspawner_->set_game(this);

	layer_.reset(al_create_bitmap(level_->width, level_->height));
	competitors_.set_level(level_.get());

    bg_colour = level_->bg_color;

    foods_.clear();
    auto spawner_fct = std::bind(&FoodSpawner::update, foodspawner_.get(), std::placeholders::_1);
    auto spawner_object = std::make_unique<Updatable>(spawner_fct);
    add(*spawner_object);
    objects_.emplace_back(std::move(spawner_object));

    auto pickup_fct = std::bind(&Game::update_food_pickup, this, std::placeholders::_1);
    auto pickup_object = std::make_unique<Updatable>(pickup_fct);
    add(*pickup_object);
    objects_.emplace_back(std::move(pickup_object));

    auto fooddraw_fct = std::bind(&Game::draw_food, this);
    auto fooddraw_object = std::make_unique<Drawable>(fooddraw_fct);
    add(*fooddraw_object);
    objects_.emplace_back(std::move(fooddraw_object));

    auto competitors_fct = std::bind(&Competitors::update, &(this->competitors_), std::placeholders::_1);
    auto competitors_object = std::make_unique<Updatable>(competitors_fct);
    add(*competitors_object);
    objects_.emplace_back(std::move(competitors_object));

    auto compdraw_fct = std::bind(&Game::draw_competitors, this);
    auto compdraw_object = std::make_unique<Drawable>(compdraw_fct);
    add(*compdraw_object);
    objects_.emplace_back(std::move(compdraw_object));

}

void Game::update_impl(double delta_t)
{
    if (delta_t >= 1.) {
        cerr << "lag!" << endl;
    }
    Object_aggregator::update_impl(delta_t);

    if (want_menu_)
    {
        want_menu_ = false;
        menu_.activate(true);
    }

    if (player_ && player_->paused())
    {
        disable_all();
        pause_.activate(true);
    }

    if (want_reload_)
    {
        want_reload_ = false;
        load_game(level_->location_);
    }

    if (player_ && player_->activated() && !player_->alive())
    {
        game_over();
    }

    if (player_ && player_->activated() && player_->finished())
    {
        game_won();
    }

    sum_t += delta_t;
    if (sum_t >= 1.)
    {
        sum_t = 0;
        mk_fps_string(delta_t);
    }
}

void Game::draw_impl()
{
	al_clear_to_color(bg_colour);

    Object_aggregator::draw_impl();

    al_draw_text(debug_font(), al_map_rgb_f(1,1,1), 792, 8, ALLEGRO_ALIGN_RIGHT, fps_string.c_str());
    al_flip_display();
}

void Game::handle_impl(const ALLEGRO_EVENT& event)
{
    switch (event.type) {
    case ALLEGRO_EVENT_DISPLAY_CLOSE:
        cerr << "Bye!" << endl;
        throw 1;
   }
    Object_aggregator::handle_impl(event);
}

void Game::mk_fps_string(double delta_t)
{
	ostringstream oss;
	oss << static_cast<int>(1/delta_t) << " fps";
	fps_string = oss.str();

}

void Game::draw_competitors()
{
    ALLEGRO_BITMAP *restore = al_get_target_bitmap();
    al_set_target_bitmap(layer_.get());
    al_clear_to_color(al_map_rgba(0, 0, 0, 0));
	competitors_.draw();
    al_set_target_bitmap(restore);
}

void Game::spawn_food(std::unique_ptr<Food>&& food)
{
    foods_.emplace_back(std::move(food));
}

void Game::draw_food()
{
    ALLEGRO_BITMAP *restore = al_get_target_bitmap();
    al_set_target_bitmap(layer_.get());
	auto pos = level_->tracks[player_->get_track()].get_position(level_->tracks[2], player_->get_pos());
    for (auto& f : foods_)
    {
        f->draw(-pos.p);
    }
    al_set_target_bitmap(restore);
}

void Game::update_food_pickup(double delta_t)
{
    (void) delta_t;
    auto i = std::begin(foods_);
    auto pt = player_->get_track();
    auto pp = player_->get_pos();
    auto p16p = level_->tracks[pt].get_16px_percentage();
    while (i != std::end(foods_))
    {
        auto& ptr = *i;
        if (ptr->get_track() == pt
            && std::abs(ptr->get_fpos() - pp) < p16p)
        {
            player_->add_power(ptr->get_power());
            i = foods_.erase(i);
            continue;
        }
        ++i;
    }
}
void Game::disable_all()
{
    for (auto& o: objects_)
    {
        o->activate(false);
        player_->activate(false);
        menu_.activate(false);
        pause_.activate(false);
    }
}

void Game::activate_all()
{
    for (auto& o: objects_)
    {
        o->activate(true);
        player_->activate(true);
    }
}
void Game::game_over()
{
    disable_all();
    auto drawmap_fct = [&]() {
        al_clear_to_color(al_map_rgb(0, 0, 0));
        al_draw_scaled_bitmap(gameover_.get(),
		    0, 0,
            155, 203,
		    245, 194,
		    310, 406,
		    0);
        al_draw_text(debug_font(), al_map_rgb(255, 0, 0), 400, 300, ALLEGRO_ALIGN_CENTRE, "WASTED");
        al_draw_text(debug_font(), al_map_rgb(0, 120, 120), 400, 400, ALLEGRO_ALIGN_CENTRE, "[R]etry - Space to Main Menu");
        };
    auto drawmap_object = std::make_unique<Drawable>(drawmap_fct);
    add(*drawmap_object);
    objects_.emplace_back(std::move(drawmap_object));

    auto gameover_fct = [&](const ALLEGRO_EVENT& event){
        switch(event.type)
        {
            case ALLEGRO_EVENT_KEY_DOWN:
                switch(event.keyboard.keycode)
                {
                    case ALLEGRO_KEY_R:
                        disable_all();
                        want_reload_ = true;
                    break;
                    case ALLEGRO_KEY_SPACE:
                        disable_all();
                        want_menu_ = true;
                    break;
                }
            break;
        }
    };
    auto gameover_object = std::make_unique<Listener>(gameover_fct);
    add(*gameover_object);
    objects_.emplace_back(std::move(gameover_object));
}

void Game::game_won()
{
    disable_all();
    auto drawmap_fct = [&]() {
        al_clear_to_color(al_map_rgb(0, 255, 255));
        al_draw_scaled_bitmap(gamewon_.get(),
				0, 0,
				219, 226,
				181, 144,
				438, 456,
				0);
        al_draw_text(debug_font(), al_map_rgb(255, 0, 0), 400, 300, ALLEGRO_ALIGN_CENTRE, "VICTORY");
        al_draw_text(debug_font(), al_map_rgb(255, 255, 0), 400, 400, ALLEGRO_ALIGN_CENTRE, "[R]un Again - Space to Main Menu");
        };
    auto drawmap_object = std::make_unique<Drawable>(drawmap_fct);
    add(*drawmap_object);
    objects_.emplace_back(std::move(drawmap_object));

    auto gamewon_fct = [&](const ALLEGRO_EVENT& event){
        switch(event.type)
        {
            case ALLEGRO_EVENT_KEY_DOWN:
                switch(event.keyboard.keycode)
                {
                    case ALLEGRO_KEY_R:
                        disable_all();
                        want_reload_ = true;
                    break;
                    case ALLEGRO_KEY_SPACE:
                        disable_all();
                        want_menu_ = true;;
                    break;
                }
            break;
        }
    };
    auto gamewon_object = std::make_unique<Listener>(gamewon_fct);
    add(*gamewon_object);
    objects_.emplace_back(std::move(gamewon_object));
}

int main(void) {
	try {
        std::srand(std::time(nullptr));
		Vivace engine("GAME_NAME"s, ""s);
		map::initialize();
		unique_ptr<ALLEGRO_DISPLAY, al_display_deleter> dsp(al_create_display(800, 600));
		Game game;
		Basic_loop main_loop(1/30., game);
		main_loop.register_event_source(al_get_display_event_source(dsp.get()));
		main_loop.register_event_source(al_get_keyboard_event_source());
		main_loop.run();
	}
	catch (const std::exception& ex) {
		std::cerr << ex.what() << std::endl;
	}
	catch (int ex) {}
}
<commit_msg>Upsample Game::layer_ to smooth pixels<commit_after>/*
	Copyright 2016 Jonathan Bayle, Thomas Medioni

	Licensed under the Apache License, Version 2.0 (the "License");
	you may not use this file except in compliance with the License.
	You may obtain a copy of the License at

	   http://www.apache.org/licenses/LICENSE-2.0

	Unless required by applicable law or agreed to in writing, software
	distributed under the License is distributed on an "AS IS" BASIS,
	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
	See the License for the specific language governing permissions and
	limitations under the License.
*/

#include "game.hpp"

#include <vivace/vivace.hpp>
#include "cyclist.hpp"
#include "food.hpp"
#include "map.hpp"
#include "competitors.hpp"
using namespace vivace;

#include <exception>
#include <iostream>
#include <string>
#include <sstream>
#include <ctime>

using namespace std;

#include <glm/glm.hpp>

using namespace glm;

Game::Game() : want_menu_(false), want_reload_(false)
{
    bg_colour = al_map_rgb(0, 0, 40);
    add(menu_);
    add(pause_);

	unique_ptr<Menu> submenu = make_map_selection_menu(this, &menu_);
	Menu* backup = submenu.get();
    menu_.add_entry("PLAY", std::move(submenu));
    menu_.add_entry("QUIT", [&]() { throw 1;});

    pause_.add_entry("RESUME", [&]() { pause_.activate(false);
                                       player_->set_pause(false);
                                       activate_all();});
    pause_.activate(false);
    gameover_ = std::unique_ptr<ALLEGRO_BITMAP, al_bitmap_deleter>(reinterpret_cast<ALLEGRO_BITMAP*>(al_img_loader("data/gameover.png")));
	menubg_ = std::shared_ptr<ALLEGRO_BITMAP>(reinterpret_cast<ALLEGRO_BITMAP*>(al_img_loader("data/menu.png")), al_bitmap_deleter());
	if (menubg_.get()) {
		menu_.set_background(menubg_, 2.f, 2.f);
		menu_.set_bg_col(al_map_rgb(215, 123, 186));
		menu_.set_entry_settings(500.f, 360.f, 2.f);
		backup->set_background(menubg_, 2.f, 2.f);
		backup->set_bg_col(al_map_rgb(215, 123, 186));
		backup->set_entry_settings(500.f, 360.f, 2.f);
		pause_.set_background(menubg_, 2.f, 2.f);
		pause_.set_bg_col(al_map_rgb(215, 123, 186));
		pause_.set_entry_settings(500.f, 360.f, 2.f);
	}

	gamewon_ = std::unique_ptr<ALLEGRO_BITMAP, al_bitmap_deleter>(reinterpret_cast<ALLEGRO_BITMAP*>(al_img_loader("data/victory.png")));
}

void Game::load_game(std::string map_name)
{
    auto it = std::begin(objects_);
    while (it != std::end(objects_))
    {
        remove((**it));
        it = objects_.erase(it);
    }

    auto drawmap_fct = [&]() {
        auto pos = level_->tracks[player_->get_track()].get_position(level_->tracks[2], player_->get_pos());
        al_draw_scaled_rotated_bitmap(level_->bitmap.get(),
            pos.x, // center x
            pos.y, // center y
            400,   // destination x
            450,   // destination y
            6.,    // xscale
            6.,    // yscale
            pos.p, // angle in rad
            0      // flags (flip)
            );
    al_draw_scaled_rotated_bitmap(layer_.get(),
            pos.x*2.f, // center x
            pos.y*2.f, // center y
            400,   // destination x
            450,   // destination y
            3.,    // xscale
            3.,    // yscale
            pos.p, // angle in rad
            0      // flags (flip)
            );
    };
    auto drawmap_object = std::make_unique<Drawable>(drawmap_fct);

    level_ = std::make_unique<map>(map_name.c_str());

    if (player_)
    {
        remove(*player_);
    }
    player_ = std::make_unique<PlayerCyclist>(level_->tracks[2].get_16px_percentage());
    add(*player_);
    add(*drawmap_object);
    objects_.emplace_back(std::move(drawmap_object));

    foodspawner_ = std::make_unique<FoodSpawner>(*player_, *level_);
    foodspawner_->set_game(this);

	layer_.reset(al_create_bitmap(level_->width * 2, level_->height * 2));

	// Set scale transform on map
	ALLEGRO_TRANSFORM transform;
	al_identity_transform(&transform);
	al_scale_transform(&transform, 2.f, 2.f);
	ALLEGRO_BITMAP *restore = al_get_target_bitmap();
    al_set_target_bitmap(layer_.get());
    al_use_transform(&transform);
    al_set_target_bitmap(restore);

	competitors_.set_level(level_.get());

    bg_colour = level_->bg_color;

    foods_.clear();
    auto spawner_fct = std::bind(&FoodSpawner::update, foodspawner_.get(), std::placeholders::_1);
    auto spawner_object = std::make_unique<Updatable>(spawner_fct);
    add(*spawner_object);
    objects_.emplace_back(std::move(spawner_object));

    auto pickup_fct = std::bind(&Game::update_food_pickup, this, std::placeholders::_1);
    auto pickup_object = std::make_unique<Updatable>(pickup_fct);
    add(*pickup_object);
    objects_.emplace_back(std::move(pickup_object));

    auto fooddraw_fct = std::bind(&Game::draw_food, this);
    auto fooddraw_object = std::make_unique<Drawable>(fooddraw_fct);
    add(*fooddraw_object);
    objects_.emplace_back(std::move(fooddraw_object));

    auto competitors_fct = std::bind(&Competitors::update, &(this->competitors_), std::placeholders::_1);
    auto competitors_object = std::make_unique<Updatable>(competitors_fct);
    add(*competitors_object);
    objects_.emplace_back(std::move(competitors_object));

    auto compdraw_fct = std::bind(&Game::draw_competitors, this);
    auto compdraw_object = std::make_unique<Drawable>(compdraw_fct);
    add(*compdraw_object);
    objects_.emplace_back(std::move(compdraw_object));

}

void Game::update_impl(double delta_t)
{
    if (delta_t >= 1.) {
        cerr << "lag!" << endl;
    }
    Object_aggregator::update_impl(delta_t);

    if (want_menu_)
    {
        want_menu_ = false;
        menu_.activate(true);
    }

    if (player_ && player_->paused())
    {
        disable_all();
        pause_.activate(true);
    }

    if (want_reload_)
    {
        want_reload_ = false;
        load_game(level_->location_);
    }

    if (player_ && player_->activated() && !player_->alive())
    {
        game_over();
    }

    if (player_ && player_->activated() && player_->finished())
    {
        game_won();
    }

    sum_t += delta_t;
    if (sum_t >= 1.)
    {
        sum_t = 0;
        mk_fps_string(delta_t);
    }
}

void Game::draw_impl()
{
	al_clear_to_color(bg_colour);

    Object_aggregator::draw_impl();

    al_draw_text(debug_font(), al_map_rgb_f(1,1,1), 792, 8, ALLEGRO_ALIGN_RIGHT, fps_string.c_str());
    al_flip_display();
}

void Game::handle_impl(const ALLEGRO_EVENT& event)
{
    switch (event.type) {
    case ALLEGRO_EVENT_DISPLAY_CLOSE:
        cerr << "Bye!" << endl;
        throw 1;
   }
    Object_aggregator::handle_impl(event);
}

void Game::mk_fps_string(double delta_t)
{
	ostringstream oss;
	oss << static_cast<int>(1/delta_t) << " fps";
	fps_string = oss.str();

}

void Game::draw_competitors()
{
    ALLEGRO_BITMAP *restore = al_get_target_bitmap();
    al_set_target_bitmap(layer_.get());
    al_clear_to_color(al_map_rgba(0, 0, 0, 0));
	competitors_.draw();
    al_set_target_bitmap(restore);
}

void Game::spawn_food(std::unique_ptr<Food>&& food)
{
    foods_.emplace_back(std::move(food));
}

void Game::draw_food()
{
    ALLEGRO_BITMAP *restore = al_get_target_bitmap();
    al_set_target_bitmap(layer_.get());
	auto pos = level_->tracks[player_->get_track()].get_position(level_->tracks[2], player_->get_pos());
    for (auto& f : foods_)
    {
        f->draw(-pos.p);
    }
    al_set_target_bitmap(restore);
}

void Game::update_food_pickup(double delta_t)
{
    (void) delta_t;
    auto i = std::begin(foods_);
    auto pt = player_->get_track();
    auto pp = player_->get_pos();
    auto p16p = level_->tracks[pt].get_16px_percentage();
    while (i != std::end(foods_))
    {
        auto& ptr = *i;
        if (ptr->get_track() == pt
            && std::abs(ptr->get_fpos() - pp) < p16p)
        {
            player_->add_power(ptr->get_power());
            i = foods_.erase(i);
            continue;
        }
        ++i;
    }
}
void Game::disable_all()
{
    for (auto& o: objects_)
    {
        o->activate(false);
        player_->activate(false);
        menu_.activate(false);
        pause_.activate(false);
    }
}

void Game::activate_all()
{
    for (auto& o: objects_)
    {
        o->activate(true);
        player_->activate(true);
    }
}
void Game::game_over()
{
    disable_all();
    auto drawmap_fct = [&]() {
        al_clear_to_color(al_map_rgb(0, 0, 0));
        al_draw_scaled_bitmap(gameover_.get(),
		    0, 0,
            155, 203,
		    245, 194,
		    310, 406,
		    0);
        al_draw_text(debug_font(), al_map_rgb(255, 0, 0), 400, 300, ALLEGRO_ALIGN_CENTRE, "WASTED");
        al_draw_text(debug_font(), al_map_rgb(0, 120, 120), 400, 400, ALLEGRO_ALIGN_CENTRE, "[R]etry - Space to Main Menu");
        };
    auto drawmap_object = std::make_unique<Drawable>(drawmap_fct);
    add(*drawmap_object);
    objects_.emplace_back(std::move(drawmap_object));

    auto gameover_fct = [&](const ALLEGRO_EVENT& event){
        switch(event.type)
        {
            case ALLEGRO_EVENT_KEY_DOWN:
                switch(event.keyboard.keycode)
                {
                    case ALLEGRO_KEY_R:
                        disable_all();
                        want_reload_ = true;
                    break;
                    case ALLEGRO_KEY_SPACE:
                        disable_all();
                        want_menu_ = true;
                    break;
                }
            break;
        }
    };
    auto gameover_object = std::make_unique<Listener>(gameover_fct);
    add(*gameover_object);
    objects_.emplace_back(std::move(gameover_object));
}

void Game::game_won()
{
    disable_all();
    auto drawmap_fct = [&]() {
        al_clear_to_color(al_map_rgb(0, 255, 255));
        al_draw_scaled_bitmap(gamewon_.get(),
				0, 0,
				219, 226,
				181, 144,
				438, 456,
				0);
        al_draw_text(debug_font(), al_map_rgb(255, 0, 0), 400, 300, ALLEGRO_ALIGN_CENTRE, "VICTORY");
        al_draw_text(debug_font(), al_map_rgb(255, 255, 0), 400, 400, ALLEGRO_ALIGN_CENTRE, "[R]un Again - Space to Main Menu");
        };
    auto drawmap_object = std::make_unique<Drawable>(drawmap_fct);
    add(*drawmap_object);
    objects_.emplace_back(std::move(drawmap_object));

    auto gamewon_fct = [&](const ALLEGRO_EVENT& event){
        switch(event.type)
        {
            case ALLEGRO_EVENT_KEY_DOWN:
                switch(event.keyboard.keycode)
                {
                    case ALLEGRO_KEY_R:
                        disable_all();
                        want_reload_ = true;
                    break;
                    case ALLEGRO_KEY_SPACE:
                        disable_all();
                        want_menu_ = true;;
                    break;
                }
            break;
        }
    };
    auto gamewon_object = std::make_unique<Listener>(gamewon_fct);
    add(*gamewon_object);
    objects_.emplace_back(std::move(gamewon_object));
}

int main(void) {
	try {
        std::srand(std::time(nullptr));
		Vivace engine("GAME_NAME"s, ""s);
		map::initialize();
		unique_ptr<ALLEGRO_DISPLAY, al_display_deleter> dsp(al_create_display(800, 600));
		Game game;
		Basic_loop main_loop(1/30., game);
		main_loop.register_event_source(al_get_display_event_source(dsp.get()));
		main_loop.register_event_source(al_get_keyboard_event_source());
		main_loop.run();
	}
	catch (const std::exception& ex) {
		std::cerr << ex.what() << std::endl;
	}
	catch (int ex) {}
}
<|endoftext|>