From d9023b1430e85684e7bb0d80fccbf484dde7bbcd Mon Sep 17 00:00:00 2001 From: Fred Gleason Date: Wed, 18 May 2016 17:03:25 -0400 Subject: [PATCH] 2016-05-18 Fred Gleason * Added support for the RDCatchd 'DE' command in 'rdcatchd/rdcatchd.cpp', 'rdcatchd/rdcatchd.h', 'rdcatchd/event_player.cpp', 'rdcatchd/event_player.h' and 'rdcatchd/local_macros.cpp'. * Added a deck event indicator to RDCatch's deck monitor in 'rdcatch/deckmon.cpp' and 'rdcatch/deckmon.h'. --- ChangeLog | 7 ++ docs/catchd.txt | 3 + lib/rdcatch_connect.cpp | 11 +++ lib/rdcatch_connect.h | 1 + rdcatch/deckmon.cpp | 146 ++++++++++++++++++++++++-------------- rdcatch/deckmon.h | 13 ++-- rdcatch/rdcatch.cpp | 12 ++++ rdcatch/rdcatch.h | 1 + rdcatchd/event_player.cpp | 8 +-- rdcatchd/event_player.h | 2 +- rdcatchd/local_macros.cpp | 1 + rdcatchd/rdcatchd.cpp | 13 +++- rdcatchd/rdcatchd.h | 3 +- 13 files changed, 152 insertions(+), 69 deletions(-) diff --git a/ChangeLog b/ChangeLog index 02552605..6c72b678 100644 --- a/ChangeLog +++ b/ChangeLog @@ -15140,3 +15140,10 @@ * Implemented a 'Cut Event' ['CE'] RML. * Added a 'Event Carts' section to the Edit Deck dialog in 'rdadmin/edit_deck.cpp' and 'rdadmin/edit_deck.h'. +2016-05-18 Fred Gleason + * Added support for the RDCatchd 'DE' command in + 'rdcatchd/rdcatchd.cpp', 'rdcatchd/rdcatchd.h', + 'rdcatchd/event_player.cpp', 'rdcatchd/event_player.h' and + 'rdcatchd/local_macros.cpp'. + * Added a deck event indicator to RDCatch's deck monitor in + 'rdcatch/deckmon.cpp' and 'rdcatch/deckmon.h'. diff --git a/docs/catchd.txt b/docs/catchd.txt index 8662c38d..1ce27004 100644 --- a/docs/catchd.txt +++ b/docs/catchd.txt @@ -29,6 +29,9 @@ authentication. PRIVILEDGED - a connection must be authenticated before these can be executed. +DE ! -- Deck Event Processed +Sent by RDCatchd whenever a deck event is processed. + RD! -- Reload Deck List Reload the record/play deck configuration. Rdcatchd will respond with RD +!. diff --git a/lib/rdcatch_connect.cpp b/lib/rdcatch_connect.cpp index 10b92c10..cea88cfd 100644 --- a/lib/rdcatch_connect.cpp +++ b/lib/rdcatch_connect.cpp @@ -263,6 +263,7 @@ void RDCatchConnect::DispatchCommand() unsigned chan; int status; int id; + int number; if(!strcmp(args[0],"PW")) { // Password Response if(args[1][0]=='+') { @@ -274,6 +275,16 @@ void RDCatchConnect::DispatchCommand() } } + 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; diff --git a/lib/rdcatch_connect.h b/lib/rdcatch_connect.h index 730c921f..6fb143fe 100644 --- a/lib/rdcatch_connect.h +++ b/lib/rdcatch_connect.h @@ -72,6 +72,7 @@ class RDCatchConnect : public QObject void meterLevel(int serial,int deck,int chan,int level); void eventUpdated(int id); void eventPurged(int id); + void deckEventSent(int serial,int chan,int number); void heartbeatFailed(int id); private slots: diff --git a/rdcatch/deckmon.cpp b/rdcatch/deckmon.cpp index 58a080a9..6927dd11 100644 --- a/rdcatch/deckmon.cpp +++ b/rdcatch/deckmon.cpp @@ -2,9 +2,7 @@ // // Monitor a Rivendell RDCatch Deck // -// (C) Copyright 2002-2004 Fred Gleason -// -// $Id: deckmon.cpp,v 1.25 2010/07/29 19:32:36 cvs Exp $ +// (C) Copyright 2002-2016 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 @@ -29,9 +27,8 @@ #include -DeckMon::DeckMon(QString station,unsigned channel, - QWidget *parent,const char *name) - : QFrame(parent,name) +DeckMon::DeckMon(QString station,unsigned channel,QWidget *parent) + : QFrame(parent) { mon_station=station; mon_channel=channel; @@ -47,11 +44,24 @@ DeckMon::DeckMon(QString station,unsigned channel, small_font.setPixelSize(6); QFont label_font("Helvetica",12,QFont::Normal); label_font.setPixelSize(12); + QFont event_font("Helvetica",12,QFont::Bold); + event_font.setPixelSize(12); + + // + // Generate Palettes + // + mon_red_palette=palette(); + mon_red_palette.setColor(QColorGroup::Background,Qt::darkRed); + mon_red_palette.setColor(QColorGroup::Foreground,Qt::white); + mon_dark_palette=palette(); + mon_dark_palette. + setColor(QColorGroup::Background,palette().color(QPalette::Active,QColorGroup::Mid)); + mon_dark_palette.setColor(QColorGroup::Foreground,Qt::white); // // Station/Channel // - mon_station_label=new QLabel(this,"mon_station_label"); + mon_station_label=new QLabel(this); mon_station_label->setFont(label_font); if((mon_channel>0)&&(mon_channel<(MAX_DECKS+1))) { mon_station_label-> @@ -67,7 +77,7 @@ DeckMon::DeckMon(QString station,unsigned channel, // // Monitor Button // - mon_monitor_button=new QPushButton(this,"mon_monitor_button"); + mon_monitor_button=new QPushButton(this); mon_monitor_button->setFont(small_font); mon_monitor_button->setText(tr("MON")); mon_monitor_palette=new QPalette(QColor(BUTTON_MONITOR_FLASHING_COLOR), @@ -81,7 +91,7 @@ DeckMon::DeckMon(QString station,unsigned channel, // // Abort Button // - mon_abort_button=new QPushButton(this,"mon_abort_button"); + mon_abort_button=new QPushButton(this); mon_abort_button->setFont(small_font); mon_abort_button->setText(tr("ABORT")); mon_abort_button->setDisabled(true); @@ -90,25 +100,37 @@ DeckMon::DeckMon(QString station,unsigned channel, // // Cut // - mon_cut_label=new QLabel(this,"mon_cut_label"); + mon_cut_label=new QLabel(this); mon_cut_label->setFont(label_font); + // + // Event Indicator + // + mon_event_label=new QLabel(this); + mon_event_label->setFont(event_font); + mon_event_label->setAlignment(Qt::AlignCenter); + mon_event_label->setFrameStyle(QFrame::Panel|QFrame::Sunken); + mon_event_label->setPalette(mon_dark_palette); + mon_event_label->setText("--"); + mon_event_timer=new QTimer(this); + connect(mon_event_timer,SIGNAL(timeout()),this,SLOT(eventResetData())); + // // Status // - mon_status_label=new QLabel(tr("OFFLINE"),this,"mon_status_label"); + mon_status_label=new QLabel(tr("OFFLINE"),this); mon_status_label->setFont(label_font); // // Audio Meter // - mon_left_meter=new RDPlayMeter(RDSegMeter::Right,this,"mon_left_meter"); + mon_left_meter=new RDPlayMeter(RDSegMeter::Right,this); mon_left_meter->setMode(RDSegMeter::Peak); mon_left_meter->setRange(-4600,-800); mon_left_meter->setHighThreshold(-1600); mon_left_meter->setClipThreshold(-1100); mon_left_meter->setLabel(tr("L")); - mon_right_meter=new RDPlayMeter(RDSegMeter::Right,this,"mon_right_meter"); + mon_right_meter=new RDPlayMeter(RDSegMeter::Right,this); mon_right_meter->setMode(RDSegMeter::Peak); mon_right_meter->setRange(-4600,-800); mon_right_meter->setHighThreshold(-1600); @@ -174,49 +196,58 @@ void DeckMon::setStatus(RDDeck::Status status,int id,const QString &cutname) return; } switch(status) { - case RDDeck::Offline: - mon_status_label->setText(tr("OFFLINE")); - SetCutInfo(0,""); - mon_left_meter->setPeakBar(-10000); - mon_right_meter->setPeakBar(-10000); - mon_abort_button->setDisabled(true); - break; + case RDDeck::Offline: + mon_status_label->setText(tr("OFFLINE")); + SetCutInfo(0,""); + mon_left_meter->setPeakBar(-10000); + mon_right_meter->setPeakBar(-10000); + mon_abort_button->setDisabled(true); + break; - case RDDeck::Idle: - mon_status_label->setText(tr("IDLE")); - SetCutInfo(0,""); - mon_left_meter->setPeakBar(-10000); - mon_right_meter->setPeakBar(-10000); - mon_abort_button->setDisabled(true); - break; + case RDDeck::Idle: + mon_status_label->setText(tr("IDLE")); + SetCutInfo(0,""); + mon_left_meter->setPeakBar(-10000); + mon_right_meter->setPeakBar(-10000); + mon_abort_button->setDisabled(true); + break; - case RDDeck::Ready: - mon_status_label->setText(tr("READY")); - SetCutInfo(id,""); - mon_left_meter->setPeakBar(-10000); - mon_right_meter->setPeakBar(-10000); - mon_abort_button->setEnabled(true); - break; + case RDDeck::Ready: + mon_status_label->setText(tr("READY")); + SetCutInfo(id,""); + mon_left_meter->setPeakBar(-10000); + mon_right_meter->setPeakBar(-10000); + mon_abort_button->setEnabled(true); + break; - case RDDeck::Waiting: - mon_status_label->setText(tr("WAITING")); - SetCutInfo(id,""); - mon_left_meter->setPeakBar(-10000); - mon_right_meter->setPeakBar(-10000); - mon_abort_button->setEnabled(true); - break; + case RDDeck::Waiting: + mon_status_label->setText(tr("WAITING")); + SetCutInfo(id,""); + mon_left_meter->setPeakBar(-10000); + mon_right_meter->setPeakBar(-10000); + mon_abort_button->setEnabled(true); + break; - case RDDeck::Recording: - if((mon_channel>0)&&(mon_channel<(MAX_DECKS+1))) { - mon_status_label->setText(tr("RECORDING")); - } - if((mon_channel>128)&&(mon_channel<(MAX_DECKS+129))) { - mon_status_label->setText(tr("PLAYING")); - } - SetCutInfo(id,cutname); - mon_abort_button->setEnabled(true); - break; + case RDDeck::Recording: + if((mon_channel>0)&&(mon_channel<(MAX_DECKS+1))) { + mon_status_label->setText(tr("RECORDING")); + } + if((mon_channel>128)&&(mon_channel<(MAX_DECKS+129))) { + mon_status_label->setText(tr("PLAYING")); + } + SetCutInfo(id,cutname); + mon_abort_button->setEnabled(true); + break; } + mon_event_label->setText("--"); +} + + +void DeckMon::setEvent(int number) +{ + mon_event_label->setText(QString().sprintf("%d",number)); + mon_event_label->setPalette(mon_red_palette); + mon_event_timer->start(1000,true); } @@ -244,13 +275,20 @@ void DeckMon::abortButtonData() } +void DeckMon::eventResetData() +{ + mon_event_label->setPalette(mon_dark_palette); +} + + void DeckMon::resizeEvent(QResizeEvent *e) { - mon_station_label->setGeometry(10,10,150,12); + mon_station_label->setGeometry(10,6,140,18); mon_monitor_button->setGeometry(155,5,40,20); mon_abort_button->setGeometry(200,5,40,20); - mon_cut_label->setGeometry(260,10,e->size().width()-580,12); - mon_status_label->setGeometry(e->size().width()-320,10,80,12); + mon_cut_label->setGeometry(245,6,e->size().width()-595,18); + mon_event_label->setGeometry(e->size().width()-345,6,20,18); + mon_status_label->setGeometry(e->size().width()-320,6,80,18); mon_left_meter->setGeometry(e->size().width()-235,6,225,10); mon_right_meter->setGeometry(e->size().width()-235,16,225,10); QFrame::resizeEvent(e); diff --git a/rdcatch/deckmon.h b/rdcatch/deckmon.h index 97dace09..96a0b624 100644 --- a/rdcatch/deckmon.h +++ b/rdcatch/deckmon.h @@ -2,9 +2,7 @@ // // Monitor a Rivendell Netcatcher Deck // -// (C) Copyright 2002-2004 Fred Gleason -// -// $Id: deckmon.h,v 1.15 2010/07/29 19:32:36 cvs Exp $ +// (C) Copyright 2002-2016 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 @@ -37,8 +35,7 @@ class DeckMon : public QFrame { Q_OBJECT public: - DeckMon(QString station,unsigned channel, - QWidget *parent=0,const char *name=0); + DeckMon(QString station,unsigned channel,QWidget *parent=0); ~DeckMon(); QSize sizeHint() const; QSizePolicy sizePolicy() const; @@ -51,6 +48,7 @@ class DeckMon : public QFrame public slots: void setMonitor(bool state); void setStatus(RDDeck::Status status,int id,const QString &cutname); + void setEvent(int number); void setLeftMeter(int level); void setRightMeter(int level); @@ -64,11 +62,13 @@ class DeckMon : public QFrame private slots: void monitorButtonData(); void abortButtonData(); + void eventResetData(); private: void SetCutInfo(int id,const QString &cutname); QLabel *mon_station_label; QLabel *mon_cut_label; + QLabel *mon_event_label; QLabel *mon_status_label; QPushButton *mon_abort_button; QPushButton *mon_monitor_button; @@ -77,6 +77,9 @@ class DeckMon : public QFrame RDPlayMeter *mon_right_meter; QString mon_station; unsigned mon_channel; + QTimer *mon_event_timer; + QPalette mon_red_palette; + QPalette mon_dark_palette; }; diff --git a/rdcatch/rdcatch.cpp b/rdcatch/rdcatch.cpp index 43a03928..65f04e32 100644 --- a/rdcatch/rdcatch.cpp +++ b/rdcatch/rdcatch.cpp @@ -296,6 +296,9 @@ MainWidget::MainWidget(QWidget *parent,const char *name) connect(catch_connect[catch_station_count].connect, SIGNAL(eventPurged(int)), this,SLOT(eventPurgedData(int))); + connect(catch_connect[catch_station_count].connect, + SIGNAL(deckEventSent(int,int,int)), + this,SLOT(deckEventSentData(int,int,int))); connect(catch_connect[catch_station_count].connect, SIGNAL(heartbeatFailed(int)), this,SLOT(heartbeatFailedData(int))); @@ -1040,6 +1043,15 @@ void MainWidget::monitorChangedData(int serial,unsigned chan,bool state) } +void MainWidget::deckEventSentData(int serial,int chan,int number) +{ + int mon=GetMonitor(serial,chan); + if(mon>=0) { + catch_monitor[mon]->deckMon()->setEvent(number); + } +} + + void MainWidget::scrollButtonData() { EnableScroll(!catch_scroll); diff --git a/rdcatch/rdcatch.h b/rdcatch/rdcatch.h index b3674c93..218cf3ef 100644 --- a/rdcatch/rdcatch.h +++ b/rdcatch/rdcatch.h @@ -83,6 +83,7 @@ class MainWidget : public QWidget void statusChangedData(int,unsigned,RDDeck::Status,int, const QString &cutname); void monitorChangedData(int serial,unsigned chan,bool state); + void deckEventSentData(int serial,int chan,int number); void scrollButtonData(); void reportsButtonData(); void headButtonData(); diff --git a/rdcatchd/event_player.cpp b/rdcatchd/event_player.cpp index f7bfd51c..c3faf23e 100644 --- a/rdcatchd/event_player.cpp +++ b/rdcatchd/event_player.cpp @@ -99,14 +99,12 @@ void EventPlayer::timeoutData() // // Dispatch current event // - if(event_numbers[event_current_event]>=(int)event_deck_events.size()) { + if(event_numbers[event_current_event]>(int)event_deck_events.size()) { syslog(LOG_ERR,"playout cut event referenced non-existent deck event"); return; } - unsigned cartnum=event_deck_events[event_numbers[event_current_event]-1]; - if(cartnum>0) { - emit runCart(cartnum); - } + emit runCart(event_channel,event_numbers[event_current_event], + event_deck_events[event_numbers[event_current_event]-1]); // // Set up next event diff --git a/rdcatchd/event_player.h b/rdcatchd/event_player.h index b98c6a89..ccf336c7 100644 --- a/rdcatchd/event_player.h +++ b/rdcatchd/event_player.h @@ -39,7 +39,7 @@ class EventPlayer : public QObject void stop(); signals: - void runCart(unsigned cartnum); + void runCart(int chan,int number,unsigned cartnum); private slots: void timeoutData(); diff --git a/rdcatchd/local_macros.cpp b/rdcatchd/local_macros.cpp index 743d8890..fd04e5e0 100644 --- a/rdcatchd/local_macros.cpp +++ b/rdcatchd/local_macros.cpp @@ -64,6 +64,7 @@ void MainObject::RunLocalMacros(RDMacro *rml) msecsTo(QTime::currentTime())); q=new RDSqlQuery(sql); delete q; + SendDeckEvent(decknum+1,eventnum); } } if(rml->echoRequested()) { diff --git a/rdcatchd/rdcatchd.cpp b/rdcatchd/rdcatchd.cpp index 02e6bc77..950cc249 100644 --- a/rdcatchd/rdcatchd.cpp +++ b/rdcatchd/rdcatchd.cpp @@ -338,8 +338,8 @@ MainObject::MainObject(QObject *parent,const char *name) // for(unsigned i=0;iexists()&&(cart->type()==RDCart::Macro)) { ExecuteMacroCart(cart); } delete cart; + SendDeckEvent(chan,number); } @@ -1567,6 +1568,12 @@ void MainObject::SendMeterLevel(int deck,short levels[2]) } +void MainObject::SendDeckEvent(int deck,int number) +{ + BroadcastCommand(QString().sprintf("DE %d %d!",deck,number)); +} + + void MainObject::ParseCommand(int ch) { char buf[256]; diff --git a/rdcatchd/rdcatchd.h b/rdcatchd/rdcatchd.h index f1048c70..a0798315 100644 --- a/rdcatchd/rdcatchd.h +++ b/rdcatchd/rdcatchd.h @@ -108,7 +108,7 @@ class MainObject : public QObject void playingData(int handle); void playStoppedData(int handle); void playUnloadedData(int handle); - void runCartData(unsigned cartnum); + void runCartData(int chan,int number,unsigned cartnum); void meterData(); void eventFinishedData(int id); void freeEventsData(); @@ -149,6 +149,7 @@ class MainObject : public QObject bool ExecuteMacroCart(RDCart *cart,int id=-1,int event=-1); void SendFullStatus(int ch); void SendMeterLevel(int deck,short levels[2]); + void SendDeckEvent(int deck,int number); void ParseCommand(int); void DispatchCommand(int); void KillSocket(int);