// rdripc.cpp // // Connection to the Rivendell Interprocess Communication Daemon // // (C) Copyright 2002-2003,2016-2017 Fred Gleason <fredg@paravelsystems.com> // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License version 2 as // published by the Free Software Foundation. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public // License along with this program; if not, write to the Free Software // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // #include <ctype.h> #include <qobject.h> #include <qapplication.h> #include <qdatetime.h> #include "rddatedecode.h" #include "rddb.h" #include "rdescape_string.h" #include "rdripc.h" //RDRipc::RDRipc(QString stationname,QObject *parent) RDRipc::RDRipc(RDStation *station,RDConfig *config,QObject *parent) : QObject(parent) { ripc_station=station; ripc_config=config; ripc_onair_flag=false; ripc_ignore_mask=false; ripc_accum=""; debug=false; // argnum=0; // argptr=0; ripc_connected=false; // // TCP Connection // ripc_socket=new QSocket(this); connect(ripc_socket,SIGNAL(connected()),this,SLOT(connectedData())); connect(ripc_socket,SIGNAL(error(int)),this,SLOT(errorData(int))); connect(ripc_socket,SIGNAL(readyRead()),this,SLOT(readyData())); } RDRipc::~RDRipc() { delete ripc_socket; } QString RDRipc::user() const { return ripc_user; } QString RDRipc::station() const { return ripc_station->name(); } bool RDRipc::onairFlag() const { return ripc_onair_flag; } void RDRipc::setUser(QString user) { SendCommand(QString("SU ")+user+"!"); } void RDRipc::setIgnoreMask(bool state) { ripc_ignore_mask=state; } void RDRipc::connectHost(QString hostname,Q_UINT16 hostport,QString password) { ripc_password=password; ripc_socket->connectToHost(hostname,hostport); } void RDRipc::connectedData() { SendCommand(QString("PW ")+ripc_password+"!"); } void RDRipc::sendGpiStatus(int matrix) { SendCommand(QString().sprintf("GI %d!",matrix)); } void RDRipc::sendGpoStatus(int matrix) { SendCommand(QString().sprintf("GO %d!",matrix)); } void RDRipc::sendGpiMask(int matrix) { SendCommand(QString().sprintf("GM %d!",matrix)); } void RDRipc::sendGpoMask(int matrix) { SendCommand(QString().sprintf("GN %d!",matrix)); } void RDRipc::sendGpiCart(int matrix) { SendCommand(QString().sprintf("GC %d!",matrix)); } void RDRipc::sendGpoCart(int matrix) { SendCommand(QString().sprintf("GD %d!",matrix)); } void RDRipc::sendNotification(const RDNotification ¬ify) { SendCommand("ON "+notify.write()+"!"); } void RDRipc::sendOnairFlag() { SendCommand("TA!"); } void RDRipc::sendRml(RDMacro *macro) { // char buffer[RD_RML_MAX_LENGTH]; QString cmd; Q_UINT16 port=RD_RML_NOECHO_PORT; QDateTime now=QDateTime::currentDateTime(); if(macro->echoRequested()) { port=RD_RML_ECHO_PORT; } if(macro->port()>0) { port=macro->port(); } QString rmlline=macro->toString(); QString sql=QString("select NAME,VARVALUE from HOSTVARS where ")+ "STATION_NAME=\""+RDEscapeString(ripc_station->name())+"\""; RDSqlQuery *q=new RDSqlQuery(sql); while(q->next()) { rmlline.replace(q->value(0).toString(),q->value(1).toString()); } delete q; rmlline=RDDateTimeDecode(rmlline,now,ripc_station,ripc_config); switch(macro->role()) { case RDMacro::Cmd: cmd=QString("MS ")+macro->address().toString()+ QString().sprintf(" %d ",port)+rmlline; break; case RDMacro::Reply: cmd=QString("ME ")+macro->address().toString()+ QString().sprintf(" %d ",port)+rmlline; break; default: break; } SendCommand(cmd); } void RDRipc::reloadHeartbeat() { SendCommand("RH!"); } void RDRipc::errorData(int errorcode) { } void RDRipc::readyData() { char data[1501]; int n; while((n=ripc_socket->readBlock(data,1500))>0) { data[n]=0; QString line=QString::fromUtf8(data); for(unsigned i=0;i<line.length();i++) { QChar c=line.ref(i); if(c=="!") { DispatchCommand(); ripc_accum=""; } else { if((c!="\r")&&(c!="\n")) { ripc_accum+=c; } } } } /* char buf[255]; int c; while((c=ripc_socket->readBlock(buf,256))>0) { buf[c]=0; for(int i=0;i<c;i++) { if(buf[i]==' ') { if(argnum<RIPC_MAX_ARGS) { args[argnum][argptr]=0; argptr=0; argnum++; } else { if(debug) { printf("Argument list truncated!\n"); } } } if(buf[i]=='!') { args[argnum++][argptr]=0; DispatchCommand(); argnum=0; argptr=0; if(ripc_socket==NULL) { return; } } if((isgraph(buf[i]))&&(buf[i]!='!')) { if(argptr<RIPC_MAX_LENGTH) { args[argnum][argptr]=buf[i]; argptr++; } else { if(debug) { printf("WARNING: argument truncated!\n"); } } } } } */ } void RDRipc::SendCommand(const QString &cmd) { // printf("RDRipc::SendCommand(%s)\n",(const char *)cmd.utf8()); ripc_socket->writeBlock((const char *)cmd.utf8(),cmd.utf8().length()); } void RDRipc::DispatchCommand() { RDMacro macro; QString str; // char str[RD_RML_MAX_LENGTH]; QStringList cmds=cmds.split(" ",ripc_accum); if(cmds[0]=="PW") { // Password Response SendCommand("RU!"); } if((cmds[0]=="RU")&&(cmds.size()==2)) { // User Identity if(cmds[1]!=ripc_user) { ripc_user=cmds[1]; if(!ripc_connected) { ripc_connected=true; emit connected(true); } emit userChanged(); } } if(cmds[0]=="MS") { // Macro Sent if(cmds.size()<4) { return; } str=cmds[3]; for(unsigned i=4;i<cmds.size();i++) { str+=" "+cmds[i]; } str+="!"; macro=RDMacro::fromString(str,RDMacro::Cmd); if(!macro.isNull()) { QHostAddress addr; addr.setAddress(cmds[1]); if(cmds[2].left(0)=="1") { macro.setEchoRequested(true); } macro.setAddress(addr); emit rmlReceived(¯o); } return; } if(cmds[0]=="ME") { // Macro Echoed if(cmds.size()<4) { return; } str=cmds[3]; for(unsigned i=4;i<cmds.size();i++) { str+=" "+cmds[i]; } str+="!"; macro=RDMacro::fromString(str,RDMacro::Reply); if(!macro.isNull()) { macro.setAddress(QHostAddress().setAddress(cmds[1])); macro.setRole(RDMacro::Reply); emit rmlReceived(¯o); } return; } if(cmds[0]=="GI") { // GPI State Changed if(cmds.size()<4) { return; } int matrix=cmds[1].toInt(); int line=cmds[2].toInt(); int mask=cmds[4].toInt(); if((mask>0)||ripc_ignore_mask) { if(cmds[3].left(0)=="0") { emit gpiStateChanged(matrix,line,false); } else { emit gpiStateChanged(matrix,line,true); } } } if(cmds[0]=="GO") { // GPO State Changed if(cmds.size()<4) { return; } int matrix=cmds[1].toInt(); int line=cmds[2].toInt(); int mask=cmds[4].toInt(); if((mask>0)||ripc_ignore_mask) { if(cmds[3].left(0)=="0") { emit gpoStateChanged(matrix,line,false); } else { emit gpoStateChanged(matrix,line,true); } } } if(cmds[0]=="GM") { // GPI Mask Changed if(cmds.size()<4) { return; } int matrix=cmds[1].toInt(); int line=cmds[2].toInt(); if(cmds[3].left(0)=="0") { emit gpiMaskChanged(matrix,line,false); } else { emit gpiMaskChanged(matrix,line,true); } } if(cmds[0]=="GN") { // GPO Mask Changed if(cmds.size()<4) { return; } int matrix=cmds[1].toInt(); int line=cmds[2].toInt(); if(cmds[3].left(0)=="0") { emit gpoMaskChanged(matrix,line,false); } else { emit gpoMaskChanged(matrix,line,true); } } if(cmds[0]=="GC") { // GPI Cart Changed if(cmds.size()<5) { return; } int matrix=cmds[1].toInt(); int line=cmds[2].toInt(); unsigned off_cartnum=cmds[3].toUInt(); unsigned on_cartnum=cmds[4].toUInt(); emit gpiCartChanged(matrix,line,off_cartnum,on_cartnum); } if(cmds[0]=="GD") { // GPO Cart Changed if(cmds.size()<5) { return; } int matrix=cmds[1].toInt(); int line=cmds[2].toInt(); unsigned off_cartnum=cmds[3].toUInt(); unsigned on_cartnum=cmds[4].toUInt(); emit gpoCartChanged(matrix,line,off_cartnum,on_cartnum); } if(cmds[0]=="TA") { // On Air Flag Changed if(cmds.size()!=2) { return; } ripc_onair_flag=cmds[1].left(0)=="1"; emit onairFlagChanged(ripc_onair_flag); } if(cmds[0]=="ON") { // Notification Received if(cmds.size()<4) { return; } QString msg; for(unsigned i=1;i<cmds.size();i++) { msg+=QString(cmds[i])+" "; } msg=msg.left(msg.length()-1); RDNotification *notify=new RDNotification(); if(!notify->read(msg)) { delete notify; return; } emit notificationReceived(notify); delete notify; } }