From c0962205702072f8856f43e012d6713937d0d226 Mon Sep 17 00:00:00 2001 From: Fred Gleason Date: Wed, 9 May 2018 17:34:08 +0000 Subject: [PATCH] 2018-05-09 Fred Gleason * Added rdvairplay(1). --- .gitignore | 1 + ChangeLog | 2 + Makefile.am | 1 + configure.ac | 1 + lib/rdapplication.cpp | 6 + lib/rdapplication.h | 1 + lib/rdlogplay.cpp | 9 +- rdvairplay/Makefile.am | 49 ++++ rdvairplay/local_macros.cpp | 563 ++++++++++++++++++++++++++++++++++++ rdvairplay/rdvairplay.cpp | 205 +++++++++++++ rdvairplay/rdvairplay.h | 61 ++++ 11 files changed, 896 insertions(+), 3 deletions(-) create mode 100644 rdvairplay/Makefile.am create mode 100644 rdvairplay/local_macros.cpp create mode 100644 rdvairplay/rdvairplay.cpp create mode 100644 rdvairplay/rdvairplay.h diff --git a/.gitignore b/.gitignore index b6f4e662..d6761b78 100644 --- a/.gitignore +++ b/.gitignore @@ -78,6 +78,7 @@ rdpanel/rdpanel rdrepld/rdrepld rdrepld-suse rdselect/rdselect +rdvairplay/rdvairplay ripcd/ripcd rivendell rivendell-suse diff --git a/ChangeLog b/ChangeLog index c80529ce..84f364d0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -16805,3 +16805,5 @@ methods. * Added a 'Allow WebGet Login' control in the 'Production Rights' section of the 'User' dialog in rdadmin(1). +2018-05-09 Fred Gleason + * Added rdvairplay(1). diff --git a/Makefile.am b/Makefile.am index f58eb310..a95944b6 100644 --- a/Makefile.am +++ b/Makefile.am @@ -56,6 +56,7 @@ SUBDIRS = icons\ rdpanel\ rdrepld\ rdselect\ + rdvairplay\ ripcd\ tests\ utils\ diff --git a/configure.ac b/configure.ac index df50dc1c..59a4f9e9 100644 --- a/configure.ac +++ b/configure.ac @@ -563,6 +563,7 @@ AC_CONFIG_FILES([rivendell.spec \ rdselect/Makefile \ rdmonitor/Makefile \ rdrepld/Makefile \ + rdvairplay/Makefile \ tests/Makefile \ importers/Makefile \ ios/Makefile \ diff --git a/lib/rdapplication.cpp b/lib/rdapplication.cpp index 110ac649..2dedc0a0 100644 --- a/lib/rdapplication.cpp +++ b/lib/rdapplication.cpp @@ -219,6 +219,12 @@ RDUser *RDApplication::user() } +void RDApplication::log(RDConfig::LogPriority prio,const QString &msg) +{ + app_config->log(app_module_name,prio,msg); +} + + void RDApplication::userChangedData() { app_user->setName(app_ripc->user()); diff --git a/lib/rdapplication.h b/lib/rdapplication.h index 8651a59e..f98a6e85 100644 --- a/lib/rdapplication.h +++ b/lib/rdapplication.h @@ -55,6 +55,7 @@ class RDApplication : public QObject RDStation *station(); RDSystem *system(); RDUser *user(); + void log(RDConfig::LogPriority prio,const QString &msg); private slots: void userChangedData(); diff --git a/lib/rdlogplay.cpp b/lib/rdlogplay.cpp index 7a98bd1d..fa8b412e 100644 --- a/lib/rdlogplay.cpp +++ b/lib/rdlogplay.cpp @@ -21,6 +21,8 @@ #include #include +#include + #include "rdapplication.h" #include "rdconf.h" #include "rddb.h" @@ -33,8 +35,8 @@ #include "rdsvc.h" RDLogPlay::RDLogPlay(int id,RDEventPlayer *player,QSocketDevice *nn_sock, - QString logname,std::vector *rlm_hosts, - QObject *parent) + QString logname,std::vector *rlm_hosts, + QObject *parent) : QObject(parent),RDLogEvent(logname) { // @@ -125,7 +127,8 @@ RDLogPlay::RDLogPlay(int id,RDEventPlayer *player,QSocketDevice *nn_sock, // play_audition_line=-1; if((rda->station()->cueCard()>=0)&& - (rda->station()->cuePort()>=0)) { + (rda->station()->cuePort()>=0)&& + (qApp->type()!=QApplication::Tty)) { play_audition_player= new RDSimplePlayer(play_cae,rda->ripc(),rda->station()->cueCard(), rda->station()->cuePort(),0,0); diff --git a/rdvairplay/Makefile.am b/rdvairplay/Makefile.am new file mode 100644 index 00000000..bb79aaf9 --- /dev/null +++ b/rdvairplay/Makefile.am @@ -0,0 +1,49 @@ +## Makefile.am +## +## Makefile for rdvairplay(1) +## +## (C) Copyright 2018 Fred Gleason +## +## 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. +## +## Use automake to process this into a Makefile.in + +AM_CPPFLAGS = -Wall -DPREFIX=\"$(prefix)\" -DQTDIR=\"@QT_DIR@\" @QT_CXXFLAGS@ -I$(top_srcdir)/lib +LIBS = @QT_LIBS@ -L$(top_srcdir)/lib +MOC = @QT_MOC@ + +# The dependency for qt's Meta Object Compiler (moc) +moc_%.cpp: %.h + $(MOC) $< -o $@ + +bin_PROGRAMS = rdvairplay + +dist_rdvairplay_SOURCES = local_macros.cpp\ + rdvairplay.cpp rdvairplay.h + +nodist_rdvairplay_SOURCES = moc_rdvairplay.cpp + +rdvairplay_LDADD = @LIB_RDLIBS@ @LIBVORBIS@ + +CLEANFILES = *~\ + *.idb\ + *ilk\ + *.obj\ + *.pdb\ + *.qm\ + moc_* + +MAINTAINERCLEANFILES = *~\ + Makefile.in\ + moc_* diff --git a/rdvairplay/local_macros.cpp b/rdvairplay/local_macros.cpp new file mode 100644 index 00000000..f112616d --- /dev/null +++ b/rdvairplay/local_macros.cpp @@ -0,0 +1,563 @@ +// local_macros.cpp +// +// Local RML Macros for the Rivendell's RDvAirPlay +// +// (C) Copyright 2002-2004,2016-2018 Fred Gleason +// +// 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 + +#include +#include +#include +#include + +#include "rdvairplay.h" + +void MainObject::rmlReceivedData(RDMacro *rml) +{ + QString logname; + int fade; + RDLogLine *logline=NULL; + int index=-1; + bool all_logs=false; + int start; + int end; + int next_line; + + if(rml->role()!=RDMacro::Cmd) { + return; + } + + switch(rml->command()) { + case RDMacro::LL: // Load Log + if((rml->argQuantity()<1)||(rml->argQuantity()>3)) { + if(rml->echoRequested()) { + rml->acknowledge(false); + rda->ripc()->sendRml(rml); + } + return; + } + if((index=LogMachineIndex(rml->arg(0).toInt()))<0) { + if(rml->echoRequested()) { + rml->acknowledge(false); + rda->ripc()->sendRml(rml); + } + return; + } + if(rml->argQuantity()==1) { // Clear Log + air_logs[index]->clear(); + rda->log(RDConfig::LogInfo,QString().sprintf("unloaded log machine %d", + rml->arg(0).toInt())); + } + else { // Load Log + logname=rml->arg(1).toString(); + if(!RDLog::exists(logname)) { + if(rml->echoRequested()) { + rml->acknowledge(false); + rda->ripc()->sendRml(rml); + } + return; + } + air_logs[index]->setLogName(RDLog::tableName(logname)); + air_logs[index]->load(); + rda->log(RDConfig::LogInfo,"loaded log \""+logname+"\" into log machine"+ + QString().sprintf(" %d",rml->arg(0).toInt())); + } + if(rml->argQuantity()==3) { // Start Log + if(rml->arg(2).toInt()size()) { + if(rml->arg(2).toInt()>=0) { // Unconditional start + air_logs[index]->play(rml->arg(2).toInt(),RDLogLine::StartMacro); + rda->log(RDConfig::LogInfo,QString(). + sprintf("started log machine %d at line %d", + rml->arg(0).toInt(),rml->arg(2).toInt())); + } + if(rml->arg(2).toInt()==-2) { // Start if trans type allows + // Find first non-running event + bool found=false; + for(int i=0;isize();i++) { + if((logline=air_logs[index]->logLine(i))!=NULL) { + if(logline->status()==RDLogLine::Scheduled) { + found=true; + i=air_logs[index]->size(); + } + } + } + if(found) { + switch(logline->transType()) { + case RDLogLine::Play: + case RDLogLine::Segue: + air_logs[index]->play(0,RDLogLine::StartMacro); + rda->log(RDConfig::LogInfo,QString(). + sprintf("started log machine %d at line 0", + rml->arg(0).toInt())); + break; + + case RDLogLine::Stop: + case RDLogLine::NoTrans: + break; + } + } + } + } + } + if(rml->echoRequested()) { + rml->acknowledge(true); + rda->ripc()->sendRml(rml); + } + break; + + case RDMacro::AL: // Append Log + if(rml->argQuantity()!=2) { + if(rml->echoRequested()) { + rml->acknowledge(false); + rda->ripc()->sendRml(rml); + } + return; + } + if((index=LogMachineIndex(rml->arg(0).toInt()))<0) { + if(rml->echoRequested()) { + rml->acknowledge(false); + rda->ripc()->sendRml(rml); + } + return; + } + logname=rml->arg(1).toString(); + if(!RDLog::exists(logname)) { + if(rml->echoRequested()) { + rml->acknowledge(false); + rda->ripc()->sendRml(rml); + } + return; + } + air_logs[index]->append(logname); + rda->log(RDConfig::LogInfo,QString("appended log \"")+logname+ + QString().sprintf("\" into log machine %d",rml->arg(0).toInt())); + break; + + case RDMacro::MN: // Make Next + if(rml->argQuantity()!=2) { + if(rml->echoRequested()) { + rml->acknowledge(false); + rda->ripc()->sendRml(rml); + } + return; + } + if((index=LogMachineIndex(rml->arg(0).toInt()))<0) { + if(rml->echoRequested()) { + rml->acknowledge(false); + rda->ripc()->sendRml(rml); + } + return; + } + if((rml->arg(1).toInt()<0)|| + (rml->arg(1).toInt()>=air_logs[index]->size())) { + if(rml->echoRequested()) { + rml->acknowledge(false); + rda->ripc()->sendRml(rml); + } + return; + } + air_logs[index]->makeNext(rml->arg(1).toInt()); + rda->log(RDConfig::LogInfo, + QString().sprintf("made line %d next in log machine %d", + rml->arg(1).toInt(),rml->arg(0).toInt())); + if(rml->echoRequested()) { + rml->acknowledge(true); + rda->ripc()->sendRml(rml); + } + break; + + case RDMacro::PL: // Start + if(rml->argQuantity()!=2) { + if(rml->echoRequested()) { + rml->acknowledge(false); + rda->ripc()->sendRml(rml); + } + return; + } + if((index=LogMachineIndex(rml->arg(0).toInt()))<0) { + if(rml->echoRequested()) { + rml->acknowledge(false); + rda->ripc()->sendRml(rml); + } + return; + } + if((rml->arg(1).toInt()<0)|| + (rml->arg(1).toInt()>=air_logs[index]->size())) { + if(rml->echoRequested()) { + rml->acknowledge(false); + rda->ripc()->sendRml(rml); + } + return; + } + if(!air_logs[index]->running()) { + if(!air_logs[index]->play(rml->arg(1).toInt(),RDLogLine::StartMacro)) { + if(rml->echoRequested()) { + rml->acknowledge(false); + rda->ripc()->sendRml(rml); + } + return; + } + } + rda->log(RDConfig::LogInfo,QString(). + sprintf("started log machine %d at line %d", + rml->arg(0).toInt(),rml->arg(1).toInt())); + if(rml->echoRequested()) { + rml->acknowledge(true); + rda->ripc()->sendRml(rml); + } + break; + + case RDMacro::PM: // Set Mode + if((rml->argQuantity()!=1)&&(rml->argQuantity()!=2)) { + if(rml->echoRequested()) { + rml->acknowledge(false); + rda->ripc()->sendRml(rml); + } + return; + } + if(rml->argQuantity()==2) { + if((index=LogMachineIndex(rml->arg(1).toInt()))<0) { + if(rml->echoRequested()) { + rml->acknowledge(false); + rda->ripc()->sendRml(rml); + } + return; + } + } + start=0; + end=RD_RDVAIRPLAY_LOG_QUAN; + if(index>=0) { + start=index; + end=index+1; + } + switch((RDAirPlayConf::OpMode)rml->arg(0).toInt()) { + case RDAirPlayConf::LiveAssist: + for(int i=start;iechoRequested()) { + rml->acknowledge(false); + rda->ripc()->sendRml(rml); + return; + } + } + if(rml->echoRequested()) { + rml->acknowledge(true); + rda->ripc()->sendRml(rml); + } + break; + + case RDMacro::PN: // Start Next + if((rml->argQuantity()<1)||(rml->argQuantity()>3)) { + if(rml->echoRequested()) { + rml->acknowledge(false); + rda->ripc()->sendRml(rml); + } + return; + } + if((index=LogMachineIndex(rml->arg(0).toInt()))<0) { + if(rml->echoRequested()) { + rml->acknowledge(false); + rda->ripc()->sendRml(rml); + } + return; + } + if(rml->argQuantity()>=2) { + if((rml->arg(1).toInt()<1)||(rml->arg(1).toInt()>2)) { + if(rml->echoRequested()) { + rml->acknowledge(false); + rda->ripc()->sendRml(rml); + } + return; + } + if(rml->argQuantity()==3) { + if((rml->arg(2).toInt()<0)||(rml->arg(2).toInt()>1)) { + if(rml->echoRequested()) { + rml->acknowledge(false); + rda->ripc()->sendRml(rml); + } + return; + } + } + } + next_line=air_logs[index]->nextLine(); + if(air_logs[index]->nextLine()>=0) { + if(rml->argQuantity()==1) { + air_logs[index]-> + play(air_logs[index]->nextLine(),RDLogLine::StartMacro); + } + else { + if(rml->argQuantity()==2) { + air_logs[index]->play(air_logs[index]->nextLine(), + RDLogLine::StartMacro,rml->arg(1).toInt()-1); + } + else { + air_logs[index]-> + play(air_logs[index]->nextLine(),RDLogLine::StartMacro, + rml->arg(1).toInt()-1,rml->arg(2).toInt()); + } + } + rda->log(RDConfig::LogInfo,QString(). + sprintf("started log machine %d at line %d", + rml->arg(0).toInt(),next_line)); + } + if(rml->echoRequested()) { + rml->acknowledge(true); + rda->ripc()->sendRml(rml); + } + break; + + case RDMacro::PS: // Stop + if((rml->argQuantity()<1)||(rml->argQuantity()>3)) { + if(rml->echoRequested()) { + rml->acknowledge(false); + rda->ripc()->sendRml(rml); + } + return; + } + index=LogMachineIndex(rml->arg(0).toInt(),&all_logs); + if((index<0)&(!all_logs)) { + if(rml->echoRequested()) { + rml->acknowledge(false); + rda->ripc()->sendRml(rml); + } + return; + } + fade=0; + if(rml->argQuantity()>1) { + fade=rml->arg(1).toInt(); + } + if(all_logs) { + for(int i=0;istop(true,0,fade); + } + rda->log(RDConfig::LogInfo,"stopped all logs"); + } + else { + if(rml->argQuantity()==3) { + air_logs[index]->stop(false,rml->arg(2).toInt(),fade); + } + else { + air_logs[index]->stop(true,0,fade); + } + rda->log(RDConfig::LogInfo,QString().sprintf("stopped log machine %d", + rml->arg(0).toInt())); + break; + } + if(rml->echoRequested()) { + rml->acknowledge(true); + rda->ripc()->sendRml(rml); + } + break; + + case RDMacro::MD: // Duck Machine + if(rml->argQuantity()<3 || rml->argQuantity()>4) { + if(rml->echoRequested()) { + rml->acknowledge(false); + rda->ripc()->sendRml(rml); + } + return; + } + index=LogMachineIndex(rml->arg(0).toInt(),&all_logs); + if((index<0)&&(!all_logs)) { + if(rml->echoRequested()) { + rml->acknowledge(false); + rda->ripc()->sendRml(rml); + } + return; + } + if(all_logs) { + for(int i=0;iduckVolume(rml->arg(1).toInt()*100,rml->arg(2).toInt()); + } + rda->log(RDConfig::LogInfo,QString(). + sprintf("set volumne of all log machines to %d dBFS", + rml->arg(1).toInt())); + } + else { + if(rml->argQuantity()==3) { + air_logs[index]-> + duckVolume(rml->arg(1).toInt()*100,rml->arg(2).toInt()); + } + else { + air_logs[index]->duckVolume(rml->arg(1).toInt()*100, + rml->arg(2).toInt(),rml->arg(3).toInt()); + } + rda->log(RDConfig::LogInfo,QString(). + sprintf("set volumne of log machine %d to %d dBFS", + rml->arg(0).toInt(), + rml->arg(1).toInt())); + break; + } + if(rml->echoRequested()) { + rml->acknowledge(true); + rda->ripc()->sendRml(rml); + } + break; + + case RDMacro::PX: // Add Next + if(rml->argQuantity()!=2) { + if(rml->echoRequested()) { + rml->acknowledge(false); + rda->ripc()->sendRml(rml); + } + return; + } + index=LogMachineIndex(rml->arg(0).toInt()); + if((index<0)||(rml->arg(1).toUInt()>999999)) { + if(rml->echoRequested()) { + rml->acknowledge(false); + rda->ripc()->sendRml(rml); + } + return; + } + next_line=air_logs[index]->nextLine(); + if(air_logs[index]->nextLine()>=0) { + air_logs[index]->insert(air_logs[index]->nextLine(), + rml->arg(1).toUInt(),RDLogLine::Play); + rda->log(RDConfig::LogInfo,QString(). + sprintf("inserted cart %06u at line %d on log machine %d", + rml->arg(1).toUInt(),next_line,rml->arg(0).toInt())); + } + else { + air_logs[index]->insert(air_logs[index]->size(), + rml->arg(1).toUInt(),RDLogLine::Play); + air_logs[index]->makeNext(air_logs[index]->size()-1); + rda->log(RDConfig::LogInfo,QString(). + sprintf("inserted cart %06u at line %d on log machine %d", + rml->arg(1).toUInt(),air_logs[index]->size()-1, + rml->arg(0).toInt())); + } + if(rml->echoRequested()) { + rml->acknowledge(true); + rda->ripc()->sendRml(rml); + } + break; + + case RDMacro::RL: // Refresh Log + if(rml->argQuantity()!=1) { + if(rml->echoRequested()) { + rml->acknowledge(false); + rda->ripc()->sendRml(rml); + } + return; + } + if((index=LogMachineIndex(rml->arg(0).toInt()))<0) { + if(rml->echoRequested()) { + rml->acknowledge(false); + rda->ripc()->sendRml(rml); + } + return; + } + if(!air_logs[index]->refresh()) { + if(rml->echoRequested()) { + rml->acknowledge(false); + rda->ripc()->sendRml(rml); + } + return; + } + else { + rda->log(RDConfig::LogInfo,QString().sprintf("refreshed log machine %d", + rml->arg(0).toInt())); + } + if(rml->echoRequested()) { + rml->acknowledge(true); + rda->ripc()->sendRml(rml); + } + break; + + case RDMacro::SN: // Set default Now & Next Cart + if(rml->argQuantity()!=3) { + if(rml->echoRequested()) { + rml->acknowledge(false); + rda->ripc()->sendRml(rml); + } + return; + } + if((rml->arg(0).toString().lower()!="now")&& + (rml->arg(0).toString().lower()!="next")) { + if(rml->echoRequested()) { + rml->acknowledge(false); + rda->ripc()->sendRml(rml); + } + return; + } + if((index=LogMachineIndex(rml->arg(1).toInt()))<0) { + if(rml->echoRequested()) { + rml->acknowledge(false); + rda->ripc()->sendRml(rml); + } + return; + } + if(rml->arg(2).toUInt()>999999) { + if(rml->echoRequested()) { + rml->acknowledge(false); + rda->ripc()->sendRml(rml); + } + return; + } + if(rml->arg(0).toString().lower()=="now") { + air_logs[index]->setNowCart(rml->arg(2).toUInt()); + rda->log(RDConfig::LogInfo,QString(). + sprintf("set default \"now\" cart to %06u on log machine %d", + rml->arg(2).toUInt(),rml->arg(1).toInt())); + } + else { + air_logs[index]->setNextCart(rml->arg(2).toUInt()); + rda->log(RDConfig::LogInfo,QString(). + sprintf("set default \"next\" cart to %06u on log machine %d", + rml->arg(2).toUInt(),rml->arg(1).toInt())); + } + if(rml->echoRequested()) { + rml->acknowledge(true); + rda->ripc()->sendRml(rml); + } + break; + + default: + break; + } +} + + +int MainObject::LogMachineIndex(int log_mach,bool *all) const +{ + if((log_mach<=RD_RDVAIRPLAY_LOG_BASE)|| + (log_mach>RD_RDVAIRPLAY_LOG_BASE+RD_RDVAIRPLAY_LOG_QUAN)) { + return -1; + } + if(all!=NULL) { + *all=log_mach-RD_RDVAIRPLAY_LOG_BASE==0; + } + return log_mach-RD_RDVAIRPLAY_LOG_BASE-1; +} diff --git a/rdvairplay/rdvairplay.cpp b/rdvairplay/rdvairplay.cpp new file mode 100644 index 00000000..04ed6038 --- /dev/null +++ b/rdvairplay/rdvairplay.cpp @@ -0,0 +1,205 @@ +// rdvairplay.cpp +// +// Headless RDAirPlay +// +// (C) Copyright 2018 Fred Gleason +// +// 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 +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include "rdvairplay.h" + +MainObject::MainObject(QObject *parent) + :QObject(parent) +{ + QString err_msg; + + // + // Ensure Single Instance + // + air_lock=new RDInstanceLock(QString().sprintf("%s/.rdvairplaylock", + (const char *)RDHomeDir())); + if(!air_lock->lock()) { + fprintf(stderr,"rdvairplay: multiple instances not allowed\n"); + exit(1); + } + + // + // Ensure that system daemons are running + // + RDInitializeDaemons(); + + // + // Open the Database + // + rda=new RDApplication("rdvairplay","rdvairplay",RDVAIRPLAY_USAGE,this); + if(!rda->open(&err_msg)) { + fprintf(stderr,"rdvairplay: %s\n",(const char *)err_msg); + exit(1); + } + + // + // Read Command Options + // + for(unsigned i=0;icmdSwitch()->keys();i++) { + if(!rda->cmdSwitch()->processed(i)) { + fprintf(stderr,"rdvairplay: unknown command option \"%s\"\n", + (const char *)rda->cmdSwitch()->key(i)); + exit(2); + } + } + + // + // CAE Connection + // + rda->cae()->connectHost(); + + // + // Set Audio Assignments + // + // air_segue_length=rda->airplayConf()->segueLength()+1; + RDSetMixerPorts(rda->config()->stationName(),rda->cae()); + + // + // RIPC Connection + // + // connect(rda->ripc(),SIGNAL(connected(bool)),this,SLOT(ripcConnected(bool))); + connect(rda,SIGNAL(userChanged()),this,SLOT(userData())); + connect(rda->ripc(),SIGNAL(rmlReceived(RDMacro *)), + this,SLOT(rmlReceivedData(RDMacro *))); + // connect(rda->ripc(),SIGNAL(gpiStateChanged(int,int,bool)), + // this,SLOT(gpiStateChangedData(int,int,bool))); + rda->ripc()-> + connectHost("localhost",RIPCD_TCP_PORT,rda->config()->password()); + + // + // Macro Player + // + air_event_player=new RDEventPlayer(rda->ripc(),this); + + // + // UDP Transmission Socket + // + air_nownext_socket=new QSocketDevice(QSocketDevice::Datagram); + + // + // Log Machines + // + QSignalMapper *reload_mapper=new QSignalMapper(this); + connect(reload_mapper,SIGNAL(mapped(int)),this,SLOT(logReloadedData(int))); + QSignalMapper *rename_mapper=new QSignalMapper(this); + // connect(rename_mapper,SIGNAL(mapped(int)),this,SLOT(logRenamedData(int))); + QString default_svcname=rda->airplayConf()->defaultSvc(); + for(int i=0;isetDefaultServiceName(default_svcname); + air_logs[i]->setNowCart(rda->airplayConf()->logNowCart(i)); + air_logs[i]->setNextCart(rda->airplayConf()->logNextCart(i)); + reload_mapper->setMapping(air_logs[i],i); + connect(air_logs[i],SIGNAL(reloaded()),reload_mapper,SLOT(map())); + rename_mapper->setMapping(air_logs[i],i); + connect(air_logs[i],SIGNAL(renamed()),rename_mapper,SLOT(map())); + // connect(air_logs[i],SIGNAL(refreshStatusChanged(bool)), + // this,SLOT(refreshStatusChangedData(bool))); + // connect(air_logs[i],SIGNAL(channelStarted(int,int,int,int)), + // this,SLOT(logChannelStartedData(int,int,int,int))); + // connect(air_logs[i],SIGNAL(channelStopped(int,int,int,int)), + // this,SLOT(logChannelStoppedData(int,int,int,int))); + int chans[2]={0,0}; + int ports[2]={0,0}; + QString start_rml[2]={"",""}; + QString stop_rml[2]={"",""}; + air_logs[i]->setChannels(chans,ports,start_rml,stop_rml); + } + // connect(air_logs[0],SIGNAL(transportChanged()), + // this,SLOT(transportChangedData())); + +} + + +void MainObject::userData() +{ + printf("User connected!\n"); +} + + +void MainObject::logReloadedData(int log) +{ +} + + +void MainObject::SetAutoMode(int index) +{ + air_logs[index]->setOpMode(RDAirPlayConf::Auto); + rda->log(RDConfig::LogInfo, + QString().sprintf("log machine %d mode set to AUTOMATIC", + index+RD_RDVAIRPLAY_LOG_BASE+1)); +} + + +void MainObject::SetLiveAssistMode(int index) +{ + /* + if(mach==0) { + air_pie_counter->setOpMode(RDAirPlayConf::LiveAssist); + } + air_mode_display->setOpMode(mach,RDAirPlayConf::LiveAssist); + air_op_mode[mach]=RDAirPlayConf::LiveAssist; + rda->airplayConf()->setOpMode(mach,RDAirPlayConf::LiveAssist); + */ + air_logs[index]->setOpMode(RDAirPlayConf::LiveAssist); + /* + air_log_list[mach]->setOpMode(RDAirPlayConf::LiveAssist); + if(mach==0) { + air_button_list->setOpMode(RDAirPlayConf::LiveAssist); + air_post_counter->setDisabled(true); + } + */ + rda->log(RDConfig::LogInfo, + QString().sprintf("log machine %d mode set to LIVE ASSIST", + index+RD_RDVAIRPLAY_LOG_BASE+1)); +} + + +void MainObject::SetManualMode(int index) +{ + air_logs[index]->setOpMode(RDAirPlayConf::Manual); + rda->log(RDConfig::LogInfo, + QString().sprintf("log machine %d mode set to MANUAL", + index+RD_RDVAIRPLAY_LOG_BASE+1)); +} + + +int main(int argc,char *argv[]) +{ + QApplication a(argc,argv,false); + new MainObject(); + return a.exec(); +} diff --git a/rdvairplay/rdvairplay.h b/rdvairplay/rdvairplay.h new file mode 100644 index 00000000..d2833b14 --- /dev/null +++ b/rdvairplay/rdvairplay.h @@ -0,0 +1,61 @@ +// rdvairplay.h +// +// Headless RDAirPlay +// +// (C) Copyright 2018 Fred Gleason +// +// 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 RDVAIRPLAY_H +#define RDVAIRPLAY_H + +#include +#include + +#include +#include +#include +#include +#include + +#define RD_RDVAIRPLAY_LOG_BASE 100 +#define RD_RDVAIRPLAY_LOG_QUAN 1 +#define RDVAIRPLAY_USAGE "[options]\n" + +class MainObject : public QObject +{ + Q_OBJECT; + public: + MainObject(QObject *parent=0); + + private slots: + void userData(); + void rmlReceivedData(RDMacro*); + void logReloadedData(int log); + + private: + void SetAutoMode(int index); + void SetLiveAssistMode(int index); + void SetManualMode(int index); + int LogMachineIndex(int log_mach,bool *all=NULL) const; + RDLogPlay *air_logs[RD_RDVAIRPLAY_LOG_QUAN]; + std::vector air_plugin_hosts; + RDInstanceLock *air_lock; + RDEventPlayer *air_event_player; + QSocketDevice *air_nownext_socket; +}; + + +#endif // RDVAIRPLAY_H