Merge branch 'fsd'

This commit is contained in:
Mathew Sutcliffe
2013-08-28 23:29:10 +01:00
19 changed files with 1833 additions and 1 deletions

View File

@@ -44,6 +44,7 @@ equals(WITH_DRIVER_XPLANE, ON) {
}
equals(WITH_SAMPLES, ON) {
SUBDIRS += samples/cli_client/sample_cli_client.pro
SUBDIRS += samples/com_client/sample_com_client.pro
SUBDIRS += samples/com_server/sample_com_server.pro
SUBDIRS += samples/config/sample_config.pro

View File

@@ -1,4 +1,5 @@
ADD_SUBDIRECTORY(logging)
ADD_SUBDIRECTORY(cli_client)
ADD_SUBDIRECTORY(com_server)
ADD_SUBDIRECTORY(com_client)
ADD_SUBDIRECTORY(geodetic2ecef)

View File

@@ -0,0 +1,7 @@
FILE(GLOB SRC *.cpp)
SET(HEADERS *.h)
ADD_EXECUTABLE(sample_cli_client ${SRC})
TARGET_LINK_LIBRARIES(sample_cli_client blackmisc ${QT_LIBRARIES})
SET_TARGET_PROPERTIES(sample_cli_client PROPERTIES PROJECT_LABEL "Samples - CLI Client")

View File

@@ -0,0 +1,423 @@
/* Copyright (C) 2013 VATSIM Community / authors
* 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 "client.h"
#include "blackmisc/context.h"
#include <iostream>
#include <QStringList>
Client::Client()
: m_net(BlackMisc::IContext::getInstance().singleton<BlackCore::INetwork>())
{
using namespace BlackCore;
connect(m_net, &INetwork::atcPositionUpdate, this, &Client::atcPositionUpdate);
connect(m_net, &INetwork::atcDisconnected, this, &Client::atcDisconnected);
connect(m_net, &INetwork::connectionStatusIdle, this, &Client::connectionStatusIdle);
connect(m_net, &INetwork::connectionStatusConnecting, this, &Client::connectionStatusConnecting);
connect(m_net, &INetwork::connectionStatusConnected, this, &Client::connectionStatusConnected);
connect(m_net, &INetwork::connectionStatusDisconnected, this, &Client::connectionStatusDisconnected);
connect(m_net, &INetwork::connectionStatusError, this, &Client::connectionStatusError);
connect(m_net, &INetwork::ipQueryReplyReceived, this, &Client::ipQueryReplyReceived);
connect(m_net, &INetwork::freqQueryReplyReceived, this, &Client::freqQueryReplyReceived);
connect(m_net, &INetwork::serverQueryReplyReceived, this, &Client::serverQueryReplyReceived);
connect(m_net, &INetwork::atcQueryReplyReceived, this, &Client::atcQueryReplyReceived);
connect(m_net, &INetwork::atisQueryReplyReceived, this, &Client::atisQueryReplyReceived);
connect(m_net, &INetwork::nameQueryReplyReceived, this, &Client::nameQueryReplyReceived);
connect(m_net, &INetwork::capabilitiesQueryReplyReceived, this, &Client::capabilitiesQueryReplyReceived);
connect(m_net, &INetwork::freqQueryRequestReceived, this, &Client::freqQueryRequestReceived);
connect(m_net, &INetwork::nameQueryRequestReceived, this, &Client::nameQueryRequestReceived);
connect(m_net, &INetwork::kicked, this, &Client::kicked);
connect(m_net, &INetwork::metarReceived, this, &Client::metarReceived);
connect(m_net, &INetwork::pilotDisconnected, this, &Client::pilotDisconnected);
connect(m_net, &INetwork::planeInfoReceived, this, &Client::planeInfoReceived);
connect(m_net, &INetwork::planeInfoRequestReceived, this, &Client::planeInfoRequestReceived);
connect(m_net, &INetwork::pong, this, &Client::pong);
connect(m_net, &INetwork::radioTextMessageReceived, this, &Client::radioTextMessageReceived);
connect(m_net, &INetwork::privateTextMessageReceived, this, &Client::privateTextMessageReceived);
connect(this, &Client::setServerDetails, m_net, &INetwork::setServerDetails);
connect(this, &Client::setUserCredentials, m_net, &INetwork::setUserCredentials);
connect(this, &Client::setCallsign, m_net, &INetwork::setCallsign);
connect(this, &Client::setRealName, m_net, &INetwork::setRealName);
connect(this, &Client::initiateConnection, m_net, &INetwork::initiateConnection);
connect(this, &Client::terminateConnection, m_net, &INetwork::terminateConnection);
connect(this, &Client::sendPrivateTextMessage, m_net, &INetwork::sendPrivateTextMessage);
connect(this, &Client::sendRadioTextMessage, m_net, &INetwork::sendRadioTextMessage);
connect(this, &Client::sendIpQuery, m_net, &INetwork::sendIpQuery);
connect(this, &Client::sendFreqQuery, m_net, &INetwork::sendFreqQuery);
connect(this, &Client::sendServerQuery, m_net, &INetwork::sendServerQuery);
connect(this, &Client::sendAtcQuery, m_net, &INetwork::sendAtcQuery);
connect(this, &Client::sendAtisQuery, m_net, &INetwork::sendAtisQuery);
connect(this, &Client::sendNameQuery, m_net, &INetwork::sendNameQuery);
connect(this, &Client::sendCapabilitiesQuery, m_net, &INetwork::sendCapabilitiesQuery);
connect(this, &Client::replyToFreqQuery, m_net, &INetwork::replyToFreqQuery);
connect(this, &Client::replyToNameQuery, m_net, &INetwork::replyToNameQuery);
connect(this, &Client::requestPlaneInfo, m_net, &INetwork::requestPlaneInfo);
connect(this, &Client::sendPlaneInfo, m_net, &INetwork::sendPlaneInfo);
connect(this, &Client::ping, m_net, &INetwork::ping);
connect(this, &Client::requestMetar, m_net, &INetwork::requestMetar);
connect(this, &Client::requestWeatherData, m_net, &INetwork::requestWeatherData);
using namespace std::placeholders;
m_commands["help"] = std::bind(&Client::help, this, _1);
m_commands["echo"] = std::bind(&Client::echo, this, _1);
m_commands["exit"] = std::bind(&Client::exit, this, _1);
m_commands["setserver"] = std::bind(&Client::setServerDetailsCmd, this, _1);
m_commands["setuser"] = std::bind(&Client::setUserCredentialsCmd, this, _1);
m_commands["setcallsign"] = std::bind(&Client::setCallsignCmd, this, _1);
m_commands["setrealname"] = std::bind(&Client::setRealNameCmd, this, _1);
m_commands["initconnect"] = std::bind(&Client::initiateConnectionCmd, this, _1);
m_commands["termconnect"] = std::bind(&Client::terminateConnectionCmd, this, _1);
m_commands["privmsg"] = std::bind(&Client::sendPrivateTextMessageCmd, this, _1);
m_commands["textmsg"] = std::bind(&Client::sendRadioTextMessageCmd, this, _1);
m_commands["ip"] = std::bind(&Client::sendIpQueryCmd, this, _1);
m_commands["freq"] = std::bind(&Client::sendFreqQueryCmd, this, _1);
m_commands["server"] = std::bind(&Client::sendServerQueryCmd, this, _1);
m_commands["atc"] = std::bind(&Client::sendAtcQueryCmd, this, _1);
m_commands["atis"] = std::bind(&Client::sendAtisQueryCmd, this, _1);
m_commands["name"] = std::bind(&Client::sendNameQueryCmd, this, _1);
m_commands["caps"] = std::bind(&Client::sendCapabilitiesQueryCmd, this, _1);
m_commands["freqreply"] = std::bind(&Client::replyToFreqQueryCmd, this, _1);
m_commands["namereply"] = std::bind(&Client::replyToNameQueryCmd, this, _1);
m_commands["planeinfo"] = std::bind(&Client::requestPlaneInfoCmd, this, _1);
m_commands["planeinforeply"] = std::bind(&Client::sendPlaneInfoCmd, this, _1);
m_commands["ping"] = std::bind(&Client::pingCmd, this, _1);
m_commands["metar"] = std::bind(&Client::requestMetarCmd, this, _1);
m_commands["weather"] = std::bind(&Client::requestWeatherDataCmd, this, _1);
}
void Client::command(QString line)
{
QTextStream stream (&line, QIODevice::ReadOnly);
QString cmd;
stream >> cmd;
stream.skipWhiteSpace();
auto found = m_commands.find(cmd);
if (found == m_commands.end())
{
std::cout << "No such command" << std::endl;
}
else
{
(*found)(stream);
}
}
/****************************************************************************/
/************ Commands *************/
/****************************************************************************/
void Client::help(QTextStream&)
{
std::cout << "Commands:" << std::endl;
auto keys = m_commands.keys();
for (auto i = keys.begin(); i != keys.end(); ++i)
{
std::cout << " " << i->toStdString() << std::endl;
}
}
void Client::echo(QTextStream& line)
{
std::cout << "echo: " << line.readAll().toStdString() << std::endl;
}
void Client::exit(QTextStream&)
{
emit quit();
}
void Client::setServerDetailsCmd(QTextStream& args)
{
QString hostname;
quint16 port;
args >> hostname >> port;
emit setServerDetails(hostname, port);
}
void Client::setUserCredentialsCmd(QTextStream& args)
{
QString username;
QString password;
args >> username >> password;
emit setUserCredentials(username, password);
}
void Client::setCallsignCmd(QTextStream& args)
{
QString callsign;
args >> callsign;
emit setCallsign(callsign);
}
void Client::setRealNameCmd(QTextStream& args)
{
emit setRealName(args.readAll());
}
void Client::initiateConnectionCmd(QTextStream&)
{
emit initiateConnection();
}
void Client::terminateConnectionCmd(QTextStream&)
{
emit terminateConnection();
}
void Client::sendPrivateTextMessageCmd(QTextStream& args)
{
QString callsign;
args >> callsign;
args.skipWhiteSpace();
emit sendPrivateTextMessage(callsign, args.readAll());
}
void Client::sendRadioTextMessageCmd(QTextStream& args)
{
QString freqsBlob;
args >> freqsBlob;
QStringList freqStrings = freqsBlob.split("|");
QVector<BlackMisc::PhysicalQuantities::CFrequency> freqs;
for (auto i = freqStrings.begin(); i != freqStrings.end(); ++i)
{
freqs.push_back(BlackMisc::PhysicalQuantities::CFrequency(i->toDouble(), BlackMisc::PhysicalQuantities::CFrequencyUnit::MHz()));
}
emit sendRadioTextMessage(freqs, args.readAll());
}
void Client::sendIpQueryCmd(QTextStream&)
{
emit sendIpQuery();
}
void Client::sendFreqQueryCmd(QTextStream& args)
{
QString callsign;
args >> callsign;
emit sendFreqQuery(callsign);
}
void Client::sendServerQueryCmd(QTextStream& args)
{
QString callsign;
args >> callsign;
emit sendServerQuery(callsign);
}
void Client::sendAtcQueryCmd(QTextStream& args)
{
QString callsign;
args >> callsign;
emit sendAtcQuery(callsign);
}
void Client::sendAtisQueryCmd(QTextStream& args)
{
QString callsign;
args >> callsign;
emit sendAtisQuery(callsign);
}
void Client::sendNameQueryCmd(QTextStream& args)
{
QString callsign;
args >> callsign;
emit sendNameQuery(callsign);
}
void Client::sendCapabilitiesQueryCmd(QTextStream& args)
{
QString callsign;
args >> callsign;
emit sendCapabilitiesQuery(callsign);
}
void Client::replyToFreqQueryCmd(QTextStream& args)
{
QString callsign;
double num;
args >> callsign >> num;
BlackMisc::PhysicalQuantities::CFrequency freq (num, BlackMisc::PhysicalQuantities::CFrequencyUnit::kHz());
emit replyToFreqQuery(callsign, freq);
}
void Client::replyToNameQueryCmd(QTextStream& args)
{
QString callsign;
QString realname;
args >> callsign >> realname;
emit replyToNameQuery(callsign, realname);
}
void Client::requestPlaneInfoCmd(QTextStream& args)
{
QString callsign;
args >> callsign;
emit requestPlaneInfo(callsign);
}
void Client::sendPlaneInfoCmd(QTextStream& args)
{
QString callsign;
QString acTypeICAO;
QString airlineICAO;
QString livery;
args >> callsign >> acTypeICAO >> airlineICAO >> livery;
emit sendPlaneInfo(callsign, acTypeICAO, airlineICAO, livery);
}
void Client::pingCmd(QTextStream& args)
{
QString callsign;
args >> callsign;
emit ping(callsign);
}
void Client::requestMetarCmd(QTextStream& args)
{
QString airportICAO;
args >> airportICAO;
emit requestMetar(airportICAO);
}
void Client::requestWeatherDataCmd(QTextStream& args)
{
QString airportICAO;
args >> airportICAO;
emit requestWeatherData(airportICAO);
}
/****************************************************************************/
/************ Slots to receive signals from INetwork *************/
/****************************************************************************/
void Client::atcPositionUpdate(const QString& callsign, const BlackMisc::PhysicalQuantities::CFrequency& freq,
const BlackMisc::Geo::CCoordinateGeodetic& pos, const BlackMisc::PhysicalQuantities::CLength& range)
{
std::cout << "POSITION " << callsign.toStdString() << " " << freq << " " << pos << " " << range << std::endl;
}
void Client::atcDisconnected(const QString& callsign)
{
std::cout << "ATC_DISCONNECTED " << callsign.toStdString() << std::endl;
}
void Client::connectionStatusIdle()
{
std::cout << "CONN_STATUS_IDLE" << std::endl;
}
void Client::connectionStatusConnecting()
{
std::cout << "CONN_STATUS_CONNECTING" << std::endl;
}
void Client::connectionStatusConnected()
{
std::cout << "CONN_STATUS_CONNECTED" << std::endl;
}
void Client::connectionStatusDisconnected()
{
std::cout << "CONN_STATUS_DISCONNECTED" << std::endl;
}
void Client::connectionStatusError()
{
std::cout << "CONN_STATUS_ERROR" << std::endl;
}
void Client::ipQueryReplyReceived(const QString& ip)
{
std::cout << "IP_REPLY " << ip.toStdString() << std::endl;
}
void Client::freqQueryReplyReceived(const QString& callsign, const BlackMisc::PhysicalQuantities::CFrequency& freq)
{
std::cout << "FREQ_REPLY " << callsign.toStdString() << " " << freq << std::endl;
}
void Client::serverQueryReplyReceived(const QString& callsign, const QString& hostname)
{
std::cout << "SERVER_REPLY " << callsign.toStdString() << " " << hostname.toStdString() << std::endl;
}
void Client::atcQueryReplyReceived(const QString& callsign, bool isATC)
{
std::cout << "ATC_REPLY " << callsign.toStdString() << (isATC ? " yes" : " no") << std::endl;
}
void Client::atisQueryReplyReceived(const QString& callsign, const QString& data)
{
std::cout << "ATIS_REPLY " << callsign.toStdString() << " " << data.toStdString() << std::endl;
}
void Client::nameQueryReplyReceived(const QString& callsign, const QString& realname)
{
std::cout << "NAME_REPLY " << callsign.toStdString() << " " << realname.toStdString() << std::endl;
}
void Client::capabilitiesQueryReplyReceived(const QString& callsign, quint32 flags)
{
std::cout << "CAPS_REPLY " << callsign.toStdString() << " " << flags << std::endl;
}
void Client::freqQueryRequestReceived(const QString& callsign)
{
std::cout << "FREQ_QUERY " << callsign.toStdString() << std::endl;
}
void Client::nameQueryRequestReceived(const QString& callsign)
{
std::cout << "NAME_QUERY " << callsign.toStdString() << std::endl;
}
void Client::kicked(const QString& msg)
{
std::cout << "KICKED " << msg.toStdString() << std::endl;
}
void Client::metarReceived(const QString& data)
{
std::cout << "METAR " << data.toStdString() << std::endl;
}
void Client::pilotDisconnected(const QString& callsign)
{
std::cout << "PILOT_DISCONNECTED " << callsign.toStdString() << std::endl;
}
void Client::planeInfoReceived(const QString& callsign, const QString& acTypeICAO, const QString& airlineICAO, const QString& livery)
{
std::cout << "PLANE_INFO_REPLY " << callsign.toStdString() << " " << acTypeICAO.toStdString() << " " << airlineICAO.toStdString() << " " << livery.toStdString() << std::endl;
}
void Client::planeInfoRequestReceived(const QString& callsign)
{
std::cout << "PLANE_INFO_QUERY " << callsign.toStdString() << std::endl;
}
void Client::pong(const QString& callsign, const BlackMisc::PhysicalQuantities::CTime& elapsedTime)
{
std::cout << "PONG " << callsign.toStdString() << " " << elapsedTime << std::endl;
}
void Client::radioTextMessageReceived(const QString& callsign, const QString& msg, const QVector<BlackMisc::PhysicalQuantities::CFrequency>& freqs)
{
QString freqsBlob = freqs[0].toQString();
for (auto i = freqs.begin() + 1; i != freqs.end(); ++i)
{
freqsBlob.append("|");
freqsBlob.append(i->toQString());
}
std::cout << "TEXT_MSG " << callsign.toStdString() << " " << freqsBlob.toStdString() << " " << msg.toStdString() << std::endl;
}
void Client::privateTextMessageReceived(const QString& fromCallsign, const QString& toCallsign, const QString& msg)
{
std::cout << "PRIV_MSG " << fromCallsign.toStdString() << " -> " << toCallsign.toStdString() << " " << msg.toStdString() << std::endl;
}

111
samples/cli_client/client.h Normal file
View File

@@ -0,0 +1,111 @@
/* Copyright (C) 2013 VATSIM Community / authors
* 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/. */
#ifndef __BLACKSAMPLE_CLI_CLIENT_H__
#define __BLACKSAMPLE_CLI_CLIENT_H__
#include <QObject>
#include <QTextStream>
#include <QMap>
#include <functional>
#include "blackcore/network.h"
class Client : public QObject
{
Q_OBJECT
public:
Client();
signals:
void quit();
public slots:
void command(QString line);
private: //commands
void help(QTextStream& args);
void echo(QTextStream& args);
void exit(QTextStream& args);
void setServerDetailsCmd(QTextStream& args);
void setUserCredentialsCmd(QTextStream& args);
void setCallsignCmd(QTextStream& args);
void setRealNameCmd(QTextStream& args);
void initiateConnectionCmd(QTextStream& args);
void terminateConnectionCmd(QTextStream& args);
void sendPrivateTextMessageCmd(QTextStream& args);
void sendRadioTextMessageCmd(QTextStream& args);
void sendIpQueryCmd(QTextStream& args);
void sendFreqQueryCmd(QTextStream& args);
void sendServerQueryCmd(QTextStream& args);
void sendAtcQueryCmd(QTextStream& args);
void sendAtisQueryCmd(QTextStream& args);
void sendNameQueryCmd(QTextStream& args);
void sendCapabilitiesQueryCmd(QTextStream& args);
void replyToFreqQueryCmd(QTextStream& args);
void replyToNameQueryCmd(QTextStream& args);
void requestPlaneInfoCmd(QTextStream& args);
void sendPlaneInfoCmd(QTextStream& args);
void pingCmd(QTextStream& args);
void requestMetarCmd(QTextStream& args);
void requestWeatherDataCmd(QTextStream& args);
signals: //to send to INetwork
void setServerDetails(const QString& hostname, quint16 port);
void setUserCredentials(const QString& username, const QString& password);
void setCallsign(const QString& callsign);
void setRealName(const QString& name);
void initiateConnection();
void terminateConnection();
void sendPrivateTextMessage(const QString& callsign, const QString& msg);
void sendRadioTextMessage(const QVector<BlackMisc::PhysicalQuantities::CFrequency>& freqs, const QString& msg);
void sendIpQuery();
void sendFreqQuery(const QString& callsign);
void sendServerQuery(const QString& callsign);
void sendAtcQuery(const QString& callsign);
void sendAtisQuery(const QString& callsign);
void sendNameQuery(const QString& callsign);
void sendCapabilitiesQuery(const QString& callsign);
void replyToFreqQuery(const QString& callsign, const BlackMisc::PhysicalQuantities::CFrequency& freq);
void replyToNameQuery(const QString& callsign, const QString& realname);
void requestPlaneInfo(const QString& callsign);
void sendPlaneInfo(const QString& callsign, const QString& acTypeICAO, const QString& airlineICAO, const QString& livery);
void ping(const QString& callsign);
void requestMetar(const QString& airportICAO);
void requestWeatherData(const QString& airportICAO);
public slots: //to receive from INetwork
void atcPositionUpdate(const QString& callsign, const BlackMisc::PhysicalQuantities::CFrequency& freq,
const BlackMisc::Geo::CCoordinateGeodetic& pos, const BlackMisc::PhysicalQuantities::CLength& range);
void atcDisconnected(const QString& callsign);
void connectionStatusIdle();
void connectionStatusConnecting();
void connectionStatusConnected();
void connectionStatusDisconnected();
void connectionStatusError();
void ipQueryReplyReceived(const QString& ip);
void freqQueryReplyReceived(const QString& callsign, const BlackMisc::PhysicalQuantities::CFrequency& freq);
void serverQueryReplyReceived(const QString& callsign, const QString& hostname);
void atcQueryReplyReceived(const QString& callsign, bool isATC);
void atisQueryReplyReceived(const QString& callsign, const QString& data);
void nameQueryReplyReceived(const QString& callsign, const QString& realname);
void capabilitiesQueryReplyReceived(const QString& callsign, quint32 flags);
void freqQueryRequestReceived(const QString& callsign);
void nameQueryRequestReceived(const QString& callsign);
void kicked(const QString& msg);
void metarReceived(const QString& data);
void pilotDisconnected(const QString& callsign);
void planeInfoReceived(const QString& callsign, const QString& acTypeICAO, const QString& airlineICAO, const QString& livery);
void planeInfoRequestReceived(const QString& callsign);
void pong(const QString& callsign, const BlackMisc::PhysicalQuantities::CTime& elapsedTime);
void radioTextMessageReceived(const QString& callsign, const QString& msg, const QVector<BlackMisc::PhysicalQuantities::CFrequency>& freqs);
void privateTextMessageReceived(const QString& fromCallsign, const QString& toCallsign, const QString& msg);
private:
QMap<QString, std::function<void(QTextStream&)>> m_commands;
BlackCore::INetwork* m_net;
};
#endif //__BLACKSAMPLE_CLI_CLIENT_H__

View File

@@ -0,0 +1,27 @@
/* Copyright (C) 2013 VATSIM Community / authors
* 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 "blackcore/network_vatlib.h"
#include "client.h"
#include "reader.h"
#include <QCoreApplication>
#include <QTextCodec>
int main(int argc, char *argv[])
{
QCoreApplication app (argc, argv);
BlackMisc::CApplicationContext myApplicationContext;
BlackMisc::IContext::getInstance().setSingleton(new BlackMisc::CDebug());
BlackMisc::IContext::getInstance().setSingleton<BlackCore::INetwork>(new BlackCore::NetworkVatlib());
Client client;
LineReader reader;
QObject::connect(&reader, SIGNAL(command(const QString&)), &client, SLOT(command(const QString&)));
QObject::connect(&client, SIGNAL(quit()), &reader, SLOT(terminate()));
QObject::connect(&client, SIGNAL(quit()), &app, SLOT(quit()));
reader.start();
app.exec();
}

View File

@@ -0,0 +1,21 @@
/* Copyright (C) 2013 VATSIM Community / authors
* 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 "reader.h"
#include <QFile>
void LineReader::run()
{
QFile file;
file.open(stdin, QIODevice::ReadOnly | QIODevice::Text);
forever
{
QString line = file.readLine().trimmed();
if (! line.isEmpty())
{
emit command(line);
}
}
}

View File

@@ -0,0 +1,26 @@
/* Copyright (C) 2013 VATSIM Community / authors
* 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/. */
#ifndef __BLACKSAMPLE_CLI_CLIENT_READER_H__
#define __BLACKSAMPLE_CLI_CLIENT_READER_H__
#include <QThread>
#include <QString>
class LineReader : public QThread
{
Q_OBJECT
public:
LineReader() {}
protected:
void run();
signals:
void command(const QString& line);
};
#endif //__BLACKSAMPLE_CLI_CLIENT_READER_H__

View File

@@ -0,0 +1,27 @@
QT += core
QT -= gui
TARGET = sample_cli_client
TEMPLATE = app
CONFIG += console
CONFIG -= app_bundle
DEPENDPATH += . ../../src
INCLUDEPATH += . ../../src
SOURCES += *.cpp
HEADERS += *.h
LIBS += -L../../lib -lblackcore -lblackmisc
LIBS += -L../../../vatlib -lvatlib
win32:!win32-g++*: PRE_TARGETDEPS += ../../lib/blackmisc.lib \
../../lib/blackcore.lib \
../../../vatlib/vatlib.lib
else: PRE_TARGETDEPS += ../../lib/libblackmisc.a \
../../lib/libblackcore.a \
../../../vatlib/libvatlib.a
#TODO standardize dependency locations
DESTDIR = ../../bin

View File

@@ -0,0 +1,35 @@
/* Copyright (C) 2013 VATSIM Community / authors
* 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 "atclistmgr.h"
#include "network.h"
BlackCore::CAtcListManager::CAtcListManager()
{
INetwork *net = BlackMisc::IContext::getInstance().singleton<INetwork>();
connect(net, &INetwork::atcPositionUpdate, this, &CAtcListManager::update, Qt::QueuedConnection);
connect(net, &INetwork::atcDisconnected, this, &CAtcListManager::remove, Qt::QueuedConnection);
connect(net, &INetwork::connectionStatusDisconnected, this, &CAtcListManager::clear, Qt::QueuedConnection);
}
void BlackCore::CAtcListManager::update(const QString& callsign, const BlackMisc::PhysicalQuantities::CFrequency& freq,
const BlackMisc::Geo::CCoordinateGeodetic& pos, const BlackMisc::PhysicalQuantities::CLength& range)
{
m_list.insert(BlackMisc::CAtcListEntry(callsign, freq, pos, range));
emit listChanged(m_list);
}
void BlackCore::CAtcListManager::remove(const QString& callsign)
{
m_list.remove(callsign);
emit listChanged(m_list);
}
void BlackCore::CAtcListManager::clear()
{
m_list.clear();
emit listChanged(m_list);
}

View File

@@ -0,0 +1,83 @@
/* Copyright (C) 2013 VATSIM Community / authors
* 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/. */
/*!
\file
*/
#ifndef BLACKCORE_ATCLISTMGR_H
#define BLACKCORE_ATCLISTMGR_H
#include "blackmisc/atclist.h"
#include <QObject>
namespace BlackCore
{
/*!
* Abstract base class that manages and provides access to a list of available ATC stations.
*/
class IAtcListManager : public QObject
{
Q_OBJECT
Q_PROPERTY(BlackMisc::CAtcList list READ getList NOTIFY listChanged)
public:
BLACK_INTERFACE(BlackCore::IAtcListManager)
/*!
* Virtual destructor.
*/
virtual ~IAtcListManager() {}
/*!
* Immutable getter.
* \return
*/
virtual const BlackMisc::CAtcList &getList() const = 0;
signals:
/*!
* Emitted whenever there is a change in the ATC list.
* \param list The new list
*/
void listChanged(const BlackMisc::CAtcList &list);
};
/*!
* Concrete ATC list manager. Implementation of IAtcListManager.
*
* Has a dependency on INetwork. An INetwork must be available through the IContext singleton.
*/
class CAtcListManager : public IAtcListManager
{
Q_OBJECT
public:
/*!
* Constructor.
*/
CAtcListManager();
virtual const BlackMisc::CAtcList& getList() const { return m_list; }
public slots:
/*!
* CAtcListManager is responsible for connecting these slots.
* \{
*/
void update(const QString& callsign, const BlackMisc::PhysicalQuantities::CFrequency& freq,
const BlackMisc::Geo::CCoordinateGeodetic& pos, const BlackMisc::PhysicalQuantities::CLength& range);
void remove(const QString& callsign);
void clear();
/*! \} */
private:
BlackMisc::CAtcList m_list;
};
}//namespace BlackCore
#endif //BLACKCORE_ATCLISTMGR_H

139
src/blackcore/network.h Normal file
View File

@@ -0,0 +1,139 @@
/* Copyright (C) 2013 VATSIM Community / authors
* 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/. */
/*!
\file
*/
#ifndef BLACKCORE_NETWORK_H
#define BLACKCORE_NETWORK_H
#include "../blackmisc/pqfrequency.h"
#include "../blackmisc/coordinategeodetic.h"
#include "../blackmisc/pqlength.h"
#include "../blackmisc/pqtime.h"
#include <QObject>
#include <QString>
#include <QMap>
#include <QVector>
namespace BlackCore
{
/*!
* Interface to a connection to a multi-user flight simulation and ATC network.
*
* \warning If an INetwork signal is connected to a slot, and that slot emits a signal
* which is connected to an INetwork slot, then at least one of those connections
* must be a Qt::QueuedConnection.
*/
class INetwork : public QObject
{
Q_OBJECT
public:
BLACK_INTERFACE(BlackCore::INetwork)
virtual ~INetwork() {}
enum
{
AcceptsAtisResponses = 1 << 0,
SupportsInterimPosUpdates = 1 << 1,
SupportsModelDescriptions = 1 << 2,
};
public slots:
virtual void setServerDetails(const QString& hostname, quint16 port) = 0;
virtual void setUserCredentials(const QString& username, const QString& password) = 0;
virtual void setCallsign(const QString& callsign) = 0;
virtual void setRealName(const QString& name) = 0;
virtual void initiateConnection() = 0;
virtual void terminateConnection() = 0;
virtual void sendPrivateTextMessage(const QString& callsign, const QString& msg) = 0;
virtual void sendRadioTextMessage(const QVector<BlackMisc::PhysicalQuantities::CFrequency>& freqs, const QString& msg) = 0;
virtual void sendIpQuery() = 0;
virtual void sendFreqQuery(const QString& callsign) = 0;
virtual void sendServerQuery(const QString& callsign) = 0;
virtual void sendAtcQuery(const QString& callsign) = 0;
virtual void sendAtisQuery(const QString& callsign) = 0;
virtual void sendNameQuery(const QString& callsign) = 0;
virtual void sendCapabilitiesQuery(const QString& callsign) = 0;
virtual void replyToFreqQuery(const QString& callsign, const BlackMisc::PhysicalQuantities::CFrequency& freq) = 0;
virtual void replyToNameQuery(const QString& callsign, const QString& realname) = 0;
virtual void requestPlaneInfo(const QString& callsign) = 0;
//TODO virtual void setPlanePosition(...) = 0;
//TODO virtual void sendFlightPlan(...) = 0;
virtual void sendPlaneInfo(const QString& callsign, const QString& acTypeICAO, const QString& airlineICAO, const QString& livery) = 0;
virtual void ping(const QString& callsign) = 0;
virtual void requestMetar(const QString& airportICAO) = 0;
virtual void requestWeatherData(const QString& airportICAO) = 0;
signals:
void atcPositionUpdate(const QString& callsign, const BlackMisc::PhysicalQuantities::CFrequency& freq,
const BlackMisc::Geo::CCoordinateGeodetic& pos, const BlackMisc::PhysicalQuantities::CLength& range);
void atcDisconnected(const QString& callsign);
//TODO void cloudDataReceived(...);
void connectionStatusIdle();
void connectionStatusConnecting();
void connectionStatusConnected();
void connectionStatusDisconnected();
void connectionStatusError();
void ipQueryReplyReceived(const QString& ip);
void freqQueryReplyReceived(const QString& callsign, const BlackMisc::PhysicalQuantities::CFrequency& freq);
void serverQueryReplyReceived(const QString& callsign, const QString& hostname);
void atcQueryReplyReceived(const QString& callsign, bool isATC);
void atisQueryReplyReceived(const QString& callsign, const QString& data);
void nameQueryReplyReceived(const QString& callsign, const QString& realname);
void capabilitiesQueryReplyReceived(const QString& callsign, quint32 flags);
void freqQueryRequestReceived(const QString& callsign);
void nameQueryRequestReceived(const QString& callsign);
//TODO void interimPilotPositionUpdate(...);
void kicked(const QString& msg);
void metarReceived(const QString& data);
void pilotDisconnected(const QString& callsign);
void planeInfoReceived(const QString& callsign, const QString& acTypeICAO, const QString& airlineICAO, const QString& livery);
void planeInfoRequestReceived(const QString& callsign);
//TODO void pilotPositionUpdate(...);
void pong(const QString& callsign, const BlackMisc::PhysicalQuantities::CTime& elapsedTime);
void radioTextMessageReceived(const QString& callsign, const QString& msg, const QVector<BlackMisc::PhysicalQuantities::CFrequency>& freqs);
void privateTextMessageReceived(const QString& fromCallsign, const QString& toCallsign, const QString& msg);
//TODO void temperatureDataReceived(...);
//TODO void windDataReceived(...);
};
/*!
* Dummy implementation of INetwork used for testing.
*/
class NetworkDummy : public INetwork
{
public: //INetwork slots overrides
virtual void setServerDetails(const QString&, quint16) {}
virtual void setUserCredentials(const QString&, const QString&) {}
virtual void setCallsign(const QString&) {}
virtual void setRealName(const QString&) {}
virtual void initiateConnection() {}
virtual void terminateConnection() {}
virtual void sendPrivateTextMessage(const QString&, const QString&) {}
virtual void sendRadioTextMessage(const QVector<BlackMisc::PhysicalQuantities::CFrequency>&, const QString&) {}
virtual void sendIpQuery() {}
virtual void sendFreqQuery(const QString&) {}
virtual void sendServerQuery(const QString&) {}
virtual void sendAtcQuery(const QString&) {}
virtual void sendAtisQuery(const QString&) {}
virtual void sendNameQuery(const QString&) {}
virtual void sendCapabilitiesQuery(const QString&) {}
virtual void replyToFreqQuery(const QString&, const BlackMisc::PhysicalQuantities::CFrequency&) {}
virtual void replyToNameQuery(const QString&, const QString&) {}
virtual void requestPlaneInfo(const QString&) {}
virtual void sendPlaneInfo(const QString&, const QString&, const QString&, const QString&) {}
virtual void ping(const QString&) {}
virtual void requestMetar(const QString&) {}
virtual void requestWeatherData(const QString&) {}
};
} //namespace BlackCore
#endif //BLACKCORE_NETWORK_H

View File

@@ -0,0 +1,576 @@
/* Copyright (C) 2013 VATSIM Community / authors
* 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 "network_vatlib.h"
#include <vector>
#include <exception>
#include <type_traits>
static_assert(! std::is_abstract<BlackCore::NetworkVatlib>::value, "Must implement all pure virtuals");
//TODO just placeholders to allow this to compile
#define CLIENT_NAME_VERSION "BlackBox 0.1"
#define CLIENT_VERSION_MAJOR 0
#define CLIENT_VERSION_MINOR 1
#define CLIENT_SIMULATOR_NAME "None"
#define CLIENT_PUBLIC_ID 0
#define CLIENT_PRIVATE_KEY ""
namespace BlackCore
{
using namespace BlackMisc::PhysicalQuantities;
using namespace BlackMisc::Geo;
void exceptionDispatcher(const char* caller);
NetworkVatlib::NetworkVatlib()
: m_net(Create_Cvatlib_Network()),
m_status(Cvatlib_Network::connStatus_Idle),
m_fsdTextCodec(QTextCodec::codecForName("latin1"))
{
try
{
connect(this, SIGNAL(terminate()), this, SLOT(terminateConnection()), Qt::QueuedConnection);
Q_ASSERT_X(m_fsdTextCodec, "NetworkVatlib", "Missing default wire text encoding");
//TODO reinit m_fsdTextCodec from WireTextEncoding config setting if present
QString capabilities;
capabilities += m_net->capability_AtcInfo;
capabilities += "=1:";
capabilities += m_net->capability_InterimPos;
capabilities += "=1:";
capabilities += m_net->capability_ModelDesc;
capabilities += "=1";
m_net->CreateNetworkSession(CLIENT_NAME_VERSION, CLIENT_VERSION_MAJOR, CLIENT_VERSION_MINOR,
CLIENT_SIMULATOR_NAME, CLIENT_PUBLIC_ID, CLIENT_PRIVATE_KEY, toFSD(capabilities));
m_net->InstallOnConnectionStatusChangedEvent(onConnectionStatusChanged, this);
m_net->InstallOnTextMessageReceivedEvent(onTextMessageReceived, this);
m_net->InstallOnRadioMessageReceivedEvent(onRadioMessageReceived, this);
m_net->InstallOnPilotDisconnectedEvent(onPilotDisconnected, this);
m_net->InstallOnControllerDisconnectedEvent(onControllerDisconnected, this);
m_net->InstallOnPilotPositionUpdateEvent(onPilotPositionUpdate, this);
m_net->InstallOnInterimPilotPositionUpdateEvent(onInterimPilotPositionUpdate, this);
m_net->InstallOnAtcPositionUpdateEvent(onAtcPositionUpdate, this);
m_net->InstallOnKickedEvent(onKicked, this);
m_net->InstallOnPongEvent(onPong, this);
m_net->InstallOnMetarReceivedEvent(onMetarReceived, this);
m_net->InstallOnInfoQueryRequestReceivedEvent(onInfoQueryRequestReceived, this);
m_net->InstallOnInfoQueryReplyReceivedEvent(onInfoQueryReplyReceived, this);
m_net->InstallOnCapabilitiesReplyReceivedEvent(onCapabilitiesReplyReceived, this);
m_net->InstallOnAtisReplyReceivedEvent(onAtisReplyReceived, this);
m_net->InstallOnTemperatureDataReceivedEvent(onTemperatureDataReceived, this);
m_net->InstallOnErrorReceivedEvent(onErrorReceived, this);
m_net->InstallOnWindDataReceivedEvent(onWindDataReceived, this);
m_net->InstallOnCloudDataReceivedEvent(onCloudDataReceived, this);
m_net->InstallOnPilotInfoRequestReceivedEvent(onPilotInfoRequestReceived, this);
m_net->InstallOnPilotInfoReceivedEvent(onPilotInfoReceived, this);
m_timer.start(c_updateIntervalMillisecs, this);
}
catch (...) { exceptionDispatcher(Q_FUNC_INFO); }
}
NetworkVatlib::~NetworkVatlib()
{
m_timer.stop();
try
{
if (m_net->IsNetworkConnected())
{
m_net->LogoffAndDisconnect(0);
}
}
catch (...) { exceptionDispatcher(Q_FUNC_INFO); }
try
{
m_net->DestroyNetworkSession();
}
catch (...) { exceptionDispatcher(Q_FUNC_INFO); }
}
void NetworkVatlib::timerEvent(QTimerEvent*)
{
try
{
if (m_net->IsValid() && m_net->IsSessionExists())
{
m_net->DoProcessing();
}
}
catch (...) { exceptionDispatcher(Q_FUNC_INFO); }
}
QByteArray NetworkVatlib::toFSD(QString qstr) const
{
return m_fsdTextCodec->fromUnicode(qstr);
}
QString NetworkVatlib::fromFSD(const char* cstr) const
{
return m_fsdTextCodec->toUnicode(cstr);
}
void exceptionDispatcher(const char* caller)
{
try
{
throw;
}
catch (const NetworkNotConnectedException& e)
{
// this could be caused by a race condition during normal operation, so not an error
qDebug() << "NetworkNotConnectedException caught in " << caller << "\n" << e.what();
}
catch (const VatlibException& e)
{
qFatal("VatlibException caught in %s\n%s", caller, e.what());
}
catch (const std::exception& e)
{
qFatal("std::exception caught in %s\n%s", caller, e.what());
}
catch (...)
{
qFatal("Unknown exception caught in %s", caller);
}
}
/********************************** * * * * * * * * * * * * * * * * * * * ************************************/
/********************************** INetwork slots ************************************/
/********************************** * * * * * * * * * * * * * * * * * * * ************************************/
void NetworkVatlib::setServerDetails(const QString& host, quint16 port)
{
Q_ASSERT_X(isDisconnected(), "NetworkVatlib", "Can't change server details while still connected");
m_serverHost = host;
m_serverPort = port;
}
void NetworkVatlib::setUserCredentials(const QString& username, const QString& password)
{
Q_ASSERT_X(isDisconnected(), "NetworkVatlib", "Can't change login details while still connected");
m_username = username;
m_password = password;
}
void NetworkVatlib::setCallsign(const QString& callsign)
{
Q_ASSERT_X(isDisconnected(), "NetworkVatlib", "Can't change callsign while still connected");
m_callsign = toFSD(callsign);
}
void NetworkVatlib::setRealName(const QString& name)
{
Q_ASSERT_X(isDisconnected(), "NetworkVatlib", "Can't change name while still connected");
m_realname = toFSD(name);
}
void NetworkVatlib::initiateConnection()
{
Q_ASSERT_X(isDisconnected(), "NetworkVatlib", "Can't connect while still connected");
try
{
m_status = Cvatlib_Network::connStatus_Connecting; //paranoia
Cvatlib_Network::PilotConnectionInfo info;
info.callsign = m_callsign.data();
info.name = m_realname.data();
info.rating = Cvatlib_Network::pilotRating_Student; //TODO
info.sim = Cvatlib_Network::simType_XPlane; //TODO
m_net->SetPilotLoginInfo(toFSD(m_serverHost).data(), m_serverPort,
toFSD(m_username).data(), toFSD(m_password).data(), info);
m_net->ConnectAndLogon();
}
catch (...)
{
m_status = Cvatlib_Network::connStatus_Idle;
exceptionDispatcher(Q_FUNC_INFO);
}
}
void NetworkVatlib::terminateConnection()
{
try
{
m_net->LogoffAndDisconnect(c_logoffTimeoutSeconds);
}
catch (...) { exceptionDispatcher(Q_FUNC_INFO); }
}
void NetworkVatlib::sendPrivateTextMessage(const QString& callsign, const QString& msg)
{
try
{
m_net->SendPrivateTextMessage(toFSD(callsign), toFSD(msg));
}
catch (...) { exceptionDispatcher(Q_FUNC_INFO); }
}
void NetworkVatlib::sendRadioTextMessage(const QVector<CFrequency>& freqs, const QString& msg)
{
try
{
std::vector<INT> freqsVec;
for (int i = 0; i < freqs.size(); ++i)
{
freqsVec.push_back(freqs[i].value(CFrequencyUnit::kHz()));
}
m_net->SendRadioTextMessage(freqsVec.size(), freqsVec.data(), toFSD(msg));
}
catch (...) { exceptionDispatcher(Q_FUNC_INFO); }
}
void NetworkVatlib::sendIpQuery()
{
try
{
m_net->SendInfoQuery(Cvatlib_Network::infoQuery_IP, "SERVER");
}
catch (...) { exceptionDispatcher(Q_FUNC_INFO); }
}
void NetworkVatlib::sendFreqQuery(const QString& callsign)
{
try
{
m_net->SendInfoQuery(Cvatlib_Network::infoQuery_Freq, toFSD(callsign));
}
catch (...) { exceptionDispatcher(Q_FUNC_INFO); }
}
void NetworkVatlib::sendServerQuery(const QString& callsign)
{
try
{
m_net->SendInfoQuery(Cvatlib_Network::infoQuery_Server, toFSD(callsign));
}
catch (...) { exceptionDispatcher(Q_FUNC_INFO); }
}
void NetworkVatlib::sendAtcQuery(const QString& callsign)
{
try
{
m_net->SendInfoQuery(Cvatlib_Network::infoQuery_ATC, toFSD(callsign));
}
catch (...) { exceptionDispatcher(Q_FUNC_INFO); }
}
void NetworkVatlib::sendAtisQuery(const QString& callsign)
{
try
{
m_net->SendInfoQuery(Cvatlib_Network::infoQuery_ATIS, toFSD(callsign));
}
catch (...) { exceptionDispatcher(Q_FUNC_INFO); }
}
void NetworkVatlib::sendNameQuery(const QString& callsign)
{
try
{
m_net->SendInfoQuery(Cvatlib_Network::infoQuery_Name, toFSD(callsign));
}
catch (...) { exceptionDispatcher(Q_FUNC_INFO); }
}
void NetworkVatlib::sendCapabilitiesQuery(const QString& callsign)
{
try
{
m_net->SendInfoQuery(Cvatlib_Network::infoQuery_Capabilities, toFSD(callsign));
}
catch (...) { exceptionDispatcher(Q_FUNC_INFO); }
}
void NetworkVatlib::replyToFreqQuery(const QString& callsign, const BlackMisc::PhysicalQuantities::CFrequency& freq)
{
try
{
CFrequency freqCopy = freq;
freqCopy.switchUnit(CFrequencyUnit::MHz());
m_net->ReplyToInfoQuery(Cvatlib_Network::infoQuery_Freq, toFSD(callsign), toFSD(freqCopy.unitValueToQStringRounded(6)));
}
catch (...) { exceptionDispatcher(Q_FUNC_INFO); }
}
void NetworkVatlib::replyToNameQuery(const QString& callsign, const QString& realname)
{
try
{
m_net->ReplyToInfoQuery(Cvatlib_Network::infoQuery_Name, toFSD(callsign), toFSD(realname));
}
catch (...) { exceptionDispatcher(Q_FUNC_INFO); }
}
void NetworkVatlib::requestPlaneInfo(const QString& callsign)
{
try
{
m_net->RequestPlaneInfo(toFSD(callsign));
}
catch (...) { exceptionDispatcher(Q_FUNC_INFO); }
}
void NetworkVatlib::sendPlaneInfo(const QString& callsign, const QString& acTypeICAO, const QString& airlineICAO, const QString& livery)
{
try
{
const QByteArray acTypeICAObytes = toFSD(acTypeICAO);
const QByteArray airlineICAObytes = toFSD(airlineICAO);
const QByteArray liverybytes = toFSD(livery);
std::vector<const char*> keysValues;
if (! acTypeICAO.isEmpty())
{
keysValues.push_back(m_net->acinfo_Equipment);
keysValues.push_back(acTypeICAObytes);
}
if (! airlineICAO.isEmpty())
{
keysValues.push_back(m_net->acinfo_Airline);
keysValues.push_back(airlineICAObytes);
}
if (! livery.isEmpty())
{
keysValues.push_back(m_net->acinfo_Livery);
keysValues.push_back(liverybytes);
}
keysValues.push_back(0);
m_net->SendPlaneInfo(toFSD(callsign), keysValues.data());
}
catch (...) { exceptionDispatcher(Q_FUNC_INFO); }
}
void NetworkVatlib::ping(const QString& callsign)
{
try
{
m_net->PingUser(toFSD(callsign));
}
catch (...) { exceptionDispatcher(Q_FUNC_INFO); }
}
void NetworkVatlib::requestMetar(const QString& airportICAO)
{
try
{
m_net->RequestMetar(toFSD(airportICAO));
}
catch (...) { exceptionDispatcher(Q_FUNC_INFO); }
}
void NetworkVatlib::requestWeatherData(const QString& airportICAO)
{
try
{
m_net->RequestWeatherData(toFSD(airportICAO));
}
catch (...) { exceptionDispatcher(Q_FUNC_INFO); }
}
/********************************** * * * * * * * * * * * * * * * * * * * ************************************/
/********************************** shimlib callbacks ************************************/
/********************************** * * * * * * * * * * * * * * * * * * * ************************************/
NetworkVatlib* cbvar_cast(void* cbvar)
{
return static_cast<NetworkVatlib*>(cbvar);
}
void NetworkVatlib::onConnectionStatusChanged(Cvatlib_Network*, Cvatlib_Network::connStatus, Cvatlib_Network::connStatus newStatus, void* cbvar)
{
cbvar_cast(cbvar)->m_status = newStatus;
switch (newStatus)
{
case Cvatlib_Network::connStatus_Idle: emit cbvar_cast(cbvar)->connectionStatusIdle(); break;
case Cvatlib_Network::connStatus_Connecting: emit cbvar_cast(cbvar)->connectionStatusConnecting(); break;
case Cvatlib_Network::connStatus_Connected: emit cbvar_cast(cbvar)->connectionStatusConnected(); break;
case Cvatlib_Network::connStatus_Disconnected: emit cbvar_cast(cbvar)->connectionStatusDisconnected(); break;
case Cvatlib_Network::connStatus_Error: emit cbvar_cast(cbvar)->connectionStatusError(); break;
}
}
void NetworkVatlib::onTextMessageReceived(Cvatlib_Network*, const char* from, const char* to, const char* msg, void* cbvar)
{
emit cbvar_cast(cbvar)->privateTextMessageReceived(cbvar_cast(cbvar)->fromFSD(from), cbvar_cast(cbvar)->fromFSD(to), cbvar_cast(cbvar)->fromFSD(msg));
}
void NetworkVatlib::onRadioMessageReceived(Cvatlib_Network*, const char* from, INT numFreq, INT* freqList, const char* msg, void* cbvar)
{
QVector<CFrequency> freqs;
for (int i = 0; i < numFreq; ++i)
{
freqs.push_back(CFrequency(freqList[i], CFrequencyUnit::kHz()));
}
emit cbvar_cast(cbvar)->radioTextMessageReceived(cbvar_cast(cbvar)->fromFSD(from), cbvar_cast(cbvar)->fromFSD(msg), freqs);
}
void NetworkVatlib::onPilotDisconnected(Cvatlib_Network*, const char* callsign, void* cbvar)
{
emit cbvar_cast(cbvar)->pilotDisconnected(cbvar_cast(cbvar)->fromFSD(callsign));
}
void NetworkVatlib::onControllerDisconnected(Cvatlib_Network*, const char* callsign, void* cbvar)
{
emit cbvar_cast(cbvar)->atcDisconnected(cbvar_cast(cbvar)->fromFSD(callsign));
}
void NetworkVatlib::onPilotPositionUpdate(Cvatlib_Network*, const char* callsign, Cvatlib_Network::PilotPosUpdate pos, void* cbvar)
{
//TODO
}
void NetworkVatlib::onInterimPilotPositionUpdate(Cvatlib_Network*, const char* callsign, Cvatlib_Network::PilotPosUpdate pos, void* cbvar)
{
//TODO
}
void NetworkVatlib::onAtcPositionUpdate(Cvatlib_Network*, const char* callsign, Cvatlib_Network::ATCPosUpdate pos, void* cbvar)
{
emit cbvar_cast(cbvar)->atcPositionUpdate(cbvar_cast(cbvar)->fromFSD(callsign), CFrequency(pos.frequency, CFrequencyUnit::kHz()),
CCoordinateGeodetic(pos.lat, pos.lon, 0), CLength(pos.visibleRange, CLengthUnit::NM()));
}
void NetworkVatlib::onKicked(Cvatlib_Network*, const char* reason, void* cbvar)
{
emit cbvar_cast(cbvar)->kicked(cbvar_cast(cbvar)->fromFSD(reason));
}
void NetworkVatlib::onPong(Cvatlib_Network*, const char* callsign, INT elapsedTime, void* cbvar)
{
emit cbvar_cast(cbvar)->pong(cbvar_cast(cbvar)->fromFSD(callsign), CTime(elapsedTime, CTimeUnit::s()));
}
void NetworkVatlib::onMetarReceived(Cvatlib_Network*, const char* data, void* cbvar)
{
emit cbvar_cast(cbvar)->metarReceived(cbvar_cast(cbvar)->fromFSD(data));
}
void NetworkVatlib::onInfoQueryRequestReceived(Cvatlib_Network*, const char* callsign, Cvatlib_Network::infoQuery type, const char*, void* cbvar)
{
switch (type)
{
case Cvatlib_Network::infoQuery_Freq: emit cbvar_cast(cbvar)->freqQueryRequestReceived(cbvar_cast(cbvar)->fromFSD(callsign)); break;
case Cvatlib_Network::infoQuery_Name: emit cbvar_cast(cbvar)->nameQueryRequestReceived(cbvar_cast(cbvar)->fromFSD(callsign)); break;
}
}
void NetworkVatlib::onInfoQueryReplyReceived(Cvatlib_Network*, const char* callsign, Cvatlib_Network::infoQuery type, const char* data, const char* data2, void* cbvar)
{
switch (type)
{
case Cvatlib_Network::infoQuery_Freq: emit cbvar_cast(cbvar)->freqQueryReplyReceived(cbvar_cast(cbvar)->fromFSD(callsign), CFrequency(cbvar_cast(cbvar)->fromFSD(data).toFloat(), CFrequencyUnit::MHz())); break;
case Cvatlib_Network::infoQuery_Server: emit cbvar_cast(cbvar)->serverQueryReplyReceived(cbvar_cast(cbvar)->fromFSD(callsign), cbvar_cast(cbvar)->fromFSD(data)); break;
case Cvatlib_Network::infoQuery_ATC: emit cbvar_cast(cbvar)->atcQueryReplyReceived(cbvar_cast(cbvar)->fromFSD(data2), *data == 'Y'); break;
case Cvatlib_Network::infoQuery_Name: emit cbvar_cast(cbvar)->nameQueryReplyReceived(cbvar_cast(cbvar)->fromFSD(callsign), cbvar_cast(cbvar)->fromFSD(data)); break;
case Cvatlib_Network::infoQuery_IP: emit cbvar_cast(cbvar)->ipQueryReplyReceived(cbvar_cast(cbvar)->fromFSD(data)); break;
}
}
void NetworkVatlib::onCapabilitiesReplyReceived(Cvatlib_Network* net, const char* callsign, const char** keysValues, void* cbvar)
{
quint32 flags = 0;
while (*keysValues)
{
const char* key = keysValues[0];
const char* value = keysValues[1];
if (key == net->capability_AtcInfo) { flags |= AcceptsAtisResponses; }
else if (key == net->capability_InterimPos) { flags |= SupportsInterimPosUpdates; }
else if (key == net->capability_ModelDesc) { flags |= SupportsModelDescriptions; }
keysValues += 2;
}
emit cbvar_cast(cbvar)->capabilitiesQueryReplyReceived(cbvar_cast(cbvar)->fromFSD(callsign), flags);
}
void NetworkVatlib::onAtisReplyReceived(Cvatlib_Network*, const char* callsign, Cvatlib_Network::atisLineType, const char* data, void* cbvar)
{
emit cbvar_cast(cbvar)->atisQueryReplyReceived(cbvar_cast(cbvar)->fromFSD(callsign), cbvar_cast(cbvar)->fromFSD(data));
}
void NetworkVatlib::onTemperatureDataReceived(Cvatlib_Network*, Cvatlib_Network::TempLayer layers[4], INT pressure, void* cbvar)
{
//TODO
}
void NetworkVatlib::onErrorReceived(Cvatlib_Network*, Cvatlib_Network::error type, const char* msg, const char* data, void* cbvar)
{
switch (type)
{
case Cvatlib_Network::error_CallsignTaken: qCritical() << "The requested callsign is already taken"; goto terminate;
case Cvatlib_Network::error_CallsignInvalid: qCritical() << "The requested callsign is not valid"; goto terminate;
case Cvatlib_Network::error_CIDPasswdInvalid: qCritical() << "Wrong user ID or password"; goto terminate;
case Cvatlib_Network::error_ProtoVersion: qCritical() << "This server does not support our protocol version"; goto terminate;
case Cvatlib_Network::error_LevelTooHigh: qCritical() << "You are not authorized to use the requested pilot rating"; goto terminate;
case Cvatlib_Network::error_ServerFull: qCritical() << "The server is full"; goto terminate;
case Cvatlib_Network::error_CIDSuspended: qCritical() << "Your user account is suspended"; goto terminate;
case Cvatlib_Network::error_InvalidPosition: qCritical() << "You are not authorized to use the requested pilot rating"; goto terminate;
case Cvatlib_Network::error_SoftwareNotAuthorized: qCritical() << "This client software has not been authorized for use on this network"; goto terminate;
case Cvatlib_Network::error_Ok: break;
case Cvatlib_Network::error_Syntax: qWarning() << "Malformed packet: Syntax error: %s" << cbvar_cast(cbvar)->fromFSD(data); break;
case Cvatlib_Network::error_SourceInvalid: qDebug() << "Server: source invalid (" << cbvar_cast(cbvar)->fromFSD(data); break;
case Cvatlib_Network::error_CallsignNotExists: qDebug() << "Shim lib: " << cbvar_cast(cbvar)->fromFSD(msg) << " (" << cbvar_cast(cbvar)->fromFSD(data) << ")"; break;
case Cvatlib_Network::error_NoFP: qDebug() << "Server: no flight plan"; break;
case Cvatlib_Network::error_NoWeather: qDebug() << "Server: requested weather profile does not exist"; break;
// we have no idea what these mean
case Cvatlib_Network::error_Registered:
case Cvatlib_Network::error_InvalidControl: qWarning() << "Server: " << cbvar_cast(cbvar)->fromFSD(msg); break;
default: qFatal("VATSIM shim library: %s (error %d)", cbvar_cast(cbvar)->fromFSD(msg), type); goto terminate;
}
return;
terminate:
emit cbvar_cast(cbvar)->terminate();
}
void NetworkVatlib::onWindDataReceived(Cvatlib_Network*, Cvatlib_Network::WindLayer layers[4], void* cbvar)
{
//TODO
}
void NetworkVatlib::onCloudDataReceived(Cvatlib_Network*, Cvatlib_Network::CloudLayer layers[2], Cvatlib_Network::StormLayer storm, float vis, void* cbvar)
{
//TODO
}
void NetworkVatlib::onPilotInfoRequestReceived(Cvatlib_Network*, const char* callsign, void* cbvar)
{
emit cbvar_cast(cbvar)->planeInfoRequestReceived(cbvar_cast(cbvar)->fromFSD(callsign));
}
void NetworkVatlib::onPilotInfoReceived(Cvatlib_Network* net, const char* callsign, const char** keysValues, void* cbvar)
{
const char* acTypeICAO;
const char* airlineICAO;
const char* livery;
while (*keysValues)
{
QString key (*keysValues);
keysValues++;
if (key == net->acinfo_Equipment) { acTypeICAO = *keysValues; }
else if (key == net->acinfo_Airline) { airlineICAO = *keysValues; }
else if (key == net->acinfo_Livery) { livery = *keysValues; }
keysValues++;
}
emit cbvar_cast(cbvar)->planeInfoReceived(cbvar_cast(cbvar)->fromFSD(callsign), cbvar_cast(cbvar)->fromFSD(acTypeICAO),
cbvar_cast(cbvar)->fromFSD(airlineICAO), cbvar_cast(cbvar)->fromFSD(livery));
}
} //namespace BlackCore

View File

@@ -0,0 +1,109 @@
/* Copyright (C) 2013 VATSIM Community / authors
* 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/. */
/*!
\file
*/
#ifndef BLACKCORE_NETWORK_VATLIB_H
#define BLACKCORE_NETWORK_VATLIB_H
#include "network.h"
#include "../../vatlib/vatlib.h"
#include <QScopedPointer>
#include <QBasicTimer>
#include <QTextCodec>
#include <QByteArray>
namespace BlackCore
{
class NetworkVatlib : public INetwork
{
Q_OBJECT;
public:
NetworkVatlib();
virtual ~NetworkVatlib();
protected: //QObject overrides
virtual void timerEvent(QTimerEvent*);
public: //INetwork slots overrides
virtual void setServerDetails(const QString& hostname, quint16 port);
virtual void setUserCredentials(const QString& username, const QString& password);
virtual void setCallsign(const QString& callsign);
virtual void setRealName(const QString& name);
virtual void initiateConnection();
virtual void terminateConnection();
virtual void sendPrivateTextMessage(const QString& callsign, const QString& msg);
virtual void sendRadioTextMessage(const QVector<BlackMisc::PhysicalQuantities::CFrequency>& freqs, const QString& msg);
virtual void sendIpQuery();
virtual void sendFreqQuery(const QString& callsign);
virtual void sendServerQuery(const QString& callsign);
virtual void sendAtcQuery(const QString& callsign);
virtual void sendAtisQuery(const QString& callsign);
virtual void sendNameQuery(const QString& callsign);
virtual void sendCapabilitiesQuery(const QString& callsign);
virtual void replyToFreqQuery(const QString& callsign, const BlackMisc::PhysicalQuantities::CFrequency& freq);
virtual void replyToNameQuery(const QString& callsign, const QString& realname);
virtual void requestPlaneInfo(const QString& callsign);
virtual void sendPlaneInfo(const QString& callsign, const QString& acTypeICAO, const QString& airlineICAO, const QString& livery);
virtual void ping(const QString& callsign);
virtual void requestMetar(const QString& airportICAO);
virtual void requestWeatherData(const QString& airportICAO);
private: //shimlib callbacks
static void onConnectionStatusChanged(Cvatlib_Network*, Cvatlib_Network::connStatus oldStatus, Cvatlib_Network::connStatus newStatus, void* cbvar);
static void onTextMessageReceived(Cvatlib_Network*, const char* from, const char* to, const char* msg, void* cbvar);
static void onRadioMessageReceived(Cvatlib_Network*, const char* from, INT numFreq, INT* freqList, const char* msg, void* cbvar);
static void onPilotDisconnected(Cvatlib_Network*, const char* callsign, void* cbvar);
static void onControllerDisconnected(Cvatlib_Network*, const char* callsign, void* cbvar);
static void onPilotPositionUpdate(Cvatlib_Network*, const char* callsign, Cvatlib_Network::PilotPosUpdate pos, void* cbvar);
static void onInterimPilotPositionUpdate(Cvatlib_Network*, const char* callsign, Cvatlib_Network::PilotPosUpdate pos, void* cbvar);
static void onAtcPositionUpdate(Cvatlib_Network*, const char* callsign, Cvatlib_Network::ATCPosUpdate pos, void* cbvar);
static void onKicked(Cvatlib_Network*, const char* reason, void* cbvar);
static void onPong(Cvatlib_Network*, const char* callsign, INT elapsedTime, void* cbvar);
static void onMetarReceived(Cvatlib_Network*, const char* data, void* cbvar);
static void onInfoQueryRequestReceived(Cvatlib_Network*, const char* callsign, Cvatlib_Network::infoQuery type, const char* data, void* cbvar);
static void onInfoQueryReplyReceived(Cvatlib_Network*, const char* callsign, Cvatlib_Network::infoQuery type, const char* data, const char* data2, void* cbvar);
static void onCapabilitiesReplyReceived(Cvatlib_Network*, const char* callsign, const char** keysValues, void* cbvar);
static void onAtisReplyReceived(Cvatlib_Network*, const char* callsign, Cvatlib_Network::atisLineType type, const char* data, void* cbvar);
static void onTemperatureDataReceived(Cvatlib_Network*, Cvatlib_Network::TempLayer layers[4], INT pressure, void* cbvar);
static void onErrorReceived(Cvatlib_Network*, Cvatlib_Network::error type, const char* msg, const char* data, void* cbvar);
static void onWindDataReceived(Cvatlib_Network*, Cvatlib_Network::WindLayer layers[4], void* cbvar);
static void onCloudDataReceived(Cvatlib_Network*, Cvatlib_Network::CloudLayer layers[2], Cvatlib_Network::StormLayer storm, float vis, void* cbvar);
static void onPilotInfoRequestReceived(Cvatlib_Network*, const char* callsign, void* cbvar);
static void onPilotInfoReceived(Cvatlib_Network*, const char* callsign, const char** keysValues, void* cbvar);
private:
QByteArray toFSD(QString qstr) const;
QString fromFSD(const char* cstr) const;
bool isDisconnected() const { return m_status == Cvatlib_Network::connStatus_Idle || m_status == Cvatlib_Network::connStatus_Disconnected; }
signals:
void terminate();
private:
QScopedPointer<Cvatlib_Network> m_net;
Cvatlib_Network::connStatus m_status;
QBasicTimer m_timer;
static int const c_updateIntervalMillisecs = 100;
static int const c_logoffTimeoutSeconds = 5;
QString m_serverHost;
quint16 m_serverPort;
QString m_username;
QString m_password;
QByteArray m_callsign;
QByteArray m_realname;
QTextCodec* m_fsdTextCodec;
};
} //namespace BlackCore
#endif //BLACKCORE_NETWORK_VATLIB_H

111
src/blackmisc/atclist.h Normal file
View File

@@ -0,0 +1,111 @@
/* Copyright (C) 2013 VATSIM Community / authors
* 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/. */
/*!
\file
*/
#ifndef BLACKMISC_ATCLIST_H
#define BLACKMISC_ATCLIST_H
#include "pqfrequency.h"
#include "pqlength.h"
#include "coordinategeodetic.h"
#include "context.h"
#include <QObject>
#include <QString>
#include <QMap>
namespace BlackMisc
{
/*!
* Value object encapsulating information about an ATC station.
*/
class CAtcListEntry
{
public:
/*!
* Default constructor.
*/
CAtcListEntry() {}
/*!
* Constructor.
*/
CAtcListEntry(const QString &callsign, const BlackMisc::PhysicalQuantities::CFrequency &freq,
const BlackMisc::Geo::CCoordinateGeodetic &pos, const BlackMisc::PhysicalQuantities::CLength &range)
: m_callsign(callsign), m_freq(freq), m_pos(pos), m_range(range)
{}
/*!
* Get callsign.
* \return
*/
const QString &getCallsign() const { return m_callsign; }
/*!
* Get frequency.
* \return
*/
const BlackMisc::PhysicalQuantities::CFrequency &getFrequency() const { return m_freq; }
/*!
* Get the position of the center of the controller's area of visibility.
* \return
*/
const BlackMisc::Geo::CCoordinateGeodetic &getPosition() const { return m_pos; }
/*!
* Get the radius of the controller's area of visibility.
* \return
*/
const BlackMisc::PhysicalQuantities::CLength &getAtcRange() const { return m_range; }
private:
QString m_callsign;
BlackMisc::PhysicalQuantities::CFrequency m_freq;
BlackMisc::Geo::CCoordinateGeodetic m_pos;
BlackMisc::PhysicalQuantities::CLength m_range;
};
/*!
* Value object encapsulating a list of ATC stations.
*/
class CAtcList
{
public:
/*!
* Immutable getter for the internal map.
* \return
*/
const QMap<QString, CAtcListEntry> &constMap() const { return m_map; }
/*!
* Insert an ATC station into the list.
* \param entry
*/
void insert(const CAtcListEntry &entry) { m_map.insert(entry.getCallsign(), entry); }
/*!
* Remove an ATC station from the list.
* \param callsign
*/
void remove(const QString &callsign) { m_map.remove(callsign); }
/*!
* Remove all ATC stations from the list.
*/
void clear() { m_map.clear(); }
private:
QMap<QString, CAtcListEntry> m_map;
};
} //namespace BlackMisc
Q_DECLARE_METATYPE(BlackMisc::CAtcList)
#endif //BLACKMISC_ATCLIST_H

View File

@@ -7,7 +7,7 @@
#define BLACKCORETEST_H
/*!
* @namespace BlackCoreTest
* \namespace BlackCoreTest
* Unit tests for BlackCore. Unit tests do have their own namespace, so
* the regular namespace BlackCore is completely free of unit tests.
* Add any new tests to TestMain::unitMain as shown there.

View File

@@ -5,6 +5,7 @@
#include "testblackcoremain.h"
#include "testinterpolator.h"
#include "testnetmediators.h"
namespace BlackCoreTest
{
@@ -19,6 +20,10 @@ int CBlackCoreTestMain::unitMain(int argc, char *argv[])
CTestInterpolator interpolatorTests;
status |= QTest::qExec(&interpolatorTests, argc, argv);
}
{
CTestNetMediators mediatorTests;
status |= QTest::qExec(&mediatorTests, argc, argv);
}
return status;
}
} // namespace

View File

@@ -0,0 +1,55 @@
/* Copyright (C) 2013 VATSIM Community / contributors
* 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 "testnetmediators.h"
#include "blackmisc/context.h"
#include <QObject>
namespace BlackCoreTest
{
using namespace BlackCore;
using namespace BlackMisc;
using namespace BlackMisc::PhysicalQuantities;
using namespace BlackMisc::Geo;
void CTestNetMediators::initTestCase()
{
BlackMisc::IContext::getInstance().setSingleton<INetwork>(&m_networkDummy);
}
void CTestNetMediators::cleanupTestCase()
{
BlackMisc::IContext::getInstance().releaseSingleton<INetwork>();
}
void CTestNetMediators::atcListManagerTest()
{
CAtcListManager mgr;
AtcListConsumer cons;
QObject::connect(&mgr, &IAtcListManager::listChanged, &cons, &AtcListConsumer::listChanged);
QVERIFY(cons.m_list.constMap().size() == 0);
emit m_networkDummy.atcPositionUpdate("EGLL_TWR", CFrequency(118.7, CFrequencyUnit::MHz()), CCoordinateGeodetic(51.4775, 0.46139, 0), CLength(50, CLengthUnit::m()));
QVERIFY(cons.m_list.constMap().size() == 1);
emit m_networkDummy.atcPositionUpdate("EGLL_GND", CFrequency(121.9, CFrequencyUnit::MHz()), CCoordinateGeodetic(51.4775, 0.46139, 0), CLength(20, CLengthUnit::m()));
QVERIFY(cons.m_list.constMap().size() == 2);
emit m_networkDummy.atcPositionUpdate("EGLL_TWR", CFrequency(118.5, CFrequencyUnit::MHz()), CCoordinateGeodetic(51.4775, 0.46139, 0), CLength(50, CLengthUnit::m()));
QVERIFY(cons.m_list.constMap().size() == 2);
emit m_networkDummy.atcDisconnected("EGLL_TWR");
QVERIFY(cons.m_list.constMap().size() == 1);
emit m_networkDummy.connectionStatusDisconnected();
QVERIFY(cons.m_list.constMap().size() == 0);
emit m_networkDummy.atcPositionUpdate("EGLL_TWR", CFrequency(118.5, CFrequencyUnit::MHz()), CCoordinateGeodetic(51.4775, 0.46139, 0), CLength(50, CLengthUnit::m()));
QVERIFY(cons.m_list.constMap().contains("EGLL_TWR"));
QVERIFY(cons.m_list.constMap()["EGLL_TWR"].getCallsign() == "EGLL_TWR");
QVERIFY(cons.m_list.constMap()["EGLL_TWR"].getFrequency() == CFrequency(118.5, CFrequencyUnit::MHz()));
QVERIFY(cons.m_list.constMap()["EGLL_TWR"].getPosition() == CCoordinateGeodetic(51.4775, 0.46139, 0));
QVERIFY(cons.m_list.constMap()["EGLL_TWR"].getAtcRange() == CLength(50, CLengthUnit::m()));
}
} //namespace BlackCoreTest

View File

@@ -0,0 +1,75 @@
/* Copyright (C) 2013 VATSIM Community / contributors
* 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/. */
#ifndef BLACKCORETEST_TESTNETMEDIATORS_H
#define BLACKCORETEST_TESTNETMEDIATORS_H
#include "blackcore/atclistmgr.h"
#include "blackcoretest.h"
#include "blackcore/network.h"
#include <QtTest/QtTest>
namespace BlackCoreTest
{
/*!
* Network mediator classes tests
*/
class CTestNetMediators : public QObject
{
Q_OBJECT
public:
/*!
* Constructor.
* \param parent
*/
explicit CTestNetMediators(QObject *parent = 0) : QObject(parent) {}
private slots:
/*!
* Called before the first test.
*/
void initTestCase();
/*!
* Test CAtcListManager
*/
void atcListManagerTest();
/*!
* Called after the last test.
*/
void cleanupTestCase();
private:
BlackCore::NetworkDummy m_networkDummy;
};
/*!
* Helper class that connects to CAtcListManager signals
*/
class AtcListConsumer : public QObject
{
Q_OBJECT
public:
//! List is updated by the slot
BlackMisc::CAtcList m_list;
public slots:
/*!
* Slot updates the list
* \param list
*/
void listChanged(const BlackMisc::CAtcList &list)
{
m_list = list;
}
};
} //namespace BlackCoreTest
#endif //BLACKCORETEST_TESTNETMEDIATORS_H