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

#include <algorithm>
#include <stdexcept>
#include <vector>

#include <np-divs/matrix_arrays.hpp>
#include <np-divs/np_divs.hpp>
#include <flann/util/matrix.h>
#include <svm.h>

namespace sdm {

// TODO memory ownership with this is all screwy...make it clearer
template <typename Scalar>
class SDM {
    const svm_model &svm;
    const svm_problem &svm_prob; // needs to live at least as long as the model
    const Kernel &kernel;

    const flann::Matrix<Scalar> *training_bags;
    size_t num_training;

    public:
        SDM(const svm_model &svm, const svm_problem &svm_prob,
            const Kernel &kernel,
            const flann::Matrix<Scalar> *training_bags, size_t num_training)
        :
            svm(svm), svm_prob(svm_prob), kernel(kernel),
            training_bags(training_bags), num_training(num_training)
        { }

        std::vector<bool> predict(
                const flann::Matrix<Scalar> *test_dists, size_t num_test)
            const;

        std::vector<bool> predict(
                const flann::Matrix<Scalar> *test_dists, size_t num_test,
                std::vector<double> &values)
            const;

};

// TODO: support multi-class classification
// TODO: a mass-training method for more than one kernel
template <typename Scalar>
SDM<Scalar> train_sdm(
    const flann::Matrix<Scalar> *training_bags, size_t num_train,
    const std::vector<int> &labels,
    const Kernel &kernel,
    const NPDivs::DivParams &div_params,
    const svm_parameter &svm_params
    // TODO: cross-validation options
);

////////////////////////////////////////////////////////////////////////////////
// Template member function implementations

void store_kernel_matrix(svm_problem &prob, double *divs, bool alloc) {
    size_t n = prob.l;
    if (alloc) prob.x = new svm_node*[n];

    for (size_t i = 0; i < n; i++) {
        if (alloc) prob.x[i] = new svm_node[n];
        for (size_t j = 0; j < n; j++) {
            prob.x[i][j].index = j;
            prob.x[i][j].value = divs[i + j*n];
        }
    }
}

namespace detail {
    void print_null(const char *s) {}
}

template <typename Scalar>
SDM<Scalar> train_sdm(
        const flann::Matrix<Scalar> *training_bags, size_t num_train,
        const std::vector<int> &labels,
        const Kernel &kernel,
        const NPDivs::DivParams &div_params,
        const svm_parameter &svm_params)
{   // TODO - logging

    // copy the svm params so we can change them
    svm_parameter svm_p = svm_params;
    svm_p.svm_type = C_SVC;
    svm_p.kernel_type = PRECOMPUTED;

    // make libSVM shut up  -  TODO real logging
    svm_set_print_string_function(&detail::print_null);

    // set up the basic svm_problem, except for the kernel values
    svm_problem *prob = new svm_problem;
    prob->l = num_train;
    prob->y = new double[num_train];
    std::copy(labels.begin(), labels.end(), prob->y);

    // first compute divergences
    flann::Matrix<double>* divs =
        NPDivs::alloc_matrix_array<double>(1, num_train, num_train);
    np_divs(training_bags, num_train, kernel.getDivFunc(), divs,
            div_params, false);

    // TODO cross-validate over possibilities for the svm/kernel parameters

    // build up our best kernel matrix
    kernel.transformDivergences(divs->ptr(), num_train);
    project_to_kernel(divs->ptr(), num_train);

    // train an SVM on the whole thing
    // TODO after doing CV, won't need to alloc here
    store_kernel_matrix(*prob, divs->ptr(), true);
    const char* error = svm_check_parameter(prob, &svm_p);
    if (error != NULL)
        throw std::domain_error(error);
    svm_model *svm = svm_train(prob, &svm_p);

    return SDM<Scalar>(*svm, *prob, kernel, training_bags, num_train);
}

} // end namespace

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

#include <algorithm>
#include <stdexcept>
#include <vector>

#include <np-divs/matrix_arrays.hpp>
#include <np-divs/np_divs.hpp>
#include <flann/util/matrix.h>
#include <svm.h>

namespace sdm {

// TODO memory ownership with this is all screwy...make it clearer
template <typename Scalar>
class SDM {
    const svm_model &svm;
    const svm_problem &svm_prob; // needs to live at least as long as the model
    const Kernel &kernel;

    const flann::Matrix<Scalar> *training_bags;
    size_t num_training;

    public:
        SDM(const svm_model &svm, const svm_problem &svm_prob,
            const Kernel &kernel,
            const flann::Matrix<Scalar> *training_bags, size_t num_training)
        :
            svm(svm), svm_prob(svm_prob), kernel(kernel),
            training_bags(training_bags), num_training(num_training)
        { }

        std::vector<bool> predict(
                const flann::Matrix<Scalar> *test_dists, size_t num_test)
            const;

        std::vector<bool> predict(
                const flann::Matrix<Scalar> *test_dists, size_t num_test,
                std::vector<double> &values)
            const;

};

// TODO: support multi-class classification
// TODO: a mass-training method for more than one kernel
template <typename Scalar>
SDM<Scalar> train_sdm(
    const flann::Matrix<Scalar> *training_bags, size_t num_train,
    const std::vector<int> &labels,
    const Kernel &kernel,
    const NPDivs::DivParams &div_params,
    const svm_parameter &svm_params
    // TODO: cross-validation options
);

////////////////////////////////////////////////////////////////////////////////
// Template function implementations

namespace detail {
    void store_kernel_matrix(svm_problem &prob, double *divs, bool alloc) {
        size_t n = prob.l;
        if (alloc) prob.x = new svm_node*[n];

        for (size_t i = 0; i < n; i++) {
            if (alloc) prob.x[i] = new svm_node[n];
            for (size_t j = 0; j < n; j++) {
                prob.x[i][j].index = j;
                prob.x[i][j].value = divs[i + j*n];
            }
        }
    }

    void print_null(const char *s) {}
}

template <typename Scalar>
SDM<Scalar> train_sdm(
        const flann::Matrix<Scalar> *training_bags, size_t num_train,
        const std::vector<int> &labels,
        const Kernel &kernel,
        const NPDivs::DivParams &div_params,
        const svm_parameter &svm_params)
{   // TODO - logging

    // copy the svm params so we can change them
    svm_parameter svm_p = svm_params;
    svm_p.svm_type = C_SVC;
    svm_p.kernel_type = PRECOMPUTED;

    // make libSVM shut up  -  TODO real logging
    svm_set_print_string_function(&detail::print_null);

    // set up the basic svm_problem, except for the kernel values
    svm_problem *prob = new svm_problem;
    prob->l = num_train;
    prob->y = new double[num_train];
    std::copy(labels.begin(), labels.end(), prob->y);

    // first compute divergences
    flann::Matrix<double>* divs =
        NPDivs::alloc_matrix_array<double>(1, num_train, num_train);
    np_divs(training_bags, num_train, kernel.getDivFunc(), divs,
            div_params, false);

    // TODO cross-validate over possibilities for the svm/kernel parameters

    // build up our best kernel matrix
    kernel.transformDivergences(divs->ptr(), num_train);
    project_to_kernel(divs->ptr(), num_train);

    // train an SVM on the whole thing
    // TODO after doing CV, won't need to alloc here
    detail::store_kernel_matrix(*prob, divs->ptr(), true);
    const char* error = svm_check_parameter(prob, &svm_p);
    if (error != NULL)
        throw std::domain_error(error);
    svm_model *svm = svm_train(prob, &svm_p);

    return SDM<Scalar>(*svm, *prob, kernel, training_bags, num_train);
}

} // end namespace

#endif
<|endoftext|>


<commit_before>
#include "ksp_plugin/interface.hpp"

#include <algorithm>
#include <array>
#include <chrono>
#include <type_traits>

#include "quantities/quantities.hpp"
#include "quantities/si.hpp"

namespace principia {
namespace interface {

using quantities::Infinity;
using quantities::Time;
using quantities::si::Nano;
using quantities::si::Second;

namespace {
constexpr int monitor_count = 64;
constexpr int window_size = 500;

struct Monitor {
  std::string* name = nullptr;
  std::chrono::steady_clock::time_point start_time{};
  bool is_running = false;

  int window_index = 0;
  Time total_Δt;
  Time min_Δt = Infinity<Time>();
  Time max_Δt = -Infinity<Time>();
};

static_assert(
    std::is_trivially_destructible<std::array<Monitor, monitor_count>>::value,
    "An array of |Monitor|s should be trivially destructible");
std::array<Monitor, monitor_count> monitors{};
}  // namespace

// No journalling to avoid measuring overhead from that; these functions have no
// side effects aside from logging and changing the internal state of the
// monitors.

void principia__MonitorSetName(int const i, char const* const name) {
  Monitor& monitor = monitors[i];
  if (monitor.name == nullptr) {
    monitor.name = new std::string(name);
  }
}

void principia__MonitorStart(int const i) {
  Monitor& monitor = monitors[i];
  if (!monitor.is_running) {
    monitor.is_running = true;
    monitor.start_time = std::chrono::steady_clock::now();
  }
}

void principia__MonitorStop(int const i) {
  Monitor& monitor = monitors[i];
  if (monitor.is_running) {
    monitor.is_running = false;
    auto const Δt =
        std::chrono::nanoseconds(
            std::chrono::steady_clock::now() - monitor.start_time).count() *
        Nano(Second);
    monitor.min_Δt = std::min(monitor.min_Δt, Δt);
    monitor.max_Δt = std::max(monitor.max_Δt, Δt);
    monitor.total_Δt += Δt;
    ++monitor.window_index %= window_size;
    if (monitor.window_index == 0) {
      LOG(INFO) << "[Monitor " << i
                <<(monitor.name == nullptr ? "" : ": " + *monitor.name) << "] "
                << "min = " << monitor.min_Δt << ", max = " << monitor.max_Δt
                << u8", μ = " << monitor.total_Δt / window_size;
      monitor.min_Δt = Infinity<Time>();
      monitor.max_Δt = -Infinity<Time>();
      monitor.total_Δt = Time();
    }
  }
}

}  // namespace interface
}  // namespace principia
<commit_msg>after pleroy's review<commit_after>
#include "ksp_plugin/interface.hpp"

#include <algorithm>
#include <array>
#include <chrono>
#include <type_traits>

#include "quantities/quantities.hpp"
#include "quantities/si.hpp"

namespace principia {
namespace interface {

using quantities::Infinity;
using quantities::Time;
using quantities::si::Nano;
using quantities::si::Second;

namespace {
constexpr int monitor_count = 64;
constexpr int window_size = 500;

struct Monitor {
  std::string* name = nullptr;
  std::chrono::steady_clock::time_point start_time{};
  bool is_running = false;

  int window_index = 0;
  Time total_Δt;
  Time min_Δt = Infinity<Time>();
  Time max_Δt = -Infinity<Time>();
};

static_assert(
    std::is_trivially_destructible<std::array<Monitor, monitor_count>>::value,
    "An array of |Monitor|s should be trivially destructible");
std::array<Monitor, monitor_count> monitors{};
}  // namespace

// No journalling to avoid measuring overhead from that; these functions have no
// side effects aside from logging and changing the internal state of the
// monitors.

void principia__MonitorSetName(int const i, char const* const name) {
  Monitor& monitor = monitors[i];
  if (monitor.name == nullptr) {
    monitor.name = new std::string(name);
  }
}

void principia__MonitorStart(int const i) {
  Monitor& monitor = monitors[i];
  if (!monitor.is_running) {
    monitor.is_running = true;
    monitor.start_time = std::chrono::steady_clock::now();
  }
}

void principia__MonitorStop(int const i) {
  Monitor& monitor = monitors[i];
  if (monitor.is_running) {
    monitor.is_running = false;
    auto const Δt =
        std::chrono::nanoseconds(
            std::chrono::steady_clock::now() - monitor.start_time).count() *
        Nano(Second);
    monitor.min_Δt = std::min(monitor.min_Δt, Δt);
    monitor.max_Δt = std::max(monitor.max_Δt, Δt);
    monitor.total_Δt += Δt;
    ++monitor.window_index %= window_size;
    if (monitor.window_index == 0) {
      LOG(INFO) << "[Monitor " << i
                << (monitor.name == nullptr ? "" : (": " + *monitor.name))
                << "] min = " << monitor.min_Δt << ", max = " << monitor.max_Δt
                << u8", μ = " << monitor.total_Δt / window_size;
      monitor.min_Δt = Infinity<Time>();
      monitor.max_Δt = -Infinity<Time>();
      monitor.total_Δt = Time();
    }
  }
}

}  // namespace interface
}  // namespace principia
<|endoftext|>


<commit_before>#include <cstdint>
#include <string>
#include <iostream>
#include <fstream>
#include "Symbol.hpp"
#include "Trade.hpp"
#include "Stats.hpp"

const char * const infile = "input.csv";
const char * const outfile = "output.csv";

namespace Symbol = ::QLTest::Symbol;

using std::int32_t;

const int32_t N = Symbol::BASE3;

int main() {
  // use stack for speed
  QLTest::Stats tradeStats[N];

  {  // load trade records from input file
    std::ifstream in(infile);
    if (!in) {
      std::cerr << "Couldn't open file " << infile << std::endl;
      return 1;
    }

    std::string line;
    QLTest::Trade trade;
    while (getline(in, line)) {
      trade.load(line);
      tradeStats[trade.symbolId].add(trade);
    }
  }  // input file get closed here

  {  // output trade statistics per symbol
    std::ofstream out(outfile);
    if (!out) {
      std::cerr << "Couldn't open file " << outfile << std::endl;
      return 1;
    }

    out.exceptions(std::ofstream::failbit | std::ofstream::badbit);
    std::string symbol(3, 'a');
    for (int32_t i = 0; i < N; ++i) {
      if (tradeStats[i].getTotalVolume() > 0) {
        Symbol::getSymbol(i, symbol);
        out << symbol << ',' << tradeStats[i] << '\n';
      }
    }
  }  // output file get flushed and closed here

  return 0;
}
<commit_msg>add error checks for ifstream & ofstream<commit_after>#include <cstdint>
#include <string>
#include <iostream>
#include <fstream>
#include "Symbol.hpp"
#include "Trade.hpp"
#include "Stats.hpp"

const char * const infile = "input.csv";
const char * const outfile = "output.csv";

namespace Symbol = ::QLTest::Symbol;

using std::int32_t;

const int32_t N = Symbol::BASE3;

int main() {
  // use stack for speed
  QLTest::Stats tradeStats[N];

  {  // load trade records from input file
    std::ifstream in(infile);
    if (!in) {
      std::cerr << "Couldn't open file " << infile << std::endl;
      return 1;
    }

    std::string line;
    QLTest::Trade trade;
    while (getline(in, line)) {
      trade.load(line);
      tradeStats[trade.symbolId].add(trade);
    }

    if (!in.eof()) {
      std::cerr << "Error while reading file " << infile << std::endl;
      return 1;
    }
  }  // input file get closed here

  {  // output trade statistics per symbol
    std::ofstream out(outfile);
    if (!out) {
      std::cerr << "Couldn't open file " << outfile << std::endl;
      return 1;
    }

    std::string symbol(3, 'a');
    for (int32_t i = 0; i < N; ++i) {
      if (tradeStats[i].getTotalVolume() > 0) {
        Symbol::getSymbol(i, symbol);
        out << symbol << ',' << tradeStats[i] << '\n';
        if (out.fail()) break;
      }
    }

    if (out.good()) out.flush();

    if (out.fail()) {
      std::cerr << "Error while writing file " << outfile << std::endl;
      return 1;
    }
  }  // output file get closed here

  return 0;
}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
**   * Redistributions of source code must retain the above copyright
**     notice, this list of conditions and the following disclaimer.
**   * Redistributions in binary form must reproduce the above copyright
**     notice, this list of conditions and the following disclaimer in
**     the documentation and/or other materials provided with the
**     distribution.
**   * Neither the name of The Qt Company Ltd nor the names of its
**     contributors may be used to endorse or promote products derived
**     from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include <QApplication>
#include <QMessageBox>
#include <QUuid>

#include "chat.h"
#include "chat_adaptor.h"
#include "chat_interface.h"

#define DBUS_PATH "/qtapp"
#define DBUS_IFACE "com.pega.rasmus"

ChatMainWindow::ChatMainWindow()
    : m_nickname(QLatin1String("nickname"))
{
    setupUi(this);
    sendButton->setEnabled(false);

    connect(messageLineEdit, SIGNAL(textChanged(QString)),
            this, SLOT(textChangedSlot(QString)));
    connect(sendButton, SIGNAL(clicked(bool)), this, SLOT(sendClickedSlot()));
    connect(actionChangeNickname, SIGNAL(triggered(bool)), this, SLOT(changeNickname()));
    connect(actionAboutQt, SIGNAL(triggered(bool)), this, SLOT(aboutQt()));
    connect(qApp, SIGNAL(lastWindowClosed()), this, SLOT(exiting()));

    // add our D-Bus interface and connect to D-Bus
    new ChatAdaptor(this);
    QDBusConnection::sessionBus().registerObject(DBUS_PATH, this);
    //org::example::chat *iface;
    ComPegaRasmusInterface *iface;
    iface = new ::ComPegaRasmusInterface(QString(), QString(), QDBusConnection::sessionBus(), this);
    //connect(iface, SIGNAL(message(QString,QString)), this, SLOT(messageSlot(QString,QString)));
    QDBusConnection::sessionBus().connect(QString(), QString(), DBUS_IFACE, "message", this, SLOT(messageSlot(QString,QString)));
    connect(iface, SIGNAL(action(QString,QString)), this, SLOT(actionSlot(QString,QString)));
    connect(iface, SIGNAL(command(QString)), this, SLOT(sltCommand(QString)));

    m_nickname = QUuid::createUuid().toString();
    emit action(m_nickname, QLatin1String("joins the chat"));
}

ChatMainWindow::~ChatMainWindow()
{
}

void ChatMainWindow::rebuildHistory()
{
    QString history = m_messages.join( QLatin1String("\n" ) );
    chatHistory->setPlainText(history);
}

void ChatMainWindow::messageSlot(const QString &nickname, const QString &text)
{
    QString msg( QLatin1String("<%1> %2") );
    msg = msg.arg(nickname, text);
    m_messages.append(msg);

    if (m_messages.count() > 100)
        m_messages.removeFirst();
    rebuildHistory();
}

void ChatMainWindow::actionSlot(const QString &nickname, const QString &text)
{
    QString msg( QLatin1String("* %1 %2") );
    msg = msg.arg(nickname, text);
    m_messages.append(msg);

    if (m_messages.count() > 100)
        m_messages.removeFirst();
    rebuildHistory();
}

void ChatMainWindow::sltCommand(const QString &text)
{
    QString msg( QLatin1String("cmd => %1") );
    msg = msg.arg(text);
    m_messages.append(msg);

    if (m_messages.count() > 100)
        m_messages.removeFirst();
    rebuildHistory();

    if (text == "quit") {
        close();
    }
}

void ChatMainWindow::textChangedSlot(const QString &newText)
{
    sendButton->setEnabled(!newText.isEmpty());
}

void ChatMainWindow::sendClickedSlot()
{
    //emit message(m_nickname, messageLineEdit->text());
    QDBusMessage msg = QDBusMessage::createSignal(DBUS_PATH, DBUS_IFACE, "message");
    msg << m_nickname << messageLineEdit->text();
    QDBusConnection::sessionBus().send(msg);
    messageLineEdit->setText(QString());
}

void ChatMainWindow::changeNickname()
{
    QString old = m_nickname;
    m_nickname = QUuid::createUuid().toString();
    emit action(m_nickname, QLatin1String("joins the chat"));
    emit action(old, QString("is now known as %1").arg(m_nickname));
}

void ChatMainWindow::aboutQt()
{
    QMessageBox::aboutQt(this);
}

void ChatMainWindow::exiting()
{
    emit action(m_nickname, QLatin1String("leaves the chat"));
}

int main(int argc, char **argv)
{
    QApplication app(argc, argv);

    if (!QDBusConnection::sessionBus().isConnected()) {
        qWarning("Cannot connect to the D-Bus session bus.\n"
                 "Please check your system settings and try again.\n");
        return 1;
    }

    ChatMainWindow chat;
    chat.show();
    return app.exec();
}
<commit_msg>update chat.cpp, use both session/system bus<commit_after>/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
**   * Redistributions of source code must retain the above copyright
**     notice, this list of conditions and the following disclaimer.
**   * Redistributions in binary form must reproduce the above copyright
**     notice, this list of conditions and the following disclaimer in
**     the documentation and/or other materials provided with the
**     distribution.
**   * Neither the name of The Qt Company Ltd nor the names of its
**     contributors may be used to endorse or promote products derived
**     from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include <QApplication>
#include <QMessageBox>
#include <QUuid>

#include "chat.h"
#include "chat_adaptor.h"
#include "chat_interface.h"

#define DBUS_PATH "/qtapp"
#define DBUS_IFACE "com.pega.rasmus"

enum ENUM_BUS {
    USE_SESSION_BUS,
    USE_SYSTEM_BUS
};

ENUM_BUS g_session_bus = USE_SYSTEM_BUS;

QDBusConnection get_bus()
{
    if (g_session_bus == USE_SESSION_BUS) {
        qDebug() << "session bus...";
        return QDBusConnection::sessionBus();
    } else if (g_session_bus == USE_SYSTEM_BUS) {
        qDebug() << "system bus...";
        return QDBusConnection::systemBus();
    } else {
        return QDBusConnection("qtchat");
    }
}

ChatMainWindow::ChatMainWindow()
    : m_nickname(QLatin1String("nickname"))
{
    setupUi(this);
    sendButton->setEnabled(false);

    connect(messageLineEdit, SIGNAL(textChanged(QString)),
            this, SLOT(textChangedSlot(QString)));
    connect(sendButton, SIGNAL(clicked(bool)), this, SLOT(sendClickedSlot()));
    connect(actionChangeNickname, SIGNAL(triggered(bool)), this, SLOT(changeNickname()));
    connect(actionAboutQt, SIGNAL(triggered(bool)), this, SLOT(aboutQt()));
    connect(qApp, SIGNAL(lastWindowClosed()), this, SLOT(exiting()));

    // add our D-Bus interface and connect to D-Bus
    new ChatAdaptor(this);
    //QDBusConnection::sessionBus().registerObject(DBUS_PATH, this);
    get_bus().registerObject(DBUS_PATH, this);

    ComPegaRasmusInterface *iface;
    //iface = new ::ComPegaRasmusInterface(QString(), QString(), QDBusConnection::sessionBus(), this);
    iface = new ::ComPegaRasmusInterface(QString(), QString(), get_bus(), this);

    //get_bus().connect(QString(), QString(), DBUS_IFACE, "message", this, SLOT(messageSlot(QString,QString)));
    connect(iface, SIGNAL(message(QString,QString)), this, SLOT(messageSlot(QString,QString)));

    connect(iface, SIGNAL(action(QString,QString)), this, SLOT(actionSlot(QString,QString)));

    //get_bus().connect(QString(), QString(), DBUS_IFACE, "command", this, SLOT(sltCommand(QString)));
    connect(iface, SIGNAL(command(QString)), this, SLOT(sltCommand(QString)));

    m_nickname = QUuid::createUuid().toString();
    emit action(m_nickname, QLatin1String("joins the chat"));
}

ChatMainWindow::~ChatMainWindow()
{
}

void ChatMainWindow::rebuildHistory()
{
    QString history = m_messages.join( QLatin1String("\n" ) );
    chatHistory->setPlainText(history);
}

void ChatMainWindow::messageSlot(const QString &nickname, const QString &text)
{
    qDebug() << Q_FUNC_INFO << nickname << " " << text;
    QString msg( QLatin1String("<%1> %2") );
    msg = msg.arg(nickname, text);
    m_messages.append(msg);

    if (m_messages.count() > 100)
        m_messages.removeFirst();
    rebuildHistory();
}

void ChatMainWindow::actionSlot(const QString &nickname, const QString &text)
{
    qDebug() << Q_FUNC_INFO << nickname << " " << text;
    QString msg( QLatin1String("* %1 %2") );
    msg = msg.arg(nickname, text);
    m_messages.append(msg);

    if (m_messages.count() > 100)
        m_messages.removeFirst();
    rebuildHistory();
}

void ChatMainWindow::sltCommand(const QString &text)
{
    qDebug() << Q_FUNC_INFO << text;
    QString msg( QLatin1String("cmd => %1") );
    msg = msg.arg(text);
    m_messages.append(msg);

    if (m_messages.count() > 100)
        m_messages.removeFirst();
    rebuildHistory();

    if (text == "quit") {
        close();
    }
}

void ChatMainWindow::textChangedSlot(const QString &newText)
{
    sendButton->setEnabled(!newText.isEmpty());
}

void ChatMainWindow::sendClickedSlot()
{
    //emit message(m_nickname, messageLineEdit->text());
    QDBusMessage msg = QDBusMessage::createSignal(DBUS_PATH, DBUS_IFACE, "message");
    msg << m_nickname << messageLineEdit->text();
    get_bus().send(msg);
    messageLineEdit->setText(QString());
}

void ChatMainWindow::changeNickname()
{
    QString old = m_nickname;
    m_nickname = QUuid::createUuid().toString();
    emit action(m_nickname, QLatin1String("joins the chat"));
    emit action(old, QString("is now known as %1").arg(m_nickname));
}

void ChatMainWindow::aboutQt()
{
    QMessageBox::aboutQt(this);
}

void ChatMainWindow::exiting()
{
    emit action(m_nickname, QLatin1String("leaves the chat"));
}

int main(int argc, char **argv)
{
    QApplication app(argc, argv);
	bool ret = false;

    g_session_bus = USE_SYSTEM_BUS;
	if (argc > 1 && strcmp(argv[1], "session")==0) {
		g_session_bus = USE_SESSION_BUS;
        ret = QDBusConnection::sessionBus().isConnected();
        qDebug() << "use session bus:" << ret;
	} else {
        ret = QDBusConnection::systemBus().isConnected();
        qDebug() << "use system bus:" << ret;
    }

	if (!ret) {
        qWarning("Cannot connect to the D-Bus session bus.\n"
                 "Please check your system settings and try again.\n");
        return 1;
    }

    ChatMainWindow chat;
    chat.show();
    return app.exec();
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: codemaker.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 02:08:59 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    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., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#include "sal/config.h"

#include "codemaker/codemaker.hxx"

#include "codemaker/options.hxx"
#include "codemaker/typemanager.hxx"
#include "codemaker/unotype.hxx"

#include "osl/diagnose.h"
#include "registry/reader.hxx"
#include "registry/types.h"
#include "rtl/strbuf.h"
#include "rtl/string.h"
#include "rtl/string.hxx"
#include "rtl/ustring.hxx"
#include "sal/types.h"

#include <vector>

namespace {

void checkNoTypeArguments(std::vector< rtl::OString > const & arguments) {
    if (!arguments.empty()) {
        throw CannotDumpException(
            rtl::OString(RTL_CONSTASCII_STRINGPARAM("Bad type information")));
            //TODO
    }
}

}

namespace codemaker {

rtl::OString convertString(rtl::OUString const & string) {
    rtl::OString s;
    if (!string.convertToString(
            &s, RTL_TEXTENCODING_UTF8,
            (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR
             | RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR)))
    {
        throw CannotDumpException(
            rtl::OString(
                RTL_CONSTASCII_STRINGPARAM(
                    "Failure converting string from UTF-16 to UTF-8")));
    }
    return s;
}

codemaker::UnoType::Sort decomposeAndResolve(
    TypeManager const & manager, rtl::OString const & type,
    bool resolveTypedefs, bool allowVoid, bool allowExtraEntities,
    RTTypeClass * typeClass, rtl::OString * name, sal_Int32 * rank,
    std::vector< rtl::OString > * arguments)
{
    OSL_ASSERT(typeClass != 0 && name != 0 && rank != 0 && arguments != 0);
    *rank = 0;
    for (rtl::OString t(type);;) {
        sal_Int32 n = 0;
        *name = codemaker::UnoType::decompose(t, &n, arguments);
        if (n > SAL_MAX_INT32 - *rank) {
            throw CannotDumpException(
                rtl::OString(
                    RTL_CONSTASCII_STRINGPARAM("Bad type information"))); //TODO
        }
        *rank += n;
        if (n > 0) {
            allowVoid = false;
            allowExtraEntities = false;
        }
        codemaker::UnoType::Sort sort = codemaker::UnoType::getSort(*name);
        switch (sort) {
        case codemaker::UnoType::SORT_VOID:
            if (!allowVoid) {
                throw CannotDumpException(
                    rtl::OString(
                        RTL_CONSTASCII_STRINGPARAM("Bad type information")));
                    //TODO
            }
        default:
            checkNoTypeArguments(*arguments);
            *typeClass = RT_TYPE_INVALID;
            return sort;

        case codemaker::UnoType::SORT_COMPLEX:
            typereg::Reader reader(manager.getTypeReader(*name));
            *typeClass = reader.getTypeClass();
            switch (*typeClass) {
            case RT_TYPE_ENUM:
            case RT_TYPE_INTERFACE:
                checkNoTypeArguments(*arguments);
                return sort;

            case RT_TYPE_STRUCT:
                if (!(allowExtraEntities && arguments->empty())
                    && (arguments->size() > SAL_MAX_UINT16
                        || (static_cast< sal_uInt16 >(arguments->size())
                            != reader.getReferenceCount())))
                {
                    throw CannotDumpException(
                        rtl::OString(
                            RTL_CONSTASCII_STRINGPARAM(
                                "Bad type information"))); //TODO
                }
                return sort;

            case RT_TYPE_MODULE:
            case RT_TYPE_EXCEPTION:
            case RT_TYPE_SERVICE:
            case RT_TYPE_SINGLETON:
            case RT_TYPE_CONSTANTS:
                if (!allowExtraEntities) {
                    throw CannotDumpException(
                        rtl::OString(
                            RTL_CONSTASCII_STRINGPARAM(
                                "Bad type information"))); //TODO
                }
                checkNoTypeArguments(*arguments);
                //TODO: check reader for consistency
                return sort;

            case RT_TYPE_TYPEDEF:
                checkNoTypeArguments(*arguments);
                if (reader.getSuperTypeCount() == 1
                    && reader.getFieldCount() == 0
                    && reader.getMethodCount() == 0
                    && reader.getReferenceCount() == 0)
                {
                    if (resolveTypedefs) {
                        t = convertString(reader.getSuperTypeName(0));
                        continue;
                    } else {
                        return sort;
                    }
                }
            default:
                throw CannotDumpException(
                    rtl::OString(
                        RTL_CONSTASCII_STRINGPARAM("Bad type information")));
                    //TODO
            }
        }
    }
}

}
<commit_msg>INTEGRATION: CWS jscpp1 (1.2.8); FILE MERGED 2005/08/10 09:46:30 jsc 1.2.8.1: #i52598# improve error output<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: codemaker.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: rt $ $Date: 2005-10-17 13:20:04 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    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., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#include "sal/config.h"

#include "codemaker/codemaker.hxx"

#include "codemaker/options.hxx"
#include "codemaker/typemanager.hxx"
#include "codemaker/unotype.hxx"

#include "osl/diagnose.h"
#include "registry/reader.hxx"
#include "registry/types.h"
#include "rtl/strbuf.h"
#include "rtl/string.h"
#include "rtl/string.hxx"
#include "rtl/ustring.hxx"
#include "sal/types.h"

#include <vector>

namespace {

void checkNoTypeArguments(std::vector< rtl::OString > const & arguments) {
    if (!arguments.empty()) {
        throw CannotDumpException(
            rtl::OString(RTL_CONSTASCII_STRINGPARAM("Bad type information")));
            //TODO
    }
}

}

namespace codemaker {

rtl::OString convertString(rtl::OUString const & string) {
    rtl::OString s;
    if (!string.convertToString(
            &s, RTL_TEXTENCODING_UTF8,
            (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR
             | RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR)))
    {
        throw CannotDumpException(
            rtl::OString(
                RTL_CONSTASCII_STRINGPARAM(
                    "Failure converting string from UTF-16 to UTF-8")));
    }
    return s;
}

rtl::OString errorMsg(rtl::OString const & desc, rtl::OString const & type) {
    rtl::OStringBuffer msg(128);
    msg.append(desc);
    msg.append(type);
    return msg.makeStringAndClear();
}

codemaker::UnoType::Sort decomposeAndResolve(
    TypeManager const & manager, rtl::OString const & type,
    bool resolveTypedefs, bool allowVoid, bool allowExtraEntities,
    RTTypeClass * typeClass, rtl::OString * name, sal_Int32 * rank,
    std::vector< rtl::OString > * arguments)
{
    OSL_ASSERT(typeClass != 0 && name != 0 && rank != 0 && arguments != 0);
    *rank = 0;
    for (rtl::OString t(type);;) {
        sal_Int32 n = 0;
        *name = codemaker::UnoType::decompose(t, &n, arguments);
        if (n > SAL_MAX_INT32 - *rank) {
            throw CannotDumpException(
                errorMsg(rtl::OString(
                    RTL_CONSTASCII_STRINGPARAM("Bad type information: ")),
                    type));
            //TODO
        }
        *rank += n;
        if (n > 0) {
            allowVoid = false;
            allowExtraEntities = false;
        }
        codemaker::UnoType::Sort sort = codemaker::UnoType::getSort(*name);
        switch (sort) {
        case codemaker::UnoType::SORT_VOID:
            if (!allowVoid) {
                throw CannotDumpException(
                    errorMsg(rtl::OString(
                        RTL_CONSTASCII_STRINGPARAM("Bad type information: ")),
                        type));
                //TODO
            }
        default:
            checkNoTypeArguments(*arguments);
            *typeClass = RT_TYPE_INVALID;
            return sort;

        case codemaker::UnoType::SORT_COMPLEX:
            typereg::Reader reader(manager.getTypeReader(*name));
            *typeClass = reader.getTypeClass();
            switch (*typeClass) {
            case RT_TYPE_ENUM:
            case RT_TYPE_INTERFACE:
                checkNoTypeArguments(*arguments);
                return sort;

            case RT_TYPE_STRUCT:
                if (!(allowExtraEntities && arguments->empty())
                    && (arguments->size() > SAL_MAX_UINT16
                        || (static_cast< sal_uInt16 >(arguments->size())
                            != reader.getReferenceCount())))
                {
                    throw CannotDumpException(
                        errorMsg(rtl::OString(
                            RTL_CONSTASCII_STRINGPARAM("Bad type information: ")),
                            type));
                    //TODO
                }
                return sort;

            case RT_TYPE_MODULE:
            case RT_TYPE_EXCEPTION:
            case RT_TYPE_SERVICE:
            case RT_TYPE_SINGLETON:
            case RT_TYPE_CONSTANTS:
                if (!allowExtraEntities) {
                    throw CannotDumpException(
                        errorMsg(rtl::OString(
                            RTL_CONSTASCII_STRINGPARAM("Bad type information: ")),
                            type));
                    //TODO
                }
                checkNoTypeArguments(*arguments);
                //TODO: check reader for consistency
                return sort;

            case RT_TYPE_TYPEDEF:
                checkNoTypeArguments(*arguments);
                if (reader.getSuperTypeCount() == 1
                    && reader.getFieldCount() == 0
                    && reader.getMethodCount() == 0
                    && reader.getReferenceCount() == 0)
                {
                    if (resolveTypedefs) {
                        t = convertString(reader.getSuperTypeName(0));
                        continue;
                    } else {
                        return sort;
                    }
                }
            default:
                throw CannotDumpException(
                    errorMsg(rtl::OString(
                        RTL_CONSTASCII_STRINGPARAM("Bad type information: ")),
                        type));
                //TODO
            }
        }
    }
}

}
<|endoftext|>


<commit_before>// Licensed GNU LGPL v3 or later: http://www.gnu.org/licenses/lgpl.html
#ifndef __RAPICORN_CXXAUX_HH__
#define __RAPICORN_CXXAUX_HH__

#include <rcore/rapicornconfig.h>       // _GNU_SOURCE
#include <stdbool.h>
#include <stdarg.h>
#include <stddef.h>			// NULL
#include <sys/types.h>			// uint, ssize
#include <stdint.h>			// uint64_t
#include <limits.h>                     // {INT|CHAR|...}_{MIN|MAX}
#include <float.h>                      // {FLT|DBL}_{MIN|MAX|EPSILON}
#include <string>
#include <vector>
#include <map>

// == Standard Macros ==
#ifndef FALSE
#  define FALSE					false
#endif
#ifndef TRUE
#  define TRUE					true
#endif
#define RAPICORN_ABS(a)                         ((a) < 0 ? -(a) : (a))
#define RAPICORN_MIN(a,b)                       ((a) <= (b) ? (a) : (b))
#define RAPICORN_MAX(a,b)                       ((a) >= (b) ? (a) : (b))
#define RAPICORN_CLAMP(v,mi,ma)                 ((v) < (mi) ? (mi) : ((v) > (ma) ? (ma) : (v)))
#define RAPICORN_ARRAY_SIZE(array)		(sizeof (array) / sizeof ((array)[0]))
#undef ABS
#define ABS                                     RAPICORN_ABS
#undef MIN
#define MIN                                     RAPICORN_MIN
#undef MAX
#define MAX                                     RAPICORN_MAX
#undef CLAMP
#define CLAMP                                   RAPICORN_CLAMP
#undef ARRAY_SIZE
#define ARRAY_SIZE				RAPICORN_ARRAY_SIZE
#undef EXTERN_C
#ifdef	__cplusplus
#define EXTERN_C                                extern "C"
#else
#define EXTERN_C                                extern
#endif
#undef STRFUNC
#define STRFUNC				        RAPICORN_SIMPLE_FUNCTION
#if     !defined (INT64_MAX) || !defined (INT64_MIN) || !defined (UINT64_MAX)
#ifdef  LLONG_MAX       // some gcc versions ship limits.h that fail to define LLONG_MAX for C99
#  define INT64_MAX     LLONG_MAX       // +9223372036854775807LL
#  define INT64_MIN     LLONG_MIN       // -9223372036854775808LL
#  define UINT64_MAX    ULLONG_MAX      // +18446744073709551615LLU
#else   // !LLONG_MAX but gcc always has __LONG_LONG_MAX__
#  define INT64_MAX     __LONG_LONG_MAX__
#  define INT64_MIN     (-INT64_MAX - 1LL)
#  define UINT64_MAX    (INT64_MAX * 2ULL + 1ULL)
#endif
#endif
#ifndef SIZE_T_MAX
#define SIZE_T_MAX              (~size_t (0))
#define SSIZE_T_MAX             (ssize_t (SIZE_T_MAX / 2))
#endif

// == Likelyness Hinting ==
#define	RAPICORN__BOOL(expr)		__extension__ ({ bool _rapicorn__bool; if (expr) _rapicorn__bool = 1; else _rapicorn__bool = 0; _rapicorn__bool; })
#define	RAPICORN_ISLIKELY(expr)		__builtin_expect (RAPICORN__BOOL (expr), 1)
#define	RAPICORN_UNLIKELY(expr)		__builtin_expect (RAPICORN__BOOL (expr), 0)
#define	RAPICORN_LIKELY			RAPICORN_ISLIKELY

// == Convenience Macros ==
#ifdef  RAPICORN_CONVENIENCE
#define	ISLIKELY		RAPICORN_ISLIKELY       ///< Compiler hint that @a expression is likely to be true.
#define	UNLIKELY		RAPICORN_UNLIKELY       ///< Compiler hint that @a expression is unlikely to be true.
#define	LIKELY			RAPICORN_LIKELY         ///< Compiler hint that @a expression is likely to be true.
#define	STRINGIFY               RAPICORN_CPP_STRINGIFY  ///< Produces a const char C string from the macro @a argument.
#endif
/**
 * @def RAPICORN_CONVENIENCE
 * Configuration macro to enable convenience macros.
 * Defining this before inclusion of rapicorn.hh or rapicorn-core.hh enables several convenience
 * macros that are defined in the global namespace without the usual "RAPICORN_" prefix,
 * see e.g. critical_unless(), UNLIKELY().
 */
#ifdef  DOXYGEN
#  define RAPICORN_CONVENIENCE
#endif // DOXYGEN

// == Preprocessor Convenience ==
#define RAPICORN_CPP_PASTE2_(a,b)               a ## b  // indirection required to expand macros like __LINE__
#define RAPICORN_CPP_PASTE2(a,b)                RAPICORN_CPP_PASTE2_ (a,b)
#define RAPICORN_CPP_STRINGIFY_(s)              #s      // indirection required to expand macros like __LINE__
#define RAPICORN_CPP_STRINGIFY(s)               RAPICORN_CPP_STRINGIFY_ (s)
#define RAPICORN_STATIC_ASSERT(expr)            static_assert (expr, #expr) ///< Shorthand for static_assert (condition, "condition")

// == GCC Attributes ==
#if     __GNUC__ >= 4
#define RAPICORN_PURE                           __attribute__ ((__pure__))
#define RAPICORN_MALLOC                         __attribute__ ((__malloc__))
#define RAPICORN_PRINTF(format_idx, arg_idx)    __attribute__ ((__format__ (__printf__, format_idx, arg_idx)))
#define RAPICORN_SCANF(format_idx, arg_idx)     __attribute__ ((__format__ (__scanf__, format_idx, arg_idx)))
#define RAPICORN_FORMAT(arg_idx)                __attribute__ ((__format_arg__ (arg_idx)))
#define RAPICORN_SENTINEL                       __attribute__ ((__sentinel__))
#define RAPICORN_NORETURN                       __attribute__ ((__noreturn__))
#define RAPICORN_CONST                          __attribute__ ((__const__))
#define RAPICORN_UNUSED                         __attribute__ ((__unused__))
#define RAPICORN_NO_INSTRUMENT                  __attribute__ ((__no_instrument_function__))
#define RAPICORN_DEPRECATED                     __attribute__ ((__deprecated__))
#define RAPICORN_ALWAYS_INLINE			__attribute__ ((always_inline))
#define RAPICORN_NOINLINE			__attribute__ ((noinline))
#define RAPICORN_CONSTRUCTOR			__attribute__ ((constructor,used))      // gcc-3.3 also needs "used" to emit code
#define RAPICORN_MAY_ALIAS                      __attribute__ ((may_alias))
#define	RAPICORN_SIMPLE_FUNCTION	       (::Rapicorn::string_from_pretty_function_name (__PRETTY_FUNCTION__).c_str())
#else   // !__GNUC__
#define RAPICORN_PURE
#define RAPICORN_MALLOC
#define RAPICORN_PRINTF(format_idx, arg_idx)
#define RAPICORN_SCANF(format_idx, arg_idx)
#define RAPICORN_FORMAT(arg_idx)
#define RAPICORN_SENTINEL
#define RAPICORN_NORETURN
#define RAPICORN_CONST
#define RAPICORN_UNUSED
#define RAPICORN_NO_INSTRUMENT
#define RAPICORN_DEPRECATED
#define RAPICORN_ALWAYS_INLINE
#define RAPICORN_NOINLINE
#define RAPICORN_CONSTRUCTOR
#define RAPICORN_MAY_ALIAS
#define	RAPICORN_SIMPLE_FUNCTION	       (__func__)
#error  Failed to detect a recent GCC version (>= 4)
#endif  // !__GNUC__

// == C++11 Keywords ==
#if __GNUC__ == 4 && __GNUC_MINOR__ < 7
#define override        /* unimplemented */
#define final           /* unimplemented */
#endif // GCC < 4.7

// == Ensure 'uint' in global namespace ==
#if 	RAPICORN_SIZEOF_SYS_TYPESH_UINT == 0
typedef unsigned int		uint;           // for systems that don't define uint in sys/types.h
#else
RAPICORN_STATIC_ASSERT (RAPICORN_SIZEOF_SYS_TYPESH_UINT == 4);
#endif
RAPICORN_STATIC_ASSERT (sizeof (uint) == 4);

// == Rapicorn Namespace ==
namespace Rapicorn {

// == Provide Canonical Integer Types ==
typedef uint8_t                 uint8;          ///< An 8-bit unsigned integer.
typedef uint16_t                uint16;         ///< A 16-bit unsigned integer.
typedef uint32_t                uint32;         ///< A 32-bit unsigned integer.
typedef unsigned long long int  uint64;         ///< A 64-bit unsigned integer, use "%llu" in format strings.
// typedef uint64_t             uint64;         // int64_t / uint64_t are longs on AMD64 which breaks printf
typedef int8_t                  int8;           ///< An 8-bit signed integer.
typedef int16_t                 int16;          ///< A 16-bit signed integer.
typedef int32_t                 int32;          ///< A 32-bit signed integer.
typedef signed long long int    int64;          ///< A 64-bit unsigned integer, use "%lld" in format strings.
typedef uint32_t                unichar;        ///< A 32-bit unsigned integer used for Unicode characters.
RAPICORN_STATIC_ASSERT (sizeof (uint8) == 1 && sizeof (uint16) == 2 && sizeof (uint32) == 4 && sizeof (uint64) == 8);
RAPICORN_STATIC_ASSERT (sizeof (int8)  == 1 && sizeof (int16)  == 2 && sizeof (int32)  == 4 && sizeof (int64)  == 8);
RAPICORN_STATIC_ASSERT (sizeof (int) == 4 && sizeof (uint) == 4 && sizeof (unichar) == 4);

// == Convenient stdc++ Types ==
using   std::map;
using   std::vector;
typedef std::string String;             ///< Convenience alias for std::string.
typedef vector<String> StringVector;    ///< Convenience alias for a std::vector<std::string>.

// == File Path Handling ==
#ifdef  _WIN32
#define RAPICORN_DIR_SEPARATOR		  '\\'
#define RAPICORN_DIR_SEPARATOR_S	  "\\"
#define RAPICORN_SEARCHPATH_SEPARATOR	  ';'
#define RAPICORN_SEARCHPATH_SEPARATOR_S	  ";"
#define RAPICORN_IS_ABSPATH(p)          (((p[0] >= 'A' && p[0] <= 'Z') || (p[0] >= 'a' && p[0] <= 'z')) && p[1] == ':' && p[2] == '\\')
#else   // !_WIN32
#define RAPICORN_DIR_SEPARATOR		  '/'
#define RAPICORN_DIR_SEPARATOR_S	  "/"
#define RAPICORN_SEARCHPATH_SEPARATOR	  ':'
#define RAPICORN_SEARCHPATH_SEPARATOR_S	  ":"
#define RAPICORN_IS_ABSPATH(p)            (p[0] == RAPICORN_DIR_SEPARATOR)
#endif  // !_WIN32

// == C++ Macros ==
#define RAPICORN_CLASS_NON_COPYABLE(ClassName)                                  private: \
  /*copy-ctor*/ ClassName  (const ClassName&) __attribute__ ((error ("NON_COPYABLE"))) = delete; \
  ClassName&    operator=  (const ClassName&) __attribute__ ((error ("NON_COPYABLE"))) = delete

// == C++ Helper Classes ==
/// Simple helper class to call one-line lambda initializers as static constructor.
struct Init {
  explicit Init (void (*f) ()) { f(); }
};

// == X86 Architecture ==
#if defined __i386__ || defined __x86_64__
#define RAPICORN_HAVE_X86_RDTSC  1
#define RAPICORN_X86_RDTSC()     ({ Rapicorn::uint32 __l_, __h_, __s_; \
                                    __asm__ __volatile__ ("rdtsc" : "=a" (__l_), "=d" (__h_));  \
                                    __s_ = __l_ + (Rapicorn::uint64 (__h_) << 32); __s_; })
#else
#define RAPICORN_HAVE_X86_RDTSC  0
#define RAPICORN_X86_RDTSC()    (0)
#endif

} // Rapicorn

#endif // __RAPICORN_CXXAUX_HH__
<commit_msg>RCORE: add LongIffy, ULongIffy, CastIffy, UCastIffy types for 32bit/64bit overloading.<commit_after>// Licensed GNU LGPL v3 or later: http://www.gnu.org/licenses/lgpl.html
#ifndef __RAPICORN_CXXAUX_HH__
#define __RAPICORN_CXXAUX_HH__

#include <rcore/rapicornconfig.h>       // _GNU_SOURCE
#include <stdbool.h>
#include <stdarg.h>
#include <stddef.h>			// NULL
#include <sys/types.h>			// uint, ssize
#include <stdint.h>			// uint64_t
#include <limits.h>                     // {INT|CHAR|...}_{MIN|MAX}
#include <float.h>                      // {FLT|DBL}_{MIN|MAX|EPSILON}
#include <string>
#include <vector>
#include <map>

// == Standard Macros ==
#ifndef FALSE
#  define FALSE					false
#endif
#ifndef TRUE
#  define TRUE					true
#endif
#define RAPICORN_ABS(a)                         ((a) < 0 ? -(a) : (a))
#define RAPICORN_MIN(a,b)                       ((a) <= (b) ? (a) : (b))
#define RAPICORN_MAX(a,b)                       ((a) >= (b) ? (a) : (b))
#define RAPICORN_CLAMP(v,mi,ma)                 ((v) < (mi) ? (mi) : ((v) > (ma) ? (ma) : (v)))
#define RAPICORN_ARRAY_SIZE(array)		(sizeof (array) / sizeof ((array)[0]))
#undef ABS
#define ABS                                     RAPICORN_ABS
#undef MIN
#define MIN                                     RAPICORN_MIN
#undef MAX
#define MAX                                     RAPICORN_MAX
#undef CLAMP
#define CLAMP                                   RAPICORN_CLAMP
#undef ARRAY_SIZE
#define ARRAY_SIZE				RAPICORN_ARRAY_SIZE
#undef EXTERN_C
#ifdef	__cplusplus
#define EXTERN_C                                extern "C"
#else
#define EXTERN_C                                extern
#endif
#undef STRFUNC
#define STRFUNC				        RAPICORN_SIMPLE_FUNCTION
#if     !defined (INT64_MAX) || !defined (INT64_MIN) || !defined (UINT64_MAX)
#ifdef  LLONG_MAX       // some gcc versions ship limits.h that fail to define LLONG_MAX for C99
#  define INT64_MAX     LLONG_MAX       // +9223372036854775807LL
#  define INT64_MIN     LLONG_MIN       // -9223372036854775808LL
#  define UINT64_MAX    ULLONG_MAX      // +18446744073709551615LLU
#else   // !LLONG_MAX but gcc always has __LONG_LONG_MAX__
#  define INT64_MAX     __LONG_LONG_MAX__
#  define INT64_MIN     (-INT64_MAX - 1LL)
#  define UINT64_MAX    (INT64_MAX * 2ULL + 1ULL)
#endif
#endif
#ifndef SIZE_T_MAX
#define SIZE_T_MAX              (~size_t (0))
#define SSIZE_T_MAX             (ssize_t (SIZE_T_MAX / 2))
#endif

// == Likelyness Hinting ==
#define	RAPICORN__BOOL(expr)		__extension__ ({ bool _rapicorn__bool; if (expr) _rapicorn__bool = 1; else _rapicorn__bool = 0; _rapicorn__bool; })
#define	RAPICORN_ISLIKELY(expr)		__builtin_expect (RAPICORN__BOOL (expr), 1)
#define	RAPICORN_UNLIKELY(expr)		__builtin_expect (RAPICORN__BOOL (expr), 0)
#define	RAPICORN_LIKELY			RAPICORN_ISLIKELY

// == Convenience Macros ==
#ifdef  RAPICORN_CONVENIENCE
#define	ISLIKELY		RAPICORN_ISLIKELY       ///< Compiler hint that @a expression is likely to be true.
#define	UNLIKELY		RAPICORN_UNLIKELY       ///< Compiler hint that @a expression is unlikely to be true.
#define	LIKELY			RAPICORN_LIKELY         ///< Compiler hint that @a expression is likely to be true.
#define	STRINGIFY               RAPICORN_CPP_STRINGIFY  ///< Produces a const char C string from the macro @a argument.
#endif
/**
 * @def RAPICORN_CONVENIENCE
 * Configuration macro to enable convenience macros.
 * Defining this before inclusion of rapicorn.hh or rapicorn-core.hh enables several convenience
 * macros that are defined in the global namespace without the usual "RAPICORN_" prefix,
 * see e.g. critical_unless(), UNLIKELY().
 */
#ifdef  DOXYGEN
#  define RAPICORN_CONVENIENCE
#endif // DOXYGEN

// == Preprocessor Convenience ==
#define RAPICORN_CPP_PASTE2_(a,b)               a ## b  // indirection required to expand macros like __LINE__
#define RAPICORN_CPP_PASTE2(a,b)                RAPICORN_CPP_PASTE2_ (a,b)
#define RAPICORN_CPP_STRINGIFY_(s)              #s      // indirection required to expand macros like __LINE__
#define RAPICORN_CPP_STRINGIFY(s)               RAPICORN_CPP_STRINGIFY_ (s)
#define RAPICORN_STATIC_ASSERT(expr)            static_assert (expr, #expr) ///< Shorthand for static_assert (condition, "condition")

// == GCC Attributes ==
#if     __GNUC__ >= 4
#define RAPICORN_PURE                           __attribute__ ((__pure__))
#define RAPICORN_MALLOC                         __attribute__ ((__malloc__))
#define RAPICORN_PRINTF(format_idx, arg_idx)    __attribute__ ((__format__ (__printf__, format_idx, arg_idx)))
#define RAPICORN_SCANF(format_idx, arg_idx)     __attribute__ ((__format__ (__scanf__, format_idx, arg_idx)))
#define RAPICORN_FORMAT(arg_idx)                __attribute__ ((__format_arg__ (arg_idx)))
#define RAPICORN_SENTINEL                       __attribute__ ((__sentinel__))
#define RAPICORN_NORETURN                       __attribute__ ((__noreturn__))
#define RAPICORN_CONST                          __attribute__ ((__const__))
#define RAPICORN_UNUSED                         __attribute__ ((__unused__))
#define RAPICORN_NO_INSTRUMENT                  __attribute__ ((__no_instrument_function__))
#define RAPICORN_DEPRECATED                     __attribute__ ((__deprecated__))
#define RAPICORN_ALWAYS_INLINE			__attribute__ ((always_inline))
#define RAPICORN_NOINLINE			__attribute__ ((noinline))
#define RAPICORN_CONSTRUCTOR			__attribute__ ((constructor,used))      // gcc-3.3 also needs "used" to emit code
#define RAPICORN_MAY_ALIAS                      __attribute__ ((may_alias))
#define	RAPICORN_SIMPLE_FUNCTION	       (::Rapicorn::string_from_pretty_function_name (__PRETTY_FUNCTION__).c_str())
#else   // !__GNUC__
#define RAPICORN_PURE
#define RAPICORN_MALLOC
#define RAPICORN_PRINTF(format_idx, arg_idx)
#define RAPICORN_SCANF(format_idx, arg_idx)
#define RAPICORN_FORMAT(arg_idx)
#define RAPICORN_SENTINEL
#define RAPICORN_NORETURN
#define RAPICORN_CONST
#define RAPICORN_UNUSED
#define RAPICORN_NO_INSTRUMENT
#define RAPICORN_DEPRECATED
#define RAPICORN_ALWAYS_INLINE
#define RAPICORN_NOINLINE
#define RAPICORN_CONSTRUCTOR
#define RAPICORN_MAY_ALIAS
#define	RAPICORN_SIMPLE_FUNCTION	       (__func__)
#error  Failed to detect a recent GCC version (>= 4)
#endif  // !__GNUC__

// == C++11 Keywords ==
#if __GNUC__ == 4 && __GNUC_MINOR__ < 7
#define override        /* unimplemented */
#define final           /* unimplemented */
#endif // GCC < 4.7

// == Ensure 'uint' in global namespace ==
#if 	RAPICORN_SIZEOF_SYS_TYPESH_UINT == 0
typedef unsigned int		uint;           // for systems that don't define uint in sys/types.h
#else
RAPICORN_STATIC_ASSERT (RAPICORN_SIZEOF_SYS_TYPESH_UINT == 4);
#endif
RAPICORN_STATIC_ASSERT (sizeof (uint) == 4);

// == Rapicorn Namespace ==
namespace Rapicorn {

// == Provide Canonical Integer Types ==
typedef uint8_t                 uint8;          ///< An 8-bit unsigned integer.
typedef uint16_t                uint16;         ///< A 16-bit unsigned integer.
typedef uint32_t                uint32;         ///< A 32-bit unsigned integer.
typedef unsigned long long int  uint64;         ///< A 64-bit unsigned integer, use "%llu" in format strings.
// typedef uint64_t             uint64;         // int64_t / uint64_t are longs on AMD64 which breaks printf
typedef int8_t                  int8;           ///< An 8-bit signed integer.
typedef int16_t                 int16;          ///< A 16-bit signed integer.
typedef int32_t                 int32;          ///< A 32-bit signed integer.
typedef signed long long int    int64;          ///< A 64-bit unsigned integer, use "%lld" in format strings.
typedef uint32_t                unichar;        ///< A 32-bit unsigned integer used for Unicode characters.
RAPICORN_STATIC_ASSERT (sizeof (uint8) == 1 && sizeof (uint16) == 2 && sizeof (uint32) == 4 && sizeof (uint64) == 8);
RAPICORN_STATIC_ASSERT (sizeof (int8)  == 1 && sizeof (int16)  == 2 && sizeof (int32)  == 4 && sizeof (int64)  == 8);
RAPICORN_STATIC_ASSERT (sizeof (int) == 4 && sizeof (uint) == 4 && sizeof (unichar) == 4);

///@{
/** LongIffy, ULongIffy, CastIffy, UCastIffy - types for 32bit/64bit overloading.
 * On 64bit, int64_t is aliased to "long int" which is 64 bit wide.
 * On 32bit, int64_t is aliased to "long long int", which is 64 bit wide (and long is 32bit wide).
 * For int-type function overloading, this means that int32, int64 and either "long" or "long long"
 * need to be overloaded, depending on platform. To aid this case, LongIffy and ULongIffy are defined
 * to signed and unsigned "long" (for 32bit) and "long long" (for 64bit). Correspondingly, CastIffy
 * and UCastIffy are defined to signed and unsigned int32 (for 32bit) or int64 (for 64bit), so
 * LongIffy can be cast losslessly into a known type.
 */
#if     __SIZEOF_LONG__ == 8    // 64bit
typedef long long signed int    LongIffy;
typedef long long unsigned int  ULongIffy;
typedef int64_t                 CastIffy;
typedef uint64_t                UCastIffy;
static_assert (__SIZEOF_LONG_LONG__ == 8, "__SIZEOF_LONG_LONG__");
static_assert (__SIZEOF_INT__ == 4, "__SIZEOF_INT__");
#elif   __SIZEOF_LONG__ == 4    // 32bit
typedef long signed int         LongIffy;
typedef long unsigned int       ULongIffy;
typedef int32_t                 CastIffy;
typedef uint32_t                UCastIffy;
static_assert (__SIZEOF_LONG_LONG__ == 8, "__SIZEOF_LONG_LONG__");
static_assert (__SIZEOF_INT__ == 4, "__SIZEOF_INT__");
#else
#error  "Unknown long size:" __SIZEOF_LONG__
#endif
static_assert (sizeof (CastIffy) == sizeof (LongIffy), "CastIffy == LongIffy");
static_assert (sizeof (UCastIffy) == sizeof (ULongIffy), "UCastIffy == ULongIffy");
///@}

// == Convenient stdc++ Types ==
using   std::map;
using   std::vector;
typedef std::string String;             ///< Convenience alias for std::string.
typedef vector<String> StringVector;    ///< Convenience alias for a std::vector<std::string>.

// == File Path Handling ==
#ifdef  _WIN32
#define RAPICORN_DIR_SEPARATOR		  '\\'
#define RAPICORN_DIR_SEPARATOR_S	  "\\"
#define RAPICORN_SEARCHPATH_SEPARATOR	  ';'
#define RAPICORN_SEARCHPATH_SEPARATOR_S	  ";"
#define RAPICORN_IS_ABSPATH(p)          (((p[0] >= 'A' && p[0] <= 'Z') || (p[0] >= 'a' && p[0] <= 'z')) && p[1] == ':' && p[2] == '\\')
#else   // !_WIN32
#define RAPICORN_DIR_SEPARATOR		  '/'
#define RAPICORN_DIR_SEPARATOR_S	  "/"
#define RAPICORN_SEARCHPATH_SEPARATOR	  ':'
#define RAPICORN_SEARCHPATH_SEPARATOR_S	  ":"
#define RAPICORN_IS_ABSPATH(p)            (p[0] == RAPICORN_DIR_SEPARATOR)
#endif  // !_WIN32

// == C++ Macros ==
#define RAPICORN_CLASS_NON_COPYABLE(ClassName)                                  private: \
  /*copy-ctor*/ ClassName  (const ClassName&) __attribute__ ((error ("NON_COPYABLE"))) = delete; \
  ClassName&    operator=  (const ClassName&) __attribute__ ((error ("NON_COPYABLE"))) = delete

// == C++ Helper Classes ==
/// Simple helper class to call one-line lambda initializers as static constructor.
struct Init {
  explicit Init (void (*f) ()) { f(); }
};

// == X86 Architecture ==
#if defined __i386__ || defined __x86_64__
#define RAPICORN_HAVE_X86_RDTSC  1
#define RAPICORN_X86_RDTSC()     ({ Rapicorn::uint32 __l_, __h_, __s_; \
                                    __asm__ __volatile__ ("rdtsc" : "=a" (__l_), "=d" (__h_));  \
                                    __s_ = __l_ + (Rapicorn::uint64 (__h_) << 32); __s_; })
#else
#define RAPICORN_HAVE_X86_RDTSC  0
#define RAPICORN_X86_RDTSC()    (0)
#endif

} // Rapicorn

#endif // __RAPICORN_CXXAUX_HH__
<|endoftext|>


<commit_before>#include <QtTest/QtTest>

#include <TelepathyQt4/Constants>
#include <TelepathyQt4/Debug>
#include <TelepathyQt4/Presence>
#include <TelepathyQt4/Types>

using namespace Tp;

class TestPresence : public QObject
{
    Q_OBJECT

public:
    TestPresence(QObject *parent = 0);

private Q_SLOTS:
    void testPresence();
};

TestPresence::TestPresence(QObject *parent)
    : QObject(parent)
{
    Tp::enableDebug(true);
    Tp::enableWarnings(true);
}

#define TEST_PRESENCE(pr, prValid, prType, prStatus, prStatusMessage) \
{ \
    QVERIFY(pr.isValid() == prValid); \
    QCOMPARE(pr.type(), prType); \
    QCOMPARE(pr.status(), prStatus); \
    QCOMPARE(pr.statusMessage(), prStatusMessage); \
}

void TestPresence::testPresence()
{
    Presence pr;
    TEST_PRESENCE(pr, false, ConnectionPresenceTypeUnknown, QString(), QString());
    pr.setStatus(ConnectionPresenceTypeAvailable, QLatin1String("available"),
            QLatin1String("I am available"));
    TEST_PRESENCE(pr, true, ConnectionPresenceTypeAvailable, QLatin1String("available"), QLatin1String("I am available"));

    pr = Presence::available();
    TEST_PRESENCE(pr, true, ConnectionPresenceTypeAvailable, QLatin1String("available"), QString());
    pr = Presence::available(QLatin1String("I am available"));
    TEST_PRESENCE(pr, true, ConnectionPresenceTypeAvailable, QLatin1String("available"), QLatin1String("I am available"));

    pr = Presence::away();
    TEST_PRESENCE(pr, true, ConnectionPresenceTypeAway, QLatin1String("away"), QString());
    pr = Presence::away(QLatin1String("I am away"));
    TEST_PRESENCE(pr, true, ConnectionPresenceTypeAway, QLatin1String("away"), QLatin1String("I am away"));

    pr = Presence::brb();
    TEST_PRESENCE(pr, true, ConnectionPresenceTypeAway, QLatin1String("brb"), QString());
    pr = Presence::brb(QLatin1String("I am brb"));
    TEST_PRESENCE(pr, true, ConnectionPresenceTypeAway, QLatin1String("brb"), QLatin1String("I am brb"));

    pr = Presence::busy();
    TEST_PRESENCE(pr, true, ConnectionPresenceTypeBusy, QLatin1String("busy"), QString());
    pr = Presence::busy(QLatin1String("I am busy"));
    TEST_PRESENCE(pr, true, ConnectionPresenceTypeBusy, QLatin1String("busy"), QLatin1String("I am busy"));

    pr = Presence::xa();
    TEST_PRESENCE(pr, true, ConnectionPresenceTypeExtendedAway, QLatin1String("xa"), QString());
    pr = Presence::xa(QLatin1String("I am xa"));
    TEST_PRESENCE(pr, true, ConnectionPresenceTypeExtendedAway, QLatin1String("xa"), QLatin1String("I am xa"));

    pr = Presence::hidden();
    TEST_PRESENCE(pr, true, ConnectionPresenceTypeHidden, QLatin1String("hidden"), QString());
    pr = Presence::hidden(QLatin1String("I am hidden"));
    TEST_PRESENCE(pr, true, ConnectionPresenceTypeHidden, QLatin1String("hidden"), QLatin1String("I am hidden"));

    pr = Presence::offline();
    TEST_PRESENCE(pr, true, ConnectionPresenceTypeOffline, QLatin1String("offline"), QString());
    pr = Presence::offline(QLatin1String("I am offline"));
    TEST_PRESENCE(pr, true, ConnectionPresenceTypeOffline, QLatin1String("offline"), QLatin1String("I am offline"));
}

QTEST_MAIN(TestPresence)

#include "_gen/presence.cpp.moc.hpp"
<commit_msg>presence test: Add PresenceSpec specific tests.<commit_after>#include <QtTest/QtTest>

#include <TelepathyQt4/Constants>
#include <TelepathyQt4/Debug>
#include <TelepathyQt4/Presence>
#include <TelepathyQt4/Types>

using namespace Tp;

class TestPresence : public QObject
{
    Q_OBJECT

public:
    TestPresence(QObject *parent = 0);

private Q_SLOTS:
    void testPresence();
    void testPresenceSpec();
};

TestPresence::TestPresence(QObject *parent)
    : QObject(parent)
{
    Tp::enableDebug(true);
    Tp::enableWarnings(true);
}

#define TEST_PRESENCE(pr, prValid, prType, prStatus, prStatusMessage) \
{ \
    QVERIFY(pr.isValid() == prValid); \
    QCOMPARE(pr.type(), prType); \
    QCOMPARE(pr.status(), prStatus); \
    QCOMPARE(pr.statusMessage(), prStatusMessage); \
}

void TestPresence::testPresence()
{
    Presence pr;
    TEST_PRESENCE(pr, false, ConnectionPresenceTypeUnknown, QString(), QString());
    pr.setStatus(ConnectionPresenceTypeAvailable, QLatin1String("available"),
            QLatin1String("I am available"));
    TEST_PRESENCE(pr, true, ConnectionPresenceTypeAvailable, QLatin1String("available"), QLatin1String("I am available"));

    pr = Presence::available();
    TEST_PRESENCE(pr, true, ConnectionPresenceTypeAvailable, QLatin1String("available"), QString());
    pr = Presence::available(QLatin1String("I am available"));
    TEST_PRESENCE(pr, true, ConnectionPresenceTypeAvailable, QLatin1String("available"), QLatin1String("I am available"));

    pr = Presence::away();
    TEST_PRESENCE(pr, true, ConnectionPresenceTypeAway, QLatin1String("away"), QString());
    pr = Presence::away(QLatin1String("I am away"));
    TEST_PRESENCE(pr, true, ConnectionPresenceTypeAway, QLatin1String("away"), QLatin1String("I am away"));

    pr = Presence::brb();
    TEST_PRESENCE(pr, true, ConnectionPresenceTypeAway, QLatin1String("brb"), QString());
    pr = Presence::brb(QLatin1String("I am brb"));
    TEST_PRESENCE(pr, true, ConnectionPresenceTypeAway, QLatin1String("brb"), QLatin1String("I am brb"));

    pr = Presence::busy();
    TEST_PRESENCE(pr, true, ConnectionPresenceTypeBusy, QLatin1String("busy"), QString());
    pr = Presence::busy(QLatin1String("I am busy"));
    TEST_PRESENCE(pr, true, ConnectionPresenceTypeBusy, QLatin1String("busy"), QLatin1String("I am busy"));

    pr = Presence::xa();
    TEST_PRESENCE(pr, true, ConnectionPresenceTypeExtendedAway, QLatin1String("xa"), QString());
    pr = Presence::xa(QLatin1String("I am xa"));
    TEST_PRESENCE(pr, true, ConnectionPresenceTypeExtendedAway, QLatin1String("xa"), QLatin1String("I am xa"));

    pr = Presence::hidden();
    TEST_PRESENCE(pr, true, ConnectionPresenceTypeHidden, QLatin1String("hidden"), QString());
    pr = Presence::hidden(QLatin1String("I am hidden"));
    TEST_PRESENCE(pr, true, ConnectionPresenceTypeHidden, QLatin1String("hidden"), QLatin1String("I am hidden"));

    pr = Presence::offline();
    TEST_PRESENCE(pr, true, ConnectionPresenceTypeOffline, QLatin1String("offline"), QString());
    pr = Presence::offline(QLatin1String("I am offline"));
    TEST_PRESENCE(pr, true, ConnectionPresenceTypeOffline, QLatin1String("offline"), QLatin1String("I am offline"));
}

#define TEST_PRESENCE_SPEC_FULL(specStatus, specType, specMaySetOnSelf, specCanHaveMessage) \
{ \
    SimpleStatusSpec bareSpec; \
    bareSpec.type = specType; \
    bareSpec.maySetOnSelf = specMaySetOnSelf; \
    bareSpec.canHaveMessage = specCanHaveMessage; \
\
    PresenceSpec spec(specStatus, bareSpec); \
    TEST_PRESENCE_SPEC(spec, true, specStatus, specType, specMaySetOnSelf, specCanHaveMessage); \
}

#define TEST_PRESENCE_SPEC(spec, specValid, specStatus, specType, specMaySetOnSelf, specCanHaveMessage) \
{ \
    QVERIFY(spec.isValid() == specValid); \
    if (specValid) { \
        QCOMPARE(spec.presence(), Presence(specType, specStatus, QString())); \
        TEST_PRESENCE(spec.presence(), true, specType, specStatus, QString()); \
        QCOMPARE(spec.presence(QLatin1String("test message")), Presence(specType, specStatus, QLatin1String("test message"))); \
        TEST_PRESENCE(spec.presence(QLatin1String("test message")), true, specType, specStatus, QLatin1String("test message")); \
    } else { \
        QVERIFY(!spec.presence().isValid()); \
    } \
    QCOMPARE(spec.maySetOnSelf(), specMaySetOnSelf); \
    QCOMPARE(spec.canHaveStatusMessage(), specCanHaveMessage); \
\
    if (specValid) { \
        SimpleStatusSpec bareSpec; \
        bareSpec.type = specType; \
        bareSpec.maySetOnSelf = specMaySetOnSelf; \
        bareSpec.canHaveMessage = specCanHaveMessage; \
        QCOMPARE(spec.bareSpec(), bareSpec); \
    } else { \
        QCOMPARE(spec.bareSpec(), SimpleStatusSpec()); \
    } \
}

void TestPresence::testPresenceSpec()
{
    PresenceSpec spec;
    TEST_PRESENCE_SPEC(spec, false, QString(), ConnectionPresenceTypeUnknown, false, false);

    TEST_PRESENCE_SPEC_FULL(QLatin1String("available"), ConnectionPresenceTypeAvailable, true, true);
    TEST_PRESENCE_SPEC_FULL(QLatin1String("brb"), ConnectionPresenceTypeAway, true, true);
    TEST_PRESENCE_SPEC_FULL(QLatin1String("away"), ConnectionPresenceTypeAway, true, true);
    TEST_PRESENCE_SPEC_FULL(QLatin1String("xa"), ConnectionPresenceTypeExtendedAway, false, false);
    TEST_PRESENCE_SPEC_FULL(QLatin1String("offline"), ConnectionPresenceTypeOffline, true, false);
}

QTEST_MAIN(TestPresence)

#include "_gen/presence.cpp.moc.hpp"
<|endoftext|>


<commit_before>#include <fstream>
#include <sstream>
#include <iostream>

#include "allocore/ui/al_Composition.hpp"
#include "allocore/system/al_Time.hpp"
#include "allocore/io/al_File.hpp"

using namespace al;

Composition::Composition(std::string fileName, std::string path) :
    mPath(path), mSubDirectory(""), mCompositionName(fileName), mPlayThread(nullptr),
    mSequencer(nullptr)
{
	mCompositionSteps = loadCompositionSteps(mCompositionName);
}

Composition::~Composition()
{
	mPlaying = false;
	if (mPlayThread) {
		mPlayThread->join();
		delete mPlayThread;
	}
}

void Composition::play()
{
	mPlayerLock.lock();
	stop();
	mCompositionSteps = loadCompositionSteps(mCompositionName);
	mPlaying = true;
	mPlayThread = new std::thread(Composition::playbackThread, this);
	mPlayerLock.unlock();
}

void Composition::stop()
{
	if (mPlayThread) {
		mPlaying = false;
		mPlayThread->join();
		delete mPlayThread;
		mPlayThread = nullptr;
	}
	mSequencer->stopSequence(); // Sequencer should also stop if in the middle of a sequence.
}

bool Composition::playArchive(std::string archiveName)
{
	std::string compositionName = archiveName;
	if (compositionName.size() > 20 && compositionName.substr(compositionName.size() - 20) == ".composition_archive") {
		compositionName = compositionName.substr(0, compositionName.size() - 20);
	} else {
		archiveName += ".composition_archive";
	}
	std::cout << getRootPath() + archiveName << "--" << getRootPath() + archiveName + "/" + compositionName << std::endl;
	if (File::isDirectory(getRootPath() + archiveName) && File::exists(getRootPath() + archiveName + "/" + compositionName + ".composition")) {
		mPlayerLock.lock();
		stop();
		setSubDirectory(archiveName);
		mCompositionName = compositionName;

		mCompositionSteps = loadCompositionSteps(mCompositionName);
		mPlayerLock.unlock();
		play();
	}
	return true;
}

std::string Composition::getName()
{
	return mCompositionName;
}

bool Composition::archiveComposition()
{
	std::string path = getCurrentPath();
	std::string compositionName = mCompositionName;
	bool ok = true;

	std::string fullPath = path;
	fullPath += compositionName + ".composition";

	std::string archivePath = fullPath;
	if (archivePath.size() > 8 && archivePath.substr(archivePath.size() - 8) != "_archive") {
		archivePath += "_archive";
	}

	if (File::isDirectory(archivePath) ) {
		if (!Dir::removeRecursively(archivePath)) {
			std::cerr << "Error removing directory: " << fullPath << " aborting composition archiving." << std::endl;
			return false;
		}
		if (!Dir::make(archivePath)) {
			std::cerr << "Error creating composition archive directory " << fullPath << std::endl;
			return false;
		}

	} else if (!File::exists(archivePath)) {
		if (!Dir::make(archivePath)) {
			std::cerr << "Error creating compostion archive directory " << archivePath << std::endl;
			return false;
		}

	} else {
		// TODO generate new name instead of error
		std::cerr << "compostion directory name taken by file: " << archivePath << std::endl;
		return false;
	}

	auto steps = loadCompositionSteps(compositionName);

	for (auto step: steps) {
		std::cout << step.sequenceName << ":" << step.deltaTime << std::endl;
		PresetSequencer sequencer;
		sequencer.setDirectory(path);
		std::queue<PresetSequencer::Step> sequenceSteps = sequencer.loadSequence(step.sequenceName);
		if (!File::copy(path + step.sequenceName + ".sequence",
		                archivePath + "/" + step.sequenceName + ".sequence")) {
			std::cerr << "Error copying sequence: " << step.sequenceName << " when archiving composition." << std::endl;
			ok = false;
		}
		while(sequenceSteps.size() > 0) {
			PresetSequencer::Step &sequenceStep = sequenceSteps.front();
			if (!File::exists(archivePath + "/" + sequenceStep.presetName + ".preset")
			        && !File::copy(path + sequenceStep.presetName + ".preset",
			                archivePath + "/" + sequenceStep.presetName + ".preset")) {
				std::cerr << "Error copying preset: " << sequenceStep.presetName << " when archiving composition." << std::endl;
				ok = false;
			}
			sequenceSteps.pop();
		}
	}
	if (!File::copy(fullPath,
	                archivePath + "/" + compositionName + ".composition")) {
		 std::cerr << "Error copying composition: " << compositionName << " when archiving composition." << std::endl;
		 ok = false;
	 }

	return true;
}

bool Composition::archive(std::string compositionName, std::string path, bool overwrite)
{
	std::cout << "archive() not implemented" <<std::endl;
	// TODO implement
	return false;

}

bool Composition::restore(std::string compositionName, std::string path, bool overwrite)
{
	std::cout << "restore() not implemented" <<std::endl;
	// TODO implement
	return false;
}

int Composition::size()
{
	mPlayerLock.lock();
	int size = mCompositionSteps.size();
	mPlayerLock.unlock();
	return size;
}

const CompositionStep Composition::getStep(int index)
{
	mPlayerLock.lock();
	CompositionStep step;
	if (index > 0 && index < size()) {
		step = mCompositionSteps[index];
	}
	mPlayerLock.unlock();
	return step;
}

void Composition::insertStep(std::string name, float deltaTime, int index)
{
	//TODO implement
}

void Composition::deleteStep(int index)
{
	//TODO implement
}

void Composition::write()
{
	std::string fileText;
	for(CompositionStep step: mCompositionSteps) {
		fileText += step.sequenceName + ":" +  std::to_string(step.deltaTime) + "\n";
	}
//	std::cout << fileText << std::endl;

	std::string path = getCurrentPath();
	std::string fileName = path + mCompositionName + ".composition";
	std::ofstream f(fileName);
	if (!f.is_open()) {
		std::cout << "Error while opening composition file: " << fileName << std::endl;
		return;
	}
	f << fileText << "::" << std::endl;
	if (f.bad()) {
		std::cout << "Error while writing composition file: " << fileName << std::endl;
	}
	f.close();
}

void Composition::registerBeginCallback(std::function<void (Composition *, void *)> beginCallback,
                                        void *userData)
{

	mBeginCallback = beginCallback;
	mBeginCallbackData = userData;
	mBeginCallbackEnabled = true;
}

void Composition::registerEndCallback(std::function<void (bool, Composition *, void *)> endCallback,
                                      void *userData)
{
	mEndCallback = endCallback;
	mEndCallbackData = userData;
	mEndCallbackEnabled = true;
}

bool Composition::consumeMessage(osc::Message &m, std::string rootOSCPath)
{
	if(m.addressPattern() == rootOSCPath + "/composition/playArchive" && m.typeTags() == "s"){
		std::string val;
		m >> val;std::cout << "play composition archive" << val << std::endl;
		playArchive(val);
		return true;
	} else if(m.addressPattern() == rootOSCPath + "/composition" && m.typeTags() == "s"){
		std::string val;
		m >> val;
		if (val == getName()) {
			std::cout << "play composition " << val << std::endl;
			play();
			return true;
		}
	} else if(m.addressPattern() == rootOSCPath + "/composition/stop" && m.typeTags() == "s"){
		std::string val;
		m >> val;
		if (val == getName()) {
			std::cout << "stop composition " << val << std::endl;
			stop();
			return true;
		}
	} else if(m.addressPattern() == rootOSCPath + "/composition/stop"){
		stop();
		return true;
	}
	return false;
}

std::vector<al::CompositionStep> Composition::loadCompositionSteps(std::string compositionName)
{
	std::vector<al::CompositionStep> steps;
	std::string fullName = getCurrentPath();

	if (fullName.size() > 12 && !(fullName.substr(fullName.size() - 12) == ".composition") ) {
		fullName += compositionName + ".composition";
	}
	std::ifstream f(fullName);
	if (!f.is_open()) {
		std::cout << "Could not open:" << fullName << std::endl;
		return steps;
	}
	std::string line;
	while (getline(f, line)) {
		if (line.substr(0, 2) == "::") {
			break;
		}
		std::stringstream ss(line);
		std::string name, delta;
		std::getline(ss, name, ':');
		std::getline(ss, delta, ':');
		if (name.size() > 0) {
			CompositionStep step;
			step.sequenceName = name;
			step.deltaTime = std::stof(delta);
			steps.push_back(step);
			// std::cout << name  << ":" << delta << std::endl;
		}
	}
	if (f.bad()) {
		std::cout << "Error reading:" << mCompositionName << std::endl;
	}
	return steps;
}

std::string Composition::getRootPath()
{
	std::string path = mPath;
	if (path.back() != '/' && path.size() > 0) {
		path += "/";
	}
	return path;
}

std::string Composition::getCurrentPath()
{
	std::string path = getRootPath();
	path += mSubDirectory;
	if (path.back() != '/' && path.size() > 0) {
		path += "/";
	}
	return path;
}

void Composition::waitForSequencerCallback(bool finished, PresetSequencer *, void *userData)
{
	Composition *comp = static_cast<Composition *>(userData);
	comp->mSequencer->mEndCallback = comp->mSequencerEndCallbackCache;
	comp->mSequencer->mEndCallbackData = comp->mSequencerEndCallbackDataCache;

	if (comp->mEndCallbackEnabled && comp->mEndCallback != nullptr) {
		comp->mEndCallback(finished, comp, comp->mEndCallbackData);
	}

}

void Composition::playbackThread(Composition *composition)
{
	composition->mPlayerLock.lock();
	size_t index = 0;
	if (composition->mCompositionSteps.size() == 0) {
		std::cout << "Composition has no steps. Done." << std::endl;
		return;
	}
	std::cout << "Composition started." << std::endl;

	composition->mSequencer->toggleEnableBeginCallback();
	composition->mSequencer->toggleEnableEndCallback();
	if (composition->mBeginCallbackEnabled && composition->mBeginCallback != nullptr) {
		composition->mBeginCallback(composition, composition->mBeginCallbackData);
	}
	const int granularity = 10; // milliseconds
	auto sequenceStart = std::chrono::high_resolution_clock::now();
	auto targetTime = sequenceStart;
	while (composition->mPlaying) {
		CompositionStep &step = composition->mCompositionSteps[index];
		//auto duration = //std::chrono::time_point_cast<std::chrono::nanoseconds>(step.deltaTime/1e9);
		targetTime += std::chrono::microseconds((int) (step.deltaTime*1e6 - (granularity * 1.5 * 1000.0)));
		while (std::chrono::high_resolution_clock::now() < targetTime) { // Granularity to allow more responsive stopping of composition playback
			std::this_thread::sleep_for(std::chrono::milliseconds(granularity));
			if (composition->mPlaying == false) {
				targetTime = std::chrono::high_resolution_clock::now();
				break;
			}
		}
		std::this_thread::sleep_until(targetTime);
		std::cout << "Composition step:" << step.sequenceName << ":" << step.deltaTime << std::endl;
		// std::cout << "Composition step:" << step.sequenceName << ":" << step.deltaTime << std::endl;
		composition->mSequencer->playSequence(step.sequenceName);
		index++;
		if (index == composition->mCompositionSteps.size()) {
			composition->mPlaying = false;
		}
	}
	composition->mSequencerEndCallbackCache = composition->mSequencer->mEndCallback;
	composition->mSequencerEndCallbackDataCache = composition->mSequencer->mEndCallbackData;

	composition->mSequencer->toggleEnableBeginCallback();
	composition->mSequencer->toggleEnableEndCallback();

	if (composition->mSequencer->running()) { // TODO There is a very small risk of a run condition here is playback stops between the check and the branches
		composition->mSequencer->registerEndCallback(Composition::waitForSequencerCallback, composition);
	} else {
		if (composition->mEndCallbackEnabled && composition->mEndCallback != nullptr) {
			bool finished = index == composition->mCompositionSteps.size();
			composition->mEndCallback(finished, composition, composition->mEndCallbackData);
		}
	}

	composition->mPlayerLock.unlock();
	std::cout << "Composition done." << std::endl;
}
<commit_msg>Minor bug fix for composition path<commit_after>#include <fstream>
#include <sstream>
#include <iostream>

#include "allocore/ui/al_Composition.hpp"
#include "allocore/system/al_Time.hpp"
#include "allocore/io/al_File.hpp"

using namespace al;

Composition::Composition(std::string fileName, std::string path) :
    mPath(path), mSubDirectory(""), mCompositionName(fileName), mPlayThread(nullptr),
    mSequencer(nullptr)
{
	mCompositionSteps = loadCompositionSteps(mCompositionName);
}

Composition::~Composition()
{
	mPlaying = false;
	if (mPlayThread) {
		mPlayThread->join();
		delete mPlayThread;
	}
}

void Composition::play()
{
	mPlayerLock.lock();
	stop();
	mCompositionSteps = loadCompositionSteps(mCompositionName);
	mPlaying = true;
	mPlayThread = new std::thread(Composition::playbackThread, this);
	mPlayerLock.unlock();
}

void Composition::stop()
{
	if (mPlayThread) {
		mPlaying = false;
		mPlayThread->join();
		delete mPlayThread;
		mPlayThread = nullptr;
	}
	mSequencer->stopSequence(); // Sequencer should also stop if in the middle of a sequence.
}

bool Composition::playArchive(std::string archiveName)
{
	std::string compositionName = archiveName;
	if (compositionName.size() > 20 && compositionName.substr(compositionName.size() - 20) == ".composition_archive") {
		compositionName = compositionName.substr(0, compositionName.size() - 20);
	} else {
		archiveName += ".composition_archive";
	}
	std::cout << getRootPath() + archiveName << "--" << getRootPath() + archiveName + "/" + compositionName << std::endl;
	if (File::isDirectory(getRootPath() + archiveName) && File::exists(getRootPath() + archiveName + "/" + compositionName + ".composition")) {
		mPlayerLock.lock();
		stop();
		mSequencer->setHandlerSubDirectory(archiveName);
		setSubDirectory(archiveName);
		mCompositionName = compositionName;

		mCompositionSteps = loadCompositionSteps(mCompositionName);
		mPlayerLock.unlock();
		play();
	}
	return true;
}

std::string Composition::getName()
{
	return mCompositionName;
}

bool Composition::archiveComposition()
{
	std::string path = getCurrentPath();
	std::string compositionName = mCompositionName;
	bool ok = true;

	std::string fullPath = path;
	fullPath += compositionName + ".composition";

	std::string archivePath = fullPath;
	if (archivePath.size() > 8 && archivePath.substr(archivePath.size() - 8) != "_archive") {
		archivePath += "_archive";
	}

	if (File::isDirectory(archivePath) ) {
		if (!Dir::removeRecursively(archivePath)) {
			std::cerr << "Error removing directory: " << fullPath << " aborting composition archiving." << std::endl;
			return false;
		}
		if (!Dir::make(archivePath)) {
			std::cerr << "Error creating composition archive directory " << fullPath << std::endl;
			return false;
		}

	} else if (!File::exists(archivePath)) {
		if (!Dir::make(archivePath)) {
			std::cerr << "Error creating compostion archive directory " << archivePath << std::endl;
			return false;
		}

	} else {
		// TODO generate new name instead of error
		std::cerr << "compostion directory name taken by file: " << archivePath << std::endl;
		return false;
	}

	auto steps = loadCompositionSteps(compositionName);

	for (auto step: steps) {
		std::cout << step.sequenceName << ":" << step.deltaTime << std::endl;
		PresetSequencer sequencer;
		sequencer.setDirectory(path);
		std::queue<PresetSequencer::Step> sequenceSteps = sequencer.loadSequence(step.sequenceName);
		if (!File::copy(path + step.sequenceName + ".sequence",
		                archivePath + "/" + step.sequenceName + ".sequence")) {
			std::cerr << "Error copying sequence: " << step.sequenceName << " when archiving composition." << std::endl;
			ok = false;
		}
		while(sequenceSteps.size() > 0) {
			PresetSequencer::Step &sequenceStep = sequenceSteps.front();
			if (!File::exists(archivePath + "/" + sequenceStep.presetName + ".preset")
			        && !File::copy(path + sequenceStep.presetName + ".preset",
			                archivePath + "/" + sequenceStep.presetName + ".preset")) {
				std::cerr << "Error copying preset: " << sequenceStep.presetName << " when archiving composition." << std::endl;
				ok = false;
			}
			sequenceSteps.pop();
		}
	}
	if (!File::copy(fullPath,
	                archivePath + "/" + compositionName + ".composition")) {
		 std::cerr << "Error copying composition: " << compositionName << " when archiving composition." << std::endl;
		 ok = false;
	 }

	return true;
}

bool Composition::archive(std::string compositionName, std::string path, bool overwrite)
{
	std::cout << "archive() not implemented" <<std::endl;
	// TODO implement
	return false;

}

bool Composition::restore(std::string compositionName, std::string path, bool overwrite)
{
	std::cout << "restore() not implemented" <<std::endl;
	// TODO implement
	return false;
}

int Composition::size()
{
	mPlayerLock.lock();
	int size = mCompositionSteps.size();
	mPlayerLock.unlock();
	return size;
}

const CompositionStep Composition::getStep(int index)
{
	mPlayerLock.lock();
	CompositionStep step;
	if (index > 0 && index < size()) {
		step = mCompositionSteps[index];
	}
	mPlayerLock.unlock();
	return step;
}

void Composition::insertStep(std::string name, float deltaTime, int index)
{
	//TODO implement
}

void Composition::deleteStep(int index)
{
	//TODO implement
}

void Composition::write()
{
	std::string fileText;
	for(CompositionStep step: mCompositionSteps) {
		fileText += step.sequenceName + ":" +  std::to_string(step.deltaTime) + "\n";
	}
//	std::cout << fileText << std::endl;

	std::string path = getCurrentPath();
	std::string fileName = path + mCompositionName + ".composition";
	std::ofstream f(fileName);
	if (!f.is_open()) {
		std::cout << "Error while opening composition file: " << fileName << std::endl;
		return;
	}
	f << fileText << "::" << std::endl;
	if (f.bad()) {
		std::cout << "Error while writing composition file: " << fileName << std::endl;
	}
	f.close();
}

void Composition::registerBeginCallback(std::function<void (Composition *, void *)> beginCallback,
                                        void *userData)
{

	mBeginCallback = beginCallback;
	mBeginCallbackData = userData;
	mBeginCallbackEnabled = true;
}

void Composition::registerEndCallback(std::function<void (bool, Composition *, void *)> endCallback,
                                      void *userData)
{
	mEndCallback = endCallback;
	mEndCallbackData = userData;
	mEndCallbackEnabled = true;
}

bool Composition::consumeMessage(osc::Message &m, std::string rootOSCPath)
{
	if(m.addressPattern() == rootOSCPath + "/composition/playArchive" && m.typeTags() == "s"){
		std::string val;
		m >> val;std::cout << "play composition archive" << val << std::endl;
		playArchive(val);
		return true;
	} else if(m.addressPattern() == rootOSCPath + "/composition" && m.typeTags() == "s"){
		std::string val;
		m >> val;
		if (val == getName()) {
			std::cout << "play composition " << val << std::endl;
			play();
			return true;
		}
	} else if(m.addressPattern() == rootOSCPath + "/composition/stop" && m.typeTags() == "s"){
		std::string val;
		m >> val;
		if (val == getName()) {
			std::cout << "stop composition " << val << std::endl;
			stop();
			return true;
		}
	} else if(m.addressPattern() == rootOSCPath + "/composition/stop"){
		stop();
		return true;
	}
	return false;
}

std::vector<al::CompositionStep> Composition::loadCompositionSteps(std::string compositionName)
{
	std::vector<al::CompositionStep> steps;
	std::string fullName = getCurrentPath();

	if (fullName.size() > 12 && !(fullName.substr(fullName.size() - 12) == ".composition") ) {
		fullName += compositionName + ".composition";
	}
	std::ifstream f(fullName);
	if (!f.is_open()) {
		std::cout << "Could not open:" << fullName << std::endl;
		return steps;
	}
	std::string line;
	while (getline(f, line)) {
		if (line.substr(0, 2) == "::") {
			break;
		}
		std::stringstream ss(line);
		std::string name, delta;
		std::getline(ss, name, ':');
		std::getline(ss, delta, ':');
		if (name.size() > 0) {
			CompositionStep step;
			step.sequenceName = name;
			step.deltaTime = std::stof(delta);
			steps.push_back(step);
			// std::cout << name  << ":" << delta << std::endl;
		}
	}
	if (f.bad()) {
		std::cout << "Error reading:" << mCompositionName << std::endl;
	}
	return steps;
}

std::string Composition::getRootPath()
{
	std::string path = mPath;
	if (path.back() != '/' && path.size() > 0) {
		path += "/";
	}
	return path;
}

std::string Composition::getCurrentPath()
{
	std::string path = getRootPath();
	path += mSubDirectory;
	if (path.back() != '/' && path.size() > 0) {
		path += "/";
	}
	return path;
}

void Composition::waitForSequencerCallback(bool finished, PresetSequencer *, void *userData)
{
	Composition *comp = static_cast<Composition *>(userData);
	comp->mSequencer->mEndCallback = comp->mSequencerEndCallbackCache;
	comp->mSequencer->mEndCallbackData = comp->mSequencerEndCallbackDataCache;

	if (comp->mEndCallbackEnabled && comp->mEndCallback != nullptr) {
		comp->mEndCallback(finished, comp, comp->mEndCallbackData);
	}

}

void Composition::playbackThread(Composition *composition)
{
	composition->mPlayerLock.lock();
	size_t index = 0;
	if (composition->mCompositionSteps.size() == 0) {
		std::cout << "Composition has no steps. Done." << std::endl;
		return;
	}
	std::cout << "Composition started." << std::endl;

	composition->mSequencer->toggleEnableBeginCallback();
	composition->mSequencer->toggleEnableEndCallback();
	if (composition->mBeginCallbackEnabled && composition->mBeginCallback != nullptr) {
		composition->mBeginCallback(composition, composition->mBeginCallbackData);
	}
	const int granularity = 10; // milliseconds
	auto sequenceStart = std::chrono::high_resolution_clock::now();
	auto targetTime = sequenceStart;
	while (composition->mPlaying) {
		CompositionStep &step = composition->mCompositionSteps[index];
		//auto duration = //std::chrono::time_point_cast<std::chrono::nanoseconds>(step.deltaTime/1e9);
		targetTime += std::chrono::microseconds((int) (step.deltaTime*1e6 - (granularity * 1.5 * 1000.0)));
		while (std::chrono::high_resolution_clock::now() < targetTime) { // Granularity to allow more responsive stopping of composition playback
			std::this_thread::sleep_for(std::chrono::milliseconds(granularity));
			if (composition->mPlaying == false) {
				targetTime = std::chrono::high_resolution_clock::now();
				break;
			}
		}
		std::this_thread::sleep_until(targetTime);
		std::cout << "Composition step:" << step.sequenceName << ":" << step.deltaTime << std::endl;
		// std::cout << "Composition step:" << step.sequenceName << ":" << step.deltaTime << std::endl;
		composition->mSequencer->playSequence(step.sequenceName);
		index++;
		if (index == composition->mCompositionSteps.size()) {
			composition->mPlaying = false;
		}
	}
	composition->mSequencerEndCallbackCache = composition->mSequencer->mEndCallback;
	composition->mSequencerEndCallbackDataCache = composition->mSequencer->mEndCallbackData;

	composition->mSequencer->toggleEnableBeginCallback();
	composition->mSequencer->toggleEnableEndCallback();

	if (composition->mSequencer->running()) { // TODO There is a very small risk of a run condition here is playback stops between the check and the branches
		composition->mSequencer->registerEndCallback(Composition::waitForSequencerCallback, composition);
	} else {
		if (composition->mEndCallbackEnabled && composition->mEndCallback != nullptr) {
			bool finished = index == composition->mCompositionSteps.size();
			composition->mEndCallback(finished, composition, composition->mEndCallbackData);
		}
	}

	composition->mPlayerLock.unlock();
	std::cout << "Composition done." << std::endl;
}
<|endoftext|>