/** * Communication with A/V system - fm server * $Id$ * $HeadURL$ * $Author$ */ #include "av_socket.h" #include namespace { void disconnectAndWait(QAbstractSocket *socket) { Q_ASSERT(socket); socket->disconnectFromHost(); if (socket->state() == QAbstractSocket::UnconnectedState) return; socket->waitForDisconnected(); } } // anonymous namespace namespace AudioVideoManagement { AVSocket::AVSocket(const QString &avsServerHost, quint16 avsServerPort, NGL::INGLLogger &logger, NGL::INGLLogger &loggerIO, QObject *parent) : QObject(parent) , m_bSuccessfullyLoggedIn(false) , m_bErrorInTcpComWarnedOnce(false) , m_avsSocket(nullptr) , m_avsServerHost(avsServerHost) , m_avsServerPort(avsServerPort) , m_rcpLoginTimer(new QTimer(this)) , m_reconnectTimer(new QTimer(this)) , m_logger(logger) , m_loggerIO(loggerIO) { m_rcpLoginTimer->setSingleShot(true); m_rcpLoginTimer->setInterval(2000); connect(m_rcpLoginTimer, &QTimer::timeout, this, &AVSocket::onRcpLogin); m_reconnectTimer->setSingleShot(true); m_reconnectTimer->setInterval(2000); connect(m_reconnectTimer, &QTimer::timeout, this, &AVSocket::onConnectToAVS); } AVSocket::~AVSocket() { delete m_rcpLoginTimer; delete m_reconnectTimer; if (m_avsSocket) { m_avsSocket->disconnect(this); // disconnect all signals disconnectAndWait(m_avsSocket); delete m_avsSocket; } } void AVSocket::onDisconnected() { // WARNING_LOG(m_logger) << "Disconnected from A/V system (" // << getConnectionString() // << ") - trying to reconnect"; m_bSuccessfullyLoggedIn = false; m_reconnectTimer->start(); } void AVSocket::onError(QAbstractSocket::SocketError error) { if (!m_bErrorInTcpComWarnedOnce) { ERROR_LOG(m_logger) << "Error in tcp communication with A/V system (" << getConnectionString() << "): " << QVariant::fromValue(error).toString(); m_bErrorInTcpComWarnedOnce = true; } m_bSuccessfullyLoggedIn = false; m_avsSocket->disconnectFromHost(); m_reconnectTimer->start(); } void AVSocket::onConnectToAVS() { if (!m_avsSocket || m_avsSocket->state() != QAbstractSocket::UnconnectedState) { if (m_avsSocket) { disconnectAndWait(m_avsSocket); delete m_avsSocket; } m_avsSocket = new QTcpSocket(this); connect(m_avsSocket, &QTcpSocket::disconnected, this, &AVSocket::onDisconnected); connect(m_avsSocket, &QTcpSocket::connected, this, [this] {m_bErrorInTcpComWarnedOnce = false;}); connect(m_avsSocket, QOverload::of(&QTcpSocket::error), this, &AVSocket::onError); connect(m_avsSocket, &QTcpSocket::readyRead, this, &AVSocket::onReadyRead); } m_avsSocket->connectToHost(m_avsServerHost, m_avsServerPort); } void AVSocket::onRcpLogin() { m_rcpLoginTimer->stop(); if (!sendInternal("Session 1 0 100")) m_rcpLoginTimer->start(); } bool AVSocket::sendInternal(const QByteArray &cmd) { if (!m_avsSocket || !m_avsSocket->isWritable()) { WARNING_LOG(m_logger) << "AVS not connected - can not send command '" << cmd << "'"; return false; } DEBUG_LOG(m_loggerIO) << "To A/V: '" << cmd << "'"; m_avsSocket->write(cmd); m_commandQueueForErrorHandling.push(cmd); while (m_commandQueueForErrorHandling.size() > 10) m_commandQueueForErrorHandling.pop(); if (!cmd.endsWith("\n")) m_avsSocket->write("\n"); m_avsSocket->flush(); return true; } QString AVSocket::getConnectionString() const { return m_avsServerHost + QLatin1Char(':') + QString::number(m_avsServerPort); } QVector AVSocket::parseLine(const QByteArray &ba, const int iStart) { return NGL::parseFromTelnet(ba, iStart); } } // namespace AudioVideoManagement