<commit_before>//
// Aspia Project
// Copyright (C) 2019 Dmitry Chapyshev <dmitry@aspia.ru>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
//

#include "base/win/service.h"

#include "base/logging.h"
#include "base/message_loop/message_loop_task_runner.h"
#include "base/strings/string_util.h"
#include "base/threading/simple_thread.h"

namespace base::win {

namespace {

class ServiceThread : public SimpleThread
{
public:
    ServiceThread(Service* service);
    ~ServiceThread();

    using EventCallback = std::function<void()>;

    void setStatus(DWORD status);
    void doEvent(EventCallback callback);

    static ServiceThread* self;

    enum class State
    {
        NOT_STARTED,
        ERROR_OCCURRED,
        SERVICE_MAIN_CALLED,
        MESSAGE_LOOP_CREATED,
        RUNNING_AS_CONSOLE,
        RUNNING_AS_SERVICE
    };

    std::condition_variable startup_condition;
    std::mutex startup_lock;
    State startup_state = State::NOT_STARTED;

    std::condition_variable event_condition;
    std::mutex event_lock;
    bool event_processed = false;

protected:
    // SimpleThread implementation.
    void run() override;

private:
    static void WINAPI serviceMain(DWORD argc, LPWSTR* argv);
    static DWORD WINAPI serviceControlHandler(
        DWORD control_code, DWORD event_type, LPVOID event_data, LPVOID context);

    Service* service_;
    std::shared_ptr<TaskRunner> task_runner_;

    SERVICE_STATUS_HANDLE status_handle_ = nullptr;
    SERVICE_STATUS status_;

    DISALLOW_COPY_AND_ASSIGN(ServiceThread);
};

//================================================================================================
// ServiceThread implementation.
//================================================================================================

ServiceThread* ServiceThread::self = nullptr;

ServiceThread::ServiceThread(Service* service)
    : service_(service)
{
    DCHECK(!self);
    self = this;

    task_runner_ = service->taskRunner();
    DCHECK(task_runner_);

    memset(&status_, 0, sizeof(status_));
}

ServiceThread::~ServiceThread()
{
    setStatus(SERVICE_STOPPED);
    stop();

    DCHECK(self);
    self = nullptr;
}

void ServiceThread::setStatus(DWORD status)
{
    status_.dwServiceType = SERVICE_WIN32;
    status_.dwControlsAccepted = 0;
    status_.dwCurrentState = status;
    status_.dwWin32ExitCode = NO_ERROR;
    status_.dwServiceSpecificExitCode = NO_ERROR;
    status_.dwWaitHint = 0;

    if (status == SERVICE_RUNNING)
    {
        status_.dwControlsAccepted =
            SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_SESSIONCHANGE;
    }

    if (status != SERVICE_RUNNING && status != SERVICE_STOPPED)
        ++status_.dwCheckPoint;
    else
        status_.dwCheckPoint = 0;

    if (!SetServiceStatus(status_handle_, &status_))
    {
        PLOG(LS_WARNING) << "SetServiceStatus failed";
        return;
    }
}

void ServiceThread::doEvent(EventCallback callback)
{
    std::unique_lock lock(event_lock);
    event_processed = false;

    task_runner_->postTask([callback]()
    {
        std::scoped_lock lock(self->event_lock);

        callback();

        // Set the event flag is processed.
        self->event_processed = true;

        // Notify waiting thread for the end of processing.
        self->event_condition.notify_all();
    });

    // Wait for the event to be processed by the application.
    while (!event_processed)
        event_condition.wait(lock);
}

void ServiceThread::run()
{
    SERVICE_TABLE_ENTRYW service_table[2];

    service_table[0].lpServiceName = const_cast<wchar_t*>(asWide(service_->name()));
    service_table[0].lpServiceProc = ServiceThread::serviceMain;
    service_table[1].lpServiceName = nullptr;
    service_table[1].lpServiceProc = nullptr;

    if (!StartServiceCtrlDispatcherW(service_table))
    {
        std::scoped_lock lock(self->startup_lock);

        DWORD error_code = GetLastError();
        if (error_code == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT)
        {
            self->startup_state = State::RUNNING_AS_CONSOLE;
        }
        else
        {
            LOG(LS_WARNING) << "StartServiceCtrlDispatcherW failed: "
                            << SystemError(error_code).toString();
            self->startup_state = State::ERROR_OCCURRED;
        }

        self->startup_condition.notify_all();
    }
}

// static
void WINAPI ServiceThread::serviceMain(DWORD /* argc */, LPWSTR* /* argv */)
{
    if (!self)
        return;

    // Start creating the MessageLoop instance.
    {
        std::scoped_lock lock(self->startup_lock);
        self->startup_state = State::SERVICE_MAIN_CALLED;
        self->startup_condition.notify_all();
    }

    // Waiting for the completion of the creation.
    {
        std::unique_lock lock(self->startup_lock);

        while (self->startup_state != State::MESSAGE_LOOP_CREATED)
            self->startup_condition.wait(lock);

        self->startup_state = State::RUNNING_AS_SERVICE;
    }

    self->status_handle_ = RegisterServiceCtrlHandlerExW(
        asWide(self->service_->name()), serviceControlHandler, nullptr);

    if (!self->status_handle_)
    {
        PLOG(LS_WARNING) << "RegisterServiceCtrlHandlerExW failed";
        return;
    }

    self->setStatus(SERVICE_START_PENDING);
    self->doEvent(std::bind(&Service::onStart, self->service_));
    self->setStatus(SERVICE_RUNNING);
}

// static
DWORD WINAPI ServiceThread::serviceControlHandler(
    DWORD control_code, DWORD event_type, LPVOID event_data, LPVOID /* context */)
{
    switch (control_code)
    {
        case SERVICE_CONTROL_INTERROGATE:
            return NO_ERROR;

        case SERVICE_CONTROL_SESSIONCHANGE:
        {
            if (!self)
                return NO_ERROR;

            SessionStatus session_status = static_cast<SessionStatus>(event_type);
            SessionId session_id =
                reinterpret_cast<WTSSESSION_NOTIFICATION*>(event_data)->dwSessionId;

            self->doEvent(std::bind(
                &Service::onSessionEvent, self->service_, session_status, session_id));
        }
        return NO_ERROR;

        case SERVICE_CONTROL_SHUTDOWN:
        case SERVICE_CONTROL_STOP:
        {
            if (!self)
                return NO_ERROR;

            if (control_code == SERVICE_CONTROL_STOP)
                self->setStatus(SERVICE_STOP_PENDING);

            self->doEvent(std::bind(&Service::onStop, self->service_));
        }
        return NO_ERROR;

        default:
            return ERROR_CALL_NOT_IMPLEMENTED;
    }
}

} // namespace

Service::Service(std::u16string_view name, MessageLoop::Type type)
    : type_(type),
      name_(name)
{
    // Nothing
}

Service::~Service() = default;

void Service::exec()
{
    std::unique_ptr<ServiceThread> service_thread = std::make_unique<ServiceThread>(this);

    // Waiting for the launch ServiceThread::serviceMain.
    {
        std::unique_lock lock(service_thread->startup_lock);
        service_thread->startup_state = ServiceThread::State::NOT_STARTED;

        // Starts handler thread.
        service_thread->start();

        while (service_thread->startup_state == ServiceThread::State::NOT_STARTED)
            service_thread->startup_condition.wait(lock);

        if (service_thread->startup_state == ServiceThread::State::ERROR_OCCURRED)
            return;
    }

    message_loop_ = std::make_unique<MessageLoop>(type_);
    task_runner_ = message_loop_->taskRunner();

    // Now we can complete the registration of the service.
    {
        std::scoped_lock lock(service_thread->startup_lock);
        service_thread->startup_state = ServiceThread::State::MESSAGE_LOOP_CREATED;
        service_thread->startup_condition.notify_all();
    }

    message_loop_->run();

    service_thread.reset();
    message_loop_.reset();
}

} // namespace base::win
<commit_msg>- Creating a message loop at the very beginning.<commit_after>//
// Aspia Project
// Copyright (C) 2019 Dmitry Chapyshev <dmitry@aspia.ru>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
//

#include "base/win/service.h"

#include "base/logging.h"
#include "base/message_loop/message_loop_task_runner.h"
#include "base/strings/string_util.h"
#include "base/threading/simple_thread.h"

namespace base::win {

namespace {

class ServiceThread : public SimpleThread
{
public:
    ServiceThread(Service* service);
    ~ServiceThread();

    using EventCallback = std::function<void()>;

    void setStatus(DWORD status);
    void doEvent(EventCallback callback);

    static ServiceThread* self;

    enum class State
    {
        NOT_STARTED,
        ERROR_OCCURRED,
        SERVICE_MAIN_CALLED,
        MESSAGE_LOOP_CREATED,
        RUNNING_AS_CONSOLE,
        RUNNING_AS_SERVICE
    };

    std::condition_variable startup_condition;
    std::mutex startup_lock;
    State startup_state = State::NOT_STARTED;

    std::condition_variable event_condition;
    std::mutex event_lock;
    bool event_processed = false;

protected:
    // SimpleThread implementation.
    void run() override;

private:
    static void WINAPI serviceMain(DWORD argc, LPWSTR* argv);
    static DWORD WINAPI serviceControlHandler(
        DWORD control_code, DWORD event_type, LPVOID event_data, LPVOID context);

    Service* service_;
    std::shared_ptr<TaskRunner> task_runner_;

    SERVICE_STATUS_HANDLE status_handle_ = nullptr;
    SERVICE_STATUS status_;

    DISALLOW_COPY_AND_ASSIGN(ServiceThread);
};

//================================================================================================
// ServiceThread implementation.
//================================================================================================

ServiceThread* ServiceThread::self = nullptr;

ServiceThread::ServiceThread(Service* service)
    : service_(service)
{
    DCHECK(!self);
    self = this;

    task_runner_ = service->taskRunner();
    DCHECK(task_runner_);

    memset(&status_, 0, sizeof(status_));
}

ServiceThread::~ServiceThread()
{
    setStatus(SERVICE_STOPPED);
    stop();

    DCHECK(self);
    self = nullptr;
}

void ServiceThread::setStatus(DWORD status)
{
    status_.dwServiceType = SERVICE_WIN32;
    status_.dwControlsAccepted = 0;
    status_.dwCurrentState = status;
    status_.dwWin32ExitCode = NO_ERROR;
    status_.dwServiceSpecificExitCode = NO_ERROR;
    status_.dwWaitHint = 0;

    if (status == SERVICE_RUNNING)
    {
        status_.dwControlsAccepted =
            SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_SESSIONCHANGE;
    }

    if (status != SERVICE_RUNNING && status != SERVICE_STOPPED)
        ++status_.dwCheckPoint;
    else
        status_.dwCheckPoint = 0;

    if (!SetServiceStatus(status_handle_, &status_))
    {
        PLOG(LS_WARNING) << "SetServiceStatus failed";
        return;
    }
}

void ServiceThread::doEvent(EventCallback callback)
{
    std::unique_lock lock(event_lock);
    event_processed = false;

    task_runner_->postTask([callback]()
    {
        std::scoped_lock lock(self->event_lock);

        callback();

        // Set the event flag is processed.
        self->event_processed = true;

        // Notify waiting thread for the end of processing.
        self->event_condition.notify_all();
    });

    // Wait for the event to be processed by the application.
    while (!event_processed)
        event_condition.wait(lock);
}

void ServiceThread::run()
{
    SERVICE_TABLE_ENTRYW service_table[2];

    service_table[0].lpServiceName = const_cast<wchar_t*>(asWide(service_->name()));
    service_table[0].lpServiceProc = ServiceThread::serviceMain;
    service_table[1].lpServiceName = nullptr;
    service_table[1].lpServiceProc = nullptr;

    if (!StartServiceCtrlDispatcherW(service_table))
    {
        std::scoped_lock lock(self->startup_lock);

        DWORD error_code = GetLastError();
        if (error_code == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT)
        {
            self->startup_state = State::RUNNING_AS_CONSOLE;
        }
        else
        {
            LOG(LS_WARNING) << "StartServiceCtrlDispatcherW failed: "
                            << SystemError(error_code).toString();
            self->startup_state = State::ERROR_OCCURRED;
        }

        self->startup_condition.notify_all();
    }
}

// static
void WINAPI ServiceThread::serviceMain(DWORD /* argc */, LPWSTR* /* argv */)
{
    if (!self)
        return;

    // Start creating the MessageLoop instance.
    {
        std::scoped_lock lock(self->startup_lock);
        self->startup_state = State::SERVICE_MAIN_CALLED;
        self->startup_condition.notify_all();
    }

    // Waiting for the completion of the creation.
    {
        std::unique_lock lock(self->startup_lock);

        while (self->startup_state != State::MESSAGE_LOOP_CREATED)
            self->startup_condition.wait(lock);

        self->startup_state = State::RUNNING_AS_SERVICE;
    }

    self->status_handle_ = RegisterServiceCtrlHandlerExW(
        asWide(self->service_->name()), serviceControlHandler, nullptr);

    if (!self->status_handle_)
    {
        PLOG(LS_WARNING) << "RegisterServiceCtrlHandlerExW failed";
        return;
    }

    self->setStatus(SERVICE_START_PENDING);
    self->doEvent(std::bind(&Service::onStart, self->service_));
    self->setStatus(SERVICE_RUNNING);
}

// static
DWORD WINAPI ServiceThread::serviceControlHandler(
    DWORD control_code, DWORD event_type, LPVOID event_data, LPVOID /* context */)
{
    switch (control_code)
    {
        case SERVICE_CONTROL_INTERROGATE:
            return NO_ERROR;

        case SERVICE_CONTROL_SESSIONCHANGE:
        {
            if (!self)
                return NO_ERROR;

            SessionStatus session_status = static_cast<SessionStatus>(event_type);
            SessionId session_id =
                reinterpret_cast<WTSSESSION_NOTIFICATION*>(event_data)->dwSessionId;

            self->doEvent(std::bind(
                &Service::onSessionEvent, self->service_, session_status, session_id));
        }
        return NO_ERROR;

        case SERVICE_CONTROL_SHUTDOWN:
        case SERVICE_CONTROL_STOP:
        {
            if (!self)
                return NO_ERROR;

            if (control_code == SERVICE_CONTROL_STOP)
                self->setStatus(SERVICE_STOP_PENDING);

            self->doEvent(std::bind(&Service::onStop, self->service_));
        }
        return NO_ERROR;

        default:
            return ERROR_CALL_NOT_IMPLEMENTED;
    }
}

} // namespace

Service::Service(std::u16string_view name, MessageLoop::Type type)
    : type_(type),
      name_(name)
{
    // Nothing
}

Service::~Service() = default;

void Service::exec()
{
    message_loop_ = std::make_unique<MessageLoop>(type_);
    task_runner_ = message_loop_->taskRunner();

    std::unique_ptr<ServiceThread> service_thread = std::make_unique<ServiceThread>(this);

    // Waiting for the launch ServiceThread::serviceMain.
    {
        std::unique_lock lock(service_thread->startup_lock);
        service_thread->startup_state = ServiceThread::State::NOT_STARTED;

        // Starts handler thread.
        service_thread->start();

        while (service_thread->startup_state == ServiceThread::State::NOT_STARTED)
            service_thread->startup_condition.wait(lock);

        if (service_thread->startup_state == ServiceThread::State::ERROR_OCCURRED)
            return;
    }

    // Now we can complete the registration of the service.
    {
        std::scoped_lock lock(service_thread->startup_lock);
        service_thread->startup_state = ServiceThread::State::MESSAGE_LOOP_CREATED;
        service_thread->startup_condition.notify_all();
    }

    message_loop_->run();

    service_thread.reset();
    message_loop_.reset();
}

} // namespace base::win
<|endoftext|>


<commit_before>/*  This file is part of the KDE project
    Copyright (C) 2005-2007 Matthias Kretz <kretz@kde.org>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License version 2 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
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
    Boston, MA 02110-1301, USA.

*/

#include "videowidget.h"
#include "videowidget_p.h"
#include "videowidgetinterface.h"
#include "factory.h"
#include "phonondefs_p.h"
#include "phononnamespace_p.h"

#include <QtGui/QAction>

#define PHONON_INTERFACENAME VideoWidgetInterface

namespace Phonon
{

VideoWidget::VideoWidget(QWidget *parent)
    : QWidget(parent)
    , Phonon::AbstractVideoOutput(*new VideoWidgetPrivate(this))
{
    K_D(VideoWidget);
    d->init();
    d->createBackendObject();
    setMouseTracking(true);
}

VideoWidget::VideoWidget(VideoWidgetPrivate &dd, QWidget *parent)
    : QWidget(parent),
    Phonon::AbstractVideoOutput(dd)
{
    K_D(VideoWidget);
    d->init();
}

void VideoWidgetPrivate::init()
{
    Q_Q(VideoWidget);
    QObject::connect(&cursorTimer, SIGNAL(timeout()), q, SLOT(_k_cursorTimeout()));
    cursorTimer.start();
}

void VideoWidget::mouseMoveEvent(QMouseEvent *)
{
    K_D(VideoWidget);
    if (Qt::BlankCursor == cursor().shape()) {
        unsetCursor();
        d->cursorTimer.start();
    }
}

void VideoWidgetPrivate::_k_cursorTimeout()
{
    Q_Q(VideoWidget);
    if (Qt::ArrowCursor == q->cursor().shape()) {
        q->setCursor(Qt::BlankCursor);
    }
}

void VideoWidgetPrivate::createBackendObject()
{
    if (m_backendObject)
        return;
    Q_Q(VideoWidget);
    m_backendObject = Factory::createVideoWidget(q);
    if (m_backendObject) {
        setupBackendObject();
    }
}

#define PHONON_CLASSNAME VideoWidget

PHONON_INTERFACE_GETTER(Phonon::VideoWidget::AspectRatio, aspectRatio, d->aspectRatio)
PHONON_INTERFACE_SETTER(setAspectRatio, aspectRatio, Phonon::VideoWidget::AspectRatio)

PHONON_INTERFACE_GETTER(Phonon::VideoWidget::ScaleMode, scaleMode, d->scaleMode)
PHONON_INTERFACE_SETTER(setScaleMode, scaleMode, Phonon::VideoWidget::ScaleMode)

PHONON_INTERFACE_GETTER(qreal, brightness, d->brightness)
PHONON_INTERFACE_SETTER(setBrightness, brightness, qreal)

PHONON_INTERFACE_GETTER(qreal, contrast, d->contrast)
PHONON_INTERFACE_SETTER(setContrast, contrast, qreal)

PHONON_INTERFACE_GETTER(qreal, hue, d->hue)
PHONON_INTERFACE_SETTER(setHue, hue, qreal)

PHONON_INTERFACE_GETTER(qreal, saturation, d->saturation)
PHONON_INTERFACE_SETTER(setSaturation, saturation, qreal)

void VideoWidget::setFullScreen(bool newFullScreen)
{
    pDebug() << Q_FUNC_INFO << newFullScreen;
    K_D(VideoWidget);
    // TODO: disable screensaver? or should we leave that responsibility to the
    // application?
    Qt::WindowFlags flags = windowFlags();
    if (newFullScreen) {
        d->changeFlags = !(flags & Qt::Window);
        if (d->changeFlags) {
            flags &= ~Qt::SubWindow;
            flags |= Qt::Window;
        } // else it's a toplevel window already
    } else if (d->changeFlags && parent()) {
        flags &= ~Qt::Window;
        flags |= Qt::SubWindow;
    }
    setWindowFlags(flags);
    if (newFullScreen) {
        showFullScreen();
    } else {
        showNormal();
    }
}

void VideoWidget::exitFullScreen()
{
    setFullScreen(false);
}

void VideoWidget::enterFullScreen()
{
    setFullScreen(true);
}

bool VideoWidgetPrivate::aboutToDeleteBackendObject()
{
    aspectRatio = pINTERFACE_CALL(aspectRatio());
    scaleMode = pINTERFACE_CALL(scaleMode());
    return AbstractVideoOutputPrivate::aboutToDeleteBackendObject();
}

void VideoWidgetPrivate::setupBackendObject()
{
    Q_Q(VideoWidget);
    Q_ASSERT(m_backendObject);
    //AbstractVideoOutputPrivate::setupBackendObject();
    pDebug() << "calling setAspectRatio on the backend " << aspectRatio;
    pINTERFACE_CALL(setAspectRatio(aspectRatio));
    pINTERFACE_CALL(setScaleMode(scaleMode));

    QWidget *w = pINTERFACE_CALL(widget());
    if (w) {
        layout.addWidget(w);
        q->setSizePolicy(w->sizePolicy());
        w->setMouseTracking(true);
    }
}

/*
QSize VideoWidget::sizeHint()
{
    if (k_ptr->backendObject())
    {
        QWidget *w = pINTERFACE_CALL(widget());
        if (w)
            return w->sizeHint();
    }
    return QSize(0, 0);
}

QSize VideoWidget::minimumSizeHint()
{
    if (k_ptr->backendObject())
    {
        QWidget *w = pINTERFACE_CALL(widget());
        if (w)
            return w->minimumSizeHint();
    }
    return QSize(0, 0);
} */

} //namespace Phonon

#include "moc_videowidget.cpp"

#undef PHONON_CLASSNAME
// vim: sw=4 ts=4 tw=80
<commit_msg>there is no need to start the timer in the constructor.<commit_after>/*  This file is part of the KDE project
    Copyright (C) 2005-2007 Matthias Kretz <kretz@kde.org>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License version 2 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
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
    Boston, MA 02110-1301, USA.

*/

#include "videowidget.h"
#include "videowidget_p.h"
#include "videowidgetinterface.h"
#include "factory.h"
#include "phonondefs_p.h"
#include "phononnamespace_p.h"

#include <QtGui/QAction>

#define PHONON_INTERFACENAME VideoWidgetInterface

namespace Phonon
{

VideoWidget::VideoWidget(QWidget *parent)
    : QWidget(parent)
    , Phonon::AbstractVideoOutput(*new VideoWidgetPrivate(this))
{
    K_D(VideoWidget);
    d->init();
    d->createBackendObject();
    setMouseTracking(true);
}

VideoWidget::VideoWidget(VideoWidgetPrivate &dd, QWidget *parent)
    : QWidget(parent),
    Phonon::AbstractVideoOutput(dd)
{
    K_D(VideoWidget);
    d->init();
}

void VideoWidgetPrivate::init()
{
    Q_Q(VideoWidget);
    QObject::connect(&cursorTimer, SIGNAL(timeout()), q, SLOT(_k_cursorTimeout()));
}

void VideoWidget::mouseMoveEvent(QMouseEvent *)
{
    K_D(VideoWidget);
    if (Qt::BlankCursor == cursor().shape()) {
        unsetCursor();
        d->cursorTimer.start();
    }
}

void VideoWidgetPrivate::_k_cursorTimeout()
{
    Q_Q(VideoWidget);
    if (Qt::ArrowCursor == q->cursor().shape()) {
        q->setCursor(Qt::BlankCursor);
    }
}

void VideoWidgetPrivate::createBackendObject()
{
    if (m_backendObject)
        return;
    Q_Q(VideoWidget);
    m_backendObject = Factory::createVideoWidget(q);
    if (m_backendObject) {
        setupBackendObject();
    }
}

#define PHONON_CLASSNAME VideoWidget

PHONON_INTERFACE_GETTER(Phonon::VideoWidget::AspectRatio, aspectRatio, d->aspectRatio)
PHONON_INTERFACE_SETTER(setAspectRatio, aspectRatio, Phonon::VideoWidget::AspectRatio)

PHONON_INTERFACE_GETTER(Phonon::VideoWidget::ScaleMode, scaleMode, d->scaleMode)
PHONON_INTERFACE_SETTER(setScaleMode, scaleMode, Phonon::VideoWidget::ScaleMode)

PHONON_INTERFACE_GETTER(qreal, brightness, d->brightness)
PHONON_INTERFACE_SETTER(setBrightness, brightness, qreal)

PHONON_INTERFACE_GETTER(qreal, contrast, d->contrast)
PHONON_INTERFACE_SETTER(setContrast, contrast, qreal)

PHONON_INTERFACE_GETTER(qreal, hue, d->hue)
PHONON_INTERFACE_SETTER(setHue, hue, qreal)

PHONON_INTERFACE_GETTER(qreal, saturation, d->saturation)
PHONON_INTERFACE_SETTER(setSaturation, saturation, qreal)

void VideoWidget::setFullScreen(bool newFullScreen)
{
    pDebug() << Q_FUNC_INFO << newFullScreen;
    K_D(VideoWidget);
    // TODO: disable screensaver? or should we leave that responsibility to the
    // application?
    Qt::WindowFlags flags = windowFlags();
    if (newFullScreen) {
        d->changeFlags = !(flags & Qt::Window);
        if (d->changeFlags) {
            flags &= ~Qt::SubWindow;
            flags |= Qt::Window;
        } // else it's a toplevel window already
    } else if (d->changeFlags && parent()) {
        flags &= ~Qt::Window;
        flags |= Qt::SubWindow;
    }
    setWindowFlags(flags);
    if (newFullScreen) {
        showFullScreen();
    } else {
        showNormal();
    }
}

void VideoWidget::exitFullScreen()
{
    setFullScreen(false);
}

void VideoWidget::enterFullScreen()
{
    setFullScreen(true);
}

bool VideoWidgetPrivate::aboutToDeleteBackendObject()
{
    aspectRatio = pINTERFACE_CALL(aspectRatio());
    scaleMode = pINTERFACE_CALL(scaleMode());
    return AbstractVideoOutputPrivate::aboutToDeleteBackendObject();
}

void VideoWidgetPrivate::setupBackendObject()
{
    Q_Q(VideoWidget);
    Q_ASSERT(m_backendObject);
    //AbstractVideoOutputPrivate::setupBackendObject();
    pDebug() << "calling setAspectRatio on the backend " << aspectRatio;
    pINTERFACE_CALL(setAspectRatio(aspectRatio));
    pINTERFACE_CALL(setScaleMode(scaleMode));

    QWidget *w = pINTERFACE_CALL(widget());
    if (w) {
        layout.addWidget(w);
        q->setSizePolicy(w->sizePolicy());
        w->setMouseTracking(true);
    }
}

/*
QSize VideoWidget::sizeHint()
{
    if (k_ptr->backendObject())
    {
        QWidget *w = pINTERFACE_CALL(widget());
        if (w)
            return w->sizeHint();
    }
    return QSize(0, 0);
}

QSize VideoWidget::minimumSizeHint()
{
    if (k_ptr->backendObject())
    {
        QWidget *w = pINTERFACE_CALL(widget());
        if (w)
            return w->minimumSizeHint();
    }
    return QSize(0, 0);
} */

} //namespace Phonon

#include "moc_videowidget.cpp"

#undef PHONON_CLASSNAME
// vim: sw=4 ts=4 tw=80
<|endoftext|>


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

 Program:   ORFEO Toolbox
 Language:  C++
 Date:      $Date$
 Version:   $Revision$

 Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
 See OTBCopyright.txt for details.

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

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

#include "otbDEMConvert.h"

#include "otbImage.h"
#include "otbVectorImage.h"
#include "otbImageFileReader.h"
#include "otbStreamingImageFileWriter.h"

// OSSIM include
#include <ossim/base/ossimKeywordNames.h>
#include <ossim/base/ossimStdOutProgress.h>
#include <ossim/base/ossimFilename.h>
#include <ossim/base/ossimKeywordlist.h>
#include <ossim/imaging/ossimJpegWriter.h>
#include <ossim/imaging/ossimImageHandler.h>
#include <ossim/imaging/ossimImageSource.h>
#include <ossim/imaging/ossimImageHandlerRegistry.h>
#include <ossim/imaging/ossimImageWriterFactoryRegistry.h>
#include <ossim/imaging/ossimImageWriterFactory.h>
#include <ossim/imaging/ossimImageFileWriter.h>
#include <ossim/imaging/ossimCacheTileSource.h>
#include <ossim/imaging/ossimBandSelector.h>
#include <ossim/imaging/ossimCibCadrgTileSource.h>

namespace otb
{

template<typename TPixelType>
int generic_convert_to_tif(otb::ApplicationOptionsResult* parseResult, ossimFilename tempFilename)
{
  typedef otb::VectorImage<TPixelType>              ImageType;
  typedef otb::ImageFileReader<ImageType>          ReaderType;
  typedef otb::StreamingImageFileWriter<ImageType> WriterType;

  typename ReaderType::Pointer reader = ReaderType::New();
  typename WriterType::Pointer writer = WriterType::New();

  reader->SetFileName(parseResult->GetInputImage().c_str());
  writer->SetFileName(tempFilename);

  writer->SetInput(reader->GetOutput());
  writer->Update();

  return EXIT_SUCCESS;
}

int DEMConvert::Describe(ApplicationDescriptor* descriptor)
{
  descriptor->SetName("DEMConvertApplication");
  descriptor->SetDescription("Convert a DEM file into a general raster (.ras, .geom and .omd)");
  descriptor->AddInputImage();
  descriptor->AddOption("OutputPath", "The filename (or path filename) of the output. It generates a Output.geom, Output.omd and Output.ras file.","out", 1, true,ApplicationDescriptor::String);
  descriptor->AddOption("KeepTif", "Keep the temporary generate tif file.","ktif", 0, false,ApplicationDescriptor::Boolean);

  return EXIT_SUCCESS;
}

/* The main is simple : read image using OTB and write it as a tif.
* Read this tif using OSSIM and convert it as a general raster file (.ras, .geom and . omd)
* first write the image as a tif (supported by OSSIM) allows to not only be abble to work
* with OSSIM supported format but any more.
*/

int DEMConvert::Execute(otb::ApplicationOptionsResult* parseResult)
{
  // Load input and output filename
  const char * input_file = parseResult->GetInputImage().c_str();

  ossimFilename tempFilename(parseResult->GetParameterString("OutputPath"));
  tempFilename += "_DEMConvert.tif";

  // Search for the input
  typedef otb::VectorImage<double, 2> InputImageType;
  typedef otb::ImageFileReader<InputImageType> ReaderType;
  ReaderType::Pointer reader=ReaderType::New();
  reader->SetFileName(input_file);
  reader->UpdateOutputInformation();

  // Generate the tif image using OTB
  // We keep the same pixel type
  std::string componentTypeInfo(reader->GetImageIO()->GetComponentTypeInfo().name());
  if( componentTypeInfo == typeid(unsigned char).name())
    {
      generic_convert_to_tif<unsigned char>(parseResult, tempFilename);
    }
  else if( componentTypeInfo == typeid(char).name())
    {
      generic_convert_to_tif<char>(parseResult, tempFilename);
    }
  else if( componentTypeInfo == typeid(unsigned short).name())
    {
      generic_convert_to_tif<unsigned short>(parseResult, tempFilename);
    }
  else if( componentTypeInfo == typeid(short).name())
    {
      generic_convert_to_tif<short>(parseResult, tempFilename);
    }
  else if( componentTypeInfo == typeid(unsigned int).name())
    {
      generic_convert_to_tif<unsigned int>(parseResult, tempFilename);
    }
  else if( componentTypeInfo == typeid(int).name())
    {
      generic_convert_to_tif<int>(parseResult, tempFilename);
    }
  else if( componentTypeInfo == typeid(unsigned long).name())
    {
      generic_convert_to_tif<unsigned long>(parseResult, tempFilename);
    }
  else if( componentTypeInfo == typeid(long).name())
    {
      generic_convert_to_tif<long>(parseResult, tempFilename);
    }
  else if( componentTypeInfo == typeid(float).name())
    {
      generic_convert_to_tif<float>(parseResult, tempFilename);
    }
  else if( componentTypeInfo == typeid(double).name())
    {
      generic_convert_to_tif<double>(parseResult, tempFilename);
    }
  else
    {
      itkExceptionMacro("This appication doesn't support image pixel type " << componentTypeInfo);
      return EXIT_FAILURE;
    }

  // Keyword list to initialize image writers with.
   ossimKeywordlist kwl;
   const char* PREFIX = "imagewriter.";
   // Define the output file type
   const ossimString output_type("general_raster_bil");
   kwl.add(PREFIX, ossimKeywordNames::TYPE_KW, output_type.c_str(), true);

   // Get an image handler for the input file.
   ossimRefPtr<ossimImageHandler> ih = ossimImageHandlerRegistry::instance()->open(tempFilename);

   // Initialize the
   if (ih->getErrorStatus() == ossimErrorCodes::OSSIM_ERROR)
   {
     itkExceptionMacro("Error reading image:  " << input_file << "Exiting application...");
     return EXIT_FAILURE;
   }

   ih->initialize();

   ossimRefPtr<ossimImageSource> source = ih.get();
   ossimRefPtr<ossimBandSelector> bs = 0;

   // Get the image rectangle for the rrLevel selected.
   ossimIrect output_rect;
   output_rect = source->getBoundingRect(0);

   ossimRefPtr<ossimImageFileWriter> writer =
     ossimImageWriterFactoryRegistry::instance()->createWriter(kwl, PREFIX);

   writer->connectMyInputTo(0, source.get());
   writer->open(ossimFilename(parseResult->GetParameterString("OutputPath"))+".ras");

   // Add a listener to get percent complete.
   ossimStdOutProgress prog(0, true);
   writer->addListener(&prog);

   if (writer->getErrorStatus() == ossimErrorCodes::OSSIM_OK)
   {
      if( (ih->getOutputScalarType() != OSSIM_UCHAR) &&
          (PTR_CAST(ossimJpegWriter, writer.get()) ) )
      {
         writer->setScaleToEightBitFlag(true);
      }

      ossimRefPtr<ossimCacheTileSource> cache = new ossimCacheTileSource;
      ossimIpt tileWidthHeight(ih->getImageTileWidth(),
                               ih->getImageTileHeight());
      // only use the cache if its stripped
      if(static_cast<ossim_uint32>(tileWidthHeight.x) ==
         ih->getBoundingRect().width())
      {
         cache->connectMyInputTo(0, source.get());
         cache->setTileSize(tileWidthHeight);
         writer->connectMyInputTo(0, cache.get());
      }
      else
      {
         writer->connectMyInputTo(0, source.get());
      }
      writer->initialize();
      writer->setAreaOfInterest(output_rect); // Set the output rectangle.

      try
      {
         writer->execute();
      }
      catch(std::exception& e)
      {
        itkExceptionMacro("Error occurs writing the ouput image...");
        return EXIT_FAILURE;
      }

   }
   else
     {
       itkExceptionMacro("Error detected in the image writer...");
       return EXIT_FAILURE;
     }

   if ( parseResult->IsOptionPresent("KeepTif") == false)
     {
       bool resRemove = tempFilename.remove();
       if( resRemove == false )
         {
           std::cout<<"Enable to erase the output temporary file "<<tempFilename<<"."<<std::endl;
         }
     }

   return EXIT_SUCCESS;
}

} // namespace otb
<commit_msg>ENH : refactoring, direct ras writing with OTB, no more cache tif image<commit_after>/*=========================================================================

 Program:   ORFEO Toolbox
 Language:  C++
 Date:      $Date$
 Version:   $Revision$

 Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
 See OTBCopyright.txt for details.

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

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

#include "otbDEMConvert.h"

#include "otbImage.h"
#include "otbVectorImage.h"
#include "otbImageFileReader.h"
#include "otbStreamingImageFileWriter.h"
#include "otbStreamingMinMaxVectorImageFilter.h"

// OSSIM include
#include <ossim/base/ossimKeywordNames.h>
#include <ossim/base/ossimStdOutProgress.h>
#include <ossim/base/ossimFilename.h>
#include <ossim/base/ossimKeywordlist.h>
#include <ossim/imaging/ossimJpegWriter.h>
#include <ossim/imaging/ossimImageHandler.h>
#include <ossim/imaging/ossimImageSource.h>
#include <ossim/imaging/ossimImageHandlerRegistry.h>
#include <ossim/imaging/ossimImageWriterFactoryRegistry.h>
#include <ossim/imaging/ossimImageWriterFactory.h>
#include <ossim/imaging/ossimImageFileWriter.h>
//#include <ossim/imaging/ossimCacheTileSource.h>
//#include <ossim/imaging/ossimBandSelector.h>
//#include <ossim/imaging/ossimCibCadrgTileSource.h>
#include <ossim/base/ossimEndian.h>
#include <ossim/base/ossimScalarTypeLut.h>
#include <ossim/imaging/ossimMetadataFileWriter.h>
//#include <ossim/base/ossimSource.h>
#include <ossim/imaging/ossimGeomFileWriter.h>

namespace otb
{

template<typename TPixelType>
int generic_convert_to_ras(otb::ApplicationOptionsResult* parseResult, ossimFilename rasFilename)
{
  typedef otb::VectorImage<TPixelType>              ImageType;
  typedef otb::ImageFileReader<ImageType>          ReaderType;
  typedef otb::StreamingImageFileWriter<ImageType> WriterType;

  typename ReaderType::Pointer reader = ReaderType::New();
  typename WriterType::Pointer writer = WriterType::New();

  reader->SetFileName(parseResult->GetInputImage().c_str());
  writer->SetFileName(rasFilename);

  writer->SetInput(reader->GetOutput());
  writer->Update();

  return EXIT_SUCCESS;
}

int DEMConvert::Describe(ApplicationDescriptor* descriptor)
{
  descriptor->SetName("DEMConvertApplication");
  descriptor->SetDescription("Convert a DEM file into a general raster (.ras, .geom and .omd)");
  descriptor->AddInputImage();
  descriptor->AddOption("OutputPath", "The filename (or path filename) of the output. It generates a Output.geom, Output.omd and Output.ras file.","out", 1, true, ApplicationDescriptor::String);

  return EXIT_SUCCESS;
}

/* The main is simple : read image using OTB and write it as a tif.
* Read this tif using OSSIM and convert it as a general raster file (.ras, .geom and . omd)
* first write the image as a tif (supported by OSSIM) allows to not only be abble to work
* with OSSIM supported format but any more.
*/

int DEMConvert::Execute(otb::ApplicationOptionsResult* parseResult)
{
  // Load input and output filename
  const char * input_file = parseResult->GetInputImage().c_str();

  ossimFilename rasFilename(parseResult->GetParameterString("OutputPath"));
  rasFilename += ".ras";

  // Search for the input
  typedef otb::VectorImage<double, 2> InputImageType;
  typedef otb::ImageFileReader<InputImageType> ReaderType;
  typedef otb::StreamingMinMaxVectorImageFilter<InputImageType> MinMaxCalculatorType;

  ReaderType::Pointer reader=ReaderType::New();
  reader->SetFileName(input_file);
  reader->UpdateOutputInformation();

  // Generate the tif image using OTB
  // We keep the same pixel type
  std::string componentTypeInfo(reader->GetImageIO()->GetComponentTypeInfo().name());
  if( componentTypeInfo == typeid(unsigned char).name())
    {
      generic_convert_to_ras<unsigned char>(parseResult, rasFilename);
    }
  else if( componentTypeInfo == typeid(char).name())
    {
      generic_convert_to_ras<char>(parseResult, rasFilename);
    }
  else if( componentTypeInfo == typeid(unsigned short).name())
    {
      generic_convert_to_ras<unsigned short>(parseResult, rasFilename);
    }
  else if( componentTypeInfo == typeid(short).name())
    {
      generic_convert_to_ras<short>(parseResult, rasFilename);
    }
  else if( componentTypeInfo == typeid(unsigned int).name())
    {
      generic_convert_to_ras<unsigned int>(parseResult, rasFilename);
    }
  else if( componentTypeInfo == typeid(int).name())
    {
      generic_convert_to_ras<int>(parseResult, rasFilename);
    }
  else if( componentTypeInfo == typeid(unsigned long).name())
    {
      generic_convert_to_ras<unsigned long>(parseResult, rasFilename);
    }
  else if( componentTypeInfo == typeid(long).name())
    {
      generic_convert_to_ras<long>(parseResult, rasFilename);
    }
  else if( componentTypeInfo == typeid(float).name())
    {
      generic_convert_to_ras<float>(parseResult, rasFilename);
    }
  else if( componentTypeInfo == typeid(double).name())
    {
      generic_convert_to_ras<double>(parseResult, rasFilename);
    }
  else
    {
      itkExceptionMacro("This appication doesn't support image pixel type " << componentTypeInfo);
      return EXIT_FAILURE;
    }

  // Keyword list to initialize image writers with.
  ossimKeywordlist kwl;
  const char* PREFIX = "imagewriter.";
  // Define the output file type
  const ossimString output_type("general_raster_bil");
  kwl.add(PREFIX, ossimKeywordNames::TYPE_KW, output_type.c_str(), true);

  // Get an image handler for the input file.
  ossimRefPtr<ossimImageHandler> ih = ossimImageHandlerRegistry::instance()->open(rasFilename);

  // Initialize the
  if (ih->getErrorStatus() == ossimErrorCodes::OSSIM_ERROR)
    {
      itkExceptionMacro("Error reading image:  " << input_file << "Exiting application...");
      return EXIT_FAILURE;
    }

  ih->initialize();

  ossimRefPtr<ossimImageSource> source = ih.get();

  ossimString interleaveType = "bil";
  ossimString scalar = ossimScalarTypeLut::instance()->getEntryString(ih->getOutputScalarType());

  // Compute image min/max
  MinMaxCalculatorType::Pointer minMax = MinMaxCalculatorType::New();
  minMax->SetInput(reader->GetOutput());
  minMax->Update();

/*
  std::vector<double> minVect;
  std::vector<double> maxVect;
  for (unsigned int i=0; i<reader->GetOutput()->GetNumberOfComponentsPerPixel(); ++i)
    {
      minVect.push_back( static_cast<double>(ih->getMinPixelValue(i) ) );
      maxVect.push_back( static_cast<double>(ih->getMaxPixelValue(i) ) );
    }
  */

  /***************************************************************************
   ************************** WRITE OMD file
   ****************************************************************************/
  // Make a header file name from the image file.
   ossimFilename headerFile(rasFilename);
   headerFile.setExtension(".omd"); // ossim meta data

   std::ofstream os;
   os.open(headerFile.c_str(), ios::out);
   if (!os)
   {
      itkExceptionMacro(" Error: Could not open:  " << headerFile);
      return EXIT_FAILURE;
   }

   os << "// *** ossim meta data general raster header file ***\n"
      << ossimKeywordNames::IMAGE_FILE_KW << ":  "
      << rasFilename.file().c_str() << "\n"
      << ossimKeywordNames::IMAGE_TYPE_KW << ":  "
      << output_type << "\n"
      << ossimKeywordNames::INTERLEAVE_TYPE_KW << ":  "
      << interleaveType.c_str() << "\n"
      << ossimKeywordNames::NUMBER_BANDS_KW << ":  "
      << reader->GetOutput()->GetNumberOfComponentsPerPixel() << "\n"
      << ossimKeywordNames::NUMBER_LINES_KW << ":  "
      << ih->getNumberOfLines() << "\n"//(theAreaOfInterest.lr().y - theAreaOfInterest.ul().y + 1) << "\n"
      << ossimKeywordNames::NUMBER_SAMPLES_KW << ":  "
      << ih->getNumberOfSamples() << "\n"//(theAreaOfInterest.lr().x - theAreaOfInterest.ul().x + 1) << "\n"
      << ossimKeywordNames::SCALAR_TYPE_KW << ":  "
      << scalar.c_str() << "\n"
      << ossimKeywordNames::BYTE_ORDER_KW <<": "
      << ((ossimEndian().getSystemEndianType()==OSSIM_BIG_ENDIAN)?"big_endian":"little_endian")
      << "\n"
      << std::endl;

   // Output the null/min/max for each band.
   os << "\n// NOTE:  Bands are one based, band1 is the first band."
      << std::endl;

   for (ossim_uint32 i=0; i<reader->GetOutput()->GetNumberOfComponentsPerPixel(); ++i)
   {
      ossimString prefix = ossimKeywordNames::BAND_KW +
                           ossimString::toString(i+1) + ".";

      ossimString null_pix = ossimString::toString(ih->getNullPixelValue(i));
      ossimString  min_pix   = ossimString::toString(minMax->GetMinimum()[i]);
      ossimString max_pix  = ossimString::toString(minMax->GetMaximum()[i]);

      os << prefix.c_str() << ossimKeywordNames::NULL_VALUE_KW << ":  "
         << null_pix.c_str() << "\n"
         << prefix << ossimKeywordNames::MIN_VALUE_KW << ":  "
         << min_pix.c_str() << "\n"
         << prefix << ossimKeywordNames::MAX_VALUE_KW << ":  "
         << max_pix.c_str() << std::endl;
   }

   os.close();

   /***************************************************************************
   ************************** WRITE GEOM file
   ***************************************************************************/
   // Make the file name.
   ossimFilename geomFile( rasFilename );
   geomFile.setExtension(ossimString("geom"));

   // Make the writer.
   ossimRefPtr<ossimMetadataFileWriter> geoWriter = new ossimGeomFileWriter();

   // Set things up.
   geoWriter->connectMyInputTo(0, source.get());
   geoWriter->setFilename(geomFile);
   geoWriter->initialize();
   geoWriter->setPixelType(OSSIM_PIXEL_IS_POINT);
   source.get()->initialize();
   geoWriter->setAreaOfInterest( ih->getBoundingRect() );

   // Write it to disk.
   try
     {
       geoWriter->execute();
     }
   catch(std::exception& e)
     {
       itkExceptionMacro("Error occurs writing geom file...");
       return EXIT_FAILURE;
     }

   return EXIT_SUCCESS;
}

} // namespace otb
<|endoftext|>


<commit_before>//=====================================================================//
/*! @file
    @brief  VL53L0X 距離センサー・サンプル
    @author 平松邦仁 (hira@rvf-rc45.net)
	@copyright	Copyright (C) 2017 Kunihito Hiramatsu @n
				Released under the MIT license @n
				https://github.com/hirakuni45/R8C/blob/master/LICENSE
*/
//=====================================================================//
#include <cstring>
#include "system.hpp"
#include "clock.hpp"
#include "port.hpp"
#include "common/command.hpp"
#include "common/format.hpp"
#include "common/intr_utils.hpp"
#include "common/port_map.hpp"
#include "common/uart_io.hpp"
#include "common/fifo.hpp"
#include "common/trb_io.hpp"
#include "chip/VL53L0X.hpp"

namespace {

	typedef device::trb_io<utils::null_task, uint8_t> timer_b;
	timer_b timer_b_;

	typedef utils::fifo<uint8_t, 16> buffer;
	typedef device::uart_io<device::UART0, buffer, buffer> uart;
	uart uart_;

	// I2C ポートの定義クラス
	// P4_B5 (12): SDA
	typedef device::PORT<device::PORT4, device::bitpos::B5> sda_port;
	// P1_B7 (13): SCL
	typedef device::PORT<device::PORT1, device::bitpos::B7> scl_port;

	typedef device::iica_io<sda_port, scl_port> iica;
	iica	i2c_;
	typedef chip::VL53L0X<iica> VLX;
	VLX		vlx_(i2c_);

	utils::command<64> command_;
}

extern "C" {

	void sci_putch(char ch) {
		uart_.putch(ch);
	}

	char sci_getch(void) {
		return uart_.getch();
	}

	uint16_t sci_length() {
		return uart_.length();
	}

	void sci_puts(const char* str) {
		uart_.puts(str);
	}

	void TIMER_RB_intr(void) {
		timer_b_.itask();
		vlx_.add_millis(10);
	}

	void UART0_TX_intr(void) {
		uart_.isend();
	}

	void UART0_RX_intr(void) {
		uart_.irecv();
	}

}

namespace {

}

//  __attribute__ ((section (".exttext")))
int main(int argc, char *argv[])
{
	using namespace device;

// クロック関係レジスタ・プロテクト解除
	PRCR.PRC0 = 1;

// 高速オンチップオシレーターへ切り替え(20MHz)
// ※ F_CLK を設定する事（Makefile内）
	OCOCR.HOCOE = 1;
	utils::delay::micro_second(1);  // >=30us(125KHz)
	SCKCR.HSCKSEL = 1;
	CKSTPR.SCKSEL = 1;

	// タイマーＢ初期化
	{
		uint8_t ir_level = 2;
		timer_b_.start_timer(100, ir_level);
	}

	// UART の設定 (P1_4: TXD0[out], P1_5: RXD0[in])
	// ※シリアルライターでは、RXD 端子は、P1_6 となっているので注意！
	{
		utils::PORT_MAP(utils::port_map::P14::TXD0);
		utils::PORT_MAP(utils::port_map::P15::RXD0);
		uint8_t ir_level = 1;
		uart_.start(57600, ir_level);
	}

	// I2C クラスの初期化
	{
		i2c_.start(iica::speed::fast);
	}

	// VL53L0X を開始
	if(!vlx_.start()) {
		utils::format("VL53L0X start fail\n");
	} else {
		// 20ms
		vlx_.set_measurement_timing_budget(200000);
	}

	sci_puts("Start R8C VL53L0X monitor\n");
	command_.set_prompt("# ");

	// LED シグナル用ポートを出力
	PD1.B0 = 1;

	uint8_t cnt = 0;
	uint8_t itv = 0;
	while(1) {
		timer_b_.sync();

		if(cnt >= 20) {
			cnt = 0;
		}
		if(cnt < 10) P1.B0 = 1;
		else P1.B0 = 0;
		++cnt;

		++itv;
		if(itv >= 100) {
			auto len = vlx_.read_range_single_millimeters();
			utils::format("Length: %d\n") % len;
			itv = 0;
		}

		// コマンド入力と、コマンド解析
		if(command_.service()) {
			uint8_t cmdn = command_.get_words();
			if(cmdn >= 1) {
				if(command_.cmp_word(0, "date")) {
					if(cmdn == 1) {

					} else {

					}
				} else if(command_.cmp_word(0, "help")) {
//					sci_puts("date\n");
//					sci_puts("date yyyy/mm/dd hh:mm[:ss]\n");
				} else {
					char buff[12];
					if(command_.get_word(0, sizeof(buff), buff)) {
						utils::format("Command error: %s\n") % buff;
					}
				}
			}
		}
	}
}
<commit_msg>update print interval<commit_after>//=====================================================================//
/*! @file
    @brief  VL53L0X 距離センサー・サンプル
    @author 平松邦仁 (hira@rvf-rc45.net)
	@copyright	Copyright (C) 2017 Kunihito Hiramatsu @n
				Released under the MIT license @n
				https://github.com/hirakuni45/R8C/blob/master/LICENSE
*/
//=====================================================================//
#include <cstring>
#include "system.hpp"
#include "clock.hpp"
#include "port.hpp"
#include "common/command.hpp"
#include "common/format.hpp"
#include "common/intr_utils.hpp"
#include "common/port_map.hpp"
#include "common/uart_io.hpp"
#include "common/fifo.hpp"
#include "common/trb_io.hpp"
#include "chip/VL53L0X.hpp"

namespace {

	typedef device::trb_io<utils::null_task, uint8_t> timer_b;
	timer_b timer_b_;

	typedef utils::fifo<uint8_t, 16> buffer;
	typedef device::uart_io<device::UART0, buffer, buffer> uart;
	uart uart_;

	// I2C ポートの定義クラス
	// P4_B5 (12): SDA
	typedef device::PORT<device::PORT4, device::bitpos::B5> sda_port;
	// P1_B7 (13): SCL
	typedef device::PORT<device::PORT1, device::bitpos::B7> scl_port;

	typedef device::iica_io<sda_port, scl_port> iica;
	iica	i2c_;
	typedef chip::VL53L0X<iica> VLX;
	VLX		vlx_(i2c_);

	utils::command<64> command_;
}

extern "C" {

	void sci_putch(char ch) {
		uart_.putch(ch);
	}

	char sci_getch(void) {
		return uart_.getch();
	}

	uint16_t sci_length() {
		return uart_.length();
	}

	void sci_puts(const char* str) {
		uart_.puts(str);
	}

	void TIMER_RB_intr(void) {
		timer_b_.itask();
		vlx_.add_millis(10);
	}

	void UART0_TX_intr(void) {
		uart_.isend();
	}

	void UART0_RX_intr(void) {
		uart_.irecv();
	}

}

namespace {

}

//  __attribute__ ((section (".exttext")))
int main(int argc, char *argv[])
{
	using namespace device;

// クロック関係レジスタ・プロテクト解除
	PRCR.PRC0 = 1;

// 高速オンチップオシレーターへ切り替え(20MHz)
// ※ F_CLK を設定する事（Makefile内）
	OCOCR.HOCOE = 1;
	utils::delay::micro_second(1);  // >=30us(125KHz)
	SCKCR.HSCKSEL = 1;
	CKSTPR.SCKSEL = 1;

	// タイマーＢ初期化
	{
		uint8_t ir_level = 2;
		timer_b_.start_timer(100, ir_level);
	}

	// UART の設定 (P1_4: TXD0[out], P1_5: RXD0[in])
	// ※シリアルライターでは、RXD 端子は、P1_6 となっているので注意！
	{
		utils::PORT_MAP(utils::port_map::P14::TXD0);
		utils::PORT_MAP(utils::port_map::P15::RXD0);
		uint8_t ir_level = 1;
		uart_.start(57600, ir_level);
	}

	// I2C クラスの初期化
	{
		i2c_.start(iica::speed::fast);
	}

	// VL53L0X を開始
	if(!vlx_.start()) {
		utils::format("VL53L0X start fail\n");
	} else {
		// 20ms
		vlx_.set_measurement_timing_budget(200000);
	}

	sci_puts("Start R8C VL53L0X monitor\n");
	command_.set_prompt("# ");

	// LED シグナル用ポートを出力
	PD1.B0 = 1;

	uint8_t cnt = 0;
	uint8_t itv = 0;
	while(1) {
		timer_b_.sync();

		if(cnt >= 20) {
			cnt = 0;
		}
		if(cnt < 10) P1.B0 = 1;
		else P1.B0 = 0;
		++cnt;

		++itv;
		if(itv >= 50) {
			auto len = vlx_.read_range_single_millimeters();
			utils::format("Length: %d\n") % len;
			itv = 0;
		}

		// コマンド入力と、コマンド解析
		if(command_.service()) {
			uint8_t cmdn = command_.get_words();
			if(cmdn >= 1) {
				if(command_.cmp_word(0, "date")) {
					if(cmdn == 1) {

					} else {

					}
				} else if(command_.cmp_word(0, "help")) {
//					sci_puts("date\n");
//					sci_puts("date yyyy/mm/dd hh:mm[:ss]\n");
				} else {
					char buff[12];
					if(command_.get_word(0, sizeof(buff), buff)) {
						utils::format("Command error: %s\n") % buff;
					}
				}
			}
		}
	}
}
<|endoftext|>


<commit_before>#include "amd64.h"
#include "distribution.hh"
#include "spinbarrier.hh"
#include "libutil.h"
#include "xsys.h"

#include <fcntl.h>
#include <spawn.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/wait.h>

#include <string>
#include <thread>

// Set to 1 to manage the queue manager's life time from this program.
// Set to 0 if the queue manager is started and stopped outside of
// mailbench.
#define START_QMAN 1

using std::string;

enum { warmup_secs = 1 };
enum { duration = 5 };

const char *message =
  "Received: from incoming.csail.mit.edu (incoming.csail.mit.edu [128.30.2.16])\n"
  "        by metroplex (Cyrus v2.2.13-Debian-2.2.13-14+lenny5) with LMTPA;\n"
  "        Tue, 19 Mar 2013 22:45:50 -0400\n"
  "X-Sieve: CMU Sieve 2.2\n"
  "Received: from mailhub-auth-3.mit.edu ([18.9.21.43])\n"
  "        by incoming.csail.mit.edu with esmtps\n"
  "        (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32)\n"
  "        (Exim 4.72)\n"
  "        (envelope-from <xxxxxxxx@MIT.EDU>)\n"
  "        id 1UI92E-0007D2-7N\n"
  "        for xxxxxxxxx@csail.mit.edu; Tue, 19 Mar 2013 22:45:50 -0400\n"
  "Received: from outgoing.mit.edu (OUTGOING-AUTH-1.MIT.EDU [18.9.28.11])\n"
  "        by mailhub-auth-3.mit.edu (8.13.8/8.9.2) with ESMTP id r2K2jnO5025684\n"
  "        for <xxxxxxxx@mit.edu>; Tue, 19 Mar 2013 22:45:49 -0400\n"
  "Received: from xxxxxxxxx.csail.mit.edu (xxxxxxxxx.csail.mit.edu [18.26.4.91])\n"
  "        (authenticated bits=0)\n"
  "        (User authenticated as xxxxxxxx@ATHENA.MIT.EDU)\n"
  "        by outgoing.mit.edu (8.13.8/8.12.4) with ESMTP id r2K2jmc7032022\n"
  "        (version=TLSv1/SSLv3 cipher=DHE-RSA-AES128-SHA bits=128 verify=NOT)\n"
  "        for <xxxxxxxx@mit.edu>; Tue, 19 Mar 2013 22:45:49 -0400\n"
  "Received: from xxxxxxx by xxxxxxxxx.csail.mit.edu with local (Exim 4.80)\n"
  "        (envelope-from <xxxxxxxx@mit.edu>)\n"
  "        id 1UI92C-0000il-4L\n"
  "        for xxxxxxxx@mit.edu; Tue, 19 Mar 2013 22:45:48 -0400\n"
  "From: Austin Clements <xxxxxxxx@MIT.EDU>\n"
  "To: xxxxxxxx@mit.edu\n"
  "Subject: Test message\n"
  "User-Agent: Notmuch/0.15+6~g7d4cb73 (http://notmuchmail.org) Emacs/23.4.1\n"
  "        (i486-pc-linux-gnu)\n"
  "Date: Tue, 19 Mar 2013 22:45:48 -0400\n"
  "Message-ID: <874ng6vler.fsf@xxxxxxxxx.csail.mit.edu>\n"
  "MIME-Version: 1.0\n"
  "Content-Type: text/plain; charset=us-ascii\n"
  "\n"
  "Hello.\n";

extern char **environ;

static spin_barrier bar;

static concurrent_distribution<uint64_t> start_tsc, stop_tsc;
static concurrent_distribution<uint64_t> start_usec, stop_usec;
static concurrent_distribution<uint64_t> count;

static volatile bool stop __mpalign__;
static volatile bool warmup;
static __padout__ __attribute__((unused));

static void
timer_thread(void)
{
  warmup = true;
  bar.join();
  bar.join();
  sleep(warmup_secs);
  warmup = false;
  sleep(duration);
  stop = true;
}

static void
xwaitpid(int pid, const char *cmd)
{
  int status;
  if (waitpid(pid, &status, 0) < 0)
    edie("waitpid %s failed", cmd);
  if (!WIFEXITED(status) || WEXITSTATUS(status))
    die("status %d from %s", status, cmd);
}

static void
do_mua(int cpu, string spooldir, string msgpath)
{
  const char *argv[] = {"./mail-enqueue", spooldir.c_str(), "user", nullptr};
#if defined(XV6_USER)
  int errno;
#endif
  setaffinity(cpu);

  // Open message file (alternatively, we could use an open spawn
  // action)
  int msgfd = open(msgpath.c_str(), O_RDONLY|O_CLOEXEC|O_ANYFD);
  if (msgfd < 0)
    edie("open %s failed", msgpath.c_str());

  bool mywarmup = true;
  uint64_t mycount = 0;
  while (!stop) {
    if (__builtin_expect(warmup != mywarmup, 0)) {
      mywarmup = warmup;
      mycount = 0;
      start_usec.add(now_usec());
      start_tsc.add(rdtsc());
    }

    if (lseek(msgfd, 0, SEEK_SET) < 0)
      edie("lseek failed");

    pid_t pid;
    posix_spawn_file_actions_t actions;
    if ((errno = posix_spawn_file_actions_init(&actions)))
      edie("posix_spawn_file_actions_init failed");
    if ((errno = posix_spawn_file_actions_adddup2(&actions, msgfd, 0)))
      edie("posix_spawn_file_actions_adddup2 failed");
    if ((errno = posix_spawn(&pid, argv[0], &actions, nullptr,
                             const_cast<char *const*>(argv), environ)))
      edie("posix_spawn failed");
    if ((errno = posix_spawn_file_actions_destroy(&actions)))
      edie("posix_spawn_file_actions_destroy failed");
    xwaitpid(pid, argv[0]);

    ++mycount;
  }

  stop_usec.add(now_usec());
  stop_tsc.add(rdtsc());
  count.add(mycount);
}

static void
xmkdir(const string &d)
{
  if (mkdir(d.c_str(), 0777) < 0)
    edie("failed to mkdir %s", d.c_str());
}

static void
create_spool(const string &base)
{
  xmkdir(base);
  xmkdir(base + "/pid");
  xmkdir(base + "/todo");
  xmkdir(base + "/mess");
}

static void
create_maildir(const string &base)
{
  xmkdir(base);
  xmkdir(base + "/tmp");
  xmkdir(base + "/new");
  xmkdir(base + "/cur");
}

void
usage(const char *argv0)
{
  fprintf(stderr, "Usage: %s basedir nthreads\n", argv0);
  exit(2);
}

int
main(int argc, char **argv)
{
  if (argc != 3)
    usage(argv[0]);

  string basedir(argv[1]);
  const char *nthreads_str = argv[2];
  int nthreads = atoi(nthreads_str);
  if (nthreads <= 0)
    usage(argv[0]);

  // Create spool and inboxes
  // XXX This terminology is wrong.  The spool is where mail
  // ultimately gets delivered to.
  string spooldir = basedir + "/spool";
  if (START_QMAN)
    create_spool(spooldir);
  string mailroot = basedir + "/mail";
  xmkdir(mailroot);
  create_maildir(mailroot + "/user");

  pid_t qman_pid;
  if (START_QMAN) {
    // Start queue manager
    const char *qman[] = {"./mail-qman", spooldir.c_str(), mailroot.c_str(),
                          nthreads_str, nullptr};
    if (posix_spawn(&qman_pid, qman[0], nullptr, nullptr,
                    const_cast<char *const*>(qman), environ) != 0)
      die("posix_spawn %s failed", qman[0]);
    sleep(1);
  }

  // Write message to a file
  int fd = open((basedir + "/msg").c_str(), O_CREAT|O_WRONLY, 0666);
  if (fd < 0)
    edie("open");
  xwrite(fd, message, strlen(message));
  close(fd);

  printf("# --cores=%d --duration=%ds\n", nthreads, duration);

  // Run benchmark
  bar.init(nthreads + 1);

  std::thread timer(timer_thread);

  std::thread *threads = new std::thread[nthreads];
  for (int i = 0; i < nthreads; ++i)
    threads[i] = std::thread(do_mua, i, basedir + "/spool", basedir + "/msg");

  // Wait
  timer.join();
  for (int i = 0; i < nthreads; ++i)
    threads[i].join();

  if (START_QMAN) {
    // Kill qman and wait for it to exit
    const char *enq[] = {"./mail-enqueue", "--exit", spooldir.c_str(), nullptr};
    pid_t enq_pid;
    if (posix_spawn(&enq_pid, enq[0], nullptr, nullptr,
                    const_cast<char *const*>(enq), environ) != 0)
      die("posix_spawn %s failed", enq[0]);
    xwaitpid(enq_pid, "mail-enqueue --exit");
    xwaitpid(qman_pid, "mail-qman");
  }

  // Summarize
  printf("%lu start usec skew\n", start_usec.span());
  printf("%lu stop usec skew\n", stop_usec.span());
  uint64_t usec = stop_usec.mean() - start_usec.mean();
  printf("%f secs\n", (double)usec / 1e6);
  printf("%lu cycles\n", stop_tsc.mean() - start_tsc.mean());

  uint64_t iters = count.sum();
  printf("%lu iters\n", iters);
  if (iters) {
    printf("%lu cycles/iter\n", (stop_tsc.sum() - start_tsc.sum()) / iters);
    printf("%lu iters/sec\n", iters * 1000000 / usec);
  }

  printf("\n");
}
<commit_msg>mailbench: s/iter/message/<commit_after>#include "amd64.h"
#include "distribution.hh"
#include "spinbarrier.hh"
#include "libutil.h"
#include "xsys.h"

#include <fcntl.h>
#include <spawn.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/wait.h>

#include <string>
#include <thread>

// Set to 1 to manage the queue manager's life time from this program.
// Set to 0 if the queue manager is started and stopped outside of
// mailbench.
#define START_QMAN 1

using std::string;

enum { warmup_secs = 1 };
enum { duration = 5 };

const char *message =
  "Received: from incoming.csail.mit.edu (incoming.csail.mit.edu [128.30.2.16])\n"
  "        by metroplex (Cyrus v2.2.13-Debian-2.2.13-14+lenny5) with LMTPA;\n"
  "        Tue, 19 Mar 2013 22:45:50 -0400\n"
  "X-Sieve: CMU Sieve 2.2\n"
  "Received: from mailhub-auth-3.mit.edu ([18.9.21.43])\n"
  "        by incoming.csail.mit.edu with esmtps\n"
  "        (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32)\n"
  "        (Exim 4.72)\n"
  "        (envelope-from <xxxxxxxx@MIT.EDU>)\n"
  "        id 1UI92E-0007D2-7N\n"
  "        for xxxxxxxxx@csail.mit.edu; Tue, 19 Mar 2013 22:45:50 -0400\n"
  "Received: from outgoing.mit.edu (OUTGOING-AUTH-1.MIT.EDU [18.9.28.11])\n"
  "        by mailhub-auth-3.mit.edu (8.13.8/8.9.2) with ESMTP id r2K2jnO5025684\n"
  "        for <xxxxxxxx@mit.edu>; Tue, 19 Mar 2013 22:45:49 -0400\n"
  "Received: from xxxxxxxxx.csail.mit.edu (xxxxxxxxx.csail.mit.edu [18.26.4.91])\n"
  "        (authenticated bits=0)\n"
  "        (User authenticated as xxxxxxxx@ATHENA.MIT.EDU)\n"
  "        by outgoing.mit.edu (8.13.8/8.12.4) with ESMTP id r2K2jmc7032022\n"
  "        (version=TLSv1/SSLv3 cipher=DHE-RSA-AES128-SHA bits=128 verify=NOT)\n"
  "        for <xxxxxxxx@mit.edu>; Tue, 19 Mar 2013 22:45:49 -0400\n"
  "Received: from xxxxxxx by xxxxxxxxx.csail.mit.edu with local (Exim 4.80)\n"
  "        (envelope-from <xxxxxxxx@mit.edu>)\n"
  "        id 1UI92C-0000il-4L\n"
  "        for xxxxxxxx@mit.edu; Tue, 19 Mar 2013 22:45:48 -0400\n"
  "From: Austin Clements <xxxxxxxx@MIT.EDU>\n"
  "To: xxxxxxxx@mit.edu\n"
  "Subject: Test message\n"
  "User-Agent: Notmuch/0.15+6~g7d4cb73 (http://notmuchmail.org) Emacs/23.4.1\n"
  "        (i486-pc-linux-gnu)\n"
  "Date: Tue, 19 Mar 2013 22:45:48 -0400\n"
  "Message-ID: <874ng6vler.fsf@xxxxxxxxx.csail.mit.edu>\n"
  "MIME-Version: 1.0\n"
  "Content-Type: text/plain; charset=us-ascii\n"
  "\n"
  "Hello.\n";

extern char **environ;

static spin_barrier bar;

static concurrent_distribution<uint64_t> start_tsc, stop_tsc;
static concurrent_distribution<uint64_t> start_usec, stop_usec;
static concurrent_distribution<uint64_t> count;

static volatile bool stop __mpalign__;
static volatile bool warmup;
static __padout__ __attribute__((unused));

static void
timer_thread(void)
{
  warmup = true;
  bar.join();
  bar.join();
  sleep(warmup_secs);
  warmup = false;
  sleep(duration);
  stop = true;
}

static void
xwaitpid(int pid, const char *cmd)
{
  int status;
  if (waitpid(pid, &status, 0) < 0)
    edie("waitpid %s failed", cmd);
  if (!WIFEXITED(status) || WEXITSTATUS(status))
    die("status %d from %s", status, cmd);
}

static void
do_mua(int cpu, string spooldir, string msgpath)
{
  const char *argv[] = {"./mail-enqueue", spooldir.c_str(), "user", nullptr};
#if defined(XV6_USER)
  int errno;
#endif
  setaffinity(cpu);

  // Open message file (alternatively, we could use an open spawn
  // action)
  int msgfd = open(msgpath.c_str(), O_RDONLY|O_CLOEXEC|O_ANYFD);
  if (msgfd < 0)
    edie("open %s failed", msgpath.c_str());

  bool mywarmup = true;
  uint64_t mycount = 0;
  while (!stop) {
    if (__builtin_expect(warmup != mywarmup, 0)) {
      mywarmup = warmup;
      mycount = 0;
      start_usec.add(now_usec());
      start_tsc.add(rdtsc());
    }

    if (lseek(msgfd, 0, SEEK_SET) < 0)
      edie("lseek failed");

    pid_t pid;
    posix_spawn_file_actions_t actions;
    if ((errno = posix_spawn_file_actions_init(&actions)))
      edie("posix_spawn_file_actions_init failed");
    if ((errno = posix_spawn_file_actions_adddup2(&actions, msgfd, 0)))
      edie("posix_spawn_file_actions_adddup2 failed");
    if ((errno = posix_spawn(&pid, argv[0], &actions, nullptr,
                             const_cast<char *const*>(argv), environ)))
      edie("posix_spawn failed");
    if ((errno = posix_spawn_file_actions_destroy(&actions)))
      edie("posix_spawn_file_actions_destroy failed");
    xwaitpid(pid, argv[0]);

    ++mycount;
  }

  stop_usec.add(now_usec());
  stop_tsc.add(rdtsc());
  count.add(mycount);
}

static void
xmkdir(const string &d)
{
  if (mkdir(d.c_str(), 0777) < 0)
    edie("failed to mkdir %s", d.c_str());
}

static void
create_spool(const string &base)
{
  xmkdir(base);
  xmkdir(base + "/pid");
  xmkdir(base + "/todo");
  xmkdir(base + "/mess");
}

static void
create_maildir(const string &base)
{
  xmkdir(base);
  xmkdir(base + "/tmp");
  xmkdir(base + "/new");
  xmkdir(base + "/cur");
}

void
usage(const char *argv0)
{
  fprintf(stderr, "Usage: %s basedir nthreads\n", argv0);
  exit(2);
}

int
main(int argc, char **argv)
{
  if (argc != 3)
    usage(argv[0]);

  string basedir(argv[1]);
  const char *nthreads_str = argv[2];
  int nthreads = atoi(nthreads_str);
  if (nthreads <= 0)
    usage(argv[0]);

  // Create spool and inboxes
  // XXX This terminology is wrong.  The spool is where mail
  // ultimately gets delivered to.
  string spooldir = basedir + "/spool";
  if (START_QMAN)
    create_spool(spooldir);
  string mailroot = basedir + "/mail";
  xmkdir(mailroot);
  create_maildir(mailroot + "/user");

  pid_t qman_pid;
  if (START_QMAN) {
    // Start queue manager
    const char *qman[] = {"./mail-qman", spooldir.c_str(), mailroot.c_str(),
                          nthreads_str, nullptr};
    if (posix_spawn(&qman_pid, qman[0], nullptr, nullptr,
                    const_cast<char *const*>(qman), environ) != 0)
      die("posix_spawn %s failed", qman[0]);
    sleep(1);
  }

  // Write message to a file
  int fd = open((basedir + "/msg").c_str(), O_CREAT|O_WRONLY, 0666);
  if (fd < 0)
    edie("open");
  xwrite(fd, message, strlen(message));
  close(fd);

  printf("# --cores=%d --duration=%ds\n", nthreads, duration);

  // Run benchmark
  bar.init(nthreads + 1);

  std::thread timer(timer_thread);

  std::thread *threads = new std::thread[nthreads];
  for (int i = 0; i < nthreads; ++i)
    threads[i] = std::thread(do_mua, i, basedir + "/spool", basedir + "/msg");

  // Wait
  timer.join();
  for (int i = 0; i < nthreads; ++i)
    threads[i].join();

  if (START_QMAN) {
    // Kill qman and wait for it to exit
    const char *enq[] = {"./mail-enqueue", "--exit", spooldir.c_str(), nullptr};
    pid_t enq_pid;
    if (posix_spawn(&enq_pid, enq[0], nullptr, nullptr,
                    const_cast<char *const*>(enq), environ) != 0)
      die("posix_spawn %s failed", enq[0]);
    xwaitpid(enq_pid, "mail-enqueue --exit");
    xwaitpid(qman_pid, "mail-qman");
  }

  // Summarize
  printf("%lu start usec skew\n", start_usec.span());
  printf("%lu stop usec skew\n", stop_usec.span());
  uint64_t usec = stop_usec.mean() - start_usec.mean();
  printf("%f secs\n", (double)usec / 1e6);
  printf("%lu cycles\n", stop_tsc.mean() - start_tsc.mean());

  uint64_t messages = count.sum();
  printf("%lu messages\n", messages);
  if (messages) {
    printf("%lu cycles/message\n",
           (stop_tsc.sum() - start_tsc.sum()) / messages);
    printf("%lu messages/sec\n", messages * 1000000 / usec);
  }

  printf("\n");
}
<|endoftext|>


<commit_before>#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QMessageBox>
#include <iostream>
#include <QCloseEvent>
#include <QColorDialog>
#include <chrono>
#include <thread>
#include "icononbuttonhandler.h"
#include "inputwindow.h"
#include "Video/shapes/shape.h"

using namespace std;
using namespace cv;

/**
 * @brief MainWindow::MainWindow
 * Constructor
 * @param parent a QWidget variable
 */
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow){
    ui->setupUi(this);

    this->selectedProject = nullptr;
    this->selectedVideo = nullptr;

    video_slider = findChild<QSlider*>("videoSlider");
    iconOnButtonHandler = new IconOnButtonHandler();
    iconOnButtonHandler->set_pictures_to_buttons(ui);

    fileHandler = new FileHandler();
    set_shortcuts();

    // Add this object as a listener to videoFrame.
    ui->videoFrame->installEventFilter(this);

    ui->ProjectTree->setContextMenuPolicy(Qt::CustomContextMenu);
    connect(ui->ProjectTree, &QTreeWidget::customContextMenuRequested, this, &MainWindow::prepare_menu);

    mvideo_player = new video_player();
    QObject::connect(mvideo_player, SIGNAL(processedImage(QImage)),
                                  this, SLOT(update_video(QImage)));
    QObject::connect(mvideo_player, SIGNAL(currentFrame(int)),
                                  this, SLOT(set_video_slider_pos(int)));

    //Used for rescaling the source image for video playback
    mvideo_player->set_frame_height(ui->videoFrame->height());
    mvideo_player->set_frame_width(ui->videoFrame->width());
}

/**
 * @brief MainWindow::~MainWindow
 * Destructor
 */

MainWindow::~MainWindow() {

    delete iconOnButtonHandler;
    delete fileHandler;
    delete mvideo_player;
    delete ui;
}

/**
 * @brief MainWindow::set_shortcuts
 * Function to set shortcuts on actions
 */
void MainWindow::set_shortcuts(){
    ui->actionExit->setShortcut(tr("Ctrl+e"));
}

/**
 * @brief MainWindow::set_status_bar
 * @param status text to show in the statusbar
 * @param timer time to show it in the bar in ms, 750ms is standard
 */
void MainWindow::set_status_bar(string status, int timer){
    ui->statusBar->showMessage(QString::fromStdString(status), timer);
}

/**
 * @brief MainWindow::on_fastBackwardButton_clicked
 * The button supposed to play the video slower
 *
 */
void MainWindow::on_fastBackwardButton_clicked(){

}

/**
 * @brief MainWindow::on_playPauseButton_clicked
 * The button supposed to play and pause the video
 */
void MainWindow::on_playPauseButton_clicked() {
    if (mvideo_player->is_paused() || mvideo_player->is_stopped()) {
        set_status_bar("Playing");
        iconOnButtonHandler->set_icon("pause", ui->playPauseButton);//changes the icon on the play button to a pause-icon
        mvideo_player->start();
    } else {
        set_status_bar("Paused");
        iconOnButtonHandler->set_icon("play", ui->playPauseButton);
        mvideo_player->play_pause();
        mvideo_player->wait();
    }
}

/**
 * @brief MainWindow::on_fastForwardButton_clicked
 * The button supposed to play the video faster
 */
void MainWindow::on_fastForwardButton_clicked(){

}

/**
 * @brief MainWindow::on_stopButton_clicked
 * The button supposed to stop the video
 */
void MainWindow::on_stopButton_clicked() {
    set_status_bar("Stopped");
    if (!mvideo_player->is_paused()) {
        iconOnButtonHandler->set_icon("play", ui->playPauseButton);
    }

    mvideo_player->stop_video();
}

/**
 * @brief MainWindow::on_nextFrameButton_clicked
 * The button supposed to play the next frame of the video
 */
void MainWindow::on_nextFrameButton_clicked() {
    if (mvideo_player->is_paused()) {
        set_status_bar("Went forward a frame");
        mvideo_player->next_frame();
    } else {
        set_status_bar("Needs to be paused");
    }
}

/**
 * @brief MainWindow::on_previousFrameButton_clicked
 * The button supposed to play the previous frame of the video
 */
void MainWindow::on_previousFrameButton_clicked() {
    if (mvideo_player->is_paused()) {
        set_status_bar("Went back a frame");
        mvideo_player->previous_frame();
    } else {
        set_status_bar("Needs to be paused");
    }
}

/**
 * @brief MainWindow::update_video
 * Sets the videoFrame pixmap to the current frame from video
 * @param frame
 */
void MainWindow::update_video(QImage frame) {
    ui->videoFrame->setPixmap(QPixmap::fromImage(frame));
}

/**
 * @brief MainWindow::set_video_slider_pos
 * Sets the position of slider in video to position pos
 * @param pos
 */
void MainWindow::set_video_slider_pos(int pos) {
    if (pos <= video_slider->maximum()) {
        video_slider->setSliderPosition(pos);
    }
}

/**
 * @brief MainWindow::resizeEvent
 * Used for rescaling the source image for video playback
 * @param event
 */
void MainWindow::resizeEvent(QResizeEvent* event) {
   QMainWindow::resizeEvent(event);
   mvideo_player->set_frame_height(ui->videoFrame->height());
   mvideo_player->set_frame_width(ui->videoFrame->width());
}

/**
 * @brief MainWindow::on_videoSlider_valueChanged
 * Update the slider to where the mouse is
 * @param newPos current position of the slider
 */
void MainWindow::on_videoSlider_valueChanged(int newPos){
    // Make slider to follow the mouse directly and not by pageStep steps
    Qt::MouseButtons btns = QApplication::mouseButtons();
    QPoint localMousePos = ui->videoSlider->mapFromGlobal(QCursor::pos());
    bool clickOnSlider = (btns & Qt::LeftButton) &&
                         (localMousePos.x() >= 0 && localMousePos.y() >= 0 &&
                          localMousePos.x() < ui->videoSlider->size().width() &&
                          localMousePos.y() < ui->videoSlider->size().height());
    if (clickOnSlider)
    {
        // Attention! The following works only for Horizontal, Left-to-right sliders
        float posRatio = localMousePos.x() / (float )ui->videoSlider->size().width();
        int sliderRange = ui->videoSlider->maximum() - ui->videoSlider->minimum();
        int sliderPosUnderMouse = ui->videoSlider->minimum() + sliderRange * posRatio;
        if (sliderPosUnderMouse != newPos)
        {
            ui->videoSlider->setValue(sliderPosUnderMouse);
            return;
        }
    }
}
/**
 * @brief MainWindow::closeEvent
 * asks if you are sure you want to quit.
 * @param event closing
 */
void MainWindow::closeEvent (QCloseEvent *event){
    set_status_bar("Closing");
    QMessageBox::StandardButton resBtn = QMessageBox::question( this, "Exit",
                                                                tr("Are you sure you want to quit?\n"),
                                                                QMessageBox::No | QMessageBox::Yes,
                                                                QMessageBox::No);

    if (resBtn != QMessageBox::Yes) {
        event->ignore();
    } else {
        event->accept();
    }
}
/**
 * @brief MainWindow::on_actionExit_triggered
 * sends a closeEvent when you press exit
 */
void MainWindow::on_actionExit_triggered(){
    this->close();
}

/**
 * @brief MainWindow::on_bookmarkButton_clicked
 * the button supposed to add a bookmark
 */
void MainWindow::on_bookmarkButton_clicked(){
}

/**
 * @brief MainWindow::on_actionAddProject_triggered
 */
void MainWindow::on_actionAddProject_triggered() {
    ACTION action = ADD_PROJECT;
    inputWindow = new inputwindow(this, action, "Project name:");
    inputWindow->show();
    set_status_bar("Adding project, need name");
}

/**
 * @brief MainWindow::inputSwitchCase
 * @param input the input from the user
 * @param action the action that was triggered earlier
 */
void MainWindow::input_switch_case(ACTION action, QString qInput) {
    std::string input = qInput.toStdString();
    switch(action){
        case ADD_PROJECT: {
            int id = fileHandler->create_project(input)->m_id;
            MyQTreeWidgetItem *projectInTree = new MyQTreeWidgetItem(TYPE::PROJECT, qInput, id);
            projectInTree->setText(0, qInput);
            selectedProject = projectInTree;
            ui->ProjectTree->addTopLevelItem(projectInTree);
            set_status_bar("Project " + input + " created.");
            delete inputWindow;
            break;
        }
        case CANCEL: {
            set_status_bar("Cancel");
            break;
        }
        case ADD_VIDEO: {
            fileHandler->add_video(fileHandler->get_project(selectedProject->id), input);
            MyQTreeWidgetItem *videoInTree = new MyQTreeWidgetItem(TYPE::VIDEO, qInput);
            videoInTree->setText(0, qInput);
            selectedProject->addChild(videoInTree);
            set_status_bar("Video " + input + " added.");
            break;
        }
        default:
            break;

    }
}
/**
 * @brief MainWindow::on_ProjectTree_itemClicked
 * @param item the item in the projectTree that was clicked
 * @param column the column in the tree
 */
void MainWindow::on_ProjectTree_itemClicked(QTreeWidgetItem *item, int column) {
    MyQTreeWidgetItem *newitem = (MyQTreeWidgetItem*)item;
    std::cout << newitem->id << std::endl;
}

 /** @brief MainWindow::on_actionShow_hide_overview_triggered
 * Toggles the showing/hiding of the overlay.
 * Invoked by menu item.
 */
void MainWindow::on_actionShow_hide_overview_triggered() {
    mvideo_player->toggle_overlay();
    if (mvideo_player->is_showing_overlay()) {
        set_status_bar("Overlay: On.");
    } else {
        set_status_bar("Overlay: Off.");
    }
}

/**
 * @brief MainWindow::on_actionColour_triggered
 * Selects a colour for the overlay drawing tool.
 */
void MainWindow::on_actionColour_triggered() {
    QColor col = QColorDialog::getColor();
    mvideo_player->set_overlay_colour(col);
    string msg = "Color: ";
    msg.append(col.name().toStdString());
    set_status_bar(msg);
}

/**
 * @brief MainWindow::on_actionRectangle_triggered
 * Selects the rectangle shape for the overlay drawing tool.
 */
void MainWindow::on_actionRectangle_triggered() {
    mvideo_player->set_overlay_tool(RECTANGLE);
    set_status_bar("Tool: rectangle.");
}

/**
 * @brief MainWindow::on_actionCircle_triggered
 * Selects the circle shape for the overlay drawing tool.
 */
void MainWindow::on_actionCircle_triggered() {
    mvideo_player->set_overlay_tool(CIRCLE);
    set_status_bar("Tool: circle.");
}

/**
 * @brief MainWindow::on_actionLine_triggered
 * Selects the line shape for the overlay drawing tool.
 */
void MainWindow::on_actionLine_triggered() {
    mvideo_player->set_overlay_tool(LINE);
    set_status_bar("Tool: line.");
}

/**
 * @brief MainWindow::on_actionArrow_triggered
 * Selects the arrow shape for the overlay drawing tool.
 */
void MainWindow::on_actionArrow_triggered() {
    mvideo_player->set_overlay_tool(ARROW);
    set_status_bar("Tool: arrow.");
}

/**
 * @brief MainWindow::on_actionPen_triggered
 * Selects the pen for the overlay drawing tool.
 */
void MainWindow::on_actionPen_triggered() {
    mvideo_player->set_overlay_tool(PEN);
    set_status_bar("Tool: pen.");
}

/**
 * @brief MainWindow::eventFilter
 * Listener function for all eventFilters MainWindow has installed.
 * @param obj the object invoking the event
 * @param event the invooked event
 * @return Returns true if the event matched any of the overlay's
 *         functionality, else false.
 *         (Returning false means that the event is sent to the
 *          target object instead, but not if true is returned.)
 */
bool MainWindow::eventFilter(QObject *obj, QEvent *event) {
    // Check who invoked the event.
    if (qobject_cast<QLabel*>(obj)==ui->videoFrame) {
        // Cast to a mouse event to get the mouse position.
        QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
        QPoint pos = mouseEvent->pos();
        // Check what kind of event.
        if (event->type() == QEvent::MouseButtonPress) {
            mvideo_player->video_mouse_pressed(pos);
            return true;
        } else if (event->type() == QEvent::MouseButtonRelease) {
            mvideo_player->video_mouse_released(pos);
            return true;
        } else if (event->type() == QEvent::MouseMove) {
            mvideo_player->video_mouse_moved(pos);
            return true;
        }
    }
    return false;
}
/**
 * @brief MainWindow::prepare_menu
 * @param pos
 * Creates context menu on right-click in tree view
 */
void MainWindow::prepare_menu(const QPoint & pos) {
    QTreeWidget *tree = ui->ProjectTree;

    MyQTreeWidgetItem *item = (MyQTreeWidgetItem*)tree->itemAt( pos );

    QMenu menu(this);

    if(item == nullptr) {

    } else if(item->type == TYPE::PROJECT) {
        selectedProject = item;
        QAction *addVideo = new QAction(QIcon(""), tr("&Add video"), this);
        addVideo->setStatusTip(tr("Add video"));
        menu.addAction(addVideo);
        connect(addVideo, SIGNAL(triggered()), this, SLOT(add_video()));
    } else if(item->type == TYPE::VIDEO) {
        selectedVideo = item;
        QAction *loadVideo = new QAction(QIcon(""), tr("&Play video"), this);
        loadVideo->setStatusTip(tr("Play video"));
        menu.addAction(loadVideo);
        connect(loadVideo, SIGNAL(triggered()), this, SLOT(play_video()));
    }

    QPoint pt(pos);
    menu.exec( tree->mapToGlobal(pos) );
}
/**
 * @brief MainWindow::add_video
 * Prompts user with file browser to add video
 * to selected project
 */
void MainWindow::add_video() {
    QString dir = QFileDialog::getOpenFileName(this, tr("Choose video"),WORKSPACE,tr("*.avi;;*.mkv;;*.mov;;*.mp4"));
    input_switch_case(ACTION::ADD_VIDEO, dir);
}
/**
 * @brief MainWindow::play_video
 *  Loads selected video, flips playbutton to pause
 *  plays video from beginning
 *
 */
void MainWindow::play_video() {
    mvideo_player->load_video(selectedVideo->name.toStdString());
    iconOnButtonHandler->set_icon("pause", ui->playPauseButton);
    video_slider->setMaximum(mvideo_player->get_num_frames());
    mvideo_player->set_playback_frame(0);
}
/**
 * @todo To be implemented
 * @brief MainWindow::set_selected_project
 * @param newSelectedProject
 */
void MainWindow::set_selected_project(MyQTreeWidgetItem *newSelectedProject){
    /*if(selectedProject) {
        std::cout << "1" << std::endl;
        selectedProject = newSelectedProject;
        std::cout << "2" << std::endl;
        QString string = selectedProject->text(0);
        std::cout << "3" << std::endl;
        string.append(" <--");
        std::cout << "4" << std::endl;
        selectedProject->setText(0, string);
        std::cout << "5" << std::endl;
    } else if (selectedProject != newSelectedProject) {
        QString string = selectedProject->text(0);
        string.chop(4);
        selectedProject->setText(0, string);
        selectedProject = newSelectedProject;
        string = selectedProject->text(0);
        string.append(" <--");
        selectedProject->setText(0, string);
    }*/
    selectedProject = newSelectedProject;
}
/**
 * @brief MainWindow::on_actionSave_triggered
 * saves project which is selected in tree view,
 * checks if there is one
 */
void MainWindow::on_actionSave_triggered()
{
    if(selectedProject != nullptr) {
        this->fileHandler->save_project(this->selectedProject->id);
        std::string text = "Saved project " + this->selectedProject->name.toStdString();
        set_status_bar(text);
    } else {
        set_status_bar("Nothing to save");
    }
}
<commit_msg>Fixed outcommented code<commit_after>#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QMessageBox>
#include <iostream>
#include <QCloseEvent>
#include <QColorDialog>
#include <chrono>
#include <thread>
#include "icononbuttonhandler.h"
#include "inputwindow.h"
#include "Video/shapes/shape.h"

using namespace std;
using namespace cv;

/**
 * @brief MainWindow::MainWindow
 * Constructor
 * @param parent a QWidget variable
 */
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow){
    ui->setupUi(this);

    this->selectedProject = nullptr;
    this->selectedVideo = nullptr;

    video_slider = findChild<QSlider*>("videoSlider");
    iconOnButtonHandler = new IconOnButtonHandler();
    iconOnButtonHandler->set_pictures_to_buttons(ui);

    fileHandler = new FileHandler();
    set_shortcuts();

    // Add this object as a listener to videoFrame.
    ui->videoFrame->installEventFilter(this);

    ui->ProjectTree->setContextMenuPolicy(Qt::CustomContextMenu);
    connect(ui->ProjectTree, &QTreeWidget::customContextMenuRequested, this, &MainWindow::prepare_menu);

    mvideo_player = new video_player();
    QObject::connect(mvideo_player, SIGNAL(processedImage(QImage)),
                                  this, SLOT(update_video(QImage)));
    QObject::connect(mvideo_player, SIGNAL(currentFrame(int)),
                                  this, SLOT(set_video_slider_pos(int)));

    //Used for rescaling the source image for video playback
    mvideo_player->set_frame_height(ui->videoFrame->height());
    mvideo_player->set_frame_width(ui->videoFrame->width());
}

/**
 * @brief MainWindow::~MainWindow
 * Destructor
 */

MainWindow::~MainWindow() {

    delete iconOnButtonHandler;
    delete fileHandler;
    delete mvideo_player;
    delete ui;
}

/**
 * @brief MainWindow::set_shortcuts
 * Function to set shortcuts on actions
 */
void MainWindow::set_shortcuts(){
    ui->actionExit->setShortcut(tr("Ctrl+e"));
}

/**
 * @brief MainWindow::set_status_bar
 * @param status text to show in the statusbar
 * @param timer time to show it in the bar in ms, 750ms is standard
 */
void MainWindow::set_status_bar(string status, int timer){
    ui->statusBar->showMessage(QString::fromStdString(status), timer);
}

/**
 * @brief MainWindow::on_fastBackwardButton_clicked
 * The button supposed to play the video slower
 *
 */
void MainWindow::on_fastBackwardButton_clicked(){

}

/**
 * @brief MainWindow::on_playPauseButton_clicked
 * The button supposed to play and pause the video
 */
void MainWindow::on_playPauseButton_clicked() {
    if (mvideo_player->is_paused() || mvideo_player->is_stopped()) {
        set_status_bar("Playing");
        iconOnButtonHandler->set_icon("pause", ui->playPauseButton);//changes the icon on the play button to a pause-icon
        mvideo_player->start();
    } else {
        set_status_bar("Paused");
        iconOnButtonHandler->set_icon("play", ui->playPauseButton);
        mvideo_player->play_pause();
        mvideo_player->wait();
    }
}

/**
 * @brief MainWindow::on_fastForwardButton_clicked
 * The button supposed to play the video faster
 */
void MainWindow::on_fastForwardButton_clicked(){

}

/**
 * @brief MainWindow::on_stopButton_clicked
 * The button supposed to stop the video
 */
void MainWindow::on_stopButton_clicked() {
    set_status_bar("Stopped");
    if (!mvideo_player->is_paused()) {
        iconOnButtonHandler->set_icon("play", ui->playPauseButton);
    }

    mvideo_player->stop_video();
}

/**
 * @brief MainWindow::on_nextFrameButton_clicked
 * The button supposed to play the next frame of the video
 */
void MainWindow::on_nextFrameButton_clicked() {
    if (mvideo_player->is_paused()) {
        set_status_bar("Went forward a frame");
        mvideo_player->next_frame();
    } else {
        set_status_bar("Needs to be paused");
    }
}

/**
 * @brief MainWindow::on_previousFrameButton_clicked
 * The button supposed to play the previous frame of the video
 */
void MainWindow::on_previousFrameButton_clicked() {
    if (mvideo_player->is_paused()) {
        set_status_bar("Went back a frame");
        mvideo_player->previous_frame();
    } else {
        set_status_bar("Needs to be paused");
    }
}

/**
 * @brief MainWindow::update_video
 * Sets the videoFrame pixmap to the current frame from video
 * @param frame
 */
void MainWindow::update_video(QImage frame) {
    ui->videoFrame->setPixmap(QPixmap::fromImage(frame));
}

/**
 * @brief MainWindow::set_video_slider_pos
 * Sets the position of slider in video to position pos
 * @param pos
 */
void MainWindow::set_video_slider_pos(int pos) {
    if (pos <= video_slider->maximum()) {
        video_slider->setSliderPosition(pos);
    }
}

/**
 * @brief MainWindow::resizeEvent
 * Used for rescaling the source image for video playback
 * @param event
 */
void MainWindow::resizeEvent(QResizeEvent* event) {
   QMainWindow::resizeEvent(event);
   mvideo_player->set_frame_height(ui->videoFrame->height());
   mvideo_player->set_frame_width(ui->videoFrame->width());
}

/**
 * @brief MainWindow::on_videoSlider_valueChanged
 * Update the slider to where the mouse is
 * @param newPos current position of the slider
 */
void MainWindow::on_videoSlider_valueChanged(int newPos){
    // Make slider to follow the mouse directly and not by pageStep steps
    Qt::MouseButtons btns = QApplication::mouseButtons();
    QPoint localMousePos = ui->videoSlider->mapFromGlobal(QCursor::pos());
    bool clickOnSlider = (btns & Qt::LeftButton) &&
                         (localMousePos.x() >= 0 && localMousePos.y() >= 0 &&
                          localMousePos.x() < ui->videoSlider->size().width() &&
                          localMousePos.y() < ui->videoSlider->size().height());
    if (clickOnSlider)
    {
        // Attention! The following works only for Horizontal, Left-to-right sliders
        float posRatio = localMousePos.x() / (float )ui->videoSlider->size().width();
        int sliderRange = ui->videoSlider->maximum() - ui->videoSlider->minimum();
        int sliderPosUnderMouse = ui->videoSlider->minimum() + sliderRange * posRatio;
        if (sliderPosUnderMouse != newPos)
        {
            ui->videoSlider->setValue(sliderPosUnderMouse);
            return;
        }
    }
}
/**
 * @brief MainWindow::closeEvent
 * asks if you are sure you want to quit.
 * @param event closing
 */
void MainWindow::closeEvent (QCloseEvent *event){
    set_status_bar("Closing");
    QMessageBox::StandardButton resBtn = QMessageBox::question( this, "Exit",
                                                                tr("Are you sure you want to quit?\n"),
                                                                QMessageBox::No | QMessageBox::Yes,
                                                                QMessageBox::No);

    if (resBtn != QMessageBox::Yes) {
        event->ignore();
    } else {
        event->accept();
    }
}
/**
 * @brief MainWindow::on_actionExit_triggered
 * sends a closeEvent when you press exit
 */
void MainWindow::on_actionExit_triggered(){
    this->close();
}

/**
 * @brief MainWindow::on_bookmarkButton_clicked
 * the button supposed to add a bookmark
 */
void MainWindow::on_bookmarkButton_clicked(){
}

/**
 * @brief MainWindow::on_actionAddProject_triggered
 */
void MainWindow::on_actionAddProject_triggered() {
    ACTION action = ADD_PROJECT;
    inputWindow = new inputwindow(this, action, "Project name:");
    inputWindow->show();
    set_status_bar("Adding project, need name");
}

/**
 * @brief MainWindow::inputSwitchCase
 * @param input the input from the user
 * @param action the action that was triggered earlier
 */
void MainWindow::input_switch_case(ACTION action, QString qInput) {
    std::string input = qInput.toStdString();
    switch(action){
        case ADD_PROJECT: {
            int id = fileHandler->create_project(input)->m_id;
            MyQTreeWidgetItem *projectInTree = new MyQTreeWidgetItem(TYPE::PROJECT, qInput, id);
            projectInTree->setText(0, qInput);
            selectedProject = projectInTree;
            ui->ProjectTree->addTopLevelItem(projectInTree);
            set_status_bar("Project " + input + " created.");
            delete inputWindow;
            break;
        }
        case CANCEL: {
            set_status_bar("Cancel");
            break;
        }
        case ADD_VIDEO: {
            fileHandler->add_video(fileHandler->get_project(selectedProject->id), input);
            MyQTreeWidgetItem *videoInTree = new MyQTreeWidgetItem(TYPE::VIDEO, qInput);
            videoInTree->setText(0, qInput);
            selectedProject->addChild(videoInTree);
            set_status_bar("Video " + input + " added.");
            break;
        }
        default:
            break;

    }
}
/**
 * @brief MainWindow::on_ProjectTree_itemClicked
 * @param item the item in the projectTree that was clicked
 * @param column the column in the tree
 */
void MainWindow::on_ProjectTree_itemClicked(QTreeWidgetItem *item, int column) {
    MyQTreeWidgetItem *newitem = (MyQTreeWidgetItem*)item;
    std::cout << newitem->id << std::endl;
}

 /** @brief MainWindow::on_actionShow_hide_overview_triggered
 * Toggles the showing/hiding of the overlay.
 * Invoked by menu item.
 */
void MainWindow::on_actionShow_hide_overview_triggered() {
    mvideo_player->toggle_overlay();
    if (mvideo_player->is_showing_overlay()) {
        set_status_bar("Overlay: On.");
    } else {
        set_status_bar("Overlay: Off.");
    }
}

/**
 * @brief MainWindow::on_actionColour_triggered
 * Selects a colour for the overlay drawing tool.
 */
void MainWindow::on_actionColour_triggered() {
    QColor col = QColorDialog::getColor();
    mvideo_player->set_overlay_colour(col);
    string msg = "Color: ";
    msg.append(col.name().toStdString());
    set_status_bar(msg);
}

/**
 * @brief MainWindow::on_actionRectangle_triggered
 * Selects the rectangle shape for the overlay drawing tool.
 */
void MainWindow::on_actionRectangle_triggered() {
    mvideo_player->set_overlay_tool(RECTANGLE);
    set_status_bar("Tool: rectangle.");
}

/**
 * @brief MainWindow::on_actionCircle_triggered
 * Selects the circle shape for the overlay drawing tool.
 */
void MainWindow::on_actionCircle_triggered() {
    mvideo_player->set_overlay_tool(CIRCLE);
    set_status_bar("Tool: circle.");
}

/**
 * @brief MainWindow::on_actionLine_triggered
 * Selects the line shape for the overlay drawing tool.
 */
void MainWindow::on_actionLine_triggered() {
    mvideo_player->set_overlay_tool(LINE);
    set_status_bar("Tool: line.");
}

/**
 * @brief MainWindow::on_actionArrow_triggered
 * Selects the arrow shape for the overlay drawing tool.
 */
void MainWindow::on_actionArrow_triggered() {
    mvideo_player->set_overlay_tool(ARROW);
    set_status_bar("Tool: arrow.");
}

/**
 * @brief MainWindow::on_actionPen_triggered
 * Selects the pen for the overlay drawing tool.
 */
void MainWindow::on_actionPen_triggered() {
    mvideo_player->set_overlay_tool(PEN);
    set_status_bar("Tool: pen.");
}

/**
 * @brief MainWindow::eventFilter
 * Listener function for all eventFilters MainWindow has installed.
 * @param obj the object invoking the event
 * @param event the invooked event
 * @return Returns true if the event matched any of the overlay's
 *         functionality, else false.
 *         (Returning false means that the event is sent to the
 *          target object instead, but not if true is returned.)
 */
bool MainWindow::eventFilter(QObject *obj, QEvent *event) {
    // Check who invoked the event.
    if (qobject_cast<QLabel*>(obj)==ui->videoFrame) {
        // Cast to a mouse event to get the mouse position.
        QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
        QPoint pos = mouseEvent->pos();
        // Check what kind of event.
        if (event->type() == QEvent::MouseButtonPress) {
            mvideo_player->video_mouse_pressed(pos);
            return true;
        } else if (event->type() == QEvent::MouseButtonRelease) {
            mvideo_player->video_mouse_released(pos);
            return true;
        } else if (event->type() == QEvent::MouseMove) {
            mvideo_player->video_mouse_moved(pos);
            return true;
        }
    }
    return false;
}
/**
 * @brief MainWindow::prepare_menu
 * @param pos
 * Creates context menu on right-click in tree view
 */
void MainWindow::prepare_menu(const QPoint & pos) {
    QTreeWidget *tree = ui->ProjectTree;

    MyQTreeWidgetItem *item = (MyQTreeWidgetItem*)tree->itemAt( pos );

    QMenu menu(this);

    if(item == nullptr) {

    } else if(item->type == TYPE::PROJECT) {
        selectedProject = item;
        QAction *addVideo = new QAction(QIcon(""), tr("&Add video"), this);
        addVideo->setStatusTip(tr("Add video"));
        menu.addAction(addVideo);
        connect(addVideo, SIGNAL(triggered()), this, SLOT(add_video()));
    } else if(item->type == TYPE::VIDEO) {
        selectedVideo = item;
        QAction *loadVideo = new QAction(QIcon(""), tr("&Play video"), this);
        loadVideo->setStatusTip(tr("Play video"));
        menu.addAction(loadVideo);
        connect(loadVideo, SIGNAL(triggered()), this, SLOT(play_video()));
    }

    QPoint pt(pos);
    menu.exec( tree->mapToGlobal(pos) );
}
/**
 * @brief MainWindow::add_video
 * Prompts user with file browser to add video
 * to selected project
 */
void MainWindow::add_video() {
    QString dir = QFileDialog::getOpenFileName(this, tr("Choose video"),WORKSPACE,tr("*.avi;;*.mkv;;*.mov;;*.mp4"));
    input_switch_case(ACTION::ADD_VIDEO, dir);
}
/**
 * @brief MainWindow::play_video
 *  Loads selected video, flips playbutton to pause
 *  plays video from beginning
 *
 */
void MainWindow::play_video() {
    mvideo_player->load_video(selectedVideo->name.toStdString());
    iconOnButtonHandler->set_icon("pause", ui->playPauseButton);
    video_slider->setMaximum(mvideo_player->get_num_frames());
    mvideo_player->set_playback_frame(0);
}
/**
 * @brief MainWindow::set_selected_project
 * @param newSelectedProject
 */
void MainWindow::set_selected_project(MyQTreeWidgetItem *newSelectedProject){
    if(selectedProject) {
        selectedProject = newSelectedProject;
        QString string = selectedProject->text(0);
        string.append(" <--");
        selectedProject->setText(0, string);
    } else if (selectedProject != newSelectedProject) {
        QString string = selectedProject->text(0);
        string.chop(4);
        selectedProject->setText(0, string);
        selectedProject = newSelectedProject;
        string = selectedProject->text(0);
        string.append(" <--");
        selectedProject->setText(0, string);
    }
}
/**
 * @brief MainWindow::on_actionSave_triggered
 * saves project which is selected in tree view,
 * checks if there is one
 */
void MainWindow::on_actionSave_triggered()
{
    if(selectedProject != nullptr) {
        this->fileHandler->save_project(this->selectedProject->id);
        std::string text = "Saved project " + this->selectedProject->name.toStdString();
        set_status_bar(text);
    } else {
        set_status_bar("Nothing to save");
    }
}
<|endoftext|>