63#include <QCoreApplication>
78#define LOC QString("LCDServer: ")
79#define LOC_WARN QString("LCDServer, Warning: ")
80#define LOC_ERR QString("LCDServer, Error: ")
97 LOG(VB_GENERAL, LOG_ERR,
"There is probably a copy of mythlcdserver "
98 "already running. You can verify this by running: \n"
99 "'ps ax | grep mythlcdserver'");
110 connect(socket, &QIODevice::readyRead,
112 connect(socket, &QAbstractSocket::disconnected,
116 LOG(VB_NETWORK, LOG_INFO,
"LCDServer: new connection");
124 auto *socket = qobject_cast<QTcpSocket*>(sender());
128 socket->deleteLater();
130 LOG(VB_NETWORK, LOG_INFO,
"LCDServer: close connection");
139 auto *socket = qobject_cast<QTcpSocket*>(sender());
144 while(socket->canReadLine())
146 QString incoming_data = socket->readLine();
147 incoming_data = incoming_data.remove(
"\n");
148 incoming_data = incoming_data.remove(
"\r");
149 incoming_data = incoming_data.simplified();
161 bool bInString =
false;
163 for (
auto && x : std::as_const(command))
166 if (!bInString && c ==
'"')
170 else if (bInString && c ==
'"')
174 else if (!bInString && c ==
' ')
196 if (tokens[0] ==
"HALT" ||
197 tokens[0] ==
"QUIT" ||
198 tokens[0] ==
"SHUTDOWN")
202 else if (tokens[0] ==
"HELLO")
206 else if (tokens[0] ==
"SWITCH_TO_TIME")
210 else if (tokens[0] ==
"SWITCH_TO_MUSIC")
214 else if (tokens[0] ==
"SWITCH_TO_VOLUME")
218 else if (tokens[0] ==
"SWITCH_TO_GENERIC")
222 else if (tokens[0] ==
"SWITCH_TO_MENU")
226 else if (tokens[0] ==
"SWITCH_TO_CHANNEL")
230 else if (tokens[0] ==
"SWITCH_TO_NOTHING")
234 else if (tokens[0] ==
"SET_VOLUME_LEVEL")
238 else if (tokens[0] ==
"SET_GENERIC_PROGRESS")
242 else if (tokens[0] ==
"SET_MUSIC_PROGRESS")
246 else if (tokens[0] ==
"SET_MUSIC_PLAYER_PROP")
250 else if (tokens[0] ==
"SET_CHANNEL_PROGRESS")
254 else if (tokens[0] ==
"UPDATE_LEDS")
258 else if (tokens[0] ==
"STOP_ALL")
263 else if (tokens[0] ==
"RESET")
271 QString did_not_parse = tokens.join(
" ");
274 LOG(VB_GENERAL, LOG_ERR,
"LCDServer::failed to parse this: " +
284 LOG(VB_GENERAL, LOG_INFO,
"LCDServer:: shuting down");
296 QString message = what;
297 message.append(
"\n");
298 QByteArray tmp = message.toUtf8();
299 where->write(tmp.constData(), tmp.length());
305 LOG(VB_GENERAL, LOG_INFO,
"LCDServer:: send key press: " + key_pressed);
325 sWidth = sWidth.setNum(nWidth);
326 sHeight = sHeight.setNum(nHeight);
328 sendMessage(socket,
"CONNECTED " + sWidth +
" " + sHeight);
334 LOG(VB_GENERAL, LOG_INFO,
"LCDServer:: SWITCH_TO_TIME");
345 LOG(VB_GENERAL, LOG_INFO,
"LCDServer: SWITCH_TO_MUSIC");
347 QString flat = tokens.join(
" ");
349 if (tokens.count() != 4)
351 LOG(VB_GENERAL, LOG_ERR,
352 "LCDServer: bad SWITCH_TO_MUSIC command: " + flat);
366 LOG(VB_GENERAL, LOG_INFO,
"LCDServer: SWITCH_TO_GENERIC");
368 QString flat = tokens.join(
" ");
370 if ((tokens.count() - 1) % 5 != 0)
372 LOG(VB_GENERAL, LOG_ERR,
373 "LCDServer: bad no. of args SWITCH_TO_GENERIC command: " + flat);
378 QList<LCDTextItem> items;
380 for (
int x = 1; x < tokens.count(); x += 5)
383 int row = tokens[x].toInt(&bOK);
386 LOG(VB_GENERAL, LOG_ERR,
387 "LCDServer: bad row no. in SWITCH_TO_GENERIC "
388 "command: " + tokens[x]);
394 if (tokens[x + 1] ==
"ALIGN_LEFT") {
396 }
else if (tokens[x + 1] ==
"ALIGN_RIGHT") {
398 }
else if (tokens[x + 1] ==
"ALIGN_CENTERED") {
401 LOG(VB_GENERAL, LOG_ERR,
402 "LCDServer: bad align in SWITCH_TO_GENERIC command: " +
408 const QString& text = tokens[x + 2];
409 const QString& screen = tokens[x + 3];
410 bool scrollable =
false;
411 if (tokens[x + 4] ==
"TRUE") {
413 }
else if (tokens[x + 4] ==
"FALSE") {
416 LOG(VB_GENERAL, LOG_ERR,
417 "LCDServer: bad scrollable bool in SWITCH_TO_GENERIC "
418 "command: " + tokens[x + 4]);
423 items.append(
LCDTextItem(row, align, text, screen, scrollable));
435 LOG(VB_GENERAL, LOG_INFO,
"LCDServer: SWITCH_TO_CHANNEL");
437 QString flat = tokens.join(
" ");
439 if (tokens.count() != 4)
441 LOG(VB_GENERAL, LOG_ERR,
442 "LCDServer: bad SWITCH_TO_CHANNEL command: " + flat);
456 LOG(VB_GENERAL, LOG_INFO,
"LCDServer: SWITCH_TO_VOLUME");
458 QString flat = tokens.join(
" ");
460 if (tokens.count() != 2)
462 LOG(VB_GENERAL, LOG_ERR,
463 "LCDServer: bad SWITCH_TO_VOLUME command: " + flat);
477 LOG(VB_GENERAL, LOG_INFO,
"LCDServer: SWITCH_TO_NOTHING");
488 LOG(VB_GENERAL, LOG_INFO,
489 QString(
"LCDServer: SWITCH_TO_MENU: %1").arg(tokens.count()));
491 QString flat = tokens.join(
" ");
493 if ((tokens.count() - 3) % 5 != 0)
495 LOG(VB_GENERAL, LOG_ERR,
496 "LCDServer: bad no. of args SWITCH_TO_MENU command: " + flat);
501 const QString& appName = tokens[1];
504 if (tokens[2] ==
"TRUE") {
506 }
else if (tokens[2] ==
"FALSE") {
509 LOG(VB_GENERAL, LOG_ERR,
510 "LCDServer: bad popup bool in SWITCH_TO_MENU command: " +
516 QList<LCDMenuItem> items;
518 for (
int x = 3; x < tokens.count(); x += 5)
520 const QString& text = tokens[x];
523 if (tokens[x + 1] ==
"CHECKED") {
525 }
else if (tokens[x + 1] ==
"UNCHECKED") {
527 }
else if (tokens[x + 1] ==
"NOTCHECKABLE") {
530 LOG(VB_GENERAL, LOG_ERR,
531 "LCDServer: bad checked state in SWITCH_TO_MENU command: " +
537 bool selected =
false;
538 if (tokens[x + 2] ==
"TRUE") {
540 }
else if (tokens[x + 2] ==
"FALSE") {
543 LOG(VB_GENERAL, LOG_ERR,
544 "LCDServer: bad selected state in SWITCH_TO_MENU command: " +
550 bool scrollable =
false;
551 if (tokens[x + 3] ==
"TRUE") {
553 }
else if (tokens[x + 3] ==
"FALSE") {
556 LOG(VB_GENERAL, LOG_ERR,
557 "LCDServer: bad scrollable bool in SWITCH_TO_MENU command: " +
564 int indent = tokens[x + 4].toInt(&bOK);
567 LOG(VB_GENERAL, LOG_ERR,
568 "LCDServer: bad indent in SWITCH_TO_MENU command: " +
586 LOG(VB_GENERAL, LOG_INFO,
"LCDServer: SET_CHANNEL_PROGRESS");
588 QString flat = tokens.join(
" ");
590 if (tokens.count() != 3)
592 LOG(VB_GENERAL, LOG_ERR,
593 "LCDServer: bad SET_CHANNEL_PROGRESS command: " + flat);
599 float progress = tokens[2].toFloat(&bOK);
602 LOG(VB_GENERAL, LOG_ERR,
603 QString(
"LCDServer: bad float value in SET_CHANNEL_PROGRESS "
604 "command: %1").arg(tokens[2]));
618 LOG(VB_GENERAL, LOG_INFO,
"LCDServer: SET_GENERIC_PROGRESS");
620 QString flat = tokens.join(
" ");
622 if (tokens.count() != 3)
624 LOG(VB_GENERAL, LOG_ERR,
625 "LCDServer: bad SET_GENERIC_PROGRESS command: " + flat);
631 bool busy = tokens[1].toInt(&bOK) != 0;
634 LOG(VB_GENERAL, LOG_ERR,
635 QString(
"LCDServer: bad bool value in SET_GENERIC_PROGRESS "
636 "command: %1 %2").arg(tokens[1], tokens[2]));
640 float progress = tokens[2].toFloat(&bOK);
643 LOG(VB_GENERAL, LOG_ERR,
644 QString(
"LCDServer: bad float value in SET_GENERIC_PROGRESS "
645 "command: %1").arg(tokens[2]));
659 LOG(VB_GENERAL, LOG_INFO,
"LCDServer: SET_MUSIC_PROGRESS");
661 QString flat = tokens.join(
" ");
663 if (tokens.count() != 3)
665 LOG(VB_GENERAL, LOG_ERR,
666 "LCDServer: bad SET_MUSIC_PROGRESS command: " + flat);
672 float progress = tokens[2].toFloat(&bOK);
675 LOG(VB_GENERAL, LOG_ERR,
676 "LCDServer: bad float value in SET_MUSIC_PROGRESS command: " +
691 LOG(VB_GENERAL, LOG_INFO,
"LCDServer: SET_MUSIC_PROP");
693 QString flat = tokens.join(
" ");
695 if (tokens.count() < 3)
697 LOG(VB_GENERAL, LOG_ERR,
698 "LCDServer: bad SET_MUSIC_PROP command: " + flat);
703 if (tokens[1] ==
"SHUFFLE")
705 if (tokens.count () != 3)
707 LOG(VB_GENERAL, LOG_ERR,
708 "LCDServer: missing argument for SET_MUSIC_PROP SHUFFLE "
714 int state = tokens[2].toInt (&bOk);
717 LOG(VB_GENERAL, LOG_ERR,
718 "LCDServer: bad argument for SET_MUSIC_PROP SHUFFLE "
719 "command: " + tokens[2]);
726 else if (tokens[1] ==
"REPEAT")
728 if (tokens.count () != 3)
730 LOG(VB_GENERAL, LOG_ERR,
731 "LCDServer: missing argument for SET_MUSIC_PROP REPEAT "
737 int state = tokens[2].toInt (&bOk);
740 LOG(VB_GENERAL, LOG_ERR,
741 "LCDServer: bad argument for SET_MUSIC_PROP REPEAT command: " +
751 LOG(VB_GENERAL, LOG_ERR,
752 "LCDServer: bad argument for SET_MUSIC_PROP command: " + tokens[1]);
763 LOG(VB_GENERAL, LOG_INFO,
"LCDServer: SET_VOLUME_LEVEL");
765 QString flat = tokens.join(
" ");
767 if (tokens.count() != 2)
769 LOG(VB_GENERAL, LOG_ERR,
770 "LCDServer: bad SET_VOLUME_LEVEL command: " + flat);
776 float progress = tokens[1].toFloat(&bOK);
779 LOG(VB_GENERAL, LOG_ERR,
780 "LCDServer: bad float value in SET_VOLUME_LEVEL command: " +
795 LOG(VB_GENERAL, LOG_INFO,
"LCDServer: UPDATE_LEDS");
797 QString flat = tokens.join(
" ");
799 if (tokens.count() != 2)
801 LOG(VB_GENERAL, LOG_ERR,
"LCDServer: bad UPDATE_LEDs command: " + flat);
807 int mask = tokens[1].toInt(&bOK);
810 LOG(VB_GENERAL, LOG_ERR,
811 "LCDServer: bad mask in UPDATE_LEDS command: " + tokens[1]);
void switchToChannel(const QString &channum="", const QString &title="", const QString &subtitle="")
void setMusicShuffle(int shuffle)
void setGenericProgress(bool busy, float value)
void switchToVolume(const QString &app_name)
int getLCDHeight(void) const
void setMusicRepeat(int repeat)
void switchToMenu(QList< LCDMenuItem > *menuItems, const QString &app_name="", bool popMenu=true)
void switchToGeneric(QList< LCDTextItem > *textItems)
void switchToMusic(const QString &artist, const QString &album, const QString &track)
void setVolumeLevel(float value)
void setMusicProgress(QString time, float value)
int getLCDWidth(void) const
void setChannelProgress(const QString &time, float value)
void setStartupMessage(QString msg, std::chrono::seconds messagetime)
void updateLEDs(int mask)
QTcpSocket * m_lastSocket
void switchToGeneric(const QStringList &tokens, QTcpSocket *socket)
void switchToMusic(const QStringList &tokens, QTcpSocket *socket)
void switchToMenu(const QStringList &tokens, QTcpSocket *socket)
void newConnection(QTcpSocket *socket)
void sendConnected(QTcpSocket *socket)
ServerPool * m_serverPool
LCDServer(int port, QString message, std::chrono::seconds messageTime)
void switchToVolume(const QStringList &tokens, QTcpSocket *socket)
void switchToTime(QTcpSocket *socket)
void setVolumeLevel(const QStringList &tokens, QTcpSocket *socket)
void sendKeyPress(const QString &key_pressed)
static void sendMessage(QTcpSocket *where, const QString &what)
static QStringList parseCommand(QString &command)
void updateLEDs(const QStringList &tokens, QTcpSocket *socket)
void setGenericProgress(const QStringList &tokens, QTcpSocket *socket)
void switchToNothing(QTcpSocket *socket)
void setMusicProgress(const QStringList &tokens, QTcpSocket *socket)
void setChannelProgress(const QStringList &tokens, QTcpSocket *socket)
void parseTokens(const QStringList &tokens, QTcpSocket *socket)
void setMusicProp(const QStringList &tokens, QTcpSocket *socket)
void switchToChannel(const QStringList &tokens, QTcpSocket *socket)
Manages a collection of sockets listening on different ports.
bool listen(QList< QHostAddress > addrs, quint16 port, bool requireall=true, PoolServerType type=kTCPServer)
void newConnection(QTcpSocket *)
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
static QString indent(uint level)