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

#include "io/marshalls.h"
#include "project_settings.h"
/* helpers / binders */

PacketPeer::PacketPeer() {

	allow_object_decoding = false;
	last_get_error = OK;
}

void PacketPeer::set_allow_object_decoding(bool p_enable) {

	allow_object_decoding = p_enable;
}

bool PacketPeer::is_object_decoding_allowed() const {

	return allow_object_decoding;
}

Error PacketPeer::get_packet_buffer(PoolVector<uint8_t> &r_buffer) {

	const uint8_t *buffer;
	int buffer_size;
	Error err = get_packet(&buffer, buffer_size);
	if (err)
		return err;

	r_buffer.resize(buffer_size);
	if (buffer_size == 0)
		return OK;

	PoolVector<uint8_t>::Write w = r_buffer.write();
	for (int i = 0; i < buffer_size; i++)
		w[i] = buffer[i];

	return OK;
}

Error PacketPeer::put_packet_buffer(const PoolVector<uint8_t> &p_buffer) {

	int len = p_buffer.size();
	if (len == 0)
		return OK;

	PoolVector<uint8_t>::Read r = p_buffer.read();
	return put_packet(&r[0], len);
}

Error PacketPeer::get_var(Variant &r_variant) {

	const uint8_t *buffer;
	int buffer_size;
	Error err = get_packet(&buffer, buffer_size);
	if (err)
		return err;

	return decode_variant(r_variant, buffer, buffer_size, NULL, allow_object_decoding);
}

Error PacketPeer::put_var(const Variant &p_packet) {

	int len;
	Error err = encode_variant(p_packet, NULL, len, !allow_object_decoding); // compute len first
	if (err)
		return err;

	if (len == 0)
		return OK;

	uint8_t *buf = (uint8_t *)alloca(len);
	ERR_FAIL_COND_V(!buf, ERR_OUT_OF_MEMORY);
	err = encode_variant(p_packet, buf, len, !allow_object_decoding);
	ERR_FAIL_COND_V(err, err);

	return put_packet(buf, len);
}

Variant PacketPeer::_bnd_get_var() {
	Variant var;
	get_var(var);

	return var;
};

Error PacketPeer::_put_packet(const PoolVector<uint8_t> &p_buffer) {
	return put_packet_buffer(p_buffer);
}
PoolVector<uint8_t> PacketPeer::_get_packet() {

	PoolVector<uint8_t> raw;
	last_get_error = get_packet_buffer(raw);
	return raw;
}

Error PacketPeer::_get_packet_error() const {

	return last_get_error;
}

void PacketPeer::_bind_methods() {

	ClassDB::bind_method(D_METHOD("get_var"), &PacketPeer::_bnd_get_var);
	ClassDB::bind_method(D_METHOD("put_var", "var"), &PacketPeer::put_var);
	ClassDB::bind_method(D_METHOD("get_packet"), &PacketPeer::_get_packet);
	ClassDB::bind_method(D_METHOD("put_packet", "buffer"), &PacketPeer::_put_packet);
	ClassDB::bind_method(D_METHOD("get_packet_error"), &PacketPeer::_get_packet_error);
	ClassDB::bind_method(D_METHOD("get_available_packet_count"), &PacketPeer::get_available_packet_count);

	ClassDB::bind_method(D_METHOD("set_allow_object_decoding", "enable"), &PacketPeer::set_allow_object_decoding);
	ClassDB::bind_method(D_METHOD("is_object_decoding_allowed"), &PacketPeer::is_object_decoding_allowed);
};

/***************/

void PacketPeerStream::_set_stream_peer(REF p_peer) {

	ERR_FAIL_COND(p_peer.is_null());
	set_stream_peer(p_peer);
}

void PacketPeerStream::_bind_methods() {

	ClassDB::bind_method(D_METHOD("set_stream_peer", "peer"), &PacketPeerStream::_set_stream_peer);
	ClassDB::bind_method(D_METHOD("set_input_buffer_max_size", "max_size_bytes"), &PacketPeerStream::set_input_buffer_max_size);
	ClassDB::bind_method(D_METHOD("set_output_buffer_max_size", "max_size_bytes"), &PacketPeerStream::set_output_buffer_max_size);
	ClassDB::bind_method(D_METHOD("get_input_buffer_max_size"), &PacketPeerStream::get_input_buffer_max_size);
	ClassDB::bind_method(D_METHOD("get_output_buffer_max_size"), &PacketPeerStream::get_output_buffer_max_size);
}

Error PacketPeerStream::_poll_buffer() const {

	ERR_FAIL_COND_V(peer.is_null(), ERR_UNCONFIGURED);

	int read = 0;
	Error err = peer->get_partial_data(&input_buffer[0], ring_buffer.space_left(), read);
	if (err)
		return err;
	if (read == 0)
		return OK;

	int w = ring_buffer.write(&input_buffer[0], read);
	ERR_FAIL_COND_V(w != read, ERR_BUG);

	return OK;
}

int PacketPeerStream::get_available_packet_count() const {

	_poll_buffer();

	uint32_t remaining = ring_buffer.data_left();

	int ofs = 0;
	int count = 0;

	while (remaining >= 4) {

		uint8_t lbuf[4];
		ring_buffer.copy(lbuf, ofs, 4);
		uint32_t len = decode_uint32(lbuf);
		remaining -= 4;
		ofs += 4;
		if (len > remaining)
			break;
		remaining -= len;
		ofs += len;
		count++;
	}

	return count;
}

Error PacketPeerStream::get_packet(const uint8_t **r_buffer, int &r_buffer_size) {

	ERR_FAIL_COND_V(peer.is_null(), ERR_UNCONFIGURED);
	_poll_buffer();

	int remaining = ring_buffer.data_left();
	ERR_FAIL_COND_V(remaining < 4, ERR_UNAVAILABLE);
	uint8_t lbuf[4];
	ring_buffer.copy(lbuf, 0, 4);
	remaining -= 4;
	uint32_t len = decode_uint32(lbuf);
	ERR_FAIL_COND_V(remaining < (int)len, ERR_UNAVAILABLE);

	ring_buffer.read(lbuf, 4); //get rid of first 4 bytes
	ring_buffer.read(&input_buffer[0], len); // read packet

	*r_buffer = &input_buffer[0];
	r_buffer_size = len;
	return OK;
}

Error PacketPeerStream::put_packet(const uint8_t *p_buffer, int p_buffer_size) {

	ERR_FAIL_COND_V(peer.is_null(), ERR_UNCONFIGURED);
	Error err = _poll_buffer(); //won't hurt to poll here too

	if (err)
		return err;

	if (p_buffer_size == 0)
		return OK;

	ERR_FAIL_COND_V(p_buffer_size < 0, ERR_INVALID_PARAMETER);
	ERR_FAIL_COND_V(p_buffer_size + 4 > output_buffer.size(), ERR_INVALID_PARAMETER);

	encode_uint32(p_buffer_size, &output_buffer[0]);
	uint8_t *dst = &output_buffer[4];
	for (int i = 0; i < p_buffer_size; i++)
		dst[i] = p_buffer[i];

	return peer->put_data(&output_buffer[0], p_buffer_size + 4);
}

int PacketPeerStream::get_max_packet_size() const {

	return output_buffer.size();
}

void PacketPeerStream::set_stream_peer(const Ref<StreamPeer> &p_peer) {

	//ERR_FAIL_COND(p_peer.is_null());

	if (p_peer.ptr() != peer.ptr()) {
		ring_buffer.advance_read(ring_buffer.data_left()); // reset the ring buffer
	};

	peer = p_peer;
}

void PacketPeerStream::set_input_buffer_max_size(int p_max_size) {

	//warning may lose packets
	ERR_EXPLAIN("Buffer in use, resizing would cause loss of data");
	ERR_FAIL_COND(ring_buffer.data_left());
	ring_buffer.resize(nearest_shift(p_max_size + 4));
	input_buffer.resize(next_power_of_2(p_max_size + 4));
}

int PacketPeerStream::get_input_buffer_max_size() const {

	return input_buffer.size() - 4;
}

void PacketPeerStream::set_output_buffer_max_size(int p_max_size) {

	output_buffer.resize(next_power_of_2(p_max_size + 4));
}

int PacketPeerStream::get_output_buffer_max_size() const {

	return output_buffer.size() - 4;
}

PacketPeerStream::PacketPeerStream() {

	int rbsize = GLOBAL_GET("network/limits/packet_peer_stream/max_buffer_po2");

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

#include "io/marshalls.h"
#include "project_settings.h"
/* helpers / binders */

PacketPeer::PacketPeer() {

	allow_object_decoding = false;
	last_get_error = OK;
}

void PacketPeer::set_allow_object_decoding(bool p_enable) {

	allow_object_decoding = p_enable;
}

bool PacketPeer::is_object_decoding_allowed() const {

	return allow_object_decoding;
}

Error PacketPeer::get_packet_buffer(PoolVector<uint8_t> &r_buffer) {

	const uint8_t *buffer;
	int buffer_size;
	Error err = get_packet(&buffer, buffer_size);
	if (err)
		return err;

	r_buffer.resize(buffer_size);
	if (buffer_size == 0)
		return OK;

	PoolVector<uint8_t>::Write w = r_buffer.write();
	for (int i = 0; i < buffer_size; i++)
		w[i] = buffer[i];

	return OK;
}

Error PacketPeer::put_packet_buffer(const PoolVector<uint8_t> &p_buffer) {

	int len = p_buffer.size();
	if (len == 0)
		return OK;

	PoolVector<uint8_t>::Read r = p_buffer.read();
	return put_packet(&r[0], len);
}

Error PacketPeer::get_var(Variant &r_variant) {

	const uint8_t *buffer;
	int buffer_size;
	Error err = get_packet(&buffer, buffer_size);
	if (err)
		return err;

	return decode_variant(r_variant, buffer, buffer_size, NULL, allow_object_decoding);
}

Error PacketPeer::put_var(const Variant &p_packet) {

	int len;
	Error err = encode_variant(p_packet, NULL, len, !allow_object_decoding); // compute len first
	if (err)
		return err;

	if (len == 0)
		return OK;

	uint8_t *buf = (uint8_t *)alloca(len);
	ERR_FAIL_COND_V(!buf, ERR_OUT_OF_MEMORY);
	err = encode_variant(p_packet, buf, len, !allow_object_decoding);
	ERR_FAIL_COND_V(err, err);

	return put_packet(buf, len);
}

Variant PacketPeer::_bnd_get_var() {
	Variant var;
	get_var(var);

	return var;
};

Error PacketPeer::_put_packet(const PoolVector<uint8_t> &p_buffer) {
	return put_packet_buffer(p_buffer);
}
PoolVector<uint8_t> PacketPeer::_get_packet() {

	PoolVector<uint8_t> raw;
	last_get_error = get_packet_buffer(raw);
	return raw;
}

Error PacketPeer::_get_packet_error() const {

	return last_get_error;
}

void PacketPeer::_bind_methods() {

	ClassDB::bind_method(D_METHOD("get_var"), &PacketPeer::_bnd_get_var);
	ClassDB::bind_method(D_METHOD("put_var", "var"), &PacketPeer::put_var);
	ClassDB::bind_method(D_METHOD("get_packet"), &PacketPeer::_get_packet);
	ClassDB::bind_method(D_METHOD("put_packet", "buffer"), &PacketPeer::_put_packet);
	ClassDB::bind_method(D_METHOD("get_packet_error"), &PacketPeer::_get_packet_error);
	ClassDB::bind_method(D_METHOD("get_available_packet_count"), &PacketPeer::get_available_packet_count);

	ClassDB::bind_method(D_METHOD("set_allow_object_decoding", "enable"), &PacketPeer::set_allow_object_decoding);
	ClassDB::bind_method(D_METHOD("is_object_decoding_allowed"), &PacketPeer::is_object_decoding_allowed);
};

/***************/

void PacketPeerStream::_set_stream_peer(REF p_peer) {

	ERR_FAIL_COND(p_peer.is_null());
	set_stream_peer(p_peer);
}

void PacketPeerStream::_bind_methods() {

	ClassDB::bind_method(D_METHOD("set_stream_peer", "peer"), &PacketPeerStream::_set_stream_peer);
	ClassDB::bind_method(D_METHOD("set_input_buffer_max_size", "max_size_bytes"), &PacketPeerStream::set_input_buffer_max_size);
	ClassDB::bind_method(D_METHOD("set_output_buffer_max_size", "max_size_bytes"), &PacketPeerStream::set_output_buffer_max_size);
	ClassDB::bind_method(D_METHOD("get_input_buffer_max_size"), &PacketPeerStream::get_input_buffer_max_size);
	ClassDB::bind_method(D_METHOD("get_output_buffer_max_size"), &PacketPeerStream::get_output_buffer_max_size);
}

Error PacketPeerStream::_poll_buffer() const {

	ERR_FAIL_COND_V(peer.is_null(), ERR_UNCONFIGURED);

	int read = 0;
	ERR_FAIL_COND_V(input_buffer.size() < ring_buffer.space_left(), ERR_UNAVAILABLE);
	Error err = peer->get_partial_data(&input_buffer[0], ring_buffer.space_left(), read);
	if (err)
		return err;
	if (read == 0)
		return OK;

	int w = ring_buffer.write(&input_buffer[0], read);
	ERR_FAIL_COND_V(w != read, ERR_BUG);

	return OK;
}

int PacketPeerStream::get_available_packet_count() const {

	_poll_buffer();

	uint32_t remaining = ring_buffer.data_left();

	int ofs = 0;
	int count = 0;

	while (remaining >= 4) {

		uint8_t lbuf[4];
		ring_buffer.copy(lbuf, ofs, 4);
		uint32_t len = decode_uint32(lbuf);
		remaining -= 4;
		ofs += 4;
		if (len > remaining)
			break;
		remaining -= len;
		ofs += len;
		count++;
	}

	return count;
}

Error PacketPeerStream::get_packet(const uint8_t **r_buffer, int &r_buffer_size) {

	ERR_FAIL_COND_V(peer.is_null(), ERR_UNCONFIGURED);
	_poll_buffer();

	int remaining = ring_buffer.data_left();
	ERR_FAIL_COND_V(remaining < 4, ERR_UNAVAILABLE);
	uint8_t lbuf[4];
	ring_buffer.copy(lbuf, 0, 4);
	remaining -= 4;
	uint32_t len = decode_uint32(lbuf);
	ERR_FAIL_COND_V(remaining < (int)len, ERR_UNAVAILABLE);

	ERR_FAIL_COND_V(input_buffer.size() < len, ERR_UNAVAILABLE);
	ring_buffer.read(lbuf, 4); //get rid of first 4 bytes
	ring_buffer.read(&input_buffer[0], len); // read packet

	*r_buffer = &input_buffer[0];
	r_buffer_size = len;
	return OK;
}

Error PacketPeerStream::put_packet(const uint8_t *p_buffer, int p_buffer_size) {

	ERR_FAIL_COND_V(peer.is_null(), ERR_UNCONFIGURED);
	Error err = _poll_buffer(); //won't hurt to poll here too

	if (err)
		return err;

	if (p_buffer_size == 0)
		return OK;

	ERR_FAIL_COND_V(p_buffer_size < 0, ERR_INVALID_PARAMETER);
	ERR_FAIL_COND_V(p_buffer_size + 4 > output_buffer.size(), ERR_INVALID_PARAMETER);

	encode_uint32(p_buffer_size, &output_buffer[0]);
	uint8_t *dst = &output_buffer[4];
	for (int i = 0; i < p_buffer_size; i++)
		dst[i] = p_buffer[i];

	return peer->put_data(&output_buffer[0], p_buffer_size + 4);
}

int PacketPeerStream::get_max_packet_size() const {

	return output_buffer.size();
}

void PacketPeerStream::set_stream_peer(const Ref<StreamPeer> &p_peer) {

	//ERR_FAIL_COND(p_peer.is_null());

	if (p_peer.ptr() != peer.ptr()) {
		ring_buffer.advance_read(ring_buffer.data_left()); // reset the ring buffer
	};

	peer = p_peer;
}

void PacketPeerStream::set_input_buffer_max_size(int p_max_size) {

	//warning may lose packets
	ERR_EXPLAIN("Buffer in use, resizing would cause loss of data");
	ERR_FAIL_COND(ring_buffer.data_left());
	ring_buffer.resize(nearest_shift(p_max_size + 4));
	input_buffer.resize(next_power_of_2(p_max_size + 4));
}

int PacketPeerStream::get_input_buffer_max_size() const {

	return input_buffer.size() - 4;
}

void PacketPeerStream::set_output_buffer_max_size(int p_max_size) {

	output_buffer.resize(next_power_of_2(p_max_size + 4));
}

int PacketPeerStream::get_output_buffer_max_size() const {

	return output_buffer.size() - 4;
}

PacketPeerStream::PacketPeerStream() {

	int rbsize = GLOBAL_GET("network/limits/packet_peer_stream/max_buffer_po2");

	ring_buffer.resize(rbsize);
	input_buffer.resize(1 << rbsize);
	output_buffer.resize(1 << rbsize);
}
<|endoftext|>


<commit_before>/*
   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License version 2 as published by the Free Software Foundation.

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

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

#include "propertiesdock.h"

#include <widgets/propertywidget.h>

using namespace GluonCreator;

class PropertiesDock::PropertiesDockPrivate
{
    public:
        PropertiesDockPrivate() { }

        PropertyWidget *widget;
};

PropertiesDock::PropertiesDock(const QString& title, QWidget* parent, Qt::WindowFlags flags): Dock(title, parent, flags)
{
    setObjectName("PropertiesDock");

    d = new PropertiesDockPrivate;

    d->widget = new PropertyWidget(this);
    setWidget(d->widget);

    connect(SelectionManager::instance(), SIGNAL(selectionChanged(SelectionManager::SelectionList)), SLOT(selectionChanged(SelectionManager::SelectionList)));
}

PropertiesDock::~PropertiesDock()
{
    delete d;
    d = 0;
}

void PropertiesDock::setSelection(GluonCore::GluonObject* obj)
{
    d->widget->setObject(obj);
}

QAbstractItemView* PropertiesDock::view()
{
    return 0;
}

QAbstractItemModel* PropertiesDock::model()
{
    return 0;
}

void PropertiesDock::selectionChanged(SelectionManager::SelectionList selection)
{
    setSelection(selection.at(0));
}

<commit_msg>Connect propertyChanged to updateAll of game<commit_after>/*
   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License version 2 as published by the Free Software Foundation.

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

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

#include "propertiesdock.h"

#include <widgets/propertywidget.h>
#include <engine/game.h>

using namespace GluonCreator;

class PropertiesDock::PropertiesDockPrivate
{
    public:
        PropertiesDockPrivate() { }

        PropertyWidget *widget;
};

PropertiesDock::PropertiesDock(const QString& title, QWidget* parent, Qt::WindowFlags flags): Dock(title, parent, flags)
{
    setObjectName("PropertiesDock");

    d = new PropertiesDockPrivate;

    d->widget = new PropertyWidget(this);
    setWidget(d->widget);

    connect(SelectionManager::instance(), SIGNAL(selectionChanged(SelectionManager::SelectionList)), SLOT(selectionChanged(SelectionManager::SelectionList)));
    connect(d->widget, SIGNAL(propertyChanged(QString,QVariant,QVariant)), GluonEngine::Game::instance(), SLOT(updateAll()));
}

PropertiesDock::~PropertiesDock()
{
    delete d;
    d = 0;
}

void PropertiesDock::setSelection(GluonCore::GluonObject* obj)
{
    d->widget->setObject(obj);
}

QAbstractItemView* PropertiesDock::view()
{
    return 0;
}

QAbstractItemModel* PropertiesDock::model()
{
    return 0;
}

void PropertiesDock::selectionChanged(SelectionManager::SelectionList selection)
{
    setSelection(selection.at(0));
}

<|endoftext|>


<commit_before>#include <core/stdafx.h>
#include <mapistub/library/mapiStubUtils.h>
#include <core/utility/output.h>

namespace mapistub
{
	void initStubCallbacks()
	{
		mapistub::logLoadMapiCallback = [](auto _1, auto _2) { output::DebugPrint(output::DBGLoadMAPI, _1, _2); };
		mapistub::logLoadLibraryCallback = [](auto _1, auto _2) { output::DebugPrint(output::DBGLoadLibrary, _1, _2); };
	}
} // namespace mapistub
<commit_msg>remove redundant namespace<commit_after>#include <core/stdafx.h>
#include <mapistub/library/mapiStubUtils.h>
#include <core/utility/output.h>

namespace mapistub
{
	void initStubCallbacks()
	{
		logLoadMapiCallback = [](auto _1, auto _2) { output::DebugPrint(output::DBGLoadMAPI, _1, _2); };
		logLoadLibraryCallback = [](auto _1, auto _2) { output::DebugPrint(output::DBGLoadLibrary, _1, _2); };
	}
} // namespace mapistub
<|endoftext|>


<commit_before>/******************************************************************************
 * Copyright 2018 The Apollo Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *****************************************************************************/

#include "cyber/tools/cyber_recorder/player/play_task_producer.h"

#include <iostream>

#include "cyber/common/log.h"
#include "cyber/common/time_conversion.h"
#include "cyber/cyber.h"
#include "cyber/message/protobuf_factory.h"
#include "cyber/record/record_viewer.h"

namespace apollo {
namespace cyber {
namespace record {

const uint32_t PlayTaskProducer::kMinTaskBufferSize = 500;
const uint32_t PlayTaskProducer::kPreloadTimeSec = 3;
const uint64_t PlayTaskProducer::kSleepIntervalNanoSec = 1000000;

PlayTaskProducer::PlayTaskProducer(const TaskBufferPtr& task_buffer,
                                   const PlayParam& play_param)
    : play_param_(play_param),
      task_buffer_(task_buffer),
      produce_th_(nullptr),
      is_initialized_(false),
      is_stopped_(true),
      node_(nullptr),
      earliest_begin_time_(UINT64_MAX),
      latest_end_time_(0),
      total_msg_num_(0) {}

PlayTaskProducer::~PlayTaskProducer() { Stop(); }

bool PlayTaskProducer::Init() {
  if (is_initialized_.exchange(true)) {
    AERROR << "producer has been initialized.";
    return false;
  }

  if (!ReadRecordInfo()) {
    is_initialized_.exchange(false);
    return false;
  }

  if (!UpdatePlayParam()) {
    is_initialized_.exchange(false);
    return false;
  }

  if (!CreateWriters()) {
    is_initialized_.exchange(false);
    return false;
  }

  return true;
}

void PlayTaskProducer::Start() {
  if (!is_initialized_.load()) {
    AERROR << "please call Init firstly.";
    return;
  }

  if (!is_stopped_.exchange(false)) {
    AERROR << "producer has been started.";
    return;
  }

  produce_th_.reset(new std::thread(&PlayTaskProducer::ThreadFunc, this));
}

void PlayTaskProducer::Stop() {
  if (!is_stopped_.exchange(true)) {
    return;
  }
  if (produce_th_ != nullptr && produce_th_->joinable()) {
    produce_th_->join();
    produce_th_ = nullptr;
  }
}

bool PlayTaskProducer::ReadRecordInfo() {
  if (play_param_.files_to_play.empty()) {
    AINFO << "no file to play.";
    return false;
  }

  auto pb_factory = message::ProtobufFactory::Instance();

  // loop each file
  for (auto& file : play_param_.files_to_play) {
    auto record_reader = std::make_shared<RecordReader>(file);
    if (!record_reader->IsValid()) {
      continue;
    }
    if (!record_reader->header().is_complete()) {
      std::cout << "file: " << file << " is not complete." << std::endl;
      continue;
    }

    record_readers_.emplace_back(record_reader);

    auto& channel_info = record_reader->channel_info();
    // loop each channel info
    for (auto& item : channel_info) {
      auto& channel_name = item.first;
      auto& msg_type = item.second.message_type();
      if (play_param_.black_channels.find(channel_name) !=
          play_param_.black_channels.end()) {
        // minus the black message number from record file header
        total_msg_num_ -= item.second.message_number();
        continue;
      }
      msg_types_[channel_name] = msg_type;

      if (!play_param_.is_play_all_channels &&
          play_param_.channels_to_play.count(channel_name) > 0) {
        total_msg_num_ += item.second.message_number();
      }

      auto& proto_desc = item.second.proto_desc();
      pb_factory->RegisterMessage(proto_desc);
    }

    auto& header = record_reader->header();
    if (play_param_.is_play_all_channels) {
      total_msg_num_ += header.message_number();
    }

    if (header.begin_time() < earliest_begin_time_) {
      earliest_begin_time_ = header.begin_time();
    }
    if (header.end_time() > latest_end_time_) {
      latest_end_time_ = header.end_time();
    }

    auto begin_time_s = static_cast<double>(header.begin_time()) / 1e9;
    auto end_time_s = static_cast<double>(header.end_time()) / 1e9;
    auto begin_time_str =
        common::UnixSecondsToString(static_cast<int>(begin_time_s));
    auto end_time_str =
        common::UnixSecondsToString(static_cast<int>(end_time_s));

    std::cout << "file: " << file << ", chunk_number: " << header.chunk_number()
              << ", begin_time: " << header.begin_time() << " ("
              << begin_time_str << ")"
              << ", end_time: " << header.end_time() << " (" << end_time_str
              << ")"
              << ", message_number: " << header.message_number() << std::endl;
  }

  std::cout << "earliest_begin_time: " << earliest_begin_time_
            << ", latest_end_time: " << latest_end_time_
            << ", total_msg_num: " << total_msg_num_ << std::endl;

  return true;
}

bool PlayTaskProducer::UpdatePlayParam() {
  if (play_param_.begin_time_ns < earliest_begin_time_) {
    play_param_.begin_time_ns = earliest_begin_time_;
  }
  if (play_param_.start_time_s > 0) {
    play_param_.begin_time_ns += static_cast<uint64_t>(
        static_cast<double>(play_param_.start_time_s) * 1e9);
  }
  if (play_param_.end_time_ns > latest_end_time_) {
    play_param_.end_time_ns = latest_end_time_;
  }
  if (play_param_.begin_time_ns >= play_param_.end_time_ns) {
    AERROR << "begin time are equal or larger than end time"
           << ", begin_time_ns=" << play_param_.begin_time_ns
           << ", end_time_ns=" << play_param_.end_time_ns;
    return false;
  }
  if (play_param_.preload_time_s == 0) {
    AINFO << "preload time is zero, we will use defalut value: "
          << kPreloadTimeSec << " seconds.";
    play_param_.preload_time_s = kPreloadTimeSec;
  }
  return true;
}

bool PlayTaskProducer::CreateWriters() {
  std::string node_name = "cyber_recorder_play_" + std::to_string(getpid());
  node_ = apollo::cyber::CreateNode(node_name);
  if (node_ == nullptr) {
    AERROR << "create node failed.";
    return false;
  }

  for (auto& item : msg_types_) {
    auto& channel_name = item.first;
    auto& msg_type = item.second;

    if (play_param_.is_play_all_channels ||
        play_param_.channels_to_play.count(channel_name) > 0) {
      if (play_param_.black_channels.find(channel_name) !=
          play_param_.black_channels.end()) {
        continue;
      }
      proto::RoleAttributes attr;
      attr.set_channel_name(channel_name);
      attr.set_message_type(msg_type);
      auto writer = node_->CreateWriter<message::RawMessage>(attr);
      if (writer == nullptr) {
        AERROR << "create wirter failed. channel name: " << channel_name
               << ", message type: " << msg_type;
        return false;
      }
      writers_[channel_name] = writer;
    }
  }

  return true;
}

void PlayTaskProducer::ThreadFunc() {
  const uint64_t loop_time_ns =
      play_param_.end_time_ns - play_param_.begin_time_ns;
  uint64_t avg_interval_time_ns = kSleepIntervalNanoSec;
  if (total_msg_num_ > 0) {
    avg_interval_time_ns = loop_time_ns / total_msg_num_;
  }

  double avg_freq_hz = static_cast<double>(total_msg_num_) /
                       (static_cast<double>(loop_time_ns) * 1e-9);
  uint32_t preload_size = (uint32_t)avg_freq_hz * play_param_.preload_time_s;
  AINFO << "preload_size: " << preload_size;
  if (preload_size < kMinTaskBufferSize) {
    preload_size = kMinTaskBufferSize;
  }

  auto record_viewer = std::make_shared<RecordViewer>(
      record_readers_, play_param_.begin_time_ns, play_param_.end_time_ns,
      play_param_.channels_to_play);

  uint32_t loop_num = 0;
  while (!is_stopped_.load()) {
    uint64_t plus_time_ns = loop_num * loop_time_ns;
    auto itr = record_viewer->begin();
    auto itr_end = record_viewer->end();

    while (itr != itr_end && !is_stopped_.load()) {
      while (!is_stopped_.load() && task_buffer_->Size() > preload_size) {
        std::this_thread::sleep_for(
            std::chrono::nanoseconds(avg_interval_time_ns));
      }
      for (; itr != itr_end && !is_stopped_.load(); ++itr) {
        if (task_buffer_->Size() > preload_size) {
          break;
        }

        auto search = writers_.find(itr->channel_name);
        if (search == writers_.end()) {
          continue;
        }

        auto raw_msg = std::make_shared<message::RawMessage>(itr->content);
        auto task = std::make_shared<PlayTask>(
            raw_msg, search->second, itr->time, itr->time + plus_time_ns);
        task_buffer_->Push(task);
      }
    }

    if (!play_param_.is_loop_playback) {
      is_stopped_.exchange(true);
      break;
    }
    ++loop_num;
  }
}

}  // namespace record
}  // namespace cyber
}  // namespace apollo
<commit_msg>cyber: refactor PlayTaskProducter init method<commit_after>/******************************************************************************
 * Copyright 2018 The Apollo Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *****************************************************************************/

#include "cyber/tools/cyber_recorder/player/play_task_producer.h"

#include <iostream>

#include "cyber/common/log.h"
#include "cyber/common/time_conversion.h"
#include "cyber/cyber.h"
#include "cyber/message/protobuf_factory.h"
#include "cyber/record/record_viewer.h"

namespace apollo {
namespace cyber {
namespace record {

const uint32_t PlayTaskProducer::kMinTaskBufferSize = 500;
const uint32_t PlayTaskProducer::kPreloadTimeSec = 3;
const uint64_t PlayTaskProducer::kSleepIntervalNanoSec = 1000000;

PlayTaskProducer::PlayTaskProducer(const TaskBufferPtr& task_buffer,
                                   const PlayParam& play_param)
    : play_param_(play_param),
      task_buffer_(task_buffer),
      produce_th_(nullptr),
      is_initialized_(false),
      is_stopped_(true),
      node_(nullptr),
      earliest_begin_time_(UINT64_MAX),
      latest_end_time_(0),
      total_msg_num_(0) {}

PlayTaskProducer::~PlayTaskProducer() { Stop(); }

bool PlayTaskProducer::Init() {
  if (is_initialized_.exchange(true)) {
    AERROR << "producer has been initialized.";
    return false;
  }

  if (!ReadRecordInfo() || !UpdatePlayParam() || !CreateWriters()) {
    is_initialized_.exchange(false);
    return false;
  }

  return true;
}

void PlayTaskProducer::Start() {
  if (!is_initialized_.load()) {
    AERROR << "please call Init firstly.";
    return;
  }

  if (!is_stopped_.exchange(false)) {
    AERROR << "producer has been started.";
    return;
  }

  produce_th_.reset(new std::thread(&PlayTaskProducer::ThreadFunc, this));
}

void PlayTaskProducer::Stop() {
  if (!is_stopped_.exchange(true)) {
    return;
  }
  if (produce_th_ != nullptr && produce_th_->joinable()) {
    produce_th_->join();
    produce_th_ = nullptr;
  }
}

bool PlayTaskProducer::ReadRecordInfo() {
  if (play_param_.files_to_play.empty()) {
    AINFO << "no file to play.";
    return false;
  }

  auto pb_factory = message::ProtobufFactory::Instance();

  // loop each file
  for (auto& file : play_param_.files_to_play) {
    auto record_reader = std::make_shared<RecordReader>(file);
    if (!record_reader->IsValid()) {
      continue;
    }
    if (!record_reader->header().is_complete()) {
      std::cout << "file: " << file << " is not complete." << std::endl;
      continue;
    }

    record_readers_.emplace_back(record_reader);

    auto& channel_info = record_reader->channel_info();
    // loop each channel info
    for (auto& item : channel_info) {
      auto& channel_name = item.first;
      auto& msg_type = item.second.message_type();
      if (play_param_.black_channels.find(channel_name) !=
          play_param_.black_channels.end()) {
        // minus the black message number from record file header
        total_msg_num_ -= item.second.message_number();
        continue;
      }
      msg_types_[channel_name] = msg_type;

      if (!play_param_.is_play_all_channels &&
          play_param_.channels_to_play.count(channel_name) > 0) {
        total_msg_num_ += item.second.message_number();
      }

      auto& proto_desc = item.second.proto_desc();
      pb_factory->RegisterMessage(proto_desc);
    }

    auto& header = record_reader->header();
    if (play_param_.is_play_all_channels) {
      total_msg_num_ += header.message_number();
    }

    if (header.begin_time() < earliest_begin_time_) {
      earliest_begin_time_ = header.begin_time();
    }
    if (header.end_time() > latest_end_time_) {
      latest_end_time_ = header.end_time();
    }

    auto begin_time_s = static_cast<double>(header.begin_time()) / 1e9;
    auto end_time_s = static_cast<double>(header.end_time()) / 1e9;
    auto begin_time_str =
        common::UnixSecondsToString(static_cast<int>(begin_time_s));
    auto end_time_str =
        common::UnixSecondsToString(static_cast<int>(end_time_s));

    std::cout << "file: " << file << ", chunk_number: " << header.chunk_number()
              << ", begin_time: " << header.begin_time() << " ("
              << begin_time_str << ")"
              << ", end_time: " << header.end_time() << " (" << end_time_str
              << ")"
              << ", message_number: " << header.message_number() << std::endl;
  }

  std::cout << "earliest_begin_time: " << earliest_begin_time_
            << ", latest_end_time: " << latest_end_time_
            << ", total_msg_num: " << total_msg_num_ << std::endl;

  return true;
}

bool PlayTaskProducer::UpdatePlayParam() {
  if (play_param_.begin_time_ns < earliest_begin_time_) {
    play_param_.begin_time_ns = earliest_begin_time_;
  }
  if (play_param_.start_time_s > 0) {
    play_param_.begin_time_ns += static_cast<uint64_t>(
        static_cast<double>(play_param_.start_time_s) * 1e9);
  }
  if (play_param_.end_time_ns > latest_end_time_) {
    play_param_.end_time_ns = latest_end_time_;
  }
  if (play_param_.begin_time_ns >= play_param_.end_time_ns) {
    AERROR << "begin time are equal or larger than end time"
           << ", begin_time_ns=" << play_param_.begin_time_ns
           << ", end_time_ns=" << play_param_.end_time_ns;
    return false;
  }
  if (play_param_.preload_time_s == 0) {
    AINFO << "preload time is zero, we will use defalut value: "
          << kPreloadTimeSec << " seconds.";
    play_param_.preload_time_s = kPreloadTimeSec;
  }
  return true;
}

bool PlayTaskProducer::CreateWriters() {
  std::string node_name = "cyber_recorder_play_" + std::to_string(getpid());
  node_ = apollo::cyber::CreateNode(node_name);
  if (node_ == nullptr) {
    AERROR << "create node failed.";
    return false;
  }

  for (auto& item : msg_types_) {
    auto& channel_name = item.first;
    auto& msg_type = item.second;

    if (play_param_.is_play_all_channels ||
        play_param_.channels_to_play.count(channel_name) > 0) {
      if (play_param_.black_channels.find(channel_name) !=
          play_param_.black_channels.end()) {
        continue;
      }
      proto::RoleAttributes attr;
      attr.set_channel_name(channel_name);
      attr.set_message_type(msg_type);
      auto writer = node_->CreateWriter<message::RawMessage>(attr);
      if (writer == nullptr) {
        AERROR << "create wirter failed. channel name: " << channel_name
               << ", message type: " << msg_type;
        return false;
      }
      writers_[channel_name] = writer;
    }
  }

  return true;
}

void PlayTaskProducer::ThreadFunc() {
  const uint64_t loop_time_ns =
      play_param_.end_time_ns - play_param_.begin_time_ns;
  uint64_t avg_interval_time_ns = kSleepIntervalNanoSec;
  if (total_msg_num_ > 0) {
    avg_interval_time_ns = loop_time_ns / total_msg_num_;
  }

  double avg_freq_hz = static_cast<double>(total_msg_num_) /
                       (static_cast<double>(loop_time_ns) * 1e-9);
  uint32_t preload_size = (uint32_t)avg_freq_hz * play_param_.preload_time_s;
  AINFO << "preload_size: " << preload_size;
  if (preload_size < kMinTaskBufferSize) {
    preload_size = kMinTaskBufferSize;
  }

  auto record_viewer = std::make_shared<RecordViewer>(
      record_readers_, play_param_.begin_time_ns, play_param_.end_time_ns,
      play_param_.channels_to_play);

  uint32_t loop_num = 0;
  while (!is_stopped_.load()) {
    uint64_t plus_time_ns = loop_num * loop_time_ns;
    auto itr = record_viewer->begin();
    auto itr_end = record_viewer->end();

    while (itr != itr_end && !is_stopped_.load()) {
      while (!is_stopped_.load() && task_buffer_->Size() > preload_size) {
        std::this_thread::sleep_for(
            std::chrono::nanoseconds(avg_interval_time_ns));
      }
      for (; itr != itr_end && !is_stopped_.load(); ++itr) {
        if (task_buffer_->Size() > preload_size) {
          break;
        }

        auto search = writers_.find(itr->channel_name);
        if (search == writers_.end()) {
          continue;
        }

        auto raw_msg = std::make_shared<message::RawMessage>(itr->content);
        auto task = std::make_shared<PlayTask>(
            raw_msg, search->second, itr->time, itr->time + plus_time_ns);
        task_buffer_->Push(task);
      }
    }

    if (!play_param_.is_loop_playback) {
      is_stopped_.exchange(true);
      break;
    }
    ++loop_num;
  }
}

}  // namespace record
}  // namespace cyber
}  // namespace apollo
<|endoftext|>


<commit_before><commit_msg>only use OpenGL for window devices for now<commit_after><|endoftext|>


<commit_before>/*
 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "webrtc/video_engine/vie_base_impl.h"

#include <sstream>
#include <string>
#include <utility>

#include "webrtc/engine_configurations.h"
#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h"
#include "webrtc/modules/video_coding/main/interface/video_coding.h"
#include "webrtc/modules/video_processing/main/interface/video_processing.h"
#include "webrtc/modules/video_render/include/video_render.h"
#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
#include "webrtc/system_wrappers/interface/logging.h"
#include "webrtc/video_engine/include/vie_errors.h"
#include "webrtc/video_engine/vie_capturer.h"
#include "webrtc/video_engine/vie_channel.h"
#include "webrtc/video_engine/vie_channel_manager.h"
#include "webrtc/video_engine/vie_defines.h"
#include "webrtc/video_engine/vie_encoder.h"
#include "webrtc/video_engine/vie_impl.h"
#include "webrtc/video_engine/vie_input_manager.h"
#include "webrtc/video_engine/vie_shared_data.h"

namespace webrtc {

ViEBase* ViEBase::GetInterface(VideoEngine* video_engine) {
  if (!video_engine) {
    return NULL;
  }
  VideoEngineImpl* vie_impl = static_cast<VideoEngineImpl*>(video_engine);
  ViEBaseImpl* vie_base_impl = vie_impl;
  (*vie_base_impl)++;  // Increase ref count.

  return vie_base_impl;
}

int ViEBaseImpl::Release() {
  (*this)--;  // Decrease ref count.

  int32_t ref_count = GetCount();
  if (ref_count < 0) {
    LOG(LS_WARNING) << "ViEBase released too many times.";
    return -1;
  }
  return ref_count;
}

ViEBaseImpl::ViEBaseImpl(const Config& config)
    : shared_data_(config) {}

ViEBaseImpl::~ViEBaseImpl() {}

int ViEBaseImpl::Init() {
  return 0;
}

int ViEBaseImpl::SetVoiceEngine(VoiceEngine* voice_engine) {
  LOG_F(LS_INFO) << "SetVoiceEngine";
  if (shared_data_.channel_manager()->SetVoiceEngine(voice_engine) != 0) {
    shared_data_.SetLastError(kViEBaseVoEFailure);
    return -1;
  }
  return 0;
}

int ViEBaseImpl::RegisterCpuOveruseObserver(int video_channel,
                                            CpuOveruseObserver* observer) {
  LOG_F(LS_INFO) << "RegisterCpuOveruseObserver on channel " << video_channel;
  ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
  ViEChannel* vie_channel = cs.Channel(video_channel);
  if (!vie_channel) {
    shared_data_.SetLastError(kViEBaseInvalidChannelId);
    return -1;
  }
  ViEEncoder* vie_encoder = cs.Encoder(video_channel);
  assert(vie_encoder);

  ViEInputManagerScoped is(*(shared_data_.input_manager()));
  ViEFrameProviderBase* provider = is.FrameProvider(vie_encoder);
  if (provider) {
    ViECapturer* capturer = is.Capture(provider->Id());
    assert(capturer);
    capturer->RegisterCpuOveruseObserver(observer);
  }

  shared_data_.overuse_observers()->insert(
      std::pair<int, CpuOveruseObserver*>(video_channel, observer));
  return 0;
}

int ViEBaseImpl::SetCpuOveruseOptions(int video_channel,
                                      const CpuOveruseOptions& options) {
  ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
  ViEChannel* vie_channel = cs.Channel(video_channel);
  if (!vie_channel) {
    shared_data_.SetLastError(kViEBaseInvalidChannelId);
    return -1;
  }
  ViEEncoder* vie_encoder = cs.Encoder(video_channel);
  assert(vie_encoder);

  ViEInputManagerScoped is(*(shared_data_.input_manager()));
  ViEFrameProviderBase* provider = is.FrameProvider(vie_encoder);
  if (provider) {
    ViECapturer* capturer = is.Capture(provider->Id());
    if (capturer) {
      capturer->SetCpuOveruseOptions(options);
      return 0;
    }
  }
  return -1;
}

int ViEBaseImpl::CpuOveruseMeasures(int video_channel,
                                    int* capture_jitter_ms,
                                    int* avg_encode_time_ms,
                                    int* encode_usage_percent,
                                    int* capture_queue_delay_ms_per_s) {
  ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
  ViEChannel* vie_channel = cs.Channel(video_channel);
  if (!vie_channel) {
    shared_data_.SetLastError(kViEBaseInvalidChannelId);
    return -1;
  }
  ViEEncoder* vie_encoder = cs.Encoder(video_channel);
  assert(vie_encoder);

  ViEInputManagerScoped is(*(shared_data_.input_manager()));
  ViEFrameProviderBase* provider = is.FrameProvider(vie_encoder);
  if (provider) {
    ViECapturer* capturer = is.Capture(provider->Id());
    if (capturer) {
      capturer->CpuOveruseMeasures(capture_jitter_ms,
                                   avg_encode_time_ms,
                                   encode_usage_percent,
                                   capture_queue_delay_ms_per_s);
      return 0;
    }
  }
  return -1;
}

int ViEBaseImpl::CreateChannel(int& video_channel) {  // NOLINT
  return CreateChannel(video_channel, static_cast<const Config*>(NULL));
}

int ViEBaseImpl::CreateChannel(int& video_channel,  // NOLINT
                               const Config* config) {
  if (shared_data_.channel_manager()->CreateChannel(&video_channel,
                                                    config) == -1) {
    video_channel = -1;
    shared_data_.SetLastError(kViEBaseChannelCreationFailed);
    return -1;
  }
  LOG(LS_INFO) << "Video channel created: " << video_channel;
  return 0;
}

int ViEBaseImpl::CreateChannel(int& video_channel,  // NOLINT
                               int original_channel) {
  return CreateChannel(video_channel, original_channel, true);
}

int ViEBaseImpl::CreateReceiveChannel(int& video_channel,  // NOLINT
                                      int original_channel) {
  return CreateChannel(video_channel, original_channel, false);
}

int ViEBaseImpl::DeleteChannel(const int video_channel) {
  {
    ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
    ViEChannel* vie_channel = cs.Channel(video_channel);
    if (!vie_channel) {
      shared_data_.SetLastError(kViEBaseInvalidChannelId);
      return -1;
    }

    // Deregister the ViEEncoder if no other channel is using it.
    ViEEncoder* vie_encoder = cs.Encoder(video_channel);
    if (cs.ChannelUsingViEEncoder(video_channel) == false) {
      ViEInputManagerScoped is(*(shared_data_.input_manager()));
      ViEFrameProviderBase* provider = is.FrameProvider(vie_encoder);
      if (provider) {
        provider->DeregisterFrameCallback(vie_encoder);
      }
    }
  }

  if (shared_data_.channel_manager()->DeleteChannel(video_channel) == -1) {
    shared_data_.SetLastError(kViEBaseUnknownError);
    return -1;
  }
  LOG(LS_INFO) << "Channel deleted " << video_channel;
  return 0;
}

int ViEBaseImpl::ConnectAudioChannel(const int video_channel,
                                     const int audio_channel) {
  LOG_F(LS_INFO) << "ConnectAudioChannel, video channel " << video_channel
                 << ", audio channel " << audio_channel;
  ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
  if (!cs.Channel(video_channel)) {
    shared_data_.SetLastError(kViEBaseInvalidChannelId);
    return -1;
  }

  if (shared_data_.channel_manager()->ConnectVoiceChannel(video_channel,
                                                          audio_channel) != 0) {
    shared_data_.SetLastError(kViEBaseVoEFailure);
    return -1;
  }
  return 0;
}

int ViEBaseImpl::DisconnectAudioChannel(const int video_channel) {
  LOG_F(LS_INFO) << "DisconnectAudioChannel " << video_channel;
  ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
  if (!cs.Channel(video_channel)) {
    shared_data_.SetLastError(kViEBaseInvalidChannelId);
    return -1;
  }

  if (shared_data_.channel_manager()->DisconnectVoiceChannel(
      video_channel) != 0) {
    shared_data_.SetLastError(kViEBaseVoEFailure);
    return -1;
  }
  return 0;
}

int ViEBaseImpl::StartSend(const int video_channel) {
  LOG_F(LS_INFO) << "StartSend: " << video_channel;
  ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
  ViEChannel* vie_channel = cs.Channel(video_channel);
  if (!vie_channel) {
    shared_data_.SetLastError(kViEBaseInvalidChannelId);
    return -1;
  }

  ViEEncoder* vie_encoder = cs.Encoder(video_channel);
  assert(vie_encoder != NULL);
  if (vie_encoder->Owner() != video_channel) {
    LOG_F(LS_ERROR) <<  "Can't start send on a receive only channel.";
    shared_data_.SetLastError(kViEBaseReceiveOnlyChannel);
    return -1;
  }

  // Pause and trigger a key frame.
  vie_encoder->Pause();
  int32_t error = vie_channel->StartSend();
  if (error != 0) {
    vie_encoder->Restart();
    if (error == kViEBaseAlreadySending) {
      shared_data_.SetLastError(kViEBaseAlreadySending);
    }
    LOG_F(LS_ERROR) << "Could not start sending " << video_channel;
    shared_data_.SetLastError(kViEBaseUnknownError);
    return -1;
  }
  vie_encoder->SendKeyFrame();
  vie_encoder->Restart();
  return 0;
}

int ViEBaseImpl::StopSend(const int video_channel) {
  LOG_F(LS_INFO) << "StopSend " << video_channel;

  ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
  ViEChannel* vie_channel = cs.Channel(video_channel);
  if (!vie_channel) {
    shared_data_.SetLastError(kViEBaseInvalidChannelId);
    return -1;
  }

  int32_t error = vie_channel->StopSend();
  if (error != 0) {
    if (error == kViEBaseNotSending) {
      shared_data_.SetLastError(kViEBaseNotSending);
    } else {
      LOG_F(LS_ERROR) << "Could not stop sending " << video_channel;
      shared_data_.SetLastError(kViEBaseUnknownError);
    }
    return -1;
  }
  return 0;
}

int ViEBaseImpl::StartReceive(const int video_channel) {
  LOG_F(LS_INFO) << "StartReceive " << video_channel;

  ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
  ViEChannel* vie_channel = cs.Channel(video_channel);
  if (!vie_channel) {
    shared_data_.SetLastError(kViEBaseInvalidChannelId);
    return -1;
  }
  if (vie_channel->StartReceive() != 0) {
    shared_data_.SetLastError(kViEBaseUnknownError);
    return -1;
  }
  return 0;
}

int ViEBaseImpl::StopReceive(const int video_channel) {
  LOG_F(LS_INFO) << "StopReceive " << video_channel;
  ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
  ViEChannel* vie_channel = cs.Channel(video_channel);
  if (!vie_channel) {
    shared_data_.SetLastError(kViEBaseInvalidChannelId);
    return -1;
  }
  if (vie_channel->StopReceive() != 0) {
    shared_data_.SetLastError(kViEBaseUnknownError);
    return -1;
  }
  return 0;
}

int ViEBaseImpl::GetVersion(char version[1024]) {
  assert(kViEVersionMaxMessageSize == 1024);
  if (!version) {
    shared_data_.SetLastError(kViEBaseInvalidArgument);
    return -1;
  }

  // Add WebRTC Version.
  std::stringstream version_stream;
  version_stream << "VideoEngine 3.51.0" << std::endl;

  // Add build info.
  version_stream << "Build: " << BUILDINFO << std::endl;

  int version_length = version_stream.tellp();
  assert(version_length < 1024);
  memcpy(version, version_stream.str().c_str(), version_length);
  version[version_length] = '\0';
  return 0;
}

int ViEBaseImpl::LastError() {
  return shared_data_.LastErrorInternal();
}

int ViEBaseImpl::CreateChannel(int& video_channel,  // NOLINT
                               int original_channel, bool sender) {
  ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
  if (!cs.Channel(original_channel)) {
    shared_data_.SetLastError(kViEBaseInvalidChannelId);
    return -1;
  }

  if (shared_data_.channel_manager()->CreateChannel(&video_channel,
                                                    original_channel,
                                                    sender) == -1) {
    video_channel = -1;
    shared_data_.SetLastError(kViEBaseChannelCreationFailed);
    return -1;
  }
  LOG_F(LS_INFO) << "VideoChannel created: " << video_channel
                 << ", base channel " << original_channel
                 << ", is send channel : " << sender;
  return 0;
}

}  // namespace webrtc
<commit_msg>Updated WebRTC version to 3.52 TBR=wu@webrtc.org<commit_after>/*
 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "webrtc/video_engine/vie_base_impl.h"

#include <sstream>
#include <string>
#include <utility>

#include "webrtc/engine_configurations.h"
#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h"
#include "webrtc/modules/video_coding/main/interface/video_coding.h"
#include "webrtc/modules/video_processing/main/interface/video_processing.h"
#include "webrtc/modules/video_render/include/video_render.h"
#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
#include "webrtc/system_wrappers/interface/logging.h"
#include "webrtc/video_engine/include/vie_errors.h"
#include "webrtc/video_engine/vie_capturer.h"
#include "webrtc/video_engine/vie_channel.h"
#include "webrtc/video_engine/vie_channel_manager.h"
#include "webrtc/video_engine/vie_defines.h"
#include "webrtc/video_engine/vie_encoder.h"
#include "webrtc/video_engine/vie_impl.h"
#include "webrtc/video_engine/vie_input_manager.h"
#include "webrtc/video_engine/vie_shared_data.h"

namespace webrtc {

ViEBase* ViEBase::GetInterface(VideoEngine* video_engine) {
  if (!video_engine) {
    return NULL;
  }
  VideoEngineImpl* vie_impl = static_cast<VideoEngineImpl*>(video_engine);
  ViEBaseImpl* vie_base_impl = vie_impl;
  (*vie_base_impl)++;  // Increase ref count.

  return vie_base_impl;
}

int ViEBaseImpl::Release() {
  (*this)--;  // Decrease ref count.

  int32_t ref_count = GetCount();
  if (ref_count < 0) {
    LOG(LS_WARNING) << "ViEBase released too many times.";
    return -1;
  }
  return ref_count;
}

ViEBaseImpl::ViEBaseImpl(const Config& config)
    : shared_data_(config) {}

ViEBaseImpl::~ViEBaseImpl() {}

int ViEBaseImpl::Init() {
  return 0;
}

int ViEBaseImpl::SetVoiceEngine(VoiceEngine* voice_engine) {
  LOG_F(LS_INFO) << "SetVoiceEngine";
  if (shared_data_.channel_manager()->SetVoiceEngine(voice_engine) != 0) {
    shared_data_.SetLastError(kViEBaseVoEFailure);
    return -1;
  }
  return 0;
}

int ViEBaseImpl::RegisterCpuOveruseObserver(int video_channel,
                                            CpuOveruseObserver* observer) {
  LOG_F(LS_INFO) << "RegisterCpuOveruseObserver on channel " << video_channel;
  ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
  ViEChannel* vie_channel = cs.Channel(video_channel);
  if (!vie_channel) {
    shared_data_.SetLastError(kViEBaseInvalidChannelId);
    return -1;
  }
  ViEEncoder* vie_encoder = cs.Encoder(video_channel);
  assert(vie_encoder);

  ViEInputManagerScoped is(*(shared_data_.input_manager()));
  ViEFrameProviderBase* provider = is.FrameProvider(vie_encoder);
  if (provider) {
    ViECapturer* capturer = is.Capture(provider->Id());
    assert(capturer);
    capturer->RegisterCpuOveruseObserver(observer);
  }

  shared_data_.overuse_observers()->insert(
      std::pair<int, CpuOveruseObserver*>(video_channel, observer));
  return 0;
}

int ViEBaseImpl::SetCpuOveruseOptions(int video_channel,
                                      const CpuOveruseOptions& options) {
  ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
  ViEChannel* vie_channel = cs.Channel(video_channel);
  if (!vie_channel) {
    shared_data_.SetLastError(kViEBaseInvalidChannelId);
    return -1;
  }
  ViEEncoder* vie_encoder = cs.Encoder(video_channel);
  assert(vie_encoder);

  ViEInputManagerScoped is(*(shared_data_.input_manager()));
  ViEFrameProviderBase* provider = is.FrameProvider(vie_encoder);
  if (provider) {
    ViECapturer* capturer = is.Capture(provider->Id());
    if (capturer) {
      capturer->SetCpuOveruseOptions(options);
      return 0;
    }
  }
  return -1;
}

int ViEBaseImpl::CpuOveruseMeasures(int video_channel,
                                    int* capture_jitter_ms,
                                    int* avg_encode_time_ms,
                                    int* encode_usage_percent,
                                    int* capture_queue_delay_ms_per_s) {
  ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
  ViEChannel* vie_channel = cs.Channel(video_channel);
  if (!vie_channel) {
    shared_data_.SetLastError(kViEBaseInvalidChannelId);
    return -1;
  }
  ViEEncoder* vie_encoder = cs.Encoder(video_channel);
  assert(vie_encoder);

  ViEInputManagerScoped is(*(shared_data_.input_manager()));
  ViEFrameProviderBase* provider = is.FrameProvider(vie_encoder);
  if (provider) {
    ViECapturer* capturer = is.Capture(provider->Id());
    if (capturer) {
      capturer->CpuOveruseMeasures(capture_jitter_ms,
                                   avg_encode_time_ms,
                                   encode_usage_percent,
                                   capture_queue_delay_ms_per_s);
      return 0;
    }
  }
  return -1;
}

int ViEBaseImpl::CreateChannel(int& video_channel) {  // NOLINT
  return CreateChannel(video_channel, static_cast<const Config*>(NULL));
}

int ViEBaseImpl::CreateChannel(int& video_channel,  // NOLINT
                               const Config* config) {
  if (shared_data_.channel_manager()->CreateChannel(&video_channel,
                                                    config) == -1) {
    video_channel = -1;
    shared_data_.SetLastError(kViEBaseChannelCreationFailed);
    return -1;
  }
  LOG(LS_INFO) << "Video channel created: " << video_channel;
  return 0;
}

int ViEBaseImpl::CreateChannel(int& video_channel,  // NOLINT
                               int original_channel) {
  return CreateChannel(video_channel, original_channel, true);
}

int ViEBaseImpl::CreateReceiveChannel(int& video_channel,  // NOLINT
                                      int original_channel) {
  return CreateChannel(video_channel, original_channel, false);
}

int ViEBaseImpl::DeleteChannel(const int video_channel) {
  {
    ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
    ViEChannel* vie_channel = cs.Channel(video_channel);
    if (!vie_channel) {
      shared_data_.SetLastError(kViEBaseInvalidChannelId);
      return -1;
    }

    // Deregister the ViEEncoder if no other channel is using it.
    ViEEncoder* vie_encoder = cs.Encoder(video_channel);
    if (cs.ChannelUsingViEEncoder(video_channel) == false) {
      ViEInputManagerScoped is(*(shared_data_.input_manager()));
      ViEFrameProviderBase* provider = is.FrameProvider(vie_encoder);
      if (provider) {
        provider->DeregisterFrameCallback(vie_encoder);
      }
    }
  }

  if (shared_data_.channel_manager()->DeleteChannel(video_channel) == -1) {
    shared_data_.SetLastError(kViEBaseUnknownError);
    return -1;
  }
  LOG(LS_INFO) << "Channel deleted " << video_channel;
  return 0;
}

int ViEBaseImpl::ConnectAudioChannel(const int video_channel,
                                     const int audio_channel) {
  LOG_F(LS_INFO) << "ConnectAudioChannel, video channel " << video_channel
                 << ", audio channel " << audio_channel;
  ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
  if (!cs.Channel(video_channel)) {
    shared_data_.SetLastError(kViEBaseInvalidChannelId);
    return -1;
  }

  if (shared_data_.channel_manager()->ConnectVoiceChannel(video_channel,
                                                          audio_channel) != 0) {
    shared_data_.SetLastError(kViEBaseVoEFailure);
    return -1;
  }
  return 0;
}

int ViEBaseImpl::DisconnectAudioChannel(const int video_channel) {
  LOG_F(LS_INFO) << "DisconnectAudioChannel " << video_channel;
  ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
  if (!cs.Channel(video_channel)) {
    shared_data_.SetLastError(kViEBaseInvalidChannelId);
    return -1;
  }

  if (shared_data_.channel_manager()->DisconnectVoiceChannel(
      video_channel) != 0) {
    shared_data_.SetLastError(kViEBaseVoEFailure);
    return -1;
  }
  return 0;
}

int ViEBaseImpl::StartSend(const int video_channel) {
  LOG_F(LS_INFO) << "StartSend: " << video_channel;
  ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
  ViEChannel* vie_channel = cs.Channel(video_channel);
  if (!vie_channel) {
    shared_data_.SetLastError(kViEBaseInvalidChannelId);
    return -1;
  }

  ViEEncoder* vie_encoder = cs.Encoder(video_channel);
  assert(vie_encoder != NULL);
  if (vie_encoder->Owner() != video_channel) {
    LOG_F(LS_ERROR) <<  "Can't start send on a receive only channel.";
    shared_data_.SetLastError(kViEBaseReceiveOnlyChannel);
    return -1;
  }

  // Pause and trigger a key frame.
  vie_encoder->Pause();
  int32_t error = vie_channel->StartSend();
  if (error != 0) {
    vie_encoder->Restart();
    if (error == kViEBaseAlreadySending) {
      shared_data_.SetLastError(kViEBaseAlreadySending);
    }
    LOG_F(LS_ERROR) << "Could not start sending " << video_channel;
    shared_data_.SetLastError(kViEBaseUnknownError);
    return -1;
  }
  vie_encoder->SendKeyFrame();
  vie_encoder->Restart();
  return 0;
}

int ViEBaseImpl::StopSend(const int video_channel) {
  LOG_F(LS_INFO) << "StopSend " << video_channel;

  ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
  ViEChannel* vie_channel = cs.Channel(video_channel);
  if (!vie_channel) {
    shared_data_.SetLastError(kViEBaseInvalidChannelId);
    return -1;
  }

  int32_t error = vie_channel->StopSend();
  if (error != 0) {
    if (error == kViEBaseNotSending) {
      shared_data_.SetLastError(kViEBaseNotSending);
    } else {
      LOG_F(LS_ERROR) << "Could not stop sending " << video_channel;
      shared_data_.SetLastError(kViEBaseUnknownError);
    }
    return -1;
  }
  return 0;
}

int ViEBaseImpl::StartReceive(const int video_channel) {
  LOG_F(LS_INFO) << "StartReceive " << video_channel;

  ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
  ViEChannel* vie_channel = cs.Channel(video_channel);
  if (!vie_channel) {
    shared_data_.SetLastError(kViEBaseInvalidChannelId);
    return -1;
  }
  if (vie_channel->StartReceive() != 0) {
    shared_data_.SetLastError(kViEBaseUnknownError);
    return -1;
  }
  return 0;
}

int ViEBaseImpl::StopReceive(const int video_channel) {
  LOG_F(LS_INFO) << "StopReceive " << video_channel;
  ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
  ViEChannel* vie_channel = cs.Channel(video_channel);
  if (!vie_channel) {
    shared_data_.SetLastError(kViEBaseInvalidChannelId);
    return -1;
  }
  if (vie_channel->StopReceive() != 0) {
    shared_data_.SetLastError(kViEBaseUnknownError);
    return -1;
  }
  return 0;
}

int ViEBaseImpl::GetVersion(char version[1024]) {
  assert(kViEVersionMaxMessageSize == 1024);
  if (!version) {
    shared_data_.SetLastError(kViEBaseInvalidArgument);
    return -1;
  }

  // Add WebRTC Version.
  std::stringstream version_stream;
  version_stream << "VideoEngine 3.52.0" << std::endl;

  // Add build info.
  version_stream << "Build: " << BUILDINFO << std::endl;

  int version_length = version_stream.tellp();
  assert(version_length < 1024);
  memcpy(version, version_stream.str().c_str(), version_length);
  version[version_length] = '\0';
  return 0;
}

int ViEBaseImpl::LastError() {
  return shared_data_.LastErrorInternal();
}

int ViEBaseImpl::CreateChannel(int& video_channel,  // NOLINT
                               int original_channel, bool sender) {
  ViEChannelManagerScoped cs(*(shared_data_.channel_manager()));
  if (!cs.Channel(original_channel)) {
    shared_data_.SetLastError(kViEBaseInvalidChannelId);
    return -1;
  }

  if (shared_data_.channel_manager()->CreateChannel(&video_channel,
                                                    original_channel,
                                                    sender) == -1) {
    video_channel = -1;
    shared_data_.SetLastError(kViEBaseChannelCreationFailed);
    return -1;
  }
  LOG_F(LS_INFO) << "VideoChannel created: " << video_channel
                 << ", base channel " << original_channel
                 << ", is send channel : " << sender;
  return 0;
}

}  // namespace webrtc
<|endoftext|>


<commit_before>#ifndef VIENNAGRID_IO_POLY_READER_GUARD
#define VIENNAGRID_IO_POLY_READER_GUARD

/* =======================================================================
   Copyright (c) 2011-2012, Institute for Microelectronics,
                            Institute for Analysis and Scientific Computing,
                            TU Wien.

                            -----------------
                     ViennaGrid - The Vienna Grid Library
                            -----------------

   Authors:      Karl Rupp                           rupp@iue.tuwien.ac.at
                 Josef Weinbub                    weinbub@iue.tuwien.ac.at

   (A list of additional contributors can be found in the PDF manual)

   License:      MIT (X11), see file LICENSE in the base directory
======================================================================= */

#include <fstream>
#include <iostream>
#include <assert.h>

#include "viennadata/api.hpp"

#include "viennagrid/forwards.hpp"
#include "viennagrid/io/helper.hpp"

#include "viennagrid/domain/geometric_domain.hpp"

/** @file netgen_reader.hpp
    @brief Provides a reader for Netgen files
*/

namespace viennagrid
{
  namespace io
  {
    struct poly_attribute_tag {};
  }
}

VIENNADATA_ENABLE_TYPE_BASED_KEY_DISPATCH(viennagrid::io::poly_attribute_tag)

namespace viennagrid
{
  namespace io
  {

      template<typename stream_type>
      bool get_valid_line( stream_type & stream, std::string & line, char comment_line = '#' )
      {
          std::string tmp;

          while (true)
          {
                if (!std::getline(stream, tmp))
                    return false;

                std::size_t pos = tmp.find(comment_line);
                if (pos != std::string::npos)
                    tmp = tmp.substr(0, pos);

                for (std::size_t i = 0; i != tmp.size(); ++i)
                {
                    if ( tmp[i] != ' ' )
                    {
                        line = tmp.substr(i, std::string::npos);
                        return true;
                    }
                }
          }
      }

    /** @brief Reader for Netgen files obtained from the 'Export mesh...' menu item. Tested with Netgen version 4.9.12. */
    struct poly_reader
    {
      /** @brief The functor interface triggering the read operation.
       *
       * @param domain    A ViennaGrid domain
       * @param filename  Name of the file
       */
      template <typename GeometricDomainType>
      int operator()(GeometricDomainType & domain, std::string const & filename) const
      {
        //typedef typename DomainType::config_type                         ConfigType;

//         typedef typename GeometricSegmentContainerType::value_type SegmentType;

        typedef typename viennagrid::result_of::point_type<GeometricDomainType>::type    PointType;
        typedef typename viennagrid::result_of::coord_type< PointType >::type         CoordType;

        //typedef typename ConfigType::numeric_type                        CoordType;
        //typedef typename ConfigType::coordinate_system_tag               CoordinateSystemTag;
        enum { point_dim = viennagrid::traits::static_size<PointType>::value };

        typedef plc_tag CellTag;
        typedef typename result_of::element<GeometricDomainType, CellTag>::type CellType;
        //typedef typename CellType::tag                            CellTag;
        typedef typename result_of::element_hook<GeometricDomainType, CellTag>::type                           CellHookType;

        //typedef typename result_of::point<ConfigType>::type                              PointType;
        typedef typename result_of::element<GeometricDomainType, vertex_tag>::type                           VertexType;
        typedef typename result_of::element_hook<GeometricDomainType, vertex_tag>::type                           VertexHookType;
        typedef typename VertexType::id_type VertexIDType;
        //typedef typename result_of::ncell<DomainType, CellTag::dim>::type     CellType;

        typedef typename result_of::element<GeometricDomainType, polygon_tag>::type                           PolygonType;
        typedef typename result_of::element_hook<GeometricDomainType, polygon_tag>::type                           PolygonHookType;

        typedef typename result_of::element<GeometricDomainType, line_tag>::type                           LineType;
        typedef typename result_of::element_hook<GeometricDomainType, line_tag>::type                           LineHookType;

//         typedef typename viennagrid::result_of::element_range<GeometricDomainType, vertex_tag>::type   VertexRange;
//         typedef typename viennagrid::result_of::iterator<VertexRange>::type        VertexIterator;
//
//         typedef typename viennagrid::result_of::element_range<GeometricDomainType, line_tag>::type   EdgeRange;
//         typedef typename viennagrid::result_of::iterator<EdgeRange>::type          EdgeIterator;
//
//         typedef typename viennagrid::result_of::element_range<GeometricDomainType, typename CellType::tag::facet_tag >::type   FacetRange;
//         typedef typename viennagrid::result_of::iterator<FacetRange>::type                                 FacetIterator;
//
//         typedef typename viennagrid::result_of::element_range<GeometricDomainType, CellTag>::type     CellRange;
//         typedef typename viennagrid::result_of::iterator<CellRange>::type                                  CellIterator;

        std::ifstream reader(filename.c_str());

        #if defined VIENNAGRID_DEBUG_STATUS || defined VIENNAGRID_DEBUG_IO
        std::cout << "* netgen_reader::operator(): Reading file " << filename << std::endl;
        #endif

        if (!reader)
        {
          throw cannot_open_file_exception(filename);
          return EXIT_FAILURE;
        }

        std::string tmp;
        std::istringstream current_line;

        long node_num = 0;
        long dim = 0;
        long attribute_num = 0;
        long boundary_marker_num = 0;

        if (!reader.good())
          throw bad_file_format_exception(filename, "File is empty.");

        //
        // Read vertices:
        //
        if (!get_valid_line(reader, tmp))
            throw bad_file_format_exception(filename, "EOF encountered when reading information");

        current_line.str(tmp); current_line.clear();
        current_line >> node_num >> dim >> attribute_num >> boundary_marker_num;

        if (node_num < 0)
            throw bad_file_format_exception(filename, "POLY file has less than 0 nodes");
        if (dim != 3)
            throw bad_file_format_exception(filename, "POLY dimension is not 3");
        if (attribute_num < 0)
            throw bad_file_format_exception(filename, "POLY file has less than 0 attributes");
        if ((boundary_marker_num < 0) || (boundary_marker_num > 1))
            throw bad_file_format_exception(filename, "POLY file has not 0 or 1 boundary marker");

        #if defined VIENNAGRID_DEBUG_STATUS || defined VIENNAGRID_DEBUG_IO
        std::cout << "* netgen_reader::operator(): Reading " << node_num << " vertices... " << std::endl;
        #endif

        for (int i=0; i<node_num; i++)
        {
            if (!get_valid_line(reader, tmp))
                throw bad_file_format_exception(filename, "EOF encountered when reading information");

            typename VertexIDType::base_id_type id;

            current_line.str(tmp); current_line.clear();
            current_line >> id;

            VertexHookType vertex = viennagrid::create_element<VertexType>( domain, VertexIDType(id) );
            PointType & p = viennagrid::point( domain, vertex );

            for (int j=0; j<point_dim; j++)
                current_line >> p[j];

            std::vector<CoordType> attributes(attribute_num);
            for (int j=0; j<attribute_num; j++)
                current_line >> attributes[j];

            viennadata::access<poly_attribute_tag, std::vector<CoordType> >()(viennagrid::dereference_hook(domain, vertex)) = attributes;
        }

        //std::cout << "DONE" << std::endl;
        if (!reader.good())
          throw bad_file_format_exception(filename, "EOF encountered when reading number of cells.");

        //
        // Read facets:
        //
        long facet_num = 0;
        if (!get_valid_line(reader, tmp))
            throw bad_file_format_exception(filename, "EOF encountered when reading information");

        current_line.str(tmp); current_line.clear();
        current_line >> facet_num >> boundary_marker_num;

        if (facet_num < 0)
            throw bad_file_format_exception(filename, "POLY file has less than 0 facets");
        if ((boundary_marker_num < 0) || (boundary_marker_num > 1))
            throw bad_file_format_exception(filename, "POLY file has not 0 or 1 boundary marker");

        //domain.reserve_cells(cell_num);

        #if defined VIENNAGRID_DEBUG_STATUS || defined VIENNAGRID_DEBUG_IO
        std::cout << "* netgen_reader::operator(): Reading " << cell_num << " cells... " << std::endl;
        #endif

        //CellHookType cell = viennagrid::create_element<CellType>(domain);
        //std::cout << "Filling " << cell_num << " cells:" << std::endl;

        for (int i=0; i<facet_num; ++i)
        {
            long polygon_num;
            long hole_num;

            if (!get_valid_line(reader, tmp))
                throw bad_file_format_exception(filename, "EOF encountered when reading information");

            current_line.str(tmp); current_line.clear();
            current_line >> polygon_num >> hole_num;

            if (polygon_num < 0)
                throw bad_file_format_exception(filename, "POLY facet has less than 0 polygons");
            if (hole_num < 0)
                throw bad_file_format_exception(filename, "POLY facet has less than 0 holes");

            std::vector<PolygonHookType> polygons;
            std::vector<LineHookType> lines;
            std::vector<VertexHookType> vertices;

            for (int j = 0; j<polygon_num; ++j)
            {
                long vertex_num;

                if (!get_valid_line(reader, tmp))
                    throw bad_file_format_exception(filename, "EOF encountered when reading information");

                current_line.str(tmp); current_line.clear();
                current_line >> vertex_num;

                if (vertex_num < 0)
                    throw bad_file_format_exception(filename, "POLY polygon has less than 0 vertices");

                std::vector<VertexHookType> vertex_hooks(vertex_num);

                for (int k = 0; k<vertex_num; ++k)
                {
                    long id;
                    current_line >> id;
                    vertex_hooks[k] = *viennagrid::find_hook( domain, VertexIDType(id) );
                }

                if (vertex_num == 1)
                {
                    vertices.push_back( vertex_hooks.front() );
//                     std::cout << " Added loose vertex" << std::endl;
                }
                else if (vertex_num == 2)
                {
                    lines.push_back( viennagrid::create_element<LineType>(domain, vertex_hooks.begin(), vertex_hooks.end()) );
//                     std::cout << " Added loose line" << std::endl;
                }
                else
                {
                    polygons.push_back( viennagrid::create_element<PolygonType>(domain, vertex_hooks.begin(), vertex_hooks.end()) );
//                     std::cout << " Added polygon " << vertex_hooks.size() << std::endl;
                }
            }

            viennagrid::create_element<CellType>(
                domain,
                polygons.begin(), polygons.end(),
                polygons.begin(), polygons.begin(),
                lines.begin(), lines.end(),
                vertices.begin(), vertices.end()
            );

//             std::cout << "Created PLC " << i << std::endl;
        }
        //std::cout << "All done!" << std::endl;

        return EXIT_SUCCESS;
      } //operator()

    }; //class netgen_reader

  } //namespace io
} //namespace viennagrid

#endif
<commit_msg>added hole support<commit_after>#ifndef VIENNAGRID_IO_POLY_READER_GUARD
#define VIENNAGRID_IO_POLY_READER_GUARD

/* =======================================================================
   Copyright (c) 2011-2012, Institute for Microelectronics,
                            Institute for Analysis and Scientific Computing,
                            TU Wien.

                            -----------------
                     ViennaGrid - The Vienna Grid Library
                            -----------------

   Authors:      Karl Rupp                           rupp@iue.tuwien.ac.at
                 Josef Weinbub                    weinbub@iue.tuwien.ac.at

   (A list of additional contributors can be found in the PDF manual)

   License:      MIT (X11), see file LICENSE in the base directory
======================================================================= */

#include <fstream>
#include <iostream>
#include <assert.h>

#include "viennadata/api.hpp"

#include "viennagrid/forwards.hpp"
#include "viennagrid/io/helper.hpp"

#include "viennagrid/domain/geometric_domain.hpp"

#include "viennagrid/algorithm/geometry.hpp"
#include "viennagrid/domain/metainfo_range.hpp"

/** @file netgen_reader.hpp
    @brief Provides a reader for Netgen files
*/

namespace viennagrid
{
  namespace io
  {
    struct poly_attribute_tag {};
  }
}

VIENNADATA_ENABLE_TYPE_BASED_KEY_DISPATCH(viennagrid::io::poly_attribute_tag)

namespace viennagrid
{
  namespace io
  {

      template<typename stream_type>
      bool get_valid_line( stream_type & stream, std::string & line, char comment_line = '#' )
      {
          std::string tmp;

          while (true)
          {
                if (!std::getline(stream, tmp))
                    return false;

                std::size_t pos = tmp.find(comment_line);
                if (pos != std::string::npos)
                    tmp = tmp.substr(0, pos);

                for (std::size_t i = 0; i != tmp.size(); ++i)
                {
                    if ( tmp[i] != ' ' )
                    {
                        line = tmp.substr(i, std::string::npos);
                        return true;
                    }
                }
          }
      }

    /** @brief Reader for Netgen files obtained from the 'Export mesh...' menu item. Tested with Netgen version 4.9.12. */
    struct poly_reader
    {
      /** @brief The functor interface triggering the read operation.
       *
       * @param domain    A ViennaGrid domain
       * @param filename  Name of the file
       */
      template <typename GeometricDomainType>
      int operator()(GeometricDomainType & domain, std::string const & filename) const
      {
        //typedef typename DomainType::config_type                         ConfigType;

//         typedef typename GeometricSegmentContainerType::value_type SegmentType;

        typedef typename viennagrid::result_of::point_type<GeometricDomainType>::type    PointType;
        typedef typename viennagrid::result_of::coord_type< PointType >::type         CoordType;

        //typedef typename ConfigType::numeric_type                        CoordType;
        //typedef typename ConfigType::coordinate_system_tag               CoordinateSystemTag;
        enum { point_dim = viennagrid::traits::static_size<PointType>::value };

        typedef plc_tag CellTag;
        typedef typename result_of::element<GeometricDomainType, CellTag>::type CellType;
        //typedef typename CellType::tag                            CellTag;
        typedef typename result_of::element_hook<GeometricDomainType, CellTag>::type                           CellHookType;

        //typedef typename result_of::point<ConfigType>::type                              PointType;
        typedef typename result_of::element<GeometricDomainType, vertex_tag>::type                           VertexType;
        typedef typename result_of::element_hook<GeometricDomainType, vertex_tag>::type                           VertexHookType;
        typedef typename VertexType::id_type VertexIDType;
        //typedef typename result_of::ncell<DomainType, CellTag::dim>::type     CellType;

        typedef typename result_of::element<GeometricDomainType, polygon_tag>::type                           PolygonType;
        typedef typename result_of::element_hook<GeometricDomainType, polygon_tag>::type                           PolygonHookType;

        typedef typename result_of::element<GeometricDomainType, line_tag>::type                           LineType;
        typedef typename result_of::element_hook<GeometricDomainType, line_tag>::type                           LineHookType;

//         typedef typename viennagrid::result_of::element_range<GeometricDomainType, vertex_tag>::type   VertexRange;
//         typedef typename viennagrid::result_of::iterator<VertexRange>::type        VertexIterator;
//
//         typedef typename viennagrid::result_of::element_range<GeometricDomainType, line_tag>::type   EdgeRange;
//         typedef typename viennagrid::result_of::iterator<EdgeRange>::type          EdgeIterator;
//
//         typedef typename viennagrid::result_of::element_range<GeometricDomainType, typename CellType::tag::facet_tag >::type   FacetRange;
//         typedef typename viennagrid::result_of::iterator<FacetRange>::type                                 FacetIterator;
//
//         typedef typename viennagrid::result_of::element_range<GeometricDomainType, CellTag>::type     CellRange;
//         typedef typename viennagrid::result_of::iterator<CellRange>::type                                  CellIterator;

        std::ifstream reader(filename.c_str());

        #if defined VIENNAGRID_DEBUG_STATUS || defined VIENNAGRID_DEBUG_IO
        std::cout << "* netgen_reader::operator(): Reading file " << filename << std::endl;
        #endif

        if (!reader)
        {
          throw cannot_open_file_exception(filename);
          return EXIT_FAILURE;
        }

        std::string tmp;
        std::istringstream current_line;

        long node_num = 0;
        long dim = 0;
        long attribute_num = 0;
        long boundary_marker_num = 0;

        if (!reader.good())
          throw bad_file_format_exception(filename, "File is empty.");

        //
        // Read vertices:
        //
        if (!get_valid_line(reader, tmp))
            throw bad_file_format_exception(filename, "EOF encountered when reading information");

        current_line.str(tmp); current_line.clear();
        current_line >> node_num >> dim >> attribute_num >> boundary_marker_num;

        if (node_num < 0)
            throw bad_file_format_exception(filename, "POLY file has less than 0 nodes");
        if (dim != point_dim)
            throw bad_file_format_exception(filename, "POLY point dimension missmatch");
        if (attribute_num < 0)
            throw bad_file_format_exception(filename, "POLY file has less than 0 attributes");
        if ((boundary_marker_num < 0) || (boundary_marker_num > 1))
            throw bad_file_format_exception(filename, "POLY file has not 0 or 1 boundary marker");

        #if defined VIENNAGRID_DEBUG_STATUS || defined VIENNAGRID_DEBUG_IO
        std::cout << "* netgen_reader::operator(): Reading " << node_num << " vertices... " << std::endl;
        #endif

        typedef typename VertexIDType::base_id_type id_type;

        for (int i=0; i<node_num; i++)
        {
            if (!get_valid_line(reader, tmp))
                throw bad_file_format_exception(filename, "EOF encountered when reading information");

            typename VertexIDType::base_id_type id;

            current_line.str(tmp); current_line.clear();
            current_line >> id;

            VertexHookType vertex = viennagrid::create_element<VertexType>( domain, VertexIDType(id) );
            PointType & p = viennagrid::point( domain, vertex );

            for (int j=0; j<point_dim; j++)
                current_line >> p[j];

            if (attribute_num > 0)
            {
                std::vector<CoordType> attributes(attribute_num);
                for (int j=0; j<attribute_num; j++)
                    current_line >> attributes[j];

                viennadata::access<poly_attribute_tag, std::vector<CoordType> >()(viennagrid::dereference_hook(domain, vertex)) = attributes;
            }
        }

        //std::cout << "DONE" << std::endl;
        if (!reader.good())
          throw bad_file_format_exception(filename, "EOF encountered when reading number of cells.");

        //
        // Read facets:
        //
        long facet_num = 0;
        if (!get_valid_line(reader, tmp))
            throw bad_file_format_exception(filename, "EOF encountered when reading information");

        current_line.str(tmp); current_line.clear();
        current_line >> facet_num >> boundary_marker_num;

        if (facet_num < 0)
            throw bad_file_format_exception(filename, "POLY file has less than 0 facets");
        if ((boundary_marker_num < 0) || (boundary_marker_num > 1))
            throw bad_file_format_exception(filename, "POLY file has not 0 or 1 boundary marker");

        //domain.reserve_cells(cell_num);

        #if defined VIENNAGRID_DEBUG_STATUS || defined VIENNAGRID_DEBUG_IO
        std::cout << "* netgen_reader::operator(): Reading " << cell_num << " cells... " << std::endl;
        #endif

        //CellHookType cell = viennagrid::create_element<CellType>(domain);
        //std::cout << "Filling " << cell_num << " cells:" << std::endl;

        for (int i=0; i<facet_num; ++i)
        {
            long polygon_num;
            long hole_num;

            if (!get_valid_line(reader, tmp))
                throw bad_file_format_exception(filename, "EOF encountered when reading information");

            current_line.str(tmp); current_line.clear();
            current_line >> polygon_num >> hole_num;

            if (polygon_num < 0)
                throw bad_file_format_exception(filename, "POLY facet has less than 0 polygons");
            if (hole_num < 0)
                throw bad_file_format_exception(filename, "POLY facet has less than 0 holes");

            std::list<PolygonHookType> polygons;
            std::list<LineHookType> lines;
            std::list<VertexHookType> vertices;

            typedef typename viennagrid::result_of::element_view<GeometricDomainType, VertexType>::type VertexViewType;
            VertexViewType used_vertices = viennagrid::element_view<VertexType>(domain);

            for (int j = 0; j<polygon_num; ++j)
            {
                long vertex_num;

                if (!get_valid_line(reader, tmp))
                    throw bad_file_format_exception(filename, "EOF encountered when reading information");

                current_line.str(tmp); current_line.clear();
                current_line >> vertex_num;

                if (vertex_num < 0)
                    throw bad_file_format_exception(filename, "POLY polygon has less than 0 vertices");

                std::vector<VertexHookType> vertex_hooks(vertex_num);

                for (int k = 0; k<vertex_num; ++k)
                {
                    long id;
                    current_line >> id;
                    vertex_hooks[k] = *viennagrid::find_hook( domain, VertexIDType(id) );
//                     used_vertices.insert( vertex_hooks[k] );
                    used_vertices.insert_hook( vertex_hooks[k] );
                }

                if (vertex_num == 1)
                {
                    vertices.push_back( vertex_hooks.front() );
                    std::cout << " Added loose vertex" << std::endl;
                }
                else if (vertex_num == 2)
                {
                    lines.push_back( viennagrid::create_element<LineType>(domain, vertex_hooks.begin(), vertex_hooks.end()) );
                    std::cout << " Added loose line" << std::endl;
                }
                else
                {
                    polygons.push_back( viennagrid::create_element<PolygonType>(domain, vertex_hooks.begin(), vertex_hooks.end()) );
                    std::cout << " Added polygon " << vertex_hooks.size() << std::endl;
                }
            }

            std::list<PointType> hole_points;

            for (int j = 0; j<hole_num; ++j)
            {
                if (!get_valid_line(reader, tmp))
                    throw bad_file_format_exception(filename, "EOF encountered when reading information");

                long hole_id;

                current_line.str(tmp); current_line.clear();
                current_line >> hole_id;

                PointType p;

                for (int j=0; j<point_dim; j++)
                    current_line >> p[j];

                std::cout << "Adding hole Point " << p << std::endl;

                hole_points.push_back(p);
            }

            viennagrid::create_element<CellType>(
                domain,
                polygons.begin(), polygons.end(),
                lines.begin(), lines.end(),
                vertices.begin(), vertices.end(),
                hole_points.begin(), hole_points.end()
            );
        }
        //std::cout << "All done!" << std::endl;

        return EXIT_SUCCESS;
      } //operator()

    }; //class netgen_reader

  } //namespace io
} //namespace viennagrid

#endif
<|endoftext|>