<commit_before>/* Copyright 2014 - 2015 CyberTech Labs Ltd.
 *
 * 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 "src/mailboxServer.h"

#include "src/mailboxConnection.h"

#include <QtNetwork/QNetworkInterface>
#include <QtCore/QSettings>

#include <trikKernel/paths.h>
#include <QHostInfo>
#include <QsLog.h>

using namespace trikNetwork;

MailboxServer::MailboxServer(quint16 port)
	: TrikServer([this] () { return connectionFactory(); })
	, mHullNumber(0)
	, mMyIp(determineMyIp())
	, mMyPort(port)
{
	setObjectName("MailboxServer");
	qRegisterMetaType<QHostAddress>("QHostAddress");
	loadSettings();
}

bool MailboxServer::isConnected()
{
	bool result = false;
	mKnownRobotsLock.lockForRead();
	for (auto &&endpoint : mKnownRobots) {
		const auto connection = this->connection(endpoint.ip, endpoint.port);
		auto mailboxConnection = qobject_cast<MailboxConnection *>(connection);
		if (mailboxConnection && mailboxConnection->isConnected()) {
			result = true;
			break;
		}
	}

	mKnownRobotsLock.unlock();
	return result;
}

int MailboxServer::hullNumber() const
{
	return mHullNumber;
}

QHostAddress MailboxServer::serverIp()
{
	mAuxiliaryInformationLock.lockForRead();
	const auto result = mServerIp;
	mAuxiliaryInformationLock.unlock();
	return result;
}

QHostAddress MailboxServer::myIp() const
{
	return mMyIp;
}

void MailboxServer::renewIp()
{
	mMyIp = determineMyIp();
}

void MailboxServer::start()
{
	startServer(mMyPort);

	if (!mServerIp.isNull() && mMyIp == mSavedIp) {
		connectTo(mServerIp, mServerPort);
	}
}

void MailboxServer::setHullNumber(int hullNumber)
{
	mHullNumber = hullNumber;
	saveSettings();
	forEveryConnection(
		[this](Connection *connection) {
			auto c = qobject_cast<MailboxConnection *>(connection);
			QMetaObject::invokeMethod(c, [c,this]() { c->sendConnectionInfo(mMyIp, mMyPort, mHullNumber); });
	}
	, -1);
}

void MailboxServer::connectTo(const QString &ip, int port)
{
	mAuxiliaryInformationLock.lockForRead();
	auto server = mServerIp;
	auto serverPort = mServerPort;
	mAuxiliaryInformationLock.unlock();

	if (server.toString() != ip || serverPort != port) {
		mAuxiliaryInformationLock.lockForWrite();
		mServerIp = QHostInfo::fromName(ip).addresses().first();
		mServerPort = port;
		mAuxiliaryInformationLock.unlock();

		saveSettings();
	}

	QReadLocker l(&mAuxiliaryInformationLock);
	connectTo(mServerIp, mServerPort);
}

void MailboxServer::connectTo(const QString &ip)
{
	connectTo(ip, mMyPort);
}

Connection *MailboxServer::connectTo(const QHostAddress &ip, int port)
{
	if (ip == mMyIp && port == mMyPort && isListening()) {
		// do not connect to self
		return nullptr;
	}

	const auto connectionObject = connection(ip, port);
	if (connectionObject != nullptr) {
		return connectionObject;
	}

	const auto c = new MailboxConnection();
	connectConnection(c);
	connect(this, &MailboxServer::startedConnection, c, [=]() {
		c->connect(ip, port, mMyPort, mHullNumber);
	});
	startConnection(c);
	return c;
}

Connection *MailboxServer::connectionFactory()
{
	auto connection = new MailboxConnection();

	QObject::connect(connection, &MailboxConnection::newConnection, this, &MailboxServer::onNewConnection);

	connectConnection(connection);

	return connection;
}

void MailboxServer::connectConnection(Connection * connection)
{
	auto c = qobject_cast<MailboxConnection *>(connection);
	connect(c, &MailboxConnection::connectionInfo, this, &MailboxServer::onConnectionInfo);
	connect(c, &MailboxConnection::newData, this, &MailboxServer::onNewData);
}

QHostAddress MailboxServer::determineMyIp()
{
	QList<QNetworkInterface> ifs {
				// TRIK wlan0
				QNetworkInterface::interfaceFromName("wlan0")
				// Fallback to localhost
				, QNetworkInterface::interfaceFromName("lo")
				, QNetworkInterface::interfaceFromIndex(1)
	};
	for (auto &&interface : ifs) {
		if (interface.isValid()) {
			for (auto &&entry : interface.addressEntries()) {
				const QHostAddress ip = entry.ip();
				if (ip.protocol() == QAbstractSocket::IPv4Protocol) {
					return ip;
				}
			}
		}
	}

	return QHostAddress(); // Total fail
}

Connection *MailboxServer::prepareConnection(const QHostAddress &ip)
{
	// First, trying to reuse existing connection.
	const auto connectionObject = connection(ip);
	if (connectionObject != nullptr) {
		return connectionObject;
	}
	// Next, trying to create new connection to given IP. We need port, so checking if robot is known.
	Endpoint targetEndpoint;
	mKnownRobotsLock.lockForRead();
	for (auto &&endpoint : mKnownRobots) {
		if (endpoint.ip == ip) {
			targetEndpoint = endpoint;
			break;
		}
	}

	mKnownRobotsLock.unlock();

	if (targetEndpoint.ip.isNull()) {
		QLOG_ERROR() << "Trying to connect to unknown robot, IP:" << ip;
		return nullptr;
	}
	return connectTo(targetEndpoint.ip, targetEndpoint.port);
}

void MailboxServer::onNewConnection(const QHostAddress &ip, int clientPort, int serverPort, int hullNumber)
{
	if (ip == mMyIp && serverPort == mMyPort ) {
		/// Refuse to handle connections from ourselves.
		return;
	}

	mKnownRobotsLock.lockForRead();
	const auto knownRobot = mKnownRobots.contains(hullNumber, {ip, serverPort});
	const auto endpoints = mKnownRobots.values();
	mKnownRobotsLock.unlock();

	if (!knownRobot) {
		// Propagate information about newly connected robot through robot network.
		forEveryConnection([ip, serverPort, hullNumber](Connection *connection) {
			auto c = qobject_cast<MailboxConnection *>(connection);
			QMetaObject::invokeMethod(c, [=]() {c->sendConnectionInfo(ip, serverPort, hullNumber);});
		});
	}

	// Send known connection information to newly connected robot.
	const auto c = qobject_cast<MailboxConnection *>(connection(ip, clientPort));
	if (c != nullptr) {
		mKnownRobotsLock.lockForRead();
		for (const auto &endpoint : endpoints) {
			QMetaObject::invokeMethod(c, [this, c, endpoint]() {
				c->sendConnectionInfo(endpoint.ip, endpoint.port, mKnownRobots.key(endpoint));
			});
		}

		// Send information about myself.
		QMetaObject::invokeMethod(c, [this, c]() { c->sendSelfInfo(mHullNumber); });
		mKnownRobotsLock.unlock();
	} else {
		QLOG_ERROR() << "Something went wrong, new connection to" << ip << ":" << clientPort << "is dead";
		return;
	}

	if (!knownRobot) {
		mKnownRobotsLock.lockForWrite();

		mKnownRobots.insert(hullNumber, {ip, serverPort});
		mKnownRobotsLock.unlock();
	}
}

void MailboxServer::send(int hullNumber, const QString &message)
{
	const auto data = QString("data:%1").arg(message).toUtf8();
	forEveryConnection(
		[data](Connection *c) {
			QMetaObject::invokeMethod(c, [c, data]() { c->send(data); });
		}
	, hullNumber);
}

void MailboxServer::send(const QString &message)
{
	send(-1, message);
}

void MailboxServer::onConnectionInfo(const QHostAddress &ip, int port, int hullNumber)
{
	if (ip == mMyIp && port == mMyPort) {
		return;
	}

	QVector<Endpoint> toDelete;
	mKnownRobotsLock.lockForRead();
	for (auto &&endpoint : mKnownRobots) {
		if (endpoint == Endpoint{ip, port}) {
			toDelete << endpoint;
		}
	}

	mKnownRobotsLock.unlock();

	mKnownRobotsLock.lockForWrite();
	for (const auto &endpoint : toDelete) {
		const auto keys = mKnownRobots.keys(endpoint);
		for (const auto &key : keys) {
			mKnownRobots.remove(key, endpoint);
		}
	}

	mKnownRobots.insert(hullNumber, {ip, port});
	mKnownRobotsLock.unlock();
}

void MailboxServer::onNewData(const QHostAddress &ip, int port, const QByteArray &data)
{
	QLOG_INFO() << "New data received by a mailbox from " << ip << ":" << port << ", data is:" << data;
	int senderHullNumber = -1;
	mKnownRobotsLock.lockForRead();
	for (const auto &endpoint : mKnownRobots) {
		if (endpoint.ip == ip) {
			senderHullNumber = mKnownRobots.key(endpoint);
		}
	}

	mKnownRobotsLock.unlock();

	if (senderHullNumber == -1) {
		QLOG_INFO() << "Received message from" << ip << ":" << port << "which is unknown at the moment";
	}

	mMessagesQueueLock.lockForWrite();
	mMessagesQueue.enqueue(data);
	mMessagesQueueLock.unlock();

	emit newMessage(senderHullNumber, QString(data));
}

bool MailboxServer::hasMessages()
{
	mMessagesQueueLock.lockForRead();
	const bool result = !mMessagesQueue.isEmpty();
	mMessagesQueueLock.unlock();

	return result;
}

QString MailboxServer::receive()
{
	mMessagesQueueLock.lockForWrite();
	QByteArray const result = !mMessagesQueue.isEmpty() ? mMessagesQueue.dequeue() : QByteArray();
	mMessagesQueueLock.unlock();

	return result;
}

bool MailboxServer::hasServer() const
{
	return isListening();
}

void MailboxServer::loadSettings()
{
	QWriteLocker l(&mAuxiliaryInformationLock);
	QSettings settings(trikKernel::Paths::localSettings(), QSettings::IniFormat);
	mHullNumber = settings.value("hullNumber", 0).toInt();
	auto tryResolve = [](const QString &ipOrName) {
		auto info = QHostInfo::fromName(ipOrName);
		if (info.error() != QHostInfo::NoError || info.addresses().isEmpty()) {
			QLOG_ERROR() << "Failed to get ip for " << ipOrName << ":" << info.error();
			return QHostAddress();
		} else {
			return info.addresses().first();
		}
	};

	mServerIp = tryResolve(settings.value("server", mMyIp.toString()).toString());
	mServerPort = settings.value("serverPort", mMyPort).toInt();
	mSavedIp = tryResolve(settings.value("localIp", mMyIp.toString()).toString());
}

void MailboxServer::saveSettings()
{
	mAuxiliaryInformationLock.lockForRead();
	QSettings settings(trikKernel::Paths::localSettings(), QSettings::IniFormat);
	settings.setValue("hullNumber", mHullNumber);
	settings.setValue("server", mServerIp.toString());
	settings.setValue("serverPort", mServerPort);
	settings.setValue("localIp", mMyIp.toString());
	mAuxiliaryInformationLock.unlock();
}

void MailboxServer::forEveryConnection(const std::function<void(Connection *)> &method, int hullNumber)
{
	mKnownRobotsLock.lockForRead();

	const auto endpoints = hullNumber == -1 ? mKnownRobots.values() : mKnownRobots.values(hullNumber);
	mKnownRobotsLock.unlock();

	for (const auto &endpoint : endpoints) {
		// We prepare only by IP because there was a check by a hull number.
		const auto connection = prepareConnection(endpoint.ip);
		if (connection == nullptr) {
			QLOG_ERROR() << "Connection to" << endpoint.ip << ":" << endpoint.port << "is dead at the moment, message"
					<< "is not delivered. Will try to reestablish connection on next send.";
		} else {
			if (connection->isConnected()) {
				method(connection);
			} else {
				connect(connection, &Connection::connected, this, method);
			}
		}
	}
}
<commit_msg>Style fixup<commit_after>/* Copyright 2014 - 2015 CyberTech Labs Ltd.
 *
 * 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 "src/mailboxServer.h"

#include "src/mailboxConnection.h"

#include <QtNetwork/QNetworkInterface>
#include <QtCore/QSettings>

#include <trikKernel/paths.h>
#include <QHostInfo>
#include <QsLog.h>

using namespace trikNetwork;

MailboxServer::MailboxServer(quint16 port)
	: TrikServer([this] () { return connectionFactory(); })
	, mHullNumber(0)
	, mMyIp(determineMyIp())
	, mMyPort(port)
{
	setObjectName("MailboxServer");
	qRegisterMetaType<QHostAddress>("QHostAddress");
	loadSettings();
}

bool MailboxServer::isConnected()
{
	bool result = false;
	mKnownRobotsLock.lockForRead();
	for (auto &&endpoint : mKnownRobots) {
		const auto connection = this->connection(endpoint.ip, endpoint.port);
		auto mailboxConnection = qobject_cast<MailboxConnection *>(connection);
		if (mailboxConnection && mailboxConnection->isConnected()) {
			result = true;
			break;
		}
	}

	mKnownRobotsLock.unlock();
	return result;
}

int MailboxServer::hullNumber() const
{
	return mHullNumber;
}

QHostAddress MailboxServer::serverIp()
{
	mAuxiliaryInformationLock.lockForRead();
	const auto result = mServerIp;
	mAuxiliaryInformationLock.unlock();
	return result;
}

QHostAddress MailboxServer::myIp() const
{
	return mMyIp;
}

void MailboxServer::renewIp()
{
	mMyIp = determineMyIp();
}

void MailboxServer::start()
{
	startServer(mMyPort);

	if (!mServerIp.isNull() && mMyIp == mSavedIp) {
		connectTo(mServerIp, mServerPort);
	}
}

void MailboxServer::setHullNumber(int hullNumber)
{
	mHullNumber = hullNumber;
	saveSettings();
	forEveryConnection(
		[this](Connection *connection) {
			auto c = qobject_cast<MailboxConnection *>(connection);
			QMetaObject::invokeMethod(c, [c,this]() { c->sendConnectionInfo(mMyIp, mMyPort, mHullNumber); });
	}
	, -1);
}

void MailboxServer::connectTo(const QString &ip, int port)
{
	mAuxiliaryInformationLock.lockForRead();
	auto server = mServerIp;
	auto serverPort = mServerPort;
	mAuxiliaryInformationLock.unlock();

	if (server.toString() != ip || serverPort != port) {
		mAuxiliaryInformationLock.lockForWrite();
		mServerIp = QHostInfo::fromName(ip).addresses().first();
		mServerPort = port;
		mAuxiliaryInformationLock.unlock();

		saveSettings();
	}

	QReadLocker l(&mAuxiliaryInformationLock);
	connectTo(mServerIp, mServerPort);
}

void MailboxServer::connectTo(const QString &ip)
{
	connectTo(ip, mMyPort);
}

Connection *MailboxServer::connectTo(const QHostAddress &ip, int port)
{
	if (ip == mMyIp && port == mMyPort && isListening()) {
		// do not connect to self
		return nullptr;
	}

	if (auto connectionObject = connection(ip, port)) {
		return connectionObject;
	}

	const auto c = new MailboxConnection();
	connectConnection(c);
	connect(this, &MailboxServer::startedConnection, c, [=]() {
		c->connect(ip, port, mMyPort, mHullNumber);
	});
	startConnection(c);
	return c;
}

Connection *MailboxServer::connectionFactory()
{
	auto connection = new MailboxConnection();

	QObject::connect(connection, &MailboxConnection::newConnection, this, &MailboxServer::onNewConnection);

	connectConnection(connection);

	return connection;
}

void MailboxServer::connectConnection(Connection * connection)
{
	auto c = qobject_cast<MailboxConnection *>(connection);
	connect(c, &MailboxConnection::connectionInfo, this, &MailboxServer::onConnectionInfo);
	connect(c, &MailboxConnection::newData, this, &MailboxServer::onNewData);
}

QHostAddress MailboxServer::determineMyIp()
{
	QList<QNetworkInterface> ifs {
				// TRIK wlan0
				QNetworkInterface::interfaceFromName("wlan0")
				// Fallback to localhost
				, QNetworkInterface::interfaceFromName("lo")
				, QNetworkInterface::interfaceFromIndex(1)
	};
	for (auto &&interface : ifs) {
		if (interface.isValid()) {
			for (auto &&entry : interface.addressEntries()) {
				const QHostAddress ip = entry.ip();
				if (ip.protocol() == QAbstractSocket::IPv4Protocol) {
					return ip;
				}
			}
		}
	}

	return QHostAddress(); // Total fail
}

Connection *MailboxServer::prepareConnection(const QHostAddress &ip)
{
	// First, trying to reuse existing connection.
	const auto connectionObject = connection(ip);
	if (connectionObject != nullptr) {
		return connectionObject;
	}
	// Next, trying to create new connection to given IP. We need port, so checking if robot is known.
	Endpoint targetEndpoint;
	mKnownRobotsLock.lockForRead();
	for (auto &&endpoint : mKnownRobots) {
		if (endpoint.ip == ip) {
			targetEndpoint = endpoint;
			break;
		}
	}

	mKnownRobotsLock.unlock();

	if (targetEndpoint.ip.isNull()) {
		QLOG_ERROR() << "Trying to connect to unknown robot, IP:" << ip;
		return nullptr;
	}
	return connectTo(targetEndpoint.ip, targetEndpoint.port);
}

void MailboxServer::onNewConnection(const QHostAddress &ip, int clientPort, int serverPort, int hullNumber)
{
	if (ip == mMyIp && serverPort == mMyPort ) {
		/// Refuse to handle connections from ourselves.
		return;
	}

	mKnownRobotsLock.lockForRead();
	const auto knownRobot = mKnownRobots.contains(hullNumber, {ip, serverPort});
	const auto endpoints = mKnownRobots.values();
	mKnownRobotsLock.unlock();

	if (!knownRobot) {
		// Propagate information about newly connected robot through robot network.
		forEveryConnection([ip, serverPort, hullNumber](Connection *connection) {
			auto c = qobject_cast<MailboxConnection *>(connection);
			QMetaObject::invokeMethod(c, [=]() {c->sendConnectionInfo(ip, serverPort, hullNumber);});
		});
	}

	// Send known connection information to newly connected robot.
	const auto c = qobject_cast<MailboxConnection *>(connection(ip, clientPort));
	if (c != nullptr) {
		mKnownRobotsLock.lockForRead();
		for (const auto &endpoint : endpoints) {
			QMetaObject::invokeMethod(c, [this, c, endpoint]() {
				c->sendConnectionInfo(endpoint.ip, endpoint.port, mKnownRobots.key(endpoint));
			});
		}

		// Send information about myself.
		QMetaObject::invokeMethod(c, [this, c]() { c->sendSelfInfo(mHullNumber); });
		mKnownRobotsLock.unlock();
	} else {
		QLOG_ERROR() << "Something went wrong, new connection to" << ip << ":" << clientPort << "is dead";
		return;
	}

	if (!knownRobot) {
		mKnownRobotsLock.lockForWrite();

		mKnownRobots.insert(hullNumber, {ip, serverPort});
		mKnownRobotsLock.unlock();
	}
}

void MailboxServer::send(int hullNumber, const QString &message)
{
	const auto data = QString("data:%1").arg(message).toUtf8();
	forEveryConnection(
		[data](Connection *c) {
			QMetaObject::invokeMethod(c, [c, data]() { c->send(data); });
		}
	, hullNumber);
}

void MailboxServer::send(const QString &message)
{
	send(-1, message);
}

void MailboxServer::onConnectionInfo(const QHostAddress &ip, int port, int hullNumber)
{
	if (ip == mMyIp && port == mMyPort) {
		return;
	}

	QVector<Endpoint> toDelete;
	mKnownRobotsLock.lockForRead();
	for (auto &&endpoint : mKnownRobots) {
		if (endpoint == Endpoint{ip, port}) {
			toDelete << endpoint;
		}
	}

	mKnownRobotsLock.unlock();

	mKnownRobotsLock.lockForWrite();
	for (const auto &endpoint : toDelete) {
		const auto keys = mKnownRobots.keys(endpoint);
		for (const auto &key : keys) {
			mKnownRobots.remove(key, endpoint);
		}
	}

	mKnownRobots.insert(hullNumber, {ip, port});
	mKnownRobotsLock.unlock();
}

void MailboxServer::onNewData(const QHostAddress &ip, int port, const QByteArray &data)
{
	QLOG_INFO() << "New data received by a mailbox from " << ip << ":" << port << ", data is:" << data;
	int senderHullNumber = -1;
	mKnownRobotsLock.lockForRead();
	for (const auto &endpoint : mKnownRobots) {
		if (endpoint.ip == ip) {
			senderHullNumber = mKnownRobots.key(endpoint);
		}
	}

	mKnownRobotsLock.unlock();

	if (senderHullNumber == -1) {
		QLOG_INFO() << "Received message from" << ip << ":" << port << "which is unknown at the moment";
	}

	mMessagesQueueLock.lockForWrite();
	mMessagesQueue.enqueue(data);
	mMessagesQueueLock.unlock();

	emit newMessage(senderHullNumber, QString(data));
}

bool MailboxServer::hasMessages()
{
	mMessagesQueueLock.lockForRead();
	const bool result = !mMessagesQueue.isEmpty();
	mMessagesQueueLock.unlock();

	return result;
}

QString MailboxServer::receive()
{
	mMessagesQueueLock.lockForWrite();
	QByteArray const result = !mMessagesQueue.isEmpty() ? mMessagesQueue.dequeue() : QByteArray();
	mMessagesQueueLock.unlock();

	return result;
}

bool MailboxServer::hasServer() const
{
	return isListening();
}

void MailboxServer::loadSettings()
{
	QWriteLocker l(&mAuxiliaryInformationLock);
	QSettings settings(trikKernel::Paths::localSettings(), QSettings::IniFormat);
	mHullNumber = settings.value("hullNumber", 0).toInt();
	auto tryResolve = [](const QString &ipOrName) {
		auto info = QHostInfo::fromName(ipOrName);
		if (info.error() != QHostInfo::NoError || info.addresses().isEmpty()) {
			QLOG_ERROR() << "Failed to get ip for " << ipOrName << ":" << info.error();
			return QHostAddress();
		} else {
			return info.addresses().first();
		}
	};

	mServerIp = tryResolve(settings.value("server", mMyIp.toString()).toString());
	mServerPort = settings.value("serverPort", mMyPort).toInt();
	mSavedIp = tryResolve(settings.value("localIp", mMyIp.toString()).toString());
}

void MailboxServer::saveSettings()
{
	mAuxiliaryInformationLock.lockForRead();
	QSettings settings(trikKernel::Paths::localSettings(), QSettings::IniFormat);
	settings.setValue("hullNumber", mHullNumber);
	settings.setValue("server", mServerIp.toString());
	settings.setValue("serverPort", mServerPort);
	settings.setValue("localIp", mMyIp.toString());
	mAuxiliaryInformationLock.unlock();
}

void MailboxServer::forEveryConnection(const std::function<void(Connection *)> &method, int hullNumber)
{
	mKnownRobotsLock.lockForRead();

	const auto endpoints = hullNumber == -1 ? mKnownRobots.values() : mKnownRobots.values(hullNumber);
	mKnownRobotsLock.unlock();

	for (const auto &endpoint : endpoints) {
		// We prepare only by IP because there was a check by a hull number.
		const auto connection = prepareConnection(endpoint.ip);
		if (connection == nullptr) {
			QLOG_ERROR() << "Connection to" << endpoint.ip << ":" << endpoint.port << "is dead at the moment, message"
					<< "is not delivered. Will try to reestablish connection on next send.";
		} else {
			if (connection->isConnected()) {
				method(connection);
			} else {
				connect(connection, &Connection::connected, this, method);
			}
		}
	}
}
<|endoftext|>


<commit_before>/* $Header$ */
// Copyright ***********************************************************
//
// File ecmdMain.C
//
// IBM Confidential
// OCO Source Materials
// 9400 Licensed Internal Code
// (C) COPYRIGHT IBM CORP. 1996
//
// The source code for this program is not published or otherwise
// divested of its trade secrets, irrespective of what has been
// deposited with the U.S. Copyright Office.
//
// End Copyright *******************************************************
// Module Description **************************************************
//
// Description:
//
// End Module Description **********************************************
/**
 @file ecmdMain.C
 @brief Main Program entry point for ecmdDllClient Application
*/

//----------------------------------------------------------------------
//  Includes
//----------------------------------------------------------------------

#include <stdio.h>
#include <string>

#include <ecmdClientCapi.H>
#include <ecmdInterpreter.H>
#include <ecmdReturnCodes.H>
#include <ecmdCommandUtils.H>
#include <ecmdSharedUtils.H>

int main (int argc, char *argv[])
{
  uint32_t rc = 0;

  std::string cmdsave;
  char buf[200];
  for (int i = 0; i < argc; i++) {
    cmdsave += argv[i];
    cmdsave += " ";
  }

  cmdsave += "\n";

#ifndef ECMD_STATIC_FUNCTIONS
// If building the function 'statically', it doesn't need ECMD_DLL_FILE set; it'll automatically load its DLL
  if (getenv ("ECMD_DLL_FILE") == NULL) {
    printf("ecmd - You must set ECMD_DLL_FILE in order to run the eCMD command line client\n");
    rc = ECMD_INVALID_DLL_FILENAME;
  } else {
    /* Load the one specified by ECMD_DLL_FILE */
    rc = ecmdLoadDll("");
  }
#else
  rc = ecmdLoadDll("");
#endif

  if (rc == ECMD_SUCCESS) {
    /* Check to see if we are using stdin to pass in multiple commands */
    if (ecmdParseOption(&argc, &argv, "-stdin")) {

      /* Grab any other args that may be there */
      rc = ecmdCommandArgs(&argc, &argv);
      if (rc) exit((int)rc);

      /* There shouldn't be any more args when doing a -stdin */
      if (argc > 1) {
        ecmdOutputError("ecmd - Invalid args passed to ecmd in -stdin mode\n");
        rc = ECMD_INVALID_ARGS;

      } else {

        std::vector< std::string > commands;
        int   c_argc;
        char* c_argv[ECMD_ARG_LIMIT + 1];       ///< A limit of 20 tokens(args) per command
        char* buffer = NULL;
        size_t   bufflen = 0;
        size_t   commlen;

        /* ecmdParseStdInCommands reads from stdin and returns a vector of strings */
        /*  each string contains one command (ie 'ecmdquery version')              */
        /* When Ctrl-D or EOF is reached this function will fail to break out of loop */
        while ((rc = ecmdParseStdinCommands(commands)) != ECMD_SUCCESS) {

          rc = 0;

          /* Walk through individual commands from ecmdParseStdInCommands */
          for (std::vector< std::string >::iterator commit = commands.begin(); commit != commands.end(); commit ++) {

            c_argc = 0;
	    c_argv[0] = NULL;

            /* Check for a comment or empty line, if so delete it */
            if ((*commit)[0] == '#') continue;
            else if (commit->length() == 0) continue;

            /* Create a char buffer to hold the whole command, we will use this to create pointers to each token in the command (like argc,argv) */
            commlen = commit->length();
            if ( commlen > bufflen) {
              if (buffer != NULL) delete[] buffer;
              buffer = new char[commlen + 20];
              bufflen = commlen + 19;
            }

            // Beam "error" of possible NULL 'buffer' value requires mutually
            // exclusive conditions (need an argument present to enter
            // "commands" FOR loop but commit->length = 0 ie. no command).  So
            // tell beam to ignore NULL pointer message for 'buffer' parm via
            // comment on next line.
	    //lint -e(668) Ignore passing null, same as above for lint
            strcpy(buffer, commit->c_str()); /*passing null object*/

            /* Now start carving this thing up */
            bool lookingForStart = true; /* Are we looking for the start of a word ? */
            for (size_t c = 0; c < commlen; c++) {
              if (lookingForStart) {
                if (buffer[c] != ' ' && buffer[c] != '\t') {
                  c_argv[c_argc++] = &buffer[c];
                  lookingForStart = false;
                }
              } else {
                /* Looking for the end */
                if (buffer[c] == ' ' || buffer[c] == '\t') {
                  buffer[c] = '\0';
                  lookingForStart = true;
                }
              }
              if (c_argc > ECMD_ARG_LIMIT) {
		sprintf(buf,"ecmd - Found a command with greater then %d arguments, not supported\n",ECMD_ARG_LIMIT);
                ecmdOutputError(buf);
                rc = ECMD_INVALID_ARGS;
                break;
              }
            }

            // ignore a line if it is only space or tabs -
            // This prevents c_argv[o] being accessed below when still pointing to NULL
            if (c_argc == 0) continue;

            // Before Executing the cmd save it on the Dll side
            ecmdSetCurrentCmdline(c_argc, c_argv);

            /* We now want to call the command interpreter to handle what the user provided us */
            if (!rc) rc = ecmdCallInterpreters(c_argc, c_argv);

            if (rc == ECMD_INT_UNKNOWN_COMMAND) {
              if (strlen(c_argv[0]) < 200)
                sprintf(buf,"ecmd -  Unknown Command specified '%s'\n", c_argv[0]);
              else
                sprintf(buf,"ecmd -  Unknown Command specified \n");
              ecmdOutputError(buf);
            } else if (rc) {
              std::string parse = ecmdGetErrorMsg(rc, false);
              if (parse.length() > 0) {
                /* Display the registered message right away BZ#160 */
                ecmdOutput(parse.c_str());
              }
              parse = ecmdParseReturnCode(rc);
              if (strlen(c_argv[0]) + parse.length() < 300)
                sprintf(buf,"ecmd - '%s' returned with error code %X (%s)\n", c_argv[0], rc, parse.c_str());
              else
                sprintf(buf,"ecmd - Command returned with error code %X (%s)\n", rc, parse.c_str());
              ecmdOutputError(buf);
              break;
            }

            if (!ecmdGetGlobalVar(ECMD_GLOBALVAR_QUIETMODE)) {
              ecmdOutput((*commit + "\n").c_str());
            }

          } /* tokens loop */
          if (rc) break;

        }
        if (buffer != NULL) delete[] buffer;

      } /* invalid args if */

    } else {
      /* Standard command line command */

      // Before Executing the cmd save it on the Dll side
      ecmdSetCurrentCmdline(argc-1, argv+1);

      /* We now want to call the command interpreter to handle what the user provided us */
      rc = ecmdCallInterpreters(argc - 1, argv + 1);

      if (rc == ECMD_INT_UNKNOWN_COMMAND) {
        if (argv[1] == NULL)
          sprintf(buf,"ecmd - Must specify a command to execute. Run 'ecmd -h' for command list.\n");
        else if (strlen(argv[1]) < 200)
          sprintf(buf,"ecmd - Unknown Command specified '%s'\n", argv[1]);
        else
          sprintf(buf,"ecmd - Unknown Command specified \n");
        ecmdOutputError(buf);
      } else if (rc) {
        std::string parse = ecmdGetErrorMsg(rc, false);
        if (parse.length() > 0) {
          /* Display the registered message right away BZ#160 */
          ecmdOutput(parse.c_str());
        }
        parse = ecmdParseReturnCode(rc);
        if (strlen(argv[1]) + parse.length() < 300)
          sprintf(buf,"ecmd - '%s' returned with error code %X (%s)\n", argv[1], rc, parse.c_str());
        else
          sprintf(buf,"ecmd - Command returned with error code %X (%s)\n", rc, parse.c_str());
        ecmdOutputError(buf);
      }
    }

    /* Move these outputs into the if !rc to fix BZ#224 - cje */
    if (!ecmdGetGlobalVar(ECMD_GLOBALVAR_QUIETMODE)) {
      ecmdOutput(cmdsave.c_str());
    }

    ecmdUnloadDll();
  }

  exit((int)rc);
}

// Change Log *********************************************************
//
//  Flag Reason   Vers Date     Coder    Description
//  ---- -------- ---- -------- -------- ------------------------------
//                              CENGEL   Initial Creation
//  none STGC7449      04/18/05 prahl    Clean up Beam messages.
//
// End Change Log *****************************************************
<commit_msg>Created an eCMD shell<commit_after>/* $Header$ */
// Copyright ***********************************************************
//
// File ecmdMain.C
//
// IBM Confidential
// OCO Source Materials
// 9400 Licensed Internal Code
// (C) COPYRIGHT IBM CORP. 1996
//
// The source code for this program is not published or otherwise
// divested of its trade secrets, irrespective of what has been
// deposited with the U.S. Copyright Office.
//
// End Copyright *******************************************************
// Module Description **************************************************
//
// Description:
//
// End Module Description **********************************************
/**
 @file ecmdMain.C
 @brief Main Program entry point for ecmdDllClient Application
*/

//----------------------------------------------------------------------
//  Includes
//----------------------------------------------------------------------

#include <stdio.h>
#include <string>

#include <ecmdClientCapi.H>
#include <ecmdInterpreter.H>
#include <ecmdReturnCodes.H>
#include <ecmdCommandUtils.H>
#include <ecmdSharedUtils.H>

int main (int argc, char *argv[])
{
  uint32_t rc = 0;

  std::string cmdsave;
  char errorbuf[200];
  for (int i = 0; i < argc; i++) {
    cmdsave += argv[i];
    cmdsave += " ";
  }
  cmdsave += "\n";

  rc = ecmdLoadDll("");

  if (rc == ECMD_SUCCESS) {
    /* Check to see if we are using stdin to pass in multiple commands */
    bool shellMode = ecmdParseOption(&argc, &argv, "-shell");
    bool stdinMode = ecmdParseOption(&argc, &argv, "-stdin");
    if (stdinMode || shellMode) {

      /* Grab any other args that may be there */
      rc = ecmdCommandArgs(&argc, &argv);
      if (rc) exit((int)rc);

      /* There shouldn't be any more args when doing a -stdin/-shell */
      if (argc > 1) {
        ecmdOutputError("ecmd - Invalid args passed to ecmd in -stdin/-shell mode\n");
        exit(ECMD_INVALID_ARGS);
      }

      /* Let's get things going */
      std::vector<std::string> commands;
      int   c_argc;
      char* c_argv[ECMD_ARG_LIMIT + 1];       ///< A limit of 20 tokens(args) per command
      char* buffer = NULL;
      size_t   bufflen = 0;
      size_t   commlen;
      bool shellAlive = true;

      if (shellMode) {
        ecmdOutput("ecmd> "); fflush(0);
      }

      /* ecmdParseStdInCommands reads from stdin and returns a vector of strings */
      /*  each string contains one command (ie 'ecmdquery version')              */
      /* When Ctrl-D or EOF is reached this function will fail to break out of loop */
      while (shellAlive && (rc = ecmdParseStdinCommands(commands))) {

        rc = 0;

        /* Walk through individual commands from ecmdParseStdInCommands */
        for (std::vector< std::string >::iterator commandIter = commands.begin(); commandIter != commands.end(); commandIter++) {

          c_argc = 0;
          c_argv[0] = NULL;

          /* Check for a comment or empty line, if so delete it */
          if ((*commandIter)[0] == '#') {
            continue;
          } else if (commandIter->length() == 0) {
            continue;
          }
          if (shellMode) {
            if ((*commandIter) == "quit" || (*commandIter) == "exit") {
              ecmdOutput("Leaving ecmd shell at users request... \n");
              shellAlive = false;
              break;
            }
          }

          /* Create a char buffer to hold the whole command, we will use this to create pointers to each token in the command (like argc,argv) */
          commlen = commandIter->length();
          if ( commlen > bufflen) {
            if (buffer != NULL) delete[] buffer;
            buffer = new char[commlen + 20];
            bufflen = commlen + 19;
          }

          // Beam "error" of possible NULL 'buffer' value requires mutually
          // exclusive conditions (need an argument present to enter
          // "commands" FOR loop but commandIter->length = 0 ie. no command).  So
          // tell beam to ignore NULL pointer message for 'buffer' parm via
          // comment on next line.
          //lint -e(668) Ignore passing null, same as above for lint
          strcpy(buffer, commandIter->c_str()); /*passing null object*/

          /* Now start carving this thing up */
          bool lookingForStart = true; /* Are we looking for the start of a word ? */
          for (size_t c = 0; c < commlen; c++) {
            if (lookingForStart) {
              if (buffer[c] != ' ' && buffer[c] != '\t') {
                c_argv[c_argc++] = &buffer[c];
                lookingForStart = false;
              }
            } else {
              /* Looking for the end */
              if (buffer[c] == ' ' || buffer[c] == '\t') {
                buffer[c] = '\0';
                lookingForStart = true;
              }
            }
            if (c_argc > ECMD_ARG_LIMIT) {
              sprintf(errorbuf,"ecmd - Found a command with greater then %d arguments, not supported\n",ECMD_ARG_LIMIT);
              ecmdOutputError(errorbuf);
              rc = ECMD_INVALID_ARGS;
              break;
            }
          }

          // ignore a line if it is only space or tabs -
          // This prevents c_argv[o] being accessed below when still pointing to NULL
          if (c_argc == 0) continue;

          // Before Executing the cmd save it on the Dll side
          ecmdSetCurrentCmdline(c_argc, c_argv);

          /* We now want to call the command interpreter to handle what the user provided us */
          if (!rc) rc = ecmdCallInterpreters(c_argc, c_argv);

          if (rc == ECMD_INT_UNKNOWN_COMMAND) {
            if (strlen(c_argv[0]) < 200)
              sprintf(errorbuf,"ecmd -  Unknown Command specified '%s'\n", c_argv[0]);
            else
              sprintf(errorbuf,"ecmd -  Unknown Command specified \n");
            ecmdOutputError(errorbuf);
          } else if (rc) {
            std::string parse = ecmdGetErrorMsg(rc, false);
            if (parse.length() > 0) {
              /* Display the registered message right away BZ#160 */
              ecmdOutput(parse.c_str());
            }
            parse = ecmdParseReturnCode(rc);
            if (strlen(c_argv[0]) + parse.length() < 300)
              sprintf(errorbuf,"ecmd - '%s' returned with error code %X (%s)\n", c_argv[0], rc, parse.c_str());
            else
              sprintf(errorbuf,"ecmd - Command returned with error code %X (%s)\n", rc, parse.c_str());
            ecmdOutputError(errorbuf);
            break;
          }

          if (!ecmdGetGlobalVar(ECMD_GLOBALVAR_QUIETMODE)) {
            ecmdOutput((*commandIter + "\n").c_str());
          }
        } /* tokens loop */
        if (rc) break;

        /* Print the prompt again */
        if (shellMode && shellAlive) {
          ecmdOutput("ecmd> "); fflush(0);
        }
      }
      if (buffer != NULL) delete[] buffer;

    } else {
      /* Standard command line command */

      // Before Executing the cmd save it on the Dll side
      ecmdSetCurrentCmdline(argc-1, argv+1);

      /* We now want to call the command interpreter to handle what the user provided us */
      rc = ecmdCallInterpreters(argc - 1, argv + 1);

      if (rc == ECMD_INT_UNKNOWN_COMMAND) {
        if (argv[1] == NULL)
          sprintf(errorbuf,"ecmd - Must specify a command to execute. Run 'ecmd -h' for command list.\n");
        else if (strlen(argv[1]) < 200)
          sprintf(errorbuf,"ecmd - Unknown Command specified '%s'\n", argv[1]);
        else
          sprintf(errorbuf,"ecmd - Unknown Command specified \n");
        ecmdOutputError(errorbuf);
      } else if (rc) {
        std::string parse = ecmdGetErrorMsg(rc, false);
        if (parse.length() > 0) {
          /* Display the registered message right away BZ#160 */
          ecmdOutput(parse.c_str());
        }
        parse = ecmdParseReturnCode(rc);
        if (strlen(argv[1]) + parse.length() < 300)
          sprintf(errorbuf,"ecmd - '%s' returned with error code %X (%s)\n", argv[1], rc, parse.c_str());
        else
          sprintf(errorbuf,"ecmd - Command returned with error code %X (%s)\n", rc, parse.c_str());
        ecmdOutputError(errorbuf);
      }
    }

    /* Move these outputs into the if !rc to fix BZ#224 - cje */
    if (!ecmdGetGlobalVar(ECMD_GLOBALVAR_QUIETMODE)) {
      ecmdOutput(cmdsave.c_str());
    }

    ecmdUnloadDll();
  }

  exit((int)rc);
}

// Change Log *********************************************************
//
//  Flag Reason   Vers Date     Coder    Description
//  ---- -------- ---- -------- -------- ------------------------------
//                              CENGEL   Initial Creation
//  none STGC7449      04/18/05 prahl    Clean up Beam messages.
//
// End Change Log *****************************************************
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include "oglwindow.hxx"
#include <cppuhelper/supportsservice.hxx>

using namespace com::sun::star;

namespace avmedia { namespace ogl {

OGLWindow::OGLWindow( glTFHandle& rHandle, OpenGLContext& rContext, Window& rEventHandlerParent )
    : m_rHandle( rHandle )
    , m_rContext( rContext )
    , m_rEventHandler( rEventHandlerParent )
    , m_bVisible ( false )
    , m_aLastMousePos(Point())
    , m_bIsOrbitMode( false )
    , m_fCameraDistance(0.0)
{
}

OGLWindow::~OGLWindow()
{
    dispose();
}

void SAL_CALL OGLWindow::update() throw (css::uno::RuntimeException, std::exception)
{
    m_rContext.makeCurrent();
    gltf_prepare_renderer(&m_rHandle);
    gltf_renderer(&m_rHandle);
    gltf_complete_renderer(&m_rHandle);
    m_rContext.swapBuffers();
}

sal_Bool SAL_CALL OGLWindow::setZoomLevel( css::media::ZoomLevel /*eZoomLevel*/ ) throw (css::uno::RuntimeException, std::exception)
{
    return false;
}

css::media::ZoomLevel SAL_CALL OGLWindow::getZoomLevel() throw (css::uno::RuntimeException, std::exception)
{
    return media::ZoomLevel_ORIGINAL;
}

void SAL_CALL OGLWindow::setPointerType( sal_Int32 ) throw (css::uno::RuntimeException, std::exception)
{
}

OUString SAL_CALL OGLWindow::getImplementationName() throw (css::uno::RuntimeException, std::exception)
{
    return OUString("com.sun.star.comp.avmedia.Window_OpenGL");
}

sal_Bool SAL_CALL OGLWindow::supportsService( const OUString& rServiceName ) throw (css::uno::RuntimeException, std::exception)
{
    return cppu::supportsService(this, rServiceName);
}

uno::Sequence< OUString > SAL_CALL OGLWindow::getSupportedServiceNames() throw (css::uno::RuntimeException, std::exception)
{
    uno::Sequence< OUString > aRet(1);
    aRet[0] = OUString("com.sun.star.media.Window_OpenGL");
    return aRet;
}

void SAL_CALL OGLWindow::dispose() throw (uno::RuntimeException, std::exception)
{
    assert(m_rEventHandler.GetParent());
    m_rEventHandler.GetParent()->RemoveEventListener( LINK(this, OGLWindow, FocusGrabber));
    m_rEventHandler.RemoveEventListener( LINK(this, OGLWindow, CameraHandler));
}

void SAL_CALL OGLWindow::addEventListener( const uno::Reference< lang::XEventListener >& )
    throw (uno::RuntimeException, std::exception)
{
}

void SAL_CALL OGLWindow::removeEventListener( const uno::Reference< lang::XEventListener >& )
    throw (uno::RuntimeException, std::exception)
{
}

void SAL_CALL OGLWindow::setPosSize( sal_Int32 nX, sal_Int32 nY, sal_Int32 nWidth, sal_Int32 nHeight, sal_Int16 /*nFlags*/ )
    throw (uno::RuntimeException, std::exception)
{
    if( m_rHandle.viewport.x != nX || m_rHandle.viewport.x != nY ||
        m_rHandle.viewport.width != nWidth || m_rHandle.viewport.height != nHeight )
    {
        m_rContext.setWinSize(Size(nWidth,nHeight));
        m_rHandle.viewport.x = nX;
        m_rHandle.viewport.y = nY;
        m_rHandle.viewport.width = nWidth;
        m_rHandle.viewport.height = nHeight;
    }
}

awt::Rectangle SAL_CALL OGLWindow::getPosSize()
    throw (uno::RuntimeException, std::exception)
{
    return awt::Rectangle(m_rHandle.viewport.x, m_rHandle.viewport.y,
                          m_rHandle.viewport.width, m_rHandle.viewport.height);
}

void SAL_CALL OGLWindow::setVisible( sal_Bool bSet )
    throw (uno::RuntimeException, std::exception)
{
    assert(m_rEventHandler.GetParent());
    if( bSet && !m_bVisible )
    {
        m_rEventHandler.GetParent()->AddEventListener( LINK(this, OGLWindow, FocusGrabber));
        m_rEventHandler.AddEventListener( LINK(this, OGLWindow, CameraHandler));
        m_rEventHandler.GrabFocus();
    }
    else if( !bSet )
    {
        m_rEventHandler.GetParent()->RemoveEventListener( LINK(this, OGLWindow, FocusGrabber));
        m_rEventHandler.RemoveEventListener( LINK(this, OGLWindow, CameraHandler));
    }
    m_bVisible = bSet;
}

void SAL_CALL OGLWindow::setEnable( sal_Bool )
    throw (uno::RuntimeException, std::exception)
{
}

void SAL_CALL OGLWindow::setFocus()
    throw (uno::RuntimeException, std::exception)
{
}

void SAL_CALL OGLWindow::addWindowListener( const uno::Reference< awt::XWindowListener >& )
    throw (uno::RuntimeException, std::exception)
{
}

void SAL_CALL OGLWindow::removeWindowListener( const uno::Reference< awt::XWindowListener >& )
    throw (uno::RuntimeException, std::exception)
{
}

void SAL_CALL OGLWindow::addFocusListener( const uno::Reference< awt::XFocusListener >& )
    throw (uno::RuntimeException, std::exception)
{
}

void SAL_CALL OGLWindow::removeFocusListener( const uno::Reference< awt::XFocusListener >& )
    throw (uno::RuntimeException, std::exception)
{
}

void SAL_CALL OGLWindow::addKeyListener( const uno::Reference< awt::XKeyListener >& )
    throw (uno::RuntimeException, std::exception)
{
}

void SAL_CALL OGLWindow::removeKeyListener( const uno::Reference< awt::XKeyListener >& )
    throw (uno::RuntimeException, std::exception)
{
}

void SAL_CALL OGLWindow::addMouseListener( const uno::Reference< awt::XMouseListener >& )
    throw (uno::RuntimeException, std::exception)
{
}

void SAL_CALL OGLWindow::removeMouseListener( const uno::Reference< awt::XMouseListener >& )
    throw (uno::RuntimeException, std::exception)
{
}

void SAL_CALL OGLWindow::addMouseMotionListener( const uno::Reference< awt::XMouseMotionListener >& )
    throw (uno::RuntimeException, std::exception)
{
}

void SAL_CALL OGLWindow::removeMouseMotionListener( const uno::Reference< awt::XMouseMotionListener >& )
    throw (uno::RuntimeException, std::exception)
{
}

void SAL_CALL OGLWindow::addPaintListener( const uno::Reference< awt::XPaintListener >& )
    throw (uno::RuntimeException, std::exception)
{
}

void SAL_CALL OGLWindow::removePaintListener( const uno::Reference< awt::XPaintListener >& )
    throw (uno::RuntimeException, std::exception)
{
}

IMPL_LINK(OGLWindow, FocusGrabber, VclWindowEvent*, pEvent)
{
    if( pEvent->GetId() == VCLEVENT_WINDOW_MOUSEMOVE )
    {
        MouseEvent* pMouseEvt = (MouseEvent*)pEvent->GetData();
        if(pMouseEvt)
        {
            const Point& rMousePos = pMouseEvt->GetPosPixel();
            const Rectangle aWinRect(m_rEventHandler.GetPosPixel(),m_rEventHandler.GetSizePixel());
            // Grab focus to the OpenGL window when mouse pointer is over it
            if( aWinRect.IsInside(rMousePos) )
            {
                if ( !m_rEventHandler.HasFocus() )
                {
                    m_rEventHandler.GrabFocus();
                }
            }
            // Move focus to the document when mouse is not over the OpenGL window
            else if ( m_rEventHandler.HasFocus() )
            {
                m_rEventHandler.GrabFocusToDocument();
            }
        }
    }

    return 0;
}

IMPL_LINK(OGLWindow, CameraHandler, VclWindowEvent*, pEvent)
{
    if( pEvent->GetId() == VCLEVENT_WINDOW_KEYINPUT )
    {
        KeyEvent* pKeyEvt = (KeyEvent*)pEvent->GetData();
        if(pKeyEvt)
        {
            const sal_uInt16 nCode = pKeyEvt->GetKeyCode().GetCode();
            if (nCode == KEY_Q || nCode == KEY_E ||
                nCode == KEY_A || nCode == KEY_D ||
                nCode == KEY_W || nCode == KEY_S )
            {
                // Calculate movement
                glm::vec3 vMoveBy;
                {
                    glm::vec3 vEye;
                    glm::vec3 vView;
                    glm::vec3 vUp;
                    gltf_get_camera_pos(&m_rHandle, &vEye,&vView,&vUp);
                    float fModelSize =(float)gltf_get_model_size(&m_rHandle);

                    glm::vec3 vMove = vView-vEye;
                    vMove = glm::normalize(vMove);
                    vMove *= 25.0f;
                    glm::vec3 vStrafe = glm::cross(vView-vEye, vUp);
                    vStrafe = glm::normalize(vStrafe);
                    vStrafe *= 25.0f;
                    glm::vec3 vMup = glm::cross(vView-vEye,glm::vec3(1.0f,0.0f,0.0f) );
                    vMup = glm::normalize(vMup);
                    vMup *= 25.0f;

                    if(nCode == KEY_W)vMoveBy += vMove*(0.0005f*fModelSize);
                    if(nCode == KEY_S)vMoveBy -= vMove*(0.0005f*fModelSize);
                    if( !m_bIsOrbitMode )
                    {
                        if(nCode == KEY_A)vMoveBy -= vStrafe*(0.0005f*fModelSize);
                        if(nCode == KEY_D)vMoveBy += vStrafe*(0.0005f*fModelSize);
                    }
                    else
                    {
                        // Limit zooming in orbit mode
                        m_fCameraDistance += vMoveBy.z;
                        if ((m_fCameraDistance < 0.75 * fModelSize && vMoveBy.z < 0.0 ) ||
                            (m_fCameraDistance > 2 * fModelSize && vMoveBy.z > 0.0 ))
                        {
                            m_fCameraDistance -= vMoveBy.z;
                            vMoveBy = glm::vec3(0.0);
                        }
                    }
                }
                gltf_renderer_move_camera(&m_rHandle, vMoveBy.x, vMoveBy.y, vMoveBy.z, 0.0);
            }
            else if(nCode == KEY_M)
            {
                if(m_bIsOrbitMode)
                {
                    gltf_orbit_view_stop(&m_rHandle);
                    m_bIsOrbitMode = false;
                }
                else
                {
                    gltf_orbit_mode_start(&m_rHandle);
                    m_bIsOrbitMode = true;
                    // Set default camera distance
                    glm::vec3 vEye;
                    glm::vec3 vView;
                    glm::vec3 vUp;
                    gltf_get_camera_pos(&m_rHandle, &vEye,&vView,&vUp);
                    m_fCameraDistance = vEye.z - gltf_get_model_center_pos(&m_rHandle)->z;
                }
            }
            else if(nCode == KEY_F)
            {
                gltf_render_FPS_enable(&m_rHandle);
            }
        }
    }
    else if( pEvent->GetId() == VCLEVENT_WINDOW_MOUSEBUTTONDOWN )
    {
        MouseEvent* pMouseEvt = (MouseEvent*)pEvent->GetData();
        if(pMouseEvt && pMouseEvt->IsLeft() && pMouseEvt->GetClicks() == 1)
        {
            m_aLastMousePos = pMouseEvt->GetPosPixel();
        }
    }
    else if( pEvent->GetId() == VCLEVENT_WINDOW_MOUSEMOVE )
    {
        if ( !m_rEventHandler.HasFocus() )
        {
            m_rEventHandler.GrabFocus();
        }
        MouseEvent* pMouseEvt = (MouseEvent*)pEvent->GetData();
        if(pMouseEvt && pMouseEvt->IsLeft())
        {
            const Point& aCurPos = pMouseEvt->GetPosPixel();
            float fSensitivity = std::min(m_rHandle.viewport.width, m_rHandle.viewport.height);
            if (fSensitivity == 0.0)
                fSensitivity = 1.0;
            else
                fSensitivity = 540.0 / fSensitivity;

            long nDeltaX = m_aLastMousePos.X()-aCurPos.X();
            long nDeltaY = m_aLastMousePos.Y()-aCurPos.Y();
            if( m_bIsOrbitMode )
            {
                fSensitivity *= 5;
                gltf_renderer_rotate_model(&m_rHandle, (float)nDeltaX*fSensitivity, (float)nDeltaY*fSensitivity, 0.0);
            }
            else
            {
                // Filter out too small deltas to avoid rewrite rotation parameter with 0
                // before rotation is done
                if( nDeltaX != 0 || nDeltaY != 0 )
                    gltf_renderer_rotate_camera(&m_rHandle, (float)nDeltaX*fSensitivity, (float)nDeltaY*fSensitivity, 0.0);
            }
            m_aLastMousePos = aCurPos;
        }
    }
    else if( pEvent->GetId() == VCLEVENT_WINDOW_MOUSEBUTTONUP )
    {
        MouseEvent* pMouseEvt = (MouseEvent*)pEvent->GetData();
        if(pMouseEvt && pMouseEvt->IsLeft() && pMouseEvt->GetClicks() == 1)
        {
            gltf_renderer_stop_rotate_model(&m_rHandle);
        }
    }
    return 0;
}

} // namespace ogl
} // namespace avmedia

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>glTF: camera movement constraint: use distance from the boundary box<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include "oglwindow.hxx"
#include <cppuhelper/supportsservice.hxx>

using namespace com::sun::star;

namespace avmedia { namespace ogl {

OGLWindow::OGLWindow( glTFHandle& rHandle, OpenGLContext& rContext, Window& rEventHandlerParent )
    : m_rHandle( rHandle )
    , m_rContext( rContext )
    , m_rEventHandler( rEventHandlerParent )
    , m_bVisible ( false )
    , m_aLastMousePos(Point())
    , m_bIsOrbitMode( false )
    , m_fCameraDistance(0.0)
{
}

OGLWindow::~OGLWindow()
{
    dispose();
}

void SAL_CALL OGLWindow::update() throw (css::uno::RuntimeException, std::exception)
{
    m_rContext.makeCurrent();
    gltf_prepare_renderer(&m_rHandle);
    gltf_renderer(&m_rHandle);
    gltf_complete_renderer(&m_rHandle);
    m_rContext.swapBuffers();
}

sal_Bool SAL_CALL OGLWindow::setZoomLevel( css::media::ZoomLevel /*eZoomLevel*/ ) throw (css::uno::RuntimeException, std::exception)
{
    return false;
}

css::media::ZoomLevel SAL_CALL OGLWindow::getZoomLevel() throw (css::uno::RuntimeException, std::exception)
{
    return media::ZoomLevel_ORIGINAL;
}

void SAL_CALL OGLWindow::setPointerType( sal_Int32 ) throw (css::uno::RuntimeException, std::exception)
{
}

OUString SAL_CALL OGLWindow::getImplementationName() throw (css::uno::RuntimeException, std::exception)
{
    return OUString("com.sun.star.comp.avmedia.Window_OpenGL");
}

sal_Bool SAL_CALL OGLWindow::supportsService( const OUString& rServiceName ) throw (css::uno::RuntimeException, std::exception)
{
    return cppu::supportsService(this, rServiceName);
}

uno::Sequence< OUString > SAL_CALL OGLWindow::getSupportedServiceNames() throw (css::uno::RuntimeException, std::exception)
{
    uno::Sequence< OUString > aRet(1);
    aRet[0] = OUString("com.sun.star.media.Window_OpenGL");
    return aRet;
}

void SAL_CALL OGLWindow::dispose() throw (uno::RuntimeException, std::exception)
{
    assert(m_rEventHandler.GetParent());
    m_rEventHandler.GetParent()->RemoveEventListener( LINK(this, OGLWindow, FocusGrabber));
    m_rEventHandler.RemoveEventListener( LINK(this, OGLWindow, CameraHandler));
}

void SAL_CALL OGLWindow::addEventListener( const uno::Reference< lang::XEventListener >& )
    throw (uno::RuntimeException, std::exception)
{
}

void SAL_CALL OGLWindow::removeEventListener( const uno::Reference< lang::XEventListener >& )
    throw (uno::RuntimeException, std::exception)
{
}

void SAL_CALL OGLWindow::setPosSize( sal_Int32 nX, sal_Int32 nY, sal_Int32 nWidth, sal_Int32 nHeight, sal_Int16 /*nFlags*/ )
    throw (uno::RuntimeException, std::exception)
{
    if( m_rHandle.viewport.x != nX || m_rHandle.viewport.x != nY ||
        m_rHandle.viewport.width != nWidth || m_rHandle.viewport.height != nHeight )
    {
        m_rContext.setWinSize(Size(nWidth,nHeight));
        m_rHandle.viewport.x = nX;
        m_rHandle.viewport.y = nY;
        m_rHandle.viewport.width = nWidth;
        m_rHandle.viewport.height = nHeight;
    }
}

awt::Rectangle SAL_CALL OGLWindow::getPosSize()
    throw (uno::RuntimeException, std::exception)
{
    return awt::Rectangle(m_rHandle.viewport.x, m_rHandle.viewport.y,
                          m_rHandle.viewport.width, m_rHandle.viewport.height);
}

void SAL_CALL OGLWindow::setVisible( sal_Bool bSet )
    throw (uno::RuntimeException, std::exception)
{
    assert(m_rEventHandler.GetParent());
    if( bSet && !m_bVisible )
    {
        m_rEventHandler.GetParent()->AddEventListener( LINK(this, OGLWindow, FocusGrabber));
        m_rEventHandler.AddEventListener( LINK(this, OGLWindow, CameraHandler));
        m_rEventHandler.GrabFocus();
    }
    else if( !bSet )
    {
        m_rEventHandler.GetParent()->RemoveEventListener( LINK(this, OGLWindow, FocusGrabber));
        m_rEventHandler.RemoveEventListener( LINK(this, OGLWindow, CameraHandler));
    }
    m_bVisible = bSet;
}

void SAL_CALL OGLWindow::setEnable( sal_Bool )
    throw (uno::RuntimeException, std::exception)
{
}

void SAL_CALL OGLWindow::setFocus()
    throw (uno::RuntimeException, std::exception)
{
}

void SAL_CALL OGLWindow::addWindowListener( const uno::Reference< awt::XWindowListener >& )
    throw (uno::RuntimeException, std::exception)
{
}

void SAL_CALL OGLWindow::removeWindowListener( const uno::Reference< awt::XWindowListener >& )
    throw (uno::RuntimeException, std::exception)
{
}

void SAL_CALL OGLWindow::addFocusListener( const uno::Reference< awt::XFocusListener >& )
    throw (uno::RuntimeException, std::exception)
{
}

void SAL_CALL OGLWindow::removeFocusListener( const uno::Reference< awt::XFocusListener >& )
    throw (uno::RuntimeException, std::exception)
{
}

void SAL_CALL OGLWindow::addKeyListener( const uno::Reference< awt::XKeyListener >& )
    throw (uno::RuntimeException, std::exception)
{
}

void SAL_CALL OGLWindow::removeKeyListener( const uno::Reference< awt::XKeyListener >& )
    throw (uno::RuntimeException, std::exception)
{
}

void SAL_CALL OGLWindow::addMouseListener( const uno::Reference< awt::XMouseListener >& )
    throw (uno::RuntimeException, std::exception)
{
}

void SAL_CALL OGLWindow::removeMouseListener( const uno::Reference< awt::XMouseListener >& )
    throw (uno::RuntimeException, std::exception)
{
}

void SAL_CALL OGLWindow::addMouseMotionListener( const uno::Reference< awt::XMouseMotionListener >& )
    throw (uno::RuntimeException, std::exception)
{
}

void SAL_CALL OGLWindow::removeMouseMotionListener( const uno::Reference< awt::XMouseMotionListener >& )
    throw (uno::RuntimeException, std::exception)
{
}

void SAL_CALL OGLWindow::addPaintListener( const uno::Reference< awt::XPaintListener >& )
    throw (uno::RuntimeException, std::exception)
{
}

void SAL_CALL OGLWindow::removePaintListener( const uno::Reference< awt::XPaintListener >& )
    throw (uno::RuntimeException, std::exception)
{
}

IMPL_LINK(OGLWindow, FocusGrabber, VclWindowEvent*, pEvent)
{
    if( pEvent->GetId() == VCLEVENT_WINDOW_MOUSEMOVE )
    {
        MouseEvent* pMouseEvt = (MouseEvent*)pEvent->GetData();
        if(pMouseEvt)
        {
            const Point& rMousePos = pMouseEvt->GetPosPixel();
            const Rectangle aWinRect(m_rEventHandler.GetPosPixel(),m_rEventHandler.GetSizePixel());
            // Grab focus to the OpenGL window when mouse pointer is over it
            if( aWinRect.IsInside(rMousePos) )
            {
                if ( !m_rEventHandler.HasFocus() )
                {
                    m_rEventHandler.GrabFocus();
                }
            }
            // Move focus to the document when mouse is not over the OpenGL window
            else if ( m_rEventHandler.HasFocus() )
            {
                m_rEventHandler.GrabFocusToDocument();
            }
        }
    }

    return 0;
}

IMPL_LINK(OGLWindow, CameraHandler, VclWindowEvent*, pEvent)
{
    if( pEvent->GetId() == VCLEVENT_WINDOW_KEYINPUT )
    {
        KeyEvent* pKeyEvt = (KeyEvent*)pEvent->GetData();
        if(pKeyEvt)
        {
            const sal_uInt16 nCode = pKeyEvt->GetKeyCode().GetCode();
            if (nCode == KEY_Q || nCode == KEY_E ||
                nCode == KEY_A || nCode == KEY_D ||
                nCode == KEY_W || nCode == KEY_S )
            {
                // Calculate movement
                glm::vec3 vMoveBy;
                {
                    glm::vec3 vEye;
                    glm::vec3 vView;
                    glm::vec3 vUp;
                    gltf_get_camera_pos(&m_rHandle, &vEye,&vView,&vUp);
                    float fModelSize =(float)gltf_get_model_size(&m_rHandle);

                    glm::vec3 vMove = vView-vEye;
                    vMove = glm::normalize(vMove);
                    vMove *= 25.0f;
                    glm::vec3 vStrafe = glm::cross(vView-vEye, vUp);
                    vStrafe = glm::normalize(vStrafe);
                    vStrafe *= 25.0f;
                    glm::vec3 vMup = glm::cross(vView-vEye,glm::vec3(1.0f,0.0f,0.0f) );
                    vMup = glm::normalize(vMup);
                    vMup *= 25.0f;

                    if(nCode == KEY_W)vMoveBy += vMove*(0.0005f*fModelSize);
                    if(nCode == KEY_S)vMoveBy -= vMove*(0.0005f*fModelSize);
                    if( !m_bIsOrbitMode )
                    {
                        if(nCode == KEY_A)vMoveBy -= vStrafe*(0.0005f*fModelSize);
                        if(nCode == KEY_D)vMoveBy += vStrafe*(0.0005f*fModelSize);
                    }
                    else
                    {
                        // Limit zooming in orbit mode
                        m_fCameraDistance += vMoveBy.z;
                        if ((m_fCameraDistance < 0.5 * fModelSize && vMoveBy.z < 0.0 ) ||
                            (m_fCameraDistance > 2 * fModelSize && vMoveBy.z > 0.0 ))
                        {
                            m_fCameraDistance -= vMoveBy.z;
                            vMoveBy = glm::vec3(0.0);
                        }
                    }
                }
                gltf_renderer_move_camera(&m_rHandle, vMoveBy.x, vMoveBy.y, vMoveBy.z, 0.0);
            }
            else if(nCode == KEY_M)
            {
                if(m_bIsOrbitMode)
                {
                    gltf_orbit_view_stop(&m_rHandle);
                    m_bIsOrbitMode = false;
                }
                else
                {
                    gltf_orbit_mode_start(&m_rHandle);
                    m_bIsOrbitMode = true;
                    // Set default camera distance
                    glm::vec3 vEye;
                    glm::vec3 vView;
                    glm::vec3 vUp;
                    gltf_get_camera_pos(&m_rHandle, &vEye,&vView,&vUp);
                    m_fCameraDistance = vEye.z - gltf_get_model_center_pos(&m_rHandle)->z - (gltf_get_model_size(&m_rHandle)/2.0);
                }
            }
            else if(nCode == KEY_F)
            {
                gltf_render_FPS_enable(&m_rHandle);
            }
        }
    }
    else if( pEvent->GetId() == VCLEVENT_WINDOW_MOUSEBUTTONDOWN )
    {
        MouseEvent* pMouseEvt = (MouseEvent*)pEvent->GetData();
        if(pMouseEvt && pMouseEvt->IsLeft() && pMouseEvt->GetClicks() == 1)
        {
            m_aLastMousePos = pMouseEvt->GetPosPixel();
        }
    }
    else if( pEvent->GetId() == VCLEVENT_WINDOW_MOUSEMOVE )
    {
        if ( !m_rEventHandler.HasFocus() )
        {
            m_rEventHandler.GrabFocus();
        }
        MouseEvent* pMouseEvt = (MouseEvent*)pEvent->GetData();
        if(pMouseEvt && pMouseEvt->IsLeft())
        {
            const Point& aCurPos = pMouseEvt->GetPosPixel();
            float fSensitivity = std::min(m_rHandle.viewport.width, m_rHandle.viewport.height);
            if (fSensitivity == 0.0)
                fSensitivity = 1.0;
            else
                fSensitivity = 540.0 / fSensitivity;

            long nDeltaX = m_aLastMousePos.X()-aCurPos.X();
            long nDeltaY = m_aLastMousePos.Y()-aCurPos.Y();
            if( m_bIsOrbitMode )
            {
                fSensitivity *= 5;
                gltf_renderer_rotate_model(&m_rHandle, (float)nDeltaX*fSensitivity, (float)nDeltaY*fSensitivity, 0.0);
            }
            else
            {
                // Filter out too small deltas to avoid rewrite rotation parameter with 0
                // before rotation is done
                if( nDeltaX != 0 || nDeltaY != 0 )
                    gltf_renderer_rotate_camera(&m_rHandle, (float)nDeltaX*fSensitivity, (float)nDeltaY*fSensitivity, 0.0);
            }
            m_aLastMousePos = aCurPos;
        }
    }
    else if( pEvent->GetId() == VCLEVENT_WINDOW_MOUSEBUTTONUP )
    {
        MouseEvent* pMouseEvt = (MouseEvent*)pEvent->GetData();
        if(pMouseEvt && pMouseEvt->IsLeft() && pMouseEvt->GetClicks() == 1)
        {
            gltf_renderer_stop_rotate_model(&m_rHandle);
        }
    }
    return 0;
}

} // namespace ogl
} // namespace avmedia

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2018, Arm Limited and affiliates.
 * SPDX-License-Identifier: Apache-2.0
 *
 * 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 "GEMALTO_CINTERION_CellularContext.h"
#include "GEMALTO_CINTERION_CellularInformation.h"
#include "GEMALTO_CINTERION.h"
#include "AT_CellularNetwork.h"
#include "CellularLog.h"

using namespace mbed;
using namespace events;

const uint16_t RESPONSE_TO_SEND_DELAY = 100; // response-to-send delay in milliseconds at bit-rate over 9600

GEMALTO_CINTERION::Module GEMALTO_CINTERION::_module;

GEMALTO_CINTERION::GEMALTO_CINTERION(FileHandle *fh) : AT_CellularDevice(fh)
{
}

AT_CellularContext *GEMALTO_CINTERION::create_context_impl(ATHandler &at, const char *apn, bool cp_req, bool nonip_req)
{
    return new GEMALTO_CINTERION_CellularContext(at, this, apn, cp_req, nonip_req);
}

AT_CellularInformation *GEMALTO_CINTERION::open_information_impl(ATHandler &at)
{
    if (_module == ModuleBGS2) {
        return new GEMALTO_CINTERION_CellularInformation(at);
    }
    return AT_CellularDevice::open_information_impl(at);
}

nsapi_error_t GEMALTO_CINTERION::init()
{
    nsapi_error_t err = AT_CellularDevice::init();
    if (err != NSAPI_ERROR_OK) {
        return err;
    }

    CellularInformation *information = open_information();
    if (!information) {
        return NSAPI_ERROR_NO_MEMORY;
    }
    char model[sizeof("EHS5-E") + 1]; // sizeof need to be long enough to hold just the model text
    nsapi_error_t ret = information->get_model(model, sizeof(model));
    close_information();
    if (ret != NSAPI_ERROR_OK) {
        tr_error("Cellular model not found!");
        return NSAPI_ERROR_DEVICE_ERROR;
    }

    if (memcmp(model, "ELS61", sizeof("ELS61") - 1) == 0) {
        init_module_els61();
    } else if (memcmp(model, "BGS2", sizeof("BGS2") - 1) == 0) {
        init_module_bgs2();
    } else if (memcmp(model, "EMS31", sizeof("EMS31") - 1) == 0) {
        init_module_ems31();
    } else if (memcmp(model, "EHS5-E", sizeof("EHS5-E") - 1) == 0) {
        init_module_ehs5e();
    } else {
        tr_error("Cinterion model unsupported %s", model);
        return NSAPI_ERROR_UNSUPPORTED;
    }
    tr_info("Cinterion model %s (%d)", model, _module);

    return NSAPI_ERROR_OK;
}

uint16_t GEMALTO_CINTERION::get_send_delay() const
{
    return RESPONSE_TO_SEND_DELAY;
}

GEMALTO_CINTERION::Module GEMALTO_CINTERION::get_module()
{
    return _module;
}

void GEMALTO_CINTERION::init_module_bgs2()
{
    // BGS2-W_ATC_V00.100
    static const intptr_t cellular_properties[AT_CellularBase::PROPERTY_MAX] = {
        AT_CellularNetwork::RegistrationModeDisable,  // C_EREG
        AT_CellularNetwork::RegistrationModeEnable,  // C_GREG
        AT_CellularNetwork::RegistrationModeLAC,  // C_REG
        0,  // AT_CGSN_WITH_TYPE
        1,  // AT_CGDATA
        1,  // AT_CGAUTH
        1,  // AT_CNMI
        1,  // AT_CSMP
        1,  // AT_CMGF
        1,  // AT_CSDH
        1,  // PROPERTY_IPV4_STACK
        0,  // PROPERTY_IPV6_STACK
        0,  // PROPERTY_IPV4V6_STACK
    };
    AT_CellularBase::set_cellular_properties(cellular_properties);
    _module = ModuleBGS2;
}

void GEMALTO_CINTERION::init_module_els61()
{
    // ELS61-E2_ATC_V01.000
    static const intptr_t cellular_properties[AT_CellularBase::PROPERTY_MAX] = {
        AT_CellularNetwork::RegistrationModeDisable, // C_EREG
        AT_CellularNetwork::RegistrationModeEnable,  // C_GREG
        AT_CellularNetwork::RegistrationModeLAC,     // C_REG
        0,  // AT_CGSN_WITH_TYPE
        1,  // AT_CGDATA
        1,  // AT_CGAUTH
        1,  // PROPERTY_IPV4_STACK
        1,  // PROPERTY_IPV6_STACK
        0,  // PROPERTY_IPV4V6_STACK
    };
    AT_CellularBase::set_cellular_properties(cellular_properties);
    _module = ModuleELS61;
}

void GEMALTO_CINTERION::init_module_ems31()
{
    // EMS31-US_ATC_V4.9.5
    static const intptr_t cellular_properties[AT_CellularBase::PROPERTY_MAX] = {
        AT_CellularNetwork::RegistrationModeLAC,        // C_EREG
        AT_CellularNetwork::RegistrationModeDisable,    // C_GREG
        AT_CellularNetwork::RegistrationModeDisable,    // C_REG
        1,  // AT_CGSN_WITH_TYPE
        1,  // AT_CGDATA
        1,  // AT_CGAUTH
        1,  // PROPERTY_IPV4_STACK
        1,  // PROPERTY_IPV6_STACK
        1,  // PROPERTY_IPV4V6_STACK
    };
    AT_CellularBase::set_cellular_properties(cellular_properties);
    _module = ModuleEMS31;
}

void GEMALTO_CINTERION::init_module_ehs5e()
{
    // EHS5-E
    static const intptr_t cellular_properties[AT_CellularBase::PROPERTY_MAX] = {
        AT_CellularNetwork::RegistrationModeDisable, // C_EREG
        AT_CellularNetwork::RegistrationModeLAC, // C_GREG
        AT_CellularNetwork::RegistrationModeLAC, // C_REG
        0,  // AT_CGSN_WITH_TYPE
        1,  // AT_CGDATA
        1,  // AT_CGAUTH
        1,  // PROPERTY_IPV4_STACK
        1,  // PROPERTY_IPV6_STACK
        1,  // PROPERTY_IPV4V6_STACK
    };
    AT_CellularBase::set_cellular_properties(cellular_properties);
    _module = ModuleEHS5E;
}

#if MBED_CONF_GEMALTO_CINTERION_PROVIDE_DEFAULT
#include "UARTSerial.h"
CellularDevice *CellularDevice::get_default_instance()
{
    static UARTSerial serial(MBED_CONF_GEMALTO_CINTERION_TX, MBED_CONF_GEMALTO_CINTERION_RX, MBED_CONF_GEMALTO_CINTERION_BAUDRATE);
#if defined (MBED_CONF_UBLOX_AT_RTS) && defined(MBED_CONF_UBLOX_AT_CTS)
    tr_debug("GEMALTO_CINTERION flow control: RTS %d CTS %d", MBED_CONF_GEMALTO_CINTERION_RTS, MBED_CONF_GEMALTO_CINTERION_CTS);
    serial.set_flow_control(SerialBase::RTSCTS, MBED_CONF_GEMALTO_CINTERION_RTS, MBED_CONF_GEMALTO_CINTERION_CTS);
#endif
    static GEMALTO_CINTERION device(&serial);
    return &device;
}
#endif
<commit_msg>Disable dual stack mode<commit_after>/*
 * Copyright (c) 2018, Arm Limited and affiliates.
 * SPDX-License-Identifier: Apache-2.0
 *
 * 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 "GEMALTO_CINTERION_CellularContext.h"
#include "GEMALTO_CINTERION_CellularInformation.h"
#include "GEMALTO_CINTERION.h"
#include "AT_CellularNetwork.h"
#include "CellularLog.h"

using namespace mbed;
using namespace events;

const uint16_t RESPONSE_TO_SEND_DELAY = 100; // response-to-send delay in milliseconds at bit-rate over 9600

GEMALTO_CINTERION::Module GEMALTO_CINTERION::_module;

GEMALTO_CINTERION::GEMALTO_CINTERION(FileHandle *fh) : AT_CellularDevice(fh)
{
}

AT_CellularContext *GEMALTO_CINTERION::create_context_impl(ATHandler &at, const char *apn, bool cp_req, bool nonip_req)
{
    return new GEMALTO_CINTERION_CellularContext(at, this, apn, cp_req, nonip_req);
}

AT_CellularInformation *GEMALTO_CINTERION::open_information_impl(ATHandler &at)
{
    if (_module == ModuleBGS2) {
        return new GEMALTO_CINTERION_CellularInformation(at);
    }
    return AT_CellularDevice::open_information_impl(at);
}

nsapi_error_t GEMALTO_CINTERION::init()
{
    nsapi_error_t err = AT_CellularDevice::init();
    if (err != NSAPI_ERROR_OK) {
        return err;
    }

    CellularInformation *information = open_information();
    if (!information) {
        return NSAPI_ERROR_NO_MEMORY;
    }
    char model[sizeof("EHS5-E") + 1]; // sizeof need to be long enough to hold just the model text
    nsapi_error_t ret = information->get_model(model, sizeof(model));
    close_information();
    if (ret != NSAPI_ERROR_OK) {
        tr_error("Cellular model not found!");
        return NSAPI_ERROR_DEVICE_ERROR;
    }

    if (memcmp(model, "ELS61", sizeof("ELS61") - 1) == 0) {
        init_module_els61();
    } else if (memcmp(model, "BGS2", sizeof("BGS2") - 1) == 0) {
        init_module_bgs2();
    } else if (memcmp(model, "EMS31", sizeof("EMS31") - 1) == 0) {
        init_module_ems31();
    } else if (memcmp(model, "EHS5-E", sizeof("EHS5-E") - 1) == 0) {
        init_module_ehs5e();
    } else {
        tr_error("Cinterion model unsupported %s", model);
        return NSAPI_ERROR_UNSUPPORTED;
    }
    tr_info("Cinterion model %s (%d)", model, _module);

    return NSAPI_ERROR_OK;
}

uint16_t GEMALTO_CINTERION::get_send_delay() const
{
    return RESPONSE_TO_SEND_DELAY;
}

GEMALTO_CINTERION::Module GEMALTO_CINTERION::get_module()
{
    return _module;
}

void GEMALTO_CINTERION::init_module_bgs2()
{
    // BGS2-W_ATC_V00.100
    static const intptr_t cellular_properties[AT_CellularBase::PROPERTY_MAX] = {
        AT_CellularNetwork::RegistrationModeDisable,  // C_EREG
        AT_CellularNetwork::RegistrationModeEnable,  // C_GREG
        AT_CellularNetwork::RegistrationModeLAC,  // C_REG
        0,  // AT_CGSN_WITH_TYPE
        1,  // AT_CGDATA
        1,  // AT_CGAUTH
        1,  // AT_CNMI
        1,  // AT_CSMP
        1,  // AT_CMGF
        1,  // AT_CSDH
        1,  // PROPERTY_IPV4_STACK
        0,  // PROPERTY_IPV6_STACK
        0,  // PROPERTY_IPV4V6_STACK
    };
    AT_CellularBase::set_cellular_properties(cellular_properties);
    _module = ModuleBGS2;
}

void GEMALTO_CINTERION::init_module_els61()
{
    // ELS61-E2_ATC_V01.000
    static const intptr_t cellular_properties[AT_CellularBase::PROPERTY_MAX] = {
        AT_CellularNetwork::RegistrationModeDisable, // C_EREG
        AT_CellularNetwork::RegistrationModeEnable,  // C_GREG
        AT_CellularNetwork::RegistrationModeLAC,     // C_REG
        0,  // AT_CGSN_WITH_TYPE
        1,  // AT_CGDATA
        1,  // AT_CGAUTH
        1,  // PROPERTY_IPV4_STACK
        1,  // PROPERTY_IPV6_STACK
        0,  // PROPERTY_IPV4V6_STACK
    };
    AT_CellularBase::set_cellular_properties(cellular_properties);
    _module = ModuleELS61;
}

void GEMALTO_CINTERION::init_module_ems31()
{
    // EMS31-US_ATC_V4.9.5
    static const intptr_t cellular_properties[AT_CellularBase::PROPERTY_MAX] = {
        AT_CellularNetwork::RegistrationModeLAC,        // C_EREG
        AT_CellularNetwork::RegistrationModeDisable,    // C_GREG
        AT_CellularNetwork::RegistrationModeDisable,    // C_REG
        1,  // AT_CGSN_WITH_TYPE
        1,  // AT_CGDATA
        1,  // AT_CGAUTH
        1,  // PROPERTY_IPV4_STACK
        1,  // PROPERTY_IPV6_STACK
        0,  // PROPERTY_IPV4V6_STACK
    };
    AT_CellularBase::set_cellular_properties(cellular_properties);
    _module = ModuleEMS31;
}

void GEMALTO_CINTERION::init_module_ehs5e()
{
    // EHS5-E
    static const intptr_t cellular_properties[AT_CellularBase::PROPERTY_MAX] = {
        AT_CellularNetwork::RegistrationModeDisable, // C_EREG
        AT_CellularNetwork::RegistrationModeLAC, // C_GREG
        AT_CellularNetwork::RegistrationModeLAC, // C_REG
        0,  // AT_CGSN_WITH_TYPE
        1,  // AT_CGDATA
        1,  // AT_CGAUTH
        1,  // PROPERTY_IPV4_STACK
        1,  // PROPERTY_IPV6_STACK
        1,  // PROPERTY_IPV4V6_STACK
    };
    AT_CellularBase::set_cellular_properties(cellular_properties);
    _module = ModuleEHS5E;
}

#if MBED_CONF_GEMALTO_CINTERION_PROVIDE_DEFAULT
#include "UARTSerial.h"
CellularDevice *CellularDevice::get_default_instance()
{
    static UARTSerial serial(MBED_CONF_GEMALTO_CINTERION_TX, MBED_CONF_GEMALTO_CINTERION_RX, MBED_CONF_GEMALTO_CINTERION_BAUDRATE);
#if defined (MBED_CONF_UBLOX_AT_RTS) && defined(MBED_CONF_UBLOX_AT_CTS)
    tr_debug("GEMALTO_CINTERION flow control: RTS %d CTS %d", MBED_CONF_GEMALTO_CINTERION_RTS, MBED_CONF_GEMALTO_CINTERION_CTS);
    serial.set_flow_control(SerialBase::RTSCTS, MBED_CONF_GEMALTO_CINTERION_RTS, MBED_CONF_GEMALTO_CINTERION_CTS);
#endif
    static GEMALTO_CINTERION device(&serial);
    return &device;
}
#endif
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: rc.cxx,v $
 *
 *  $Revision: 1.7 $
 *
 *  last change: $Author: vg $ $Date: 2006-04-07 16:16:52 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    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
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#define _TOOLS_RC_CXX

#include <string.h>

#ifndef _DATE_HXX
#include <date.hxx>
#endif
#ifndef _TIME_HXX
#include <time.hxx>
#endif

#ifndef _TOOLS_RC_HXX
#include <rc.hxx>
#endif
#ifndef _TOOLS_RCID_H
#include <rcid.h>
#endif

// =======================================================================

Resource::Resource( const ResId& rResId )
{
    GetRes( rResId.SetRT( RSC_RESOURCE ) );
}

// -----------------------------------------------------------------------

void Resource::GetRes( const ResId& rResId )
{
    if ( rResId.GetResMgr() )
        rResId.GetResMgr()->GetResource( rResId, this );
    else
        GetResManager()->GetResource( rResId, this );

    IncrementRes( sizeof( RSHEADER_TYPE ) );
}

// -----------------------------------------------------------------------

// =======================================================================

Time::Time( const ResId& rResId )
{
    nTime = 0;
    rResId.SetRT( RSC_TIME );
    ResMgr* pResMgr = NULL;

    ResMgr::GetResourceSkipHeader( rResId, &pResMgr );

    ULONG nObjMask = (USHORT)pResMgr->ReadLong();

    if ( 0x01 & nObjMask )
        SetHour( (USHORT)pResMgr->ReadShort() );
    if ( 0x02 & nObjMask )
        SetMin( (USHORT)pResMgr->ReadShort() );
    if ( 0x04 & nObjMask )
        SetSec( (USHORT)pResMgr->ReadShort() );
    if ( 0x08 & nObjMask )
        Set100Sec( (USHORT)pResMgr->ReadShort() );
}

// =======================================================================

Date::Date( const ResId& rResId )
{
    rResId.SetRT( RSC_DATE );
    ResMgr* pResMgr = NULL;

    ResMgr::GetResourceSkipHeader( rResId, &pResMgr );

    ULONG nObjMask = (USHORT)pResMgr->ReadLong();

    if ( 0x01 & nObjMask )
        SetYear( (USHORT)pResMgr->ReadShort() );
    if ( 0x02 & nObjMask )
        SetMonth( (USHORT)pResMgr->ReadShort() );
    if ( 0x04 & nObjMask )
        SetDay( (USHORT)pResMgr->ReadShort() );
}
<commit_msg>INTEGRATION: CWS pchfix02 (1.7.68); FILE MERGED 2006/09/01 17:54:55 kaib 1.7.68.1: #i68856# Added header markers and pch files<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: rc.cxx,v $
 *
 *  $Revision: 1.8 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-17 00:59:44 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    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
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_tools.hxx"

#define _TOOLS_RC_CXX

#include <string.h>

#ifndef _DATE_HXX
#include <date.hxx>
#endif
#ifndef _TIME_HXX
#include <time.hxx>
#endif

#ifndef _TOOLS_RC_HXX
#include <rc.hxx>
#endif
#ifndef _TOOLS_RCID_H
#include <rcid.h>
#endif

// =======================================================================

Resource::Resource( const ResId& rResId )
{
    GetRes( rResId.SetRT( RSC_RESOURCE ) );
}

// -----------------------------------------------------------------------

void Resource::GetRes( const ResId& rResId )
{
    if ( rResId.GetResMgr() )
        rResId.GetResMgr()->GetResource( rResId, this );
    else
        GetResManager()->GetResource( rResId, this );

    IncrementRes( sizeof( RSHEADER_TYPE ) );
}

// -----------------------------------------------------------------------

// =======================================================================

Time::Time( const ResId& rResId )
{
    nTime = 0;
    rResId.SetRT( RSC_TIME );
    ResMgr* pResMgr = NULL;

    ResMgr::GetResourceSkipHeader( rResId, &pResMgr );

    ULONG nObjMask = (USHORT)pResMgr->ReadLong();

    if ( 0x01 & nObjMask )
        SetHour( (USHORT)pResMgr->ReadShort() );
    if ( 0x02 & nObjMask )
        SetMin( (USHORT)pResMgr->ReadShort() );
    if ( 0x04 & nObjMask )
        SetSec( (USHORT)pResMgr->ReadShort() );
    if ( 0x08 & nObjMask )
        Set100Sec( (USHORT)pResMgr->ReadShort() );
}

// =======================================================================

Date::Date( const ResId& rResId )
{
    rResId.SetRT( RSC_DATE );
    ResMgr* pResMgr = NULL;

    ResMgr::GetResourceSkipHeader( rResId, &pResMgr );

    ULONG nObjMask = (USHORT)pResMgr->ReadLong();

    if ( 0x01 & nObjMask )
        SetYear( (USHORT)pResMgr->ReadShort() );
    if ( 0x02 & nObjMask )
        SetMonth( (USHORT)pResMgr->ReadShort() );
    if ( 0x04 & nObjMask )
        SetDay( (USHORT)pResMgr->ReadShort() );
}
<|endoftext|>


<commit_before>//FRAGMENT(header)
/*==========================================================================
  SeqAn - The Library for Sequence Analysis
  http://www.seqan.de
  ===========================================================================
  Copyright (C) 2010

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

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

  You should have received a copy of the GNU General Public License
  along with this program.  If not, see <http://www.gnu.org/licenses/>.
  ===========================================================================
  Author: Manuel Holtgrewe <manuel.holtgrewe@fu-berlin.de>
  ===========================================================================
  Minimapper -- Minimal read mapping in SeqAn.
  ===========================================================================
  This file contains code for a minimal read mapper with heavy restrictions.
  The restrictions are explained in the tutorial chapter, together with
  suggestions on how to extend this code.
  ===========================================================================*/
//FRAGMENT(includes)
#include <cstdio>
#include <iostream>

#include <seqan/basic.h>
#include <seqan/file.h>
#include <seqan/index.h>
#include <seqan/store.h>
#include <seqan/misc/misc_cmdparser.h>

using namespace seqan;

//FRAGMENT(typedefs)
// Some typedefs.
typedef FragmentStore<>::TReadSeqStore              TReadSeqStore;
typedef Value<TReadSeqStore>::Type                  TReadSeq;
typedef FragmentStore<>::TContigStore               TContigStore;
typedef Value<TContigStore>::Type                   TContigStoreElement;
typedef TContigStoreElement::TContigSeq             TContigSeq;
typedef Index<TReadSeqStore, Index_QGram<Shape<Dna, UngappedShape<11> >, OpenAddressing> > TIndex;
typedef Pattern<TIndex, Swift<SwiftSemiGlobal> >    TPattern;
typedef Finder<TContigSeq, Swift<SwiftSemiGlobal> > TFinder;
typedef FragmentStore<>::TAlignedReadStore          TAlignedReadStore;
typedef Value<TAlignedReadStore>::Type              TAlignedRead;

// const double EPSILON = 0.08;

struct Options
{
    double  epsilon;
    bool    rev_comp;

    Options()
    {
        epsilon = 0.08;
        rev_comp = false;
    }

};

//FRAGMENT(main-input)
int main(int argc, const char *argv[]) {
    // 0) Handle command line arguments.
    if (argc < 3) {
        std::cerr << "Invalid number of arguments." << std::endl
                  << "USAGE: minimapper GENOME.fasta READS.fasta OUT.sam" << std::endl;
        return 1;
    }

    CommandLineOption eps = CommandLineOption("e",
                                              "epsilon",
                                              1,
                                              "maximum error rate",
                                              OptionType::Double,
                                              0.08);

    CommandLineOption revcomp = CommandLineOption("rc",
                                              "reverse-complement",
                                              1,
                                              "align against both strands",
                                              OptionType::Bool,
                                              false);

    CommandLineParser parser;
    addOption(parser, eps);
    addOption(parser, revcomp);
    parse(parser, argc, argv);

    Options MyOptions;
    getOptionValueShort(parser, "e", MyOptions.epsilon);

    // 1) Load contigs and reads.
    FragmentStore<> fragStore;
    if (!loadContigs(fragStore, argv[1])) return 1;
    if (!loadReads(fragStore, argv[2])) return 1;

//     if (MyOptions.rev_comp)
//     {
//         int orglength = length(fragStore.contigStore);
//         resize(fragStore.contigStore, orglength *2);
//         for (int i=0; i < orglength; ++i)
//             assign(fragStore.contigStore[i+orglength],
//                       DnaStringReverseComplement(fragStore.contigStore[i]));
//     }

//FRAGMENT(pattern-finder)
    // 2) Build an index over all reads and a SWIFT pattern over this index.
    TIndex index(fragStore.readSeqStore);
    TPattern pattern(index);

    // String<TVerifyPattern> patterns
    // resize()
    // for ... setHost()

//FRAGMENT(swift)
    // 3) Enumerate all epsilon matches.
    for (unsigned i = 0; i < length(fragStore.contigStore); ++i) {
        TFinder finder(fragStore.contigStore[i].seq);
        // Verify Finder defined here
        while (find(finder, pattern, MyOptions.epsilon)) {
//FRAGMENT(verification)
            // Verify match.
            // clear(verifyFinder)
            // pattern = patterns[i]
            Finder<TContigSeq> verifyFinder(fragStore.contigStore[i].seq);
            setPosition(verifyFinder, beginPosition(finder));
//             Pattern<TReadSeq, HammingSimple> verifyPattern(fragStore.readSeqStore[position(pattern).i1]);
            Pattern<TReadSeq, Myers<> > verifyPattern(fragStore.readSeqStore[position(pattern).i1]);
            setScoreLimit(verifyPattern,
                          -floor(
                              MyOptions.epsilon
                              * length(fragStore.readSeqStore[position(pattern).i1])));

            while (find(verifyFinder, verifyPattern)
                    && position(verifyFinder) < endPosition(infix(finder))
                  )
            {
                bool b = findBegin(verifyFinder, verifyPattern, getScore(verifyPattern));
                SEQAN_ASSERT_TRUE(b);
                TAlignedRead match(length(fragStore.alignedReadStore),
                                   position(pattern).i1,
                                   i,
                                   beginPosition(verifyFinder),
                                   endPosition(verifyFinder));
                std::cout << "BEGIN: " << beginPosition(verifyFinder)
                          << " END: " << endPosition(verifyFinder) << std::endl;

                appendValue(fragStore.alignedReadStore, match);
//                 std::cout << fragStore.readSeqStore[position(pattern).i1] << std::endl;
//                 std::cout << infix(verifyFinder) << std::endl;
            }
        }
    }

    convertMatchesToGlobalAlignment(fragStore, Score<int>(0, -999, -1001, -1000), True());
//FRAGMENT(main-output)
    // 4) Write out SAM file.
    std::ofstream samFile(argv[3], std::ios_base::out);
    write(samFile, fragStore, SAM());

    return 0;
}
<commit_msg>oops, sorry. reverting to original<commit_after>//FRAGMENT(header)
/*==========================================================================
  SeqAn - The Library for Sequence Analysis
  http://www.seqan.de
  ===========================================================================
  Copyright (C) 2010

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

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

  You should have received a copy of the GNU General Public License
  along with this program.  If not, see <http://www.gnu.org/licenses/>.
  ===========================================================================
  Author: Manuel Holtgrewe <manuel.holtgrewe@fu-berlin.de>
  ===========================================================================
  Minimapper -- Minimal read mapping in SeqAn.
  ===========================================================================
  This file contains code for a minimal read mapper with heavy restrictions.
  The restrictions are explained in the tutorial chapter, together with
  suggestions on how to extend this code.
  ===========================================================================*/
//FRAGMENT(includes)
#include <cstdio>
#include <iostream>

#include <seqan/basic.h>
#include <seqan/file.h>
#include <seqan/index.h>
#include <seqan/store.h>

using namespace seqan;

//FRAGMENT(typedefs)
// Some typedefs.
typedef FragmentStore<>::TReadSeqStore TReadSeqStore;
typedef Value<TReadSeqStore>::Type TReadSeq;
typedef FragmentStore<>::TContigStore TContigStore;
typedef Value<TContigStore>::Type TContigStoreElement;
typedef TContigStoreElement::TContigSeq TContigSeq;
typedef Index<TReadSeqStore, Index_QGram<Shape<Dna, UngappedShape<11> >, OpenAddressing> > TIndex;
typedef Pattern<TIndex, Swift<SwiftSemiGlobal> > TPattern;
typedef Finder<TContigSeq, Swift<SwiftSemiGlobal> > TFinder;
typedef FragmentStore<>::TAlignedReadStore TAlignedReadStore;
typedef Value<TAlignedReadStore>::Type TAlignedRead;

const double EPSILON = 0.08;

//FRAGMENT(main-input)
int main(int argc, char *argv[]) {
    // 0) Handle command line arguments.
    if (argc < 3) {
        std::cerr << "Invalid number of arguments." << std::endl
                  << "USAGE: minimapper GENOME.fasta READS.fasta OUT.sam" << std::endl;
        return 1;
    }

    // 1) Load contigs and reads.
    FragmentStore<> fragStore;
    if (!loadContigs(fragStore, argv[1])) return 1;
    if (!loadReads(fragStore, argv[2])) return 1;

//FRAGMENT(pattern-finder)
    // 2) Build an index over all reads and a SWIFT pattern over this index.
    TIndex index(fragStore.readSeqStore);
    TPattern pattern(index);

//FRAGMENT(swift)
    // 3) Enumerate all epsilon matches.
    for (unsigned i = 0; i < length(fragStore.contigStore); ++i) {
        TFinder finder(fragStore.contigStore[i].seq);
        while (find(finder, pattern, EPSILON)) {
//FRAGMENT(verification)
            // Verify match.
            Finder<TContigSeq> verifyFinder(fragStore.contigStore[i].seq);
            setPosition(verifyFinder, beginPosition(finder));
            Pattern<TReadSeq, HammingSimple> verifyPattern(fragStore.readSeqStore[position(pattern).i1]);
            while (find(verifyFinder, verifyPattern) && position(verifyFinder) < endPosition(infix(finder))) {
                TAlignedRead match(length(fragStore.alignedReadStore), position(pattern).i1, i,
                                   beginPosition(verifyFinder), endPosition(verifyFinder));
                appendValue(fragStore.alignedReadStore, match);
            }
        }
    }

//FRAGMENT(main-output)
    // 4) Write out SAM file.
    std::ofstream samFile(argv[3], std::ios_base::out);
    write(samFile, fragStore, SAM());

    return 0;
}
<|endoftext|>