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

#include "DeclarationVisitor.h"
#include "ExpressionVisitor.h"
#include "StatementVisitor.h"
#include "ElementVisitor.h"

#include "OOModel/src/elements/FormalArgument.h"
#include "OOModel/src/elements/FormalMetaArgument.h"
#include "OOModel/src/elements/FormalResult.h"
#include "OOModel/src/elements/FormalTypeArgument.h"
#include "OOModel/src/elements/CatchClause.h"
#include "OOModel/src/elements/Enumerator.h"
#include "OOModel/src/elements/MemberInitializer.h"
#include "OOModel/src/expressions/types/PointerTypeExpression.h"
#include "OOModel/src/expressions/types/FunctionTypeExpression.h"
#include "OOModel/src/expressions/types/ArrayTypeExpression.h"
#include "OOModel/src/declarations/Method.h"

using namespace Export;
using namespace OOModel;

namespace CppExport {

SourceFragment* ElementVisitor::visit(FormalArgument* argument)
{
	auto fragment = new CompositeFragment(argument);

	auto pointerTypeExpression = DCast<PointerTypeExpression>(argument->typeExpression());
	if (pointerTypeExpression && DCast<FunctionTypeExpression>(pointerTypeExpression->typeExpression()))
		*fragment << ExpressionVisitor(data()).visitFunctionPointer(pointerTypeExpression, argument->name());
	else
	{
		if (auto arrayTypeExpression = DCast<ArrayTypeExpression>(argument->typeExpression()))
			*fragment << expression(arrayTypeExpression->typeExpression());
		else
			*fragment << expression(argument->typeExpression());

		if (headerVisitor() || argument->isUsedInParentMethod())
			*fragment << " " << argument->nameNode();

		if (DCast<ArrayTypeExpression>(argument->typeExpression()))
			*fragment << "[]";
	}

	if (headerVisitor() && argument->initialValue())
		*fragment << " = " << ExpressionVisitor(data()).visit(argument->initialValue());

	return fragment;
}

SourceFragment* ElementVisitor::visit(FormalMetaArgument* argument)
{
	auto fragment = new CompositeFragment(argument);
	*fragment << argument->nameNode();
	return fragment;
}

SourceFragment* ElementVisitor::visit(FormalResult* result)
{
	auto fragment = new CompositeFragment(result);
	*fragment << expression(result->typeExpression());
	return fragment;
}

SourceFragment* ElementVisitor::visit(FormalTypeArgument* typeArgument)
{
	auto fragment = new CompositeFragment(typeArgument);
	*fragment << "typename " << typeArgument->nameNode();
	return fragment;
}

SourceFragment* ElementVisitor::visit(CatchClause* catchClause)
{
	auto fragment = new CompositeFragment(catchClause);

	required(catchClause, catchClause->exceptionToCatch(), "Exception type to catch");

	*fragment << "catch (";
	if (catchClause->exceptionToCatch()) *fragment << expression(catchClause->exceptionToCatch());
	*fragment << ")";
	*fragment << list(catchClause->body(), StatementVisitor(data()), "body");

	return fragment;
}

SourceFragment* ElementVisitor::visit(Enumerator* enumerator)
{
	auto fragment = new CompositeFragment(enumerator);
	*fragment << enumerator->name();
	if (auto value = enumerator->value())
	{
		*fragment << " = " << expression(value);
	}
	return fragment;
}

SourceFragment* ElementVisitor::visit(MemberInitializer* memberInitializer)
{
	auto fragment = new CompositeFragment(memberInitializer);
	*fragment << expression(memberInitializer->memberReference())
				 << list(memberInitializer->arguments(), ExpressionVisitor(data()), "initializerList");
	return fragment;
}

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

#include "DeclarationVisitor.h"
#include "ExpressionVisitor.h"
#include "StatementVisitor.h"
#include "ElementVisitor.h"

#include "OOModel/src/elements/FormalArgument.h"
#include "OOModel/src/elements/FormalMetaArgument.h"
#include "OOModel/src/elements/FormalResult.h"
#include "OOModel/src/elements/FormalTypeArgument.h"
#include "OOModel/src/elements/CatchClause.h"
#include "OOModel/src/elements/Enumerator.h"
#include "OOModel/src/elements/MemberInitializer.h"
#include "OOModel/src/expressions/types/PointerTypeExpression.h"
#include "OOModel/src/expressions/types/FunctionTypeExpression.h"
#include "OOModel/src/expressions/types/ArrayTypeExpression.h"
#include "OOModel/src/declarations/Method.h"

using namespace Export;
using namespace OOModel;

namespace CppExport {

SourceFragment* ElementVisitor::visit(FormalArgument* argument)
{
	auto fragment = new CompositeFragment(argument);

	auto pointerTypeExpression = DCast<PointerTypeExpression>(argument->typeExpression());
	if (pointerTypeExpression && DCast<FunctionTypeExpression>(pointerTypeExpression->typeExpression()))
		*fragment << ExpressionVisitor(data()).visitFunctionPointer(pointerTypeExpression, argument->name());
	else
	{
		if (auto arrayTypeExpression = DCast<ArrayTypeExpression>(argument->typeExpression()))
			*fragment << expression(arrayTypeExpression->typeExpression());
		else
			*fragment << expression(argument->typeExpression());

		if (headerVisitor() || argument->isUsedInParentMethod())
			*fragment << " " << argument->nameNode();

		if (DCast<ArrayTypeExpression>(argument->typeExpression()))
			*fragment << "[]";
	}

	if (headerVisitor() && argument->initialValue())
		*fragment << " = " << ExpressionVisitor(data()).visit(argument->initialValue());

	return fragment;
}

SourceFragment* ElementVisitor::visit(FormalMetaArgument* argument)
{
	auto fragment = new CompositeFragment(argument);
	*fragment << argument->nameNode();
	return fragment;
}

SourceFragment* ElementVisitor::visit(FormalResult* result)
{
	auto fragment = new CompositeFragment(result);
	*fragment << expression(result->typeExpression());
	return fragment;
}

SourceFragment* ElementVisitor::visit(FormalTypeArgument* typeArgument)
{
	auto fragment = new CompositeFragment(typeArgument);
	*fragment << "typename " << typeArgument->nameNode();
	return fragment;
}

SourceFragment* ElementVisitor::visit(CatchClause* catchClause)
{
	auto fragment = new CompositeFragment(catchClause);

	required(catchClause, catchClause->exceptionToCatch(), "Exception type to catch");

	*fragment << "catch (";
	if (catchClause->exceptionToCatch())
		*fragment << expression(catchClause->exceptionToCatch());
	else
		*fragment << "...";
	*fragment << ")";
	*fragment << list(catchClause->body(), StatementVisitor(data()), "body");

	return fragment;
}

SourceFragment* ElementVisitor::visit(Enumerator* enumerator)
{
	auto fragment = new CompositeFragment(enumerator);
	*fragment << enumerator->name();
	if (auto value = enumerator->value())
	{
		*fragment << " = " << expression(value);
	}
	return fragment;
}

SourceFragment* ElementVisitor::visit(MemberInitializer* memberInitializer)
{
	auto fragment = new CompositeFragment(memberInitializer);
	*fragment << expression(memberInitializer->memberReference())
				 << list(memberInitializer->arguments(), ExpressionVisitor(data()), "initializerList");
	return fragment;
}

}
<|endoftext|>


<commit_before>/*
// Copyright (c) 2015 Pierre Guillot.
// For information on usage and redistribution, and for a DISCLAIMER OF ALL
// WARRANTIES, see the file, "LICENSE.txt," in this distribution.
*/

#include "test.hpp"
#include <iostream>
#include <string>
#include <string.h>
#include <stdio.h>

extern "C"
{
#include "../thread/src/thd.h"
}

using namespace xpd;

static char* test_get_patch_folder(char* location)
{
    size_t size, i;
    if(location)
    {
        size = strlen(location);
        for(i = 0; i < size; ++i)
        {
            if(strncmp(location+i, "/build/", 7) == 0)
            {
                memset(location+i+7, '\0', size-i);
                sprintf(location+i+7, "../test/");
                return location;
            }
            if(strncmp(location+i, "/zpd/", 5) == 0)
            {
                memset(location+i+5, '\0', size-i);
                sprintf(location+i+5, "/test/");
                return location;
            }
            if(strncmp(location+i, "/test/", 6) == 0)
            {
                memset(location+i+6, '\0', size-i);
                return location;
            }
        }
    }
    return NULL;
}

typedef void (*test_method)(void *);

struct dual_instance
{
    instance_test inst1;
    instance_test inst2;
};

void test_post(dual_instance* ins)
{
    thd_thread t1, t2;
    std::cout << "perform tests for console posts...";
    {
        thd_thread_detach(&t1, (thd_thread_method)(&instance_test::test_post), &ins->inst1);
        thd_thread_detach(&t2, (thd_thread_method)(&instance_test::test_post), &ins->inst2);
        thd_thread_join(&t1);
        thd_thread_join(&t2);
    }
    std::cout << "ok\n";
}

void test_binding(dual_instance* ins)
{
    thd_thread t1, t2;
    std::cout << "perform tests for binding and atoms...";
    {
        thd_thread_detach(&t1, (thd_thread_method)(&instance_test::test_message), &ins->inst1);
        thd_thread_detach(&t2, (thd_thread_method)(&instance_test::test_message), &ins->inst2);
        thd_thread_join(&t1);
        thd_thread_join(&t2);
    }
    std::cout << "ok\n";
}

void test_midi(dual_instance* ins)
{
    thd_thread t1, t2;
    std::cout << "perform tests for midi events...";
    {
        thd_thread_detach(&t1, (thd_thread_method)(&instance_test::test_midi), &ins->inst1);
        thd_thread_detach(&t2, (thd_thread_method)(&instance_test::test_midi), &ins->inst2);
        thd_thread_join(&t1);
        thd_thread_join(&t2);
    }
    std::cout << "ok\n";
}

void test_dsp(dual_instance* ins)
{
    thd_thread t1, t2;
    std::cout << "perform tests for dsp...";
    {
        thd_thread_detach(&t1, (thd_thread_method)(&instance_test::test_dsp), &ins->inst1);
        thd_thread_detach(&t2, (thd_thread_method)(&instance_test::test_dsp), &ins->inst2);
        thd_thread_join(&t1);
        thd_thread_join(&t2);
    }
    std::cout << "ok\n";
}

void test_patch(dual_instance* ins)
{
    thd_thread t1, t2;
    std::cout << "perform tests for patch, object & gui...";
    {
        thd_thread_detach(&t1, (thd_thread_method)(&instance_test::test_patch), &ins->inst1);
        thd_thread_detach(&t2, (thd_thread_method)(&instance_test::test_patch), &ins->inst2);
        thd_thread_join(&t1);
        thd_thread_join(&t2);
    }
    std::cout << "ok\n";
}

int main(int argc, char** argv)
{
    dual_instance is;

    thd_thread ta, tb, tc, td, te;
    std::cout << "tests xpd version " << environment::version_major()
    << "." << environment::version_minor()
    << "." << environment::version_bug() << "\n";

    environment::searpath_clear();
    if(argc && argv)
    {
        environment::searchpath_add(test_get_patch_folder(argv[0]));
    }
    else
    {
        std::cout << "no current directory";
        return 0;
    }

    std::cout << "perform tie, symbol and atom...";
    type_test::test_tie();
    type_test::test_symbol();
    type_test::test_atom();
    std::cout << "ok\n";

    thd_thread_detach(&ta, (thd_thread_method)(test_post), &is);
    thd_thread_join(&ta);

    thd_thread_detach(&tb, (thd_thread_method)(test_binding), &is);
    thd_thread_join(&tb);

    thd_thread_detach(&tc, (thd_thread_method)(test_midi), &is);
    thd_thread_join(&tc);

    thd_thread_detach(&td, (thd_thread_method)(test_dsp), &is);
    thd_thread_join(&td);

    thd_thread_detach(&te, (thd_thread_method)(test_patch), &is);
    thd_thread_join(&te);

    return 0;
}<commit_msg>retest<commit_after>/*
// Copyright (c) 2015 Pierre Guillot.
// For information on usage and redistribution, and for a DISCLAIMER OF ALL
// WARRANTIES, see the file, "LICENSE.txt," in this distribution.
*/

#include "test.hpp"
#include <iostream>
#include <string>
#include <string.h>
#include <stdio.h>

extern "C"
{
#include "../thread/src/thd.h"
}

using namespace xpd;

static char* test_get_patch_folder(char* location)
{
    size_t size, i;
    if(location)
    {
        size = strlen(location);
        for(i = 0; i < size; ++i)
        {
            if(strncmp(location+i, "/build/", 7) == 0)
            {
                memset(location+i+7, '\0', size-i);
                sprintf(location+i+7, "../test/");
                return location;
            }
            if(strncmp(location+i, "/zpd/", 5) == 0)
            {
                memset(location+i+5, '\0', size-i);
                sprintf(location+i+5, "/test/");
                return location;
            }
            if(strncmp(location+i, "/test/", 6) == 0)
            {
                memset(location+i+6, '\0', size-i);
                return location;
            }
        }
    }
    return NULL;
}

typedef void (*test_method)(void *);

struct dual_instance
{
    instance_test inst1;
    instance_test inst2;
};

void test_post(dual_instance* ins)
{
    thd_thread t1, t2;
    std::cout << "perform tests for console posts...";
    {
        thd_thread_detach(&t1, (thd_thread_method)(&instance_test::test_post), &ins->inst1);
        thd_thread_detach(&t2, (thd_thread_method)(&instance_test::test_post), &ins->inst2);
        thd_thread_join(&t1);
        thd_thread_join(&t2);
    }
    std::cout << "ok\n";
}

void test_binding(dual_instance* ins)
{
    thd_thread t1, t2;
    std::cout << "perform tests for binding and atoms...";
    {
        thd_thread_detach(&t1, (thd_thread_method)(&instance_test::test_message), &ins->inst1);
        thd_thread_detach(&t2, (thd_thread_method)(&instance_test::test_message), &ins->inst2);
        thd_thread_join(&t1);
        thd_thread_join(&t2);
    }
    std::cout << "ok\n";
}

void test_midi(dual_instance* ins)
{
    thd_thread t1, t2;
    std::cout << "perform tests for midi events...";
    {
        thd_thread_detach(&t1, (thd_thread_method)(&instance_test::test_midi), &ins->inst1);
        thd_thread_detach(&t2, (thd_thread_method)(&instance_test::test_midi), &ins->inst2);
        thd_thread_join(&t1);
        thd_thread_join(&t2);
    }
    std::cout << "ok\n";
}

void test_dsp(dual_instance* ins)
{
    thd_thread t1, t2;
    std::cout << "perform tests for dsp...";
    {
        thd_thread_detach(&t1, (thd_thread_method)(&instance_test::test_dsp), &ins->inst1);
        thd_thread_detach(&t2, (thd_thread_method)(&instance_test::test_dsp), &ins->inst2);
        thd_thread_join(&t1);
        thd_thread_join(&t2);
    }
    std::cout << "ok\n";
}

void test_patch(dual_instance* ins)
{
    thd_thread t1, t2;
    std::cout << "perform tests for patch, object & gui...";
    {
        thd_thread_detach(&t1, (thd_thread_method)(&instance_test::test_patch), &ins->inst1);
        thd_thread_detach(&t2, (thd_thread_method)(&instance_test::test_patch), &ins->inst2);
        thd_thread_join(&t1);
        thd_thread_join(&t2);
    }
    std::cout << "ok\n";
}

int main(int argc, char** argv)
{
    dual_instance is;

    thd_thread ta, tb, tc, td, te;
    std::cout << "tests xpd version " << environment::version_major()
    << "." << environment::version_minor()
    << "." << environment::version_bug() << "\n";

    environment::searpath_clear();
    if(argc && argv)
    {
        std::cout << argv[0];
#ifdef _WIN32
        return 0;
#endif
        environment::searchpath_add(test_get_patch_folder(argv[0]));
    }
    else
    {
        std::cout << "no current directory";
        return 0;
    }

    std::cout << "perform tie, symbol and atom...";
    type_test::test_tie();
    type_test::test_symbol();
    type_test::test_atom();
    std::cout << "ok\n";

    thd_thread_detach(&ta, (thd_thread_method)(test_post), &is);
    thd_thread_join(&ta);

    thd_thread_detach(&tb, (thd_thread_method)(test_binding), &is);
    thd_thread_join(&tb);

    thd_thread_detach(&tc, (thd_thread_method)(test_midi), &is);
    thd_thread_join(&tc);

    thd_thread_detach(&td, (thd_thread_method)(test_dsp), &is);
    thd_thread_join(&td);

    thd_thread_detach(&te, (thd_thread_method)(test_patch), &is);
    thd_thread_join(&te);

    return 0;
}<|endoftext|>


<commit_before>/*******************************
Copyright (c) 2016-2019 Grégoire Angerand

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

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

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

#include "MainWindow.h"

#include <csignal>

#include <editor/events/MainEventHandler.h>
#include <editor/context/EditorContext.h>

#include <yave/graphics/swapchain/Swapchain.h>

using namespace editor;

EditorContext* context = nullptr;
bool debug_instance = false;
bool display_console = false;

static void hide_console() {
#ifdef Y_OS_WIN
	ShowWindow(GetConsoleWindow(), SW_HIDE);
#endif
}

static void crash_handler(int) {
	log_msg("SEGFAULT!");
	Y_TODO(we might want to save whatever we can here)
}

static void setup_handlers() {
	std::signal(SIGSEGV, crash_handler);
	y_debug_assert([] { log_msg("Debug assert enabled"); return true; }());
	perf::set_output_file("perfdump.json");
}

static void parse_args(int argc, char** argv) {
	for(std::string_view arg : core::ArrayView<const char*>(argv, argc)) {
		if(arg == "--nodebug") {
			debug_instance = false;
		}
		if(arg == "--console") {
			display_console = true;
		}
	}

	if(!display_console) {
		hide_console();
	}
}

static void setup_logger() {
	set_log_callback([](std::string_view msg, Log type, void*) {
			if(context) {
				context->log_message(msg, type);
			}
			return !display_console;
		});
}

static Instance create_instance() {
	if(!debug_instance) {
		log_msg("Vulkan debugging disabled", Log::Warning);
	}
	return Instance(debug_instance ? DebugParams::debug() : DebugParams::none());
}

int main(int argc, char** argv) {
	parse_args(argc, argv);
	setup_handlers();
	setup_logger();

	Instance instance = create_instance();

	Device device(instance);
	EditorContext ctx(&device);
	context = &ctx;

	MainWindow window(&ctx);
	window.set_event_handler(std::make_unique<MainEventHandler>());
	window.show();

	for(;;) {
		if(!window.update()) {
			if(ctx.ui().confirm("Quit ?")) {
				break;
			} else {
				window.show();
			}
		}

		Swapchain* swapchain = window.swapchain();
		if(swapchain && swapchain->is_valid()) {
			FrameToken frame = swapchain->next_frame();
			CmdBufferRecorder recorder(device.create_disposable_cmd_buffer());

			ctx.ui().paint(recorder, frame);

			window.present(recorder, frame);
		}

		ctx.flush_deferred();
	}

	return 0;
}

<commit_msg>Fixed default argument values<commit_after>/*******************************
Copyright (c) 2016-2019 Grégoire Angerand

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

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

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

#include "MainWindow.h"

#include <csignal>

#include <editor/events/MainEventHandler.h>
#include <editor/context/EditorContext.h>

#include <yave/graphics/swapchain/Swapchain.h>

using namespace editor;

EditorContext* context = nullptr;

#ifdef Y_DEBUG
bool display_console = true;
bool debug_instance = true;
#else
bool display_console = false;
bool debug_instance = false;
#endif

static void hide_console() {
#ifdef Y_OS_WIN
	ShowWindow(GetConsoleWindow(), SW_HIDE);
#endif
}

static void crash_handler(int) {
	log_msg("SEGFAULT!");
	Y_TODO(we might want to save whatever we can here)
}

static void setup_handlers() {
	std::signal(SIGSEGV, crash_handler);
	y_debug_assert([] { log_msg("Debug assert enabled"); return true; }());
	perf::set_output_file("perfdump.json");
}

static void parse_args(int argc, char** argv) {
	for(std::string_view arg : core::ArrayView<const char*>(argv, argc)) {
		if(arg == "--nodebug") {
			debug_instance = false;
		}
		if(arg == "--debug") {
			debug_instance = true;
		}
		if(arg == "--console") {
			display_console = true;
		}
	}

	if(!display_console) {
		hide_console();
	}
	y_debug_assert([] { log_msg("Asserts enabled."); return true; }());
}

static void setup_logger() {
	set_log_callback([](std::string_view msg, Log type, void*) {
			if(context) {
				context->log_message(msg, type);
			}
			return !display_console;
		});
}

static Instance create_instance() {
	if(!debug_instance) {
		log_msg("Vulkan debugging disabled", Log::Warning);
	}
	return Instance(debug_instance ? DebugParams::debug() : DebugParams::none());
}

int main(int argc, char** argv) {
	parse_args(argc, argv);
	setup_handlers();
	setup_logger();

	Instance instance = create_instance();

	Device device(instance);
	EditorContext ctx(&device);
	context = &ctx;

	MainWindow window(&ctx);
	window.set_event_handler(std::make_unique<MainEventHandler>());
	window.show();

	for(;;) {
		if(!window.update()) {
			if(ctx.ui().confirm("Quit ?")) {
				break;
			} else {
				window.show();
			}
		}

		Swapchain* swapchain = window.swapchain();
		if(swapchain && swapchain->is_valid()) {
			FrameToken frame = swapchain->next_frame();
			CmdBufferRecorder recorder(device.create_disposable_cmd_buffer());

			ctx.ui().paint(recorder, frame);

			window.present(recorder, frame);
		}

		ctx.flush_deferred();
	}

	return 0;
}

<|endoftext|>


<commit_before>/*******************************
Copyright (c) 2016-2020 Grégoire Angerand

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

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

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

#include <y/test/test.h>

#include <y/utils/log.h>

using namespace y;

#if 0
#include <y/core/Chrono.h>
#include <y/core/DenseMap.h>
#include <y/utils/format.h>
#include <unordered_map>

template<typename Map>
int bench(int max_key) {
	int sum = 0;

	double runs_d = 1000000.0 / max_key;
	const usize runs = runs_d < 1.0 ? 1 : usize(runs_d);

	for(usize r = 0; r != runs; ++r) {
		Map map;
		for(int i = 0; i != max_key; ++i) {
			map.insert({i, i * 2});
		}

		usize map_size = max_key;
		unused(map_size);
		for(int i = 0; i < max_key; i += 1 + (i / 8)) {
			const auto it = map.find(i);
			y_debug_assert(it != map.end());
			map.erase(it);
			--map_size;
			y_debug_assert(map_size == map.size());
		}

		for(auto&& [k, v] : map) {
			sum += k;
			sum += v / 2;
		}
	}
	return sum;
}
#endif

int main() {
	const bool ok = test::run_tests();

	if(ok) {
		log_msg("All tests OK\n");
	} else {
		log_msg("Tests failed\n", Log::Error);
	}

#if 0
	for(int max_key = 1; max_key < 1024 * 1024; max_key *= 2) {
		log_msg(fmt("Size: %", max_key), Log::Debug);
		{
			core::DebugTimer _("ExternalDenseMap");
			bench<core::ExternalDenseMap<int, int>>(max_key);
		}

		{
			core::DebugTimer _("  StableDenseMap");
			bench<core::StableDenseMap<int, int>>(max_key);
		}

		{
			core::DebugTimer _("        DenseMap");
			bench<core::DenseMap<int, int>>(max_key);
		}

		{
			core::DebugTimer _("   unordered_map");
			bench<std::unordered_map<int, int>>(max_key);
		}
	}
#endif

	return 0;
}

<commit_msg>benches<commit_after>/*******************************
Copyright (c) 2016-2020 Grégoire Angerand

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

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

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

#include <y/test/test.h>

#include <y/utils/log.h>

using namespace y;

#if 1
#include <y/core/Chrono.h>
#include <y/core/Vector.h>
#include <y/core/DenseMap.h>
#include <y/utils/format.h>

#include <unordered_map>
#include <numeric>
#include <cmath>

template<template<typename...> typename Map>
static auto bench_fill(usize count = 100000) {
	Map<usize, usize> map;
	for(usize i = 0; i != count; ++i) {
		map.insert({i, i * 2});
	}
	return map;
}

template<template<typename...> typename Map>
static auto bench_reserve_fill(usize count = 10000000) {
	Map<usize, usize> map;
	map.reserve(count);
	for(usize i = 0; i != count; ++i) {
		map.insert({i, i * 2});
	}
	return map;
}

template<template<typename...> typename Map>
static auto bench_fill_iter_50(usize count = 100000) {
	Map<usize, usize> map;
	for(usize i = 0; i != count; ++i) {
		map.insert({i, i * 2});
	}

	usize a = 0;
	for(usize i = 0; i != 25; ++i) {
		for(const auto& [k, v] : map) {
			a += k * i;
		}
	}
	map.insert({a, a});

	a = 0;
	for(usize i = 0; i != 25; ++i) {
		for(const auto& [k, v] : map) {
			a += v * i;
		}
	}
	map.insert({a, a});

	return map;
}

template<template<typename...> typename Map>
static auto bench_fill_erase_all(usize count = 100000) {
	Map<usize, usize> map;
	for(usize i = 0; i != count; ++i) {
		map.insert({i, i * 2});
	}
	for(usize i = 0; i != count; ++i) {
		map.erase(map.find(i));
	}
	return map;
}

template<template<typename...> typename Map>
static auto bench_fill_erase_refill(usize count = 100000) {
	Map<usize, usize> map;
	for(usize i = 0; i != count; ++i) {
		map.insert({i, i * 2});
	}
	for(usize i = 0; i != count; ++i) {
		map.erase(map.find(i));
	}
	for(usize i = 0; i != count; ++i) {
		map.insert({i * 2, i});
	}
	return map;
}

template<template<typename...> typename Map>
static auto bench_fill_find_all_50_50(usize count = 100000) {
	Map<usize, usize> map;
	for(usize i = 0; i != count; ++i) {
		map.insert({i * 2, i});
	}

	usize sum = 0;
	for(usize i = 0; i != count * 2; ++i) {
		if(const auto& it = map.find(i); it != map.end()) {
			sum += i;
		}
	}
	map.insert({sum, sum});
	return map;
}

using result_type = core::Vector<std::tuple<const char*, double, usize>>;

template<template<typename...> typename Map>
result_type bench_implementation() {
	result_type results;

#define BENCH_ONE(func)															\
	do {																		\
		core::Chrono chrono;													\
		for(usize count = 1; true; ++count) {									\
			const usize res = func<Map>().size();								\
			const auto elapsed = chrono.elapsed();								\
			if(chrono.elapsed().to_secs() >= 1.0) {								\
				results.emplace_back(#func, elapsed.to_secs() / count, res);	\
				break;															\
			}																	\
		}																		\
	} while(false)

	BENCH_ONE(bench_fill);
	BENCH_ONE(bench_reserve_fill);
	BENCH_ONE(bench_fill_iter_50);
	BENCH_ONE(bench_fill_erase_all);
	BENCH_ONE(bench_fill_erase_refill);
	BENCH_ONE(bench_fill_find_all_50_50);

#undef BENCH_ONE

	return results;
}

#endif

int main() {
	const bool ok = test::run_tests();

	if(ok) {
		log_msg("All tests OK\n");
	} else {
		log_msg("Tests failed\n", Log::Error);
	}

#if 1
	core::Vector<std::pair<const char*, result_type>> results;
	log_msg("Benching...");
	results.emplace_back("ExternalDenseMap", bench_implementation<core::ExternalDenseMap>());
	results.emplace_back("DenseMap", bench_implementation<core::DenseMap>());
	results.emplace_back("std::unordered_map", bench_implementation<std::unordered_map>());
	log_msg("Done\n");

	for(const auto& impl : results) {
		const usize result_count = impl.second.size();
		log_msg(fmt("%:", impl.first), Log::Perf);
		for(usize r = 0; r != result_count; ++r) {
			const auto res = impl.second[r];
			core::String line = "    ";
			line += std::get<0>(res);
			while(line.size() != 32) {
				line += " ";
			}
			fmt_into(line, "% ms", std::get<1>(res));

			core::Vector<double> times;
			for(const auto& i : results) {
				times << std::get<1>(i.second[r]);
			}
			std::sort(times.begin(), times.end());

			const double res_time = std::get<1>(res);
			if(times[0] == res_time) {
				line += "*";
				if(times[1] * 0.5 > res_time) {
					line += "*";
				}
			}
			log_msg(line, Log::Perf);
		}
	}

#endif

	return 0;
}

<|endoftext|>


<commit_before>/*
===========================================================================
Daemon BSD Source Code
Copyright (c) 2013-2014, Daemon Developers
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.
    * Neither the name of the <organization> nor the
      names of its contributors may be used to endorse or promote products
      derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
===========================================================================
*/

#include "AudioPrivate.h"

namespace Audio {

    // Structures to keep the state of entities we were given
    struct entityData_t {
        vec3_t position;
        vec3_t velocity;
        float occlusion;
    };
    static entityData_t entities[MAX_GENTITIES];
    static int listenerEntity = -1;

    // Keep Entitymitters in an array because there is at most one per entity.
    static std::shared_ptr<Emitter> entityEmitters[MAX_GENTITIES];

    // Position Emitters can be reused so we keep the list of all of them
    // this is not very efficient but we cannot have more position emitters
    // than sounds, that is about 128
    static std::vector<std::shared_ptr<PositionEmitter>> posEmitters;

    // There is a single LocalEmitter
    static std::shared_ptr<Emitter> localEmitter;

    static const vec3_t origin = {0.0f, 0.0f, 0.0f};

    static Cvar::Range<Cvar::Cvar<float>> dopplerExaggeration("audio.dopplerExaggeration", "controls the pitch change of the doppler effect", Cvar::ARCHIVE, 0.4, 0.0, 1.0);
    static Cvar::Range<Cvar::Cvar<float>> reverbIntensity("audio.reverbIntensity", "the intensity of the reverb effects", Cvar::ARCHIVE, 1.0, 0.0, 1.0);

    struct ReverbSlot {
        AL::EffectSlot* effect;
        std::string name;
        float ratio;
        float askedRatio;
    };
    ReverbSlot reverbSlots[N_REVERB_SLOTS];
    bool testingReverb = false;

    static bool initialized = false;

    void InitEmitters() {
        if (initialized) {
            return;
        }

        AL::Effect effectParams;
        effectParams.ApplyReverbPreset(*AL::GetPresetByName("generic"));

        for (int i = 0; i < N_REVERB_SLOTS; i++) {
            reverbSlots[i].effect = new AL::EffectSlot();
            reverbSlots[i].effect->SetEffect(effectParams);
            reverbSlots[i].effect->SetGain(1.0f);
            reverbSlots[i].name = "generic";
            reverbSlots[i].ratio = 1.0f;
            reverbSlots[i].askedRatio = 1.0f;
        }

        AL::SetInverseDistanceModel();
        AL::SetSpeedOfSound(SPEED_OF_SOUND);

        localEmitter = std::make_shared<LocalEmitter>();

        initialized = true;
    }

    void ShutdownEmitters() {
        if (not initialized) {
            return;
        }

        localEmitter = nullptr;

        for (int i = 0; i < N_REVERB_SLOTS; i++) {
            delete reverbSlots[i].effect;
            reverbSlots[i].effect = nullptr;
        }

        for (int i = 0; i < MAX_GENTITIES; i++) {
            if (entityEmitters[i]) {
                entityEmitters[i] = nullptr;
            }
        }

        posEmitters.clear();

        testingReverb = false;

        initialized = false;
    }

    void UpdateEmitters() {
        localEmitter->Update();

        // Both PositionEmitters and EntityEmitters are ref-counted.
        // If we hold the only reference to them then no sound is still using
        // the Emitter that can be destroyed.
        for (int i = 0; i < MAX_GENTITIES; i++) {
            auto emitter = entityEmitters[i];

            if (not emitter) {
                continue;
            }

            emitter->Update();

            // No sound is using this emitter, destroy it
            if (emitter.unique()) {
                entityEmitters[i] = nullptr;
            }
        }

        for (auto it = posEmitters.begin(); it != posEmitters.end();){
            (*it)->Update();

            // No sound is using this emitter, destroy it
            if ((*it).unique()) {
                it = posEmitters.erase(it);
            } else {
                it ++;
            }
        }

        float reverbVolume = reverbIntensity.Get();
        for (int i = 0; i < N_REVERB_SLOTS; i++) {
            reverbSlots[i].effect->SetGain(reverbSlots[i].ratio * reverbVolume);
        }

        AL::SetDopplerExaggerationFactor(dopplerExaggeration.Get());
    }

    void UpdateListenerEntity(int entityNum, const vec3_t orientation[3]) {
        listenerEntity = entityNum;

        AL::SetListenerPosition(entities[listenerEntity].position);
        AL::SetListenerVelocity(entities[listenerEntity].velocity);
        AL::SetListenerOrientation(orientation);
    }

    std::shared_ptr<Emitter> GetEmitterForEntity(int entityNum) {
        if (not entityEmitters[entityNum]) {
            entityEmitters[entityNum] = std::make_shared<EntityEmitter>(entityNum);
        }

        return entityEmitters[entityNum];
    }

    std::shared_ptr<Emitter> GetEmitterForPosition(const vec3_t position) {
        for (auto emitter : posEmitters) {
            if (Distance(emitter->GetPosition(), position) <= 1.0f) {
                return emitter;
            }
        }
        auto emitter = std::make_shared<PositionEmitter>(position);
        posEmitters.push_back(emitter);
        return emitter;
    }

    std::shared_ptr<Emitter> GetLocalEmitter() {
        return localEmitter;
    }

    void UpdateRegisteredEntityPosition(int entityNum, const vec3_t position) {
        VectorCopy(position, entities[entityNum].position);
    }

    void UpdateRegisteredEntityVelocity(int entityNum, const vec3_t velocity) {
        VectorCopy(velocity, entities[entityNum].velocity);
    }

    void UpdateReverbSlot(int slotNum, std::string name, float ratio) {
        auto& slot = reverbSlots[slotNum];

        if (not testingReverb and name == "none") {
            ratio = 0.0f;
            name = slot.name;
        }

        if (name != slot.name) {
            if (not testingReverb) {
                auto preset = AL::GetPresetByName(name);

                if (not preset) {
                    audioLogs.Warn("Reverb preset '%s' doesn't exist.", name);
                    return;
                }

                AL::Effect effectParams;
                effectParams.ApplyReverbPreset(*preset);
                slot.effect->SetEffect(effectParams);
            }

            slot.name = std::move(name);
        }

        if (not testingReverb) {
            slot.ratio = ratio;
        }
        slot.askedRatio = ratio;
    }

    // Utility functions for emitters

    // TODO avoid more unnecessary al calls

    void MakeLocal(AL::Source& source) {
        source.SetRelative(true);
        source.SetPosition(origin);
        source.SetVelocity(origin);

        for (int i = 0; i < N_REVERB_SLOTS; i++) {
            source.DisableEffect(i);
        }
    }

    void Make3D(AL::Source& source, const vec3_t position, const vec3_t velocity) {
        source.SetRelative(false);
        source.SetPosition(position);
        source.SetVelocity(velocity);

        for (int i = 0; i < N_REVERB_SLOTS; i++) {
            source.EnableEffect(i, *reverbSlots[i].effect);
        }
    }

    // Implementation for Emitter

    Emitter::Emitter() {
    }

    Emitter::~Emitter() {
    }

    void Emitter::SetupSound(Sound& sound) {
        sound.GetSource().SetReferenceDistance(120.0f);
        InternalSetupSound(sound);
        UpdateSound(sound);
    }

    // Implementation of EntityEmitter

    EntityEmitter::EntityEmitter(int entityNum): entityNum(entityNum) {
    }

    EntityEmitter::~EntityEmitter(){
    }

    void EntityEmitter::Update() {
        // TODO
    }

    void EntityEmitter::UpdateSound(Sound& sound) {
        AL::Source& source = sound.GetSource();

        if (entityNum == listenerEntity) {
            MakeLocal(source);
        } else {
            Make3D(source, entities[entityNum].position, entities[entityNum].velocity);
        }
    }

    void EntityEmitter::InternalSetupSound(Sound& sound) {
        AL::Source& source = sound.GetSource();

        Make3D(source, entities[entityNum].position, entities[entityNum].velocity);
    }

    // Implementation of PositionEmitter

    PositionEmitter::PositionEmitter(const vec3_t position){
        VectorCopy(position, this->position);
    }

    PositionEmitter::~PositionEmitter() {
    }

    void PositionEmitter::Update() {
        //TODO
    }

    void PositionEmitter::UpdateSound(Sound& sound) {
        AL::Source& source = sound.GetSource();

        Make3D(source, position, origin);
    }

    void PositionEmitter::InternalSetupSound(Sound& sound) {
        AL::Source& source = sound.GetSource();

        Make3D(source, position, origin);
    }

    const vec3_t& PositionEmitter::GetPosition() const {
        return position;
    }

    // Implementation of LocalEmitter

    LocalEmitter::LocalEmitter() {
    }

    LocalEmitter::~LocalEmitter() {
    }

    void LocalEmitter::Update() {
    }

    void LocalEmitter::UpdateSound(Sound&) {
    }

    void LocalEmitter::InternalSetupSound(Sound& sound) {
        AL::Source& source = sound.GetSource();

        MakeLocal(source);
    }

    class TestReverbCmd : public Cmd::StaticCmd {
        public:
            TestReverbCmd(): StaticCmd("testReverb", Cmd::AUDIO, N_("Tests a reverb preset.")) {
            }

            virtual void Run(const Cmd::Args& args) const OVERRIDE {
                if (args.Argc() != 2) {
                    PrintUsage(args, "stop", "stop the test");
                    PrintUsage(args, "[preset name]", "tests the reverb preset.");
                    return;
                } else {
                    if (args.Argv(1) == "stop") {
                        StopTest();
                    } else {
                        StartTest(args);
                    }
                }
            }

            Cmd::CompletionResult Complete(int argNum, const Cmd::Args&, Str::StringRef prefix) const OVERRIDE {
                if (argNum != 1) {
                    return {};
                }
                std::vector<std::string> presets = AL::ListPresetNames();
                std::sort(presets.begin(), presets.end());

                Cmd::CompletionResult res;

                res.push_back({"stop", "stops the test"});
                res.push_back({"none", "no effect at all"});

                for (auto& name: presets) {
                    if (Str::IsPrefix(prefix, name)) {
                        res.push_back({std::move(name), ""});
                    }
                }

                return res;
            }

        private:
            void StartTest(const Cmd::Args& args) const {
                Str::StringRef name = args.Argv(1);

                if (name == "none") {
                    testingReverb = true;
                    for (int i = 0; i < N_REVERB_SLOTS; i++) {
                        reverbSlots[i].effect->SetGain(0.0f);
                    }
                    return;
                }

                auto preset = AL::GetPresetByName(name);

                if (not preset) {
                    Print("Reverb preset '%s' doesn't exist.", name);
                    return;
                }

                AL::Effect effectParams;
                effectParams.ApplyReverbPreset(*preset);

                testingReverb = true;
                for (int i = 1; i < N_REVERB_SLOTS; i++) {
                    reverbSlots[i].effect->SetGain(0.0f);
                }

                reverbSlots[0].ratio = 0.5f;
                reverbSlots[0].effect->SetEffect(effectParams);
            }

            void StopTest() const {
                testingReverb = false;
                for (int i = 0; i < N_REVERB_SLOTS; i++) {
                    std::string name = std::move(reverbSlots[i].name);
                    UpdateReverbSlot(i, std::move(name), reverbSlots[i].askedRatio);
                }
            }
    };
    static TestReverbCmd testReverbRegistration;

}
<commit_msg>Fix the completion of /testReverb<commit_after>/*
===========================================================================
Daemon BSD Source Code
Copyright (c) 2013-2014, Daemon Developers
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.
    * Neither the name of the <organization> nor the
      names of its contributors may be used to endorse or promote products
      derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
===========================================================================
*/

#include "AudioPrivate.h"

namespace Audio {

    // Structures to keep the state of entities we were given
    struct entityData_t {
        vec3_t position;
        vec3_t velocity;
        float occlusion;
    };
    static entityData_t entities[MAX_GENTITIES];
    static int listenerEntity = -1;

    // Keep Entitymitters in an array because there is at most one per entity.
    static std::shared_ptr<Emitter> entityEmitters[MAX_GENTITIES];

    // Position Emitters can be reused so we keep the list of all of them
    // this is not very efficient but we cannot have more position emitters
    // than sounds, that is about 128
    static std::vector<std::shared_ptr<PositionEmitter>> posEmitters;

    // There is a single LocalEmitter
    static std::shared_ptr<Emitter> localEmitter;

    static const vec3_t origin = {0.0f, 0.0f, 0.0f};

    static Cvar::Range<Cvar::Cvar<float>> dopplerExaggeration("audio.dopplerExaggeration", "controls the pitch change of the doppler effect", Cvar::ARCHIVE, 0.4, 0.0, 1.0);
    static Cvar::Range<Cvar::Cvar<float>> reverbIntensity("audio.reverbIntensity", "the intensity of the reverb effects", Cvar::ARCHIVE, 1.0, 0.0, 1.0);

    struct ReverbSlot {
        AL::EffectSlot* effect;
        std::string name;
        float ratio;
        float askedRatio;
    };
    ReverbSlot reverbSlots[N_REVERB_SLOTS];
    bool testingReverb = false;

    static bool initialized = false;

    void InitEmitters() {
        if (initialized) {
            return;
        }

        AL::Effect effectParams;
        effectParams.ApplyReverbPreset(*AL::GetPresetByName("generic"));

        for (int i = 0; i < N_REVERB_SLOTS; i++) {
            reverbSlots[i].effect = new AL::EffectSlot();
            reverbSlots[i].effect->SetEffect(effectParams);
            reverbSlots[i].effect->SetGain(1.0f);
            reverbSlots[i].name = "generic";
            reverbSlots[i].ratio = 1.0f;
            reverbSlots[i].askedRatio = 1.0f;
        }

        AL::SetInverseDistanceModel();
        AL::SetSpeedOfSound(SPEED_OF_SOUND);

        localEmitter = std::make_shared<LocalEmitter>();

        initialized = true;
    }

    void ShutdownEmitters() {
        if (not initialized) {
            return;
        }

        localEmitter = nullptr;

        for (int i = 0; i < N_REVERB_SLOTS; i++) {
            delete reverbSlots[i].effect;
            reverbSlots[i].effect = nullptr;
        }

        for (int i = 0; i < MAX_GENTITIES; i++) {
            if (entityEmitters[i]) {
                entityEmitters[i] = nullptr;
            }
        }

        posEmitters.clear();

        testingReverb = false;

        initialized = false;
    }

    void UpdateEmitters() {
        localEmitter->Update();

        // Both PositionEmitters and EntityEmitters are ref-counted.
        // If we hold the only reference to them then no sound is still using
        // the Emitter that can be destroyed.
        for (int i = 0; i < MAX_GENTITIES; i++) {
            auto emitter = entityEmitters[i];

            if (not emitter) {
                continue;
            }

            emitter->Update();

            // No sound is using this emitter, destroy it
            if (emitter.unique()) {
                entityEmitters[i] = nullptr;
            }
        }

        for (auto it = posEmitters.begin(); it != posEmitters.end();){
            (*it)->Update();

            // No sound is using this emitter, destroy it
            if ((*it).unique()) {
                it = posEmitters.erase(it);
            } else {
                it ++;
            }
        }

        float reverbVolume = reverbIntensity.Get();
        for (int i = 0; i < N_REVERB_SLOTS; i++) {
            reverbSlots[i].effect->SetGain(reverbSlots[i].ratio * reverbVolume);
        }

        AL::SetDopplerExaggerationFactor(dopplerExaggeration.Get());
    }

    void UpdateListenerEntity(int entityNum, const vec3_t orientation[3]) {
        listenerEntity = entityNum;

        AL::SetListenerPosition(entities[listenerEntity].position);
        AL::SetListenerVelocity(entities[listenerEntity].velocity);
        AL::SetListenerOrientation(orientation);
    }

    std::shared_ptr<Emitter> GetEmitterForEntity(int entityNum) {
        if (not entityEmitters[entityNum]) {
            entityEmitters[entityNum] = std::make_shared<EntityEmitter>(entityNum);
        }

        return entityEmitters[entityNum];
    }

    std::shared_ptr<Emitter> GetEmitterForPosition(const vec3_t position) {
        for (auto emitter : posEmitters) {
            if (Distance(emitter->GetPosition(), position) <= 1.0f) {
                return emitter;
            }
        }
        auto emitter = std::make_shared<PositionEmitter>(position);
        posEmitters.push_back(emitter);
        return emitter;
    }

    std::shared_ptr<Emitter> GetLocalEmitter() {
        return localEmitter;
    }

    void UpdateRegisteredEntityPosition(int entityNum, const vec3_t position) {
        VectorCopy(position, entities[entityNum].position);
    }

    void UpdateRegisteredEntityVelocity(int entityNum, const vec3_t velocity) {
        VectorCopy(velocity, entities[entityNum].velocity);
    }

    void UpdateReverbSlot(int slotNum, std::string name, float ratio) {
        auto& slot = reverbSlots[slotNum];

        if (not testingReverb and name == "none") {
            ratio = 0.0f;
            name = slot.name;
        }

        if (name != slot.name) {
            if (not testingReverb) {
                auto preset = AL::GetPresetByName(name);

                if (not preset) {
                    audioLogs.Warn("Reverb preset '%s' doesn't exist.", name);
                    return;
                }

                AL::Effect effectParams;
                effectParams.ApplyReverbPreset(*preset);
                slot.effect->SetEffect(effectParams);
            }

            slot.name = std::move(name);
        }

        if (not testingReverb) {
            slot.ratio = ratio;
        }
        slot.askedRatio = ratio;
    }

    // Utility functions for emitters

    // TODO avoid more unnecessary al calls

    void MakeLocal(AL::Source& source) {
        source.SetRelative(true);
        source.SetPosition(origin);
        source.SetVelocity(origin);

        for (int i = 0; i < N_REVERB_SLOTS; i++) {
            source.DisableEffect(i);
        }
    }

    void Make3D(AL::Source& source, const vec3_t position, const vec3_t velocity) {
        source.SetRelative(false);
        source.SetPosition(position);
        source.SetVelocity(velocity);

        for (int i = 0; i < N_REVERB_SLOTS; i++) {
            source.EnableEffect(i, *reverbSlots[i].effect);
        }
    }

    // Implementation for Emitter

    Emitter::Emitter() {
    }

    Emitter::~Emitter() {
    }

    void Emitter::SetupSound(Sound& sound) {
        sound.GetSource().SetReferenceDistance(120.0f);
        InternalSetupSound(sound);
        UpdateSound(sound);
    }

    // Implementation of EntityEmitter

    EntityEmitter::EntityEmitter(int entityNum): entityNum(entityNum) {
    }

    EntityEmitter::~EntityEmitter(){
    }

    void EntityEmitter::Update() {
        // TODO
    }

    void EntityEmitter::UpdateSound(Sound& sound) {
        AL::Source& source = sound.GetSource();

        if (entityNum == listenerEntity) {
            MakeLocal(source);
        } else {
            Make3D(source, entities[entityNum].position, entities[entityNum].velocity);
        }
    }

    void EntityEmitter::InternalSetupSound(Sound& sound) {
        AL::Source& source = sound.GetSource();

        Make3D(source, entities[entityNum].position, entities[entityNum].velocity);
    }

    // Implementation of PositionEmitter

    PositionEmitter::PositionEmitter(const vec3_t position){
        VectorCopy(position, this->position);
    }

    PositionEmitter::~PositionEmitter() {
    }

    void PositionEmitter::Update() {
        //TODO
    }

    void PositionEmitter::UpdateSound(Sound& sound) {
        AL::Source& source = sound.GetSource();

        Make3D(source, position, origin);
    }

    void PositionEmitter::InternalSetupSound(Sound& sound) {
        AL::Source& source = sound.GetSource();

        Make3D(source, position, origin);
    }

    const vec3_t& PositionEmitter::GetPosition() const {
        return position;
    }

    // Implementation of LocalEmitter

    LocalEmitter::LocalEmitter() {
    }

    LocalEmitter::~LocalEmitter() {
    }

    void LocalEmitter::Update() {
    }

    void LocalEmitter::UpdateSound(Sound&) {
    }

    void LocalEmitter::InternalSetupSound(Sound& sound) {
        AL::Source& source = sound.GetSource();

        MakeLocal(source);
    }

    class TestReverbCmd : public Cmd::StaticCmd {
        public:
            TestReverbCmd(): StaticCmd("testReverb", Cmd::AUDIO, N_("Tests a reverb preset.")) {
            }

            virtual void Run(const Cmd::Args& args) const OVERRIDE {
                if (args.Argc() != 2) {
                    PrintUsage(args, "stop", "stop the test");
                    PrintUsage(args, "[preset name]", "tests the reverb preset.");
                    return;
                } else {
                    if (args.Argv(1) == "stop") {
                        StopTest();
                    } else {
                        StartTest(args);
                    }
                }
            }

            Cmd::CompletionResult Complete(int argNum, const Cmd::Args&, Str::StringRef prefix) const OVERRIDE {
                if (argNum != 1) {
                    return {};
                }
                std::vector<std::string> presets = AL::ListPresetNames();
                std::sort(presets.begin(), presets.end());

                Cmd::CompletionResult res;

                if (Str::IsPrefix(prefix, "stop")) {
                    res.push_back({"stop", "stops the test"});
                }

                if (Str::IsPrefix(prefix, "none")) {
                    res.push_back({"none", "no effect at all"});
                }

                for (auto& name: presets) {
                    if (Str::IsPrefix(prefix, name)) {
                        res.push_back({std::move(name), ""});
                    }
                }

                return res;
            }

        private:
            void StartTest(const Cmd::Args& args) const {
                Str::StringRef name = args.Argv(1);

                if (name == "none") {
                    testingReverb = true;
                    for (int i = 0; i < N_REVERB_SLOTS; i++) {
                        reverbSlots[i].effect->SetGain(0.0f);
                    }
                    return;
                }

                auto preset = AL::GetPresetByName(name);

                if (not preset) {
                    Print("Reverb preset '%s' doesn't exist.", name);
                    return;
                }

                AL::Effect effectParams;
                effectParams.ApplyReverbPreset(*preset);

                testingReverb = true;
                for (int i = 1; i < N_REVERB_SLOTS; i++) {
                    reverbSlots[i].effect->SetGain(0.0f);
                }

                reverbSlots[0].ratio = 0.5f;
                reverbSlots[0].effect->SetEffect(effectParams);
            }

            void StopTest() const {
                testingReverb = false;
                for (int i = 0; i < N_REVERB_SLOTS; i++) {
                    std::string name = std::move(reverbSlots[i].name);
                    UpdateReverbSlot(i, std::move(name), reverbSlots[i].askedRatio);
                }
            }
    };
    static TestReverbCmd testReverbRegistration;

}
<|endoftext|>


<commit_before>// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab
/*
 * Ceph - scalable distributed file system
 *
 * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
 *
 * This is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License version 2.1, as published by the Free Software
 * Foundation.  See file COPYING.
 *
 */

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#include <sys/stat.h>
#include <iostream>
#include <string>
using namespace std;

#include "config.h"

#include "mon/MonMap.h"
#include "mon/Monitor.h"
#include "mon/MonitorStore.h"

#include "msg/SimpleMessenger.h"

#include "include/CompatSet.h"

#include "common/Timer.h"
#include "common/common_init.h"

extern const CompatSet::Feature ceph_mon_feature_compat[];
extern const CompatSet::Feature ceph_mon_feature_ro_compat[];
extern const CompatSet::Feature ceph_mon_feature_incompat[];

void usage()
{
  cerr << "usage: cmon -i monid [--mon-data=pathtodata] [flags]" << std::endl;
  cerr << "  --debug_mon n\n";
  cerr << "        debug monitor level (e.g. 10)\n";
  cerr << "  --mkfs\n";
  cerr << "        build fresh monitor fs\n";
  generic_server_usage();
}

int main(int argc, const char **argv)
{
  int err;
  DEFINE_CONF_VARS(usage);

  bool mkfs = false;
  const char *osdmapfn = 0;

  vector<const char*> args;
  argv_to_vec(argc, argv, args);
  env_to_vec(args);

  common_set_defaults(true);
  common_init(args, "mon", true);

  FOR_EACH_ARG(args) {
    if (CONF_ARG_EQ("mkfs", '\0')) {
      mkfs = true;
    } else if (CONF_ARG_EQ("osdmap", '\0')) {
      CONF_SAFE_SET_ARG_VAL(&osdmapfn, OPT_STR);
    } else
      usage();
  }

  // whoami
  string name = g_conf.id;
  if (name.length() == 0) {
    cerr << "must specify '-i id' where id is the mon name" << std::endl;
    usage();
  }

  if (!g_conf.mon_data) {
    cerr << "must specify '--mon-data=foo' data path" << std::endl;
    usage();
  }

  // -- mkfs --
  if (mkfs) {
    if (!g_conf.monmap || !osdmapfn)
      usage();

    // make sure it doesn't already exist
        /*
    struct stat st;
    if (::lstat(g_conf.mon_data, &st) == 0) {
      cerr << "monfs dir " << g_conf.mon_data << " already exists; remove it first" << std::endl;
      usage();
    }
	*/

    // load monmap
    bufferlist monmapbl, osdmapbl;
    int err = monmapbl.read_file(g_conf.monmap);
    if (err < 0)
      exit(1);
    MonMap monmap;
    monmap.decode(monmapbl);

    err = osdmapbl.read_file(osdmapfn);
    if (err < 0)
      exit(1);

    // go
    MonitorStore store(g_conf.mon_data);
    Monitor mon(name, &store, 0, &monmap);
    mon.mkfs(osdmapbl);
    cout << argv[0] << ": created monfs at " << g_conf.mon_data
	 << " for mon." << name
	 << std::endl;
    return 0;
  }

  if (g_conf.clock_tare) g_clock.tare();

  CompatSet mon_features(ceph_mon_feature_compat,
			 ceph_mon_feature_ro_compat,
			 ceph_mon_feature_incompat);
  CompatSet ondisk_features;

  MonitorStore store(g_conf.mon_data);
  err = store.mount();
  if (err < 0) {
    char buf[80];
    cerr << "problem opening monitor store in " << g_conf.mon_data << ": " << strerror_r(-err, buf, sizeof(buf)) << std::endl;
    exit(1);
  }

  bufferlist magicbl;
  err = store.get_bl_ss(magicbl, "magic", 0);
  if (err < 0) {
    cerr << "unable to read magic from mon data.. did you run mkcephfs?" << std::endl;
    exit(1);
  }
  string magic(magicbl.c_str(), magicbl.length()-1);  // ignore trailing \n
  if (strcmp(magic.c_str(), CEPH_MON_ONDISK_MAGIC)) {
    cerr << "mon fs magic '" << magic << "' != current '" << CEPH_MON_ONDISK_MAGIC << "'" << std::endl;
    exit(1);
  }

  bufferlist features;
  store.get_bl_ss(features, COMPAT_SET_LOC, 0);
  if (features.length() == 0) {
    cerr << "WARNING: mon fs missing feature list.\n"
	 << "Assuming it is old-style and introducing one." << std::endl;
    //we only want the baseline ~v.18 features assumed to be on disk.
    //If new features are introduced this code needs to disappear or
    //be made smarter.
    ondisk_features = CompatSet(ceph_mon_feature_compat,
				ceph_mon_feature_ro_compat,
				ceph_mon_feature_incompat);
  } else {
    bufferlist::iterator it = features.begin();
    ondisk_features.decode(it);
  }

  if (!mon_features.writeable(ondisk_features)) {
    cerr << "monitor executable cannot read disk! Missing features: "
	 << std::endl;
    CompatSet diff = mon_features.unsupported(ondisk_features);
    //NEEDS_COMPATSET_ITER
    exit(1);
  }

  // monmap?
  MonMap monmap;
  {
    bufferlist latest;
    store.get_bl_ss(latest, "monmap/latest", 0);
    if (latest.length() == 0) {
      cerr << "mon fs missing 'monmap'" << std::endl;
      exit(1);
    }
    bufferlist::iterator p = latest.begin();
    version_t v;
    ::decode(v, p);
    bufferlist mapbl;
    ::decode(mapbl, p);
    monmap.decode(mapbl);
    assert(v == monmap.get_epoch());
  }

  if (!monmap.contains(name)) {
    cerr << "mon." << name << " does not exist in monmap" << std::endl;
    exit(1);
  }

  entity_addr_t ipaddr = monmap.get_addr(name);
  entity_addr_t conf_addr;
  char *mon_addr_str;

  if (conf_read_key(NULL, "mon addr", OPT_STR, &mon_addr_str, NULL) &&
      conf_addr.parse(mon_addr_str) &&
      ipaddr != conf_addr)
    cerr << "WARNING: 'mon addr' config option " << conf_addr << " does not match monmap file" << std::endl
	 << "         continuing with monmap configuration" << std::endl;

  // bind
  SimpleMessenger *messenger = new SimpleMessenger();

  int rank = monmap.get_rank(name);

  cout << "starting mon." << name << " rank " << rank
       << " at " << monmap.get_addr(name)
       << " mon_data " << g_conf.mon_data
       << " fsid " << monmap.get_fsid()
       << std::endl;
  g_conf.public_addr = monmap.get_addr(name);
  err = messenger->bind();
  if (err < 0)
    return 1;

  // start monitor
  messenger->register_entity(entity_name_t::MON(rank));
  messenger->set_default_send_priority(CEPH_MSG_PRIO_HIGH);
  Monitor *mon = new Monitor(name, &store, messenger, &monmap);

  messenger->start();  // may daemonize

  uint64_t supported =
    CEPH_FEATURE_UID |
    CEPH_FEATURE_NOSRCADDR |
    CEPH_FEATURE_MONCLOCKCHECK;
  messenger->set_default_policy(SimpleMessenger::Policy::stateless_server(supported, 0));
  messenger->set_policy(entity_name_t::TYPE_MON,
			SimpleMessenger::Policy::lossless_peer(supported,
							       CEPH_FEATURE_UID));
  mon->init();
  messenger->wait();

  store.umount();
  delete mon;
  messenger->destroy();

  // cd on exit, so that gmon.out (if any) goes into a separate directory for each node.
  char s[20];
  snprintf(s, sizeof(s), "gmon/%d", getpid());
  if (mkdir(s, 0755) == 0)
    chdir(s);

  return 0;
}

<commit_msg>cmon: check return code of chdir<commit_after>// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab
/*
 * Ceph - scalable distributed file system
 *
 * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
 *
 * This is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License version 2.1, as published by the Free Software
 * Foundation.  See file COPYING.
 *
 */

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#include <sys/stat.h>
#include <iostream>
#include <string>
using namespace std;

#include "config.h"

#include "mon/MonMap.h"
#include "mon/Monitor.h"
#include "mon/MonitorStore.h"

#include "msg/SimpleMessenger.h"

#include "include/CompatSet.h"

#include "common/Timer.h"
#include "common/common_init.h"

extern const CompatSet::Feature ceph_mon_feature_compat[];
extern const CompatSet::Feature ceph_mon_feature_ro_compat[];
extern const CompatSet::Feature ceph_mon_feature_incompat[];

void usage()
{
  cerr << "usage: cmon -i monid [--mon-data=pathtodata] [flags]" << std::endl;
  cerr << "  --debug_mon n\n";
  cerr << "        debug monitor level (e.g. 10)\n";
  cerr << "  --mkfs\n";
  cerr << "        build fresh monitor fs\n";
  generic_server_usage();
}

int main(int argc, const char **argv)
{
  int err;
  DEFINE_CONF_VARS(usage);

  bool mkfs = false;
  const char *osdmapfn = 0;

  vector<const char*> args;
  argv_to_vec(argc, argv, args);
  env_to_vec(args);

  common_set_defaults(true);
  common_init(args, "mon", true);

  FOR_EACH_ARG(args) {
    if (CONF_ARG_EQ("mkfs", '\0')) {
      mkfs = true;
    } else if (CONF_ARG_EQ("osdmap", '\0')) {
      CONF_SAFE_SET_ARG_VAL(&osdmapfn, OPT_STR);
    } else
      usage();
  }

  // whoami
  string name = g_conf.id;
  if (name.length() == 0) {
    cerr << "must specify '-i id' where id is the mon name" << std::endl;
    usage();
  }

  if (!g_conf.mon_data) {
    cerr << "must specify '--mon-data=foo' data path" << std::endl;
    usage();
  }

  // -- mkfs --
  if (mkfs) {
    if (!g_conf.monmap || !osdmapfn)
      usage();

    // make sure it doesn't already exist
        /*
    struct stat st;
    if (::lstat(g_conf.mon_data, &st) == 0) {
      cerr << "monfs dir " << g_conf.mon_data << " already exists; remove it first" << std::endl;
      usage();
    }
	*/

    // load monmap
    bufferlist monmapbl, osdmapbl;
    int err = monmapbl.read_file(g_conf.monmap);
    if (err < 0)
      exit(1);
    MonMap monmap;
    monmap.decode(monmapbl);

    err = osdmapbl.read_file(osdmapfn);
    if (err < 0)
      exit(1);

    // go
    MonitorStore store(g_conf.mon_data);
    Monitor mon(name, &store, 0, &monmap);
    mon.mkfs(osdmapbl);
    cout << argv[0] << ": created monfs at " << g_conf.mon_data
	 << " for mon." << name
	 << std::endl;
    return 0;
  }

  if (g_conf.clock_tare) g_clock.tare();

  CompatSet mon_features(ceph_mon_feature_compat,
			 ceph_mon_feature_ro_compat,
			 ceph_mon_feature_incompat);
  CompatSet ondisk_features;

  MonitorStore store(g_conf.mon_data);
  err = store.mount();
  if (err < 0) {
    char buf[80];
    cerr << "problem opening monitor store in " << g_conf.mon_data << ": " << strerror_r(-err, buf, sizeof(buf)) << std::endl;
    exit(1);
  }

  bufferlist magicbl;
  err = store.get_bl_ss(magicbl, "magic", 0);
  if (err < 0) {
    cerr << "unable to read magic from mon data.. did you run mkcephfs?" << std::endl;
    exit(1);
  }
  string magic(magicbl.c_str(), magicbl.length()-1);  // ignore trailing \n
  if (strcmp(magic.c_str(), CEPH_MON_ONDISK_MAGIC)) {
    cerr << "mon fs magic '" << magic << "' != current '" << CEPH_MON_ONDISK_MAGIC << "'" << std::endl;
    exit(1);
  }

  bufferlist features;
  store.get_bl_ss(features, COMPAT_SET_LOC, 0);
  if (features.length() == 0) {
    cerr << "WARNING: mon fs missing feature list.\n"
	 << "Assuming it is old-style and introducing one." << std::endl;
    //we only want the baseline ~v.18 features assumed to be on disk.
    //If new features are introduced this code needs to disappear or
    //be made smarter.
    ondisk_features = CompatSet(ceph_mon_feature_compat,
				ceph_mon_feature_ro_compat,
				ceph_mon_feature_incompat);
  } else {
    bufferlist::iterator it = features.begin();
    ondisk_features.decode(it);
  }

  if (!mon_features.writeable(ondisk_features)) {
    cerr << "monitor executable cannot read disk! Missing features: "
	 << std::endl;
    CompatSet diff = mon_features.unsupported(ondisk_features);
    //NEEDS_COMPATSET_ITER
    exit(1);
  }

  // monmap?
  MonMap monmap;
  {
    bufferlist latest;
    store.get_bl_ss(latest, "monmap/latest", 0);
    if (latest.length() == 0) {
      cerr << "mon fs missing 'monmap'" << std::endl;
      exit(1);
    }
    bufferlist::iterator p = latest.begin();
    version_t v;
    ::decode(v, p);
    bufferlist mapbl;
    ::decode(mapbl, p);
    monmap.decode(mapbl);
    assert(v == monmap.get_epoch());
  }

  if (!monmap.contains(name)) {
    cerr << "mon." << name << " does not exist in monmap" << std::endl;
    exit(1);
  }

  entity_addr_t ipaddr = monmap.get_addr(name);
  entity_addr_t conf_addr;
  char *mon_addr_str;

  if (conf_read_key(NULL, "mon addr", OPT_STR, &mon_addr_str, NULL) &&
      conf_addr.parse(mon_addr_str) &&
      ipaddr != conf_addr)
    cerr << "WARNING: 'mon addr' config option " << conf_addr << " does not match monmap file" << std::endl
	 << "         continuing with monmap configuration" << std::endl;

  // bind
  SimpleMessenger *messenger = new SimpleMessenger();

  int rank = monmap.get_rank(name);

  cout << "starting mon." << name << " rank " << rank
       << " at " << monmap.get_addr(name)
       << " mon_data " << g_conf.mon_data
       << " fsid " << monmap.get_fsid()
       << std::endl;
  g_conf.public_addr = monmap.get_addr(name);
  err = messenger->bind();
  if (err < 0)
    return 1;

  // start monitor
  messenger->register_entity(entity_name_t::MON(rank));
  messenger->set_default_send_priority(CEPH_MSG_PRIO_HIGH);
  Monitor *mon = new Monitor(name, &store, messenger, &monmap);

  messenger->start();  // may daemonize

  uint64_t supported =
    CEPH_FEATURE_UID |
    CEPH_FEATURE_NOSRCADDR |
    CEPH_FEATURE_MONCLOCKCHECK;
  messenger->set_default_policy(SimpleMessenger::Policy::stateless_server(supported, 0));
  messenger->set_policy(entity_name_t::TYPE_MON,
			SimpleMessenger::Policy::lossless_peer(supported,
							       CEPH_FEATURE_UID));
  mon->init();
  messenger->wait();

  store.umount();
  delete mon;
  messenger->destroy();

  // cd on exit, so that gmon.out (if any) goes into a separate directory for each node.
  char s[20];
  snprintf(s, sizeof(s), "gmon/%d", getpid());
  if ((mkdir(s, 0755) == 0) && (chdir(s) == 0)) {
    dout(0) << "cmon: gmon.out should be in " << s << dendl;
  }

  return 0;
}

<|endoftext|>


<commit_before>#include "test.hpp"
#include "../expquat.hpp"

namespace frea {
	namespace test {
		template <class T>
		class ExpQuaternion : public Random {
			public:
				using value_t = typename std::tuple_element_t<0,T>;
				constexpr static bool align = std::tuple_element_t<1,T>::value;
				using eq_t = ExpQuatT<value_t, align>;
				using quat_t = QuatT<value_t, align>;
				using vec_t = typename quat_t::vec_t;
				using array_t = Array<value_t, 3>;

			private:
				constexpr static Range<value_t> DefaultRange{-1e3, 1e3};
				using RD = decltype(std::declval<Random>().mt().template getUniformF<value_t>(DefaultRange));
				RD	_rd;

			public:
				ExpQuaternion():
					_rd(mt().template getUniformF<value_t>())
				{}
				vec_t makeDir() {
					return random::GenVecUnit<vec_t>(_rd);
				}
				quat_t makeRQuat() {
					return random::GenQuat<quat_t>(_rd);
				}
		};
		TYPED_TEST_CASE(ExpQuaternion, types::QTypes);

		TYPED_TEST(ExpQuaternion, QuaternionConvert) {
			using eq_t = typename TestFixture::eq_t;
			using vec_t = typename TestFixture::vec_t;
			using value_t = typename TestFixture::value_t;

			// Quat -> ExpQuat -> Quat の結果比較
			const auto q0 = this->makeRQuat();
			eq_t eq(q0);
			const auto q1 = eq.asQuat();
			eq = eq_t(q1*-1);
			const auto q2 = eq.asQuat();
			// クォータニオンの符号反転した物は同一視 = 方向ベクトルを変換して同じだったらOK
			const auto v0 = this->makeDir();
			const vec_t v1 = v0 * q0,
						v2 = v0 * q1,
						v3 = v0 * q2;
            constexpr value_t Th = Threshold<value_t>(0.9, 0);
			EXPECT_LT(AbsMax(vec_t(v1-v2)), Th);
			EXPECT_LT(AbsMax(vec_t(v1-v3)), Th);
		}
		TYPED_TEST(ExpQuaternion, Lerp) {
			using eq_t = typename TestFixture::eq_t;
			using value_t = typename TestFixture::value_t;
			// ExpQuatを合成した結果をQuat合成のケースと比較
			auto q0 = this->makeRQuat(),
				q1 = this->makeRQuat();
			// 最短距離で補間するような細工
			if(q0.dot(q1) < 0) {
				q1 *= -1;
				q1.w *= -1;
			}
			const eq_t eq0(q0),
						eq1(q1);
			constexpr value_t Th = Threshold<value_t>(1.0, 0);
			constexpr int NDiv = 8;
			value_t err_sum = 0;
			const auto v0 = this->makeDir();
			// 0から1まで遷移
			for(int i=0 ; i<=NDiv ; i++) {
				const value_t t = i / value_t(NDiv);
				// Quatで変換
				const auto v1 = v0 * q0.slerp(q1, t);
				// ExpQuatで変換
				const auto eq2 = eq0 * (1.0 - t) + eq1 * t;
				const auto v2 = v0 * eq2.asQuat();

				const auto diff = v2-v1;
				err_sum += diff.dot(diff);
				EXPECT_LT(err_sum/(i+1), Th);
			}
			err_sum /= NDiv+1;
			EXPECT_LT(err_sum, Th);
		}
	}
}
<commit_msg>expquaternion: getAngAxis()のテストコード<commit_after>#include "test.hpp"
#include "../expquat.hpp"

namespace frea {
	namespace test {
		template <class T>
		class ExpQuaternion : public Random {
			public:
				using value_t = typename std::tuple_element_t<0,T>;
				constexpr static bool align = std::tuple_element_t<1,T>::value;
				using eq_t = ExpQuatT<value_t, align>;
				using quat_t = QuatT<value_t, align>;
				using vec_t = typename quat_t::vec_t;
				using array_t = Array<value_t, 3>;

			private:
				constexpr static Range<value_t> DefaultRange{-1e3, 1e3};
				using RD = decltype(std::declval<Random>().mt().template getUniformF<value_t>(DefaultRange));
				RD	_rd;

			public:
				ExpQuaternion():
					_rd(mt().template getUniformF<value_t>())
				{}
				vec_t makeDir() {
					return random::GenVecUnit<vec_t>(_rd);
				}
				quat_t makeRQuat() {
					return random::GenQuat<quat_t>(_rd);
				}
		};
		TYPED_TEST_CASE(ExpQuaternion, types::QTypes);

		TYPED_TEST(ExpQuaternion, QuaternionConvert) {
			using eq_t = typename TestFixture::eq_t;
			using vec_t = typename TestFixture::vec_t;
			using value_t = typename TestFixture::value_t;

			// Quat -> ExpQuat -> Quat の結果比較
			const auto q0 = this->makeRQuat();
			eq_t eq(q0);
			const auto q1 = eq.asQuat();
			eq = eq_t(q1*-1);
			const auto q2 = eq.asQuat();
			// クォータニオンの符号反転した物は同一視 = 方向ベクトルを変換して同じだったらOK
			const auto v0 = this->makeDir();
			const vec_t v1 = v0 * q0,
						v2 = v0 * q1,
						v3 = v0 * q2;
            constexpr value_t Th = Threshold<value_t>(0.9, 0);
			EXPECT_LT(AbsMax(vec_t(v1-v2)), Th);
			EXPECT_LT(AbsMax(vec_t(v1-v3)), Th);
		}
		TYPED_TEST(ExpQuaternion, AngAxis) {
			using value_t = typename TestFixture::value_t;
			using vec_t = typename TestFixture::vec_t;
			const auto q = this->makeRQuat();
			const auto e = q.asExpQuat();

			const auto qv = q.getAxis();
			const auto qa = q.angle();
			const auto ei = e.getAngAxis();
			if(qa.get() > ThresholdF<value_t>(0.8)) {
				constexpr auto Th = ThresholdF<value_t>(0.8);
				EXPECT_LT(AbsMax(vec_t(qv-ei.axis)), Th);
				EXPECT_LT(Radian<value_t>(qa-ei.angle).get(), Th);
			}
		}
		TYPED_TEST(ExpQuaternion, Lerp) {
			using eq_t = typename TestFixture::eq_t;
			using value_t = typename TestFixture::value_t;
			// ExpQuatを合成した結果をQuat合成のケースと比較
			auto q0 = this->makeRQuat(),
				q1 = this->makeRQuat();
			// 最短距離で補間するような細工
			if(q0.dot(q1) < 0) {
				q1 *= -1;
				q1.w *= -1;
			}
			const eq_t eq0(q0),
						eq1(q1);
			constexpr value_t Th = Threshold<value_t>(1.0, 0);
			constexpr int NDiv = 8;
			value_t err_sum = 0;
			const auto v0 = this->makeDir();
			// 0から1まで遷移
			for(int i=0 ; i<=NDiv ; i++) {
				const value_t t = i / value_t(NDiv);
				// Quatで変換
				const auto v1 = v0 * q0.slerp(q1, t);
				// ExpQuatで変換
				const auto eq2 = eq0 * (1.0 - t) + eq1 * t;
				const auto v2 = v0 * eq2.asQuat();

				const auto diff = v2-v1;
				err_sum += diff.dot(diff);
				EXPECT_LT(err_sum/(i+1), Th);
			}
			err_sum /= NDiv+1;
			EXPECT_LT(err_sum, Th);
		}
	}
}
<|endoftext|>


<commit_before>/*************************************************************************/
/*  texture_editor_plugin.cpp                                            */
/*************************************************************************/
/*                       This file is part of:                           */
/*                           GODOT ENGINE                                */
/*                      https://godotengine.org                          */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur.                 */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md).   */
/*                                                                       */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the       */
/* "Software"), to deal in the Software without restriction, including   */
/* without limitation the rights to use, copy, modify, merge, publish,   */
/* distribute, sublicense, and/or sell copies of the Software, and to    */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions:                                             */
/*                                                                       */
/* The above copyright notice and this permission notice shall be        */
/* included in all copies or substantial portions of the Software.       */
/*                                                                       */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
/*************************************************************************/

#include "texture_editor_plugin.h"

#include "editor/editor_scale.h"

TextureRect *TexturePreview::get_texture_display() {
	return texture_display;
}

void TexturePreview::_notification(int p_what) {
	switch (p_what) {
		case NOTIFICATION_ENTER_TREE:
		case NOTIFICATION_THEME_CHANGED: {
			if (!is_inside_tree()) {
				// TODO: This is a workaround because `NOTIFICATION_THEME_CHANGED`
				// is getting called for some reason when the `TexturePreview` is
				// getting destroyed, which causes `get_theme_font()` to return `nullptr`.
				// See https://github.com/godotengine/godot/issues/50743.
				break;
			}

			if (metadata_label) {
				Ref<Font> metadata_label_font = get_theme_font(SNAME("expression"), SNAME("EditorFonts"));
				metadata_label->add_theme_font_override("font", metadata_label_font);
			}

			checkerboard->set_texture(get_theme_icon(SNAME("Checkerboard"), SNAME("EditorIcons")));
		} break;
	}
}

void TexturePreview::_update_metadata_label_text() {
	Ref<Texture2D> texture = texture_display->get_texture();

	String format;
	if (Object::cast_to<ImageTexture>(*texture)) {
		format = Image::get_format_name(Object::cast_to<ImageTexture>(*texture)->get_format());
	} else if (Object::cast_to<CompressedTexture2D>(*texture)) {
		format = Image::get_format_name(Object::cast_to<CompressedTexture2D>(*texture)->get_format());
	} else {
		format = texture->get_class();
	}

	metadata_label->set_text(itos(texture->get_width()) + "x" + itos(texture->get_height()) + " " + format);
}

TexturePreview::TexturePreview(Ref<Texture2D> p_texture, bool p_show_metadata) {
	checkerboard = memnew(TextureRect);
	checkerboard->set_stretch_mode(TextureRect::STRETCH_TILE);
	checkerboard->set_texture_repeat(CanvasItem::TEXTURE_REPEAT_ENABLED);
	checkerboard->set_custom_minimum_size(Size2(0.0, 256.0) * EDSCALE);
	add_child(checkerboard);

	texture_display = memnew(TextureRect);
	texture_display->set_texture(p_texture);
	texture_display->set_anchors_preset(TextureRect::PRESET_WIDE);
	texture_display->set_stretch_mode(TextureRect::STRETCH_KEEP_ASPECT_CENTERED);
	texture_display->set_ignore_texture_size(true);
	add_child(texture_display);

	if (p_show_metadata) {
		metadata_label = memnew(Label);

		_update_metadata_label_text();
		p_texture->connect("changed", callable_mp(this, &TexturePreview::_update_metadata_label_text));

		// It's okay that these colors are static since the grid color is static too.
		metadata_label->add_theme_color_override("font_color", Color::named("white"));
		metadata_label->add_theme_color_override("font_color_shadow", Color::named("black"));

		metadata_label->add_theme_font_size_override("font_size", 16 * EDSCALE);
		metadata_label->add_theme_color_override("font_outline_color", Color::named("black"));
		metadata_label->add_theme_constant_override("outline_size", 2 * EDSCALE);

		metadata_label->add_theme_constant_override("shadow_outline_size", 1);
		metadata_label->set_h_size_flags(Control::SIZE_SHRINK_END);
		metadata_label->set_v_size_flags(Control::SIZE_SHRINK_END);

		add_child(metadata_label);
	}
}

bool EditorInspectorPluginTexture::can_handle(Object *p_object) {
	return Object::cast_to<ImageTexture>(p_object) != nullptr || Object::cast_to<AtlasTexture>(p_object) != nullptr || Object::cast_to<CompressedTexture2D>(p_object) != nullptr || Object::cast_to<AnimatedTexture>(p_object) != nullptr;
}

void EditorInspectorPluginTexture::parse_begin(Object *p_object) {
	Ref<Texture> texture(Object::cast_to<Texture>(p_object));

	add_custom_control(memnew(TexturePreview(texture, true)));
}

TextureEditorPlugin::TextureEditorPlugin() {
	Ref<EditorInspectorPluginTexture> plugin;
	plugin.instantiate();
	add_inspector_plugin(plugin);
}
<commit_msg>Use multiplication symbol in Texture size label<commit_after>/*************************************************************************/
/*  texture_editor_plugin.cpp                                            */
/*************************************************************************/
/*                       This file is part of:                           */
/*                           GODOT ENGINE                                */
/*                      https://godotengine.org                          */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur.                 */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md).   */
/*                                                                       */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the       */
/* "Software"), to deal in the Software without restriction, including   */
/* without limitation the rights to use, copy, modify, merge, publish,   */
/* distribute, sublicense, and/or sell copies of the Software, and to    */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions:                                             */
/*                                                                       */
/* The above copyright notice and this permission notice shall be        */
/* included in all copies or substantial portions of the Software.       */
/*                                                                       */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
/*************************************************************************/

#include "texture_editor_plugin.h"

#include "editor/editor_scale.h"

TextureRect *TexturePreview::get_texture_display() {
	return texture_display;
}

void TexturePreview::_notification(int p_what) {
	switch (p_what) {
		case NOTIFICATION_ENTER_TREE:
		case NOTIFICATION_THEME_CHANGED: {
			if (!is_inside_tree()) {
				// TODO: This is a workaround because `NOTIFICATION_THEME_CHANGED`
				// is getting called for some reason when the `TexturePreview` is
				// getting destroyed, which causes `get_theme_font()` to return `nullptr`.
				// See https://github.com/godotengine/godot/issues/50743.
				break;
			}

			if (metadata_label) {
				Ref<Font> metadata_label_font = get_theme_font(SNAME("expression"), SNAME("EditorFonts"));
				metadata_label->add_theme_font_override("font", metadata_label_font);
			}

			checkerboard->set_texture(get_theme_icon(SNAME("Checkerboard"), SNAME("EditorIcons")));
		} break;
	}
}

void TexturePreview::_update_metadata_label_text() {
	Ref<Texture2D> texture = texture_display->get_texture();

	String format;
	if (Object::cast_to<ImageTexture>(*texture)) {
		format = Image::get_format_name(Object::cast_to<ImageTexture>(*texture)->get_format());
	} else if (Object::cast_to<CompressedTexture2D>(*texture)) {
		format = Image::get_format_name(Object::cast_to<CompressedTexture2D>(*texture)->get_format());
	} else {
		format = texture->get_class();
	}

	metadata_label->set_text(vformat(String::utf8("%s×%s %s"), itos(texture->get_width()), itos(texture->get_height()), format));
}

TexturePreview::TexturePreview(Ref<Texture2D> p_texture, bool p_show_metadata) {
	checkerboard = memnew(TextureRect);
	checkerboard->set_stretch_mode(TextureRect::STRETCH_TILE);
	checkerboard->set_texture_repeat(CanvasItem::TEXTURE_REPEAT_ENABLED);
	checkerboard->set_custom_minimum_size(Size2(0.0, 256.0) * EDSCALE);
	add_child(checkerboard);

	texture_display = memnew(TextureRect);
	texture_display->set_texture(p_texture);
	texture_display->set_anchors_preset(TextureRect::PRESET_WIDE);
	texture_display->set_stretch_mode(TextureRect::STRETCH_KEEP_ASPECT_CENTERED);
	texture_display->set_ignore_texture_size(true);
	add_child(texture_display);

	if (p_show_metadata) {
		metadata_label = memnew(Label);

		_update_metadata_label_text();
		p_texture->connect("changed", callable_mp(this, &TexturePreview::_update_metadata_label_text));

		// It's okay that these colors are static since the grid color is static too.
		metadata_label->add_theme_color_override("font_color", Color::named("white"));
		metadata_label->add_theme_color_override("font_color_shadow", Color::named("black"));

		metadata_label->add_theme_font_size_override("font_size", 16 * EDSCALE);
		metadata_label->add_theme_color_override("font_outline_color", Color::named("black"));
		metadata_label->add_theme_constant_override("outline_size", 2 * EDSCALE);

		metadata_label->add_theme_constant_override("shadow_outline_size", 1);
		metadata_label->set_h_size_flags(Control::SIZE_SHRINK_END);
		metadata_label->set_v_size_flags(Control::SIZE_SHRINK_END);

		add_child(metadata_label);
	}
}

bool EditorInspectorPluginTexture::can_handle(Object *p_object) {
	return Object::cast_to<ImageTexture>(p_object) != nullptr || Object::cast_to<AtlasTexture>(p_object) != nullptr || Object::cast_to<CompressedTexture2D>(p_object) != nullptr || Object::cast_to<AnimatedTexture>(p_object) != nullptr;
}

void EditorInspectorPluginTexture::parse_begin(Object *p_object) {
	Ref<Texture> texture(Object::cast_to<Texture>(p_object));

	add_custom_control(memnew(TexturePreview(texture, true)));
}

TextureEditorPlugin::TextureEditorPlugin() {
	Ref<EditorInspectorPluginTexture> plugin;
	plugin.instantiate();
	add_inspector_plugin(plugin);
}
<|endoftext|>