2016-05-18 Fred Gleason <fredg@paravelsystems.com>

* Added an entry for the Broadcast Tools SRC-16 in
	'docs/SWITCHERS.txt'.
	* Added a 'CUT_EVENTS' table to the database.
	* Added a 'DECK_EVENTS' table to the database.
	* Incremented the database version to 256.
	* 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'.
This commit is contained in:
Fred Gleason
2016-05-18 13:43:21 -04:00
parent df9ac7cff1
commit 3b766a5e7d
34 changed files with 689 additions and 44 deletions

View File

@@ -2,9 +2,7 @@
##
## rdcatchd/ Makefile.am for Rivendell
##
## (C) Copyright 2002-2006 Fred Gleason <fredg@paravelsystems.com>
##
## $Id: Makefile.am,v 1.20.8.1 2012/11/29 01:37:36 cvs Exp $
## (C) Copyright 2002-2016 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
@@ -34,11 +32,13 @@ bin_PROGRAMS = rdcatchd
dist_rdcatchd_SOURCES = batch.cpp\
catch_event.cpp catch_event.h\
event_player.cpp event_player.h\
local_macros.cpp\
rdcatchd.cpp rdcatchd.h\
rdcatchd_socket.cpp rdcatchd_socket.h
nodist_rdcatchd_SOURCES = moc_rdcatchd.cpp\
nodist_rdcatchd_SOURCES = moc_event_player.cpp\
moc_rdcatchd.cpp\
moc_rdcatchd_socket.cpp
rdcatchd_LDADD = @LIB_RDLIBS@ @LIBVORBIS@

122
rdcatchd/event_player.cpp Normal file
View File

@@ -0,0 +1,122 @@
// event_player.cpp
//
// A player class for Deck Events
//
// (C) Copyright 2016 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 <syslog.h>
#include <rddb.h>
#include <rdescape_string.h>
#include "event_player.h"
EventPlayer::EventPlayer(RDStation *station,int chan,QObject *parent)
{
event_station=station;
event_channel=chan;
event_timer=new QTimer(this);
connect(event_timer,SIGNAL(timeout()),this,SLOT(timeoutData()));
}
void EventPlayer::load(const QString &cutname)
{
QString sql;
RDSqlQuery *q;
//
// Load Deck Events
//
event_deck_events.clear();
sql=QString("select CART_NUMBER from DECK_EVENTS where ")+
"(STATION_NAME=\""+RDEscapeString(event_station->name())+"\")&&"+
QString().sprintf("(CHANNEL=%d) ",event_channel)+
"order by NUMBER";
q=new RDSqlQuery(sql);
while(q->next()) {
event_deck_events.push_back(q->value(0).toUInt());
}
delete q;
printf("\n");
//
// Load Cut Events
//
event_numbers.clear();
event_points.clear();
event_current_event=-1;
sql=QString("select NUMBER,POINT from CUT_EVENTS where ")+
"CUT_NAME=\""+cutname+"\" "+
"order by POINT";
q=new RDSqlQuery(sql);
while(q->next()) {
event_numbers.push_back(q->value(0).toInt());
event_points.push_back(q->value(1).toInt());
}
delete q;
}
void EventPlayer::start(int start_ptr)
{
event_start_point=start_ptr;
event_start_time=QTime::currentTime();
for(unsigned i=0;i<event_points.size();i++) {
if(event_points[i]>=event_start_point) {
event_current_event=i;
event_timer->
start(event_points[event_current_event]-event_start_point,true);
return;
}
}
}
void EventPlayer::stop()
{
event_timer->stop();
}
void EventPlayer::timeoutData()
{
//
// Dispatch current event
//
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);
}
//
// Set up next event
//
if(++event_current_event<(int)event_numbers.size()) {
int msec=event_points[event_current_event]-
event_start_time.msecsTo(QTime::currentTime())-event_start_point;
if(msec<0) {
msec=0;
}
event_timer->start(msec,true);
}
}

60
rdcatchd/event_player.h Normal file
View File

@@ -0,0 +1,60 @@
// event_player.h
//
// A player class for Deck Events
//
// (C) Copyright 2016 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 EVENT_PLAYER_H
#define EVENT_PLAYER_H
#include <vector>
#include <qdatetime.h>
#include <qobject.h>
#include <qtimer.h>
#include <rdstation.h>
class EventPlayer : public QObject
{
Q_OBJECT;
public:
EventPlayer(RDStation *station,int chan,QObject *parent=0);
void load(const QString &cutname);
void start(int start_ptr);
void stop();
signals:
void runCart(unsigned cartnum);
private slots:
void timeoutData();
private:
std::vector<unsigned> event_deck_events;
std::vector<int> event_numbers;
std::vector<int> event_points;
int event_current_event;
int event_start_point;
QTime event_start_time;
QTimer *event_timer;
RDStation *event_station;
int event_channel;
};
#endif // EVENT_PLAYER_H

View File

@@ -36,11 +36,50 @@ void MainObject::RunLocalMacros(RDMacro *rml)
unsigned dst_cartnum;
unsigned dst_cutnum;
unsigned len;
unsigned decknum;
unsigned eventnum;
QDateTime dt;
RDUser *user;
bool ok=false;
CatchEvent e;
unsigned event_ptr=0;
QString sql;
RDSqlQuery *q;
switch(rml->command()) {
case RDMacro::CE:
if(rml->argQuantity()==2) {
decknum=rml->arg(0).toUInt()-1;
if(decknum<MAX_DECKS) {
eventnum=rml->arg(1).toUInt();
if((eventnum>0)&&(eventnum<=RD_CUT_EVENT_ID_QUAN)) {
if(catch_record_deck_status[decknum]==RDDeck::Recording) {
if((event_ptr=GetEvent(catch_record_id[decknum]))<
catch_events.size()) {
e=catch_events[event_ptr];
sql=QString("insert into CUT_EVENTS set ")+
"CUT_NAME=\""+e.cutName()+"\","+
QString().sprintf("NUMBER=%u,",eventnum)+
QString().sprintf("POINT=%u",e.startTime().
msecsTo(QTime::currentTime()));
q=new RDSqlQuery(sql);
delete q;
}
}
if(rml->echoRequested()) {
rml->acknowledge(true);
catch_ripc->sendRml(rml);
}
return;
}
}
}
if(rml->echoRequested()) {
rml->acknowledge(false);
catch_ripc->sendRml(rml);
}
break;
case RDMacro::CP:
cartnum=rml->arg(0).toUInt();
cutnum=rml->arg(1).toUInt();

View File

@@ -2,7 +2,7 @@
//
// The Rivendell Netcatcher Daemon
//
// (C) Copyright 2002-2015 Fred Gleason <fredg@paravelsystems.com>
// (C) Copyright 2002-2016 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
@@ -333,6 +333,15 @@ MainObject::MainObject(QObject *parent,const char *name)
StartDropboxes();
//
// Playout Event Players
//
for(unsigned i=0;i<MAX_DECKS;i++) {
catch_playout_event_player[i]=new EventPlayer(catch_rdstation,i+129,this);
connect(catch_playout_event_player[i],SIGNAL(runCart(unsigned)),
this,SLOT(runCartData(unsigned)));
}
//
// Time Engine
//
@@ -676,6 +685,11 @@ void MainObject::engineData(int id)
}
delete q;
sql=QString("delete from CUT_EVENTS where ")+
"CUT_NAME=\""+catch_events[event].cutName()+"\"";
q=new RDSqlQuery(sql);
delete q;
switch(catch_events[event].startType()) {
case RDRecording::HardStart:
StartRecording(event);
@@ -1004,6 +1018,7 @@ void MainObject::playStoppedData(int handle)
short levels[2]={-10000,-10000};
catch_playout_status[deck-129]=false;
catch_playout_event_player[deck-129]->stop();
LogLine(RDConfig::LogNotice,QString().
sprintf("playout stopped: cut %s",
(const char *)catch_playout_name[deck-129]));
@@ -1042,6 +1057,16 @@ void MainObject::playUnloadedData(int handle)
}
void MainObject::runCartData(unsigned cartnum)
{
RDCart *cart=new RDCart(cartnum);
if(cart->exists()&&(cart->type()==RDCart::Macro)) {
ExecuteMacroCart(cart);
}
delete cart;
}
void MainObject::meterData()
{
short levels[2];
@@ -1368,6 +1393,7 @@ void MainObject::StartPlayout(int event)
//
// Start the playout
//
catch_playout_event_player[deck-129]->load(catch_events[event].cutName());
catch_cae->loadPlay(catch_playout_card[deck-129],
catch_events[event].cutName(),
&catch_playout_stream[deck-129],
@@ -1376,6 +1402,7 @@ void MainObject::StartPlayout(int event)
catch_playout_stream[deck-129],
catch_playout_port[deck-129]);
catch_cae->positionPlay(catch_playout_handle[deck-129],start);
catch_playout_event_player[deck-129]->start(start);
catch_cae->
play(catch_playout_handle[deck-129],end-start,RD_TIMESCALE_DIVISOR,0);
catch_cae->setPlayPortActive(catch_playout_card[deck-129],

View File

@@ -57,7 +57,8 @@
#include <rdcatch_connect.h>
#include <rdsettings.h>
#include <catch_event.h>
#include "catch_event.h"
#include "event_player.h"
//
// Global RDCATCHD Definitions
@@ -107,6 +108,7 @@ class MainObject : public QObject
void playingData(int handle);
void playStoppedData(int handle);
void playUnloadedData(int handle);
void runCartData(unsigned cartnum);
void meterData();
void eventFinishedData(int id);
void freeEventsData();
@@ -228,6 +230,7 @@ class MainObject : public QObject
int catch_playout_event_id[MAX_DECKS];
int catch_playout_id[MAX_DECKS];
QString catch_playout_name[MAX_DECKS];
EventPlayer *catch_playout_event_player[MAX_DECKS];
int catch_monitor_port[MAX_DECKS];
bool catch_monitor_state[MAX_DECKS];