Rivendellaudio/lib/rdcatch_connect.cpp
Fred Gleason 6964405e0e 2019-11-26 Fred Gleason <fredg@paravelsystems.com>
* Removed 'Q3Socket' dependencies from 'RDCatchConnect'.
2019-11-26 14:51:06 -08:00

349 lines
6.9 KiB
C++

// catch_connect.cpp
//
// Connect to the Rivendell Netcatcher Daemon.
//
// (C) Copyright 2002-2019 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 <rdcatch_connect.h>
RDCatchConnect::RDCatchConnect(int serial,QObject *parent)
: QObject(parent)
{
cc_serial=serial;
cc_connected=false;
argnum=0;
argptr=0;
for(int i=0;i<MAX_DECKS;i++) {
cc_monitor_state[i]=false;
}
//
// TCP Connection
//
cc_socket=new QTcpSocket(this);
connect(cc_socket,SIGNAL(connected()),this,SLOT(connectedData()));
connect(cc_socket,SIGNAL(readyRead()),this,SLOT(readyData()));
//
// Start the heartbeat timer
//
cc_heartbeat_timer=new QTimer(this);
connect(cc_heartbeat_timer,SIGNAL(timeout()),
this,SLOT(heartbeatTimeoutData()));
cc_heartbeat_timer->start(CC_HEARTBEAT_INTERVAL,true);
cc_heartbeat_valid=true;
}
RDCatchConnect::~RDCatchConnect()
{
// printf("Destroying RDCatchConnect\n");
}
void RDCatchConnect::connectHost(QString hostname,Q_UINT16 hostport,
QString password)
{
cc_password=password;
cc_socket->connectToHost(hostname,hostport);
}
RDDeck::Status RDCatchConnect::status(unsigned chan) const
{
if(chan<=MAX_DECKS) {
return cc_record_deck_status[chan-1];
}
return cc_play_deck_status[chan-128];
}
int RDCatchConnect::currentId(unsigned chan) const
{
if(chan<=MAX_DECKS) {
return cc_record_id[chan-1];
}
return cc_play_id[chan-129];
}
void RDCatchConnect::enableMetering(bool state)
{
SendCommand(QString().sprintf("RM %d!",state));
}
void RDCatchConnect::reloadHeartbeat()
{
SendCommand("RH!");
}
void RDCatchConnect::reloadDropboxes()
{
SendCommand("RX!");
}
void RDCatchConnect::reset()
{
SendCommand("RS!");
}
void RDCatchConnect::reload()
{
SendCommand("RD!");
}
void RDCatchConnect::refresh()
{
SendCommand("RE 0!");
}
void RDCatchConnect::reloadOffset()
{
SendCommand("RO!");
}
void RDCatchConnect::stop(int deck)
{
SendCommand(QString().sprintf("SR %d!",deck));
}
void RDCatchConnect::monitor(int deck,bool state)
{
SendCommand(QString().sprintf("MN %d %d!",deck,state));
}
void RDCatchConnect::toggleMonitor(int deck)
{
if(cc_monitor_state[deck-1]) {
SendCommand(QString().sprintf("MN %d 0!",deck));
}
else {
SendCommand(QString().sprintf("MN %d 1!",deck));
}
}
void RDCatchConnect::setExitCode(int id,RDRecording::ExitCode code,
const QString &msg)
{
SendCommand(QString().sprintf("SC %d %d %s!",id,code,
(const char *)msg.simplifyWhiteSpace()));
}
void RDCatchConnect::connectedData()
{
SendCommand(QString().sprintf("PW %s!",(const char *)cc_password));
}
void RDCatchConnect::readyData()
{
char buf[1024];
int c;
while((c=cc_socket->readBlock(buf,254))>0) {
buf[c]=0;
// printf("readyData: %s\n",buf);
for(int i=0;i<c;i++) {
if(buf[i]==' ') {
if(argnum<CC_MAX_ARGS) {
args[argnum][argptr]=0;
argnum++;
argptr=0;
}
else {
if(debug) {
printf("Argument list truncated!\n");
}
}
}
if(buf[i]=='!') {
args[argnum++][argptr]=0;
DispatchCommand();
argnum=0;
argptr=0;
if(cc_socket==NULL) {
return;
}
}
if((isgraph(buf[i]))&&(buf[i]!='!')) {
if(argptr<CC_MAX_LENGTH) {
args[argnum][argptr]=buf[i];
argptr++;
}
else {
if(debug) {
printf("WARNING: argument truncated!\n");
}
}
}
}
}
}
void RDCatchConnect::heartbeatTimeoutData()
{
if(cc_heartbeat_valid) {
emit heartbeatFailed(cc_serial);
cc_heartbeat_valid=false;
}
}
void RDCatchConnect::SendCommand(QString cmd)
{
// printf("SendCommand(%s)\n",(const char *)cmd);
cc_socket->writeBlock((const char *)cmd,cmd.length());
}
void RDCatchConnect::DispatchCommand()
{
int deck;
int channel;
int level;
unsigned chan;
int status;
int id;
int number;
if(!strcmp(args[0],"PW")) { // Password Response
if(args[1][0]=='+') {
emit connected(cc_serial,true);
SendCommand("RE 0!");
}
else {
emit connected(cc_serial,false);
}
}
if(!strcmp(args[0],"DE")) { // Deck Event
if(sscanf(args[1],"%d",&deck)!=1) {
return;
}
if(sscanf(args[2],"%d",&number)!=1) {
return;
}
emit deckEventSent(cc_serial,deck,number);
}
if(!strcmp(args[0],"RE")) { // Channel Status
if(sscanf(args[1],"%u",&chan)!=1){
return;
}
if((chan<0)||((chan>(MAX_DECKS+1))&&(chan<(129)))||
(chan>(MAX_DECKS+129))) {
return;
}
if(sscanf(args[2],"%d",&status)!=1) {
return;
}
if(sscanf(args[3],"%d",&id)!=1) {
return;
}
if(chan==0) {
emit statusChanged(cc_serial,chan,(RDDeck::Status)status,id,"");
return;
}
chan--;
if(chan<=MAX_DECKS) {
if((status!=cc_record_deck_status[chan])||(id!=cc_record_id[chan])) {
cc_record_deck_status[chan]=(RDDeck::Status)status;
cc_record_id[chan]=id;
emit statusChanged(cc_serial,chan+1,cc_record_deck_status[chan],
cc_record_id[chan],args[4]);
}
}
if((chan>=128)&&(chan<MAX_DECKS+128)) {
if((status!=cc_play_deck_status[chan-128])||(id!=cc_play_id[chan-128])) {
cc_play_deck_status[chan-128]=(RDDeck::Status)status;
cc_play_id[chan-128]=id;
emit statusChanged(cc_serial,chan+1,cc_play_deck_status[chan-128],
cc_play_id[chan-128],args[4]);
}
}
return;
}
if(!strcmp(args[0],"RM")) { // Meter Level
if(sscanf(args[1],"%d",&deck)!=1) {
return;
}
if(sscanf(args[2],"%d",&channel)!=1) {
return;
}
if(sscanf(args[3],"%d",&level)!=1) {
return;
}
emit meterLevel(cc_serial,deck,channel,level);
return;
}
if(!strcmp(args[0],"RU")) { // Update Event
if(sscanf(args[1],"%d",&id)!=1) {
return;
}
emit eventUpdated(id);
}
if(!strcmp(args[0],"PE")) { // Purge Event
if(sscanf(args[1],"%d",&id)!=1) {
return;
}
emit eventPurged(id);
}
if(!strcmp(args[0],"HB")) { // Heartbeat
cc_heartbeat_timer->stop();
cc_heartbeat_timer->start(CC_HEARTBEAT_INTERVAL,true);
}
if(!strcmp(args[0],"MN")) { // Monitor State
if(sscanf(args[1],"%d",&deck)!=1) {
return;
}
if(args[2][0]=='1') {
cc_monitor_state[deck-1]=true;
emit monitorChanged(cc_serial,deck,true);
}
else {
cc_monitor_state[deck-1]=false;
emit monitorChanged(cc_serial,deck,false);
}
}
}