mirror of
https://github.com/ElvishArtisan/rivendell.git
synced 2026-01-12 07:35:55 +01:00
2018-04-14 Fred Gleason <fredg@paravelsystems.com>
* Moved the 'LogPlay' class in rdairplay(1) to 'RDLogPlay' in the core library. * Moved the 'RLMHost' class in rdairplay(1) to 'RDRLMHost' in the core library.
This commit is contained in:
@@ -172,6 +172,7 @@ dist_librd_la_SOURCES = dbversion.h\
|
||||
rdlogedit_conf.cpp rdlogedit_conf.h\
|
||||
rdlogfilter.cpp rdlogfilter.h\
|
||||
rdloglock.cpp rdloglock.h\
|
||||
rdlogplay.cpp rdlogplay.h\
|
||||
rdmacro.cpp rdmacro.h\
|
||||
rdmacro_event.cpp rdmacro_event.h\
|
||||
rdmarker_bar.cpp rdmarker_bar.h\
|
||||
@@ -205,6 +206,7 @@ dist_librd_la_SOURCES = dbversion.h\
|
||||
rdreport.cpp rdreport.h\
|
||||
rdringbuffer.cpp rdringbuffer.h\
|
||||
rdripc.cpp rdripc.h\
|
||||
rdrlmhost.cpp rdrlmhost.h\
|
||||
rdschedcode.cpp rdschedcode.h\
|
||||
rdschedcodes_dialog.cpp rdschedcodes_dialog.h\
|
||||
rdsegmeter.cpp rdsegmeter.h\
|
||||
@@ -308,6 +310,7 @@ nodist_librd_la_SOURCES = moc_rdadd_cart.cpp\
|
||||
moc_rdlivewire.cpp\
|
||||
moc_rdlogfilter.cpp\
|
||||
moc_rdloglock.cpp\
|
||||
moc_rdlogplay.cpp\
|
||||
moc_rdmacro_event.cpp\
|
||||
moc_rdmarker_bar.cpp\
|
||||
moc_rdmarker_edit.cpp\
|
||||
@@ -319,7 +322,8 @@ nodist_librd_la_SOURCES = moc_rdadd_cart.cpp\
|
||||
moc_rdplaymeter.cpp\
|
||||
moc_rdpushbutton.cpp\
|
||||
moc_rdripc.cpp\
|
||||
moc_rdschedcodes_dialog.cpp\
|
||||
moc_rdrlmhost.cpp\
|
||||
moc_rdschedcodes_dialog.cpp\
|
||||
moc_rdsegmeter.cpp\
|
||||
moc_rdsimpleplayer.cpp\
|
||||
moc_rdrehash.cpp\
|
||||
|
||||
@@ -159,6 +159,7 @@ x11 {
|
||||
SOURCES += rdimport_audio.cpp
|
||||
SOURCES += rdkernelgpio.cpp
|
||||
SOURCES += rdlist_groups.cpp
|
||||
SOURCES += rdlogplay.cpp
|
||||
SOURCES += rdmarker_button.cpp
|
||||
SOURCES += rdmarker_edit.cpp
|
||||
SOURCES += rdmatrix.cpp
|
||||
@@ -169,6 +170,7 @@ x11 {
|
||||
SOURCES += rdrecording.cpp
|
||||
SOURCES += rdrehash.cpp
|
||||
SOURCES += rdrenderer.cpp
|
||||
SOURCES += rdrlmhost.cpp
|
||||
SOURCES += rdsimpleplayer.cpp
|
||||
SOURCES += rdsound_panel.cpp
|
||||
SOURCES += rdstatus.cpp
|
||||
@@ -301,6 +303,7 @@ x11 {
|
||||
HEADERS += rdimport_audio.h
|
||||
HEADERS += rdkernelgpio.h
|
||||
HEADERS += rdlist_groups.h
|
||||
HEADERS += rdlogplay.h
|
||||
HEADERS += rdmarker_button.h
|
||||
HEADERS += rdmarker_edit.h
|
||||
HEADERS += rdmatrix.h
|
||||
@@ -312,6 +315,7 @@ x11 {
|
||||
HEADERS += rdrecording.h
|
||||
HEADERS += rdrehash.h
|
||||
HEADERS += rdrenderer.h
|
||||
HEADERS += rdrlmhost.h
|
||||
HEADERS += rdsimpleplayer.h
|
||||
HEADERS += rdsound_panel.h
|
||||
HEADERS += rdstatus.h
|
||||
|
||||
3016
lib/rdlogplay.cpp
Normal file
3016
lib/rdlogplay.cpp
Normal file
File diff suppressed because it is too large
Load Diff
258
lib/rdlogplay.h
Normal file
258
lib/rdlogplay.h
Normal file
@@ -0,0 +1,258 @@
|
||||
// rdlogplay.h
|
||||
//
|
||||
// Rivendell Log Playout Machine
|
||||
//
|
||||
// (C) Copyright 2002-2004,2016-2018 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 RDLOGPLAY_H
|
||||
#define RDLOGPLAY_H
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <qobject.h>
|
||||
#include <qsignalmapper.h>
|
||||
#include <qtimer.h>
|
||||
#include <qsocketdevice.h>
|
||||
#include <qdatetime.h>
|
||||
|
||||
#include <rd.h>
|
||||
#include <rdairplay_conf.h>
|
||||
#include <rdapplication.h>
|
||||
#include <rdevent_player.h>
|
||||
#include <rdlog.h>
|
||||
#include <rdlog_event.h>
|
||||
#include <rdmacro_event.h>
|
||||
#include <rdplay_deck.h>
|
||||
#include <rdrlmhost.h>
|
||||
#include <rdsimpleplayer.h>
|
||||
|
||||
//
|
||||
// Widget Settings
|
||||
//
|
||||
#define LOGPLAY_MAX_PLAYS 7
|
||||
#define TRANSPORT_QUANTITY 7
|
||||
#define LOGPLAY_LOOKAHEAD_EVENTS 20
|
||||
#define LOGPLAY_RESCAN_INTERVAL 5000
|
||||
#define LOGPLAY_RESCAN_SIZE 30
|
||||
|
||||
//
|
||||
// Debug Settings
|
||||
//
|
||||
//#define SHOW_SLOTS
|
||||
//#define SHOW_METER_SLOTS
|
||||
|
||||
class RDLogPlay : public QObject,public RDLogEvent
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
RDLogPlay(int id,RDEventPlayer *player,QSocketDevice *nn_sock,QString logname,
|
||||
std::vector<RDRLMHost *> *rlm_hosts,QObject *parent=0);
|
||||
QString serviceName() const;
|
||||
void setServiceName(const QString &svcname);
|
||||
QString defaultServiceName() const;
|
||||
void setDefaultServiceName(const QString &svcname);
|
||||
int card(int channum) const;
|
||||
int port(int channum) const;
|
||||
RDAirPlayConf::OpMode mode() const;
|
||||
void setOpMode(RDAirPlayConf::OpMode mode);
|
||||
void setLogName(QString name);
|
||||
void setChannels(int cards[2],int ports[2],
|
||||
const QString start_rml[2],const QString stop_rml[2]);
|
||||
void setSegueLength(int len);
|
||||
void setNowCart(unsigned cartnum);
|
||||
void setNextCart(unsigned cartnum);
|
||||
void auditionHead(int line);
|
||||
void auditionTail(int line);
|
||||
void auditionStop();
|
||||
bool play(int line,RDLogLine::StartSource src,
|
||||
int mport=-1,bool skip_meta=false);
|
||||
bool channelPlay(int mport);
|
||||
bool stop(bool all=true,int port=0,int fade=0);
|
||||
bool stop(int line,int fade=0);
|
||||
bool channelStop(int mport);
|
||||
bool pause(int line);
|
||||
void duckVolume(int level,int fade,int mport=-1);
|
||||
void makeNext(int line,bool refresh_status=true);
|
||||
void load();
|
||||
void append(const QString &log_name);
|
||||
bool refresh();
|
||||
void save(int line=-1);
|
||||
void clear();
|
||||
void insert(int line,int cartnum,RDLogLine::TransType next_type,
|
||||
RDLogLine::TransType type=RDLogLine::Play);
|
||||
void insert(int line,RDLogLine *logline,bool update=true,bool preserv_custom_transition=false);
|
||||
void remove(int line,int num_lines,bool update=true,bool preserv_custom_transition=false);
|
||||
void move(int from_line,int to_line);
|
||||
void copy(int from_line,int to_line,
|
||||
RDLogLine::TransType type=RDLogLine::Play);
|
||||
int topLine();
|
||||
int currentLine() const;
|
||||
int nextLine() const;
|
||||
int nextLine(int line);
|
||||
RDLogLine *nextEvent();
|
||||
RDLogLine::TransType nextTrans();
|
||||
RDLogLine::TransType nextTrans(int line);
|
||||
void transportEvents(int line[]);
|
||||
int runningEvents(int *line, bool include_paused=true);
|
||||
void lineModified(int line);
|
||||
RDLogLine::Status status(int line);
|
||||
QTime startTime(int line);
|
||||
QTime nextStop() const;
|
||||
bool running(bool include_paused=true);
|
||||
void resync();
|
||||
bool isRefreshable() const;
|
||||
|
||||
private slots:
|
||||
void transTimerData();
|
||||
void graceTimerData();
|
||||
void playStateChangedData(int id,RDPlayDeck::State state);
|
||||
void onairFlagChangedData(bool state);
|
||||
void segueStartData(int);
|
||||
void segueEndData(int);
|
||||
void talkStartData(int);
|
||||
void talkEndData(int);
|
||||
void positionData(int,int);
|
||||
void macroStartedData();
|
||||
void macroFinishedData();
|
||||
void macroStoppedData();
|
||||
void timescalingSupportedData(int card,bool state);
|
||||
// void rescanEventsData();
|
||||
void auditionStartedData();
|
||||
void auditionStoppedData();
|
||||
void notificationReceivedData(RDNotification *notify);
|
||||
|
||||
signals:
|
||||
void renamed();
|
||||
void reloaded();
|
||||
void transportChanged();
|
||||
void inserted(int line);
|
||||
void removed(int line,int num,bool moving);
|
||||
void modified(int line);
|
||||
void auditionHeadPlayed(int line);
|
||||
void auditionTailPlayed(int line);
|
||||
void auditionStopped(int line);
|
||||
void played(int line);
|
||||
void paused(int line);
|
||||
void stopped(int line);
|
||||
void position(int line,int point);
|
||||
void topEventChanged(int line);
|
||||
void nextEventChanged(int line);
|
||||
void activeEventChanged(int line,RDLogLine::TransType trans);
|
||||
void nextStopChanged(QTime time);
|
||||
void postPointChanged(QTime point,int offset,bool offset_valid,bool running);
|
||||
void runStatusChanged(bool running);
|
||||
void refreshabilityChanged(bool state);
|
||||
void refreshStatusChanged(bool active);
|
||||
void channelStarted(int id,int mport,int card,int port);
|
||||
void channelStopped(int id,int mport,int card,int port);
|
||||
|
||||
private:
|
||||
bool StartEvent(int line,RDLogLine::TransType trans_type,int trans_length,
|
||||
RDLogLine::StartSource src,int mport=-1,int duck_length=0);
|
||||
bool StartAudioEvent(int line);
|
||||
void CleanupEvent(int id);
|
||||
void UpdateStartTimes(int line);
|
||||
void FinishEvent(int line);
|
||||
QTime GetStartTime(QTime sched_time,RDLogLine::TransType trans_type,
|
||||
RDLogLine::TimeType time_type,QTime prev_time,
|
||||
int prev_total_length,int prev_segue_length,bool *stop,
|
||||
int running_events);
|
||||
QTime GetNextStop(int line);
|
||||
void UpdatePostPoint();
|
||||
void UpdatePostPoint(int line);
|
||||
void AdvanceActiveEvent();
|
||||
void SetTransTimer(QTime current_time=QTime(),bool stop=true);
|
||||
QString GetPortName(int card,int port);
|
||||
int GetNextChannel(int mport,int *card,int *port);
|
||||
int GetLineById(int id);
|
||||
RDPlayDeck *GetPlayDeck();
|
||||
void FreePlayDeck(RDPlayDeck *);
|
||||
bool GetNextPlayable(int *line,bool skip_meta,bool forced_start=false);
|
||||
void LogPlayEvent(RDLogLine *logline);
|
||||
void RefreshEvents(int line,int line_quan,bool force_update=false);
|
||||
void Playing(int id);
|
||||
void Paused(int id);
|
||||
void Stopping(int id);
|
||||
void Stopped(int id);
|
||||
void Finished(int id);
|
||||
void ClearChannel(int deckid);
|
||||
RDLogLine::TransType GetTransType(const QString &logname,int line);
|
||||
bool ClearBlock(int start_line);
|
||||
void SendNowNext();
|
||||
void LogTraffic(const QString &svcname,const QString &logname,
|
||||
RDLogLine *logline,RDLogLine::PlaySource src,
|
||||
RDAirPlayConf::TrafficAction action,bool onair_flag) const;
|
||||
RDCae *play_cae;
|
||||
RDAirPlayConf::OpMode play_op_mode;
|
||||
int play_slot_id[LOGPLAY_MAX_PLAYS];
|
||||
int play_segue_length;
|
||||
int play_trans_length;
|
||||
int play_next_line;
|
||||
int play_line_counter;
|
||||
bool play_start_next;
|
||||
int play_id;
|
||||
QTime play_next_stop;
|
||||
bool play_running;
|
||||
QTime play_post_time;
|
||||
int play_post_offset;
|
||||
int play_active_line;
|
||||
RDLogLine::TransType play_active_trans;
|
||||
RDMacroEvent *play_macro_deck;
|
||||
bool play_macro_running;
|
||||
bool play_refresh_pending;
|
||||
QTimer *play_trans_timer;
|
||||
QTimer *play_grace_timer;
|
||||
int play_trans_line;
|
||||
int play_grace_line;
|
||||
int play_card[2];
|
||||
int play_port[2];
|
||||
QString play_start_rml[2];
|
||||
QString play_stop_rml[2];
|
||||
bool play_timescaling_available;
|
||||
RDPlayDeck *play_deck[RD_MAX_STREAMS];
|
||||
bool play_deck_active[RD_MAX_STREAMS];
|
||||
int next_channel;
|
||||
QSocketDevice *play_nownext_socket;
|
||||
QString play_nownext_string;
|
||||
QHostAddress play_nownext_address;
|
||||
Q_UINT16 play_nownext_port;
|
||||
QString play_nownext_rml;
|
||||
bool play_timescaling_supported[RD_MAX_CARDS];
|
||||
QString play_svc_name;
|
||||
QString play_defaultsvc_name;
|
||||
int play_rescan_pos;
|
||||
RDLog *play_log;
|
||||
QDateTime play_link_datetime;
|
||||
QDateTime play_modified_datetime;
|
||||
bool play_refreshable;
|
||||
bool play_onair_flag;
|
||||
int play_duck_volume_port1;
|
||||
int play_duck_volume_port2;
|
||||
std::vector<RDRLMHost *> *play_rlm_hosts;
|
||||
unsigned play_now_cartnum;
|
||||
unsigned play_next_cartnum;
|
||||
unsigned play_prevnow_cartnum;
|
||||
unsigned play_prevnext_cartnum;
|
||||
RDSimplePlayer *play_audition_player;
|
||||
int play_audition_line;
|
||||
bool play_audition_head_played;
|
||||
int play_audition_preroll;
|
||||
RDEventPlayer *play_event_player;
|
||||
};
|
||||
|
||||
|
||||
#endif // RDLOGPLAY_H
|
||||
530
lib/rdrlmhost.cpp
Normal file
530
lib/rdrlmhost.cpp
Normal file
@@ -0,0 +1,530 @@
|
||||
// rdrlmhost.cpp
|
||||
//
|
||||
// A container class for a Rivendell Loadable Module host.
|
||||
//
|
||||
// (C) Copyright 2008,2016-2018 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 <dlfcn.h>
|
||||
#include <iostream>
|
||||
|
||||
#include <qsignalmapper.h>
|
||||
|
||||
#include "rdapplication.h"
|
||||
#include "rdconf.h"
|
||||
#include "rddatedecode.h"
|
||||
#include "rdnownext.h"
|
||||
#include "rdprofile.h"
|
||||
#include "rdrlmhost.h"
|
||||
#include "rdsvc.h"
|
||||
|
||||
//#include "globals.h"
|
||||
|
||||
|
||||
RDRLMHost::RDRLMHost(const QString &path,const QString &arg,
|
||||
QSocketDevice *udp_socket,QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
plugin_path=RDDateDecode(path,QDate::currentDate(),rda->station(),rda->config());
|
||||
plugin_arg=RDDateDecode(arg,QDate::currentDate(),rda->station(),rda->config());
|
||||
plugin_udp_socket=udp_socket;
|
||||
plugin_handle=NULL;
|
||||
plugin_start_sym=NULL;
|
||||
plugin_free_sym=NULL;
|
||||
plugin_pad_data_sent_sym=NULL;
|
||||
plugin_timer_expired_sym=NULL;
|
||||
plugin_serial_data_received_sym=NULL;
|
||||
|
||||
//
|
||||
// Utility Timers
|
||||
//
|
||||
QSignalMapper *mapper=new QSignalMapper(this);
|
||||
connect(mapper,SIGNAL(mapped(int)),this,SLOT(timerData(int)));
|
||||
for(int i=0;i<RLM_MAX_TIMERS;i++) {
|
||||
plugin_callback_timers[i]=new QTimer(this);
|
||||
mapper->setMapping(plugin_callback_timers[i],i);
|
||||
connect(plugin_callback_timers[i],SIGNAL(timeout()),mapper,SLOT(map()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
RDRLMHost::~RDRLMHost()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
QString RDRLMHost::pluginPath() const
|
||||
{
|
||||
return plugin_path;
|
||||
}
|
||||
|
||||
|
||||
QString RDRLMHost::pluginArg() const
|
||||
{
|
||||
return plugin_arg;
|
||||
}
|
||||
|
||||
|
||||
void RDRLMHost::sendEvent(const QString &svcname,const QString &logname,
|
||||
int lognum,RDLogLine **loglines,bool onair,
|
||||
RDAirPlayConf::OpMode mode)
|
||||
{
|
||||
if(plugin_pad_data_sent_sym!=NULL) {
|
||||
QDateTime now_dt(QDate::currentDate(),QTime::currentTime());
|
||||
struct rlm_svc *svc=new struct rlm_svc;
|
||||
struct rlm_log *log=new struct rlm_log;
|
||||
struct rlm_pad *now=new struct rlm_pad;
|
||||
struct rlm_pad *next=new struct rlm_pad;
|
||||
memset(svc,0,sizeof(struct rlm_svc));
|
||||
RDSvc *service=new RDSvc(svcname,rda->station(),rda->config());
|
||||
if(!svcname.isEmpty()) {
|
||||
sprintf(svc->svc_name,"%s",(const char *)svcname.left(255));
|
||||
if(!service->programCode().isEmpty()) {
|
||||
sprintf(svc->svc_pgmcode,"%s",(const char *)service->programCode());
|
||||
}
|
||||
else {
|
||||
svc->svc_pgmcode[0]=0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
svc->svc_name[0]=0;
|
||||
svc->svc_pgmcode[0]=0;
|
||||
}
|
||||
delete service;
|
||||
memset(log,0,sizeof(struct rlm_log));
|
||||
if(!logname.isEmpty()) {
|
||||
sprintf(log->log_name,"%s",(const char *)logname.left(64));
|
||||
}
|
||||
else {
|
||||
log->log_name[0]=0;
|
||||
}
|
||||
log->log_mach=lognum;
|
||||
log->log_onair=onair;
|
||||
log->log_mode=mode;
|
||||
RDRLMHost::loadMetadata(loglines[0],now,now_dt);
|
||||
RDRLMHost::loadMetadata(loglines[1],next);
|
||||
plugin_pad_data_sent_sym(this,svc,log,now,next);
|
||||
delete next;
|
||||
delete now;
|
||||
delete log;
|
||||
delete svc;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool RDRLMHost::load()
|
||||
{
|
||||
QString basename=RDGetBasePart(plugin_path);
|
||||
basename=basename.left(basename.findRev("."));
|
||||
if((plugin_handle=dlopen(plugin_path,RTLD_LAZY))==NULL) {
|
||||
return false;
|
||||
}
|
||||
*(void **)(&plugin_start_sym)=dlsym(plugin_handle,basename+"_RLMStart");
|
||||
*(void **)(&plugin_free_sym)=dlsym(plugin_handle,basename+"_RLMFree");
|
||||
*(void **)(&plugin_pad_data_sent_sym)=
|
||||
dlsym(plugin_handle,basename+"_RLMPadDataSent");
|
||||
*(void **)(&plugin_timer_expired_sym)=
|
||||
dlsym(plugin_handle,basename+"_RLMTimerExpired");
|
||||
*(void **)(&plugin_serial_data_received_sym)=
|
||||
dlsym(plugin_handle,basename+"_RLMSerialDataReceived");
|
||||
if(plugin_start_sym!=NULL) {
|
||||
plugin_start_sym(this,plugin_arg);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void RDRLMHost::unload()
|
||||
{
|
||||
if(plugin_free_sym!=NULL) {
|
||||
plugin_free_sym(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void RDRLMHost::loadMetadata(const RDLogLine *logline,struct rlm_pad *pad,
|
||||
const QDateTime &start_datetime)
|
||||
{
|
||||
QDateTime now(QDate::currentDate(),QTime::currentTime());
|
||||
|
||||
if(pad==NULL) {
|
||||
return;
|
||||
}
|
||||
memset(pad,0,sizeof(struct rlm_pad));
|
||||
if(logline==NULL) {
|
||||
return;
|
||||
}
|
||||
if(logline!=NULL) {
|
||||
pad->rlm_cartnum=logline->cartNumber();
|
||||
switch(logline->cartType()) {
|
||||
case RDCart::Audio:
|
||||
pad->rlm_len=logline->effectiveLength();
|
||||
break;
|
||||
|
||||
case RDCart::Macro:
|
||||
if((logline->eventLength()>=0)&&logline->useEventLength()) {
|
||||
pad->rlm_len=logline->eventLength();
|
||||
}
|
||||
else {
|
||||
pad->rlm_len=logline->effectiveLength();
|
||||
}
|
||||
break;
|
||||
|
||||
case RDCart::All:
|
||||
break;
|
||||
}
|
||||
pad->rlm_carttype=logline->cartType();
|
||||
if(!logline->year().isNull()) {
|
||||
snprintf(pad->rlm_year,5,"%s",
|
||||
(const char *)logline->year().toString("yyyy"));
|
||||
}
|
||||
if(!logline->groupName().isEmpty()) {
|
||||
snprintf(pad->rlm_group,11,"%s",
|
||||
(const char *)logline->groupName().utf8());
|
||||
}
|
||||
if(!logline->title().isEmpty()) {
|
||||
snprintf(pad->rlm_title,256,"%s",(const char *)logline->title().utf8());
|
||||
}
|
||||
if(!logline->artist().isEmpty()) {
|
||||
snprintf(pad->rlm_artist,256,"%s",(const char *)logline->artist().utf8());
|
||||
}
|
||||
if(!logline->label().isEmpty()) {
|
||||
snprintf(pad->rlm_label,65,"%s",(const char *)logline->label().utf8());
|
||||
}
|
||||
if(!logline->client().isEmpty()) {
|
||||
snprintf(pad->rlm_client,65,"%s",(const char *)logline->client().utf8());
|
||||
}
|
||||
if(!logline->agency().isEmpty()) {
|
||||
snprintf(pad->rlm_agency,65,"%s",(const char *)logline->agency().utf8());
|
||||
}
|
||||
if(!logline->composer().isEmpty()) {
|
||||
snprintf(pad->rlm_comp,65,"%s",(const char *)logline->composer().utf8());
|
||||
}
|
||||
if(!logline->publisher().isEmpty()) {
|
||||
snprintf(pad->rlm_pub,65,"%s",(const char *)logline->publisher().utf8());
|
||||
}
|
||||
if(!logline->userDefined().isEmpty()) {
|
||||
snprintf(pad->rlm_userdef,256,"%s",
|
||||
(const char *)logline->userDefined().utf8());
|
||||
}
|
||||
if(!logline->outcue().isEmpty()) {
|
||||
snprintf(pad->rlm_outcue,65,"%s",(const char *)logline->outcue().utf8());
|
||||
}
|
||||
if(!logline->description().isEmpty()) {
|
||||
snprintf(pad->rlm_description,65,"%s",
|
||||
(const char *)logline->description().utf8());
|
||||
}
|
||||
if(!logline->conductor().isEmpty()) {
|
||||
snprintf(pad->rlm_conductor,65,"%s",
|
||||
(const char *)logline->conductor().utf8());
|
||||
}
|
||||
if(!logline->songId().isEmpty()) {
|
||||
snprintf(pad->rlm_song_id,33,"%s",(const char *)logline->songId().utf8());
|
||||
}
|
||||
if(!logline->album().isEmpty()) {
|
||||
snprintf(pad->rlm_album,256,"%s",(const char *)logline->album().utf8());
|
||||
}
|
||||
if(!logline->isrc().isEmpty()) {
|
||||
strncpy(pad->rlm_isrc,(const char *)logline->isrc().utf8().left(12),12);
|
||||
}
|
||||
if(!logline->isci().isEmpty()) {
|
||||
strncpy(pad->rlm_isci,(const char *)logline->isci().utf8().left(32),32);
|
||||
}
|
||||
if(!logline->extData().isEmpty()) {
|
||||
snprintf(pad->rlm_ext_data,32,"%s",(const char *)logline->extData());
|
||||
}
|
||||
if(!logline->extEventId().isEmpty()) {
|
||||
snprintf(pad->rlm_ext_eventid,32,"%s",
|
||||
(const char *)logline->extEventId());
|
||||
}
|
||||
if(!logline->extAnncType().isEmpty()) {
|
||||
snprintf(pad->rlm_ext_annctype,32,"%s",
|
||||
(const char *)logline->extAnncType());
|
||||
}
|
||||
if(start_datetime.isValid()) {
|
||||
pad->rlm_start_msec=start_datetime.time().msec();
|
||||
pad->rlm_start_sec=start_datetime.time().second();
|
||||
pad->rlm_start_min=start_datetime.time().minute();
|
||||
pad->rlm_start_hour=start_datetime.time().hour();
|
||||
pad->rlm_start_day=start_datetime.date().day();
|
||||
pad->rlm_start_mon=start_datetime.date().month();
|
||||
pad->rlm_start_year=start_datetime.date().year();
|
||||
}
|
||||
else {
|
||||
QTime start_time=logline->startTime(RDLogLine::Predicted);
|
||||
if(start_time.isNull()) {
|
||||
start_time=logline->startTime(RDLogLine::Imported);
|
||||
}
|
||||
if(!start_time.isNull()) {
|
||||
if(start_time<now.time()) { // Crossing midnight
|
||||
now=now.addDays(1);
|
||||
}
|
||||
}
|
||||
pad->rlm_start_msec=start_time.msec();
|
||||
pad->rlm_start_sec=start_time.second();
|
||||
pad->rlm_start_min=start_time.minute();
|
||||
pad->rlm_start_hour=start_time.hour();
|
||||
pad->rlm_start_day=now.date().day();
|
||||
pad->rlm_start_mon=now.date().month();
|
||||
pad->rlm_start_year=now.date().year();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void RDRLMHost::saveMetadata(const struct rlm_pad *pad,RDLogLine *logline)
|
||||
{
|
||||
if(logline==NULL) {
|
||||
return;
|
||||
}
|
||||
logline->clear();
|
||||
if(pad==NULL) {
|
||||
return;
|
||||
}
|
||||
logline->setCartNumber(pad->rlm_cartnum);
|
||||
logline->setForcedLength(pad->rlm_len);
|
||||
logline->setYear(QDate(QString(pad->rlm_year).toInt(),1,1));
|
||||
logline->setGroupName(pad->rlm_group);
|
||||
logline->setTitle(pad->rlm_title);
|
||||
logline->setArtist(pad->rlm_artist);
|
||||
logline->setLabel(pad->rlm_label);
|
||||
logline->setClient(pad->rlm_client);
|
||||
logline->setAgency(pad->rlm_agency);
|
||||
logline->setComposer(pad->rlm_comp);
|
||||
logline->setPublisher(pad->rlm_pub);
|
||||
logline->setUserDefined(pad->rlm_userdef);
|
||||
logline->setOutcue(pad->rlm_outcue);
|
||||
logline->setDescription(pad->rlm_description);
|
||||
logline->setAlbum(pad->rlm_album);
|
||||
logline->setIsrc(QString::fromAscii(pad->rlm_isrc,12));
|
||||
logline->setIsci(QString::fromAscii(pad->rlm_isci,32));
|
||||
if((pad->rlm_start_year>0)&&(pad->rlm_start_mon>0)&&(pad->rlm_start_day)) {
|
||||
logline->setStartDatetime(QDateTime(QDate(pad->rlm_start_year,
|
||||
pad->rlm_start_mon,
|
||||
pad->rlm_start_day),
|
||||
QTime(pad->rlm_start_hour,
|
||||
pad->rlm_start_min,
|
||||
pad->rlm_start_sec,
|
||||
pad->rlm_start_msec)));
|
||||
}
|
||||
else {
|
||||
logline->setStartDatetime(QDateTime());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void RDRLMHost::timerData(int timernum)
|
||||
{
|
||||
if(plugin_timer_expired_sym!=NULL) {
|
||||
plugin_timer_expired_sym(this,timernum);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void RDRLMHost::ttyReceiveReadyData(int fd)
|
||||
{
|
||||
char data[1024];
|
||||
int n;
|
||||
|
||||
for(unsigned i=0;i<plugin_tty_devices.size();i++) {
|
||||
if(plugin_tty_devices[i]->socket()==fd) {
|
||||
while((n=plugin_tty_devices[i]->readBlock(data,1024))>0) {
|
||||
if(plugin_serial_data_received_sym!=NULL) {
|
||||
plugin_serial_data_received_sym(this,i,data,n);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
fprintf(stderr,"unknown tty descriptor: %d\n",fd);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// RLM Utility Functions
|
||||
//
|
||||
void RLMSendUdp(void *ptr,const char *ipaddr,uint16_t port,
|
||||
const char *data,int len)
|
||||
{
|
||||
RDRLMHost *host=(RDRLMHost *)ptr;
|
||||
QHostAddress addr;
|
||||
addr.setAddress(ipaddr);
|
||||
if(!addr.isNull()) {
|
||||
host->plugin_udp_socket->writeBlock(data,len,addr,port);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int RLMOpenSerial(void *ptr,const char *port,int speed,int parity,
|
||||
int word_length)
|
||||
{
|
||||
RDRLMHost *host=(RDRLMHost *)ptr;
|
||||
host->plugin_tty_devices.push_back(new RDTTYDevice);
|
||||
host->plugin_tty_devices.back()->setName(port);
|
||||
host->plugin_tty_devices.back()->setSpeed(speed);
|
||||
host->plugin_tty_devices.back()->setParity((RDTTYDevice::Parity)parity);
|
||||
host->plugin_tty_devices.back()->setWordLength(word_length);
|
||||
if(host->plugin_tty_devices.back()->open(IO_ReadWrite)) {
|
||||
|
||||
host->plugin_tty_notifiers.
|
||||
push_back(new QSocketNotifier(host->plugin_tty_devices.back()->socket(),
|
||||
QSocketNotifier::Read));
|
||||
host->connect(host->plugin_tty_notifiers.back(),SIGNAL(activated(int)),
|
||||
host,SLOT(ttyReceiveReadyData(int)));
|
||||
return (int)host->plugin_tty_devices.size()-1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
void RLMSendSerial(void *ptr,int handle,const char *data,int len)
|
||||
{
|
||||
RDRLMHost *host=(RDRLMHost *)ptr;
|
||||
if((handle<0)||(handle>=(int)host->plugin_tty_devices.size())) {
|
||||
return;
|
||||
}
|
||||
host->plugin_tty_devices[handle]->writeBlock(data,len);
|
||||
}
|
||||
|
||||
|
||||
void RLMCloseSerial(void *ptr,int handle)
|
||||
{
|
||||
RDRLMHost *host=(RDRLMHost *)ptr;
|
||||
|
||||
//
|
||||
// FIXME: We really ought to take out the trash here!
|
||||
//
|
||||
host->plugin_tty_devices[handle]->close();
|
||||
delete host->plugin_tty_devices[handle];
|
||||
host->plugin_tty_devices[handle]=NULL;
|
||||
}
|
||||
|
||||
|
||||
const char *RLMDateTime(void *ptr,int offset_msecs,const char *format)
|
||||
{
|
||||
RDRLMHost *host=(RDRLMHost *)ptr;
|
||||
QDateTime datetime=QDateTime(QDate::currentDate(),QTime::currentTime().
|
||||
addMSecs(offset_msecs));
|
||||
strncpy(host->plugin_value_string,datetime.toString(format),1024);
|
||||
return host->plugin_value_string;
|
||||
}
|
||||
|
||||
|
||||
const char *RLMResolveNowNextEncoded(void *ptr,const struct rlm_pad *now,
|
||||
const struct rlm_pad *next,
|
||||
const char *format,int encoding)
|
||||
{
|
||||
RDRLMHost *host=(RDRLMHost *)ptr;
|
||||
RDLogLine *loglines[2];
|
||||
QString str=format;
|
||||
|
||||
loglines[0]=new RDLogLine();
|
||||
loglines[1]=new RDLogLine();
|
||||
RDRLMHost::saveMetadata(now,loglines[0]);
|
||||
RDRLMHost::saveMetadata(next,loglines[1]);
|
||||
RDResolveNowNext(&str,loglines,encoding);
|
||||
strncpy(host->plugin_value_string,str,1024);
|
||||
delete loglines[1];
|
||||
delete loglines[0];
|
||||
|
||||
return host->plugin_value_string;
|
||||
}
|
||||
|
||||
|
||||
const char *RLMResolveNowNext(void *ptr,const struct rlm_pad *now,
|
||||
const struct rlm_pad *next,const char *format)
|
||||
{
|
||||
return RLMResolveNowNextEncoded(ptr,now,next,format,RLM_ENCODE_NONE);
|
||||
}
|
||||
|
||||
|
||||
void RLMLog(void *ptr,int prio,const char *msg)
|
||||
{
|
||||
rda->config()->log("log machine",(RDConfig::LogPriority)prio,msg);
|
||||
}
|
||||
|
||||
|
||||
void RLMStartTimer(void *ptr,int timernum,int msecs,int mode)
|
||||
{
|
||||
RDRLMHost *host=(RDRLMHost *)ptr;
|
||||
if((timernum<0)||(timernum>=RLM_MAX_TIMERS)) {
|
||||
return;
|
||||
}
|
||||
if(host->plugin_callback_timers[timernum]->isActive()) {
|
||||
host->plugin_callback_timers[timernum]->stop();
|
||||
}
|
||||
host->plugin_callback_timers[timernum]->start(msecs,mode);
|
||||
}
|
||||
|
||||
|
||||
void RLMStopTimer(void *ptr,int timernum)
|
||||
{
|
||||
RDRLMHost *host=(RDRLMHost *)ptr;
|
||||
if((timernum<0)||(timernum>=RLM_MAX_TIMERS)) {
|
||||
return;
|
||||
}
|
||||
if(host->plugin_callback_timers[timernum]->isActive()) {
|
||||
host->plugin_callback_timers[timernum]->stop();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int RLMGetIntegerValue(void *ptr,const char *filename,const char *section,
|
||||
const char *label,int default_value)
|
||||
{
|
||||
RDProfile *p=new RDProfile();
|
||||
p->setSource(filename);
|
||||
int r=p->intValue(section,label,default_value);
|
||||
delete p;
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
int RLMGetHexValue(void *ptr,const char *filename,const char *section,
|
||||
const char *label,int default_value)
|
||||
{
|
||||
RDProfile *p=new RDProfile();
|
||||
p->setSource(filename);
|
||||
int r=p->hexValue(section,label,default_value);
|
||||
delete p;
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
int RLMGetBooleanValue(void *ptr,const char *filename,const char *section,
|
||||
const char *label,int default_value)
|
||||
{
|
||||
RDProfile *p=new RDProfile();
|
||||
p->setSource(filename);
|
||||
bool r=p->boolValue(section,label,default_value);
|
||||
delete p;
|
||||
return (int)r;
|
||||
}
|
||||
|
||||
|
||||
const char *RLMGetStringValue(void *ptr,const char *filename,
|
||||
const char *section,const char *label,
|
||||
const char *default_value)
|
||||
{
|
||||
RDRLMHost *host=(RDRLMHost *)ptr;
|
||||
RDProfile *p=new RDProfile();
|
||||
p->setSource(filename);
|
||||
strncpy(host->plugin_value_string,
|
||||
p->stringValue(section,label,default_value),1024);
|
||||
delete p;
|
||||
return host->plugin_value_string;
|
||||
}
|
||||
105
lib/rdrlmhost.h
Normal file
105
lib/rdrlmhost.h
Normal file
@@ -0,0 +1,105 @@
|
||||
// rdrlmhost.h
|
||||
//
|
||||
// A container class for a Rivendell Loadable Module host.
|
||||
//
|
||||
// (C) Copyright 2008,2016-2018 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 RDRLMHOST_H
|
||||
#define RDRLMHOST_H
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <qdatetime.h>
|
||||
#include <qstring.h>
|
||||
#include <qsocketdevice.h>
|
||||
#include <qsocketnotifier.h>
|
||||
#include <qtimer.h>
|
||||
|
||||
#include <rdairplay_conf.h>
|
||||
#include <rdlog_line.h>
|
||||
#include <rdttydevice.h>
|
||||
|
||||
#include "../rlm/rlm.h"
|
||||
|
||||
class RDRLMHost : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
RDRLMHost(const QString &path,const QString &arg,QSocketDevice *udp_socket,
|
||||
QObject *parent=0);
|
||||
~RDRLMHost();
|
||||
QString pluginPath() const;
|
||||
QString pluginArg() const;
|
||||
void sendEvent(const QString &svcname,const QString &logname,
|
||||
int lognum,RDLogLine **loglines,bool onair,
|
||||
RDAirPlayConf::OpMode mode);
|
||||
bool load();
|
||||
void unload();
|
||||
static void loadMetadata(const RDLogLine *logline,struct rlm_pad *pad,
|
||||
const QDateTime &start_datetime=QDateTime());
|
||||
static void saveMetadata(const struct rlm_pad *pad,RDLogLine *logline);
|
||||
private slots:
|
||||
void timerData(int timernum);
|
||||
void ttyReceiveReadyData(int fd);
|
||||
|
||||
private:
|
||||
QString plugin_path;
|
||||
QString plugin_arg;
|
||||
QSocketDevice *plugin_udp_socket;
|
||||
void *plugin_handle;
|
||||
void (*plugin_start_sym)(void *,const char *);
|
||||
void (*plugin_free_sym)(void *);
|
||||
void (*plugin_pad_data_sent_sym)
|
||||
(void *,const struct rlm_svc *,const struct rlm_log *,
|
||||
const struct rlm_pad *,const struct rlm_pad *);
|
||||
void (*plugin_timer_expired_sym)(void *,int);
|
||||
void (*plugin_serial_data_received_sym)(void *,int,const char *,int);
|
||||
|
||||
std::vector<RDTTYDevice *> plugin_tty_devices;
|
||||
std::vector<QSocketNotifier *> plugin_tty_notifiers;
|
||||
QTimer *plugin_callback_timers[RLM_MAX_TIMERS];
|
||||
friend void RLMSendUdp(void *ptr,const char *ipaddr,uint16_t port,
|
||||
const char *data,int len);
|
||||
friend int RLMOpenSerial(void *ptr,const char *port,int speed,
|
||||
int parity,int word_length);
|
||||
friend void RLMSendSerial(void *ptr,int handle,const char *data,
|
||||
int len);
|
||||
friend void RLMCloseSerial(void *ptr,int handle);
|
||||
friend const char *RLMDateTime(int offset_msecs,const char *format);
|
||||
friend const char *RLMResolveNowNextEncoded(void *ptr,
|
||||
const struct rlm_pad *now,
|
||||
const struct rlm_pad *next,
|
||||
const char *format,
|
||||
int encoding);
|
||||
friend const char *RLMResolveNowNext(void *ptr,
|
||||
const struct rlm_pad *now,
|
||||
const struct rlm_pad *next,
|
||||
const char *format);
|
||||
friend void RLMLog(void *ptr,int prio,const char *msg);
|
||||
friend void RLMStartTimer(void *ptr,int timernum,int msecs,
|
||||
int mode);
|
||||
friend void RLMStopTimer(void *ptr,int timernum);
|
||||
friend const char *RLMDateTime(void *ptr,int offset_msecs,
|
||||
const char *format);
|
||||
friend const char *RLMGetStringValue(void *ptr,const char *filename,
|
||||
const char *section,const char *label,
|
||||
const char *default_value);
|
||||
char plugin_value_string[1024];
|
||||
};
|
||||
|
||||
|
||||
#endif // RDRLMHOST_H
|
||||
Reference in New Issue
Block a user