<commit_before>/*
 * This file is a part of Xpiks - cross platform application for
 * keywording and uploading images for microstocks
 * Copyright (C) 2014-2016 Taras Kushnir <kushnirTV@gmail.com>
 *
 * Xpiks is distributed under the GNU General Public License, version 3.0
 *
 * 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 <http://www.gnu.org/licenses/>.
 */

#include "spellcheckerservice.h"
#include "../Models/artworkmetadata.h"
#include "spellcheckworker.h"
#include "spellcheckitem.h"
#include "../Common/defines.h"
#include "../Common/flags.h"

namespace SpellCheck {
    SpellCheckerService::SpellCheckerService():
        m_SpellCheckWorker(NULL),
        m_RestartRequired(false)
    {
    }

    SpellCheckerService::~SpellCheckerService() {
        if (m_SpellCheckWorker != nullptr) {

        }
    }

    void SpellCheckerService::startService() {
        if (m_SpellCheckWorker != NULL) {
            LOG_WARNING << "Attempt to start running worker";
            return;
        }

        m_SpellCheckWorker = new SpellCheckWorker();

        QThread *thread = new QThread();
        m_SpellCheckWorker->moveToThread(thread);

        QObject::connect(thread, SIGNAL(started()), m_SpellCheckWorker, SLOT(process()));
        QObject::connect(m_SpellCheckWorker, SIGNAL(stopped()), thread, SLOT(quit()));

        QObject::connect(m_SpellCheckWorker, SIGNAL(stopped()), m_SpellCheckWorker, SLOT(deleteLater()));
        QObject::connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));

        QObject::connect(this, SIGNAL(cancelSpellChecking()),
                         m_SpellCheckWorker, SLOT(cancel()));

        QObject::connect(m_SpellCheckWorker, SIGNAL(queueIsEmpty()),
                         this, SIGNAL(spellCheckQueueIsEmpty()));

        QObject::connect(m_SpellCheckWorker, SIGNAL(stopped()),
                         this, SLOT(workerFinished()));

        QObject::connect(m_SpellCheckWorker, SIGNAL(destroyed(QObject*)),
                         this, SLOT(workerDestroyed(QObject*)));

        LOG_DEBUG << "starting thread...";
        thread->start();

        emit serviceAvailable(m_RestartRequired);
    }

    void SpellCheckerService::stopService() {
        LOG_DEBUG << "#";
        if (m_SpellCheckWorker != NULL) {
            m_SpellCheckWorker->stopWorking();
        } else {
            LOG_WARNING << "SpellCheckWorker is NULL";
        }
    }

    bool SpellCheckerService::isBusy() const {
        bool isBusy = (m_SpellCheckWorker != NULL) && (m_SpellCheckWorker->hasPendingJobs());
        return isBusy;
    }

    void SpellCheckerService::submitItem(Common::BasicKeywordsModel *itemToCheck) {
        this->submitItem(itemToCheck, Common::SpellCheckAll);
    }

    void SpellCheckerService::submitItem(Common::BasicKeywordsModel *itemToCheck, int flags) {
        if (m_SpellCheckWorker == NULL) { return; }

        LOG_INFO << "flags:" << flags;

        std::shared_ptr<SpellCheckItem> item(new SpellCheckItem(itemToCheck, flags),
                                             [](SpellCheckItem *spi) { spi->deleteLater(); });
        itemToCheck->connectSignals(item.get());
        m_SpellCheckWorker->submitItem(item);
    }

    void SpellCheckerService::submitItems(const QVector<Common::BasicKeywordsModel *> &itemsToCheck) {
        if (m_SpellCheckWorker == NULL) { return; }

        std::vector<std::shared_ptr<ISpellCheckItem> > items;
        int length = itemsToCheck.length();

        items.reserve(length);
        auto deleter = [](SpellCheckItem *item) { item->deleteLater(); };

        for (int i = 0; i < length; ++i) {
            Common::BasicKeywordsModel *itemToCheck = itemsToCheck.at(i);
            std::shared_ptr<SpellCheckItem> item(new SpellCheckItem(itemToCheck, Common::SpellCheckAll),
                                                 deleter);
            itemToCheck->connectSignals(item.get());
            items.emplace_back(std::dynamic_pointer_cast<ISpellCheckItem>(item));
        }

        LOG_INFO << length << "item(s)";

        m_SpellCheckWorker->submitItems(items);
        m_SpellCheckWorker->submitItem(std::shared_ptr<ISpellCheckItem>(new SpellCheckSeparatorItem()));
    }

    void SpellCheckerService::submitKeyword(Common::BasicKeywordsModel *itemToCheck, int keywordIndex) {
        if (m_SpellCheckWorker == NULL) { return; }

        std::shared_ptr<SpellCheckItem> item(new SpellCheckItem(itemToCheck, Common::SpellCheckKeywords, keywordIndex),
                                             [](SpellCheckItem *spi) { spi->deleteLater(); });
        itemToCheck->connectSignals(item.get());
        m_SpellCheckWorker->submitItem(item);
    }

    QStringList SpellCheckerService::suggestCorrections(const QString &word) const {
        if (m_SpellCheckWorker == NULL) { return QStringList(); }

        return m_SpellCheckWorker->retrieveCorrections(word);
    }

    void SpellCheckerService::restartWorker() {
        m_RestartRequired = true;
        stopService();
    }

    void SpellCheckerService::cancelCurrentBatch() {
        LOG_INFO << "#";

        if (m_SpellCheckWorker == NULL) { return; }

        m_SpellCheckWorker->cancelCurrentBatch();
    }

    bool SpellCheckerService::hasAnyPending() {
        bool hasPending = false;

        if (m_SpellCheckWorker != NULL) {
            hasPending = m_SpellCheckWorker->hasPendingJobs();
        }

        return hasPending;
    }

    void SpellCheckerService::workerFinished() {
        LOG_INFO << "#";
    }

    void SpellCheckerService::workerDestroyed(QObject *object) {
        Q_UNUSED(object);
        LOG_DEBUG << "#";
        m_SpellCheckWorker = NULL;

        if (m_RestartRequired) {
            LOG_INFO << "Restarting worker...";
            startService();
            m_RestartRequired = false;
        }
    }
}
<commit_msg>Priority for the last keyword spellchecking<commit_after>/*
 * This file is a part of Xpiks - cross platform application for
 * keywording and uploading images for microstocks
 * Copyright (C) 2014-2016 Taras Kushnir <kushnirTV@gmail.com>
 *
 * Xpiks is distributed under the GNU General Public License, version 3.0
 *
 * 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 <http://www.gnu.org/licenses/>.
 */

#include "spellcheckerservice.h"
#include "../Models/artworkmetadata.h"
#include "spellcheckworker.h"
#include "spellcheckitem.h"
#include "../Common/defines.h"
#include "../Common/flags.h"

namespace SpellCheck {
    SpellCheckerService::SpellCheckerService():
        m_SpellCheckWorker(NULL),
        m_RestartRequired(false)
    {
    }

    SpellCheckerService::~SpellCheckerService() {
        if (m_SpellCheckWorker != nullptr) {

        }
    }

    void SpellCheckerService::startService() {
        if (m_SpellCheckWorker != NULL) {
            LOG_WARNING << "Attempt to start running worker";
            return;
        }

        m_SpellCheckWorker = new SpellCheckWorker();

        QThread *thread = new QThread();
        m_SpellCheckWorker->moveToThread(thread);

        QObject::connect(thread, SIGNAL(started()), m_SpellCheckWorker, SLOT(process()));
        QObject::connect(m_SpellCheckWorker, SIGNAL(stopped()), thread, SLOT(quit()));

        QObject::connect(m_SpellCheckWorker, SIGNAL(stopped()), m_SpellCheckWorker, SLOT(deleteLater()));
        QObject::connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));

        QObject::connect(this, SIGNAL(cancelSpellChecking()),
                         m_SpellCheckWorker, SLOT(cancel()));

        QObject::connect(m_SpellCheckWorker, SIGNAL(queueIsEmpty()),
                         this, SIGNAL(spellCheckQueueIsEmpty()));

        QObject::connect(m_SpellCheckWorker, SIGNAL(stopped()),
                         this, SLOT(workerFinished()));

        QObject::connect(m_SpellCheckWorker, SIGNAL(destroyed(QObject*)),
                         this, SLOT(workerDestroyed(QObject*)));

        LOG_DEBUG << "starting thread...";
        thread->start();

        emit serviceAvailable(m_RestartRequired);
    }

    void SpellCheckerService::stopService() {
        LOG_DEBUG << "#";
        if (m_SpellCheckWorker != NULL) {
            m_SpellCheckWorker->stopWorking();
        } else {
            LOG_WARNING << "SpellCheckWorker is NULL";
        }
    }

    bool SpellCheckerService::isBusy() const {
        bool isBusy = (m_SpellCheckWorker != NULL) && (m_SpellCheckWorker->hasPendingJobs());
        return isBusy;
    }

    void SpellCheckerService::submitItem(Common::BasicKeywordsModel *itemToCheck) {
        this->submitItem(itemToCheck, Common::SpellCheckAll);
    }

    void SpellCheckerService::submitItem(Common::BasicKeywordsModel *itemToCheck, int flags) {
        if (m_SpellCheckWorker == NULL) { return; }

        LOG_INFO << "flags:" << flags;

        std::shared_ptr<SpellCheckItem> item(new SpellCheckItem(itemToCheck, flags),
                                             [](SpellCheckItem *spi) { spi->deleteLater(); });
        itemToCheck->connectSignals(item.get());
        m_SpellCheckWorker->submitItem(item);
    }

    void SpellCheckerService::submitItems(const QVector<Common::BasicKeywordsModel *> &itemsToCheck) {
        if (m_SpellCheckWorker == NULL) { return; }

        std::vector<std::shared_ptr<ISpellCheckItem> > items;
        int length = itemsToCheck.length();

        items.reserve(length);
        auto deleter = [](SpellCheckItem *item) { item->deleteLater(); };

        for (int i = 0; i < length; ++i) {
            Common::BasicKeywordsModel *itemToCheck = itemsToCheck.at(i);
            std::shared_ptr<SpellCheckItem> item(new SpellCheckItem(itemToCheck, Common::SpellCheckAll),
                                                 deleter);
            itemToCheck->connectSignals(item.get());
            items.emplace_back(std::dynamic_pointer_cast<ISpellCheckItem>(item));
        }

        LOG_INFO << length << "item(s)";

        m_SpellCheckWorker->submitItems(items);
        m_SpellCheckWorker->submitItem(std::shared_ptr<ISpellCheckItem>(new SpellCheckSeparatorItem()));
    }

    void SpellCheckerService::submitKeyword(Common::BasicKeywordsModel *itemToCheck, int keywordIndex) {
        if (m_SpellCheckWorker == NULL) { return; }

        std::shared_ptr<SpellCheckItem> item(new SpellCheckItem(itemToCheck, Common::SpellCheckKeywords, keywordIndex),
                                             [](SpellCheckItem *spi) { spi->deleteLater(); });
        itemToCheck->connectSignals(item.get());
        m_SpellCheckWorker->submitFirst(item);
    }

    QStringList SpellCheckerService::suggestCorrections(const QString &word) const {
        if (m_SpellCheckWorker == NULL) { return QStringList(); }

        return m_SpellCheckWorker->retrieveCorrections(word);
    }

    void SpellCheckerService::restartWorker() {
        m_RestartRequired = true;
        stopService();
    }

    void SpellCheckerService::cancelCurrentBatch() {
        LOG_INFO << "#";

        if (m_SpellCheckWorker == NULL) { return; }

        m_SpellCheckWorker->cancelCurrentBatch();
    }

    bool SpellCheckerService::hasAnyPending() {
        bool hasPending = false;

        if (m_SpellCheckWorker != NULL) {
            hasPending = m_SpellCheckWorker->hasPendingJobs();
        }

        return hasPending;
    }

    void SpellCheckerService::workerFinished() {
        LOG_INFO << "#";
    }

    void SpellCheckerService::workerDestroyed(QObject *object) {
        Q_UNUSED(object);
        LOG_DEBUG << "#";
        m_SpellCheckWorker = NULL;

        if (m_RestartRequired) {
            LOG_INFO << "Restarting worker...";
            startService();
            m_RestartRequired = false;
        }
    }
}
<|endoftext|>


<commit_before>//-----------------------------------------------
//
//	This file is part of the Siv3D Engine.
//
//	Copyright (c) 2008-2021 Ryo Suzuki
//	Copyright (c) 2016-2021 OpenSiv3D Project
//
//	Licensed under the MIT License.
//
//-----------------------------------------------

# include <Siv3D/Common.hpp>
# include <Siv3D/EngineLog.hpp>
# include "WebGPUVertex2DBatch.hpp"

namespace s3d
{
	namespace detail
	{
		static size_t CalculateNewArraySize(const size_t current, const size_t target) noexcept
		{
			size_t newArraySize = current * 2;

			while (newArraySize < target)
			{
				newArraySize *= 2;
			}

			return newArraySize;
		}
	}

	WebGPUVertex2DBatch::WebGPUVertex2DBatch()
		: m_vertexArray(InitialVertexArraySize)
		, m_indexArray(InitialIndexArraySize)
		, m_batches(1)
	{

	}

	WebGPUVertex2DBatch::~WebGPUVertex2DBatch()
	{
	}

	bool WebGPUVertex2DBatch::init(const wgpu::Device& device)
	{
		{
			wgpu::BufferDescriptor indexBufferDescripter
			{
				.size = sizeof(Vertex2D::IndexType) * InitialIndexArraySize,
				.usage = wgpu::BufferUsage::Index | wgpu::BufferUsage::CopyDst
			};

			m_indexBuffer = device.CreateBuffer(&indexBufferDescripter);
		}

		{
			wgpu::BufferDescriptor vertexBufferDescripter
			{
				.size = sizeof(Vertex2D) * InitialVertexArraySize,
				.usage = wgpu::BufferUsage::Vertex | wgpu::BufferUsage::CopyDst
			};

			m_vertexBuffer = device.CreateBuffer(&vertexBufferDescripter);
		}

		return true;
	}

	Vertex2DBufferPointer WebGPUVertex2DBatch::requestBuffer(const uint16 vertexSize, const uint32 indexSize, WebGPURenderer2DCommandManager& commandManager)
	{
		// VB
		if (const uint32 vertexArrayWritePosTarget = m_vertexArrayWritePos + vertexSize;
			m_vertexArray.size() < vertexArrayWritePosTarget) SIV3D_UNLIKELY
		{
			if (MaxVertexArraySize < vertexArrayWritePosTarget) SIV3D_UNLIKELY
			{
				return{ nullptr, 0, 0 };
			}

			const size_t newVertexArraySize = detail::CalculateNewArraySize(m_vertexArray.size(), vertexArrayWritePosTarget);
			LOG_TRACE(U"ℹ Resized WebGPUVertex2DBatch::m_vertexArray (size: {} -> {})"_fmt(m_vertexArray.size(), newVertexArraySize));
			m_vertexArray.resize(newVertexArraySize);
		}

		// IB
		if (const uint32 indexArrayWritePosTarget = m_indexArrayWritePos + indexSize;
			m_indexArray.size() < indexArrayWritePosTarget) SIV3D_UNLIKELY
		{
			if (MaxIndexArraySize < indexArrayWritePosTarget) SIV3D_UNLIKELY
			{
				return{ nullptr, 0, 0 };
			}

			const size_t newIndexArraySize = detail::CalculateNewArraySize(m_indexArray.size(), indexArrayWritePosTarget);
			LOG_TRACE(U"ℹ Resized WebGPUVertex2DBatch::m_indexArray (size: {} -> {})"_fmt(m_indexArray.size(), newIndexArraySize));
			m_indexArray.resize(newIndexArraySize);
		}

		if (const auto& lastbatch = m_batches.back();
			(VertexBufferSize < (lastbatch.vertexPos + vertexSize) || IndexBufferSize < (lastbatch.indexPos + indexSize)))
		{
			commandManager.pushUpdateBuffers(static_cast<uint32>(m_batches.size()));
			m_batches.emplace_back();
		}

		auto& lastbatch = m_batches.back();
		Vertex2D* const pVertex = (m_vertexArray.data() + m_vertexArrayWritePos);
		Vertex2D::IndexType* const pIndex = (m_indexArray.data() + m_indexArrayWritePos);
		const auto indexOffset = lastbatch.vertexPos;

		advanceArrayWritePos(vertexSize, indexSize);
		lastbatch.advance(vertexSize, indexSize);

		return{ pVertex, pIndex, indexOffset };
	}

	size_t WebGPUVertex2DBatch::num_batches() const noexcept
	{
		return m_batches.size();
	}

	void WebGPUVertex2DBatch::reset()
	{
		m_batches.clear();
		m_batches.emplace_back();

		m_vertexArrayWritePos = 0;
		m_indexArrayWritePos = 0;

		m_vertexBufferWritePos = 0;
		m_indexBufferWritePos = 0;
	}

	void WebGPUVertex2DBatch::setBuffers(const wgpu::RenderPassEncoder& pass)
	{
		// pass.SetVertexBuffer(0, m_vertexBuffer, sizeof(Vertex2D) * m_vertexBufferWritePos);
		// pass.SetIndexBuffer(m_indexBuffer, wgpu::IndexFormat::Uint16, sizeof(Vertex2D::IndexType) * m_indexBufferWritePos);

		pass.SetVertexBuffer(0, m_vertexBuffer);
		pass.SetIndexBuffer(m_indexBuffer, wgpu::IndexFormat::Uint16);
	}

	BatchInfo2D WebGPUVertex2DBatch::updateBuffers(const wgpu::Device& device, const size_t batchIndex)
	{
		assert(batchIndex < m_batches.size());

		size_t vertexArrayReadPos = 0;
		size_t indexArrayReadPos = 0;

		for (size_t i = 0; i < batchIndex; ++i)
		{
			vertexArrayReadPos += m_batches[i].vertexPos;
			indexArrayReadPos += m_batches[i].indexPos;
		}

		BatchInfo2D batchInfo;
		const auto& currentBatch = m_batches[batchIndex];

		// VB
		if (const uint16 vertexSize = currentBatch.vertexPos)
		{
			const Vertex2D* pSrc = &m_vertexArray[vertexArrayReadPos];

			if (VertexBufferSize < (m_vertexBufferWritePos + vertexSize))
			{
				m_vertexBufferWritePos = 0;

				wgpu::BufferDescriptor vertexBufferDescripter
				{
					.size = sizeof(Vertex2D) * VertexBufferSize,
					.usage = wgpu::BufferUsage::Vertex | wgpu::BufferUsage::CopyDst
				};

				m_vertexBuffer = device.CreateBuffer(&vertexBufferDescripter);
			}

			device.GetQueue().WriteBuffer(m_vertexBuffer, sizeof(Vertex2D) * m_vertexBufferWritePos, pSrc, sizeof(Vertex2D) * vertexSize);

			// void* const pDst = m_vertexBuffer.GetMappedRange(sizeof(Vertex2D) * m_vertexBufferWritePos, sizeof(Vertex2D) * vertexSize);
			// {
			// 	std::memcpy(pDst, pSrc, sizeof(Vertex2D) * vertexSize);
			// }
			// m_vertexBuffer.Unmap();

			batchInfo.baseVertexLocation = m_vertexBufferWritePos;
			m_vertexBufferWritePos += vertexSize;
		}

		// IB
		if (const uint32 indexSize = currentBatch.indexPos)
		{
			const Vertex2D::IndexType* pSrc = &m_indexArray[indexArrayReadPos];

			if (IndexBufferSize < (m_indexBufferWritePos + indexSize))
			{
				m_indexBufferWritePos = 0;

				wgpu::BufferDescriptor indexBufferDescripter
				{
					.size = sizeof(Vertex2D::IndexType) * IndexBufferSize,
					.usage = wgpu::BufferUsage::Index | wgpu::BufferUsage::CopyDst
				};

				m_indexBuffer = device.CreateBuffer(&indexBufferDescripter);
			}

			device.GetQueue().WriteBuffer(m_indexBuffer, sizeof(Vertex2D::IndexType) * m_indexBufferWritePos, pSrc, sizeof(Vertex2D::IndexType) * indexSize);

			// void* const pDst = m_indexBuffer.GetMappedRange(sizeof(Vertex2D::IndexType) * m_indexBufferWritePos, sizeof(Vertex2D::IndexType) * indexSize);
			// {
			// 	std::memcpy(pDst, pSrc, (sizeof(Vertex2D::IndexType) * indexSize));
			// }
			// m_indexBuffer.Unmap();

			batchInfo.indexCount = indexSize;
			batchInfo.startIndexLocation = m_indexBufferWritePos;
			m_indexBufferWritePos += indexSize;
		}

		return batchInfo;
	}

	void WebGPUVertex2DBatch::advanceArrayWritePos(const uint16 vertexSize, const uint32 indexSize) noexcept
	{
		m_vertexArrayWritePos	+= vertexSize;
		m_indexArrayWritePos	+= indexSize;
	}
}
<commit_msg>[Web][WebGPU] Workaround (WriteBuffer size should be multiple of 4)<commit_after>//-----------------------------------------------
//
//	This file is part of the Siv3D Engine.
//
//	Copyright (c) 2008-2021 Ryo Suzuki
//	Copyright (c) 2016-2021 OpenSiv3D Project
//
//	Licensed under the MIT License.
//
//-----------------------------------------------

# include <Siv3D/Common.hpp>
# include <Siv3D/EngineLog.hpp>
# include "WebGPUVertex2DBatch.hpp"

namespace s3d
{
	namespace detail
	{
		static size_t CalculateNewArraySize(const size_t current, const size_t target) noexcept
		{
			size_t newArraySize = current * 2;

			while (newArraySize < target)
			{
				newArraySize *= 2;
			}

			return newArraySize;
		}
	}

	WebGPUVertex2DBatch::WebGPUVertex2DBatch()
		: m_vertexArray(InitialVertexArraySize)
		, m_indexArray(InitialIndexArraySize)
		, m_batches(1)
	{

	}

	WebGPUVertex2DBatch::~WebGPUVertex2DBatch()
	{
	}

	bool WebGPUVertex2DBatch::init(const wgpu::Device& device)
	{
		{
			wgpu::BufferDescriptor indexBufferDescripter
			{
				.size = sizeof(Vertex2D::IndexType) * InitialIndexArraySize,
				.usage = wgpu::BufferUsage::Index | wgpu::BufferUsage::CopyDst
			};

			m_indexBuffer = device.CreateBuffer(&indexBufferDescripter);
		}

		{
			wgpu::BufferDescriptor vertexBufferDescripter
			{
				.size = sizeof(Vertex2D) * InitialVertexArraySize,
				.usage = wgpu::BufferUsage::Vertex | wgpu::BufferUsage::CopyDst
			};

			m_vertexBuffer = device.CreateBuffer(&vertexBufferDescripter);
		}

		return true;
	}

	Vertex2DBufferPointer WebGPUVertex2DBatch::requestBuffer(const uint16 vertexSize, const uint32 indexSize, WebGPURenderer2DCommandManager& commandManager)
	{
		// VB
		if (const uint32 vertexArrayWritePosTarget = m_vertexArrayWritePos + vertexSize;
			m_vertexArray.size() < vertexArrayWritePosTarget) SIV3D_UNLIKELY
		{
			if (MaxVertexArraySize < vertexArrayWritePosTarget) SIV3D_UNLIKELY
			{
				return{ nullptr, 0, 0 };
			}

			const size_t newVertexArraySize = detail::CalculateNewArraySize(m_vertexArray.size(), vertexArrayWritePosTarget);
			LOG_TRACE(U"ℹ Resized WebGPUVertex2DBatch::m_vertexArray (size: {} -> {})"_fmt(m_vertexArray.size(), newVertexArraySize));
			m_vertexArray.resize(newVertexArraySize);
		}

		// IB
		if (const uint32 indexArrayWritePosTarget = m_indexArrayWritePos + indexSize;
			m_indexArray.size() < indexArrayWritePosTarget) SIV3D_UNLIKELY
		{
			if (MaxIndexArraySize < indexArrayWritePosTarget) SIV3D_UNLIKELY
			{
				return{ nullptr, 0, 0 };
			}

			const size_t newIndexArraySize = detail::CalculateNewArraySize(m_indexArray.size(), indexArrayWritePosTarget);
			LOG_TRACE(U"ℹ Resized WebGPUVertex2DBatch::m_indexArray (size: {} -> {})"_fmt(m_indexArray.size(), newIndexArraySize));
			m_indexArray.resize(newIndexArraySize);
		}

		if (const auto& lastbatch = m_batches.back();
			(VertexBufferSize < (lastbatch.vertexPos + vertexSize) || IndexBufferSize < (lastbatch.indexPos + indexSize)))
		{
			commandManager.pushUpdateBuffers(static_cast<uint32>(m_batches.size()));
			m_batches.emplace_back();
		}

		auto& lastbatch = m_batches.back();
		Vertex2D* const pVertex = (m_vertexArray.data() + m_vertexArrayWritePos);
		Vertex2D::IndexType* const pIndex = (m_indexArray.data() + m_indexArrayWritePos);
		const auto indexOffset = lastbatch.vertexPos;

		advanceArrayWritePos(vertexSize, indexSize);
		lastbatch.advance(vertexSize, indexSize);

		return{ pVertex, pIndex, indexOffset };
	}

	size_t WebGPUVertex2DBatch::num_batches() const noexcept
	{
		return m_batches.size();
	}

	void WebGPUVertex2DBatch::reset()
	{
		m_batches.clear();
		m_batches.emplace_back();

		m_vertexArrayWritePos = 0;
		m_indexArrayWritePos = 0;

		m_vertexBufferWritePos = 0;
		m_indexBufferWritePos = 0;
	}

	void WebGPUVertex2DBatch::setBuffers(const wgpu::RenderPassEncoder& pass)
	{
		// pass.SetVertexBuffer(0, m_vertexBuffer, sizeof(Vertex2D) * m_vertexBufferWritePos);
		// pass.SetIndexBuffer(m_indexBuffer, wgpu::IndexFormat::Uint16, sizeof(Vertex2D::IndexType) * m_indexBufferWritePos);

		pass.SetVertexBuffer(0, m_vertexBuffer);
		pass.SetIndexBuffer(m_indexBuffer, wgpu::IndexFormat::Uint16);
	}

	BatchInfo2D WebGPUVertex2DBatch::updateBuffers(const wgpu::Device& device, const size_t batchIndex)
	{
		assert(batchIndex < m_batches.size());

		size_t vertexArrayReadPos = 0;
		size_t indexArrayReadPos = 0;

		for (size_t i = 0; i < batchIndex; ++i)
		{
			vertexArrayReadPos += m_batches[i].vertexPos;
			indexArrayReadPos += m_batches[i].indexPos;
		}

		BatchInfo2D batchInfo;
		const auto& currentBatch = m_batches[batchIndex];

		// VB
		if (const uint16 vertexSize = currentBatch.vertexPos)
		{
			const Vertex2D* pSrc = &m_vertexArray[vertexArrayReadPos];

			if (VertexBufferSize < (m_vertexBufferWritePos + vertexSize))
			{
				m_vertexBufferWritePos = 0;

				wgpu::BufferDescriptor vertexBufferDescripter
				{
					.size = sizeof(Vertex2D) * VertexBufferSize,
					.usage = wgpu::BufferUsage::Vertex | wgpu::BufferUsage::CopyDst
				};

				m_vertexBuffer = device.CreateBuffer(&vertexBufferDescripter);
			}

			device.GetQueue().WriteBuffer(m_vertexBuffer, sizeof(Vertex2D) * m_vertexBufferWritePos, pSrc, sizeof(Vertex2D) * vertexSize);

			// void* const pDst = m_vertexBuffer.GetMappedRange(sizeof(Vertex2D) * m_vertexBufferWritePos, sizeof(Vertex2D) * vertexSize);
			// {
			// 	std::memcpy(pDst, pSrc, sizeof(Vertex2D) * vertexSize);
			// }
			// m_vertexBuffer.Unmap();

			batchInfo.baseVertexLocation = m_vertexBufferWritePos;
			m_vertexBufferWritePos += vertexSize;
		}

		// IB
		if (const uint32 indexSize = currentBatch.indexPos)
		{
			const Vertex2D::IndexType* pSrc = &m_indexArray[indexArrayReadPos];

			if (IndexBufferSize < (m_indexBufferWritePos + indexSize))
			{
				m_indexBufferWritePos = 0;

				wgpu::BufferDescriptor indexBufferDescripter
				{
					.size = sizeof(Vertex2D::IndexType) * IndexBufferSize,
					.usage = wgpu::BufferUsage::Index | wgpu::BufferUsage::CopyDst
				};

				m_indexBuffer = device.CreateBuffer(&indexBufferDescripter);
			}

			device.GetQueue().WriteBuffer(m_indexBuffer, sizeof(Vertex2D::IndexType) * m_indexBufferWritePos, pSrc, sizeof(Vertex2D::IndexType) * ((indexSize & 0xFFFFFFFE) + 2));

			// void* const pDst = m_indexBuffer.GetMappedRange(sizeof(Vertex2D::IndexType) * m_indexBufferWritePos, sizeof(Vertex2D::IndexType) * indexSize);
			// {
			// 	std::memcpy(pDst, pSrc, (sizeof(Vertex2D::IndexType) * indexSize));
			// }
			// m_indexBuffer.Unmap();

			batchInfo.indexCount = indexSize;
			batchInfo.startIndexLocation = m_indexBufferWritePos;
			m_indexBufferWritePos += indexSize;
		}

		return batchInfo;
	}

	void WebGPUVertex2DBatch::advanceArrayWritePos(const uint16 vertexSize, const uint32 indexSize) noexcept
	{
		m_vertexArrayWritePos	+= vertexSize;
		m_indexArrayWritePos	+= indexSize;
	}
}
<|endoftext|>


<commit_before><commit_msg>add switch to parton/jet checks in generator analysis<commit_after><|endoftext|>


<commit_before>/*
 * Copyright (C) 2017 Tmplt <tmplt@dragons.rocks>
 *
 * 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 <http://www.gnu.org/licenses/>.
 */

/* Planned behavior:
 *   alike vim, when the currently selected object is but a few
 *   items down or up, and the menu is scrollable, scroll a single
 *   line in the same direction. This can be donw with REQ_SCR_*.
 *
 *   'g' to go to the topmost item (REQ_FIRST_ITEM).
 *
 *   'G' to go to the bottommost item (REQ_LAST_ITEM).
 *
 *   '<spacebar> to select an item (REQ_TOGGLE_ITEM).
 */

#include <spdlog/spdlog.h>

#include "components/menu.hpp"
#include "components/logger.hpp"

namespace bookwyrm {

menu::menu(vector<item> &items)
    : items_(items)
{
    std::lock_guard<std::mutex> guard(menu_mutex_);

    initscr();
    clear();

    /*
     * Don't echo the pressed characters back,
     * and let us read individual keys.
     */
    noecho(); cbreak();

    /*
     * We also want to read special keys.
     */
    keypad(stdscr, true);

    /* Hide the cursor. */
    if (curs_set(0) == ERR)
        spdlog::get("main")->warn("curses: can't hide the cursor");

    menu_items_.emplace_back(new_item("test item", "desc"));
    menu_items_.emplace_back(new_item("test item2", "desc"));

    menu_items_.emplace_back(nullptr);
    menu_ = new_menu(const_cast<ITEM**>(menu_items_.data()));
    mvprintw(LINES - 2, 0, "Press 'q' to quit");
}

menu::~menu()
{
    /* Deconstruct everything, and quick curses. */
    unpost_menu(menu_);
    for (auto &item : menu_items_) free_item(item);
    free_menu(menu_);

    endwin();
}

void menu::display()
{
    post_menu(menu_);

    menu_mutex_.lock();
    refresh();
    menu_mutex_.unlock();

    char c;
    while ((c = getch()) != 'q') {
        switch (c) {
            case 'j':
                menu_driver(menu_, REQ_DOWN_ITEM);
                break;
            case 'k':
                menu_driver(menu_, REQ_UP_ITEM);
                break;
            case 'g':
                menu_driver(menu_, REQ_FIRST_ITEM);
                break;
            case 'G':
                menu_driver(menu_, REQ_LAST_ITEM);
                break;
        }
    }
}

void menu::update()
{
    std::lock_guard<std::mutex> guard(menu_mutex_);
    /* std::scoped_guard guard{menu_mutex_, items_mutex}; */

    /* unpost_menu(menu_); */
    /* for (auto &item : menu_items_) free_item(item); */
    /* menu_items_.clear(); */

    for (const auto &item : items_) {
        menu_items_.emplace_back(
            new_item(item.nonexacts.title.c_str(), "desc")
        );
    }
    menu_items_.emplace_back(nullptr);

    set_menu_items(menu_, const_cast<ITEM**>(menu_items_.data()));
    /* post_menu(menu_); */

    mvprintw(LINES - 1, 0, "update() has been called! %d items now!", items_.size());
    refresh();
}

} /* ns bookwyrm */
<commit_msg>menu: actually update the curses menu<commit_after>/*
 * Copyright (C) 2017 Tmplt <tmplt@dragons.rocks>
 *
 * 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 <http://www.gnu.org/licenses/>.
 */

/* Planned behavior:
 *   alike vim, when the currently selected object is but a few
 *   items down or up, and the menu is scrollable, scroll a single
 *   line in the same direction. This can be donw with REQ_SCR_*.
 *
 *   'g' to go to the topmost item (REQ_FIRST_ITEM).
 *
 *   'G' to go to the bottommost item (REQ_LAST_ITEM).
 *
 *   '<spacebar> to select an item (REQ_TOGGLE_ITEM).
 */

#include <spdlog/spdlog.h>

#include "components/menu.hpp"
#include "components/logger.hpp"

namespace bookwyrm {

menu::menu(vector<item> &items)
    : items_(items)
{
    std::lock_guard<std::mutex> guard(menu_mutex_);

    initscr();
    clear();

    /*
     * Don't echo the pressed characters back,
     * and let us read individual keys.
     */
    noecho(); cbreak();

    /*
     * We also want to read special keys.
     */
    keypad(stdscr, true);

    /* Hide the cursor. */
    if (curs_set(0) == ERR)
        spdlog::get("main")->warn("curses: can't hide the cursor");

    menu_items_.emplace_back(new_item("test item", "desc"));
    menu_items_.emplace_back(new_item("test item2", "desc"));

    menu_items_.emplace_back(nullptr);
    menu_ = new_menu(const_cast<ITEM**>(menu_items_.data()));
    mvprintw(LINES - 3, 0, "Press 'q' to quit");
}

menu::~menu()
{
    /* Deconstruct everything, and quick curses. */
    unpost_menu(menu_);
    for (auto &item : menu_items_) free_item(item);
    free_menu(menu_);

    endwin();
}

void menu::display()
{
    post_menu(menu_);

    menu_mutex_.lock();
    refresh();
    menu_mutex_.unlock();

    char c;
    while ((c = getch()) != 'q') {
        switch (c) {
            case 'j':
                menu_driver(menu_, REQ_DOWN_ITEM);
                break;
            case 'k':
                menu_driver(menu_, REQ_UP_ITEM);
                break;
            case 'g':
                menu_driver(menu_, REQ_FIRST_ITEM);
                break;
            case 'G':
                menu_driver(menu_, REQ_LAST_ITEM);
                break;
        }
    }
}

void menu::update()
{
    std::lock_guard<std::mutex> guard(menu_mutex_);

    unpost_menu(menu_);
    free_menu(menu_);
    for (auto &item : menu_items_) free_item(item);
    menu_items_.clear();

    for (const auto &item : items_) {
        menu_items_.emplace_back(
            new_item(item.nonexacts.title.c_str(), "desc")
        );
    }
    menu_items_.emplace_back(nullptr);

    /* auto ret = set_menu_items(menu_, const_cast<ITEM**>(menu_items_.data())); */
    menu_ = new_menu(const_cast<ITEM**>(menu_items_.data()));
    post_menu(menu_);

    mvprintw(LINES - 2, 0, "update() has been called! %d items should be listed!"
            " The curses menu itself contains %d items.", menu_items_.size() - 1, item_count(menu_));
    /* mvprintw(LINES - 1, 0, "set_menu_items() yielded: %d (%d)", ret, ret == E_OK); */
    refresh();
}

} /* ns bookwyrm */
<|endoftext|>


<commit_before><commit_msg>Setting of n z vertex set again later, remove<commit_after><|endoftext|>


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

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) University College London (UCL).
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

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

// Blueberry
#include <berryIPreferences.h>
#include <berryIPreferencesService.h>
#include <berryIBerryPreferences.h>

// Qmitk
#include "CommandLineModulesView.h"
#include "CommandLineModulesViewConstants.h"
#include "CommandLineModulesViewControls.h"
#include "CommandLineModulesPreferencesPage.h"
#include "QmitkCmdLineModuleFactoryGui.h"
#include "QmitkCmdLineModuleGui.h"
#include "QmitkCmdLineModuleProgressWidget.h"

// Qt
#include <QDebug>
#include <QDir>
#include <QAction>
#include <QVBoxLayout>
#include <QLayoutItem>
#include <QWidgetItem>
#include <QMessageBox>

// CTK
#include <ctkCmdLineModuleManager.h>
#include <ctkCmdLineModuleFrontend.h>
#include <ctkCmdLineModuleBackendLocalProcess.h>
#include <ctkCmdLineModuleDefaultPathBuilder.h>
#include <ctkCmdLineModuleDirectoryWatcher.h>
#include <ctkCmdLineModuleReference.h>
#include <ctkCmdLineModuleDescription.h>

//-----------------------------------------------------------------------------
CommandLineModulesView::CommandLineModulesView()
: m_Controls(NULL)
, m_Parent(NULL)
, m_Layout(NULL)
, m_ModuleManager(NULL)
, m_ModuleBackend(NULL)
, m_DirectoryWatcher(NULL)
, m_TemporaryDirectoryName("")
, m_MaximumConcurrentProcesses(4)
, m_CurrentlyRunningProcesses(0)
, m_DebugOutput(false)
{
}

//-----------------------------------------------------------------------------
CommandLineModulesView::~CommandLineModulesView()
{
  if (m_ModuleManager != NULL)
  {
    delete m_ModuleManager;
  }

  if (m_ModuleBackend != NULL)
  {
    delete m_ModuleBackend;
  }

  if (m_DirectoryWatcher != NULL)
  {
    delete m_DirectoryWatcher;
  }

  if (m_Layout != NULL)
  {
    delete m_Layout;
  }

  for (int i = 0; i < m_ListOfModules.size(); i++)
  {
    delete m_ListOfModules[i];
  }
}

//-----------------------------------------------------------------------------
void CommandLineModulesView::SetFocus()
{
  this->m_Controls->m_ComboBox->setFocus();
}

//-----------------------------------------------------------------------------
void CommandLineModulesView::CreateQtPartControl( QWidget *parent )
{
  m_Parent = parent;

  if (!m_Controls)
  {
    // We create CommandLineModulesViewControls, which derives from the Qt generated class.
    m_Controls = new CommandLineModulesViewControls(parent);

    // Create a layout to contain a display of QmitkCmdLineModuleProgressWidget.
    m_Layout = new QVBoxLayout(m_Controls->m_RunningWidgets);
    m_Layout->setContentsMargins(0,0,0,0);
    m_Layout->setSpacing(0);

    // This must be done independent of other preferences, as we need it before
    // we create the ctkCmdLineModuleManager to initialise the Cache.
    this->RetrieveAndStoreTemporaryDirectoryPreferenceValues();
    this->RetrieveAndStoreValidationMode();

    // Start to create the command line module infrastructure.
    m_ModuleBackend = new ctkCmdLineModuleBackendLocalProcess();
    m_ModuleManager = new ctkCmdLineModuleManager(m_ValidationMode, m_TemporaryDirectoryName);

    // Set the main object, the ctkCmdLineModuleManager onto all the objects that need it.
    m_Controls->m_ComboBox->SetManager(m_ModuleManager);
    m_DirectoryWatcher = new ctkCmdLineModuleDirectoryWatcher(m_ModuleManager);
    m_ModuleManager->registerBackend(m_ModuleBackend);

    // Setup the remaining preferences.
    this->RetrieveAndStorePreferenceValues();

    // Connect signals to slots after we have set up GUI.
    connect(this->m_Controls->m_RunButton, SIGNAL(pressed()), this, SLOT(OnRunButtonPressed()));
    connect(this->m_Controls->m_RestoreDefaults, SIGNAL(pressed()), this, SLOT(OnRestoreButtonPressed()));
    connect(this->m_Controls->m_ComboBox, SIGNAL(actionChanged(QAction*)), this, SLOT(OnActionChanged(QAction*)));
    connect(this->m_Controls->m_TabWidget, SIGNAL(tabCloseRequested(int)), this, SLOT(OnTabCloseRequested(int)));

    this->UpdateRunButtonEnabledStatus();
  }
}

//-----------------------------------------------------------------------------
berry::IBerryPreferences::Pointer CommandLineModulesView::RetrievePreferences()
{
  berry::IPreferencesService::Pointer prefService
      = berry::Platform::GetServiceRegistry()
      .GetServiceById<berry::IPreferencesService>(berry::IPreferencesService::ID);

  assert( prefService );

  std::string id = "/" + CommandLineModulesViewConstants::VIEW_ID;
  berry::IBerryPreferences::Pointer prefs
      = (prefService->GetSystemPreferences()->Node(id))
        .Cast<berry::IBerryPreferences>();

  assert( prefs );

  return prefs;
}

//-----------------------------------------------------------------------------
void CommandLineModulesView::RetrieveAndStoreTemporaryDirectoryPreferenceValues()
{
  berry::IBerryPreferences::Pointer prefs = this->RetrievePreferences();

  QString fallbackTmpDir = QDir::tempPath();
  m_TemporaryDirectoryName = QString::fromStdString(
      prefs->Get(CommandLineModulesViewConstants::TEMPORARY_DIRECTORY_NODE_NAME, fallbackTmpDir.toStdString()));
}

//-----------------------------------------------------------------------------
void CommandLineModulesView::RetrieveAndStoreValidationMode()
{
  berry::IBerryPreferences::Pointer prefs = this->RetrievePreferences();

  int value = prefs->GetInt(CommandLineModulesViewConstants::XML_VALIDATION_MODE, 0);
  if (value == 0)
  {
    m_ValidationMode = ctkCmdLineModuleManager::STRICT_VALIDATION;
  }
  else if (value == 1)
  {
    m_ValidationMode = ctkCmdLineModuleManager::SKIP_VALIDATION;
  }
  else
  {
    m_ValidationMode = ctkCmdLineModuleManager::WEAK_VALIDATION;
  }
}

//-----------------------------------------------------------------------------
void CommandLineModulesView::RetrieveAndStorePreferenceValues()
{
  berry::IBerryPreferences::Pointer prefs = this->RetrievePreferences();

  m_MaximumConcurrentProcesses = prefs->GetInt(CommandLineModulesViewConstants::MAX_CONCURRENT, 4);

  // Get the flag for debug output, useful when parsing all the XML.
  m_DebugOutput = prefs->GetBool(CommandLineModulesViewConstants::DEBUG_OUTPUT_NODE_NAME, false);
  m_DirectoryWatcher->setDebug(m_DebugOutput);

  bool loadApplicationDir = prefs->GetBool(CommandLineModulesViewConstants::LOAD_FROM_APPLICATION_DIR, false);
  bool loadHomeDir = prefs->GetBool(CommandLineModulesViewConstants::LOAD_FROM_HOME_DIR, false);
  bool loadCurrentDir = prefs->GetBool(CommandLineModulesViewConstants::LOAD_FROM_CURRENT_DIR, false);
  bool loadAutoLoadDir = prefs->GetBool(CommandLineModulesViewConstants::LOAD_FROM_AUTO_LOAD_DIR, false);

  // Get some default application paths.

  // Here we can use the preferences to set up the builder,
  ctkCmdLineModuleDefaultPathBuilder builder;
  builder.setLoadFromApplicationDir(loadApplicationDir);
  builder.setLoadFromHomeDir(loadHomeDir);
  builder.setLoadFromCurrentDir(loadCurrentDir);
  builder.setLoadFromCtkModuleLoadPath(loadAutoLoadDir);

  // and then we ask the builder to set up the paths.
  QStringList defaultPaths = builder.build();

  // We get additional directory paths from preferences.
  QString pathString = QString::fromStdString(prefs->Get(CommandLineModulesViewConstants::MODULE_DIRECTORIES_NODE_NAME, ""));
  QStringList additionalPaths = pathString.split(";", QString::SkipEmptyParts);

  // Combine the sets of directory paths.
  QStringList totalPaths;
  totalPaths << defaultPaths;
  totalPaths << additionalPaths;

  QString additionalModulesString = QString::fromStdString(prefs->Get(CommandLineModulesViewConstants::MODULE_FILES_NODE_NAME, ""));
  QStringList additionalModules = additionalModulesString.split(";", QString::SkipEmptyParts);

  // OnPreferencesChanged can be called for each preference in a dialog box, so
  // when you hit "OK", it is called repeatedly, whereas we want to only call these only once.
  if (this->m_DirectoryWatcher->directories() != totalPaths)
  {
    m_DirectoryWatcher->setDirectories(totalPaths);
  }
  if (this->m_DirectoryWatcher->additionalModules() != additionalModules)
  {
    m_DirectoryWatcher->setAdditionalModules(additionalModules);
  }
}

//-----------------------------------------------------------------------------
void CommandLineModulesView::OnPreferencesChanged(const berry::IBerryPreferences* /*prefs*/)
{
  this->RetrieveAndStoreTemporaryDirectoryPreferenceValues();
  this->RetrieveAndStoreValidationMode();
  this->RetrieveAndStorePreferenceValues();
}

//-----------------------------------------------------------------------------
ctkCmdLineModuleReference CommandLineModulesView::GetReferenceByFullName(QString fullName)
{
  ctkCmdLineModuleReference result;

  QList<ctkCmdLineModuleReference> references = this->m_ModuleManager->moduleReferences();

  ctkCmdLineModuleReference ref;
  foreach(ref, references)
  {
    QString name = ref.description().categoryDotTitle();
    if (name == fullName)
    {
      result = ref;
    }
  }

  return result;
}

//-----------------------------------------------------------------------------
void CommandLineModulesView::OnActionChanged(QAction* action)
{
  QString fullName = action->objectName();
  ctkCmdLineModuleReference ref = this->GetReferenceByFullName(fullName);

  // ref should never be invalid, as the menu was generated from each ctkCmdLineModuleReference.
  // But just to be sure ... if invalid, don't do anything.
  if (ref)
  {
    // Check if we already have the reference.
    int tabIndex = -1;
    for (int i = 0; i < m_ListOfModules.size(); i++)
    {
      ctkCmdLineModuleReference tabsReference = m_ListOfModules[i]->moduleReference();
      if (ref.location() == tabsReference.location())
      {
        tabIndex = i;
        break;
      }
    }

    // i.e. we found a matching tab, so just switch to it.
    if (tabIndex != -1)
    {
      m_Controls->m_TabWidget->setCurrentIndex(tabIndex);
    }
    else // i.e. we did not find a matching tab
    {
      // In this case, we need to create a new tab, and give
      // it a GUI for the user to setup the parameters with.
      QmitkCmdLineModuleFactoryGui factory(this->GetDataStorage());
      ctkCmdLineModuleFrontend *frontEnd = factory.create(ref);
      QmitkCmdLineModuleGui *theGui = dynamic_cast<QmitkCmdLineModuleGui*>(frontEnd);

      // Add to list and tab wigdget
      m_ListOfModules.push_back(frontEnd);
      int tabIndex = m_Controls->m_TabWidget->addTab(theGui->getGui(), ref.description().title());
      m_Controls->m_TabWidget->setTabToolTip(tabIndex, ref.description().title() + ":" + ref.xmlValidationErrorString());
    }
  }
}

//-----------------------------------------------------------------------------
void CommandLineModulesView::OnTabCloseRequested(int tabNumber)
{

  ctkCmdLineModuleFrontend *frontEnd = m_ListOfModules[tabNumber];

  m_Controls->m_TabWidget->removeTab(tabNumber);
  m_ListOfModules.removeAt(tabNumber);

  delete frontEnd;
}

//-----------------------------------------------------------------------------
void CommandLineModulesView::AskUserToSelectAModule() const
{
  QMessageBox msgBox;
  msgBox.setText("Please select a module!");
  msgBox.setIcon(QMessageBox::Warning);
  msgBox.exec();
}

//-----------------------------------------------------------------------------
void CommandLineModulesView::OnRestoreButtonPressed()
{
  int tabNumber = m_Controls->m_TabWidget->currentIndex();
  if (tabNumber >= 0)
  {
    ctkCmdLineModuleFrontend *frontEnd = m_ListOfModules[tabNumber];
    frontEnd->resetValues();
  }
  else
  {
    this->AskUserToSelectAModule();
  }
}

//-----------------------------------------------------------------------------
void CommandLineModulesView::OnRunButtonPressed()
{
  int tabNumber = m_Controls->m_TabWidget->currentIndex();
  if (tabNumber >= 0)
  {
    // 1. Create a new QmitkCmdLineModuleProgressWidget to represent the running widget.
    QmitkCmdLineModuleProgressWidget *widget = new QmitkCmdLineModuleProgressWidget(m_Controls->m_RunningWidgets);
    widget->SetDataStorage(this->GetDataStorage());
    widget->SetManager(m_ModuleManager);
    widget->SetTemporaryDirectory(m_TemporaryDirectoryName);

    // 2. Create a new front end.
    QmitkCmdLineModuleFactoryGui factory(this->GetDataStorage());

    ctkCmdLineModuleFrontend *frontEndOnCurrentTab = m_ListOfModules[tabNumber];
    QmitkCmdLineModuleGui *frontEndGuiOnCurrentTab = dynamic_cast<QmitkCmdLineModuleGui*>(frontEndOnCurrentTab);
    ctkCmdLineModuleReference currentTabFrontendReferences = frontEndGuiOnCurrentTab->moduleReference();

    ctkCmdLineModuleFrontend *newFrontEnd = factory.create(currentTabFrontendReferences);
    QmitkCmdLineModuleGui *newFrontEndGui = dynamic_cast<QmitkCmdLineModuleGui*>(newFrontEnd);
    widget->SetFrontend(newFrontEndGui);
    m_Layout->insertWidget(0, widget);

    // 3. Copy parameters. This MUST come after widget->SetFrontEnd
    newFrontEndGui->copyParameters(*frontEndGuiOnCurrentTab);

    // 4. Connect widget signals to here, to count how many jobs running.
    connect(widget, SIGNAL(started()), this, SLOT(OnJobStarted()));
    connect(widget, SIGNAL(finished()), this, SLOT(OnJobFinished()));

    // 5. GO.
    widget->Run();
  }
  else
  {
    this->AskUserToSelectAModule();
  }
}

//-----------------------------------------------------------------------------
void CommandLineModulesView::UpdateRunButtonEnabledStatus()
{
  if (m_CurrentlyRunningProcesses >= m_MaximumConcurrentProcesses)
  {
    m_Controls->m_RunButton->setEnabled(false);
  }
  else
  {
    m_Controls->m_RunButton->setEnabled(true);
  }
}

//-----------------------------------------------------------------------------
void CommandLineModulesView::OnJobStarted()
{
  m_CurrentlyRunningProcesses++;
  this->UpdateRunButtonEnabledStatus();
}

//-----------------------------------------------------------------------------
void CommandLineModulesView::OnJobFinished()
{
  m_CurrentlyRunningProcesses--;
  this->UpdateRunButtonEnabledStatus();
}
<commit_msg>Set GUI parameters in progress widget to disabled in CLI module<commit_after>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) University College London (UCL).
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

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

// Blueberry
#include <berryIPreferences.h>
#include <berryIPreferencesService.h>
#include <berryIBerryPreferences.h>

// Qmitk
#include "CommandLineModulesView.h"
#include "CommandLineModulesViewConstants.h"
#include "CommandLineModulesViewControls.h"
#include "CommandLineModulesPreferencesPage.h"
#include "QmitkCmdLineModuleFactoryGui.h"
#include "QmitkCmdLineModuleGui.h"
#include "QmitkCmdLineModuleProgressWidget.h"

// Qt
#include <QDebug>
#include <QDir>
#include <QAction>
#include <QVBoxLayout>
#include <QLayoutItem>
#include <QWidgetItem>
#include <QMessageBox>

// CTK
#include <ctkCmdLineModuleManager.h>
#include <ctkCmdLineModuleFrontend.h>
#include <ctkCmdLineModuleBackendLocalProcess.h>
#include <ctkCmdLineModuleDefaultPathBuilder.h>
#include <ctkCmdLineModuleDirectoryWatcher.h>
#include <ctkCmdLineModuleReference.h>
#include <ctkCmdLineModuleDescription.h>

//-----------------------------------------------------------------------------
CommandLineModulesView::CommandLineModulesView()
: m_Controls(NULL)
, m_Parent(NULL)
, m_Layout(NULL)
, m_ModuleManager(NULL)
, m_ModuleBackend(NULL)
, m_DirectoryWatcher(NULL)
, m_TemporaryDirectoryName("")
, m_MaximumConcurrentProcesses(4)
, m_CurrentlyRunningProcesses(0)
, m_DebugOutput(false)
{
}

//-----------------------------------------------------------------------------
CommandLineModulesView::~CommandLineModulesView()
{
  if (m_ModuleManager != NULL)
  {
    delete m_ModuleManager;
  }

  if (m_ModuleBackend != NULL)
  {
    delete m_ModuleBackend;
  }

  if (m_DirectoryWatcher != NULL)
  {
    delete m_DirectoryWatcher;
  }

  if (m_Layout != NULL)
  {
    delete m_Layout;
  }

  for (int i = 0; i < m_ListOfModules.size(); i++)
  {
    delete m_ListOfModules[i];
  }
}

//-----------------------------------------------------------------------------
void CommandLineModulesView::SetFocus()
{
  this->m_Controls->m_ComboBox->setFocus();
}

//-----------------------------------------------------------------------------
void CommandLineModulesView::CreateQtPartControl( QWidget *parent )
{
  m_Parent = parent;

  if (!m_Controls)
  {
    // We create CommandLineModulesViewControls, which derives from the Qt generated class.
    m_Controls = new CommandLineModulesViewControls(parent);

    // Create a layout to contain a display of QmitkCmdLineModuleProgressWidget.
    m_Layout = new QVBoxLayout(m_Controls->m_RunningWidgets);
    m_Layout->setContentsMargins(0,0,0,0);
    m_Layout->setSpacing(0);

    // This must be done independent of other preferences, as we need it before
    // we create the ctkCmdLineModuleManager to initialise the Cache.
    this->RetrieveAndStoreTemporaryDirectoryPreferenceValues();
    this->RetrieveAndStoreValidationMode();

    // Start to create the command line module infrastructure.
    m_ModuleBackend = new ctkCmdLineModuleBackendLocalProcess();
    m_ModuleManager = new ctkCmdLineModuleManager(m_ValidationMode, m_TemporaryDirectoryName);

    // Set the main object, the ctkCmdLineModuleManager onto all the objects that need it.
    m_Controls->m_ComboBox->SetManager(m_ModuleManager);
    m_DirectoryWatcher = new ctkCmdLineModuleDirectoryWatcher(m_ModuleManager);
    m_ModuleManager->registerBackend(m_ModuleBackend);

    // Setup the remaining preferences.
    this->RetrieveAndStorePreferenceValues();

    // Connect signals to slots after we have set up GUI.
    connect(this->m_Controls->m_RunButton, SIGNAL(pressed()), this, SLOT(OnRunButtonPressed()));
    connect(this->m_Controls->m_RestoreDefaults, SIGNAL(pressed()), this, SLOT(OnRestoreButtonPressed()));
    connect(this->m_Controls->m_ComboBox, SIGNAL(actionChanged(QAction*)), this, SLOT(OnActionChanged(QAction*)));
    connect(this->m_Controls->m_TabWidget, SIGNAL(tabCloseRequested(int)), this, SLOT(OnTabCloseRequested(int)));

    this->UpdateRunButtonEnabledStatus();
  }
}

//-----------------------------------------------------------------------------
berry::IBerryPreferences::Pointer CommandLineModulesView::RetrievePreferences()
{
  berry::IPreferencesService::Pointer prefService
      = berry::Platform::GetServiceRegistry()
      .GetServiceById<berry::IPreferencesService>(berry::IPreferencesService::ID);

  assert( prefService );

  std::string id = "/" + CommandLineModulesViewConstants::VIEW_ID;
  berry::IBerryPreferences::Pointer prefs
      = (prefService->GetSystemPreferences()->Node(id))
        .Cast<berry::IBerryPreferences>();

  assert( prefs );

  return prefs;
}

//-----------------------------------------------------------------------------
void CommandLineModulesView::RetrieveAndStoreTemporaryDirectoryPreferenceValues()
{
  berry::IBerryPreferences::Pointer prefs = this->RetrievePreferences();

  QString fallbackTmpDir = QDir::tempPath();
  m_TemporaryDirectoryName = QString::fromStdString(
      prefs->Get(CommandLineModulesViewConstants::TEMPORARY_DIRECTORY_NODE_NAME, fallbackTmpDir.toStdString()));
}

//-----------------------------------------------------------------------------
void CommandLineModulesView::RetrieveAndStoreValidationMode()
{
  berry::IBerryPreferences::Pointer prefs = this->RetrievePreferences();

  int value = prefs->GetInt(CommandLineModulesViewConstants::XML_VALIDATION_MODE, 0);
  if (value == 0)
  {
    m_ValidationMode = ctkCmdLineModuleManager::STRICT_VALIDATION;
  }
  else if (value == 1)
  {
    m_ValidationMode = ctkCmdLineModuleManager::SKIP_VALIDATION;
  }
  else
  {
    m_ValidationMode = ctkCmdLineModuleManager::WEAK_VALIDATION;
  }
}

//-----------------------------------------------------------------------------
void CommandLineModulesView::RetrieveAndStorePreferenceValues()
{
  berry::IBerryPreferences::Pointer prefs = this->RetrievePreferences();

  m_MaximumConcurrentProcesses = prefs->GetInt(CommandLineModulesViewConstants::MAX_CONCURRENT, 4);

  // Get the flag for debug output, useful when parsing all the XML.
  m_DebugOutput = prefs->GetBool(CommandLineModulesViewConstants::DEBUG_OUTPUT_NODE_NAME, false);
  m_DirectoryWatcher->setDebug(m_DebugOutput);

  bool loadApplicationDir = prefs->GetBool(CommandLineModulesViewConstants::LOAD_FROM_APPLICATION_DIR, false);
  bool loadHomeDir = prefs->GetBool(CommandLineModulesViewConstants::LOAD_FROM_HOME_DIR, false);
  bool loadCurrentDir = prefs->GetBool(CommandLineModulesViewConstants::LOAD_FROM_CURRENT_DIR, false);
  bool loadAutoLoadDir = prefs->GetBool(CommandLineModulesViewConstants::LOAD_FROM_AUTO_LOAD_DIR, false);

  // Get some default application paths.

  // Here we can use the preferences to set up the builder,
  ctkCmdLineModuleDefaultPathBuilder builder;
  builder.setLoadFromApplicationDir(loadApplicationDir);
  builder.setLoadFromHomeDir(loadHomeDir);
  builder.setLoadFromCurrentDir(loadCurrentDir);
  builder.setLoadFromCtkModuleLoadPath(loadAutoLoadDir);

  // and then we ask the builder to set up the paths.
  QStringList defaultPaths = builder.build();

  // We get additional directory paths from preferences.
  QString pathString = QString::fromStdString(prefs->Get(CommandLineModulesViewConstants::MODULE_DIRECTORIES_NODE_NAME, ""));
  QStringList additionalPaths = pathString.split(";", QString::SkipEmptyParts);

  // Combine the sets of directory paths.
  QStringList totalPaths;
  totalPaths << defaultPaths;
  totalPaths << additionalPaths;

  QString additionalModulesString = QString::fromStdString(prefs->Get(CommandLineModulesViewConstants::MODULE_FILES_NODE_NAME, ""));
  QStringList additionalModules = additionalModulesString.split(";", QString::SkipEmptyParts);

  // OnPreferencesChanged can be called for each preference in a dialog box, so
  // when you hit "OK", it is called repeatedly, whereas we want to only call these only once.
  if (this->m_DirectoryWatcher->directories() != totalPaths)
  {
    m_DirectoryWatcher->setDirectories(totalPaths);
  }
  if (this->m_DirectoryWatcher->additionalModules() != additionalModules)
  {
    m_DirectoryWatcher->setAdditionalModules(additionalModules);
  }
}

//-----------------------------------------------------------------------------
void CommandLineModulesView::OnPreferencesChanged(const berry::IBerryPreferences* /*prefs*/)
{
  this->RetrieveAndStoreTemporaryDirectoryPreferenceValues();
  this->RetrieveAndStoreValidationMode();
  this->RetrieveAndStorePreferenceValues();
}

//-----------------------------------------------------------------------------
ctkCmdLineModuleReference CommandLineModulesView::GetReferenceByFullName(QString fullName)
{
  ctkCmdLineModuleReference result;

  QList<ctkCmdLineModuleReference> references = this->m_ModuleManager->moduleReferences();

  ctkCmdLineModuleReference ref;
  foreach(ref, references)
  {
    QString name = ref.description().categoryDotTitle();
    if (name == fullName)
    {
      result = ref;
    }
  }

  return result;
}

//-----------------------------------------------------------------------------
void CommandLineModulesView::OnActionChanged(QAction* action)
{
  QString fullName = action->objectName();
  ctkCmdLineModuleReference ref = this->GetReferenceByFullName(fullName);

  // ref should never be invalid, as the menu was generated from each ctkCmdLineModuleReference.
  // But just to be sure ... if invalid, don't do anything.
  if (ref)
  {
    // Check if we already have the reference.
    int tabIndex = -1;
    for (int i = 0; i < m_ListOfModules.size(); i++)
    {
      ctkCmdLineModuleReference tabsReference = m_ListOfModules[i]->moduleReference();
      if (ref.location() == tabsReference.location())
      {
        tabIndex = i;
        break;
      }
    }

    // i.e. we found a matching tab, so just switch to it.
    if (tabIndex != -1)
    {
      m_Controls->m_TabWidget->setCurrentIndex(tabIndex);
    }
    else // i.e. we did not find a matching tab
    {
      // In this case, we need to create a new tab, and give
      // it a GUI for the user to setup the parameters with.
      QmitkCmdLineModuleFactoryGui factory(this->GetDataStorage());
      ctkCmdLineModuleFrontend *frontEnd = factory.create(ref);
      QmitkCmdLineModuleGui *theGui = dynamic_cast<QmitkCmdLineModuleGui*>(frontEnd);

      // Add to list and tab wigdget
      m_ListOfModules.push_back(frontEnd);
      int tabIndex = m_Controls->m_TabWidget->addTab(theGui->getGui(), ref.description().title());
      m_Controls->m_TabWidget->setTabToolTip(tabIndex, ref.description().title() + ":" + ref.xmlValidationErrorString());
    }
  }
}

//-----------------------------------------------------------------------------
void CommandLineModulesView::OnTabCloseRequested(int tabNumber)
{

  ctkCmdLineModuleFrontend *frontEnd = m_ListOfModules[tabNumber];

  m_Controls->m_TabWidget->removeTab(tabNumber);
  m_ListOfModules.removeAt(tabNumber);

  delete frontEnd;
}

//-----------------------------------------------------------------------------
void CommandLineModulesView::AskUserToSelectAModule() const
{
  QMessageBox msgBox;
  msgBox.setText("Please select a module!");
  msgBox.setIcon(QMessageBox::Warning);
  msgBox.exec();
}

//-----------------------------------------------------------------------------
void CommandLineModulesView::OnRestoreButtonPressed()
{
  int tabNumber = m_Controls->m_TabWidget->currentIndex();
  if (tabNumber >= 0)
  {
    ctkCmdLineModuleFrontend *frontEnd = m_ListOfModules[tabNumber];
    frontEnd->resetValues();
  }
  else
  {
    this->AskUserToSelectAModule();
  }
}

//-----------------------------------------------------------------------------
void CommandLineModulesView::OnRunButtonPressed()
{
  int tabNumber = m_Controls->m_TabWidget->currentIndex();
  if (tabNumber >= 0)
  {
    // 1. Create a new QmitkCmdLineModuleProgressWidget to represent the running widget.
    QmitkCmdLineModuleProgressWidget *widget = new QmitkCmdLineModuleProgressWidget(m_Controls->m_RunningWidgets);
    widget->SetDataStorage(this->GetDataStorage());
    widget->SetManager(m_ModuleManager);
    widget->SetTemporaryDirectory(m_TemporaryDirectoryName);

    // 2. Create a new front end.
    QmitkCmdLineModuleFactoryGui factory(this->GetDataStorage());

    ctkCmdLineModuleFrontend *frontEndOnCurrentTab = m_ListOfModules[tabNumber];
    QmitkCmdLineModuleGui *frontEndGuiOnCurrentTab = dynamic_cast<QmitkCmdLineModuleGui*>(frontEndOnCurrentTab);
    ctkCmdLineModuleReference currentTabFrontendReferences = frontEndGuiOnCurrentTab->moduleReference();

    ctkCmdLineModuleFrontend *newFrontEnd = factory.create(currentTabFrontendReferences);
    QmitkCmdLineModuleGui *newFrontEndGui = dynamic_cast<QmitkCmdLineModuleGui*>(newFrontEnd);
    widget->SetFrontend(newFrontEndGui);
    m_Layout->insertWidget(0, widget);

    // 3. Copy parameters. This MUST come after widget->SetFrontEnd
    newFrontEndGui->copyParameters(*frontEndGuiOnCurrentTab);
    newFrontEndGui->setParametersEnabled(false);

    // 4. Connect widget signals to here, to count how many jobs running.
    connect(widget, SIGNAL(started()), this, SLOT(OnJobStarted()));
    connect(widget, SIGNAL(finished()), this, SLOT(OnJobFinished()));

    // 5. GO.
    widget->Run();
  }
  else
  {
    this->AskUserToSelectAModule();
  }
}

//-----------------------------------------------------------------------------
void CommandLineModulesView::UpdateRunButtonEnabledStatus()
{
  if (m_CurrentlyRunningProcesses >= m_MaximumConcurrentProcesses)
  {
    m_Controls->m_RunButton->setEnabled(false);
  }
  else
  {
    m_Controls->m_RunButton->setEnabled(true);
  }
}

//-----------------------------------------------------------------------------
void CommandLineModulesView::OnJobStarted()
{
  m_CurrentlyRunningProcesses++;
  this->UpdateRunButtonEnabledStatus();
}

//-----------------------------------------------------------------------------
void CommandLineModulesView::OnJobFinished()
{
  m_CurrentlyRunningProcesses--;
  this->UpdateRunButtonEnabledStatus();
}
<|endoftext|>


<commit_before>#include "stdafx.h"
#include <dukat/audiomanager.h>
#include <dukat/audiocache.h>
#include <dukat/sdlutil.h>
#include <dukat/log.h>

namespace dukat
{
	AudioManager::AudioManager(int num_channels) : num_channels(num_channels), channel_volume(num_channels)
	{
		log->info("Initializating audio mixer.");

		const auto init_flags = MIX_INIT_MP3 | MIX_INIT_OGG;
		if (Mix_Init(init_flags) != init_flags)
			throw std::runtime_error("Failed to initialize audio mixer.");

		const auto frequency = 44100;
		sdl_check_result(Mix_OpenAudio(frequency, MIX_DEFAULT_FORMAT, 2, 4096), "Open mixer");
		auto res = Mix_AllocateChannels(num_channels);
		log->debug("Allocated {} channels.", res);
		std::fill(channel_volume.begin(), channel_volume.end(), 1.0f);
	}

	AudioManager::~AudioManager(void)
	{
		Mix_CloseAudio();
	}

	int AudioManager::get_num_active_channels(void) const
	{
		return Mix_Playing(-1);
	}

	bool AudioManager::is_active(int channel) const
	{
		assert(channel < num_channels);
		return Mix_Playing(channel) != 0;
	}

	void AudioManager::set_music_volume(float volume)
	{
		music_volume = volume;
		if (Mix_PlayingMusic())
		{
			Mix_VolumeMusic(static_cast<int>(music_volume * MIX_MAX_VOLUME));
		}
	}

	void AudioManager::play_music(Music* music, int loops) const
	{
		if (Mix_PlayMusic(music->music, loops) == playback_error)
		{
			log->warn("Failed to play music: {}", Mix_GetError());
		}
		Mix_VolumeMusic(static_cast<int>(music_volume * MIX_MAX_VOLUME));
	}

	void AudioManager::pause_music(void) const
	{
		Mix_PauseMusic();
	}

	void AudioManager::stop_music(void) const
	{
		Mix_HaltMusic();
	}

	int AudioManager::play_sample(Sample* sample, int channel, int loops)
	{
		const auto res = Mix_PlayChannel(channel, sample->chunk, loops);
		if (res != playback_error)
		{
			Mix_Volume(res, static_cast<int>(channel_volume[res] * sample_volume * MIX_MAX_VOLUME));
		}
		else
		{
			// Playback failed - no channel available
		}
		return res;
	}

	void AudioManager::stop_sample(int channel)
	{
		Mix_HaltChannel(channel);
	}

	void AudioManager::stop_all(void)
	{
		for (auto channel = 0; channel < num_channels; channel++)
			Mix_HaltChannel(channel);
	}

	void AudioManager::pause_all(void)
	{
		Mix_Pause(-1);
		Mix_PausedMusic();
	}

	void AudioManager::resume_all(void)
	{
		Mix_Resume(-1);
		Mix_ResumeMusic();
	}
}<commit_msg>Better logging of Mix_Init result<commit_after>#include "stdafx.h"
#include <dukat/audiomanager.h>
#include <dukat/audiocache.h>
#include <dukat/sdlutil.h>
#include <dukat/log.h>

namespace dukat
{
	AudioManager::AudioManager(int num_channels) : num_channels(num_channels), channel_volume(num_channels)
	{
		log->info("Initializating audio mixer.");

		const auto init_flags = MIX_INIT_MP3 | MIX_INIT_OGG;
		auto res = Mix_Init(init_flags);
		log->debug("Mix_Init returned: {}", res);
		if (res != init_flags)
			throw std::runtime_error("Failed to initialize audio mixer.");

		const auto frequency = 44100;
		sdl_check_result(Mix_OpenAudio(frequency, MIX_DEFAULT_FORMAT, 2, 4096), "Open mixer");
		res = Mix_AllocateChannels(num_channels);
		log->debug("Allocated {} channels.", res);
		std::fill(channel_volume.begin(), channel_volume.end(), 1.0f);
	}

	AudioManager::~AudioManager(void)
	{
		Mix_CloseAudio();
		Mix_Quit();
	}

	int AudioManager::get_num_active_channels(void) const
	{
		return Mix_Playing(-1);
	}

	bool AudioManager::is_active(int channel) const
	{
		assert(channel < num_channels);
		return Mix_Playing(channel) != 0;
	}

	void AudioManager::set_music_volume(float volume)
	{
		music_volume = volume;
		if (Mix_PlayingMusic())
		{
			Mix_VolumeMusic(static_cast<int>(music_volume * MIX_MAX_VOLUME));
		}
	}

	void AudioManager::play_music(Music* music, int loops) const
	{
		if (Mix_PlayMusic(music->music, loops) == playback_error)
		{
			log->warn("Failed to play music: {}", Mix_GetError());
		}
		Mix_VolumeMusic(static_cast<int>(music_volume * MIX_MAX_VOLUME));
	}

	void AudioManager::pause_music(void) const
	{
		Mix_PauseMusic();
	}

	void AudioManager::stop_music(void) const
	{
		Mix_HaltMusic();
	}

	int AudioManager::play_sample(Sample* sample, int channel, int loops)
	{
		const auto res = Mix_PlayChannel(channel, sample->chunk, loops);
		if (res != playback_error)
		{
			Mix_Volume(res, static_cast<int>(channel_volume[res] * sample_volume * MIX_MAX_VOLUME));
		}
		else
		{
			// Playback failed - no channel available
		}
		return res;
	}

	void AudioManager::stop_sample(int channel)
	{
		Mix_HaltChannel(channel);
	}

	void AudioManager::stop_all(void)
	{
		for (auto channel = 0; channel < num_channels; channel++)
			Mix_HaltChannel(channel);
	}

	void AudioManager::pause_all(void)
	{
		Mix_Pause(-1);
		Mix_PausedMusic();
	}

	void AudioManager::resume_all(void)
	{
		Mix_Resume(-1);
		Mix_ResumeMusic();
	}
}<|endoftext|>


<commit_before>/*
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
*/

#include "application.h"
#include "client.h"
#include "utils.h"

#include "gambc.h"
#include "mylib.h"

#include "Camera.h"

bool startfullscreen = false;
int buttonsize = 64;

Application::Application(CefRefPtr<Client> client, std::shared_ptr<Helper::Paths> paths)
  : INIT_LOGGER(Application),
    _client(client),
    _paths(paths),
    _jsMessageQueue(this),
    _mainWindow(NULL),
    _pluginManager(new PluginManager(this))
{
  // printlog("*****");
  // load and parse config and fill configured plugins
  boost::filesystem::path config_path = _paths->getApplicationDir();
  config_path /= "config.xml";
  _config = new Config(config_path, _pluginManager);
}

Application::~Application()
{

}

void Application::OnContextInitialized()
{
  std::string startup_document = _config->startDocument();

  // test if absolute url with http or https
  if(boost::starts_with(startup_document, "http://") || boost::starts_with(startup_document, "https://"))
  {
    _startupUrl = startup_document;
  }
  else
  {
    std::string www_dir = _paths->getApplicationDir().generic_string();
    www_dir += "/www";
    if(!boost::starts_with(www_dir, "/"))
      www_dir = "/" + www_dir;
    _startupUrl = "file://" + www_dir + "/" + startup_document;
  }

  CefWindowInfo info;
  bool transparent = true;

  bool offscreenrendering = false;
  config()->getBoolPreference("OffScreenRendering", offscreenrendering);

  config()->getBoolPreference("StartFullScreen", startfullscreen);
  config()->getIntPreference("ButtonSize", buttonsize);

  if(offscreenrendering)
  {
    CefRefPtr<Client::RenderHandler> osr_window = createOSRWindow(_mainWindow, _client.get(), transparent);
    _client->setOSRHandler(osr_window);
    /* old
    info.SetTransparentPainting(transparent ? true : false);
    info.SetAsOffScreen(osr_window->handle());
    */
    info.SetAsWindowless(osr_window->handle(), transparent);
  }
  else
  {
    RECT rect;
    GetClientRect(_mainWindow, &rect);
    info.SetAsChild(_mainWindow, rect);
  }

  /*
  RECT r;
  r.left = 0; r.top = 0; r.right = 700; r.bottom = 500;
  info.SetAsChild(_mainWindow, r);
  */

  //TODO: move the settings into config.xml
  CefBrowserSettings browserSettings;
  //browserSettings.developer_tools = STATE_ENABLED;
  browserSettings.file_access_from_file_urls = STATE_ENABLED;
  browserSettings.universal_access_from_file_urls = STATE_ENABLED;
  browserSettings.web_security = STATE_DISABLED;

  // init plugin manager (also create the plugins with onload=true)
  _pluginManager->init();

  // setup gambit
  setup_gambit();

  // Create the browser asynchronously and load the startup url
  LOG_DEBUG(logger()) << "create browser with startup url: '" << _startupUrl << "'";

  // FM: Create the browser syncronously instead and start in full screen mode
  CefBrowserHost::CreateBrowserSync(info, _client.get(), _startupUrl, browserSettings, NULL);
  if (startfullscreen)
	  _client.get()->toggleFullScreen(_client.get()->GetBrowser()->GetHost()->GetWindowHandle(), false);
  ShowWindow(_mainWindow, SW_SHOW );
}

void Application::OnContextCreated( CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefRefPtr<CefV8Context> context )
{
  CefRefPtr<CefV8Value> global = context->GetGlobal();
  _exposedJSObject = CefV8Value::CreateObject(NULL);
  CefRefPtr<CefV8Value> exec = CefV8Value::CreateFunction("exec", this);
  _exposedJSObject->SetValue("exec", exec, V8_PROPERTY_ATTRIBUTE_READONLY);
  global->SetValue("_cordovaNative", _exposedJSObject, V8_PROPERTY_ATTRIBUTE_READONLY);

  _exposedJSObject = CefV8Value::CreateObject(NULL);
  CefRefPtr<CefV8Value> camera = CefV8Value::CreateFunction("camera", this);
  _exposedJSObject->SetValue("camera", camera, V8_PROPERTY_ATTRIBUTE_READONLY);
  global->SetValue("_cameraNative", _exposedJSObject, V8_PROPERTY_ATTRIBUTE_READONLY);

  _exposedJSObject = CefV8Value::CreateObject(NULL);
  CefRefPtr<CefV8Value> eval = CefV8Value::CreateFunction("eval", this);
  _exposedJSObject->SetValue("eval", eval, V8_PROPERTY_ATTRIBUTE_READONLY);
  global->SetValue("_evalNative", _exposedJSObject, V8_PROPERTY_ATTRIBUTE_READONLY);

  _exposedJSObject = CefV8Value::CreateObject(NULL);
  CefRefPtr<CefV8Value> quit = CefV8Value::CreateFunction("quit", this);
  _exposedJSObject->SetValue("quit", quit, V8_PROPERTY_ATTRIBUTE_READONLY);
  global->SetValue("_quitNative", _exposedJSObject, V8_PROPERTY_ATTRIBUTE_READONLY);

  _exposedJSObject = CefV8Value::CreateObject(NULL);
  CefRefPtr<CefV8Value> devtools = CefV8Value::CreateFunction("devtools", this);
  _exposedJSObject->SetValue("devtools", devtools, V8_PROPERTY_ATTRIBUTE_READONLY);
  global->SetValue("_devtoolsNative", _exposedJSObject, V8_PROPERTY_ATTRIBUTE_READONLY);
}

void Application::OnContextReleased( CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefRefPtr<CefV8Context> context )
{
	// cleanup gambit
	cleanup_gambit();
}

CefRefPtr<CefV8Value> callback_func;
CefRefPtr<CefV8Context> callback_context;

void CameraDone(int code, wchar_t* filename)
{
	CefV8ValueList args;
	CefRefPtr<CefV8Value> num = CefV8Value::CreateInt(code);
	CefRefPtr<CefV8Value> str = CefV8Value::CreateString(filename);
	args.push_back(num);
	args.push_back(str);
	callback_func->ExecuteFunctionWithContext(callback_context, NULL, args);
}

bool Application::Execute( const CefString& name, CefRefPtr<CefV8Value> object, const CefV8ValueList& arguments, CefRefPtr<CefV8Value>& retval, CefString& exception )
{
  if(name == "exec" && arguments.size() == 4)
  {
    std::string service = arguments[0]->GetStringValue().ToString();
    std::string action  = arguments[1]->GetStringValue().ToString();
    std::string callbackId = arguments[2]->GetStringValue().ToString();
    std::string rawArgs = arguments[3]->GetStringValue().ToString();
    _pluginManager->exec(service, action, callbackId, rawArgs);
    return true;
  }
  if(name == "camera" && arguments.size() == 1 && arguments[0]->IsFunction())
  {
	  callback_func = arguments[0];
      callback_context = CefV8Context::GetCurrentContext();
	  CameraCapture(startfullscreen, buttonsize, &CameraDone);
	  return true;
  }
  if(name == "eval" && arguments.size() == 1)
  {
	  std::string str = arguments[0]->GetStringValue().ToString();
	  const char* c = str.c_str();
	  //eval_string((char*) c);
	  //std::string res = eval_result;
	  std::string res = eval_string((char*) c);
	  std::wstring reswide = std::wstring(res.begin(), res.end());
	  retval = CefV8Value::CreateString(reswide.c_str());
	  return true;
  }
  if(name == "quit" && arguments.size() == 0)
  {
      CefRefPtr<CefBrowser> browser = _client->GetBrowser();
	  browser->GetHost()->CloseBrowser(false);
	  return true;
  }
  if (name == "devtools" && arguments.size() == 0)
  {
	  CefRefPtr<CefBrowser> browser = _client->GetBrowser();
	  _client->showDevTools(browser);
	  return true;
  }
  return false;
}

void Application::sendJavascript( const std::string& statement )
{
  _jsMessageQueue.addJavaScript(statement);
}

void Application::sendPluginResult( std::shared_ptr<const PluginResult> pluginResult, const std::string& callbackId )
{
  _jsMessageQueue.addPluginResult(pluginResult, callbackId);
}

void Application::runJavaScript( const std::string& js )
{
  _client->runJavaScript(js);
}

void Application::handlePause()
{
  runJavaScript("cordova.fireDocumentEvent('pause');");
}

void Application::handleResume()
{
  runJavaScript("cordova.fireDocumentEvent('resume');");
}
<commit_msg>Random crash bug solved<commit_after>/*
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
*/

#include "application.h"
#include "client.h"
#include "utils.h"

#include "gambc.h"
#include "mylib.h"

#include "Camera.h"

bool startfullscreen = false;
int buttonsize = 64;

Application::Application(CefRefPtr<Client> client, std::shared_ptr<Helper::Paths> paths)
  : INIT_LOGGER(Application),
    _client(client),
    _paths(paths),
    _jsMessageQueue(this),
    _mainWindow(NULL),
    _pluginManager(new PluginManager(this))
{
  // printlog("*****");
  // load and parse config and fill configured plugins
  boost::filesystem::path config_path = _paths->getApplicationDir();
  config_path /= "config.xml";
  _config = new Config(config_path, _pluginManager);
}

Application::~Application()
{

}

void Application::OnContextInitialized()
{
  std::string startup_document = _config->startDocument();

  // test if absolute url with http or https
  if(boost::starts_with(startup_document, "http://") || boost::starts_with(startup_document, "https://"))
  {
    _startupUrl = startup_document;
  }
  else
  {
    std::string www_dir = _paths->getApplicationDir().generic_string();
    www_dir += "/www";
    if(!boost::starts_with(www_dir, "/"))
      www_dir = "/" + www_dir;
    _startupUrl = "file://" + www_dir + "/" + startup_document;
  }

  CefWindowInfo info;
  bool transparent = true;

  bool offscreenrendering = false;
  config()->getBoolPreference("OffScreenRendering", offscreenrendering);

  config()->getBoolPreference("StartFullScreen", startfullscreen);
  config()->getIntPreference("ButtonSize", buttonsize);

  if(offscreenrendering)
  {
    CefRefPtr<Client::RenderHandler> osr_window = createOSRWindow(_mainWindow, _client.get(), transparent);
    _client->setOSRHandler(osr_window);
    /* old
    info.SetTransparentPainting(transparent ? true : false);
    info.SetAsOffScreen(osr_window->handle());
    */
    info.SetAsWindowless(osr_window->handle(), transparent);
  }
  else
  {
    RECT rect;
    GetClientRect(_mainWindow, &rect);
    info.SetAsChild(_mainWindow, rect);
  }

  /*
  RECT r;
  r.left = 0; r.top = 0; r.right = 700; r.bottom = 500;
  info.SetAsChild(_mainWindow, r);
  */

  //TODO: move the settings into config.xml
  CefBrowserSettings browserSettings;
  //browserSettings.developer_tools = STATE_ENABLED;
  browserSettings.file_access_from_file_urls = STATE_ENABLED;
  browserSettings.universal_access_from_file_urls = STATE_ENABLED;
  browserSettings.web_security = STATE_DISABLED;

  // init plugin manager (also create the plugins with onload=true)
  _pluginManager->init();

  // setup gambit
  setup_gambit();

  // Create the browser asynchronously and load the startup url
  LOG_DEBUG(logger()) << "create browser with startup url: '" << _startupUrl << "'";

  // FM: Create the browser syncronously instead and start in full screen mode
  CefBrowserHost::CreateBrowserSync(info, _client.get(), _startupUrl, browserSettings, NULL);
  if (startfullscreen)
	  _client.get()->toggleFullScreen(_client.get()->GetBrowser()->GetHost()->GetWindowHandle(), false);
  ShowWindow(_mainWindow, SW_SHOW );
}

void Application::OnContextCreated( CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefRefPtr<CefV8Context> context )
{
  CefRefPtr<CefV8Value> global = context->GetGlobal();
  _exposedJSObject = CefV8Value::CreateObject(NULL);
  CefRefPtr<CefV8Value> exec = CefV8Value::CreateFunction("exec", this);
  _exposedJSObject->SetValue("exec", exec, V8_PROPERTY_ATTRIBUTE_READONLY);
  global->SetValue("_cordovaNative", _exposedJSObject, V8_PROPERTY_ATTRIBUTE_READONLY);

  _exposedJSObject = CefV8Value::CreateObject(NULL);
  CefRefPtr<CefV8Value> camera = CefV8Value::CreateFunction("camera", this);
  _exposedJSObject->SetValue("camera", camera, V8_PROPERTY_ATTRIBUTE_READONLY);
  global->SetValue("_cameraNative", _exposedJSObject, V8_PROPERTY_ATTRIBUTE_READONLY);

  _exposedJSObject = CefV8Value::CreateObject(NULL);
  CefRefPtr<CefV8Value> eval = CefV8Value::CreateFunction("eval", this);
  _exposedJSObject->SetValue("eval", eval, V8_PROPERTY_ATTRIBUTE_READONLY);
  global->SetValue("_evalNative", _exposedJSObject, V8_PROPERTY_ATTRIBUTE_READONLY);

  _exposedJSObject = CefV8Value::CreateObject(NULL);
  CefRefPtr<CefV8Value> quit = CefV8Value::CreateFunction("quit", this);
  _exposedJSObject->SetValue("quit", quit, V8_PROPERTY_ATTRIBUTE_READONLY);
  global->SetValue("_quitNative", _exposedJSObject, V8_PROPERTY_ATTRIBUTE_READONLY);

  _exposedJSObject = CefV8Value::CreateObject(NULL);
  CefRefPtr<CefV8Value> devtools = CefV8Value::CreateFunction("devtools", this);
  _exposedJSObject->SetValue("devtools", devtools, V8_PROPERTY_ATTRIBUTE_READONLY);
  global->SetValue("_devtoolsNative", _exposedJSObject, V8_PROPERTY_ATTRIBUTE_READONLY);
}

void Application::OnContextReleased( CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefRefPtr<CefV8Context> context )
{
	// cleanup gambit
	//cleanup_gambit();
}

CefRefPtr<CefV8Value> callback_func;
CefRefPtr<CefV8Context> callback_context;

void CameraDone(int code, wchar_t* filename)
{
	CefV8ValueList args;
	CefRefPtr<CefV8Value> num = CefV8Value::CreateInt(code);
	CefRefPtr<CefV8Value> str = CefV8Value::CreateString(filename);
	args.push_back(num);
	args.push_back(str);
	callback_func->ExecuteFunctionWithContext(callback_context, NULL, args);
}

bool Application::Execute( const CefString& name, CefRefPtr<CefV8Value> object, const CefV8ValueList& arguments, CefRefPtr<CefV8Value>& retval, CefString& exception )
{
  if(name == "exec" && arguments.size() == 4)
  {
    std::string service = arguments[0]->GetStringValue().ToString();
    std::string action  = arguments[1]->GetStringValue().ToString();
    std::string callbackId = arguments[2]->GetStringValue().ToString();
    std::string rawArgs = arguments[3]->GetStringValue().ToString();
    _pluginManager->exec(service, action, callbackId, rawArgs);
    return true;
  }
  if(name == "camera" && arguments.size() == 1 && arguments[0]->IsFunction())
  {
	  callback_func = arguments[0];
      callback_context = CefV8Context::GetCurrentContext();
	  CameraCapture(startfullscreen, buttonsize, &CameraDone);
	  return true;
  }
  if(name == "eval" && arguments.size() == 1)
  {
	  std::string str = arguments[0]->GetStringValue().ToString();
	  const char* c = str.c_str();
	  //eval_string((char*) c);
	  //std::string res = eval_result;
	  std::string res = eval_string((char*) c);
	  std::wstring reswide = std::wstring(res.begin(), res.end());
	  retval = CefV8Value::CreateString(reswide.c_str());
	  return true;
  }
  if(name == "quit" && arguments.size() == 0)
  {
      CefRefPtr<CefBrowser> browser = _client->GetBrowser();
	  browser->GetHost()->CloseBrowser(false);
	  return true;
  }
  if (name == "devtools" && arguments.size() == 0)
  {
	  CefRefPtr<CefBrowser> browser = _client->GetBrowser();
	  _client->showDevTools(browser);
	  return true;
  }
  return false;
}

void Application::sendJavascript( const std::string& statement )
{
  _jsMessageQueue.addJavaScript(statement);
}

void Application::sendPluginResult( std::shared_ptr<const PluginResult> pluginResult, const std::string& callbackId )
{
  _jsMessageQueue.addPluginResult(pluginResult, callbackId);
}

void Application::runJavaScript( const std::string& js )
{
  _client->runJavaScript(js);
}

void Application::handlePause()
{
  runJavaScript("cordova.fireDocumentEvent('pause');");
}

void Application::handleResume()
{
  runJavaScript("cordova.fireDocumentEvent('resume');");
}
<|endoftext|>