diff --git a/ChangeLog b/ChangeLog index 1cdb340d..11091714 100644 --- a/ChangeLog +++ b/ChangeLog @@ -14757,3 +14757,8 @@ 'Description' fields in 'rlm/rlm_padpoint.c'. * Fixed a bug when generating the 'Year' field in RLM updates in 'rdairplay/rlmhost.cpp'. +2015-02-18 Fred Gleason <fredg@paravelsystems.com> + * Added 'RDMatrix::SoftwareAuthority' to the 'RDMatrix::Type' + enumeration in 'lib/rdmatrix.cpp' and 'lib/rdmatrix.h'. + * Implemented a switcher driver for systems using Software Authority + Protocol in 'ripcd/swauthority.cpp' and 'ripcd/swauthority.h'. diff --git a/docs/SWITCHERS.txt b/docs/SWITCHERS.txt index 0425301f..620984e9 100644 --- a/docs/SWITCHERS.txt +++ b/docs/SWITCHERS.txt @@ -27,6 +27,7 @@ Sierra Automated Systems 32000 Audio Router Sierra Automated Systems 64000 Audio Router Sierra Automated Systems Universal Serial Interface (USI) Sine Systems ACU-1 (Prophet version) +Software Authority Protocol StarGuide III Satellite Receiver Wegener Unity4000 DVB Satellite Receiver @@ -632,6 +633,22 @@ by simultaneously pressing buttons 1 and 8 on the front panel of the unit for at least one second. +---------------------------------------------------------------------------- +SOFTWARE AUTHORITY PROTOCOL + +Driver Name: Software Authority Protocol + +Supported RML Commands: + Switch Take ('ST') + +GENERAL NOTES: +Used to control devices (such as the Axia 'PathFinder' system) by means of +the 'Software Authority' protocol. Control is by means of a +TCP/IP connection (typically to port 9500) on the controled system. Most +parameters, including the number of inputs and outputs as well as the +endpoint names, are autodetected by the driver. + + ---------------------------------------------------------------------------- STARGUIDE III Satellite Receiver diff --git a/lib/rdmatrix.cpp b/lib/rdmatrix.cpp index 0f21d1a8..341af834 100644 --- a/lib/rdmatrix.cpp +++ b/lib/rdmatrix.cpp @@ -63,7 +63,8 @@ bool __mx_primary_controls[RDMatrix::LastType][RDMatrix::LastControl]= {0,0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,1,0,0,0,0,1,0,0,0,0}, // LiveWire LWRP GPIO {0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0}, // BT Sentinel 4 Web {0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0}, // BT GPI-16 - {0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0} // Modem Lines + {0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0}, // Modem Lines + {0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0} // Software Authority }; bool __mx_backup_controls[RDMatrix::LastType][RDMatrix::LastControl]= { @@ -101,7 +102,8 @@ bool __mx_backup_controls[RDMatrix::LastType][RDMatrix::LastControl]= {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, // LiveWire LWRP GPIO {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, // BT Sentinel 4 Web {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, // BT GPI-16 - {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} // Modem Lines + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, // Modem Lines + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} // Software Authority }; int __mx_default_values[RDMatrix::LastType][RDMatrix::LastControl]= @@ -140,7 +142,8 @@ int __mx_default_values[RDMatrix::LastType][RDMatrix::LastControl]= {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0}, // LiveWire LWRP GPIO {1,0,0,0,0,0,0,0,0,0,0,4,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0}, // BT Sentinel 4 Web {0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0}, // BT GPI-16 - {0,0,0,0,0,0,0,0,0,0,0,0,0,4,2,0,0,0,0,0,0,0,0,0,0,0,0,1,0} // Modem Lines + {0,0,0,0,0,0,0,0,0,0,0,0,0,4,2,0,0,0,0,0,0,0,0,0,0,0,0,1,0}, // Modem Lines + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0} // Software Authority }; RDMatrix::RDMatrix(const QString &station,int matrix) @@ -684,6 +687,10 @@ QString RDMatrix::typeString(RDMatrix::Type type) return QString("Serial Port Modem Control Lines"); break; + case RDMatrix::SoftwareAuthority: + return QString("Software Authority Protocol"); + break; + default: return QString("Unknown Type"); break; diff --git a/lib/rdmatrix.h b/lib/rdmatrix.h index 6dcae61c..b9909cbb 100644 --- a/lib/rdmatrix.h +++ b/lib/rdmatrix.h @@ -38,7 +38,7 @@ class RDMatrix LiveWireLwrpAudio=20,Quartz1=21,BtSs44=22,BtSrc8III=23,BtSrc16=24, Harlond=25,Acu1p=26,LiveWireMcastGpio=27,Am16=28, LiveWireLwrpGpio=29,BtSentinel4Web=30,BtGpi16=31,ModemLines=32, - LastType=33}; + SoftwareAuthority=33,LastType=34}; enum Endpoint {Input=0,Output=1}; enum Mode {Stereo=0,Left=1,Right=2}; enum VguestAttribute {VguestEngine=0,VguestDevice=1,VguestSurface=2, diff --git a/rdadmin/view_node_info.cpp b/rdadmin/view_node_info.cpp index d2e4382f..106a968b 100644 --- a/rdadmin/view_node_info.cpp +++ b/rdadmin/view_node_info.cpp @@ -188,6 +188,7 @@ ViewNodeInfo::ViewNodeInfo(QWidget *parent,const char *name) view_sources_view->setItemMargin(5); view_sources_view->addColumn(tr("#")); view_sources_view->setColumnAlignment(0,Qt::AlignCenter); + view_sources_view->setColumnSortType(0,RDListView::LineSort); view_sources_view->addColumn(tr("CHAN")); view_sources_view->setColumnAlignment(1,Qt::AlignCenter); view_sources_view->addColumn(tr("NAME")); @@ -325,6 +326,7 @@ void ViewNodeInfo::closeData() void ViewNodeInfo::WriteSourceItem(RDLiveWireSource *src,RDListViewItem *item) { + item->setText(1,QString().sprintf("%05d",src->channelNumber())); item->setText(2,src->primaryName()); if(src->rtpEnabled()) { diff --git a/rdairplay/log_play.cpp b/rdairplay/log_play.cpp index 68e20fdc..1a7f57da 100644 --- a/rdairplay/log_play.cpp +++ b/rdairplay/log_play.cpp @@ -1445,9 +1445,9 @@ void LogPlay::graceTimerData() void LogPlay::playStateChangedData(int id,RDPlayDeck::State state) { -#ifdef SHOW_SLOTS - printf("playStateChangedData(%d)\n",id); -#endif + //#ifdef SHOW_SLOTS + printf("playStateChangedData(%d,%d), log: %s\n",id,state,(const char *)logName()); + //#endif switch(state) { case RDPlayDeck::Playing: Playing(id); @@ -1842,6 +1842,11 @@ bool LogPlay::StartEvent(int line,RDLogLine::TransType trans_type, rdevent_player-> exec(logline->resolveWildcards(play_start_rml[aport])); } + + printf("channelStarted(%d,%d,%d,%d)\n", + play_id,playdeck->channel(), + playdeck->card(),playdeck->port()); + emit channelStarted(play_id,playdeck->channel(), playdeck->card(),playdeck->port()); LogLine(RDConfig::LogInfo,QString().sprintf( @@ -2752,6 +2757,12 @@ void LogPlay::ClearChannel(int deckid) if(play_deck[deckid]->channel()>=0) { rdevent_player->exec(play_stop_rml[play_deck[deckid]->channel()]); + + printf("Deck: %d channelStopped(%d,%d,%d,%d\n",deckid, + play_id,play_deck[deckid]->channel(), + play_deck[deckid]->card(), + play_deck[deckid]->port()); + emit channelStopped(play_id,play_deck[deckid]->channel(), play_deck[deckid]->card(), play_deck[deckid]->port()); diff --git a/ripcd/Makefile.am b/ripcd/Makefile.am index c297896f..294912cd 100644 --- a/ripcd/Makefile.am +++ b/ripcd/Makefile.am @@ -66,6 +66,7 @@ dist_ripcd_SOURCES = acu1p.cpp acu1p.h\ sasusi.cpp sasusi.h\ starguide3.cpp starguide3.h\ starguide_feed.cpp starguide_feed.h\ + swauthority.cpp swauthority.h\ switcher.cpp switcher.h\ unity4000.cpp unity4000.h\ unity_feed.cpp unity_feed.h\ @@ -102,6 +103,7 @@ nodist_ripcd_SOURCES = moc_am16.cpp\ moc_sas64000gpi.cpp\ moc_sasusi.cpp\ moc_starguide3.cpp\ + moc_swauthority.cpp\ moc_switcher.cpp\ moc_unity4000.cpp\ moc_vguest.cpp diff --git a/ripcd/loaddrivers.cpp b/ripcd/loaddrivers.cpp index 2ab907b4..407c88d8 100644 --- a/ripcd/loaddrivers.cpp +++ b/ripcd/loaddrivers.cpp @@ -54,6 +54,7 @@ #include <sas64000gpi.h> #include <sasusi.h> #include <starguide3.h> +#include <swauthority.h> #include <unity4000.h> #include <vguest.h> @@ -178,6 +179,10 @@ bool MainObject::LoadSwitchDriver(int matrix_num) ripcd_switcher[matrix_num]=new SasUsi(matrix,this); break; + case RDMatrix::SoftwareAuthority: + ripcd_switcher[matrix_num]=new SoftwareAuthority(matrix,this); + break; + case RDMatrix::StarGuideIII: ripcd_switcher[matrix_num]=new StarGuide3(matrix,this); break; diff --git a/ripcd/swauthority.cpp b/ripcd/swauthority.cpp new file mode 100644 index 00000000..148f35e1 --- /dev/null +++ b/ripcd/swauthority.cpp @@ -0,0 +1,446 @@ +// swauthority.cpp +// +// A Rivendell switcher driver for systems using Software Authority Protocol +// +// (C) Copyright 2002-2015 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 <stdlib.h> + +#include <qstringlist.h> + +#include <rdescape_string.h> +#include <rddb.h> +#include <globals.h> +#include <swauthority.h> + +SoftwareAuthority::SoftwareAuthority(RDMatrix *matrix,QObject *parent,const char *name) + : Switcher(matrix,parent,name) +{ + swa_matrix=matrix->matrix(); + swa_ptr=0; + swa_istate=0; + + // + // Get Matrix Parameters + // + swa_username=matrix->username(RDMatrix::Primary); + swa_password=matrix->password(RDMatrix::Primary); + swa_porttype=matrix->portType(RDMatrix::Primary); + swa_ipaddress=matrix->ipAddress(RDMatrix::Primary); + swa_ipport=matrix->ipPort(RDMatrix::Primary); + swa_inputs=0; + swa_outputs=0; + swa_gpis=matrix->gpis(); + swa_gpos=matrix->gpos(); + swa_start_cart=matrix->startCart(RDMatrix::Primary); + swa_stop_cart=matrix->stopCart(RDMatrix::Primary); + + // + // Reconnection Timer + // + swa_reconnect_timer=new QTimer(this,"swa_reconnect_timer"); + connect(swa_reconnect_timer,SIGNAL(timeout()),this,SLOT(ipConnect())); + + // + // Initialize the connection + // + swa_socket=new QSocket(this,"swa_socket"); + connect(swa_socket,SIGNAL(connected()),this,SLOT(connectedData())); + connect(swa_socket,SIGNAL(connectionClosed()), + this,SLOT(connectionClosedData())); + connect(swa_socket,SIGNAL(readyRead()), + this,SLOT(readyReadData())); + connect(swa_socket,SIGNAL(error(int)),this,SLOT(errorData(int))); + ipConnect(); +} + + +RDMatrix::Type SoftwareAuthority::type() +{ + return RDMatrix::SoftwareAuthority; +} + + +unsigned SoftwareAuthority::gpiQuantity() +{ + return swa_gpis; +} + + +unsigned SoftwareAuthority::gpoQuantity() +{ + return swa_gpos; +} + + +bool SoftwareAuthority::primaryTtyActive() +{ + return false; +} + + +bool SoftwareAuthority::secondaryTtyActive() +{ + return false; +} + + +void SoftwareAuthority::processCommand(RDMacro *cmd) +{ + switch(cmd->command()) { + /* + case RDMacro::FS: + if((cmd->arg(1).toInt()<1)||(cmd->arg(1).toInt()>256)|| + (swa_porttype!=RDMatrix::TcpPort)) { + cmd->acknowledge(false); + emit rmlEcho(cmd); + return; + } + snprintf(str,256,"%c1%03d\x0D\x0A",0x13,cmd->arg(1).toInt()); + SendCommand(str); + cmd->acknowledge(true); + emit rmlEcho(cmd); + break; + + */ + case RDMacro::ST: + if((cmd->arg(1).toInt()<0)||(cmd->arg(1).toInt()>swa_inputs)|| + (cmd->arg(2).toInt()<1)||(cmd->arg(2).toInt()>swa_outputs)) { + cmd->acknowledge(false); + emit rmlEcho(cmd); + return; + } + SendCommand(QString().sprintf("activateroute 1 %d %d", + cmd->arg(2).toInt(),cmd->arg(1).toInt())); + cmd->acknowledge(true); + emit rmlEcho(cmd); + break; + /* + case RDMacro::GO: + if((cmd->arg(1).toString().lower()!="o")|| + (cmd->arg(2).toInt()<1)||(cmd->arg(2).toInt()>swa_gpos)) { + cmd->acknowledge(false); + emit rmlEcho(cmd); + return; + } + if(cmd->arg(4).toInt()==0) { // Latch + if(cmd->arg(3).toInt()==0) { // Off + cmd_byte=0x03; + } + else { + cmd_byte=0x02; + } + } + else { + if(cmd->arg(3).toInt()==0) { + cmd->acknowledge(false); + emit rmlEcho(cmd); + return; + } + cmd_byte=0x01; + } + if(cmd->arg(2).toUInt()<swa_relay_numbers.size()) { + if(swa_relay_numbers[cmd->arg(2).toUInt()-1]>=0) { + snprintf(str,256,"\x05R%d%04d\x0D\x0A",cmd_byte, + swa_relay_numbers[cmd->arg(2).toUInt()-1]); + SendCommand(str); + cmd->acknowledge(true); + emit rmlEcho(cmd); + } + else { + if((swa_console_numbers[cmd->arg(2).toUInt()-1]>=0)&& + (swa_source_numbers[cmd->arg(2).toUInt()-1]>=0)) { + if(cmd->arg(3).toInt()==0) { // Off + cmd_byte=0; + } + else { + cmd_byte=1; + } + snprintf(str,256,"\x1A%s%d%03d%04d\x0D\x0A","20",cmd_byte, + swa_console_numbers[cmd->arg(2).toUInt()-1], + swa_source_numbers[cmd->arg(2).toUInt()-1]); + SendCommand(str); + cmd->acknowledge(true); + emit rmlEcho(cmd); + } + } + } + break; + */ + default: + cmd->acknowledge(false); + emit rmlEcho(cmd); + break; + } +} + + +void SoftwareAuthority::ipConnect() +{ + swa_socket->connectToHost(swa_ipaddress.toString(),swa_ipport); +} + + +void SoftwareAuthority::connectedData() +{ + SendCommand(QString("login")+" "+swa_username+" "+swa_password); +} + + +void SoftwareAuthority::connectionClosedData() +{ + LogLine(RDConfig::LogNotice,QString(). + sprintf("Connection to SoftwareAuthority device at %s:%d closed unexpectedly, attempting reconnect", + (const char *)swa_ipaddress.toString(), + swa_ipport)); + if(swa_stop_cart>0) { + ExecuteMacroCart(swa_stop_cart); + } + swa_reconnect_timer->start(SWAUTHORITY_RECONNECT_INTERVAL,true); +} + + +void SoftwareAuthority::readyReadData() +{ + char buffer[256]; + unsigned n; + + while((n=swa_socket->readBlock(buffer,255))>0) { + buffer[n]=0; + /// printf("RECV: %s\n",buffer); + for(unsigned i=0;i<n;i++) { + if(buffer[i]==10) { // End of line + swa_buffer[--swa_ptr]=0; + DispatchCommand(); + swa_ptr=0; + } + else { + if(swa_ptr==SWAUTHORITY_MAX_LENGTH) { // Buffer overflow + swa_ptr=0; + } + swa_buffer[swa_ptr++]=buffer[i]; + } + } + } +} + + +void SoftwareAuthority::errorData(int err) +{ + switch((QSocket::Error)err) { + case QSocket::ErrConnectionRefused: + LogLine(RDConfig::LogNotice,QString().sprintf( + "Connection to SoftwareAuthority device at %s:%d refused, attempting reconnect", + (const char *)swa_ipaddress.toString(), + swa_ipport)); + swa_reconnect_timer->start(SWAUTHORITY_RECONNECT_INTERVAL,true); + break; + + case QSocket::ErrHostNotFound: + LogLine(RDConfig::LogWarning,QString().sprintf( + "Error on connection to SoftwareAuthority device at %s:%d: Host Not Found", + (const char *)swa_ipaddress.toString(), + swa_ipport)); + break; + + case QSocket::ErrSocketRead: + LogLine(RDConfig::LogWarning,QString().sprintf( + "Error on connection to SoftwareAuthority device at %s:%d: Socket Read Error", + (const char *)swa_ipaddress.toString(), + swa_ipport)); + break; + } +} + + +void SoftwareAuthority::SendCommand(const char *str) +{ + // LogLine(RDConfig::LogDebug,QString().sprintf("sending SA cmd: %s",(const char *)PrettifyCommand(str))); + QString cmd=QString().sprintf("%s\x0d\x0a",(const char *)str); + swa_socket->writeBlock((const char *)cmd,strlen(cmd)); +} + + +void SoftwareAuthority::DispatchCommand() +{ + char buffer[SWAUTHORITY_MAX_LENGTH]; + QString cmd; + QString label; + QString sql; + RDSqlQuery *q; + QStringList f0; + QString name; + + // LogLine(RDConfig::LogNotice,QString().sprintf("RECEIVED: %s",(const char *)swa_buffer)); + + QString line_in=swa_buffer; + QString section=line_in.lower(); + + // + // Startup Sequence. Get the input and output lists. + // + if(section=="login successful") { + sprintf(buffer,"sourcenames 1\x0D\x0A"); // Request Input List + SendCommand(buffer); + sprintf(buffer,"destnames 1\x0D\x0A"); // Request Output List + SendCommand(buffer); + return; + } + if(section=="login failure") { + LogLine(RDConfig::LogWarning,QString().sprintf( + "Error on connection to SoftwareAuthority device at %s:%d: Login Failure", + (const char *)swa_ipaddress.toString(), + swa_ipport)); + swa_socket->close(); + return; + } + + switch(swa_istate) { + case 0: // No section selected + if(section==">>begin sourcenames - 1") { + swa_istate=1; + swa_inputs=0; + return; + } + if(section==">>begin destnames - 1") { + swa_istate=2; + swa_outputs=0; + return; + } + break; + + case 1: // Source List + if(section=="end sourcenames - 1") { + swa_istate=0; + sql=QString("update MATRICES set ")+ + QString().sprintf("INPUTS=%d ",swa_inputs)+ + "where (STATION_NAME=\""+RDEscapeString(rdstation->name())+"\")&&"+ + QString().sprintf("(MATRIX=%d)",swa_matrix); + q=new RDSqlQuery(sql); + delete q; + return; + } + swa_inputs++; + f0=f0.split("\t",line_in); + name=f0[1]; + if(f0.size()>=7) { + name=f0[6]+": "+f0[2]; + } + sql=QString().sprintf("select NUMBER from INPUTS where \ + (STATION_NAME=\"%s\")&& \ + (MATRIX=%d)&&(NUMBER=%d)", + (const char *)rdstation->name(), + swa_matrix,f0[0].toInt()); + q=new RDSqlQuery(sql); + if(q->first()) { + sql=QString().sprintf("update INPUTS set NAME=\"%s\" where \ + (STATION_NAME=\"%s\")&&\ + (MATRIX=%d)&&(NUMBER=%d)", + (const char *)name, + (const char *)rdstation->name(), + swa_matrix,f0[0].toInt()); + } + else { + sql=QString().sprintf("insert into INPUTS set NAME=\"%s\",\ + STATION_NAME=\"%s\",MATRIX=%d,NUMBER=%d", + (const char *)name, + (const char *)rdstation->name(), + swa_matrix,f0[0].toInt()); + } + delete q; + q=new RDSqlQuery(sql); + delete q; + break; + + case 2: // Destinations List + if(section=="end destnames - 1") { + swa_istate=0; + sql=QString("update MATRICES set ")+ + QString().sprintf("OUTPUTS=%d ",swa_outputs)+ + "where (STATION_NAME=\""+RDEscapeString(rdstation->name())+"\")&&"+ + QString().sprintf("(MATRIX=%d)",swa_matrix); + q=new RDSqlQuery(sql); + delete q; + + LogLine(RDConfig::LogInfo,QString(). + sprintf("Connection to SoftwareAuthority device at %s:%d established", + (const char *)swa_ipaddress.toString(), + swa_ipport)); + if(swa_start_cart>0) { + ExecuteMacroCart(swa_start_cart); + } + return; + } + swa_outputs++; + f0=f0.split("\t",line_in); + name=f0[1]; + if(f0.size()>=6) { + name=f0[3]+"/"+f0[5]+": "+f0[2]; + } + sql=QString().sprintf("select NUMBER from OUTPUTS where \ + (STATION_NAME=\"%s\")&&\ + (MATRIX=%d)&&(NUMBER=%d)", + (const char *)rdstation->name(), + swa_matrix,f0[0].toInt()); + q=new RDSqlQuery(sql); + if(q->first()) { + sql=QString().sprintf("update OUTPUTS set NAME=\"%s\" where \ + (STATION_NAME=\"%s\")&&\ + (MATRIX=%d)&&(NUMBER=%d)", + (const char *)name, + (const char *)rdstation->name(), + swa_matrix,f0[0].toInt()); + } + else { + sql=QString().sprintf("insert into OUTPUTS set NAME=\"%s\",\ + STATION_NAME=\"%s\",MATRIX=%d,NUMBER=%d", + (const char *)name, + (const char *)rdstation->name(), + swa_matrix,f0[0].toInt()); + } + delete q; + q=new RDSqlQuery(sql); + delete q; + break; + } +} + + +void SoftwareAuthority::ExecuteMacroCart(unsigned cartnum) +{ + RDMacro rml; + rml.setRole(RDMacro::Cmd); + rml.setCommand(RDMacro::EX); + rml.setAddress(rdstation->address()); + rml.setEchoRequested(false); + rml.setArgQuantity(1); + rml.setArg(0,cartnum); + emit rmlEcho(&rml); +} + + +QString SoftwareAuthority::PrettifyCommand(const char *cmd) const +{ + QString ret; + if(cmd[0]<26) { + ret=QString().sprintf("^%c%s",'@'+cmd[0],cmd+1); + } + else { + ret=cmd; + } + return ret; +} diff --git a/ripcd/swauthority.h b/ripcd/swauthority.h new file mode 100644 index 00000000..f8f3db5c --- /dev/null +++ b/ripcd/swauthority.h @@ -0,0 +1,83 @@ +// swauthority.h +// +// A Rivendell switcher driver for systems using Software Authority Protocol +// +// (C) Copyright 2002-2015 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. +// + +#ifndef SWAUTHORITY_H +#define SWAUTHORITY_H + +#include <vector> + +#include <qsocket.h> +#include <qhostaddress.h> +#include <qtimer.h> + +#include <rd.h> +#include <rdmatrix.h> +#include <rdmacro.h> + +#include <switcher.h> + +#define SWAUTHORITY_RECONNECT_INTERVAL 10000 +#define SWAUTHORITY_MAX_LENGTH 256 + +class SoftwareAuthority : public Switcher +{ + Q_OBJECT + public: + SoftwareAuthority(RDMatrix *matrix,QObject *parent=0,const char *name=0); + RDMatrix::Type type(); + unsigned gpiQuantity(); + unsigned gpoQuantity(); + bool primaryTtyActive(); + bool secondaryTtyActive(); + void processCommand(RDMacro *cmd); + + private slots: + void ipConnect(); + void connectedData(); + void connectionClosedData(); + void readyReadData(); + void errorData(int err); + + private: + void SendCommand(const char *str); + void DispatchCommand(); + void ExecuteMacroCart(unsigned cartnum); + QString PrettifyCommand(const char *cmd) const; + QSocket *swa_socket; + char swa_buffer[SWAUTHORITY_MAX_LENGTH]; + unsigned swa_ptr; + QHostAddress swa_ipaddress; + QString swa_username; + QString swa_password; + int swa_matrix; + int swa_ipport; + int swa_inputs; + int swa_outputs; + int swa_gpis; + int swa_gpos; + QTimer *swa_reconnect_timer; + unsigned swa_start_cart; + unsigned swa_stop_cart; + int swa_istate; + RDMatrix::PortType swa_porttype; +}; + + +#endif // SWAUTHORITY_H