<commit_before>//std
#include <array>
#include <chrono>
#include <iostream>

//mandala
#include "platform_win32.hpp"
#include "gpu.hpp"

//glew
#include <GL\glew.h>

//glfw
#include <GLFW\glfw3.h>

namespace mandala
{
    platform_win32_t platform;

    static inline void on_keyboard_key(GLFWwindow* window, int key, int scancode, int action, int mods)
	{
		input_event_t input_event;
		input_event.device_type = input_event_t::device_type_e::keyboard;
		input_event.keyboard.key = static_cast<input_event_t::keyboard_t::key_e>(key);

		if ((mods & GLFW_MOD_SHIFT) == GLFW_MOD_SHIFT)
		{
			input_event.keyboard.mod_flags |= input_event_t::mod_flag_shift;
		}

        if ((mods & GLFW_MOD_CONTROL) == GLFW_MOD_CONTROL)
        {
			input_event.keyboard.mod_flags |= input_event_t::mod_flag_ctrl;
        }

        if ((mods & GLFW_MOD_ALT) == GLFW_MOD_ALT)
        {
			input_event.keyboard.mod_flags |= input_event_t::mod_flag_alt;
        }

        if ((mods & GLFW_MOD_SUPER) == GLFW_MOD_SUPER)
        {
			input_event.keyboard.mod_flags |= input_event_t::mod_flag_super;
        }

        switch (action)
        {
        case GLFW_RELEASE:
            input_event.keyboard.type = input_event_t::keyboard_t::type_e::key_release;
            break;
        case GLFW_PRESS:
            input_event.keyboard.type = input_event_t::keyboard_t::type_e::key_press;
            break;
        case GLFW_REPEAT:
            input_event.keyboard.type = input_event_t::keyboard_t::type_e::key_repeat;
            break;
        }

        platform.input.events.push_back(input_event);
    }

    static inline void on_keyboard_character(GLFWwindow* window, unsigned int character)
    {
        input_event_t input_event;
        input_event.device_type = input_event_t::device_type_e::keyboard;
        input_event.keyboard.type = input_event_t::keyboard_t::type_e::character;
        input_event.keyboard.character = character;

        platform.input.events.push_back(input_event);
    }

    static inline void on_mouse_button(GLFWwindow* window, int button, int action, int mods)
    {
        input_event_t input_event;
        input_event.device_type = input_event_t::device_type_e::touch;
        input_event.touch.button = static_cast<input_event_t::touch_t::button_e>(button);
		input_event.touch.mod_flags = mods;

        bool is_press = (action == GLFW_PRESS);

        input_event.touch.type = is_press ? input_event_t::touch_t::type_e::press : input_event_t::touch_t::type_e::release;

        if (is_press)
        {
            ++platform.input.touch_id;

            input_event.touch.id = platform.input.touch_id;
        }
        else
        {
            platform.input.touch_id = 0;    //TODO: replace with something better
        }

        input_event.touch.location = platform.get_cursor_location();

        platform.input.events.push_back(input_event);
    }

    static inline void on_mouse_move(GLFWwindow* window, double x, double y)
	{
        const auto screen_size = platform.get_screen_size();

		input_event_t input_event;
		input_event.device_type = input_event_t::device_type_e::touch;
		input_event.touch.type = input_event_t::touch_t::type_e::move;
		input_event.touch.location.x = x;
		input_event.touch.location.y = screen_size.y - y;
		input_event.touch.location_delta.x = x - platform.cursor_location.x;
		input_event.touch.location_delta.y = screen_size.y - y - platform.cursor_location.y;
        input_event.touch.id = platform.input.touch_id;

		if (platform.is_cursor_centered)
		{
			const auto screen_size = platform.get_screen_size();

			platform.set_cursor_location(static_cast<vec2_f64_t>(screen_size) / 2.0);
		}

        platform.cursor_location = platform.get_cursor_location();

        platform.input.events.push_back(input_event);
    }

    static inline void on_mouse_scroll(GLFWwindow* window, double x, double y)
    {
        const auto screen_size = platform.get_screen_size();

        input_event_t input_event;
        input_event.device_type = input_event_t::device_type_e::touch;
        input_event.touch.type = input_event_t::touch_t::type_e::scroll;
        input_event.touch.location = platform.get_cursor_location();
        input_event.touch.location_delta.x = x;
        input_event.touch.location_delta.y = screen_size.y - y;

        platform.input.events.push_back(input_event);
    }

    static inline void on_window_resize(GLFWwindow* window, int width, int height)
	{
		//TODO: a less vebose solution is possible
        auto window_events_itr = std::find_if(platform.window.events.begin(), platform.window.events.end(), [](const window_event_t& window_event)
        {
            return window_event.type == window_event_t::type_e::resize;
        });

        if (window_events_itr != platform.window.events.end())
        {
            window_events_itr->rectangle.width = width;
			window_events_itr->rectangle.height = height;
        }
        else
        {
            window_event_t window_event;
            window_event.type = window_event_t::type_e::resize;
			window_event.rectangle.width = width;
			window_event.rectangle.height = height;

            platform.window.events.push_back(window_event);
        }

        platform.window.rectangle.width = width;
        platform.window.rectangle.height = height;
    }

    static inline void on_window_move(GLFWwindow* window, int x, int y)
	{
		//TODO: a less vebose solution is possible
        auto window_events_itr = std::find_if(platform.window.events.begin(), platform.window.events.end(), [](const window_event_t& window_event)
        {
            return window_event.type == window_event_t::type_e::move;
        });

        if (window_events_itr != platform.window.events.end())
        {
			window_events_itr->rectangle.x = x;
			window_events_itr->rectangle.y = y;
        }
        else
        {
            window_event_t window_event;
            window_event.type = window_event_t::type_e::move;
			window_event.rectangle.x = x;
			window_event.rectangle.y = y;

            platform.window.events.push_back(window_event);
        }

        platform.window.rectangle.x = x;
        platform.window.rectangle.y = y;
    }

    static inline void on_error(int error_code, const char* message)
    {
        throw std::exception();
    }

    platform_win32_t::platform_win32_t()
    {
    }

	platform_win32_t::~platform_win32_t()
	{
	}

	void platform_win32_t::app_run_start()
	{
		//glfw
		glfwInit();

		window_ptr = glfwCreateWindow(1, 1, "mandala", nullptr, nullptr);

        glfwMakeContextCurrent(window_ptr);

        glfwSetKeyCallback(window_ptr, on_keyboard_key);
        glfwSetCharCallback(window_ptr, on_keyboard_character);
        glfwSetMouseButtonCallback(window_ptr, on_mouse_button);
        glfwSetCursorPosCallback(window_ptr, on_mouse_move);
        glfwSetScrollCallback(window_ptr, on_mouse_scroll);
        glfwSetWindowSizeCallback(window_ptr, on_window_resize);
        glfwSetWindowPosCallback(window_ptr, on_window_move);

		//glew
        auto glew_init_result = glewInit();

        if (glew_init_result != GLEW_OK)
        {
            throw std::exception(unsafe_cast<char*>(glewGetErrorString(glew_init_result)));
        }
	}

	void platform_win32_t::app_run_end()
	{
        glfwDestroyWindow(window_ptr);
        glfwTerminate();

        window_ptr = nullptr;
	}

	void platform_win32_t::app_tick_start(float32_t dt)
	{
        glfwPollEvents();

		for (size_t gamepad_index = 0; gamepad_index < input.gamepad_states.size(); ++gamepad_index)
		{
            if (!glfwJoystickPresent(static_cast<int>(gamepad_index)))
			{
				break;
			}

			auto& gamepad_state = input.gamepad_states[gamepad_index];

			int axis_count = 0;
			auto axes = glfwGetJoystickAxes(static_cast<int>(gamepad_index), &axis_count);

			for (auto axis_index = 0; axis_index < axis_count; ++axis_index)
			{
				if (axes[axis_index] != gamepad_state.axes[axis_index])
				{
					input_event_t input_event;
					input_event.device_type = input_event_t::device_type_e::gamepad;
					input_event.gamepad.index = gamepad_index;
					input_event.gamepad.type = input_event_t::gamepad_t::type_e::axis_move;
					input_event.gamepad.axis_index = axis_index;
					input_event.gamepad.axis_value = axes[axis_index];
                    input_event.gamepad.axis_value_delta = axes[axis_index] - gamepad_state.axes[axis_index];

					platform.input.events.push_back(input_event);
				}

				gamepad_state.axes[axis_index] = axes[axis_index];
			}

			int button_count = 0;
			auto buttons = glfwGetJoystickButtons(static_cast<int>(gamepad_index), &button_count);

			for (auto button_index = 0; button_index < button_count; ++button_index)
			{
				if (buttons[button_index] != gamepad_state.buttons[button_index])
				{
					input_event_t input_event;
					input_event.device_type = input_event_t::device_type_e::gamepad;
					input_event.gamepad.index = gamepad_index;
					input_event.gamepad.type = buttons[button_index] == 0 ? input_event_t::gamepad_t::type_e::release : input_event_t::gamepad_t::type_e::press;
                    input_event.gamepad.button_index = button_index;

					platform.input.events.push_back(input_event);
				}

				gamepad_state.buttons[button_index] = buttons[button_index];
			}
		}
	}

	void platform_win32_t::app_tick_end(float32_t dt)
	{
	}

	void platform_win32_t::app_render_start()
	{
		gpu.set_clear_color(rgba_type(0));

        gpu.clear(gpu_t::clear_flag_color | gpu_t::clear_flag_depth);
	}

	void platform_win32_t::app_render_end()
	{
        glfwSwapBuffers(window_ptr);
	}

	bool platform_win32_t::should_exit() const
	{
        return glfwWindowShouldClose(window_ptr) != 0;
	}

    platform_t::screen_size_type platform_win32_t::get_screen_size() const
    {
        platform_t::screen_size_type screen_size;

        glfwGetWindowSize(window_ptr, &screen_size.x, &screen_size.y);

		return screen_size;
    }

	void platform_win32_t::set_screen_size(const screen_size_type& screen_size) const
	{
        glfwSetWindowSize(window_ptr, screen_size.x, screen_size.y);
	}

    bool platform_win32_t::pop_input_event(input_event_t& input_event)
    {
		if (input.events.empty())
        {
            return false;
        }

		input_event = input.events.front();
		input_event.id = input.event_id;
		input_event.is_consumed = false;

		input.events.pop_front();

		++input.event_id;

        return true;
    }

    bool platform_win32_t::pop_window_event(window_event_t& window_event)
    {
        if (window.events.empty())
        {
            return false;
        }

        window_event = window.events.front();

        window.events.pop_front();

        return true;
    }

	platform_t::cursor_location_type platform_win32_t::get_cursor_location() const
	{
        cursor_location_type cursor_location;

        glfwGetCursorPos(window_ptr, &cursor_location.x, &cursor_location.y);

        //cursor_location.y = get_screen_size().y - cursor_location.y;

		return cursor_location;
	}

	void platform_win32_t::set_cursor_location(const cursor_location_type& cursor_location) const
	{
        glfwSetCursorPos(window_ptr, cursor_location.x, cursor_location.y);
	}

	bool platform_win32_t::is_cursor_hidden() const
	{
        return glfwGetInputMode(window_ptr, GLFW_CURSOR) == GLFW_CURSOR_HIDDEN;
	}

	void platform_win32_t::set_cursor_hidden(bool is_hidden) const
	{
        glfwSetInputMode(window_ptr, GLFW_CURSOR, is_hidden ? GLFW_CURSOR_HIDDEN : GLFW_CURSOR_NORMAL);
	}

	platform_t::window_title_type platform_win32_t::get_window_title() const
	{
		//TODO: implement this
		return std::string();
	}

	void platform_win32_t::set_window_title(const window_title_type& window_title) const
	{
        glfwSetWindowTitle(window_ptr, window_title.c_str());
	}

    platform_t::window_size_type platform_win32_t::get_window_size() const
	{
        window_size_type window_size;

        glfwGetWindowSize(window_ptr, &window_size.x, &window_size.y);

		return window_size;
	}

	void platform_win32_t::set_window_size(const window_size_type& window_size) const
	{
        glfwSetWindowSize(window_ptr, window_size.x, window_size.y);
	}

	platform_t::window_size_type platform_win32_t::get_window_location() const
	{
		vec2_i32_t window_location;

        glfwGetWindowPos(window_ptr, &window_location.x, &window_location.y);

		return window_location;
	}

	void platform_win32_t::set_window_location(const window_size_type& window_location) const
	{
        glfwSetWindowPos(window_ptr, window_location.x, window_location.y);
	}

	std::string platform_win32_t::get_clipboard_string() const
	{
		return glfwGetClipboardString(window_ptr);
	}

	void platform_win32_t::set_clipboard_string(const std::string& clipboard_string) const
	{
		glfwSetClipboardString(window_ptr, clipboard_string.c_str());
	}
}
<commit_msg>remove pointless re-setting of clear color every render<commit_after>//std
#include <array>
#include <chrono>
#include <iostream>

//mandala
#include "platform_win32.hpp"
#include "gpu.hpp"

//glew
#include <GL\glew.h>

//glfw
#include <GLFW\glfw3.h>

namespace mandala
{
    platform_win32_t platform;

    static inline void on_keyboard_key(GLFWwindow* window, int key, int scancode, int action, int mods)
	{
		input_event_t input_event;
		input_event.device_type = input_event_t::device_type_e::keyboard;
		input_event.keyboard.key = static_cast<input_event_t::keyboard_t::key_e>(key);

		if ((mods & GLFW_MOD_SHIFT) == GLFW_MOD_SHIFT)
		{
			input_event.keyboard.mod_flags |= input_event_t::mod_flag_shift;
		}

        if ((mods & GLFW_MOD_CONTROL) == GLFW_MOD_CONTROL)
        {
			input_event.keyboard.mod_flags |= input_event_t::mod_flag_ctrl;
        }

        if ((mods & GLFW_MOD_ALT) == GLFW_MOD_ALT)
        {
			input_event.keyboard.mod_flags |= input_event_t::mod_flag_alt;
        }

        if ((mods & GLFW_MOD_SUPER) == GLFW_MOD_SUPER)
        {
			input_event.keyboard.mod_flags |= input_event_t::mod_flag_super;
        }

        switch (action)
        {
        case GLFW_RELEASE:
            input_event.keyboard.type = input_event_t::keyboard_t::type_e::key_release;
            break;
        case GLFW_PRESS:
            input_event.keyboard.type = input_event_t::keyboard_t::type_e::key_press;
            break;
        case GLFW_REPEAT:
            input_event.keyboard.type = input_event_t::keyboard_t::type_e::key_repeat;
            break;
        }

        platform.input.events.push_back(input_event);
    }

    static inline void on_keyboard_character(GLFWwindow* window, unsigned int character)
    {
        input_event_t input_event;
        input_event.device_type = input_event_t::device_type_e::keyboard;
        input_event.keyboard.type = input_event_t::keyboard_t::type_e::character;
        input_event.keyboard.character = character;

        platform.input.events.push_back(input_event);
    }

    static inline void on_mouse_button(GLFWwindow* window, int button, int action, int mods)
    {
        input_event_t input_event;
        input_event.device_type = input_event_t::device_type_e::touch;
        input_event.touch.button = static_cast<input_event_t::touch_t::button_e>(button);
		input_event.touch.mod_flags = mods;

        bool is_press = (action == GLFW_PRESS);

        input_event.touch.type = is_press ? input_event_t::touch_t::type_e::press : input_event_t::touch_t::type_e::release;

        if (is_press)
        {
            ++platform.input.touch_id;

            input_event.touch.id = platform.input.touch_id;
        }
        else
        {
            platform.input.touch_id = 0;    //TODO: replace with something better
        }

        input_event.touch.location = platform.get_cursor_location();

        platform.input.events.push_back(input_event);
    }

    static inline void on_mouse_move(GLFWwindow* window, double x, double y)
	{
        const auto screen_size = platform.get_screen_size();

		input_event_t input_event;
		input_event.device_type = input_event_t::device_type_e::touch;
		input_event.touch.type = input_event_t::touch_t::type_e::move;
		input_event.touch.location.x = x;
		input_event.touch.location.y = screen_size.y - y;
		input_event.touch.location_delta.x = x - platform.cursor_location.x;
		input_event.touch.location_delta.y = screen_size.y - y - platform.cursor_location.y;
        input_event.touch.id = platform.input.touch_id;

		if (platform.is_cursor_centered)
		{
			const auto screen_size = platform.get_screen_size();

			platform.set_cursor_location(static_cast<vec2_f64_t>(screen_size) / 2.0);
		}

        platform.cursor_location = platform.get_cursor_location();

        platform.input.events.push_back(input_event);
    }

    static inline void on_mouse_scroll(GLFWwindow* window, double x, double y)
    {
        const auto screen_size = platform.get_screen_size();

        input_event_t input_event;
        input_event.device_type = input_event_t::device_type_e::touch;
        input_event.touch.type = input_event_t::touch_t::type_e::scroll;
        input_event.touch.location = platform.get_cursor_location();
        input_event.touch.location_delta.x = x;
        input_event.touch.location_delta.y = screen_size.y - y;

        platform.input.events.push_back(input_event);
    }

    static inline void on_window_resize(GLFWwindow* window, int width, int height)
	{
		//TODO: a less vebose solution is possible
        auto window_events_itr = std::find_if(platform.window.events.begin(), platform.window.events.end(), [](const window_event_t& window_event)
        {
            return window_event.type == window_event_t::type_e::resize;
        });

        if (window_events_itr != platform.window.events.end())
        {
            window_events_itr->rectangle.width = width;
			window_events_itr->rectangle.height = height;
        }
        else
        {
            window_event_t window_event;
            window_event.type = window_event_t::type_e::resize;
			window_event.rectangle.width = width;
			window_event.rectangle.height = height;

            platform.window.events.push_back(window_event);
        }

        platform.window.rectangle.width = width;
        platform.window.rectangle.height = height;
    }

    static inline void on_window_move(GLFWwindow* window, int x, int y)
	{
		//TODO: a less vebose solution is possible
        auto window_events_itr = std::find_if(platform.window.events.begin(), platform.window.events.end(), [](const window_event_t& window_event)
        {
            return window_event.type == window_event_t::type_e::move;
        });

        if (window_events_itr != platform.window.events.end())
        {
			window_events_itr->rectangle.x = x;
			window_events_itr->rectangle.y = y;
        }
        else
        {
            window_event_t window_event;
            window_event.type = window_event_t::type_e::move;
			window_event.rectangle.x = x;
			window_event.rectangle.y = y;

            platform.window.events.push_back(window_event);
        }

        platform.window.rectangle.x = x;
        platform.window.rectangle.y = y;
    }

    static inline void on_error(int error_code, const char* message)
    {
        throw std::exception();
    }

    platform_win32_t::platform_win32_t()
    {
    }

	platform_win32_t::~platform_win32_t()
	{
	}

	void platform_win32_t::app_run_start()
	{
		//glfw
		glfwInit();

		window_ptr = glfwCreateWindow(1, 1, "mandala", nullptr, nullptr);

        glfwMakeContextCurrent(window_ptr);

        glfwSetKeyCallback(window_ptr, on_keyboard_key);
        glfwSetCharCallback(window_ptr, on_keyboard_character);
        glfwSetMouseButtonCallback(window_ptr, on_mouse_button);
        glfwSetCursorPosCallback(window_ptr, on_mouse_move);
        glfwSetScrollCallback(window_ptr, on_mouse_scroll);
        glfwSetWindowSizeCallback(window_ptr, on_window_resize);
        glfwSetWindowPosCallback(window_ptr, on_window_move);

		//glew
        auto glew_init_result = glewInit();

        if (glew_init_result != GLEW_OK)
        {
            throw std::exception(unsafe_cast<char*>(glewGetErrorString(glew_init_result)));
        }
	}

	void platform_win32_t::app_run_end()
	{
        glfwDestroyWindow(window_ptr);
        glfwTerminate();

        window_ptr = nullptr;
	}

	void platform_win32_t::app_tick_start(float32_t dt)
	{
        glfwPollEvents();

		for (size_t gamepad_index = 0; gamepad_index < input.gamepad_states.size(); ++gamepad_index)
		{
            if (!glfwJoystickPresent(static_cast<int>(gamepad_index)))
			{
				break;
			}

			auto& gamepad_state = input.gamepad_states[gamepad_index];

			int axis_count = 0;
			auto axes = glfwGetJoystickAxes(static_cast<int>(gamepad_index), &axis_count);

			for (auto axis_index = 0; axis_index < axis_count; ++axis_index)
			{
				if (axes[axis_index] != gamepad_state.axes[axis_index])
				{
					input_event_t input_event;
					input_event.device_type = input_event_t::device_type_e::gamepad;
					input_event.gamepad.index = gamepad_index;
					input_event.gamepad.type = input_event_t::gamepad_t::type_e::axis_move;
					input_event.gamepad.axis_index = axis_index;
					input_event.gamepad.axis_value = axes[axis_index];
                    input_event.gamepad.axis_value_delta = axes[axis_index] - gamepad_state.axes[axis_index];

					platform.input.events.push_back(input_event);
				}

				gamepad_state.axes[axis_index] = axes[axis_index];
			}

			int button_count = 0;
			auto buttons = glfwGetJoystickButtons(static_cast<int>(gamepad_index), &button_count);

			for (auto button_index = 0; button_index < button_count; ++button_index)
			{
				if (buttons[button_index] != gamepad_state.buttons[button_index])
				{
					input_event_t input_event;
					input_event.device_type = input_event_t::device_type_e::gamepad;
					input_event.gamepad.index = gamepad_index;
					input_event.gamepad.type = buttons[button_index] == 0 ? input_event_t::gamepad_t::type_e::release : input_event_t::gamepad_t::type_e::press;
                    input_event.gamepad.button_index = button_index;

					platform.input.events.push_back(input_event);
				}

				gamepad_state.buttons[button_index] = buttons[button_index];
			}
		}
	}

	void platform_win32_t::app_tick_end(float32_t dt)
	{
	}

	void platform_win32_t::app_render_start()
	{
        gpu.clear(gpu_t::clear_flag_color | gpu_t::clear_flag_depth);
	}

	void platform_win32_t::app_render_end()
	{
        glfwSwapBuffers(window_ptr);
	}

	bool platform_win32_t::should_exit() const
	{
        return glfwWindowShouldClose(window_ptr) != 0;
	}

    platform_t::screen_size_type platform_win32_t::get_screen_size() const
    {
        screen_size_type screen_size;

        glfwGetWindowSize(window_ptr, &screen_size.x, &screen_size.y);

		return screen_size;
    }

	void platform_win32_t::set_screen_size(const screen_size_type& screen_size) const
	{
        glfwSetWindowSize(window_ptr, screen_size.x, screen_size.y);
	}

    bool platform_win32_t::pop_input_event(input_event_t& input_event)
    {
		if (input.events.empty())
        {
            return false;
        }

		input_event = input.events.front();
		input_event.id = input.event_id;
		input_event.is_consumed = false;

		input.events.pop_front();

		++input.event_id;

        return true;
    }

    bool platform_win32_t::pop_window_event(window_event_t& window_event)
    {
        if (window.events.empty())
        {
            return false;
        }

        window_event = window.events.front();

        window.events.pop_front();

        return true;
    }

	platform_t::cursor_location_type platform_win32_t::get_cursor_location() const
	{
        cursor_location_type cursor_location;

        glfwGetCursorPos(window_ptr, &cursor_location.x, &cursor_location.y);

        //cursor_location.y = get_screen_size().y - cursor_location.y;

		return cursor_location;
	}

	void platform_win32_t::set_cursor_location(const cursor_location_type& cursor_location) const
	{
        glfwSetCursorPos(window_ptr, cursor_location.x, cursor_location.y);
	}

	bool platform_win32_t::is_cursor_hidden() const
	{
        return glfwGetInputMode(window_ptr, GLFW_CURSOR) == GLFW_CURSOR_HIDDEN;
	}

	void platform_win32_t::set_cursor_hidden(bool is_hidden) const
	{
        glfwSetInputMode(window_ptr, GLFW_CURSOR, is_hidden ? GLFW_CURSOR_HIDDEN : GLFW_CURSOR_NORMAL);
	}

	platform_t::window_title_type platform_win32_t::get_window_title() const
	{
		//TODO: implement this
		return std::string();
	}

	void platform_win32_t::set_window_title(const window_title_type& window_title) const
	{
        glfwSetWindowTitle(window_ptr, window_title.c_str());
	}

    platform_t::window_size_type platform_win32_t::get_window_size() const
	{
        window_size_type window_size;

        glfwGetWindowSize(window_ptr, &window_size.x, &window_size.y);

		return window_size;
	}

	void platform_win32_t::set_window_size(const window_size_type& window_size) const
	{
        glfwSetWindowSize(window_ptr, window_size.x, window_size.y);
	}

	platform_t::window_size_type platform_win32_t::get_window_location() const
	{
		vec2_i32_t window_location;

        glfwGetWindowPos(window_ptr, &window_location.x, &window_location.y);

		return window_location;
	}

	void platform_win32_t::set_window_location(const window_size_type& window_location) const
	{
        glfwSetWindowPos(window_ptr, window_location.x, window_location.y);
	}

	std::string platform_win32_t::get_clipboard_string() const
	{
		return glfwGetClipboardString(window_ptr);
	}

	void platform_win32_t::set_clipboard_string(const std::string& clipboard_string) const
	{
		glfwSetClipboardString(window_ptr, clipboard_string.c_str());
	}
}
<|endoftext|>


<commit_before>#define _USE_MATH_DEFINES
#include <math.h>
#include "DCFreeHedron.h"
#include "DCData.h"
#include "TrialMol.h"
#include "../MolSetup.h"
#include "../Forcefield.h"
#include "../PRNG.h"
#include "../../lib/NumLib.h"

namespace cbmc
{

   DCFreeHedron::DCFreeHedron(DCData* data, const mol_setup::MolKind& kind,
			      uint focus, uint prev)
      : data(data), seed(data, focus), hed(data, kind, focus, prev)
   {
         using namespace mol_setup;
         using namespace std;
         vector<Bond> onFocus = AtomBonds(kind, hed.Focus());
         for(uint i = 0; i < onFocus.size(); ++i) {
            if (onFocus[i].a1 == prev) {
               anchorBond = data->ff.bonds.Length(onFocus[i].kind);
	       anchorBondKind = onFocus[i].kind;
               break;
            }
         }
   }

   void DCFreeHedron::PrepareNew(TrialMol& newMol, uint molIndex)
   {
      hed.PrepareNew(newMol, molIndex);
   }

   void DCFreeHedron::PrepareOld(TrialMol& oldMol, uint molIndex)
   {
      hed.PrepareOld(oldMol, molIndex);
      double bondLengthOld = sqrt(oldMol.OldDistSq(hed.Focus(), hed.Prev()));
      oldBondEnergy =  data->ff.bonds.Calc(anchorBondKind, bondLengthOld);
   }

   void DCFreeHedron::BuildNew(TrialMol& newMol, uint molIndex)
   {
      seed.BuildNew(newMol, molIndex);
      PRNG& prng = data->prng;
      const CalculateEnergy& calc = data->calc;

      const EwaldCached *calcEwald = data->calcEwald;

      const Forcefield& ff = data->ff;
      uint nLJTrials = data->nLJTrialsNth;
      double* ljWeights = data->ljWeights;
      double* inter = data->inter;
      double* real = data->real;
      double* self = data->self;
      double* correction = data->correction;

      std::fill_n(inter, nLJTrials, 0.0);
      std::fill_n(self, nLJTrials, 0.0);
      std::fill_n(real, nLJTrials, 0.0);
      std::fill_n(correction, nLJTrials, 0.0);
      std::fill_n(ljWeights, nLJTrials, 0.0);

      //get info about existing geometry
      newMol.ShiftBasis(hed.Focus());
      const XYZ center = newMol.AtomPosition(hed.Focus());
      XYZArray* positions = data->multiPositions;

      for (uint i = 0; i < hed.NumBond(); ++i)
      {
         positions[i].Set(0, newMol.RawRectCoords(hed.BondLength(i),
                                                  hed.Theta(i), hed.Phi(i)));
      }
      //add anchor atom
      positions[hed.NumBond()].Set(0, newMol.RawRectCoords(anchorBond, 0, 0));

      //counting backward to preserve prototype
      for (uint lj = nLJTrials; lj-- > 0;)
      {
         //convert chosen torsion to 3D positions
         RotationMatrix spin =
            RotationMatrix::UniformRandom(prng(), prng(), prng());
         for (uint b = 0; b < hed.NumBond() + 1; ++b)
         {
               //find positions
               positions[b].Set(lj, spin.Apply(positions[b][0]));
               positions[b].Add(lj, center);
         }
      }

      for (uint b = 0; b < hed.NumBond() + 1; ++b)
      {
         data->axes.WrapPBC(positions[b], newMol.GetBox());

      }

      for (uint b = 0; b < hed.NumBond(); ++b)
      {
	 calc.ParticleInter(inter, real, positions[b], hed.Bonded(b),
			    molIndex, newMol.GetBox(), nLJTrials);
#ifdef _OPENMP
#pragma omp parallel sections
#endif
{
#ifdef _OPENMP
#pragma omp section
#endif
	 calcEwald->SwapSelf(self, molIndex, hed.Bonded(b), newMol.GetBox(),
			    nLJTrials);
#ifdef _OPENMP
#pragma omp section
#endif
	 calcEwald->SwapCorrection(correction, newMol, positions, b,
				   hed.bonded,  newMol.GetBox(), nLJTrials,
				   hed.Prev(), false);
}
      }

      calc.ParticleInter(inter, real, positions[hed.NumBond()], hed.Prev(),
                         molIndex, newMol.GetBox(), nLJTrials);

#ifdef _OPENMP
#pragma omp parallel sections
#endif
{
#ifdef _OPENMP
#pragma omp section
#endif
      calcEwald->SwapSelf(self, molIndex, hed.Prev(), newMol.GetBox(),
			    nLJTrials);
#ifdef _OPENMP
#pragma omp section
#endif
      calcEwald->SwapCorrection(correction, newMol, positions, hed.Prev(),
			       hed.bonded, newMol.GetBox(), nLJTrials,
			       hed.Prev(), true);
}

      double stepWeight = 0;
      for (uint lj = 0; lj < nLJTrials; ++lj)
      {
	ljWeights[lj] = exp(-ff.beta * (inter[lj] + real[lj] + self[lj] +
					correction[lj]));
         stepWeight += ljWeights[lj];
      }
      uint winner = prng.PickWeighted(ljWeights, nLJTrials, stepWeight);
      for(uint b = 0; b < hed.NumBond(); ++b)
      {
         newMol.AddAtom(hed.Bonded(b), positions[b][winner]);
      }
      newMol.AddAtom(hed.Prev(), positions[hed.NumBond()][winner]);
      newMol.AddEnergy(Energy(hed.GetEnergy(), hed.GetNonBondedEn(),
			      inter[winner], real[winner],
			      0.0, self[winner], correction[winner]));
      newMol.MultWeight(hed.GetWeight());
      newMol.MultWeight(stepWeight);
   }

   void DCFreeHedron::BuildOld(TrialMol& oldMol, uint molIndex)
   {
      seed.BuildOld(oldMol, molIndex);
      PRNG& prng = data->prng;
      const CalculateEnergy& calc = data->calc;

      const EwaldCached * calcEwald = data->calcEwald;

      const Forcefield& ff = data->ff;
      uint nLJTrials = data->nLJTrialsNth;
      double* ljWeights = data->ljWeights;
      double* inter = data->inter;
      double* real = data->real;
      double* self = data->self;
      double* correction = data->correction;

      std::fill_n(inter, nLJTrials, 0.0);
      std::fill_n(self, nLJTrials, 0.0);
      std::fill_n(real, nLJTrials, 0.0);
      std::fill_n(correction, nLJTrials, 0.0);
      std::fill_n(ljWeights, nLJTrials, 0.0);

      //get info about existing geometry
      oldMol.SetBasis(hed.Focus(), hed.Prev());
      //Calculate OldMol Bond Energy &
      //Calculate phi weight for nTrials using actual theta of OldMol
      hed.ConstrainedAnglesOld(data->nAngleTrials - 1, oldMol, molIndex);
      const XYZ center = oldMol.AtomPosition(hed.Focus());
      XYZArray* positions = data->multiPositions;
      double prevPhi[MAX_BONDS];
      for (uint i = 0; i < hed.NumBond(); ++i)
      {
         //get position and shift to origin
         positions[i].Set(0, oldMol.AtomPosition(hed.Bonded(i)));
         data->axes.UnwrapPBC(positions[i], 0, 1, oldMol.GetBox(), center);
         positions[i].Add(0, -center);
      }
      //add anchor atom
      positions[hed.NumBond()].Set(0, oldMol.AtomPosition(hed.Prev()));
      data->axes.UnwrapPBC(positions[hed.NumBond()], 0, 1,
			   oldMol.GetBox(), center);
      positions[hed.NumBond()].Add(0, -center);

      //counting backward to preserve prototype
      for (uint lj = nLJTrials; lj-- > 1;)
      {
         //convert chosen torsion to 3D positions
         RotationMatrix spin =
            RotationMatrix::UniformRandom(prng(), prng(), prng());
         for (uint b = 0; b < hed.NumBond() + 1; ++b)
         {
            //find positions
            positions[b].Set(lj, spin.Apply(positions[b][0]));
            positions[b].Add(lj, center);
         }
      }

      for (uint b = 0; b < hed.NumBond() + 1; ++b)
      {
         positions[b].Add(0, center);
         data->axes.WrapPBC(positions[b], oldMol.GetBox());
      }

      for (uint b = 0; b < hed.NumBond(); ++b)
      {
	calc.ParticleInter(inter, real, positions[b], hed.Bonded(b),
                            molIndex, oldMol.GetBox(), nLJTrials);

#ifdef _OPENMP
#pragma omp parallel sections
#endif
{
#ifdef _OPENMP
#pragma omp section
#endif
	calcEwald->SwapSelf(self, molIndex, hed.Bonded(b), oldMol.GetBox(),
			   nLJTrials);
#ifdef _OPENMP
#pragma omp section
#endif
	calcEwald->SwapCorrection(correction, oldMol, positions, b,
				  hed.bonded, oldMol.GetBox(), nLJTrials,
				  hed.Prev(), false);
 }
      }
      double stepWeight = 0;
      calc.ParticleInter(inter, real, positions[hed.NumBond()], hed.Prev(),
                         molIndex, oldMol.GetBox(), nLJTrials);

#ifdef _OPENMP
#pragma omp parallel sections
#endif
{
#ifdef _OPENMP
#pragma omp section
#endif
      calcEwald->SwapSelf(self, molIndex, hed.Prev(), oldMol.GetBox(),
			   nLJTrials);
#ifdef _OPENMP
#pragma omp section
#endif
      calcEwald->SwapCorrection(correction, oldMol, positions, hed.NumBond(),
			       hed.bonded, oldMol.GetBox(), nLJTrials,
			       hed.Prev(), true);
}

      for (uint lj = 0; lj < nLJTrials; ++lj)
      {
	stepWeight += exp(-ff.beta * (inter[lj] + real[lj] + self[lj] +
				      correction[lj]));
      }
      for(uint b = 0; b < hed.NumBond(); ++b)
      {
         oldMol.ConfirmOldAtom(hed.Bonded(b));
      }
      oldMol.ConfirmOldAtom(hed.Prev());
      oldMol.AddEnergy(Energy(hed.GetEnergy() + oldBondEnergy +
			      hed.GetOldBondEn(),
			      hed.GetNonBondedEn(),
			      inter[0], real[0], 0.0,
			      self[0], correction[0]));
      oldMol.MultWeight(hed.GetWeight());
      oldMol.MultWeight(stepWeight);
   }

}
<commit_msg>Update DCFreeHedron.cpp<commit_after>#define _USE_MATH_DEFINES
#include <math.h>
#include "DCFreeHedron.h"
#include "DCData.h"
#include "TrialMol.h"
#include "../MolSetup.h"
#include "../Forcefield.h"
#include "../PRNG.h"
#include "../../lib/NumLib.h"

namespace cbmc
{

   DCFreeHedron::DCFreeHedron(DCData* data, const mol_setup::MolKind& kind,
			      uint focus, uint prev)
      : data(data), seed(data, focus), hed(data, kind, focus, prev)
   {
         using namespace mol_setup;
         using namespace std;
         vector<Bond> onFocus = AtomBonds(kind, hed.Focus());
         for(uint i = 0; i < onFocus.size(); ++i) {
            if (onFocus[i].a1 == prev) {
               anchorBond = data->ff.bonds.Length(onFocus[i].kind);
	       anchorBondKind = onFocus[i].kind;
               break;
            }
         }
   }

   void DCFreeHedron::PrepareNew(TrialMol& newMol, uint molIndex)
   {
      hed.PrepareNew(newMol, molIndex);
   }

   void DCFreeHedron::PrepareOld(TrialMol& oldMol, uint molIndex)
   {
      hed.PrepareOld(oldMol, molIndex);
      double bondLengthOld = sqrt(oldMol.OldDistSq(hed.Focus(), hed.Prev()));
      oldBondEnergy =  data->ff.bonds.Calc(anchorBondKind, bondLengthOld);
   }

   void DCFreeHedron::BuildNew(TrialMol& newMol, uint molIndex)
   {
      seed.BuildNew(newMol, molIndex);
      PRNG& prng = data->prng;
      const CalculateEnergy& calc = data->calc;

      const EwaldCached *calcEwald = data->calcEwald;

      const Forcefield& ff = data->ff;
      uint nLJTrials = data->nLJTrialsNth;
      double* ljWeights = data->ljWeights;
      double* inter = data->inter;
      double* real = data->real;
      double* self = data->self;
      double* correction = data->correction;

      std::fill_n(inter, nLJTrials, 0.0);
      std::fill_n(self, nLJTrials, 0.0);
      std::fill_n(real, nLJTrials, 0.0);
      std::fill_n(correction, nLJTrials, 0.0);
      std::fill_n(ljWeights, nLJTrials, 0.0);

      //get info about existing geometry
      newMol.ShiftBasis(hed.Focus());
      const XYZ center = newMol.AtomPosition(hed.Focus());
      XYZArray* positions = data->multiPositions;

      for (uint i = 0; i < hed.NumBond(); ++i)
      {
         positions[i].Set(0, newMol.RawRectCoords(hed.BondLength(i),
                                                  hed.Theta(i), hed.Phi(i)));
      }
      //add anchor atom
      positions[hed.NumBond()].Set(0, newMol.RawRectCoords(anchorBond, 0, 0));

      //counting backward to preserve prototype
      for (uint lj = nLJTrials; lj-- > 0;)
      {
         //convert chosen torsion to 3D positions
         RotationMatrix spin =
            RotationMatrix::UniformRandom(prng(), prng(), prng());
         for (uint b = 0; b < hed.NumBond() + 1; ++b)
         {
               //find positions
               positions[b].Set(lj, spin.Apply(positions[b][0]));
               positions[b].Add(lj, center);
         }
      }

      for (uint b = 0; b < hed.NumBond() + 1; ++b)
      {
         data->axes.WrapPBC(positions[b], newMol.GetBox());

      }

      for (uint b = 0; b < hed.NumBond(); ++b)
      {
	 calc.ParticleInter(inter, real, positions[b], hed.Bonded(b),
			    molIndex, newMol.GetBox(), nLJTrials);
#ifdef _OPENMP
#pragma omp parallel sections
#endif
{
#ifdef _OPENMP
#pragma omp section
#endif
	 calcEwald->SwapSelf(self, molIndex, hed.Bonded(b), newMol.GetBox(),
			    nLJTrials);
#ifdef _OPENMP
#pragma omp section
#endif
	 calcEwald->SwapCorrection(correction, newMol, positions, b,
				   hed.bonded,  newMol.GetBox(), nLJTrials,
				   hed.Prev(), false);
}
      }

      calc.ParticleInter(inter, real, positions[hed.NumBond()], hed.Prev(),
                         molIndex, newMol.GetBox(), nLJTrials);

#ifdef _OPENMP
#pragma omp parallel sections
#endif
{
#ifdef _OPENMP
#pragma omp section
#endif
      calcEwald->SwapSelf(self, molIndex, hed.Prev(), newMol.GetBox(),
			    nLJTrials);
#ifdef _OPENMP
#pragma omp section
#endif
      calcEwald->SwapCorrection(correction, newMol, positions, hed.NumBond(),
			       hed.bonded, newMol.GetBox(), nLJTrials,
			       hed.Prev(), true);
}

      double stepWeight = 0;
      for (uint lj = 0; lj < nLJTrials; ++lj)
      {
	ljWeights[lj] = exp(-ff.beta * (inter[lj] + real[lj] + self[lj] +
					correction[lj]));
         stepWeight += ljWeights[lj];
      }
      uint winner = prng.PickWeighted(ljWeights, nLJTrials, stepWeight);
      for(uint b = 0; b < hed.NumBond(); ++b)
      {
         newMol.AddAtom(hed.Bonded(b), positions[b][winner]);
      }
      newMol.AddAtom(hed.Prev(), positions[hed.NumBond()][winner]);
      newMol.AddEnergy(Energy(hed.GetEnergy(), hed.GetNonBondedEn(),
			      inter[winner], real[winner],
			      0.0, self[winner], correction[winner]));
      newMol.MultWeight(hed.GetWeight());
      newMol.MultWeight(stepWeight);
   }

   void DCFreeHedron::BuildOld(TrialMol& oldMol, uint molIndex)
   {
      seed.BuildOld(oldMol, molIndex);
      PRNG& prng = data->prng;
      const CalculateEnergy& calc = data->calc;

      const EwaldCached * calcEwald = data->calcEwald;

      const Forcefield& ff = data->ff;
      uint nLJTrials = data->nLJTrialsNth;
      double* ljWeights = data->ljWeights;
      double* inter = data->inter;
      double* real = data->real;
      double* self = data->self;
      double* correction = data->correction;

      std::fill_n(inter, nLJTrials, 0.0);
      std::fill_n(self, nLJTrials, 0.0);
      std::fill_n(real, nLJTrials, 0.0);
      std::fill_n(correction, nLJTrials, 0.0);
      std::fill_n(ljWeights, nLJTrials, 0.0);

      //get info about existing geometry
      oldMol.SetBasis(hed.Focus(), hed.Prev());
      //Calculate OldMol Bond Energy &
      //Calculate phi weight for nTrials using actual theta of OldMol
      hed.ConstrainedAnglesOld(data->nAngleTrials - 1, oldMol, molIndex);
      const XYZ center = oldMol.AtomPosition(hed.Focus());
      XYZArray* positions = data->multiPositions;
      double prevPhi[MAX_BONDS];
      for (uint i = 0; i < hed.NumBond(); ++i)
      {
         //get position and shift to origin
         positions[i].Set(0, oldMol.AtomPosition(hed.Bonded(i)));
         data->axes.UnwrapPBC(positions[i], 0, 1, oldMol.GetBox(), center);
         positions[i].Add(0, -center);
      }
      //add anchor atom
      positions[hed.NumBond()].Set(0, oldMol.AtomPosition(hed.Prev()));
      data->axes.UnwrapPBC(positions[hed.NumBond()], 0, 1,
			   oldMol.GetBox(), center);
      positions[hed.NumBond()].Add(0, -center);

      //counting backward to preserve prototype
      for (uint lj = nLJTrials; lj-- > 1;)
      {
         //convert chosen torsion to 3D positions
         RotationMatrix spin =
            RotationMatrix::UniformRandom(prng(), prng(), prng());
         for (uint b = 0; b < hed.NumBond() + 1; ++b)
         {
            //find positions
            positions[b].Set(lj, spin.Apply(positions[b][0]));
            positions[b].Add(lj, center);
         }
      }

      for (uint b = 0; b < hed.NumBond() + 1; ++b)
      {
         positions[b].Add(0, center);
         data->axes.WrapPBC(positions[b], oldMol.GetBox());
      }

      for (uint b = 0; b < hed.NumBond(); ++b)
      {
	calc.ParticleInter(inter, real, positions[b], hed.Bonded(b),
                            molIndex, oldMol.GetBox(), nLJTrials);

#ifdef _OPENMP
#pragma omp parallel sections
#endif
{
#ifdef _OPENMP
#pragma omp section
#endif
	calcEwald->SwapSelf(self, molIndex, hed.Bonded(b), oldMol.GetBox(),
			   nLJTrials);
#ifdef _OPENMP
#pragma omp section
#endif
	calcEwald->SwapCorrection(correction, oldMol, positions, b,
				  hed.bonded, oldMol.GetBox(), nLJTrials,
				  hed.Prev(), false);
 }
      }
      double stepWeight = 0;
      calc.ParticleInter(inter, real, positions[hed.NumBond()], hed.Prev(),
                         molIndex, oldMol.GetBox(), nLJTrials);

#ifdef _OPENMP
#pragma omp parallel sections
#endif
{
#ifdef _OPENMP
#pragma omp section
#endif
      calcEwald->SwapSelf(self, molIndex, hed.Prev(), oldMol.GetBox(),
			   nLJTrials);
#ifdef _OPENMP
#pragma omp section
#endif
      calcEwald->SwapCorrection(correction, oldMol, positions, hed.NumBond(),
			       hed.bonded, oldMol.GetBox(), nLJTrials,
			       hed.Prev(), true);
}

      for (uint lj = 0; lj < nLJTrials; ++lj)
      {
	stepWeight += exp(-ff.beta * (inter[lj] + real[lj] + self[lj] +
				      correction[lj]));
      }
      for(uint b = 0; b < hed.NumBond(); ++b)
      {
         oldMol.ConfirmOldAtom(hed.Bonded(b));
      }
      oldMol.ConfirmOldAtom(hed.Prev());
      oldMol.AddEnergy(Energy(hed.GetEnergy() + oldBondEnergy +
			      hed.GetOldBondEn(),
			      hed.GetNonBondedEn(),
			      inter[0], real[0], 0.0,
			      self[0], correction[0]));
      oldMol.MultWeight(hed.GetWeight());
      oldMol.MultWeight(stepWeight);
   }

}
<|endoftext|>


<commit_before>// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "media/base/audio_buffer.h"

#include "base/logging.h"
#include "media/base/audio_bus.h"
#include "media/base/buffers.h"
#include "media/base/limits.h"

namespace media {

static base::TimeDelta CalculateDuration(int frames, double sample_rate) {
  DCHECK_GT(sample_rate, 0);
  return base::TimeDelta::FromMicroseconds(
      frames * base::Time::kMicrosecondsPerSecond / sample_rate);
}

AudioBuffer::AudioBuffer(SampleFormat sample_format,
                         ChannelLayout channel_layout,
                         int channel_count,
                         int sample_rate,
                         int frame_count,
                         bool create_buffer,
                         const uint8* const* data,
                         const base::TimeDelta timestamp)
    : sample_format_(sample_format),
      channel_layout_(channel_layout),
      channel_count_(channel_count),
      sample_rate_(sample_rate),
      adjusted_frame_count_(frame_count),
      trim_start_(0),
      end_of_stream_(!create_buffer && data == NULL && frame_count == 0),
      timestamp_(timestamp),
      duration_(end_of_stream_
                    ? base::TimeDelta()
                    : CalculateDuration(adjusted_frame_count_, sample_rate_)) {
  CHECK_GE(channel_count_, 0);
  CHECK_LE(channel_count_, limits::kMaxChannels);
  CHECK_GE(frame_count, 0);
  DCHECK(channel_layout == CHANNEL_LAYOUT_DISCRETE ||
         ChannelLayoutToChannelCount(channel_layout) == channel_count);

  int bytes_per_channel = SampleFormatToBytesPerChannel(sample_format);
  DCHECK_LE(bytes_per_channel, kChannelAlignment);
  int data_size = frame_count * bytes_per_channel;

  // Empty buffer?
  if (!create_buffer)
    return;

  if (sample_format == kSampleFormatPlanarF32 ||
      sample_format == kSampleFormatPlanarS16 ||
      sample_format == kSampleFormatPlanarS32) {
    // Planar data, so need to allocate buffer for each channel.
    // Determine per channel data size, taking into account alignment.
    int block_size_per_channel =
        (data_size + kChannelAlignment - 1) & ~(kChannelAlignment - 1);
    DCHECK_GE(block_size_per_channel, data_size);

    // Allocate a contiguous buffer for all the channel data.
    data_.reset(static_cast<uint8*>(base::AlignedAlloc(
        channel_count_ * block_size_per_channel, kChannelAlignment)));
    channel_data_.reserve(channel_count_);

    // Copy each channel's data into the appropriate spot.
    for (int i = 0; i < channel_count_; ++i) {
      channel_data_.push_back(data_.get() + i * block_size_per_channel);
      if (data)
        memcpy(channel_data_[i], data[i], data_size);
    }
    return;
  }

  // Remaining formats are interleaved data.
  DCHECK(sample_format_ == kSampleFormatU8 ||
         sample_format_ == kSampleFormatS16 ||
         sample_format_ == kSampleFormatS32 ||
         sample_format_ == kSampleFormatF32) << sample_format_;
  // Allocate our own buffer and copy the supplied data into it. Buffer must
  // contain the data for all channels.
  data_size *= channel_count_;
  data_.reset(
      static_cast<uint8*>(base::AlignedAlloc(data_size, kChannelAlignment)));
  channel_data_.reserve(1);
  channel_data_.push_back(data_.get());
  if (data)
    memcpy(data_.get(), data[0], data_size);
}

AudioBuffer::~AudioBuffer() {}

// static
scoped_refptr<AudioBuffer> AudioBuffer::CopyFrom(
    SampleFormat sample_format,
    ChannelLayout channel_layout,
    int channel_count,
    int sample_rate,
    int frame_count,
    const uint8* const* data,
    const base::TimeDelta timestamp) {
  // If you hit this CHECK you likely have a bug in a demuxer. Go fix it.
  CHECK_GT(frame_count, 0);  // Otherwise looks like an EOF buffer.
  CHECK(data[0]);
  return make_scoped_refptr(new AudioBuffer(sample_format,
                                            channel_layout,
                                            channel_count,
                                            sample_rate,
                                            frame_count,
                                            true,
                                            data,
                                            timestamp));
}

// static
scoped_refptr<AudioBuffer> AudioBuffer::CreateBuffer(
    SampleFormat sample_format,
    ChannelLayout channel_layout,
    int channel_count,
    int sample_rate,
    int frame_count) {
  CHECK_GT(frame_count, 0);  // Otherwise looks like an EOF buffer.
  return make_scoped_refptr(new AudioBuffer(sample_format,
                                            channel_layout,
                                            channel_count,
                                            sample_rate,
                                            frame_count,
                                            true,
                                            NULL,
                                            kNoTimestamp()));
}

// static
scoped_refptr<AudioBuffer> AudioBuffer::CreateEmptyBuffer(
    ChannelLayout channel_layout,
    int channel_count,
    int sample_rate,
    int frame_count,
    const base::TimeDelta timestamp) {
  CHECK_GT(frame_count, 0);  // Otherwise looks like an EOF buffer.
  // Since data == NULL, format doesn't matter.
  return make_scoped_refptr(new AudioBuffer(kSampleFormatF32,
                                            channel_layout,
                                            channel_count,
                                            sample_rate,
                                            frame_count,
                                            false,
                                            NULL,
                                            timestamp));
}

// static
scoped_refptr<AudioBuffer> AudioBuffer::CreateEOSBuffer() {
  return make_scoped_refptr(new AudioBuffer(kUnknownSampleFormat,
                                            CHANNEL_LAYOUT_NONE,
                                            0,
                                            0,
                                            0,
                                            false,
                                            NULL,
                                            kNoTimestamp()));
}

// Convert int16 values in the range [INT16_MIN, INT16_MAX] to [-1.0, 1.0].
static inline float ConvertS16ToFloat(int16 value) {
  return value * (value < 0 ? -1.0f / std::numeric_limits<int16>::min()
                            : 1.0f / std::numeric_limits<int16>::max());
}

void AudioBuffer::ReadFrames(int frames_to_copy,
                             int source_frame_offset,
                             int dest_frame_offset,
                             AudioBus* dest) {
  // Deinterleave each channel (if necessary) and convert to 32bit
  // floating-point with nominal range -1.0 -> +1.0 (if necessary).

  // |dest| must have the same number of channels, and the number of frames
  // specified must be in range.
  DCHECK(!end_of_stream());
  DCHECK_EQ(dest->channels(), channel_count_);
  DCHECK_LE(source_frame_offset + frames_to_copy, adjusted_frame_count_);
  DCHECK_LE(dest_frame_offset + frames_to_copy, dest->frames());

  // Move the start past any frames that have been trimmed.
  source_frame_offset += trim_start_;

  if (!data_) {
    // Special case for an empty buffer.
    dest->ZeroFramesPartial(dest_frame_offset, frames_to_copy);
    return;
  }

  if (sample_format_ == kSampleFormatPlanarF32) {
    // Format is planar float32. Copy the data from each channel as a block.
    for (int ch = 0; ch < channel_count_; ++ch) {
      const float* source_data =
          reinterpret_cast<const float*>(channel_data_[ch]) +
          source_frame_offset;
      memcpy(dest->channel(ch) + dest_frame_offset,
             source_data,
             sizeof(float) * frames_to_copy);
    }
    return;
  }

  if (sample_format_ == kSampleFormatPlanarS16) {
    // Format is planar signed16. Convert each value into float and insert into
    // output channel data.
    for (int ch = 0; ch < channel_count_; ++ch) {
      const int16* source_data =
          reinterpret_cast<const int16*>(channel_data_[ch]) +
          source_frame_offset;
      float* dest_data = dest->channel(ch) + dest_frame_offset;
      for (int i = 0; i < frames_to_copy; ++i) {
        dest_data[i] = ConvertS16ToFloat(source_data[i]);
      }
    }
    return;
  }

  if (sample_format_ == kSampleFormatF32) {
    // Format is interleaved float32. Copy the data into each channel.
    const float* source_data = reinterpret_cast<const float*>(data_.get()) +
                               source_frame_offset * channel_count_;
    for (int ch = 0; ch < channel_count_; ++ch) {
      float* dest_data = dest->channel(ch) + dest_frame_offset;
      for (int i = 0, offset = ch; i < frames_to_copy;
           ++i, offset += channel_count_) {
        dest_data[i] = source_data[offset];
      }
    }
    return;
  }

  // Remaining formats are integer interleaved data. Use the deinterleaving code
  // in AudioBus to copy the data.
  DCHECK(sample_format_ == kSampleFormatU8 ||
         sample_format_ == kSampleFormatS16 ||
         sample_format_ == kSampleFormatS32);
  int bytes_per_channel = SampleFormatToBytesPerChannel(sample_format_);
  int frame_size = channel_count_ * bytes_per_channel;
  const uint8* source_data = data_.get() + source_frame_offset * frame_size;
  dest->FromInterleavedPartial(
      source_data, dest_frame_offset, frames_to_copy, bytes_per_channel);
}

static inline int32 ConvertS16ToS32(int16 value) {
  return static_cast<int32>(value) << 16;
}

static inline int32 ConvertF32ToS32(float value) {
  return static_cast<int32>(value < 0
                                ? (-value) * std::numeric_limits<int32>::min()
                                : value * std::numeric_limits<int32>::max());
}

// No need for conversion. Return value as is. Keeping function to align with
// code structure.
static inline int32 ConvertS32ToS32(int32 value) {
  return value;
}

template <class Target, typename Converter>
void InterleaveToS32(const std::vector<uint8*>& channel_data,
                     size_t frames_to_copy,
                     int trim_start,
                     int32* dest_data,
                     Converter convert_func) {
  for (size_t ch = 0; ch < channel_data.size(); ++ch) {
    const Target* source_data =
        reinterpret_cast<const Target*>(channel_data[ch]) + trim_start;
    for (size_t i = 0, offset = ch; i < frames_to_copy;
         ++i, offset += channel_data.size()) {
      dest_data[offset] = convert_func(source_data[i]);
    }
  }
}

void AudioBuffer::ReadFramesInterleavedS32(int frames_to_copy,
                                           int32* dest_data) {
  DCHECK_LE(frames_to_copy, adjusted_frame_count_);

  switch (sample_format_) {
    case kSampleFormatU8:
      NOTIMPLEMENTED();
      break;
    case kSampleFormatS16:
      // Format is interleaved signed16. Convert each value into int32 and
      // insert into output channel data.
      InterleaveToS32<int16>(channel_data_,
                             frames_to_copy * channel_count_,
                             trim_start_,
                             dest_data,
                             ConvertS16ToS32);
      break;
    case kSampleFormatS32: {
      // Format is interleaved signed32; just copy the data.
      const int32* source_data =
          reinterpret_cast<const int32*>(channel_data_[0]) + trim_start_;
      memcpy(dest_data,
             source_data,
             frames_to_copy * channel_count_ * sizeof(int32));
    } break;
    case kSampleFormatF32:
      // Format is interleaved float. Convert each value into int32 and insert
      // into output channel data.
      InterleaveToS32<float>(channel_data_,
                             frames_to_copy * channel_count_,
                             trim_start_,
                             dest_data,
                             ConvertF32ToS32);
      break;
    case kSampleFormatPlanarS16:
      // Format is planar signed 16 bit. Convert each value into int32 and
      // insert into output channel data.
      InterleaveToS32<int16>(channel_data_,
                             frames_to_copy,
                             trim_start_,
                             dest_data,
                             ConvertS16ToS32);
      break;
    case kSampleFormatPlanarF32:
      // Format is planar float. Convert each value into int32 and insert into
      // output channel data.
      InterleaveToS32<float>(channel_data_,
                             frames_to_copy,
                             trim_start_,
                             dest_data,
                             ConvertF32ToS32);
      break;
    case kSampleFormatPlanarS32:
      // Format is planar signed 32 bit. Convert each value into int32 and
      // insert into output channel data.
      InterleaveToS32<int32>(channel_data_,
                             frames_to_copy,
                             trim_start_,
                             dest_data,
                             ConvertS32ToS32);
    case kUnknownSampleFormat:
      NOTREACHED();
      break;
  }
}

void AudioBuffer::TrimStart(int frames_to_trim) {
  CHECK_GE(frames_to_trim, 0);
  CHECK_LE(frames_to_trim, adjusted_frame_count_);

  // Adjust the number of frames in this buffer and where the start really is.
  adjusted_frame_count_ -= frames_to_trim;
  trim_start_ += frames_to_trim;

  // Adjust timestamp_ and duration_ to reflect the smaller number of frames.
  const base::TimeDelta old_duration = duration_;
  duration_ = CalculateDuration(adjusted_frame_count_, sample_rate_);
  timestamp_ += old_duration - duration_;
}

void AudioBuffer::TrimEnd(int frames_to_trim) {
  CHECK_GE(frames_to_trim, 0);
  CHECK_LE(frames_to_trim, adjusted_frame_count_);

  // Adjust the number of frames and duration for this buffer.
  adjusted_frame_count_ -= frames_to_trim;
  duration_ = CalculateDuration(adjusted_frame_count_, sample_rate_);
}

void AudioBuffer::TrimRange(int start, int end) {
  CHECK_GE(start, 0);
  CHECK_LE(end, adjusted_frame_count_);

  const int frames_to_trim = end - start;
  CHECK_GE(frames_to_trim, 0);
  CHECK_LE(frames_to_trim, adjusted_frame_count_);

  const int bytes_per_channel = SampleFormatToBytesPerChannel(sample_format_);
  const int frames_to_copy = adjusted_frame_count_ - end;
  if (frames_to_copy > 0) {
    switch (sample_format_) {
      case kSampleFormatPlanarS16:
      case kSampleFormatPlanarF32:
      case kSampleFormatPlanarS32:
        // Planar data must be shifted per channel.
        for (int ch = 0; ch < channel_count_; ++ch) {
          memmove(channel_data_[ch] + (trim_start_ + start) * bytes_per_channel,
                  channel_data_[ch] + (trim_start_ + end) * bytes_per_channel,
                  bytes_per_channel * frames_to_copy);
        }
        break;
      case kSampleFormatU8:
      case kSampleFormatS16:
      case kSampleFormatS32:
      case kSampleFormatF32: {
        // Interleaved data can be shifted all at once.
        const int frame_size = channel_count_ * bytes_per_channel;
        memmove(channel_data_[0] + (trim_start_ + start) * frame_size,
                channel_data_[0] + (trim_start_ + end) * frame_size,
                frame_size * frames_to_copy);
        break;
      }
      case kUnknownSampleFormat:
        NOTREACHED() << "Invalid sample format!";
    }
  } else {
    CHECK_EQ(frames_to_copy, 0);
  }

  // Trim the leftover data off the end of the buffer and update duration.
  TrimEnd(frames_to_trim);
}

}  // namespace media
<commit_msg>media:AudioBuffer : Add missing break statement<commit_after>// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "media/base/audio_buffer.h"

#include "base/logging.h"
#include "media/base/audio_bus.h"
#include "media/base/buffers.h"
#include "media/base/limits.h"

namespace media {

static base::TimeDelta CalculateDuration(int frames, double sample_rate) {
  DCHECK_GT(sample_rate, 0);
  return base::TimeDelta::FromMicroseconds(
      frames * base::Time::kMicrosecondsPerSecond / sample_rate);
}

AudioBuffer::AudioBuffer(SampleFormat sample_format,
                         ChannelLayout channel_layout,
                         int channel_count,
                         int sample_rate,
                         int frame_count,
                         bool create_buffer,
                         const uint8* const* data,
                         const base::TimeDelta timestamp)
    : sample_format_(sample_format),
      channel_layout_(channel_layout),
      channel_count_(channel_count),
      sample_rate_(sample_rate),
      adjusted_frame_count_(frame_count),
      trim_start_(0),
      end_of_stream_(!create_buffer && data == NULL && frame_count == 0),
      timestamp_(timestamp),
      duration_(end_of_stream_
                    ? base::TimeDelta()
                    : CalculateDuration(adjusted_frame_count_, sample_rate_)) {
  CHECK_GE(channel_count_, 0);
  CHECK_LE(channel_count_, limits::kMaxChannels);
  CHECK_GE(frame_count, 0);
  DCHECK(channel_layout == CHANNEL_LAYOUT_DISCRETE ||
         ChannelLayoutToChannelCount(channel_layout) == channel_count);

  int bytes_per_channel = SampleFormatToBytesPerChannel(sample_format);
  DCHECK_LE(bytes_per_channel, kChannelAlignment);
  int data_size = frame_count * bytes_per_channel;

  // Empty buffer?
  if (!create_buffer)
    return;

  if (sample_format == kSampleFormatPlanarF32 ||
      sample_format == kSampleFormatPlanarS16 ||
      sample_format == kSampleFormatPlanarS32) {
    // Planar data, so need to allocate buffer for each channel.
    // Determine per channel data size, taking into account alignment.
    int block_size_per_channel =
        (data_size + kChannelAlignment - 1) & ~(kChannelAlignment - 1);
    DCHECK_GE(block_size_per_channel, data_size);

    // Allocate a contiguous buffer for all the channel data.
    data_.reset(static_cast<uint8*>(base::AlignedAlloc(
        channel_count_ * block_size_per_channel, kChannelAlignment)));
    channel_data_.reserve(channel_count_);

    // Copy each channel's data into the appropriate spot.
    for (int i = 0; i < channel_count_; ++i) {
      channel_data_.push_back(data_.get() + i * block_size_per_channel);
      if (data)
        memcpy(channel_data_[i], data[i], data_size);
    }
    return;
  }

  // Remaining formats are interleaved data.
  DCHECK(sample_format_ == kSampleFormatU8 ||
         sample_format_ == kSampleFormatS16 ||
         sample_format_ == kSampleFormatS32 ||
         sample_format_ == kSampleFormatF32) << sample_format_;
  // Allocate our own buffer and copy the supplied data into it. Buffer must
  // contain the data for all channels.
  data_size *= channel_count_;
  data_.reset(
      static_cast<uint8*>(base::AlignedAlloc(data_size, kChannelAlignment)));
  channel_data_.reserve(1);
  channel_data_.push_back(data_.get());
  if (data)
    memcpy(data_.get(), data[0], data_size);
}

AudioBuffer::~AudioBuffer() {}

// static
scoped_refptr<AudioBuffer> AudioBuffer::CopyFrom(
    SampleFormat sample_format,
    ChannelLayout channel_layout,
    int channel_count,
    int sample_rate,
    int frame_count,
    const uint8* const* data,
    const base::TimeDelta timestamp) {
  // If you hit this CHECK you likely have a bug in a demuxer. Go fix it.
  CHECK_GT(frame_count, 0);  // Otherwise looks like an EOF buffer.
  CHECK(data[0]);
  return make_scoped_refptr(new AudioBuffer(sample_format,
                                            channel_layout,
                                            channel_count,
                                            sample_rate,
                                            frame_count,
                                            true,
                                            data,
                                            timestamp));
}

// static
scoped_refptr<AudioBuffer> AudioBuffer::CreateBuffer(
    SampleFormat sample_format,
    ChannelLayout channel_layout,
    int channel_count,
    int sample_rate,
    int frame_count) {
  CHECK_GT(frame_count, 0);  // Otherwise looks like an EOF buffer.
  return make_scoped_refptr(new AudioBuffer(sample_format,
                                            channel_layout,
                                            channel_count,
                                            sample_rate,
                                            frame_count,
                                            true,
                                            NULL,
                                            kNoTimestamp()));
}

// static
scoped_refptr<AudioBuffer> AudioBuffer::CreateEmptyBuffer(
    ChannelLayout channel_layout,
    int channel_count,
    int sample_rate,
    int frame_count,
    const base::TimeDelta timestamp) {
  CHECK_GT(frame_count, 0);  // Otherwise looks like an EOF buffer.
  // Since data == NULL, format doesn't matter.
  return make_scoped_refptr(new AudioBuffer(kSampleFormatF32,
                                            channel_layout,
                                            channel_count,
                                            sample_rate,
                                            frame_count,
                                            false,
                                            NULL,
                                            timestamp));
}

// static
scoped_refptr<AudioBuffer> AudioBuffer::CreateEOSBuffer() {
  return make_scoped_refptr(new AudioBuffer(kUnknownSampleFormat,
                                            CHANNEL_LAYOUT_NONE,
                                            0,
                                            0,
                                            0,
                                            false,
                                            NULL,
                                            kNoTimestamp()));
}

// Convert int16 values in the range [INT16_MIN, INT16_MAX] to [-1.0, 1.0].
static inline float ConvertS16ToFloat(int16 value) {
  return value * (value < 0 ? -1.0f / std::numeric_limits<int16>::min()
                            : 1.0f / std::numeric_limits<int16>::max());
}

void AudioBuffer::ReadFrames(int frames_to_copy,
                             int source_frame_offset,
                             int dest_frame_offset,
                             AudioBus* dest) {
  // Deinterleave each channel (if necessary) and convert to 32bit
  // floating-point with nominal range -1.0 -> +1.0 (if necessary).

  // |dest| must have the same number of channels, and the number of frames
  // specified must be in range.
  DCHECK(!end_of_stream());
  DCHECK_EQ(dest->channels(), channel_count_);
  DCHECK_LE(source_frame_offset + frames_to_copy, adjusted_frame_count_);
  DCHECK_LE(dest_frame_offset + frames_to_copy, dest->frames());

  // Move the start past any frames that have been trimmed.
  source_frame_offset += trim_start_;

  if (!data_) {
    // Special case for an empty buffer.
    dest->ZeroFramesPartial(dest_frame_offset, frames_to_copy);
    return;
  }

  if (sample_format_ == kSampleFormatPlanarF32) {
    // Format is planar float32. Copy the data from each channel as a block.
    for (int ch = 0; ch < channel_count_; ++ch) {
      const float* source_data =
          reinterpret_cast<const float*>(channel_data_[ch]) +
          source_frame_offset;
      memcpy(dest->channel(ch) + dest_frame_offset,
             source_data,
             sizeof(float) * frames_to_copy);
    }
    return;
  }

  if (sample_format_ == kSampleFormatPlanarS16) {
    // Format is planar signed16. Convert each value into float and insert into
    // output channel data.
    for (int ch = 0; ch < channel_count_; ++ch) {
      const int16* source_data =
          reinterpret_cast<const int16*>(channel_data_[ch]) +
          source_frame_offset;
      float* dest_data = dest->channel(ch) + dest_frame_offset;
      for (int i = 0; i < frames_to_copy; ++i) {
        dest_data[i] = ConvertS16ToFloat(source_data[i]);
      }
    }
    return;
  }

  if (sample_format_ == kSampleFormatF32) {
    // Format is interleaved float32. Copy the data into each channel.
    const float* source_data = reinterpret_cast<const float*>(data_.get()) +
                               source_frame_offset * channel_count_;
    for (int ch = 0; ch < channel_count_; ++ch) {
      float* dest_data = dest->channel(ch) + dest_frame_offset;
      for (int i = 0, offset = ch; i < frames_to_copy;
           ++i, offset += channel_count_) {
        dest_data[i] = source_data[offset];
      }
    }
    return;
  }

  // Remaining formats are integer interleaved data. Use the deinterleaving code
  // in AudioBus to copy the data.
  DCHECK(sample_format_ == kSampleFormatU8 ||
         sample_format_ == kSampleFormatS16 ||
         sample_format_ == kSampleFormatS32);
  int bytes_per_channel = SampleFormatToBytesPerChannel(sample_format_);
  int frame_size = channel_count_ * bytes_per_channel;
  const uint8* source_data = data_.get() + source_frame_offset * frame_size;
  dest->FromInterleavedPartial(
      source_data, dest_frame_offset, frames_to_copy, bytes_per_channel);
}

static inline int32 ConvertS16ToS32(int16 value) {
  return static_cast<int32>(value) << 16;
}

static inline int32 ConvertF32ToS32(float value) {
  return static_cast<int32>(value < 0
                                ? (-value) * std::numeric_limits<int32>::min()
                                : value * std::numeric_limits<int32>::max());
}

// No need for conversion. Return value as is. Keeping function to align with
// code structure.
static inline int32 ConvertS32ToS32(int32 value) {
  return value;
}

template <class Target, typename Converter>
void InterleaveToS32(const std::vector<uint8*>& channel_data,
                     size_t frames_to_copy,
                     int trim_start,
                     int32* dest_data,
                     Converter convert_func) {
  for (size_t ch = 0; ch < channel_data.size(); ++ch) {
    const Target* source_data =
        reinterpret_cast<const Target*>(channel_data[ch]) + trim_start;
    for (size_t i = 0, offset = ch; i < frames_to_copy;
         ++i, offset += channel_data.size()) {
      dest_data[offset] = convert_func(source_data[i]);
    }
  }
}

void AudioBuffer::ReadFramesInterleavedS32(int frames_to_copy,
                                           int32* dest_data) {
  DCHECK_LE(frames_to_copy, adjusted_frame_count_);

  switch (sample_format_) {
    case kSampleFormatU8:
      NOTIMPLEMENTED();
      break;
    case kSampleFormatS16:
      // Format is interleaved signed16. Convert each value into int32 and
      // insert into output channel data.
      InterleaveToS32<int16>(channel_data_,
                             frames_to_copy * channel_count_,
                             trim_start_,
                             dest_data,
                             ConvertS16ToS32);
      break;
    case kSampleFormatS32: {
      // Format is interleaved signed32; just copy the data.
      const int32* source_data =
          reinterpret_cast<const int32*>(channel_data_[0]) + trim_start_;
      memcpy(dest_data,
             source_data,
             frames_to_copy * channel_count_ * sizeof(int32));
    } break;
    case kSampleFormatF32:
      // Format is interleaved float. Convert each value into int32 and insert
      // into output channel data.
      InterleaveToS32<float>(channel_data_,
                             frames_to_copy * channel_count_,
                             trim_start_,
                             dest_data,
                             ConvertF32ToS32);
      break;
    case kSampleFormatPlanarS16:
      // Format is planar signed 16 bit. Convert each value into int32 and
      // insert into output channel data.
      InterleaveToS32<int16>(channel_data_,
                             frames_to_copy,
                             trim_start_,
                             dest_data,
                             ConvertS16ToS32);
      break;
    case kSampleFormatPlanarF32:
      // Format is planar float. Convert each value into int32 and insert into
      // output channel data.
      InterleaveToS32<float>(channel_data_,
                             frames_to_copy,
                             trim_start_,
                             dest_data,
                             ConvertF32ToS32);
      break;
    case kSampleFormatPlanarS32:
      // Format is planar signed 32 bit. Convert each value into int32 and
      // insert into output channel data.
      InterleaveToS32<int32>(channel_data_,
                             frames_to_copy,
                             trim_start_,
                             dest_data,
                             ConvertS32ToS32);
      break;
    case kUnknownSampleFormat:
      NOTREACHED();
      break;
  }
}

void AudioBuffer::TrimStart(int frames_to_trim) {
  CHECK_GE(frames_to_trim, 0);
  CHECK_LE(frames_to_trim, adjusted_frame_count_);

  // Adjust the number of frames in this buffer and where the start really is.
  adjusted_frame_count_ -= frames_to_trim;
  trim_start_ += frames_to_trim;

  // Adjust timestamp_ and duration_ to reflect the smaller number of frames.
  const base::TimeDelta old_duration = duration_;
  duration_ = CalculateDuration(adjusted_frame_count_, sample_rate_);
  timestamp_ += old_duration - duration_;
}

void AudioBuffer::TrimEnd(int frames_to_trim) {
  CHECK_GE(frames_to_trim, 0);
  CHECK_LE(frames_to_trim, adjusted_frame_count_);

  // Adjust the number of frames and duration for this buffer.
  adjusted_frame_count_ -= frames_to_trim;
  duration_ = CalculateDuration(adjusted_frame_count_, sample_rate_);
}

void AudioBuffer::TrimRange(int start, int end) {
  CHECK_GE(start, 0);
  CHECK_LE(end, adjusted_frame_count_);

  const int frames_to_trim = end - start;
  CHECK_GE(frames_to_trim, 0);
  CHECK_LE(frames_to_trim, adjusted_frame_count_);

  const int bytes_per_channel = SampleFormatToBytesPerChannel(sample_format_);
  const int frames_to_copy = adjusted_frame_count_ - end;
  if (frames_to_copy > 0) {
    switch (sample_format_) {
      case kSampleFormatPlanarS16:
      case kSampleFormatPlanarF32:
      case kSampleFormatPlanarS32:
        // Planar data must be shifted per channel.
        for (int ch = 0; ch < channel_count_; ++ch) {
          memmove(channel_data_[ch] + (trim_start_ + start) * bytes_per_channel,
                  channel_data_[ch] + (trim_start_ + end) * bytes_per_channel,
                  bytes_per_channel * frames_to_copy);
        }
        break;
      case kSampleFormatU8:
      case kSampleFormatS16:
      case kSampleFormatS32:
      case kSampleFormatF32: {
        // Interleaved data can be shifted all at once.
        const int frame_size = channel_count_ * bytes_per_channel;
        memmove(channel_data_[0] + (trim_start_ + start) * frame_size,
                channel_data_[0] + (trim_start_ + end) * frame_size,
                frame_size * frames_to_copy);
        break;
      }
      case kUnknownSampleFormat:
        NOTREACHED() << "Invalid sample format!";
    }
  } else {
    CHECK_EQ(frames_to_copy, 0);
  }

  // Trim the leftover data off the end of the buffer and update duration.
  TrimEnd(frames_to_trim);
}

}  // namespace media
<|endoftext|>


<commit_before>#include <boost/assert.hpp>

#include "replies.pb.h"
#include "reply_message.h"

void traffic::ReplyMessage::serialize(std::string &output) const
{
	_reply_msg->SerializeToString(&output);
}

traffic::ReplyMessage::ReplyMessage()
:
	_reply_msg(new replies::Reply())
{
	_reply_msg->set_version(1U);
}

void
traffic::SummaryReply::add_entry(std::string const &address,
				 traffic_t in, traffic_t out)
{
	replies::SummaryEntry * entry(_summary_msg->add_data());
	entry->set_address(address);
	entry->set_sum_traffic_in(in);
	entry->set_sum_traffic_out(out);
}

traffic::SummaryReply::SummaryReply()
:
	_summary_msg(_reply_msg->mutable_summary())
{ }

void
traffic::StatisticReply::add_slice(time_t timestamp,
				   traffic_t in, traffic_t out)
{
	replies::StatisticSlice * slice(_statistic_msg->add_slice());
	slice->set_timestamp(timestamp);
	slice->set_traffic_in(in);
	slice->set_traffic_out(out);
}

void
traffic::StatisticReply::available_interval(TimeRange const &range)
{
	BOOST_ASSERT(range.valid() && "Given range not valid");
	if (! range.valid())
		return;

	common::TimeRange * range_msg(
			_statistic_msg->mutable_available_range());
	range_msg->set_start(range.start());
	range_msg->set_end(range.end());
}

traffic::StatisticReply::StatisticReply(time_t interval,
					traffic_t in, traffic_t out)
:
	_statistic_msg(_reply_msg->mutable_statistic())
{
	_statistic_msg->set_data_interval_step(interval);
	_statistic_msg->set_sum_traffic_in(in);
	_statistic_msg->set_sum_traffic_out(out);
}

traffic::ErrorReply::ErrorReply(uint32_t code, std::string const &msg)
:
	_error_msg(_reply_msg->mutable_error())
{
	_error_msg->set_code(code);
	_error_msg->set_reason(msg);
}
<commit_msg>Drop the assertion for wron intervals<commit_after>#include <iostream>

#include "replies.pb.h"
#include "reply_message.h"

void traffic::ReplyMessage::serialize(std::string &output) const
{
	_reply_msg->SerializeToString(&output);
}

traffic::ReplyMessage::ReplyMessage()
:
	_reply_msg(new replies::Reply())
{
	_reply_msg->set_version(1U);
}

void
traffic::SummaryReply::add_entry(std::string const &address,
				 traffic_t in, traffic_t out)
{
	replies::SummaryEntry * entry(_summary_msg->add_data());
	entry->set_address(address);
	entry->set_sum_traffic_in(in);
	entry->set_sum_traffic_out(out);
}

traffic::SummaryReply::SummaryReply()
:
	_summary_msg(_reply_msg->mutable_summary())
{ }

void
traffic::StatisticReply::add_slice(time_t timestamp,
				   traffic_t in, traffic_t out)
{
	replies::StatisticSlice * slice(_statistic_msg->add_slice());
	slice->set_timestamp(timestamp);
	slice->set_traffic_in(in);
	slice->set_traffic_out(out);
}

void
traffic::StatisticReply::available_interval(TimeRange const &range)
{
	if (! range.valid()) {
		std::cerr << "Invalid TimeRange - ignore it." << std::endl;
		return;
	}

	common::TimeRange * range_msg(
			_statistic_msg->mutable_available_range());
	range_msg->set_start(range.start());
	range_msg->set_end(range.end());
}

traffic::StatisticReply::StatisticReply(time_t interval,
					traffic_t in, traffic_t out)
:
	_statistic_msg(_reply_msg->mutable_statistic())
{
	_statistic_msg->set_data_interval_step(interval);
	_statistic_msg->set_sum_traffic_in(in);
	_statistic_msg->set_sum_traffic_out(out);
}

traffic::ErrorReply::ErrorReply(uint32_t code, std::string const &msg)
:
	_error_msg(_reply_msg->mutable_error())
{
	_error_msg->set_code(code);
	_error_msg->set_reason(msg);
}
<|endoftext|>


<commit_before>/* bzflag
* Copyright (c) 1993 - 2005 Tim Riker
*
* This package is free software;  you can redistribute it and/or
* modify it under the terms of the license found in the file
* named COPYING that should have accompanied this file.
*
* THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/

#ifdef _MSC_VER
#pragma warning( 4: 4786)
#define _WINSOCK2API_
#endif

// class interface header
#include "URLManager.h"

// system headers
#ifdef _WIN32
#include <winsock.h>
#endif
#ifdef HAVE_CURL
#include <curl/curl.h>
#endif
#include <iostream>

// common implementation headers
#include "bzfio.h"
#include "StateDatabase.h"

template <>
URLManager* Singleton<URLManager>::_instance = (URLManager*)0;

#ifdef HAVE_CURL

static size_t writeFunction(void *ptr, size_t size, size_t nmemb, void *stream);

bool URLManager::getURL(const std::string& URL, std::string &data)
{
  clearInternal();

  if (!beginGet(URL))
    return false;

  char* newData = (char*)malloc(theLen + 1);
  memcpy(newData, theData, theLen);
  newData[theLen] = 0;

  data = newData;
  free(newData);

  return true;
}

bool URLManager::getURL(const std::string& URL, void **data, unsigned int& size)
{
  clearInternal();

  if (!beginGet(URL))
    return false;

  *data = malloc(theLen);
  memcpy(*data, theData, theLen);
  size = theLen;
  return true;
}

bool URLManager::getFileTime(const std::string& URL, time_t& t)
{
//  return false;

  bool retcode = true;
  CURLcode result;

  float timeout = 15;
  if (BZDB.isSet("httpTimeout")) {
    timeout = BZDB.eval("httpTimeout");
  }

#if LIBCURL_VERSION_NUM >= 0x070a00
  result = curl_easy_setopt((CURL*)easyHandle, CURLOPT_NOSIGNAL, true);
  if (result) {
    DEBUG1("Something wrong with CURL; Error: %d\n", result);
    retcode = false;
  }
#endif

  result = curl_easy_setopt((CURL*)easyHandle, CURLOPT_TIMEOUT, timeout);
  if (result) {
    DEBUG1("Something wrong with CURL; Error: %d\n", result);
    retcode = false;
  }

  result = curl_easy_setopt((CURL*)easyHandle, CURLOPT_NOBODY, 1);
  if (result) {
    DEBUG1("Something wrong with CURL; Error: %d\n", result);
    retcode = false;
  }

  result = curl_easy_setopt((CURL*)easyHandle, CURLOPT_URL, URL.c_str());
  if (result) {
    DEBUG1("Something wrong with CURL; Error: %d\n", result);
    retcode = false;
  }

  // FIXME: This could block for a _long_ time.
  result = curl_easy_perform((CURL*)easyHandle);
  if (result == (CURLcode)CURLOPT_ERRORBUFFER) {
    DEBUG1("Error: server reported: %d\n", result);
    retcode = false;
  } else if (result) {
    DEBUG1("Something wrong with CURL; Error: %d\n", result);
    retcode = false;
  }

  long filetime = 42;
  result = curl_easy_getinfo((CURL*)easyHandle, CURLINFO_FILETIME, &filetime);
  if (result) {
    DEBUG1("Something wrong with CURL; Error: %d\n", result);
    retcode = false;
    t = 0;
  } else {
    t = (time_t)filetime;
  }

  result = curl_easy_setopt((CURL*)easyHandle, CURLOPT_URL, NULL);
  if (result) {
    DEBUG1("Something wrong with CURL; Error: %d\n", result);
    retcode = false;
  }

  result = curl_easy_setopt((CURL*)easyHandle, CURLOPT_NOBODY, 0);
  if (result) {
    DEBUG1("Something wrong with CURL; Error: %d\n", result);
    retcode = false;
  }

  return retcode;
}

void URLManager::freeURLData(void *data)
{
  free(data);
}

URLManager::URLManager()
{
  easyHandle = NULL;
  theData = NULL;
  theLen = 0;

#if LIBCURL_VERSION_NUM >= 0x070a00
  CURLcode curlResult;
  if ((curlResult = curl_global_init(CURL_GLOBAL_NOTHING)))
    DEBUG1("Unexpected error from libcurl; Error: %d\n", curlResult);
#endif

  easyHandle = curl_easy_init();
  if (!easyHandle) {
    DEBUG1("Something wrong with CURL\n");
    return;
  }

  CURLcode result = curl_easy_setopt((CURL*)easyHandle, CURLOPT_WRITEFUNCTION, writeFunction);
  if (result)
    DEBUG1("Something wrong with CURL; Error: %d\n", result);

  result = curl_easy_setopt((CURL*)easyHandle, CURLOPT_FILE, this);
  if (result)
    DEBUG1("Something wrong with CURL; Error: %d\n", result);

  result = curl_easy_setopt((CURL*)easyHandle, CURLOPT_FILETIME, 1);
  if (result)
    DEBUG1("Something wrong with CURL; Error: %d\n", result);
}

URLManager::~URLManager()
{
  clearInternal();

  if (easyHandle)
    curl_easy_cleanup((CURL*)easyHandle);

#if LIBCURL_VERSION_NUM >= 0x070a00
  curl_global_cleanup();
#endif
}

void URLManager::collectData(char* ptr, int len)
{
  unsigned char	*newData = (unsigned char*)malloc(theLen + len);
  if (theData)
    memcpy(newData, theData, theLen);

  memcpy(&(newData[theLen]), ptr, len);
  theLen += len;

  free(theData);
  theData = newData;
}

void URLManager::clearInternal()
{
  if (theData)
    free (theData);

  theData = NULL;
  theLen = 0;
}

bool URLManager::beginGet(const std::string URL)
{
  CURLcode result = CURLE_OK;
  if (!easyHandle) {
    return false;
  }

  float timeout = 15;
  if (BZDB.isSet("httpTimeout"))
    timeout = BZDB.eval("httpTimeout");

#if LIBCURL_VERSION_NUM >= 0x070a00
  result = curl_easy_setopt((CURL*)easyHandle, CURLOPT_NOSIGNAL, true);
  if (result) {
    DEBUG1("Something wrong with CURL; Error: %d\n", result);
  }
#endif

  result = curl_easy_setopt((CURL*)easyHandle, CURLOPT_TIMEOUT, timeout);
  if (result) {
    DEBUG1("Something wrong with CURL; Error: %d\n", result);
  }

  result = curl_easy_setopt((CURL*)easyHandle, CURLOPT_URL, URL.c_str());
  if (result) {
    DEBUG1("Something wrong with CURL; Error: %d\n", result);
  }

  // FIXME: This could block for a _long_ time.
  result = curl_easy_perform((CURL*)easyHandle);
  if (result == (CURLcode)CURLOPT_ERRORBUFFER) {
    DEBUG1("Error: server reported: %d\n", result);
    return false;
  } else if (result) {
    DEBUG1("Something wrong with CURL; Error: %d\n", result);
    return false;
  }

  result = curl_easy_setopt((CURL*)easyHandle, CURLOPT_URL, NULL);
  if (result) {
    DEBUG1("Something wrong with CURL; Error: %d\n", result);
    return false;
  }

  if (!theData)
    return false;

  return true;
}

void URLManager::setProgressFunc(int (*func)(void* clientp,
                                             double dltotal, double dlnow,
                                             double ultotal, double ulnow),
                                             void* data)
{
  if (!easyHandle) {
    return;
  }
  CURLcode code;
  if (func != NULL) {
    CURL* curl = (CURL*)easyHandle;
    code = curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, func);
    code = curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, data);
    code = curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0);
  } else {
    CURL* curl = (CURL*)easyHandle;
    code = curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1);
  }
}

static size_t writeFunction(void *ptr, size_t size, size_t nmemb, void *stream)
{
  int len = size * nmemb;
  ((URLManager*)stream)->collectData((char*)ptr, len);
  return len;
}

#else // HAVE_CURL

// stub the functions
URLManager::URLManager()
{
}
URLManager::~URLManager()
{
}
bool URLManager::getURL(const std::string&, std::string&)
{
  return false;
}
bool URLManager::getURL(const std::string&, void **, unsigned int&)
{
  return false;
}
bool URLManager::getFileTime(const std::string&, time_t &)
{
  return false;
}
void URLManager::freeURLData(void*)
{
  return;
}
void URLManager::collectData(char*, int)
{
  return;
}
void URLManager::clearInternal()
{
  return;
}
bool URLManager::beginGet(const std::string)
{
  return false;
}
void URLManager::setProgressFunc(int (*)(void*, double, double,
                                                double, double), void*)
{
  return;
}

#endif // HAVE_CURL

// Local Variables: ***
// mode:C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<commit_msg>- reset the CURL's HEAD->GET state two differents ways   (7.11.2 likes CURLOPT_NOBODY, 7.12.3 likes CURLOPT_HTTPGET)<commit_after>/* bzflag
* Copyright (c) 1993 - 2005 Tim Riker
*
* This package is free software;  you can redistribute it and/or
* modify it under the terms of the license found in the file
* named COPYING that should have accompanied this file.
*
* THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/

#ifdef _MSC_VER
#pragma warning( 4: 4786)
#define _WINSOCK2API_
#endif

// class interface header
#include "URLManager.h"

// system headers
#ifdef _WIN32
#include <winsock.h>
#endif
#ifdef HAVE_CURL
#include <curl/curl.h>
#endif
#include <iostream>

// common implementation headers
#include "bzfio.h"
#include "StateDatabase.h"

template <>
URLManager* Singleton<URLManager>::_instance = (URLManager*)0;

#ifdef HAVE_CURL

static size_t writeFunction(void *ptr, size_t size, size_t nmemb, void *stream);

bool URLManager::getURL(const std::string& URL, std::string &data)
{
  clearInternal();

  if (!beginGet(URL))
    return false;

  char* newData = (char*)malloc(theLen + 1);
  memcpy(newData, theData, theLen);
  newData[theLen] = 0;

  data = newData;
  free(newData);

  return true;
}

bool URLManager::getURL(const std::string& URL, void **data, unsigned int& size)
{
  clearInternal();

  if (!beginGet(URL))
    return false;

  *data = malloc(theLen);
  memcpy(*data, theData, theLen);
  size = theLen;
  return true;
}

bool URLManager::getFileTime(const std::string& URL, time_t& t)
{
//  return false;

  bool retcode = true;
  CURLcode result;

  float timeout = 15;
  if (BZDB.isSet("httpTimeout")) {
    timeout = BZDB.eval("httpTimeout");
  }

#if LIBCURL_VERSION_NUM >= 0x070a00
  result = curl_easy_setopt((CURL*)easyHandle, CURLOPT_NOSIGNAL, true);
  if (result) {
    DEBUG1("Something wrong with CURL; Error: %d\n", result);
    retcode = false;
  }
#endif

  result = curl_easy_setopt((CURL*)easyHandle, CURLOPT_TIMEOUT, timeout);
  if (result) {
    DEBUG1("Something wrong with CURL; Error: %d\n", result);
    retcode = false;
  }

  result = curl_easy_setopt((CURL*)easyHandle, CURLOPT_NOBODY, 1);
  if (result) {
    DEBUG1("Something wrong with CURL; Error: %d\n", result);
    retcode = false;
  }

  result = curl_easy_setopt((CURL*)easyHandle, CURLOPT_URL, URL.c_str());
  if (result) {
    DEBUG1("Something wrong with CURL; Error: %d\n", result);
    retcode = false;
  }

  // FIXME: This could block for a _long_ time.
  result = curl_easy_perform((CURL*)easyHandle);
  if (result == (CURLcode)CURLOPT_ERRORBUFFER) {
    DEBUG1("Error: server reported: %d\n", result);
    retcode = false;
  } else if (result) {
    DEBUG1("Something wrong with CURL; Error: %d\n", result);
    retcode = false;
  }

  long filetime = 42;
  result = curl_easy_getinfo((CURL*)easyHandle, CURLINFO_FILETIME, &filetime);
  if (result) {
    DEBUG1("Something wrong with CURL; Error: %d\n", result);
    retcode = false;
    t = 0;
  } else {
    t = (time_t)filetime;
  }

  result = curl_easy_setopt((CURL*)easyHandle, CURLOPT_URL, NULL);
  if (result) {
    DEBUG1("Something wrong with CURL; Error: %d\n", result);
    retcode = false;
  }

  result = curl_easy_setopt((CURL*)easyHandle, CURLOPT_NOBODY, 0);
  if (result) {
    DEBUG1("Something wrong with CURL; Error: %d\n", result);
    retcode = false;
  }

  result = curl_easy_setopt((CURL*)easyHandle, CURLOPT_HTTPGET, 1);
  if (result) {
    DEBUG1("Something wrong with CURL; Error: %d\n", result);
    retcode = false;
  }

  return retcode;
}

void URLManager::freeURLData(void *data)
{
  free(data);
}

URLManager::URLManager()
{
  easyHandle = NULL;
  theData = NULL;
  theLen = 0;

#if LIBCURL_VERSION_NUM >= 0x070a00
  CURLcode curlResult;
  if ((curlResult = curl_global_init(CURL_GLOBAL_NOTHING)))
    DEBUG1("Unexpected error from libcurl; Error: %d\n", curlResult);
#endif

  easyHandle = curl_easy_init();
  if (!easyHandle) {
    DEBUG1("Something wrong with CURL\n");
    return;
  }

  CURLcode result = curl_easy_setopt((CURL*)easyHandle, CURLOPT_WRITEFUNCTION, writeFunction);
  if (result)
    DEBUG1("Something wrong with CURL; Error: %d\n", result);

  result = curl_easy_setopt((CURL*)easyHandle, CURLOPT_FILE, this);
  if (result)
    DEBUG1("Something wrong with CURL; Error: %d\n", result);

  result = curl_easy_setopt((CURL*)easyHandle, CURLOPT_FILETIME, 1);
  if (result)
    DEBUG1("Something wrong with CURL; Error: %d\n", result);
}

URLManager::~URLManager()
{
  clearInternal();

  if (easyHandle)
    curl_easy_cleanup((CURL*)easyHandle);

#if LIBCURL_VERSION_NUM >= 0x070a00
  curl_global_cleanup();
#endif
}

void URLManager::collectData(char* ptr, int len)
{
  unsigned char	*newData = (unsigned char*)malloc(theLen + len);
  if (theData)
    memcpy(newData, theData, theLen);

  memcpy(&(newData[theLen]), ptr, len);
  theLen += len;

  free(theData);
  theData = newData;
}

void URLManager::clearInternal()
{
  if (theData)
    free (theData);

  theData = NULL;
  theLen = 0;
}

bool URLManager::beginGet(const std::string URL)
{
  CURLcode result = CURLE_OK;
  if (!easyHandle) {
    return false;
  }

  float timeout = 15;
  if (BZDB.isSet("httpTimeout"))
    timeout = BZDB.eval("httpTimeout");

#if LIBCURL_VERSION_NUM >= 0x070a00
  result = curl_easy_setopt((CURL*)easyHandle, CURLOPT_NOSIGNAL, true);
  if (result) {
    DEBUG1("Something wrong with CURL; Error: %d\n", result);
  }
#endif

  result = curl_easy_setopt((CURL*)easyHandle, CURLOPT_TIMEOUT, timeout);
  if (result) {
    DEBUG1("Something wrong with CURL; Error: %d\n", result);
  }

  result = curl_easy_setopt((CURL*)easyHandle, CURLOPT_URL, URL.c_str());
  if (result) {
    DEBUG1("Something wrong with CURL; Error: %d\n", result);
  }

  // FIXME: This could block for a _long_ time.
  result = curl_easy_perform((CURL*)easyHandle);
  if (result == (CURLcode)CURLOPT_ERRORBUFFER) {
    DEBUG1("Error: server reported: %d\n", result);
    return false;
  } else if (result) {
    DEBUG1("Something wrong with CURL; Error: %d\n", result);
    return false;
  }

  result = curl_easy_setopt((CURL*)easyHandle, CURLOPT_URL, NULL);
  if (result) {
    DEBUG1("Something wrong with CURL; Error: %d\n", result);
    return false;
  }

  if (!theData)
    return false;

  return true;
}

void URLManager::setProgressFunc(int (*func)(void* clientp,
                                             double dltotal, double dlnow,
                                             double ultotal, double ulnow),
                                             void* data)
{
  if (!easyHandle) {
    return;
  }
  CURLcode code;
  if (func != NULL) {
    CURL* curl = (CURL*)easyHandle;
    code = curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, func);
    code = curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, data);
    code = curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0);
  } else {
    CURL* curl = (CURL*)easyHandle;
    code = curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1);
  }
}

static size_t writeFunction(void *ptr, size_t size, size_t nmemb, void *stream)
{
  int len = size * nmemb;
  ((URLManager*)stream)->collectData((char*)ptr, len);
  return len;
}

#else // HAVE_CURL

// stub the functions
URLManager::URLManager()
{
}
URLManager::~URLManager()
{
}
bool URLManager::getURL(const std::string&, std::string&)
{
  return false;
}
bool URLManager::getURL(const std::string&, void **, unsigned int&)
{
  return false;
}
bool URLManager::getFileTime(const std::string&, time_t &)
{
  return false;
}
void URLManager::freeURLData(void*)
{
  return;
}
void URLManager::collectData(char*, int)
{
  return;
}
void URLManager::clearInternal()
{
  return;
}
bool URLManager::beginGet(const std::string)
{
  return false;
}
void URLManager::setProgressFunc(int (*)(void*, double, double,
                                                double, double), void*)
{
  return;
}

#endif // HAVE_CURL

// Local Variables: ***
// mode:C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<|endoftext|>