<commit_before>/** \file    extract_keywords_for_translation.cc
 *  \brief   A tool for extracting keywords that need to be translated.  The keywords and any possibly pre-existing
 *           translations will be stored in a SQL database.
 *  \author  Dr. Johannes Ruscheinski
 */

/*
    Copyright (C) 2016, Library of the University of Tübingen

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as
    published by the Free Software Foundation, either version 3 of the
    License, or (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <iostream>
#include <string>
#include <unordered_set>
#include <utility>
#include <vector>
#include <cstdlib>
#include "Compiler.h"
#include "DbConnection.h"
#include "DbResultSet.h"
#include "DbRow.h"
#include "DirectoryEntry.h"
#include "IniFile.h"
#include "Leader.h"
#include "MarcUtil.h"
#include "StringUtil.h"
#include "Subfields.h"
#include "TimeUtil.h"
#include "TranslationUtil.h"
#include "WallClockTimer.h"
#include "util.h"

void Usage() {
    std::cerr << "Usage: " << progname << " title_input norm_data_input\n";
    std::exit(EXIT_FAILURE);
}

static WallClockTimer *shared_timer;
static unsigned keyword_count, translation_count, additional_hits, synonym_count;
static std::unordered_set<std::string> *shared_norm_data_control_numbers;
static DbConnection *shared_connection;

bool RecordKeywordControlNumbers(MarcUtil::Record * const record, XmlWriter * const /*xml_writer*/,
                                 std::string * const /* err_msg */)
{
    std::vector<std::string> keyword_tags;
    StringUtil::Split("600:610:611:630:650:653:656", ':', &keyword_tags);
    const std::vector<std::string> &fields(record->getFields());
    const std::vector<DirectoryEntry> &dir_entries(record->getDirEntries());
    for (const auto &keyword_tag : keyword_tags) {
        const ssize_t start_index(record->getFieldIndex(keyword_tag));
        if (start_index == -1)
            continue;

        for (size_t index(start_index); index < dir_entries.size() and dir_entries[index].getTag() == keyword_tag; ++index) {
            const Subfields subfields(fields[index]);
            const auto begin_end(subfields.getIterators('0'));
            for (auto subfield0(begin_end.first); subfield0 != begin_end.second; ++subfield0) {
                if (not StringUtil::StartsWith(subfield0->second, "(DE-576)"))
                    continue;

                const std::string topic_id(subfield0->second.substr(8));
                shared_norm_data_control_numbers->insert(topic_id);
            }
        }
    }
    return true;
}

void ExtractKeywordNormdataControlNumbers(File * const marc_input, std::unordered_set<std::string> * const norm_data_control_numbers)
{
    const size_t orig_size(norm_data_control_numbers->size());
    std::string err_msg;
    if (not MarcUtil::ProcessRecords(marc_input, RecordKeywordControlNumbers, nullptr, &err_msg))
        Error("error while extracting keyword control numbers for \"" + marc_input->getPath() + "\": " + err_msg);

    std::cerr << "Found " << (norm_data_control_numbers->size() - orig_size) << " new keyword control numbers in "
              << marc_input->getPath() << '\n';
}

void RemoveExistingKeywords(DbConnection * const connection, std::unordered_set<std::string> * const norm_data_control_numbers)
{
    const std::string SELECT_STMT = "SELECT DISTINCT id FROM keyword_translations";
    if (not connection->query(SELECT_STMT))
        Error("Select failed: " + SELECT_STMT + " (" + connection->getLastErrorMessage() + ")");

    DbResultSet result_set(connection->getLastResultSet());
    while (const DbRow row = result_set.getNextRow()) {
        const auto iter = norm_data_control_numbers->find(row["id"]);
        if (iter != norm_data_control_numbers->end()) {
            norm_data_control_numbers->erase(iter);
        }
    }
}

bool ExtractTranslations(MarcUtil::Record * const record, XmlWriter * const /*xml_writer*/, std::string * const /* err_msg */) {
    const std::vector<std::string> &fields(record->getFields());
    if (shared_norm_data_control_numbers->find(fields[0]) == shared_norm_data_control_numbers->cend())
        return true; // Not one of the records w/ a keyword used in our title data or it is in the database already.

    ++keyword_count;

    std::deque<std::pair<std::string, std::string>> text_and_language_codes;

    // Look for German synonyms:
    const std::vector<DirectoryEntry> &dir_entries(record->getDirEntries());
    ssize_t _450_index(record->getFieldIndex("450"));
    if (_450_index != -1) {
        for (/* Intentionally empty! */;
             static_cast<size_t>(_450_index) < fields.size() and dir_entries[_450_index].getTag() == "450"; ++_450_index)
        {
            const Subfields _450_subfields(fields[_450_index]);
            if (_450_subfields.hasSubfield('a')) {
                text_and_language_codes.emplace_back(std::make_pair(_450_subfields.getFirstSubfieldValue('a'), "deu"));
                ++synonym_count;
            }
        }
    }

    // Find translations:
    const ssize_t first_750_index(record->getFieldIndex("750"));
    if (first_750_index != -1) {
        for (size_t index(first_750_index); index < dir_entries.size() and dir_entries[index].getTag() == "750"; ++index) {
            const Subfields _750_subfields(fields[index]);
            auto start_end(_750_subfields.getIterators('9'));
            if (start_end.first == start_end.second)
                continue;
            std::string language_code;
            for (auto code_and_value(start_end.first); code_and_value != start_end.second; ++code_and_value) {
                if (StringUtil::StartsWith(code_and_value->second, "L:"))
                    language_code = code_and_value->second.substr(2);
            }
            if (language_code.empty() and _750_subfields.hasSubfield('2')) {
                const std::string _750_2(_750_subfields.getFirstSubfieldValue('2'));
                if (_750_2 == "lcsh")
                    language_code = "eng";
                else if (_750_2 == "ram")
                    language_code ="fra";
                if (not language_code.empty())
                    ++additional_hits;
            }
            if (not language_code.empty()) {
                ++translation_count;
                text_and_language_codes.emplace_back(std::make_pair(_750_subfields.getFirstSubfieldValue('a'), language_code));
            }
        }
    }

    const std::string INSERT_STATEMENT_BEGIN("INSERT INTO keyword_translations (id,language_code,translation,preexists) VALUES ");
    std::string insert_statement(INSERT_STATEMENT_BEGIN);
    size_t row_counter(0);
    const size_t MAX_ROW_COUNT(1000);
    // Update the database.
    for (const auto &text_and_language_code : text_and_language_codes) {
        const std::string language_code = shared_connection->escapeString(text_and_language_code.second);
        const std::string translation = shared_connection->escapeString(text_and_language_code.first);
        insert_statement.append("('" + record->getControlNumber() + "', "
                                "'" + language_code + "', "
                                "'" + translation + "', TRUE), ");
        if (++row_counter > MAX_ROW_COUNT) {
            insert_statement = insert_statement.substr(0, insert_statement.size() - 2).append(";");
            if (not shared_connection->query(insert_statement))
                Error("Insert failed: " + insert_statement + " (" + shared_connection->getLastErrorMessage() + ")");

            insert_statement.clear();
            insert_statement.append(INSERT_STATEMENT_BEGIN);
            row_counter = 0;
        }
    }
    return true;
}

void ExtractTranslationTerms(File * const norm_data_input) {
    std::string err_msg;
    if (not MarcUtil::ProcessRecords(norm_data_input, ExtractTranslations, nullptr, &err_msg))
        Error("error while extracting translations from \"" + norm_data_input->getPath() + "\": " + err_msg);

    std::cerr << "Added " << keyword_count << " to the translation database.\n";
    std::cerr << "Found " << translation_count << " translations in the norm data. (" << additional_hits
              << " due to 'ram' and 'lcsh' entries.)\n";
    std::cerr << "Found " << synonym_count << " synonym entries.\n";
}

const std::string CONF_FILE_PATH("/var/lib/tuelib/translations.conf");

int main(int argc, char **argv) {
    ::progname = argv[0];

    if (argc != 3)
        Usage();
    WallClockTimer timer(WallClockTimer::CUMULATIVE_WITH_AUTO_START);
    shared_timer = &timer;

    const std::string marc_input_filename(argv[1]);
    File marc_input(marc_input_filename, "rm");
    if (not marc_input)
        Error("can't open \"" + marc_input_filename + "\" for reading!");

    const std::string norm_data_marc_input_filename(argv[2]);
    File norm_data_marc_input(norm_data_marc_input_filename, "rm");
    if (not norm_data_marc_input)
        Error("can't open \"" + norm_data_marc_input_filename + "\" for reading!");

    try {
        const IniFile ini_file(CONF_FILE_PATH);
        const std::string sql_database(ini_file.getString("", "sql_database"));
        const std::string sql_username(ini_file.getString("", "sql_username"));
        const std::string sql_password(ini_file.getString("", "sql_password"));
        DbConnection db_connection(sql_database, sql_username, sql_password);
        shared_connection = &db_connection;

        std::unordered_set<std::string> norm_data_control_numbers;
        shared_norm_data_control_numbers = &norm_data_control_numbers;

        ExtractKeywordNormdataControlNumbers(&marc_input, &norm_data_control_numbers);
        RemoveExistingKeywords(&db_connection, &norm_data_control_numbers);
        ExtractTranslationTerms(&norm_data_marc_input);

        timer.stop();
        std::cout << ::progname << ": execution time: " << TimeUtil::FormatTime(timer.getTimeInMilliseconds()) << ".\n";
    } catch (const std::exception &x) {
        Error("caught exception: " + std::string(x.what()));
    }
}
<commit_msg>Update extract_keywords_for_translation.cc<commit_after>/** \file    extract_keywords_for_translation.cc
 *  \brief   A tool for extracting keywords that need to be translated.  The keywords and any possibly pre-existing
 *           translations will be stored in a SQL database.
 *  \author  Dr. Johannes Ruscheinski
 */

/*
    Copyright (C) 2016, Library of the University of Tübingen

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as
    published by the Free Software Foundation, either version 3 of the
    License, or (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <iostream>
#include <string>
#include <unordered_set>
#include <utility>
#include <vector>
#include <cstdlib>
#include "Compiler.h"
#include "DbConnection.h"
#include "DbResultSet.h"
#include "DbRow.h"
#include "DirectoryEntry.h"
#include "IniFile.h"
#include "Leader.h"
#include "MarcUtil.h"
#include "StringUtil.h"
#include "Subfields.h"
#include "TimeUtil.h"
#include "TranslationUtil.h"
#include "WallClockTimer.h"
#include "util.h"

void Usage() {
    std::cerr << "Usage: " << progname << " title_input norm_data_input\n";
    std::exit(EXIT_FAILURE);
}

static unsigned keyword_count, translation_count, additional_hits, synonym_count;
static std::unordered_set<std::string> *shared_norm_data_control_numbers;
static DbConnection *shared_connection;

bool RecordKeywordControlNumbers(MarcUtil::Record * const record, XmlWriter * const /*xml_writer*/,
                                 std::string * const /* err_msg */)
{
    std::vector<std::string> keyword_tags;
    StringUtil::Split("600:610:611:630:650:653:656", ':', &keyword_tags);
    const std::vector<std::string> &fields(record->getFields());
    const std::vector<DirectoryEntry> &dir_entries(record->getDirEntries());
    for (const auto &keyword_tag : keyword_tags) {
        const ssize_t start_index(record->getFieldIndex(keyword_tag));
        if (start_index == -1)
            continue;

        for (size_t index(start_index); index < dir_entries.size() and dir_entries[index].getTag() == keyword_tag; ++index) {
            const Subfields subfields(fields[index]);
            const auto begin_end(subfields.getIterators('0'));
            for (auto subfield0(begin_end.first); subfield0 != begin_end.second; ++subfield0) {
                if (not StringUtil::StartsWith(subfield0->second, "(DE-576)"))
                    continue;

                const std::string topic_id(subfield0->second.substr(8));
                shared_norm_data_control_numbers->insert(topic_id);
            }
        }
    }

    return true;
}

void ExtractKeywordNormdataControlNumbers(File * const marc_input, std::unordered_set<std::string> * const norm_data_control_numbers)
{
    const size_t orig_size(norm_data_control_numbers->size());
    std::string err_msg;
    if (not MarcUtil::ProcessRecords(marc_input, RecordKeywordControlNumbers, nullptr, &err_msg))
        Error("error while extracting keyword control numbers for \"" + marc_input->getPath() + "\": " + err_msg);

    std::cerr << "Found " << (norm_data_control_numbers->size() - orig_size) << " new keyword control numbers in "
              << marc_input->getPath() << '\n';
}

void RemoveExistingKeywords(DbConnection * const connection, std::unordered_set<std::string> * const norm_data_control_numbers)
{
    const std::string SELECT_STMT("SELECT DISTINCT id FROM keyword_translations");
    if (not connection->query(SELECT_STMT))
        Error("Select failed: " + SELECT_STMT + " (" + connection->getLastErrorMessage() + ")");

    DbResultSet result_set(connection->getLastResultSet());
    while (const DbRow row = result_set.getNextRow()) {
        const auto iter = norm_data_control_numbers->find(row["id"]);
        if (iter != norm_data_control_numbers->end())
            norm_data_control_numbers->erase(iter);
    }
}

bool ExtractTranslations(MarcUtil::Record * const record, XmlWriter * const /*xml_writer*/, std::string * const /* err_msg */) {
    const std::vector<std::string> &fields(record->getFields());
    if (shared_norm_data_control_numbers->find(fields[0]) == shared_norm_data_control_numbers->cend())
        return true; // Not one of the records w/ a keyword used in our title data or it is in the database already.

    ++keyword_count;

    std::deque<std::pair<std::string, std::string>> text_and_language_codes;

    // Look for German synonyms:
    const std::vector<DirectoryEntry> &dir_entries(record->getDirEntries());
    ssize_t _450_index(record->getFieldIndex("450"));
    if (_450_index != -1) {
        for (/* Intentionally empty! */;
             static_cast<size_t>(_450_index) < fields.size() and dir_entries[_450_index].getTag() == "450"; ++_450_index)
        {
            const Subfields _450_subfields(fields[_450_index]);
            if (_450_subfields.hasSubfield('a')) {
                text_and_language_codes.emplace_back(std::make_pair(_450_subfields.getFirstSubfieldValue('a'), "deu"));
                ++synonym_count;
            }
        }
    }

    // Find translations:
    const ssize_t first_750_index(record->getFieldIndex("750"));
    if (first_750_index != -1) {
        for (size_t index(first_750_index); index < dir_entries.size() and dir_entries[index].getTag() == "750"; ++index) {
            const Subfields _750_subfields(fields[index]);
            auto start_end(_750_subfields.getIterators('9'));
            if (start_end.first == start_end.second)
                continue;
            std::string language_code;
            for (auto code_and_value(start_end.first); code_and_value != start_end.second; ++code_and_value) {
                if (StringUtil::StartsWith(code_and_value->second, "L:"))
                    language_code = code_and_value->second.substr(2);
            }
            if (language_code.empty() and _750_subfields.hasSubfield('2')) {
                const std::string _750_2(_750_subfields.getFirstSubfieldValue('2'));
                if (_750_2 == "lcsh")
                    language_code = "eng";
                else if (_750_2 == "ram")
                    language_code ="fra";
                if (not language_code.empty())
                    ++additional_hits;
            }
            if (not language_code.empty()) {
                ++translation_count;
                text_and_language_codes.emplace_back(std::make_pair(_750_subfields.getFirstSubfieldValue('a'), language_code));
            }
        }
    }

    const std::string INSERT_STATEMENT_BEGIN("INSERT INTO keyword_translations (id,language_code,translation,preexists) VALUES ");
    std::string insert_statement(INSERT_STATEMENT_BEGIN);
    size_t row_counter(0);
    const size_t MAX_ROW_COUNT(1000);
    // Update the database.
    for (const auto &text_and_language_code : text_and_language_codes) {
        const std::string language_code = shared_connection->escapeString(text_and_language_code.second);
        const std::string translation = shared_connection->escapeString(text_and_language_code.first);
        insert_statement.append("('" + record->getControlNumber() + "', "
                                "'" + language_code + "', "
                                "'" + translation + "', TRUE), ");
        if (++row_counter > MAX_ROW_COUNT) {
            insert_statement = insert_statement.substr(0, insert_statement.size() - 2).append(";");
            if (not shared_connection->query(insert_statement))
                Error("Insert failed: " + insert_statement + " (" + shared_connection->getLastErrorMessage() + ")");

            insert_statement.clear();
            insert_statement.append(INSERT_STATEMENT_BEGIN);
            row_counter = 0;
        }
    }
    return true;
}

void ExtractTranslationTerms(File * const norm_data_input) {
    std::string err_msg;
    if (not MarcUtil::ProcessRecords(norm_data_input, ExtractTranslations, nullptr, &err_msg))
        Error("error while extracting translations from \"" + norm_data_input->getPath() + "\": " + err_msg);

    std::cerr << "Added " << keyword_count << " to the translation database.\n";
    std::cerr << "Found " << translation_count << " translations in the norm data. (" << additional_hits
              << " due to 'ram' and 'lcsh' entries.)\n";
    std::cerr << "Found " << synonym_count << " synonym entries.\n";
}

const std::string CONF_FILE_PATH("/var/lib/tuelib/translations.conf");

int main(int argc, char **argv) {
    ::progname = argv[0];

    if (argc != 3)
        Usage();
    WallClockTimer timer(WallClockTimer::CUMULATIVE_WITH_AUTO_START);
    shared_timer = &timer;

    const std::string marc_input_filename(argv[1]);
    File marc_input(marc_input_filename, "rm");
    if (not marc_input)
        Error("can't open \"" + marc_input_filename + "\" for reading!");

    const std::string norm_data_marc_input_filename(argv[2]);
    File norm_data_marc_input(norm_data_marc_input_filename, "rm");
    if (not norm_data_marc_input)
        Error("can't open \"" + norm_data_marc_input_filename + "\" for reading!");

    try {
        const IniFile ini_file(CONF_FILE_PATH);
        const std::string sql_database(ini_file.getString("", "sql_database"));
        const std::string sql_username(ini_file.getString("", "sql_username"));
        const std::string sql_password(ini_file.getString("", "sql_password"));
        DbConnection db_connection(sql_database, sql_username, sql_password);
        shared_connection = &db_connection;

        std::unordered_set<std::string> norm_data_control_numbers;
        shared_norm_data_control_numbers = &norm_data_control_numbers;

        ExtractKeywordNormdataControlNumbers(&marc_input, &norm_data_control_numbers);
        RemoveExistingKeywords(&db_connection, &norm_data_control_numbers);
        ExtractTranslationTerms(&norm_data_marc_input);

        timer.stop();
        std::cout << ::progname << ": execution time: " << TimeUtil::FormatTime(timer.getTimeInMilliseconds()) << ".\n";
    } catch (const std::exception &x) {
        Error("caught exception: " + std::string(x.what()));
    }
}
<|endoftext|>


<commit_before>// UDP receiver node
// Author: Max Schwarz <max.schwarz@uni-bonn.de>

#include "udp_receiver.h"
#include "udp_packet.h"

#include <sys/socket.h>
#include <arpa/inet.h>

#include <ros/console.h>
#include <ros/node_handle.h>

#include <topic_tools/shape_shifter.h>

#include <std_msgs/Time.h>

#include <stdio.h>

#include <ros/names.h>

#include "../topic_info.h"

#include <bzlib.h>

namespace nimbro_topic_transport
{

bool Message::decompress(Message* dest)
{
	unsigned int destLen = 1024;
	dest->payload.resize(destLen);

	while(1)
	{
		int ret = BZ2_bzBuffToBuffDecompress((char*)dest->payload.data(), &destLen, (char*)payload.data(), payload.size(), 0, 0);

		if(ret == BZ_OUTBUFF_FULL)
		{
			destLen *= 2;
			dest->payload.resize(destLen);
			continue;
		}

		if(ret != BZ_OK)
		{
			ROS_ERROR("Could not decompress message");
			return false;
		}

		break;
	}

	dest->payload.resize(destLen);
	dest->header = header;
	dest->id = id;
	dest->size = destLen;
	return true;
}

UDPReceiver::UDPReceiver()
 : m_incompleteMessages(4)
{
	ros::NodeHandle nh("~");

	m_pub_heartbeat = nh.advertise<std_msgs::Time>("heartbeat", 1);

	m_fd = socket(AF_INET, SOCK_DGRAM, 0);
	if(m_fd < 0)
	{
		ROS_FATAL("Could not create socket: %s", strerror(errno));
		throw std::runtime_error(strerror(errno));
	}

	int port;
	nh.param("port", port, 5050);

	sockaddr_in addr;
	addr.sin_family = AF_INET;
	addr.sin_addr.s_addr = INADDR_ANY;
	addr.sin_port = htons(port);

	ROS_INFO("Binding to :%d", port);

	if(bind(m_fd, (sockaddr*)&addr, sizeof(addr)) != 0)
	{
		ROS_FATAL("Could not bind socket: %s", strerror(errno));
		throw std::runtime_error(strerror(errno));
	}

	int on = 1;
	if(setsockopt(m_fd, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)) != 0)
	{
		ROS_FATAL("Could not set broadcast flag: %s", strerror(errno));
		throw std::runtime_error(strerror(errno));
	}

	nh.param("drop_repeated_msgs", m_dropRepeatedMessages, false);
}

UDPReceiver::~UDPReceiver()
{
}

void UDPReceiver::run()
{
	uint8_t buf[PACKET_SIZE];

	ROS_INFO("UDP receiver ready");
	while(1)
	{
		ros::spinOnce();

		ssize_t size = recv(m_fd, buf, sizeof(buf), 0);

		if(size < 0)
		{
			ROS_FATAL("Could not recv(): %s", strerror(errno));
			throw std::runtime_error(strerror(errno));
		}

		ROS_DEBUG("packet");

		Message* msg;

		UDPGenericPacket* generic = (UDPGenericPacket*)buf;

		MessageBuffer::iterator it = std::find_if(m_incompleteMessages.begin(), m_incompleteMessages.end(),
			[=](const Message& msg) { return msg.id == generic->msg_id(); }
		);

		if(it == m_incompleteMessages.end())
		{
			// Insert a new message
			m_incompleteMessages.push_front(Message(generic->msg_id()));
			it = m_incompleteMessages.begin();

			// Erase messages that are too old (after index 31)
			MessageBuffer::iterator itr = m_incompleteMessages.begin();
			MessageBuffer::iterator it_end = m_incompleteMessages.end();
			for(int i = 0; i < 32; ++i)
			{
				itr++;
				if(itr == it_end)
					break;
			}

			for(MessageBuffer::iterator itd = itr; itr != it_end; ++itr)
			{
				const Message& msg = *itd;

				int num_fragments = msg.msgs.size();
				int received = 0;
				for(unsigned int i = 0; i < msg.msgs.size(); ++i)
				{
					if(msg.msgs[i])
						received++;
				}

				ROS_WARN("Dropping message %d, %.2f%% of fragments received (%d/%d)",
					msg.id, 100.0 * received / num_fragments, received, num_fragments
				);
			}

			m_incompleteMessages.erase(itr, it_end);
		}

		msg = &*it;

		if(generic->frag_id == 0)
		{
			UDPFirstPacket* first = (UDPFirstPacket*)buf;

			msg->header = first->header;

			// We can calculate an approximate size now
			uint32_t required_size = (msg->header.remaining_packets()+1) * PACKET_SIZE;
			uint32_t my_size = size - sizeof(UDPFirstPacket);
			if(msg->payload.size() < required_size)
				msg->payload.resize(required_size);
			memcpy(msg->payload.data(), first->data, my_size);

			if(msg->size < my_size)
				msg->size = my_size;

			if(((uint16_t)msg->msgs.size()) < msg->header.remaining_packets()+1)
				msg->msgs.resize(msg->header.remaining_packets()+1, false);
		}
		else
		{
			UDPDataPacket* data = (UDPDataPacket*)buf;

			uint32_t offset = UDPFirstPacket::MaxDataSize + (data->header.frag_id-1) * UDPDataPacket::MaxDataSize;
			uint32_t required_size = offset + size - sizeof(UDPDataPacket);
			if(msg->payload.size() < required_size)
				msg->payload.resize(required_size);
			memcpy(msg->payload.data() + offset, data->data, size - sizeof(UDPDataPacket));

			if(msg->size < required_size)
				msg->size = required_size;
		}

		if(generic->frag_id >= msg->msgs.size())
			msg->msgs.resize(generic->frag_id+1, false);

		ROS_DEBUG("fragment: %d of msg %d", (int)generic->frag_id(), (int)generic->msg_id());
		msg->msgs[generic->frag_id] = true;

		if(std::all_of(msg->msgs.begin(), msg->msgs.end(), [](bool x){return x;}))
		{
			// Packet complete

			// Enforce termination
			msg->header.topic_type[sizeof(msg->header.topic_type)-1] = 0;
			msg->header.topic_name[sizeof(msg->header.topic_name)-1] = 0;

			ROS_DEBUG("Got a packet of type %s, topic %s, %d extra udp packets (msg id %d)", msg->header.topic_type, msg->header.topic_name, msg->header.remaining_packets(), msg->id);

			// Find topic
			TopicMap::iterator topic_it = m_topics.find(msg->header.topic_name);

			TopicData* topic;
			if(topic_it == m_topics.end())
			{
				m_topics.insert(std::pair<std::string, TopicData>(
					msg->header.topic_name,
					TopicData()
				));
				topic = &m_topics[msg->header.topic_name];

				topic->last_message_counter = -1;
			}
			else
				topic = &topic_it->second;

			if(m_dropRepeatedMessages && msg->header.topic_msg_counter() == topic->last_message_counter)
			{
				// This is the same message, probably sent in relay mode
				m_incompleteMessages.erase(it);
				continue;
			}

			// Compare md5
			if(memcmp(topic->md5, msg->header.topic_md5, sizeof(topic->md5)) != 0)
			{
				topic->msg_def = topic_info::getMsgDef(msg->header.topic_type);
				topic->md5_str = topic_info::getMd5Sum(msg->header.topic_type);

				ROS_WARN_STREAM("Got " << topic->msg_def << topic->md5_str << "end");
				for(int i = 0; i < 4; ++i)
				{
					std::string md5_part = topic->md5_str.substr(8*i, 8);
					uint32_t md5_num = strtol(md5_part.c_str(), 0, 16);
					topic->md5[i] = md5_num;
				}

				if(memcmp(topic->md5, msg->header.topic_md5, sizeof(topic->md5)) != 0)
				{
					ROS_ERROR("Invalid md5 sum for topic type '%s', please make sure msg definitions are up to date", msg->header.topic_type);
					m_incompleteMessages.erase(it);
					continue;
				}

				ros::AdvertiseOptions options(
					msg->header.topic_name,
					1,
					topic->md5_str,
					msg->header.topic_type,
					topic->msg_def
				);

				// Latching is often unexpected. Better to lose the first msg.
// 				options.latch = 1;
				topic->publisher = m_nh.advertise(options);
			}

			topic_tools::ShapeShifter shapeShifter;

			shapeShifter.morph(topic->md5_str, msg->header.topic_type, topic->msg_def, "");

			if(msg->header.flags & UDP_FLAG_COMPRESSED)
			{
				if(!msg->decompress(&m_decompressedMessage))
				{
					ROS_ERROR("Could not decompress message, dropping");
					continue;
				}
				shapeShifter.read(m_decompressedMessage);
			}
			else
				shapeShifter.read(*msg);

			topic->publisher.publish(shapeShifter);

			topic->last_message_counter = msg->header.topic_msg_counter();

			m_incompleteMessages.erase(it);

			// Send heartbeat message
			ros::Time now = ros::Time::now();
			if(now - m_lastHeartbeatTime > ros::Duration(1.0))
			{
				std_msgs::Time time;
				time.data = now;
				m_pub_heartbeat.publish(time);

				m_lastHeartbeatTime = now;
			}
		}
	}
}

}

int main(int argc, char** argv)
{
	ros::init(argc, argv, "udp_receiver", ros::init_options::NoSigintHandler);
	ros::NodeHandle nh;

	nimbro_topic_transport::UDPReceiver recv;
	recv.run();

	return 0;
}
<commit_msg>udp_receiver: fix incomplete message dropping logic<commit_after>// UDP receiver node
// Author: Max Schwarz <max.schwarz@uni-bonn.de>

#include "udp_receiver.h"
#include "udp_packet.h"

#include <sys/socket.h>
#include <arpa/inet.h>

#include <ros/console.h>
#include <ros/node_handle.h>

#include <topic_tools/shape_shifter.h>

#include <std_msgs/Time.h>

#include <stdio.h>

#include <ros/names.h>

#include "../topic_info.h"

#include <bzlib.h>

namespace nimbro_topic_transport
{

bool Message::decompress(Message* dest)
{
	unsigned int destLen = 1024;
	dest->payload.resize(destLen);

	while(1)
	{
		int ret = BZ2_bzBuffToBuffDecompress((char*)dest->payload.data(), &destLen, (char*)payload.data(), payload.size(), 0, 0);

		if(ret == BZ_OUTBUFF_FULL)
		{
			destLen *= 2;
			dest->payload.resize(destLen);
			continue;
		}

		if(ret != BZ_OK)
		{
			ROS_ERROR("Could not decompress message");
			return false;
		}

		break;
	}

	dest->payload.resize(destLen);
	dest->header = header;
	dest->id = id;
	dest->size = destLen;
	return true;
}

UDPReceiver::UDPReceiver()
 : m_incompleteMessages(4)
{
	ros::NodeHandle nh("~");

	m_pub_heartbeat = nh.advertise<std_msgs::Time>("heartbeat", 1);

	m_fd = socket(AF_INET, SOCK_DGRAM, 0);
	if(m_fd < 0)
	{
		ROS_FATAL("Could not create socket: %s", strerror(errno));
		throw std::runtime_error(strerror(errno));
	}

	int port;
	nh.param("port", port, 5050);

	sockaddr_in addr;
	addr.sin_family = AF_INET;
	addr.sin_addr.s_addr = INADDR_ANY;
	addr.sin_port = htons(port);

	ROS_INFO("Binding to :%d", port);

	if(bind(m_fd, (sockaddr*)&addr, sizeof(addr)) != 0)
	{
		ROS_FATAL("Could not bind socket: %s", strerror(errno));
		throw std::runtime_error(strerror(errno));
	}

	int on = 1;
	if(setsockopt(m_fd, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)) != 0)
	{
		ROS_FATAL("Could not set broadcast flag: %s", strerror(errno));
		throw std::runtime_error(strerror(errno));
	}

	nh.param("drop_repeated_msgs", m_dropRepeatedMessages, false);
}

UDPReceiver::~UDPReceiver()
{
}

void UDPReceiver::run()
{
	uint8_t buf[PACKET_SIZE];

	ROS_INFO("UDP receiver ready");
	while(1)
	{
		ros::spinOnce();

		ssize_t size = recv(m_fd, buf, sizeof(buf), 0);

		if(size < 0)
		{
			ROS_FATAL("Could not recv(): %s", strerror(errno));
			throw std::runtime_error(strerror(errno));
		}

		ROS_DEBUG("packet");

		Message* msg;

		UDPGenericPacket* generic = (UDPGenericPacket*)buf;

		MessageBuffer::iterator it = std::find_if(m_incompleteMessages.begin(), m_incompleteMessages.end(),
			[=](const Message& msg) { return msg.id == generic->msg_id(); }
		);

		if(it == m_incompleteMessages.end())
		{
			// Insert a new message
			m_incompleteMessages.push_front(Message(generic->msg_id()));
			it = m_incompleteMessages.begin();

			// Erase messages that are too old (after index 31)
			MessageBuffer::iterator itr = m_incompleteMessages.begin();
			MessageBuffer::iterator it_end = m_incompleteMessages.end();
			for(int i = 0; i < 32; ++i)
			{
				itr++;
				if(itr == it_end)
					break;
			}

			for(MessageBuffer::iterator itd = itr; itd != it_end; ++itd)
			{
				const Message& msg = *itd;

				int num_fragments = msg.msgs.size();
				int received = 0;
				for(unsigned int i = 0; i < msg.msgs.size(); ++i)
				{
					if(msg.msgs[i])
						received++;
				}

				ROS_WARN("Dropping message %d, %.2f%% of fragments received (%d/%d)",
					msg.id, 100.0 * received / num_fragments, received, num_fragments
				);
			}

			m_incompleteMessages.erase(itr, it_end);
		}

		msg = &*it;

		if(generic->frag_id == 0)
		{
			UDPFirstPacket* first = (UDPFirstPacket*)buf;

			msg->header = first->header;

			// We can calculate an approximate size now
			uint32_t required_size = (msg->header.remaining_packets()+1) * PACKET_SIZE;
			uint32_t my_size = size - sizeof(UDPFirstPacket);
			if(msg->payload.size() < required_size)
				msg->payload.resize(required_size);
			memcpy(msg->payload.data(), first->data, my_size);

			if(msg->size < my_size)
				msg->size = my_size;

			if(((uint16_t)msg->msgs.size()) < msg->header.remaining_packets()+1)
				msg->msgs.resize(msg->header.remaining_packets()+1, false);
		}
		else
		{
			UDPDataPacket* data = (UDPDataPacket*)buf;

			uint32_t offset = UDPFirstPacket::MaxDataSize + (data->header.frag_id-1) * UDPDataPacket::MaxDataSize;
			uint32_t required_size = offset + size - sizeof(UDPDataPacket);
			if(msg->payload.size() < required_size)
				msg->payload.resize(required_size);
			memcpy(msg->payload.data() + offset, data->data, size - sizeof(UDPDataPacket));

			if(msg->size < required_size)
				msg->size = required_size;
		}

		if(generic->frag_id >= msg->msgs.size())
			msg->msgs.resize(generic->frag_id+1, false);

		ROS_DEBUG("fragment: %d of msg %d", (int)generic->frag_id(), (int)generic->msg_id());
		msg->msgs[generic->frag_id] = true;

		if(std::all_of(msg->msgs.begin(), msg->msgs.end(), [](bool x){return x;}))
		{
			// Packet complete

			// Enforce termination
			msg->header.topic_type[sizeof(msg->header.topic_type)-1] = 0;
			msg->header.topic_name[sizeof(msg->header.topic_name)-1] = 0;

			ROS_DEBUG("Got a packet of type %s, topic %s, %d extra udp packets (msg id %d)", msg->header.topic_type, msg->header.topic_name, msg->header.remaining_packets(), msg->id);

			// Find topic
			TopicMap::iterator topic_it = m_topics.find(msg->header.topic_name);

			TopicData* topic;
			if(topic_it == m_topics.end())
			{
				m_topics.insert(std::pair<std::string, TopicData>(
					msg->header.topic_name,
					TopicData()
				));
				topic = &m_topics[msg->header.topic_name];

				topic->last_message_counter = -1;
			}
			else
				topic = &topic_it->second;

			if(m_dropRepeatedMessages && msg->header.topic_msg_counter() == topic->last_message_counter)
			{
				// This is the same message, probably sent in relay mode
				m_incompleteMessages.erase(it);
				continue;
			}

			// Compare md5
			if(memcmp(topic->md5, msg->header.topic_md5, sizeof(topic->md5)) != 0)
			{
				topic->msg_def = topic_info::getMsgDef(msg->header.topic_type);
				topic->md5_str = topic_info::getMd5Sum(msg->header.topic_type);

				ROS_WARN_STREAM("Got " << topic->msg_def << topic->md5_str << "end");
				for(int i = 0; i < 4; ++i)
				{
					std::string md5_part = topic->md5_str.substr(8*i, 8);
					uint32_t md5_num = strtol(md5_part.c_str(), 0, 16);
					topic->md5[i] = md5_num;
				}

				if(memcmp(topic->md5, msg->header.topic_md5, sizeof(topic->md5)) != 0)
				{
					ROS_ERROR("Invalid md5 sum for topic type '%s', please make sure msg definitions are up to date", msg->header.topic_type);
					m_incompleteMessages.erase(it);
					continue;
				}

				ros::AdvertiseOptions options(
					msg->header.topic_name,
					1,
					topic->md5_str,
					msg->header.topic_type,
					topic->msg_def
				);

				// Latching is often unexpected. Better to lose the first msg.
// 				options.latch = 1;
				topic->publisher = m_nh.advertise(options);
			}

			topic_tools::ShapeShifter shapeShifter;

			shapeShifter.morph(topic->md5_str, msg->header.topic_type, topic->msg_def, "");

			if(msg->header.flags & UDP_FLAG_COMPRESSED)
			{
				if(!msg->decompress(&m_decompressedMessage))
				{
					ROS_ERROR("Could not decompress message, dropping");
					continue;
				}
				shapeShifter.read(m_decompressedMessage);
			}
			else
				shapeShifter.read(*msg);

			topic->publisher.publish(shapeShifter);

			topic->last_message_counter = msg->header.topic_msg_counter();

			m_incompleteMessages.erase(it);

			// Send heartbeat message
			ros::Time now = ros::Time::now();
			if(now - m_lastHeartbeatTime > ros::Duration(1.0))
			{
				std_msgs::Time time;
				time.data = now;
				m_pub_heartbeat.publish(time);

				m_lastHeartbeatTime = now;
			}
		}
	}
}

}

int main(int argc, char** argv)
{
	ros::init(argc, argv, "udp_receiver", ros::init_options::NoSigintHandler);
	ros::NodeHandle nh;

	nimbro_topic_transport::UDPReceiver recv;
	recv.run();

	return 0;
}
<|endoftext|>


<commit_before>/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

#include "ViewEventEmitter.h"

namespace facebook {
namespace react {

#pragma mark - Accessibility

void ViewEventEmitter::onAccessibilityAction(const std::string &name) const {
  dispatchEvent("accessibilityAction", folly::dynamic::object("action", name));
}

void ViewEventEmitter::onAccessibilityTap() const {
  dispatchEvent("accessibilityTap");
}

void ViewEventEmitter::onAccessibilityMagicTap() const {
  dispatchEvent("magicTap");
}

#pragma mark - Layout

void ViewEventEmitter::onLayout(const LayoutMetrics &layoutMetrics) const {
  folly::dynamic payload = folly::dynamic::object();
  const auto &frame = layoutMetrics.frame;
  payload["layout"] =
      folly::dynamic::object("x", frame.origin.x)("y", frame.origin.y)(
          "width", frame.size.width)("height", frame.size.height);

  dispatchEvent("layout", payload);
}

} // namespace react
} // namespace facebook
<commit_msg>Fabric: Migrating ViewEventEmitter to JSI-based payload<commit_after>/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

#include "ViewEventEmitter.h"

namespace facebook {
namespace react {

#pragma mark - Accessibility

void ViewEventEmitter::onAccessibilityAction(const std::string &name) const {
  dispatchEvent("accessibilityAction", [name](jsi::Runtime &runtime) {
    auto payload = jsi::Object(runtime);
    payload.setProperty(runtime, "action", name);
    return payload;
  });
}

void ViewEventEmitter::onAccessibilityTap() const {
  dispatchEvent("accessibilityTap");
}

void ViewEventEmitter::onAccessibilityMagicTap() const {
  dispatchEvent("magicTap");
}

#pragma mark - Layout

void ViewEventEmitter::onLayout(const LayoutMetrics &layoutMetrics) const {
  dispatchEvent("layout", [frame = layoutMetrics.frame](jsi::Runtime &runtime) {
    auto layout = jsi::Object(runtime);
    layout.setProperty(runtime, "x", frame.origin.x);
    layout.setProperty(runtime, "y", frame.origin.y);
    layout.setProperty(runtime, "width", frame.size.width);
    layout.setProperty(runtime, "height", frame.size.height);
    auto payload = jsi::Object(runtime);
    payload.setProperty(runtime, "layout", std::move(layout));
    return payload;
  });
}

} // namespace react
} // namespace facebook
<|endoftext|>


<commit_before>/*!
@file

@copyright Edouard Alligand and Joel Falcou 2015-2017
(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_BRIGAND_TYPES_INTEGRAL_CONSTANT_HPP
#define BOOST_BRIGAND_TYPES_INTEGRAL_CONSTANT_HPP

// having our own integral constant fixes brigand on systems with broken std::integral_constant
// implementations

namespace brigand
{

template <typename T, T Value>
struct integral_constant
{
    // no constexpr for maximum C++ 11 compatibility
    static const T value = Value;

    using value_type = T;
    using type = integral_constant<T, Value>;

    operator value_type() const { return (value); }

    value_type operator()() const { return (value); }
};

template <typename T, T Value>
const T integral_constant<T, Value>::value;

using true_type = ::brigand::integral_constant<bool, true>;
using false_type = ::brigand::integral_constant<bool, false>;
}
#endif
<commit_msg>Delete integral_constant.hpp<commit_after><|endoftext|>


<commit_before>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
    (Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/

Copyright (c) 2008 Renato Araujo Oliveira Filho <renatox@gmail.com>
Copyright (c) 2000-2009 Torus Knot Software Ltd

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

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

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

#include "OgreRoot.h"
#include "OgreException.h"
#include "OgreLogManager.h"
#include "OgreStringConverter.h"
#include "OgreWindowEventUtilities.h"

#include "OgreGLESPrerequisites.h"
#include "OgreGLESRenderSystem.h"

#include "OgreWin32EGLSupport.h"
#include "OgreWin32EGLWindow.h"
#include "OgreWin32EGLContext.h"

#include <iostream>
#include <algorithm>
#include <climits>

namespace Ogre {
    Win32EGLWindow::Win32EGLWindow(Win32EGLSupport *glsupport)
		: EGLWindow(glsupport)
    {
		mGLSupport = glsupport;
		mNativeDisplay = glsupport->getNativeDisplay();
    }

    Win32EGLWindow::~Win32EGLWindow()
    {
    }

	EGLContext * Win32EGLWindow::createEGLContext() const
	{
		return new Win32EGLContext(mEglDisplay, mGLSupport, mEglConfig, mEglSurface);
	}

	void Win32EGLWindow::getLeftAndTopFromNativeWindow( int & left, int & top, uint width, uint height )
	{

	}

	void Win32EGLWindow::initNativeCreatedWindow(const NameValuePairList *miscParams)
	{

	}

	void Win32EGLWindow::createNativeWindow( int &left, int &top, uint &width, uint &height, String &title )
	{
		// destroy current window, if any
		if (mWindow)
			destroy();

#ifdef OGRE_STATIC_LIB
		HINSTANCE hInst = GetModuleHandle( NULL );
#else
#  if OGRE_DEBUG_MODE == 1
		HINSTANCE hInst = GetModuleHandle("RenderSystem_GLES_d.dll");
#  else
		HINSTANCE hInst = GetModuleHandle("RenderSystem_GLES.dll");
#  endif
#endif

		mWindow = 0;
		mClosed = false;
		mIsDepthBuffered = true;
		mColourDepth = mIsFullScreen? 32 : GetDeviceCaps(GetDC(0), BITSPIXEL);
		HWND parent = 0;
		bool vsync = false;
		String border;
		bool outerSize = false;
		bool hwGamma = false;
		int monitorIndex = -1;
		HMONITOR hMonitor = NULL;

		if (!mIsExternal)
		{
			DWORD		  dwStyle = WS_VISIBLE | WS_CLIPCHILDREN;
			DWORD		  dwStyleEx = 0;
			MONITORINFOEX monitorInfoEx;
			RECT		  rc;

			// If we didn't specified the adapter index, or if it didn't find it
			if (hMonitor == NULL)
			{
				POINT windowAnchorPoint;

				// Fill in anchor point.
				windowAnchorPoint.x = left;
				windowAnchorPoint.y = top;

				// Get the nearest monitor to this window.
				hMonitor = MonitorFromPoint(windowAnchorPoint, MONITOR_DEFAULTTONEAREST);
			}

			// Get the target monitor info
			memset(&monitorInfoEx, 0, sizeof(MONITORINFOEX));
			monitorInfoEx.cbSize = sizeof(MONITORINFOEX);
			GetMonitorInfo(hMonitor, &monitorInfoEx);

			//size_t devNameLen = strlen(monitorInfoEx.szDevice);
			//mDeviceName = new char[devNameLen + 1];

			//strcpy(mDeviceName, monitorInfoEx.szDevice);

			// No specified top left -> Center the window in the middle of the monitor
			if (left == -1 || top == -1)
			{
				int screenw = monitorInfoEx.rcMonitor.right  - monitorInfoEx.rcMonitor.left;
				int screenh = monitorInfoEx.rcMonitor.bottom - monitorInfoEx.rcMonitor.top;

				SetRect(&rc, 0, 0, width, height);
				AdjustWindowRect(&rc, dwStyle, false);

				// clamp window dimensions to screen size
				int outerw = (rc.right-rc.left < screenw)? rc.right-rc.left : screenw;
				int outerh = (rc.bottom-rc.top < screenh)? rc.bottom-rc.top : screenh;

				if (left == -1)
					left = monitorInfoEx.rcMonitor.left + (screenw - outerw) / 2;
				else if (monitorIndex != -1)
					left += monitorInfoEx.rcMonitor.left;

				if (top == -1)
					top = monitorInfoEx.rcMonitor.top + (screenh - outerh) / 2;
				else if (monitorIndex != -1)
					top += monitorInfoEx.rcMonitor.top;
			}
			else if (monitorIndex != -1)
			{
				left += monitorInfoEx.rcMonitor.left;
				top += monitorInfoEx.rcMonitor.top;
			}

			mWidth = width;
			mHeight = height;
			mTop = top;
			mLeft = left;

			if (mIsFullScreen)
			{
				dwStyle |= WS_POPUP;
				dwStyleEx |= WS_EX_TOPMOST;
				mTop = monitorInfoEx.rcMonitor.top;
				mLeft = monitorInfoEx.rcMonitor.left;
			}
			else
			{
				if (parent)
				{
					dwStyle |= WS_CHILD;
				}
				else
				{
					if (border == "none")
						dwStyle |= WS_POPUP;
					else if (border == "fixed")
						dwStyle |= WS_OVERLAPPED | WS_BORDER | WS_CAPTION |
						WS_SYSMENU | WS_MINIMIZEBOX;
					else
						dwStyle |= WS_OVERLAPPEDWINDOW;
				}

				int screenw = GetSystemMetrics(SM_CXSCREEN);
				int screenh = GetSystemMetrics(SM_CYSCREEN);

				if (!outerSize)
				{
					// Calculate window dimensions required
					// to get the requested client area
					SetRect(&rc, 0, 0, mWidth, mHeight);
					AdjustWindowRect(&rc, dwStyle, false);
					mWidth = rc.right - rc.left;
					mHeight = rc.bottom - rc.top;

					// Clamp window rect to the nearest display monitor.
					if (mLeft < monitorInfoEx.rcMonitor.left)
						mLeft = monitorInfoEx.rcMonitor.left;

					if (mTop < monitorInfoEx.rcMonitor.top)
						mTop = monitorInfoEx.rcMonitor.top;

					if ((int)mWidth > monitorInfoEx.rcMonitor.right - mLeft)
						mWidth = monitorInfoEx.rcMonitor.right - mLeft;

					if ((int)mHeight > monitorInfoEx.rcMonitor.bottom - mTop)
						mHeight = monitorInfoEx.rcMonitor.bottom - mTop;
				}
			}

			// register class and create window
			WNDCLASS wc = { CS_OWNDC, WindowEventUtilities::_WndProc, 0, 0, hInst,
				LoadIcon(NULL, IDI_APPLICATION), LoadCursor(NULL, IDC_ARROW),
				(HBRUSH)GetStockObject(BLACK_BRUSH), NULL, "OgreGLWindow" };
			RegisterClass(&wc);

			if (mIsFullScreen)
			{
				DEVMODE displayDeviceMode;

				memset(&displayDeviceMode, 0, sizeof(displayDeviceMode));
				displayDeviceMode.dmSize = sizeof(DEVMODE);
				displayDeviceMode.dmBitsPerPel = mColourDepth;
				displayDeviceMode.dmPelsWidth = mWidth;
				displayDeviceMode.dmPelsHeight = mHeight;
				displayDeviceMode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
/*
				if (mDisplayFrequency)
				{
					displayDeviceMode.dmDisplayFrequency = mDisplayFrequency;
					displayDeviceMode.dmFields |= DM_DISPLAYFREQUENCY;
					if (ChangeDisplaySettingsEx(mDeviceName, &displayDeviceMode, NULL, CDS_FULLSCREEN | CDS_TEST, NULL) != DISP_CHANGE_SUCCESSFUL)
					{
						LogManager::getSingleton().logMessage(LML_NORMAL, "ChangeDisplaySettings with user display frequency failed");
						displayDeviceMode.dmFields ^= DM_DISPLAYFREQUENCY;
					}
				}
				if (ChangeDisplaySettingsEx(mDeviceName, &displayDeviceMode, NULL, CDS_FULLSCREEN, NULL) != DISP_CHANGE_SUCCESSFUL)
					LogManager::getSingleton().logMessage(LML_CRITICAL, "ChangeDisplaySettings failed");
*/

			}
			// Pass pointer to self as WM_CREATE parameter
			mWindow = CreateWindowEx(dwStyleEx, "OgreGLWindow", title.c_str(),
				dwStyle, mLeft, mTop, mWidth, mHeight, parent, 0, hInst, this);

			WindowEventUtilities::_addRenderWindow(this);

			LogManager::getSingleton().stream()
				<< "Created Win32Window '"
				<< mName << "' : " << mWidth << "x" << mHeight
				<< ", " << mColourDepth << "bpp";

		}

		RECT rc;
		// top and left represent outer window position
		GetWindowRect(mWindow, &rc);
		mTop = rc.top;
		mLeft = rc.left;
		// width and height represent drawable area only
		GetClientRect(mWindow, &rc);
		mWidth = rc.right;
		mHeight = rc.bottom;

		mNativeDisplay = GetDC(mWindow);
		mEglDisplay = eglGetDisplay(mNativeDisplay);
		mGLSupport->setGLDisplay(mEglDisplay);
		mEglSurface = createSurfaceFromWindow(mEglDisplay, mWindow);

	}

	void Win32EGLWindow::reposition( int left, int top )
	{

	}

	void Win32EGLWindow::resize( unsigned int width, unsigned int height )
	{

	}

	void Win32EGLWindow::windowMovedOrResized()
	{

	}

	void Win32EGLWindow::switchFullScreen( bool fullscreen )
	{

	}

    void Win32EGLWindow::create(const String& name, uint width, uint height,
                                bool fullScreen, const NameValuePairList *miscParams)
    {
        String title = name;
        uint samples = 0;
        int gamma;
        short frequency = 0;
        bool vsync = false;
        ::EGLContext eglContext = 0;
		int left = 0;
		int top  = 0;

		getLeftAndTopFromNativeWindow(left, top, width, height);

        mIsFullScreen = fullScreen;

        if (miscParams)
        {
            NameValuePairList::const_iterator opt;
            NameValuePairList::const_iterator end = miscParams->end();

            if ((opt = miscParams->find("currentGLContext")) != end &&
                StringConverter::parseBool(opt->second))
            {
                eglContext = eglGetCurrentContext();
                if (eglContext)
                {
                    OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
                                "currentGLContext was specified with no current GL context",
                                "EGLWindow::create");
                }

                eglContext = eglGetCurrentContext();
                mEglSurface = eglGetCurrentSurface(EGL_DRAW);
            }

            // Note: Some platforms support AA inside ordinary windows
            if ((opt = miscParams->find("FSAA")) != end)
            {
                samples = StringConverter::parseUnsignedInt(opt->second);
            }

            if ((opt = miscParams->find("displayFrequency")) != end)
            {
                frequency = (short)StringConverter::parseInt(opt->second);
            }

            if ((opt = miscParams->find("vsync")) != end)
            {
                vsync = StringConverter::parseBool(opt->second);
            }

            if ((opt = miscParams->find("gamma")) != end)
            {
                gamma = StringConverter::parseBool(opt->second);
            }

            if ((opt = miscParams->find("left")) != end)
            {
                left = StringConverter::parseInt(opt->second);
            }

            if ((opt = miscParams->find("top")) != end)
            {
                top = StringConverter::parseInt(opt->second);
            }

            if ((opt = miscParams->find("title")) != end)
            {
                title = opt->second;
            }

            if ((opt = miscParams->find("externalGLControl")) != end)
            {
                mIsExternalGLControl = StringConverter::parseBool(opt->second);
            }
		}

		initNativeCreatedWindow(miscParams);

        if (mEglSurface)
        {
            mEglConfig = mGLSupport->getGLConfigFromDrawable (mEglSurface, &width, &height);
        }

        if (!mEglConfig && eglContext)
        {
            mEglConfig = mGLSupport->getGLConfigFromContext(eglContext);

            if (!mEglConfig)
            {
                // This should never happen.
                OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
                            "Unexpected failure to determine a EGLFBConfig",
                            "EGLWindow::create");
            }
        }

        mIsExternal = (mEglSurface != 0);

        if (!mEglConfig)
        {
            int minAttribs[] = {
                EGL_LEVEL, 0,
                EGL_DEPTH_SIZE, 16,
                EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
                EGL_NONE
            };

            int maxAttribs[] = {
                EGL_SAMPLES, samples,
                EGL_STENCIL_SIZE, INT_MAX,
                EGL_NONE
            };

            mEglConfig = mGLSupport->selectGLConfig(minAttribs, maxAttribs);
            mHwGamma = false;
        }

        if (!mIsTopLevel)
        {
            mIsFullScreen = false;
            left = top = 0;
        }

        if (mIsFullScreen)
        {
            mGLSupport->switchMode (width, height, frequency);
        }

		if (!mIsExternal)
        {
			createNativeWindow(left, top, width, height, title);
		}

		mContext = createEGLContext();

        ::EGLSurface oldDrawableDraw = eglGetCurrentSurface(EGL_DRAW);
        ::EGLSurface oldDrawableRead = eglGetCurrentSurface(EGL_READ);
        ::EGLContext oldContext  = eglGetCurrentContext();

        int glConfigID;

        mGLSupport->getGLConfigAttrib(mEglConfig, EGL_CONFIG_ID, &glConfigID);
        LogManager::getSingleton().logMessage("EGLWindow::create used FBConfigID = " + StringConverter::toString(glConfigID));

        mName = name;
        mWidth = width;
        mHeight = height;
        mLeft = left;
        mTop = top;
        mActive = true;
		mVisible = true;

        mClosed = false;
	}

}
<commit_msg>GLES: Remove obselete data member initialization<commit_after>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
    (Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/

Copyright (c) 2008 Renato Araujo Oliveira Filho <renatox@gmail.com>
Copyright (c) 2000-2009 Torus Knot Software Ltd

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

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

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

#include "OgreRoot.h"
#include "OgreException.h"
#include "OgreLogManager.h"
#include "OgreStringConverter.h"
#include "OgreWindowEventUtilities.h"

#include "OgreGLESPrerequisites.h"
#include "OgreGLESRenderSystem.h"

#include "OgreWin32EGLSupport.h"
#include "OgreWin32EGLWindow.h"
#include "OgreWin32EGLContext.h"

#include <iostream>
#include <algorithm>
#include <climits>

namespace Ogre {
    Win32EGLWindow::Win32EGLWindow(Win32EGLSupport *glsupport)
		: EGLWindow(glsupport)
    {
		mGLSupport = glsupport;
		mNativeDisplay = glsupport->getNativeDisplay();
    }

    Win32EGLWindow::~Win32EGLWindow()
    {
    }

	EGLContext * Win32EGLWindow::createEGLContext() const
	{
		return new Win32EGLContext(mEglDisplay, mGLSupport, mEglConfig, mEglSurface);
	}

	void Win32EGLWindow::getLeftAndTopFromNativeWindow( int & left, int & top, uint width, uint height )
	{

	}

	void Win32EGLWindow::initNativeCreatedWindow(const NameValuePairList *miscParams)
	{

	}

	void Win32EGLWindow::createNativeWindow( int &left, int &top, uint &width, uint &height, String &title )
	{
		// destroy current window, if any
		if (mWindow)
			destroy();

#ifdef OGRE_STATIC_LIB
		HINSTANCE hInst = GetModuleHandle( NULL );
#else
#  if OGRE_DEBUG_MODE == 1
		HINSTANCE hInst = GetModuleHandle("RenderSystem_GLES_d.dll");
#  else
		HINSTANCE hInst = GetModuleHandle("RenderSystem_GLES.dll");
#  endif
#endif

		mWindow = 0;
		mClosed = false;
		mColourDepth = mIsFullScreen? 32 : GetDeviceCaps(GetDC(0), BITSPIXEL);
		HWND parent = 0;
		bool vsync = false;
		String border;
		bool outerSize = false;
		bool hwGamma = false;
		int monitorIndex = -1;
		HMONITOR hMonitor = NULL;

		if (!mIsExternal)
		{
			DWORD		  dwStyle = WS_VISIBLE | WS_CLIPCHILDREN;
			DWORD		  dwStyleEx = 0;
			MONITORINFOEX monitorInfoEx;
			RECT		  rc;

			// If we didn't specified the adapter index, or if it didn't find it
			if (hMonitor == NULL)
			{
				POINT windowAnchorPoint;

				// Fill in anchor point.
				windowAnchorPoint.x = left;
				windowAnchorPoint.y = top;

				// Get the nearest monitor to this window.
				hMonitor = MonitorFromPoint(windowAnchorPoint, MONITOR_DEFAULTTONEAREST);
			}

			// Get the target monitor info
			memset(&monitorInfoEx, 0, sizeof(MONITORINFOEX));
			monitorInfoEx.cbSize = sizeof(MONITORINFOEX);
			GetMonitorInfo(hMonitor, &monitorInfoEx);

			//size_t devNameLen = strlen(monitorInfoEx.szDevice);
			//mDeviceName = new char[devNameLen + 1];

			//strcpy(mDeviceName, monitorInfoEx.szDevice);

			// No specified top left -> Center the window in the middle of the monitor
			if (left == -1 || top == -1)
			{
				int screenw = monitorInfoEx.rcMonitor.right  - monitorInfoEx.rcMonitor.left;
				int screenh = monitorInfoEx.rcMonitor.bottom - monitorInfoEx.rcMonitor.top;

				SetRect(&rc, 0, 0, width, height);
				AdjustWindowRect(&rc, dwStyle, false);

				// clamp window dimensions to screen size
				int outerw = (rc.right-rc.left < screenw)? rc.right-rc.left : screenw;
				int outerh = (rc.bottom-rc.top < screenh)? rc.bottom-rc.top : screenh;

				if (left == -1)
					left = monitorInfoEx.rcMonitor.left + (screenw - outerw) / 2;
				else if (monitorIndex != -1)
					left += monitorInfoEx.rcMonitor.left;

				if (top == -1)
					top = monitorInfoEx.rcMonitor.top + (screenh - outerh) / 2;
				else if (monitorIndex != -1)
					top += monitorInfoEx.rcMonitor.top;
			}
			else if (monitorIndex != -1)
			{
				left += monitorInfoEx.rcMonitor.left;
				top += monitorInfoEx.rcMonitor.top;
			}

			mWidth = width;
			mHeight = height;
			mTop = top;
			mLeft = left;

			if (mIsFullScreen)
			{
				dwStyle |= WS_POPUP;
				dwStyleEx |= WS_EX_TOPMOST;
				mTop = monitorInfoEx.rcMonitor.top;
				mLeft = monitorInfoEx.rcMonitor.left;
			}
			else
			{
				if (parent)
				{
					dwStyle |= WS_CHILD;
				}
				else
				{
					if (border == "none")
						dwStyle |= WS_POPUP;
					else if (border == "fixed")
						dwStyle |= WS_OVERLAPPED | WS_BORDER | WS_CAPTION |
						WS_SYSMENU | WS_MINIMIZEBOX;
					else
						dwStyle |= WS_OVERLAPPEDWINDOW;
				}

				int screenw = GetSystemMetrics(SM_CXSCREEN);
				int screenh = GetSystemMetrics(SM_CYSCREEN);

				if (!outerSize)
				{
					// Calculate window dimensions required
					// to get the requested client area
					SetRect(&rc, 0, 0, mWidth, mHeight);
					AdjustWindowRect(&rc, dwStyle, false);
					mWidth = rc.right - rc.left;
					mHeight = rc.bottom - rc.top;

					// Clamp window rect to the nearest display monitor.
					if (mLeft < monitorInfoEx.rcMonitor.left)
						mLeft = monitorInfoEx.rcMonitor.left;

					if (mTop < monitorInfoEx.rcMonitor.top)
						mTop = monitorInfoEx.rcMonitor.top;

					if ((int)mWidth > monitorInfoEx.rcMonitor.right - mLeft)
						mWidth = monitorInfoEx.rcMonitor.right - mLeft;

					if ((int)mHeight > monitorInfoEx.rcMonitor.bottom - mTop)
						mHeight = monitorInfoEx.rcMonitor.bottom - mTop;
				}
			}

			// register class and create window
			WNDCLASS wc = { CS_OWNDC, WindowEventUtilities::_WndProc, 0, 0, hInst,
				LoadIcon(NULL, IDI_APPLICATION), LoadCursor(NULL, IDC_ARROW),
				(HBRUSH)GetStockObject(BLACK_BRUSH), NULL, "OgreGLWindow" };
			RegisterClass(&wc);

			if (mIsFullScreen)
			{
				DEVMODE displayDeviceMode;

				memset(&displayDeviceMode, 0, sizeof(displayDeviceMode));
				displayDeviceMode.dmSize = sizeof(DEVMODE);
				displayDeviceMode.dmBitsPerPel = mColourDepth;
				displayDeviceMode.dmPelsWidth = mWidth;
				displayDeviceMode.dmPelsHeight = mHeight;
				displayDeviceMode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
/*
				if (mDisplayFrequency)
				{
					displayDeviceMode.dmDisplayFrequency = mDisplayFrequency;
					displayDeviceMode.dmFields |= DM_DISPLAYFREQUENCY;
					if (ChangeDisplaySettingsEx(mDeviceName, &displayDeviceMode, NULL, CDS_FULLSCREEN | CDS_TEST, NULL) != DISP_CHANGE_SUCCESSFUL)
					{
						LogManager::getSingleton().logMessage(LML_NORMAL, "ChangeDisplaySettings with user display frequency failed");
						displayDeviceMode.dmFields ^= DM_DISPLAYFREQUENCY;
					}
				}
				if (ChangeDisplaySettingsEx(mDeviceName, &displayDeviceMode, NULL, CDS_FULLSCREEN, NULL) != DISP_CHANGE_SUCCESSFUL)
					LogManager::getSingleton().logMessage(LML_CRITICAL, "ChangeDisplaySettings failed");
*/

			}
			// Pass pointer to self as WM_CREATE parameter
			mWindow = CreateWindowEx(dwStyleEx, "OgreGLWindow", title.c_str(),
				dwStyle, mLeft, mTop, mWidth, mHeight, parent, 0, hInst, this);

			WindowEventUtilities::_addRenderWindow(this);

			LogManager::getSingleton().stream()
				<< "Created Win32Window '"
				<< mName << "' : " << mWidth << "x" << mHeight
				<< ", " << mColourDepth << "bpp";

		}

		RECT rc;
		// top and left represent outer window position
		GetWindowRect(mWindow, &rc);
		mTop = rc.top;
		mLeft = rc.left;
		// width and height represent drawable area only
		GetClientRect(mWindow, &rc);
		mWidth = rc.right;
		mHeight = rc.bottom;

		mNativeDisplay = GetDC(mWindow);
		mEglDisplay = eglGetDisplay(mNativeDisplay);
		mGLSupport->setGLDisplay(mEglDisplay);
		mEglSurface = createSurfaceFromWindow(mEglDisplay, mWindow);

	}

	void Win32EGLWindow::reposition( int left, int top )
	{

	}

	void Win32EGLWindow::resize( unsigned int width, unsigned int height )
	{

	}

	void Win32EGLWindow::windowMovedOrResized()
	{

	}

	void Win32EGLWindow::switchFullScreen( bool fullscreen )
	{

	}

    void Win32EGLWindow::create(const String& name, uint width, uint height,
                                bool fullScreen, const NameValuePairList *miscParams)
    {
        String title = name;
        uint samples = 0;
        int gamma;
        short frequency = 0;
        bool vsync = false;
        ::EGLContext eglContext = 0;
		int left = 0;
		int top  = 0;

		getLeftAndTopFromNativeWindow(left, top, width, height);

        mIsFullScreen = fullScreen;

        if (miscParams)
        {
            NameValuePairList::const_iterator opt;
            NameValuePairList::const_iterator end = miscParams->end();

            if ((opt = miscParams->find("currentGLContext")) != end &&
                StringConverter::parseBool(opt->second))
            {
                eglContext = eglGetCurrentContext();
                if (eglContext)
                {
                    OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
                                "currentGLContext was specified with no current GL context",
                                "EGLWindow::create");
                }

                eglContext = eglGetCurrentContext();
                mEglSurface = eglGetCurrentSurface(EGL_DRAW);
            }

            // Note: Some platforms support AA inside ordinary windows
            if ((opt = miscParams->find("FSAA")) != end)
            {
                samples = StringConverter::parseUnsignedInt(opt->second);
            }

            if ((opt = miscParams->find("displayFrequency")) != end)
            {
                frequency = (short)StringConverter::parseInt(opt->second);
            }

            if ((opt = miscParams->find("vsync")) != end)
            {
                vsync = StringConverter::parseBool(opt->second);
            }

            if ((opt = miscParams->find("gamma")) != end)
            {
                gamma = StringConverter::parseBool(opt->second);
            }

            if ((opt = miscParams->find("left")) != end)
            {
                left = StringConverter::parseInt(opt->second);
            }

            if ((opt = miscParams->find("top")) != end)
            {
                top = StringConverter::parseInt(opt->second);
            }

            if ((opt = miscParams->find("title")) != end)
            {
                title = opt->second;
            }

            if ((opt = miscParams->find("externalGLControl")) != end)
            {
                mIsExternalGLControl = StringConverter::parseBool(opt->second);
            }
		}

		initNativeCreatedWindow(miscParams);

        if (mEglSurface)
        {
            mEglConfig = mGLSupport->getGLConfigFromDrawable (mEglSurface, &width, &height);
        }

        if (!mEglConfig && eglContext)
        {
            mEglConfig = mGLSupport->getGLConfigFromContext(eglContext);

            if (!mEglConfig)
            {
                // This should never happen.
                OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
                            "Unexpected failure to determine a EGLFBConfig",
                            "EGLWindow::create");
            }
        }

        mIsExternal = (mEglSurface != 0);

        if (!mEglConfig)
        {
            int minAttribs[] = {
                EGL_LEVEL, 0,
                EGL_DEPTH_SIZE, 16,
                EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
                EGL_NONE
            };

            int maxAttribs[] = {
                EGL_SAMPLES, samples,
                EGL_STENCIL_SIZE, INT_MAX,
                EGL_NONE
            };

            mEglConfig = mGLSupport->selectGLConfig(minAttribs, maxAttribs);
            mHwGamma = false;
        }

        if (!mIsTopLevel)
        {
            mIsFullScreen = false;
            left = top = 0;
        }

        if (mIsFullScreen)
        {
            mGLSupport->switchMode (width, height, frequency);
        }

		if (!mIsExternal)
        {
			createNativeWindow(left, top, width, height, title);
		}

		mContext = createEGLContext();

        ::EGLSurface oldDrawableDraw = eglGetCurrentSurface(EGL_DRAW);
        ::EGLSurface oldDrawableRead = eglGetCurrentSurface(EGL_READ);
        ::EGLContext oldContext  = eglGetCurrentContext();

        int glConfigID;

        mGLSupport->getGLConfigAttrib(mEglConfig, EGL_CONFIG_ID, &glConfigID);
        LogManager::getSingleton().logMessage("EGLWindow::create used FBConfigID = " + StringConverter::toString(glConfigID));

        mName = name;
        mWidth = width;
        mHeight = height;
        mLeft = left;
        mTop = top;
        mActive = true;
		mVisible = true;

        mClosed = false;
	}

}
<|endoftext|>


<commit_before>/******************************************************************************
*       SOFA, Simulation Open-Framework Architecture, development version     *
*                (c) 2006-2017 INRIA, USTL, UJF, CNRS, MGH                    *
*                                                                             *
* This program is free software; you can redistribute it and/or modify it     *
* under the terms of the GNU Lesser General Public License as published by    *
* the Free Software Foundation; either version 2.1 of the License, or (at     *
* your option) any later version.                                             *
*                                                                             *
* This program is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
* for more details.                                                           *
*                                                                             *
* You should have received a copy of the GNU Lesser General Public License    *
* along with this program. If not, see <http://www.gnu.org/licenses/>.        *
*******************************************************************************
* Authors: The SOFA Team and external contributors (see Authors.txt)          *
*                                                                             *
* Contact information: contact@sofa-framework.org                             *
******************************************************************************/
#include <sofa/simulation/AnimateVisitor.h>
#include <sofa/simulation/MechanicalVisitor.h>
#include <sofa/simulation/CollisionVisitor.h>

#include <sofa/simulation/PropagateEventVisitor.h>
#include <sofa/simulation/CollisionBeginEvent.h>
#include <sofa/simulation/CollisionEndEvent.h>
#include <sofa/simulation/IntegrateBeginEvent.h>
#include <sofa/simulation/IntegrateEndEvent.h>
#include <sofa/simulation/PropagateEventVisitor.h>

#include <sofa/helper/AdvancedTimer.h>

//#include "MechanicalIntegration.h"

using namespace sofa::core;

namespace sofa
{

namespace simulation
{

AnimateVisitor::AnimateVisitor(const core::ExecParams* params, SReal dt)
    : Visitor(params)
    , dt(dt)
    , firstNodeVisited(false)
{
}

AnimateVisitor::AnimateVisitor(const core::ExecParams* params)
    : Visitor(params)
    , dt(0)
    , firstNodeVisited(false)
{
}

void AnimateVisitor::processBehaviorModel(simulation::Node*, core::BehaviorModel* obj)
{
    sofa::helper::AdvancedTimer::stepBegin("BehaviorModel",obj);

    obj->updatePosition(getDt());
    sofa::helper::AdvancedTimer::stepEnd("BehaviorModel",obj);
}

void AnimateVisitor::fwdInteractionForceField(simulation::Node*, core::behavior::BaseInteractionForceField* obj)
{
    //cerr<<"AnimateVisitor::IFF "<<obj->getName()<<endl;
    sofa::helper::AdvancedTimer::stepBegin("InteractionFF",obj);

    MultiVecDerivId   ffId      = VecDerivId::externalForce();
    MechanicalParams mparams; // = MechanicalParams::defaultInstance();
    mparams.setDt(this->dt);
    obj->addForce(&mparams, ffId);

    sofa::helper::AdvancedTimer::stepEnd("InteractionFF",obj);
}

void AnimateVisitor::processCollisionPipeline(simulation::Node* node, core::collision::Pipeline* obj)
{
     sofa::helper::AdvancedTimer::stepBegin("Collision",obj);

    sofa::helper::AdvancedTimer::stepBegin("begin collision",obj);
    {
        CollisionBeginEvent evBegin;
        PropagateEventVisitor eventPropagation( params, &evBegin);
        eventPropagation.execute(node->getContext());
    }
    sofa::helper::AdvancedTimer::stepEnd("begin collision",obj);

    CollisionVisitor act(this->params);
    node->execute(&act);

    sofa::helper::AdvancedTimer::stepBegin("end collision",obj);
    {
        CollisionEndEvent evEnd;
        PropagateEventVisitor eventPropagation( params, &evEnd);
        eventPropagation.execute(node->getContext());
    }
    sofa::helper::AdvancedTimer::stepEnd("end collision",obj);

    sofa::helper::AdvancedTimer::stepEnd("Collision",obj);
}

void AnimateVisitor::processOdeSolver(simulation::Node* node, core::behavior::OdeSolver* solver)
{
    sofa::helper::AdvancedTimer::stepBegin("Mechanical",node);
    /*    MechanicalIntegrationVisitor act(getDt());
        node->execute(&act);*/
//  cerr<<"AnimateVisitor::processOdeSolver "<<solver->getName()<<endl;
    solver->solve(params, getDt());
    sofa::helper::AdvancedTimer::stepEnd("Mechanical",node);
}

Visitor::Result AnimateVisitor::processNodeTopDown(simulation::Node* node)
{

    static const bool use_constraints = false;

    //cerr<<"AnimateVisitor::process Node  "<<node->getName()<<endl;
    if (!node->isActive()) return Visitor::RESULT_PRUNE;
    if (node->isSleeping()) return Visitor::RESULT_PRUNE;
    if (!firstNodeVisited)
    {
        firstNodeVisited=true;

//        core::behavior::BaseAnimationLoop* presenceAnimationManager;
//        node->get(presenceAnimationManager, core::objectmodel::BaseContext::SearchDown);
//        if (!presenceAnimationManager)
//        {
//          std::cerr << "AnimateVisitor::processNodeTopDown, ERROR: no BaseAnimationLoop found while searching down from node: " << node->getName() << std::endl;

//        }

        if(use_constraints) {
            sofa::core::MechanicalParams mparams(*this->params);
            mparams.setDt(dt);
            MechanicalResetConstraintVisitor resetConstraint(&mparams);
            node->execute(&resetConstraint);
        }
    }

    if (dt == 0) setDt(node->getDt());
    else node->setDt(dt);

    if (node->collisionPipeline != NULL)
    {

        //ctime_t t0 = begin(node, node->collisionPipeline);
#ifndef SOFA_SMP
        processCollisionPipeline(node, node->collisionPipeline);
#endif
        //end(node, node->collisionPipeline, t0);
    }
    /*	if (node->solver != NULL)
        {
            ctime_t t0 = begin(node, node->solver);
            processOdeSolver(node, node->solver);
            end(node, node->solver, t0);
            return RESULT_PRUNE;
            }*/
    if (!node->solver.empty() )
    {
        sofa::helper::AdvancedTimer::StepVar timer("Mechanical",node);
        SReal nextTime = node->getTime() + dt;

        {
            IntegrateBeginEvent evBegin;
            PropagateEventVisitor eventPropagation( this->params, &evBegin);
            eventPropagation.execute(node);
        }

        MechanicalBeginIntegrationVisitor beginVisitor(this->params, dt);
        node->execute(&beginVisitor);

        sofa::core::MechanicalParams m_mparams(*this->params);
        m_mparams.setDt(dt);

        if(use_constraints){
            unsigned int constraintId=0;
            core::ConstraintParams cparams;
            //MechanicalAccumulateConstraint(&m_mparams, constraintId, VecCoordId::position()).execute(node);
            simulation::MechanicalAccumulateConstraint(&cparams, core::MatrixDerivId::holonomicC(),constraintId).execute(node);
        }

        for( unsigned i=0; i<node->solver.size(); i++ )
        {
            ctime_t t0 = begin(node, node->solver[i]);
            //cerr<<"AnimateVisitor::processNodeTpDown  solver  "<<node->solver[i]->getName()<<endl;
            node->solver[i]->solve(params, getDt());
            end(node, node->solver[i], t0);
        }

        MechanicalPropagatePositionAndVelocityVisitor(&m_mparams, nextTime,VecCoordId::position(),VecDerivId::velocity(),
#ifdef SOFA_SUPPORT_MAPPED_MASS
                VecDerivId::dx(),
#endif
                true).execute( node );

        MechanicalEndIntegrationVisitor endVisitor(this->params, dt);
        node->execute(&endVisitor);

        {
            IntegrateEndEvent evBegin;
            PropagateEventVisitor eventPropagation(this->params, &evBegin);
            eventPropagation.execute(node);
        }

        return RESULT_PRUNE;
    }
    /*
    if (node->mechanicalModel != NULL)
    {
    	std::cerr << "Graph Error: MechanicalState without solver." << std::endl;
    	return RESULT_PRUNE;
    }
    */
    {
        // process InteractionForceFields
        for_each(this, node, node->interactionForceField, &AnimateVisitor::fwdInteractionForceField);
        return RESULT_CONTINUE;
    }
}

// void AnimateVisitor::processNodeBottomUp(simulation::Node* node)
// {
//     node->setTime( node->getTime() + node->getDt() );
// }

} // namespace simulation

} // namespace sofa

<commit_msg>[core] added timings for position/velocity propagation<commit_after>/******************************************************************************
*       SOFA, Simulation Open-Framework Architecture, development version     *
*                (c) 2006-2017 INRIA, USTL, UJF, CNRS, MGH                    *
*                                                                             *
* This program is free software; you can redistribute it and/or modify it     *
* under the terms of the GNU Lesser General Public License as published by    *
* the Free Software Foundation; either version 2.1 of the License, or (at     *
* your option) any later version.                                             *
*                                                                             *
* This program is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
* for more details.                                                           *
*                                                                             *
* You should have received a copy of the GNU Lesser General Public License    *
* along with this program. If not, see <http://www.gnu.org/licenses/>.        *
*******************************************************************************
* Authors: The SOFA Team and external contributors (see Authors.txt)          *
*                                                                             *
* Contact information: contact@sofa-framework.org                             *
******************************************************************************/
#include <sofa/simulation/AnimateVisitor.h>
#include <sofa/simulation/MechanicalVisitor.h>
#include <sofa/simulation/CollisionVisitor.h>

#include <sofa/simulation/PropagateEventVisitor.h>
#include <sofa/simulation/CollisionBeginEvent.h>
#include <sofa/simulation/CollisionEndEvent.h>
#include <sofa/simulation/IntegrateBeginEvent.h>
#include <sofa/simulation/IntegrateEndEvent.h>
#include <sofa/simulation/PropagateEventVisitor.h>

#include <sofa/helper/AdvancedTimer.h>

//#include "MechanicalIntegration.h"

using namespace sofa::core;

namespace sofa
{

namespace simulation
{

AnimateVisitor::AnimateVisitor(const core::ExecParams* params, SReal dt)
    : Visitor(params)
    , dt(dt)
    , firstNodeVisited(false)
{
}

AnimateVisitor::AnimateVisitor(const core::ExecParams* params)
    : Visitor(params)
    , dt(0)
    , firstNodeVisited(false)
{
}

void AnimateVisitor::processBehaviorModel(simulation::Node*, core::BehaviorModel* obj)
{
    sofa::helper::AdvancedTimer::stepBegin("BehaviorModel",obj);

    obj->updatePosition(getDt());
    sofa::helper::AdvancedTimer::stepEnd("BehaviorModel",obj);
}

void AnimateVisitor::fwdInteractionForceField(simulation::Node*, core::behavior::BaseInteractionForceField* obj)
{
    //cerr<<"AnimateVisitor::IFF "<<obj->getName()<<endl;
    sofa::helper::AdvancedTimer::stepBegin("InteractionFF",obj);

    MultiVecDerivId   ffId      = VecDerivId::externalForce();
    MechanicalParams mparams; // = MechanicalParams::defaultInstance();
    mparams.setDt(this->dt);
    obj->addForce(&mparams, ffId);

    sofa::helper::AdvancedTimer::stepEnd("InteractionFF",obj);
}

void AnimateVisitor::processCollisionPipeline(simulation::Node* node, core::collision::Pipeline* obj)
{
     sofa::helper::AdvancedTimer::stepBegin("Collision",obj);

    sofa::helper::AdvancedTimer::stepBegin("begin collision",obj);
    {
        CollisionBeginEvent evBegin;
        PropagateEventVisitor eventPropagation( params, &evBegin);
        eventPropagation.execute(node->getContext());
    }
    sofa::helper::AdvancedTimer::stepEnd("begin collision",obj);

    CollisionVisitor act(this->params);
    node->execute(&act);

    sofa::helper::AdvancedTimer::stepBegin("end collision",obj);
    {
        CollisionEndEvent evEnd;
        PropagateEventVisitor eventPropagation( params, &evEnd);
        eventPropagation.execute(node->getContext());
    }
    sofa::helper::AdvancedTimer::stepEnd("end collision",obj);

    sofa::helper::AdvancedTimer::stepEnd("Collision",obj);
}

void AnimateVisitor::processOdeSolver(simulation::Node* node, core::behavior::OdeSolver* solver)
{
    sofa::helper::AdvancedTimer::stepBegin("Mechanical",node);
    /*    MechanicalIntegrationVisitor act(getDt());
        node->execute(&act);*/
//  cerr<<"AnimateVisitor::processOdeSolver "<<solver->getName()<<endl;
    solver->solve(params, getDt());
    sofa::helper::AdvancedTimer::stepEnd("Mechanical",node);
}

Visitor::Result AnimateVisitor::processNodeTopDown(simulation::Node* node)
{

    static const bool use_constraints = false;

    //cerr<<"AnimateVisitor::process Node  "<<node->getName()<<endl;
    if (!node->isActive()) return Visitor::RESULT_PRUNE;
    if (node->isSleeping()) return Visitor::RESULT_PRUNE;
    if (!firstNodeVisited)
    {
        firstNodeVisited=true;

//        core::behavior::BaseAnimationLoop* presenceAnimationManager;
//        node->get(presenceAnimationManager, core::objectmodel::BaseContext::SearchDown);
//        if (!presenceAnimationManager)
//        {
//          std::cerr << "AnimateVisitor::processNodeTopDown, ERROR: no BaseAnimationLoop found while searching down from node: " << node->getName() << std::endl;

//        }

        if(use_constraints) {
            sofa::core::MechanicalParams mparams(*this->params);
            mparams.setDt(dt);
            MechanicalResetConstraintVisitor resetConstraint(&mparams);
            node->execute(&resetConstraint);
        }
    }

    if (dt == 0) setDt(node->getDt());
    else node->setDt(dt);

    if (node->collisionPipeline != NULL)
    {

        //ctime_t t0 = begin(node, node->collisionPipeline);
#ifndef SOFA_SMP
        processCollisionPipeline(node, node->collisionPipeline);
#endif
        //end(node, node->collisionPipeline, t0);
    }
    /*	if (node->solver != NULL)
        {
            ctime_t t0 = begin(node, node->solver);
            processOdeSolver(node, node->solver);
            end(node, node->solver, t0);
            return RESULT_PRUNE;
            }*/
    if (!node->solver.empty() )
    {
        sofa::helper::AdvancedTimer::StepVar timer("Mechanical",node);
        SReal nextTime = node->getTime() + dt;

        {
            IntegrateBeginEvent evBegin;
            PropagateEventVisitor eventPropagation( this->params, &evBegin);
            eventPropagation.execute(node);
        }

        MechanicalBeginIntegrationVisitor beginVisitor(this->params, dt);
        node->execute(&beginVisitor);

        sofa::core::MechanicalParams m_mparams(*this->params);
        m_mparams.setDt(dt);

        if(use_constraints){
            unsigned int constraintId=0;
            core::ConstraintParams cparams;
            //MechanicalAccumulateConstraint(&m_mparams, constraintId, VecCoordId::position()).execute(node);
            simulation::MechanicalAccumulateConstraint(&cparams, core::MatrixDerivId::holonomicC(),constraintId).execute(node);
        }

        for( unsigned i=0; i<node->solver.size(); i++ )
        {
            ctime_t t0 = begin(node, node->solver[i]);
            //cerr<<"AnimateVisitor::processNodeTpDown  solver  "<<node->solver[i]->getName()<<endl;
            node->solver[i]->solve(params, getDt());
            end(node, node->solver[i], t0);
        }

        {
            helper::ScopedAdvancedTimer step("MechanicalPropagatePositionAndVelocity");
            MechanicalPropagatePositionAndVelocityVisitor(&m_mparams, nextTime,VecCoordId::position(),VecDerivId::velocity(),
#ifdef SOFA_SUPPORT_MAPPED_MASS
                                                          VecDerivId::dx(),
#endif
                                                          true).execute( node );
        }

        MechanicalEndIntegrationVisitor endVisitor(this->params, dt);
        node->execute(&endVisitor);

        {
            IntegrateEndEvent evBegin;
            PropagateEventVisitor eventPropagation(this->params, &evBegin);
            eventPropagation.execute(node);
        }

        return RESULT_PRUNE;
    }
    /*
    if (node->mechanicalModel != NULL)
    {
    	std::cerr << "Graph Error: MechanicalState without solver." << std::endl;
    	return RESULT_PRUNE;
    }
    */
    {
        // process InteractionForceFields
        for_each(this, node, node->interactionForceField, &AnimateVisitor::fwdInteractionForceField);
        return RESULT_CONTINUE;
    }
}

// void AnimateVisitor::processNodeBottomUp(simulation::Node* node)
// {
//     node->setTime( node->getTime() + node->getDt() );
// }

} // namespace simulation

} // namespace sofa

<|endoftext|>


<commit_before>// Copyright (c) 2011 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 "content/public/test/browser_test_base.h"

#include "base/bind.h"
#include "base/command_line.h"
#include "base/debug/stack_trace.h"
#include "base/process_util.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/main_function_params.h"

#if defined(OS_MACOSX)
#include "base/mac/mac_util.h"
#include "base/system_monitor/system_monitor.h"
#endif

namespace {

#if defined(OS_POSIX)
// On SIGTERM (sent by the runner on timeouts), dump a stack trace (to make
// debugging easier) and also exit with a known error code (so that the test
// framework considers this a failure -- http://crbug.com/57578).
// Note: We only want to do this in the browser process, and not forked
// processes. That might lead to hangs because of locks inside tcmalloc or the
// OS. See http://crbug.com/141302.
static int g_browser_process_pid;
static void DumpStackTraceSignalHandler(int signal) {
  if (g_browser_process_pid == base::GetCurrentProcId())
    base::debug::StackTrace().PrintBacktrace();
  _exit(128 + signal);
}
#endif  // defined(OS_POSIX)

}  // namespace

namespace content {

extern int BrowserMain(const content::MainFunctionParams&);

BrowserTestBase::BrowserTestBase() {
#if defined(OS_MACOSX)
  base::mac::SetOverrideAmIBundled(true);
  base::SystemMonitor::AllocateSystemIOPorts();
#endif

#if defined(OS_POSIX)
  handle_sigterm_ = true;
#endif
}

BrowserTestBase::~BrowserTestBase() {
}

void BrowserTestBase::SetUp() {
  CommandLine* command_line = CommandLine::ForCurrentProcess();

  // The tests assume that file:// URIs can freely access other file:// URIs.
  command_line->AppendSwitch(switches::kAllowFileAccessFromFiles);

  command_line->AppendSwitch(switches::kDomAutomationController);

  command_line->AppendSwitch(switches::kSkipGpuDataLoading);

  MainFunctionParams params(*command_line);
  params.ui_task =
      new base::Closure(
          base::Bind(&BrowserTestBase::ProxyRunTestOnMainThreadLoop, this));

  SetUpInProcessBrowserTestFixture();
  BrowserMain(params);
  TearDownInProcessBrowserTestFixture();
}

void BrowserTestBase::TearDown() {
}

void BrowserTestBase::ProxyRunTestOnMainThreadLoop() {
#if defined(OS_POSIX)
  if (handle_sigterm_) {
    g_browser_process_pid = base::GetCurrentProcId();
    signal(SIGTERM, DumpStackTraceSignalHandler);
  }
#endif  // defined(OS_POSIX)
  RunTestOnMainThreadLoop();
}

void BrowserTestBase::CreateTestServer(const FilePath& test_server_base) {
  CHECK(!test_server_.get());
  test_server_.reset(new net::TestServer(
      net::TestServer::TYPE_HTTP,
      net::TestServer::kLocalhost,
      test_server_base));
}

}  // namespace content
<commit_msg>Provide more context when logging a stack backtrace on timeout (SIGTERM)<commit_after>// Copyright (c) 2011 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 "content/public/test/browser_test_base.h"

#include "base/bind.h"
#include "base/command_line.h"
#include "base/debug/stack_trace.h"
#include "base/process_util.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/main_function_params.h"

#if defined(OS_MACOSX)
#include "base/mac/mac_util.h"
#include "base/system_monitor/system_monitor.h"
#endif

namespace {

#if defined(OS_POSIX)
// On SIGTERM (sent by the runner on timeouts), dump a stack trace (to make
// debugging easier) and also exit with a known error code (so that the test
// framework considers this a failure -- http://crbug.com/57578).
// Note: We only want to do this in the browser process, and not forked
// processes. That might lead to hangs because of locks inside tcmalloc or the
// OS. See http://crbug.com/141302.
static int g_browser_process_pid;
static void DumpStackTraceSignalHandler(int signal) {
  if (g_browser_process_pid == base::GetCurrentProcId()) {
    logging::RawLog(logging::LOG_ERROR,
                    "BrowserTestBase signal handler received SIGTERM. "
                    "Backtrace:\n");
    base::debug::StackTrace().PrintBacktrace();
  }
  _exit(128 + signal);
}
#endif  // defined(OS_POSIX)

}  // namespace

namespace content {

extern int BrowserMain(const content::MainFunctionParams&);

BrowserTestBase::BrowserTestBase() {
#if defined(OS_MACOSX)
  base::mac::SetOverrideAmIBundled(true);
  base::SystemMonitor::AllocateSystemIOPorts();
#endif

#if defined(OS_POSIX)
  handle_sigterm_ = true;
#endif
}

BrowserTestBase::~BrowserTestBase() {
}

void BrowserTestBase::SetUp() {
  CommandLine* command_line = CommandLine::ForCurrentProcess();

  // The tests assume that file:// URIs can freely access other file:// URIs.
  command_line->AppendSwitch(switches::kAllowFileAccessFromFiles);

  command_line->AppendSwitch(switches::kDomAutomationController);

  command_line->AppendSwitch(switches::kSkipGpuDataLoading);

  MainFunctionParams params(*command_line);
  params.ui_task =
      new base::Closure(
          base::Bind(&BrowserTestBase::ProxyRunTestOnMainThreadLoop, this));

  SetUpInProcessBrowserTestFixture();
  BrowserMain(params);
  TearDownInProcessBrowserTestFixture();
}

void BrowserTestBase::TearDown() {
}

void BrowserTestBase::ProxyRunTestOnMainThreadLoop() {
#if defined(OS_POSIX)
  if (handle_sigterm_) {
    g_browser_process_pid = base::GetCurrentProcId();
    signal(SIGTERM, DumpStackTraceSignalHandler);
  }
#endif  // defined(OS_POSIX)
  RunTestOnMainThreadLoop();
}

void BrowserTestBase::CreateTestServer(const FilePath& test_server_base) {
  CHECK(!test_server_.get());
  test_server_.reset(new net::TestServer(
      net::TestServer::TYPE_HTTP,
      net::TestServer::kLocalhost,
      test_server_base));
}

}  // namespace content
<|endoftext|>


<commit_before>#include "stdafx.h"
#include <iostream>
#include "RadioMaster.h"
#include <Windows.h>

using namespace std;

HANDLE hStdin;
HANDLE hStdout;
DWORD fdwSaveOldMode;

void ErrorExit(LPSTR);

void MouseEventProc(MOUSE_EVENT_RECORD mer, RadioMaster *master);
void ResizeEventProc(WINDOW_BUFFER_SIZE_RECORD);

int main(void) {

	hStdin = GetStdHandle(STD_INPUT_HANDLE);
	hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
	INPUT_RECORD irInBuf[128];

	DWORD cNumRead;

	string *options = new string[4];
	options[0] = "This is the first option";
	options[1] = "This is the second option";
	options[2] = "This is the third option";
	options[3] = "This is the fourth option";

	RadioMaster *radioMaster = new RadioMaster(options, 4);

	while (1)
	{
		// Wait for the events.

		if (!ReadConsoleInput(
			hStdin,      // input buffer handle
			irInBuf,     // buffer to read into
			128,         // size of read buffer
			&cNumRead)) // number of records read
			ErrorExit("ReadConsoleInput");

		// Dispatch the events to the appropriate handler.

		for (int i = 0; i < cNumRead; i++)
		{
			switch (irInBuf[i].EventType)
			{
			case KEY_EVENT: // keyboard input
				if (irInBuf[i].Event.KeyEvent.bKeyDown) {
					if (irInBuf[i].Event.KeyEvent.wVirtualKeyCode == VK_UP) {
						radioMaster->goUp();
					}
					if (irInBuf[i].Event.KeyEvent.wVirtualKeyCode == VK_DOWN) {
						radioMaster->goDown();
					}
					if (irInBuf[i].Event.KeyEvent.wVirtualKeyCode == VK_RETURN) {
						radioMaster->markHovered();
					}
				}
				break;

			case MOUSE_EVENT: // mouse input
				MouseEventProc(irInBuf[i].Event.MouseEvent, radioMaster);
				break;

			case WINDOW_BUFFER_SIZE_EVENT: // scrn buf. resizing
				ResizeEventProc(irInBuf[i].Event.WindowBufferSizeEvent);
				break;

			case FOCUS_EVENT:  // disregard focus events

			case MENU_EVENT:   // disregard menu events
				break;

			default:
				ErrorExit("Unknown event type");
				break;
			}
		}
	}
}

void MouseEventProc(MOUSE_EVENT_RECORD mer, RadioMaster *master) {
#ifndef MOUSE_HWHEELED
#define MOUSE_HWHEELED 0x0008
#endif
	switch (mer.dwEventFlags) {

	case 0:
		//Left button press
		if (mer.dwButtonState == FROM_LEFT_1ST_BUTTON_PRESSED) {
			SHORT yPosition = mer.dwMousePosition.Y;
			if (yPosition >= master->getTopY() && yPosition <= master->getBottomY()) {
				master->markHovered();
			}
			//checkClickedPosition(mer.dwMousePosition);
		}
		break;
	case MOUSE_MOVED:
		//Right button press

		SHORT yPosition = mer.dwMousePosition.Y;
		if (yPosition >= master->getTopY() && yPosition <= master->getBottomY()) {
			master->setHoverBackground(yPosition);
		}
		//setHover(mer.dwMousePosition);
		break;
	}
}

void ErrorExit(LPSTR lpszMessage)
{
	fprintf(stderr, "%s\n", lpszMessage);

	// Restore input mode on exit.

	SetConsoleMode(hStdin, fdwSaveOldMode);

	ExitProcess(0);
}

void ResizeEventProc(WINDOW_BUFFER_SIZE_RECORD wbsr)
{
	printf("Resize event\n");
	printf("Console screen buffer is %d columns by %d rows.\n", wbsr.dwSize.X, wbsr.dwSize.Y);
}
<commit_msg>Update main.cpp<commit_after>#include <iostream>
#include "RadioMaster.h"
#include <Windows.h>

using namespace std;

HANDLE hStdin;
HANDLE hStdout;
DWORD fdwSaveOldMode;

void ErrorExit(LPSTR);

void MouseEventProc(MOUSE_EVENT_RECORD mer, RadioMaster *master);
void ResizeEventProc(WINDOW_BUFFER_SIZE_RECORD);

int main(void) {

	hStdin = GetStdHandle(STD_INPUT_HANDLE);
	hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
	INPUT_RECORD irInBuf[128];

	DWORD cNumRead;

	string *options = new string[4];
	options[0] = "This is the first option";
	options[1] = "This is the second option";
	options[2] = "This is the third option";
	options[3] = "This is the fourth option";

	RadioMaster *radioMaster = new RadioMaster(options, 4);

	while (1)
	{
		// Wait for the events.

		if (!ReadConsoleInput(
			hStdin,      // input buffer handle
			irInBuf,     // buffer to read into
			128,         // size of read buffer
			&cNumRead)) // number of records read
			ErrorExit("ReadConsoleInput");

		// Dispatch the events to the appropriate handler.

		for (int i = 0; i < cNumRead; i++)
		{
			switch (irInBuf[i].EventType)
			{
			case KEY_EVENT: // keyboard input
				if (irInBuf[i].Event.KeyEvent.bKeyDown) {
					if (irInBuf[i].Event.KeyEvent.wVirtualKeyCode == VK_UP) {
						radioMaster->goUp();
					}
					if (irInBuf[i].Event.KeyEvent.wVirtualKeyCode == VK_DOWN) {
						radioMaster->goDown();
					}
					if (irInBuf[i].Event.KeyEvent.wVirtualKeyCode == VK_RETURN) {
						radioMaster->markHovered();
					}
				}
				break;

			case MOUSE_EVENT: // mouse input
				MouseEventProc(irInBuf[i].Event.MouseEvent, radioMaster);
				break;

			case WINDOW_BUFFER_SIZE_EVENT: // scrn buf. resizing
				ResizeEventProc(irInBuf[i].Event.WindowBufferSizeEvent);
				break;

			case FOCUS_EVENT:  // disregard focus events

			case MENU_EVENT:   // disregard menu events
				break;

			default:
				ErrorExit("Unknown event type");
				break;
			}
		}
	}
}

void MouseEventProc(MOUSE_EVENT_RECORD mer, RadioMaster *master) {
#ifndef MOUSE_HWHEELED
#define MOUSE_HWHEELED 0x0008
#endif
	switch (mer.dwEventFlags) {

	case 0:
		//Left button press
		if (mer.dwButtonState == FROM_LEFT_1ST_BUTTON_PRESSED) {
			SHORT yPosition = mer.dwMousePosition.Y;
			if (yPosition >= master->getTopY() && yPosition <= master->getBottomY()) {
				master->markHovered();
			}
			//checkClickedPosition(mer.dwMousePosition);
		}
		break;
	case MOUSE_MOVED:
		//Right button press

		SHORT yPosition = mer.dwMousePosition.Y;
		if (yPosition >= master->getTopY() && yPosition <= master->getBottomY()) {
			master->setHoverBackground(yPosition);
		}
		//setHover(mer.dwMousePosition);
		break;
	}
}

void ErrorExit(LPSTR lpszMessage)
{
	fprintf(stderr, "%s\n", lpszMessage);

	// Restore input mode on exit.

	SetConsoleMode(hStdin, fdwSaveOldMode);

	ExitProcess(0);
}

void ResizeEventProc(WINDOW_BUFFER_SIZE_RECORD wbsr)
{
	printf("Resize event\n");
	printf("Console screen buffer is %d columns by %d rows.\n", wbsr.dwSize.X, wbsr.dwSize.Y);
}
<|endoftext|>