2013-08-17 11:54:16 +02:00
|
|
|
// stl includes
|
|
|
|
#include <stdexcept>
|
2016-08-15 22:32:01 +02:00
|
|
|
#include <cassert>
|
2013-08-17 11:54:16 +02:00
|
|
|
|
|
|
|
// Qt includes
|
|
|
|
#include <QRgb>
|
|
|
|
|
|
|
|
// hyperion-remote includes
|
|
|
|
#include "JsonConnection.h"
|
|
|
|
|
2016-08-28 15:10:43 +02:00
|
|
|
JsonConnection::JsonConnection(const QString & address, bool printJson)
|
2016-07-31 22:21:35 +02:00
|
|
|
: _printJson(printJson)
|
|
|
|
, _socket()
|
2013-08-17 11:54:16 +02:00
|
|
|
{
|
|
|
|
QStringList parts = address.split(":");
|
|
|
|
if (parts.size() != 2)
|
|
|
|
{
|
|
|
|
throw std::runtime_error(QString("Wrong address: unable to parse address (%1)").arg(address).toStdString());
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ok;
|
|
|
|
uint16_t port = parts[1].toUShort(&ok);
|
|
|
|
if (!ok)
|
|
|
|
{
|
|
|
|
throw std::runtime_error(QString("Wrong address: Unable to parse the port number (%1)").arg(parts[1]).toStdString());
|
|
|
|
}
|
|
|
|
|
|
|
|
_socket.connectToHost(parts[0], port);
|
|
|
|
if (!_socket.waitForConnected())
|
|
|
|
{
|
|
|
|
throw std::runtime_error("Unable to connect to host");
|
|
|
|
}
|
|
|
|
|
2016-08-28 15:10:43 +02:00
|
|
|
qDebug() << "Connected to:" << address;
|
2013-08-17 11:54:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
JsonConnection::~JsonConnection()
|
|
|
|
{
|
|
|
|
_socket.close();
|
|
|
|
}
|
|
|
|
|
2013-12-13 00:01:48 +01:00
|
|
|
void JsonConnection::setColor(std::vector<QColor> colors, int priority, int duration)
|
2013-08-17 11:54:16 +02:00
|
|
|
{
|
2013-12-13 00:01:48 +01:00
|
|
|
std::cout << "Set color to " << colors[0].red() << " " << colors[0].green() << " " << colors[0].blue() << (colors.size() > 1 ? " + ..." : "") << std::endl;
|
2013-08-17 11:54:16 +02:00
|
|
|
|
|
|
|
// create command
|
|
|
|
Json::Value command;
|
|
|
|
command["command"] = "color";
|
|
|
|
command["priority"] = priority;
|
|
|
|
Json::Value & rgbValue = command["color"];
|
2013-12-13 00:01:48 +01:00
|
|
|
for (const QColor & color : colors)
|
|
|
|
{
|
|
|
|
rgbValue.append(color.red());
|
|
|
|
rgbValue.append(color.green());
|
|
|
|
rgbValue.append(color.blue());
|
|
|
|
}
|
2013-08-17 11:54:16 +02:00
|
|
|
if (duration > 0)
|
|
|
|
{
|
|
|
|
command["duration"] = duration;
|
|
|
|
}
|
|
|
|
|
|
|
|
// send command message
|
|
|
|
Json::Value reply = sendMessage(command);
|
|
|
|
|
|
|
|
// parse reply message
|
|
|
|
parseReply(reply);
|
|
|
|
}
|
|
|
|
|
2016-08-28 15:10:43 +02:00
|
|
|
void JsonConnection::setImage(QImage &image, int priority, int duration)
|
2013-08-17 11:54:16 +02:00
|
|
|
{
|
|
|
|
std::cout << "Set image has size: " << image.width() << "x" << image.height() << std::endl;
|
|
|
|
|
|
|
|
// ensure the image has RGB888 format
|
|
|
|
image = image.convertToFormat(QImage::Format_ARGB32_Premultiplied);
|
|
|
|
QByteArray binaryImage;
|
|
|
|
binaryImage.reserve(image.width() * image.height() * 3);
|
|
|
|
for (int i = 0; i < image.height(); ++i)
|
|
|
|
{
|
|
|
|
const QRgb * scanline = reinterpret_cast<const QRgb *>(image.scanLine(i));
|
|
|
|
for (int j = 0; j < image.width(); ++j)
|
|
|
|
{
|
|
|
|
binaryImage.append((char) qRed(scanline[j]));
|
|
|
|
binaryImage.append((char) qGreen(scanline[j]));
|
|
|
|
binaryImage.append((char) qBlue(scanline[j]));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
const QByteArray base64Image = binaryImage.toBase64();
|
|
|
|
|
|
|
|
// create command
|
|
|
|
Json::Value command;
|
|
|
|
command["command"] = "image";
|
|
|
|
command["priority"] = priority;
|
2013-08-17 19:20:19 +02:00
|
|
|
command["imagewidth"] = image.width();
|
|
|
|
command["imageheight"] = image.height();
|
2016-08-28 15:10:43 +02:00
|
|
|
command["imagedata"] = base64Image.data();
|
2013-08-17 11:54:16 +02:00
|
|
|
if (duration > 0)
|
|
|
|
{
|
|
|
|
command["duration"] = duration;
|
|
|
|
}
|
|
|
|
|
|
|
|
// send command message
|
|
|
|
Json::Value reply = sendMessage(command);
|
|
|
|
|
|
|
|
// parse reply message
|
|
|
|
parseReply(reply);
|
|
|
|
}
|
|
|
|
|
2016-08-28 15:10:43 +02:00
|
|
|
void JsonConnection::setEffect(const QString &effectName, const QString & effectArgs, int priority, int duration)
|
2013-11-24 16:10:48 +01:00
|
|
|
{
|
2016-08-28 15:10:43 +02:00
|
|
|
qDebug() << "Start effect " << effectName;
|
2013-11-24 16:10:48 +01:00
|
|
|
|
|
|
|
// create command
|
|
|
|
Json::Value command;
|
|
|
|
command["command"] = "effect";
|
|
|
|
command["priority"] = priority;
|
|
|
|
Json::Value & effect = command["effect"];
|
2016-08-28 15:10:43 +02:00
|
|
|
effect["name"] = effectName.toStdString();
|
2013-12-01 14:09:01 +01:00
|
|
|
if (effectArgs.size() > 0)
|
|
|
|
{
|
|
|
|
Json::Reader reader;
|
2016-08-28 15:10:43 +02:00
|
|
|
if (!reader.parse(effectArgs.toStdString(), effect["args"], false))
|
2013-12-01 14:09:01 +01:00
|
|
|
{
|
|
|
|
throw std::runtime_error("Error in effect arguments: " + reader.getFormattedErrorMessages());
|
|
|
|
}
|
|
|
|
}
|
2013-11-24 16:10:48 +01:00
|
|
|
if (duration > 0)
|
|
|
|
{
|
|
|
|
command["duration"] = duration;
|
|
|
|
}
|
|
|
|
|
|
|
|
// send command message
|
|
|
|
Json::Value reply = sendMessage(command);
|
|
|
|
|
|
|
|
// parse reply message
|
|
|
|
parseReply(reply);
|
|
|
|
}
|
2013-08-17 11:54:16 +02:00
|
|
|
|
|
|
|
QString JsonConnection::getServerInfo()
|
|
|
|
{
|
|
|
|
std::cout << "Get server info" << std::endl;
|
|
|
|
|
|
|
|
// create command
|
|
|
|
Json::Value command;
|
|
|
|
command["command"] = "serverinfo";
|
|
|
|
|
|
|
|
// send command message
|
|
|
|
Json::Value reply = sendMessage(command);
|
|
|
|
|
|
|
|
// parse reply message
|
|
|
|
if (parseReply(reply))
|
|
|
|
{
|
|
|
|
if (!reply.isMember("info") || !reply["info"].isObject())
|
|
|
|
{
|
|
|
|
throw std::runtime_error("No info available in result");
|
|
|
|
}
|
|
|
|
|
|
|
|
const Json::Value & info = reply["info"];
|
|
|
|
return QString(info.toStyledString().c_str());
|
|
|
|
}
|
|
|
|
|
|
|
|
return QString();
|
|
|
|
}
|
|
|
|
|
|
|
|
void JsonConnection::clear(int priority)
|
|
|
|
{
|
|
|
|
std::cout << "Clear priority channel " << priority << std::endl;
|
|
|
|
|
|
|
|
// create command
|
|
|
|
Json::Value command;
|
|
|
|
command["command"] = "clear";
|
|
|
|
command["priority"] = priority;
|
|
|
|
|
|
|
|
// send command message
|
|
|
|
Json::Value reply = sendMessage(command);
|
|
|
|
|
|
|
|
// parse reply message
|
|
|
|
parseReply(reply);
|
|
|
|
}
|
|
|
|
|
|
|
|
void JsonConnection::clearAll()
|
|
|
|
{
|
|
|
|
std::cout << "Clear all priority channels" << std::endl;
|
|
|
|
|
|
|
|
// create command
|
|
|
|
Json::Value command;
|
|
|
|
command["command"] = "clearall";
|
|
|
|
|
|
|
|
// send command message
|
|
|
|
Json::Value reply = sendMessage(command);
|
|
|
|
|
|
|
|
// parse reply message
|
|
|
|
parseReply(reply);
|
|
|
|
}
|
|
|
|
|
2016-08-28 15:10:43 +02:00
|
|
|
void JsonConnection::setComponentState(const QString & component, const bool state)
|
2016-08-04 13:10:53 +02:00
|
|
|
{
|
2016-08-28 15:10:43 +02:00
|
|
|
qDebug() << (state ? "Enable" : "Disable") << "Component" << component;
|
2016-08-04 13:10:53 +02:00
|
|
|
|
|
|
|
// create command
|
|
|
|
Json::Value command;
|
|
|
|
command["command"] = "componentstate";
|
|
|
|
Json::Value & parameter = command["componentstate"];
|
2016-08-28 15:10:43 +02:00
|
|
|
parameter["component"] = component.toStdString();
|
2016-08-04 13:10:53 +02:00
|
|
|
parameter["state"] = state;
|
|
|
|
|
|
|
|
// send command message
|
|
|
|
Json::Value reply = sendMessage(command);
|
|
|
|
|
|
|
|
// parse reply message
|
|
|
|
parseReply(reply);
|
|
|
|
}
|
|
|
|
|
2016-07-31 22:21:35 +02:00
|
|
|
void JsonConnection::setSource(int priority)
|
|
|
|
{
|
|
|
|
// create command
|
|
|
|
Json::Value command;
|
|
|
|
command["command"] = "sourceselect";
|
|
|
|
command["priority"] = priority;
|
|
|
|
|
|
|
|
// send command message
|
|
|
|
Json::Value reply = sendMessage(command);
|
|
|
|
|
|
|
|
// parse reply message
|
|
|
|
parseReply(reply);
|
|
|
|
}
|
|
|
|
|
|
|
|
void JsonConnection::setSourceAutoSelect()
|
|
|
|
{
|
|
|
|
// create command
|
|
|
|
Json::Value command;
|
|
|
|
command["command"] = "sourceselect";
|
|
|
|
command["auto"] = true;
|
|
|
|
|
|
|
|
// send command message
|
|
|
|
Json::Value reply = sendMessage(command);
|
|
|
|
|
|
|
|
// parse reply message
|
|
|
|
parseReply(reply);
|
|
|
|
}
|
|
|
|
|
2016-08-15 22:32:01 +02:00
|
|
|
QString JsonConnection::getConfig(std::string type)
|
2016-08-03 22:03:19 +02:00
|
|
|
{
|
2016-08-15 22:32:01 +02:00
|
|
|
assert( type == "schema" || type == "config" );
|
2016-08-03 22:03:19 +02:00
|
|
|
std::cout << "Get configuration file from Hyperion Server" << std::endl;
|
|
|
|
|
|
|
|
// create command
|
|
|
|
Json::Value command;
|
2016-08-15 22:32:01 +02:00
|
|
|
command["command"] = "config";
|
|
|
|
command["subcommand"] = (type == "schema")? "getschema" : "getconfig";
|
2016-08-03 22:03:19 +02:00
|
|
|
|
|
|
|
// send command message
|
|
|
|
Json::Value reply = sendMessage(command);
|
|
|
|
|
|
|
|
// parse reply message
|
|
|
|
if (parseReply(reply))
|
|
|
|
{
|
|
|
|
if (!reply.isMember("result") || !reply["result"].isObject())
|
|
|
|
{
|
|
|
|
throw std::runtime_error("No configuration file available in result");
|
|
|
|
}
|
|
|
|
|
|
|
|
const Json::Value & config = reply["result"];
|
|
|
|
return QString(config.toStyledString().c_str());
|
|
|
|
}
|
|
|
|
|
|
|
|
return QString();
|
|
|
|
}
|
|
|
|
|
2016-10-09 22:22:17 +02:00
|
|
|
void JsonConnection::setConfig(const QString &jsonString)
|
2016-08-14 20:17:12 +02:00
|
|
|
{
|
|
|
|
// create command
|
|
|
|
Json::Value command;
|
2016-08-15 22:32:01 +02:00
|
|
|
command["command"] = "config";
|
|
|
|
command["subcommand"] = "setconfig";
|
|
|
|
|
|
|
|
Json::Value & config = command["config"];
|
2016-08-14 20:17:12 +02:00
|
|
|
if (jsonString.size() > 0)
|
|
|
|
{
|
|
|
|
Json::Reader reader;
|
2016-08-28 15:10:43 +02:00
|
|
|
if (!reader.parse(jsonString.toStdString(), config, false))
|
2016-08-14 20:17:12 +02:00
|
|
|
{
|
|
|
|
throw std::runtime_error("Error in configset arguments: " + reader.getFormattedErrorMessages());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// send command message
|
|
|
|
Json::Value reply = sendMessage(command);
|
|
|
|
|
|
|
|
// parse reply message
|
|
|
|
parseReply(reply);
|
|
|
|
}
|
|
|
|
|
2016-08-28 15:10:43 +02:00
|
|
|
void JsonConnection::setTransform(const QString &transformId,
|
|
|
|
double *saturation,
|
|
|
|
double *value,
|
|
|
|
double *saturationL,
|
|
|
|
double *luminance,
|
|
|
|
double *luminanceMin,
|
|
|
|
QColor threshold,
|
|
|
|
QColor gamma,
|
|
|
|
QColor blacklevel,
|
|
|
|
QColor whitelevel)
|
2013-08-17 11:54:16 +02:00
|
|
|
{
|
|
|
|
std::cout << "Set color transforms" << std::endl;
|
|
|
|
|
|
|
|
// create command
|
|
|
|
Json::Value command;
|
|
|
|
command["command"] = "transform";
|
|
|
|
Json::Value & transform = command["transform"];
|
|
|
|
|
2016-08-28 15:10:43 +02:00
|
|
|
if (!transformId.isNull())
|
2013-11-22 11:48:10 +01:00
|
|
|
{
|
2016-08-28 15:10:43 +02:00
|
|
|
transform["id"] = transformId.toStdString();
|
2013-11-22 11:48:10 +01:00
|
|
|
}
|
|
|
|
|
2013-08-21 21:50:17 +02:00
|
|
|
if (saturation != nullptr)
|
|
|
|
{
|
|
|
|
transform["saturationGain"] = *saturation;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (value != nullptr)
|
|
|
|
{
|
|
|
|
transform["valueGain"] = *value;
|
|
|
|
}
|
2016-03-11 12:30:32 +01:00
|
|
|
|
2016-03-13 13:05:47 +01:00
|
|
|
if (saturationL != nullptr)
|
2016-03-11 12:30:32 +01:00
|
|
|
{
|
|
|
|
transform["saturationLGain"] = *saturationL;
|
|
|
|
}
|
2013-08-21 21:50:17 +02:00
|
|
|
|
2016-03-13 13:05:47 +01:00
|
|
|
if (luminance != nullptr)
|
2016-03-11 12:30:32 +01:00
|
|
|
{
|
|
|
|
transform["luminanceGain"] = *luminance;
|
|
|
|
}
|
2016-05-23 00:00:48 +02:00
|
|
|
|
|
|
|
if (luminanceMin != nullptr)
|
|
|
|
{
|
|
|
|
transform["luminanceMinimum"] = *luminanceMin;
|
|
|
|
}
|
|
|
|
|
2016-08-28 15:10:43 +02:00
|
|
|
if (threshold.isValid())
|
2013-08-17 11:54:16 +02:00
|
|
|
{
|
|
|
|
Json::Value & v = transform["threshold"];
|
2016-08-28 15:10:43 +02:00
|
|
|
v.append(threshold.red());
|
|
|
|
v.append(threshold.green());
|
|
|
|
v.append(threshold.blue());
|
2013-08-17 11:54:16 +02:00
|
|
|
}
|
|
|
|
|
2016-08-28 15:10:43 +02:00
|
|
|
if (gamma.isValid())
|
2013-08-17 11:54:16 +02:00
|
|
|
{
|
|
|
|
Json::Value & v = transform["gamma"];
|
2016-08-28 15:10:43 +02:00
|
|
|
v.append(gamma.red());
|
|
|
|
v.append(gamma.green());
|
|
|
|
v.append(gamma.blue());
|
2013-08-17 11:54:16 +02:00
|
|
|
}
|
|
|
|
|
2016-08-28 15:10:43 +02:00
|
|
|
if (blacklevel.isValid())
|
2013-08-17 11:54:16 +02:00
|
|
|
{
|
|
|
|
Json::Value & v = transform["blacklevel"];
|
2016-08-28 15:10:43 +02:00
|
|
|
v.append(blacklevel.red());
|
|
|
|
v.append(blacklevel.green());
|
|
|
|
v.append(blacklevel.blue());
|
2013-08-17 11:54:16 +02:00
|
|
|
}
|
|
|
|
|
2016-08-28 15:10:43 +02:00
|
|
|
if (whitelevel.isValid())
|
2013-08-17 11:54:16 +02:00
|
|
|
{
|
|
|
|
Json::Value & v = transform["whitelevel"];
|
2016-08-28 15:10:43 +02:00
|
|
|
v.append(whitelevel.red());
|
|
|
|
v.append(whitelevel.green());
|
|
|
|
v.append(whitelevel.blue());
|
2013-08-17 11:54:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// send command message
|
|
|
|
Json::Value reply = sendMessage(command);
|
|
|
|
|
|
|
|
// parse reply message
|
|
|
|
parseReply(reply);
|
|
|
|
}
|
|
|
|
|
2016-08-28 15:10:43 +02:00
|
|
|
void JsonConnection::setAdjustment(const QString &adjustmentId,
|
|
|
|
const QColor & redAdjustment,
|
|
|
|
const QColor & greenAdjustment,
|
|
|
|
const QColor & blueAdjustment)
|
2016-04-02 00:04:11 +02:00
|
|
|
{
|
|
|
|
std::cout << "Set color adjustments" << std::endl;
|
|
|
|
|
|
|
|
// create command
|
|
|
|
Json::Value command;
|
|
|
|
command["command"] = "adjustment";
|
|
|
|
Json::Value & adjust = command["adjustment"];
|
|
|
|
|
2016-08-28 15:10:43 +02:00
|
|
|
if (!adjustmentId.isNull())
|
2016-04-02 00:04:11 +02:00
|
|
|
{
|
2016-08-28 15:10:43 +02:00
|
|
|
adjust["id"] = adjustmentId.toStdString();
|
2016-04-02 00:04:11 +02:00
|
|
|
}
|
|
|
|
|
2016-08-28 15:10:43 +02:00
|
|
|
if (redAdjustment.isValid())
|
2016-04-02 00:04:11 +02:00
|
|
|
{
|
|
|
|
Json::Value & v = adjust["redAdjust"];
|
2016-08-28 15:10:43 +02:00
|
|
|
v.append(redAdjustment.red());
|
|
|
|
v.append(redAdjustment.green());
|
|
|
|
v.append(redAdjustment.blue());
|
2016-04-02 00:04:11 +02:00
|
|
|
}
|
|
|
|
|
2016-08-28 15:10:43 +02:00
|
|
|
if (greenAdjustment.isValid())
|
2016-04-02 00:04:11 +02:00
|
|
|
{
|
|
|
|
Json::Value & v = adjust["greenAdjust"];
|
2016-08-28 15:10:43 +02:00
|
|
|
v.append(greenAdjustment.red());
|
|
|
|
v.append(greenAdjustment.green());
|
|
|
|
v.append(greenAdjustment.blue());
|
2016-04-02 00:04:11 +02:00
|
|
|
}
|
|
|
|
|
2016-08-28 15:10:43 +02:00
|
|
|
if (blueAdjustment.isValid())
|
2016-04-02 00:04:11 +02:00
|
|
|
{
|
|
|
|
Json::Value & v = adjust["blueAdjust"];
|
2016-08-28 15:10:43 +02:00
|
|
|
v.append(blueAdjustment.red());
|
|
|
|
v.append(blueAdjustment.green());
|
|
|
|
v.append(blueAdjustment.blue());
|
2016-04-02 00:04:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// send command message
|
|
|
|
Json::Value reply = sendMessage(command);
|
|
|
|
|
|
|
|
// parse reply message
|
|
|
|
parseReply(reply);
|
|
|
|
}
|
|
|
|
|
2013-08-17 11:54:16 +02:00
|
|
|
Json::Value JsonConnection::sendMessage(const Json::Value & message)
|
|
|
|
{
|
2013-08-17 15:39:29 +02:00
|
|
|
// serialize message (FastWriter already appends a newline)
|
|
|
|
std::string serializedMessage = Json::FastWriter().write(message);
|
|
|
|
|
2013-08-17 11:54:16 +02:00
|
|
|
// print command if requested
|
|
|
|
if (_printJson)
|
|
|
|
{
|
2013-08-17 15:39:29 +02:00
|
|
|
std::cout << "Command: " << serializedMessage;
|
2013-08-17 11:54:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// write message
|
|
|
|
_socket.write(serializedMessage.c_str());
|
|
|
|
if (!_socket.waitForBytesWritten())
|
|
|
|
{
|
|
|
|
throw std::runtime_error("Error while writing data to host");
|
|
|
|
}
|
|
|
|
|
|
|
|
// read reply data
|
|
|
|
QByteArray serializedReply;
|
|
|
|
while (!serializedReply.contains('\n'))
|
|
|
|
{
|
|
|
|
// receive reply
|
|
|
|
if (!_socket.waitForReadyRead())
|
|
|
|
{
|
|
|
|
throw std::runtime_error("Error while reading data from host");
|
|
|
|
}
|
|
|
|
|
|
|
|
serializedReply += _socket.readAll();
|
|
|
|
}
|
|
|
|
int bytes = serializedReply.indexOf('\n') + 1; // Find the end of message
|
|
|
|
|
2013-08-17 15:39:29 +02:00
|
|
|
// print reply if requested
|
|
|
|
if (_printJson)
|
|
|
|
{
|
|
|
|
std::cout << "Reply: " << std::string(serializedReply.data(), bytes);
|
|
|
|
}
|
|
|
|
|
2013-08-17 11:54:16 +02:00
|
|
|
// parse reply data
|
|
|
|
Json::Reader jsonReader;
|
|
|
|
Json::Value reply;
|
|
|
|
if (!jsonReader.parse(serializedReply.constData(), serializedReply.constData() + bytes, reply))
|
|
|
|
{
|
|
|
|
throw std::runtime_error("Error while parsing reply: invalid json");
|
|
|
|
}
|
|
|
|
|
|
|
|
return reply;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool JsonConnection::parseReply(const Json::Value &reply)
|
|
|
|
{
|
|
|
|
bool success = false;
|
|
|
|
std::string reason = "No error info";
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
success = reply.get("success", false).asBool();
|
|
|
|
if (!success)
|
|
|
|
reason = reply.get("error", reason).asString();
|
|
|
|
}
|
|
|
|
catch (const std::runtime_error &)
|
|
|
|
{
|
2013-08-17 15:39:29 +02:00
|
|
|
// Some json parsing error: ignore and set parsing error
|
2013-08-17 11:54:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!success)
|
|
|
|
{
|
2013-08-18 12:02:17 +02:00
|
|
|
throw std::runtime_error("Error: " + reason);
|
2013-08-17 11:54:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return success;
|
|
|
|
}
|