Initial import of CVS-v2_8_branch

This commit is contained in:
Fred Gleason
2014-08-12 15:13:02 -04:00
commit afd67c7af8
1508 changed files with 405304 additions and 0 deletions

42
rlm/Makefile-example Normal file
View File

@@ -0,0 +1,42 @@
## Makefile
##
## An example Makefile for building Rivendell Loadable Modules
##
## (C) Copyright 2008-2013 Fred Gleason <fredg@paravelsystems.com>
##
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU Library 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.
##
OBJS = rlm_ando.rlm\
rlm_facebook.rlm\
rlm_icecast2.rlm\
rlm_inno713.rlm\
rlm_liqcomp.rlm\
rlm_padpoint.rlm\
rlm_serial.rlm\
rlm_shoutcast1.rlm\
rlm_spinitron_plus.rlm\
rlm_spottrap.rlm\
rlm_test.rlm\
rlm_twitter.rlm\
rlm_udp.rlm \
rlm_xmpad.rlm
%.rlm: %.c
$(CC) $(CFLAGS) -fPIC -shared $< -o $@
all: $(OBJS)
clean:
rm -f $(OBJS) *~

90
rlm/Makefile.am Normal file
View File

@@ -0,0 +1,90 @@
## automake.am
##
## Automake.am for rivendell/rlm
##
## (C) Copyright 2008 Fred Gleason <fredg@paravelsystems.com>
##
## $Id: Makefile.am,v 1.7.4.5 2013/09/12 23:26:11 cvs Exp $
##
## 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_CFLAGS = -fPIC -Wall
RLM_MODULES=rlm_ando.rlm\
rlm_facebook.rlm\
rlm_filewrite.rlm\
rlm_icecast2.rlm\
rlm_inno713.rlm\
rlm_liqcomp.rlm\
rlm_padpoint.rlm\
rlm_serial.rlm\
rlm_shoutcast1.rlm\
rlm_spinitron_plus.rlm\
rlm_spottrap.rlm\
rlm_test.rlm\
rlm_twitter.rlm\
rlm_udp.rlm\
rlm_xds.rlm\
rlm_xmpad.rlm
all: $(RLM_MODULES)
%.rlm: %.c
$(CC) $(AM_CFLAGS) -I$(top_srcdir) -shared $< -o $@
install: all
mkdir -p $(DESTDIR)$(prefix)/@RD_LIB_PATH@/rivendell
cp $(RLM_MODULES) $(DESTDIR)$(prefix)/@RD_LIB_PATH@/rivendell/
mkdir -p $(headerdir)
cp rlm.h $(headerdir)
headerdir = $(includedir)/rlm
header_HEADERS = rlm.h
EXTRA_DIST = Makefile-example\
rlm.h\
rlm_ando.c\
rlm_facebook.c\
rlm_filewrite.c\
rlm_icecast2.c\
rlm_inno713.c\
rlm_liqcomp.c\
rlm_padpoint.c\
rlm_serial.c\
rlm_shoutcast1.c\
rlm_spinitron_plus.c\
rlm_spottrap.c\
rlm_test.c\
rlm_twitter.c\
rlm_udp.c\
rlm_xds.c\
rlm_xmpad.c
CLEANFILES = *~\
*.idb\
*ilk\
*.obj\
*.pdb\
*.qm\
*.rlm\
moc_*
MAINTAINERCLEANFILES = *~\
*.tar.gz\
aclocal.m4\
configure\
Makefile.in\
moc_*

372
rlm/rlm.h Normal file
View File

@@ -0,0 +1,372 @@
/* rlm.h
*
* The Rivendell Loadable Module Interface
*
* (C) Copyright 2008-2013 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.
*
*
* This interface can be used to create "Rivendell Loadable Modules" [RLMs]
* that enable Rivendell's "Now & Next" capability to supply program associated
* data [PAD] to external devices and systems. Runtime module configuration
* is accomplished in RDAdmin->ManageHosts->RDAirPlay->ConfigureNow&Next.
*
* Compiled plugins are dynamically loadable libraries (DLLs) and have names
* of the form '<basename>.rlm'. The following callbacks are provided:
*
* void <basename>_RLMStart(void *ptr,const char *arg)
* Called once upon RDAirPlay startup. The plugin should do any necessary
* startup tasks (opening i/o devices, allocating memory, etc) here. The
* single argument 'arg' is a null-terminated string, consisting of the
* 'Argument' parameter supplied in the specific runtime configuration
* from RDAdmin. The 'ptr' argument is an opaque pointer that is
* used as the first argument to the utility functions.
*
* void <basename>_RLMFree(void *ptr)
* Called once upon RDAirPlay shutdown. Any system resources allocated
* by the plugin should be released here. The 'ptr' argument is an opaque
* pointer that is be used as the first argument to any of the utility
* functions.
*
*
* void <basename>_RLMPadDataSent(void *ptr,const struct rlm_svc *svc,
* const struct rlm_log *log,
* const struct rlm_pad *now,
* const struct rlm_pad *next)
* Called each time RDAirPlay changes play state on a log. The 'svc'
* and 'log' parameters provide information about the current log and
* service respectively. The 'ptr' argument is an opaque pointer that
* is used as the first argument to the utility functions.
*
* WARNING: the structures provided in this callback are dynamically
* allocated, their scope is valid only within the callback!
*
* void <basename>_RLMTimerExpired(void *ptr,int timernum)
* Called each time the system RLM timer indicated by 'timernum' expires.
* See the 'RLMStartTimer()' and 'RLMStopTimer()' functions for info on
* using timers. The 'ptr' argument is an opaque pointer that is
* used as the first argument to the utility functions.
*
* void <basename>_RLMSerialDataReceived(void *ptr,int handle,
* const char *data,int len)
* Called each time data is received on an open tty/serial device. See
* the 'RLMOpenSerial()' and 'RLMCloseSerial()' functions for info on
* using tty/serial devices. The 'ptr' argument is an opaque pointer
* that is used as the first argument to the utility functions.
*/
#ifndef RLM_H
#define RLM_H
#include <stdint.h>
#include <syslog.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
* RLM Interface Version
*/
#define RLM_VERSION 17
/*
* Available Timers
*/
#define RLM_MAX_TIMERS 32
/*
* Timer Modes
* (for use in the RLMStartTimer() function).
*/
#define RLM_TIMER_REPEATING 0
#define RLM_TIMER_ONESHOT 1
/*
* Parity Modes
* (for use in the RLMOpenSerial() function).
*/
#define RLM_PARITY_NONE 0
#define RLM_PARITY_EVEN 1
#define RLM_PARITY_ODD 2
/*
* Cart Types
* (for use in the 'rlm_carttype' field of the 'rlm_pad' struct)
*/
#define RLM_CARTTYPE_ALL 0
#define RLM_CARTTYPE_AUDIO 1
#define RLM_CARTTYPE_MACRO 2
/*
* Log Machine Modes
* (for use in the 'rlm_mode' field of the 'rlm_log' struct)
*/
#define RLM_LOGMODE_LIVEASSIST 1
#define RLM_LOGMODE_AUTOMATIC 2
#define RLM_LOGMODE_MANUAL 3
/*
* Data Encodings
* (for use in the RLMResolveNowNextEncoded() function).
*/
#define RLM_ENCODE_NONE 0
#define RLM_ENCODE_XML 1
#define RLM_ENCODE_URL 2
/*
* Service data structure
*/
struct rlm_svc {
char svc_name[256]; /* Service name */
char svc_pgmcode[256]; /* Program Code */
char reserved[1536]; /* Reserved for future use */
};
/*
* Log data structure
*/
struct rlm_log {
char log_name[65]; /* Log name */
uint32_t log_mach; /* Log machine number, 0=Main, 1=Aux 1, 2=Aux2 */
char log_onair; /* On-air flag, 0=False, 1=True */
uint32_t log_mode; /* Log machine mode, 1=LiveAssist, 2=Automatic, 3=Manual */
char reserved[1974]; /* Reserved for future use */
};
/*
* Metadata structure
*/
struct rlm_pad {
uint32_t rlm_cartnum; /* Rivendell cart number */
uint32_t rlm_len; /* Event length, in milliseconds */
char rlm_year[5]; /* Cart year */
char rlm_group[11]; /* Rivendell Group Name */
char rlm_title[256]; /* Cart 'title' field */
char rlm_artist[256]; /* Cart 'artist' field */
char rlm_label[65]; /* Cart 'label' field */
char rlm_client[65]; /* Cart 'client' field */
char rlm_agency[65]; /* Cart 'agency' field */
char rlm_comp[65]; /* Cart 'composer' field */
char rlm_pub[65]; /* Cart 'publisher' field */
char rlm_userdef[256]; /* Cart 'user defined' field */
char rlm_album[256]; /* Cart 'album' field */
char rlm_isrc[12]; /* Cut International Standard Recording Code */
char rlm_isci[32]; /* Cut ISCI Code */
char rlm_carttype; /* Cart type, see RLM_CARTTYPE_* defines */
char rlm_ext_eventid[33]; /* Event ID, from external scheduler */
char rlm_ext_data[33]; /* Data, from external scheduler */
char rlm_ext_annctype[1]; /* Announcement Type, from external scheduler */
int32_t rlm_start_msec; /* Event start time, milliseconds part */
int32_t rlm_start_sec; /* Event start time, seconds part */
int32_t rlm_start_min; /* Event start time, minutes part */
int32_t rlm_start_hour; /* Event start time, hours part */
int32_t rlm_start_day; /* Event start date, day of month part */
int32_t rlm_start_mon; /* Event start date, month of year part */
int32_t rlm_start_year; /* Event start date, year part */
char rlm_conductor[65]; /* Cart 'conductor' field */
char rlm_song_id[33]; /* Cart 'songId' field */
char rlm_outcue[65]; /* Cut outcue field */
char rlm_description[65]; /* Cut description field */
char reserved[305]; /* Reserved for future use */
};
/*
* Communications Functions
*
*
* Send a UDP packet.
*
* The <ipaddr> parameter is a null-terminated string consisting of the
* IPv4 destination address in dotted-quad notation, and <port> is the
* destination UDP port number. All structures are in host (*not* network)
* byte order. The data to be sent, of length <len>, is pointed to by
* <data>.
*/
void RLMSendUdp(void *ptr,const char *ipaddr,uint16_t port,
const char *data,int len);
/*
* Open a tty device (serial port) for output.
*
* The <devname> parameter is a null-terminated string consisting of the
* name of the tty device to open (e.g. "/dev/ttyS0"). The <speed>,
* <parity> and <word_length> parameters define the communications
* parameters to be used.
*
* RETURNS: if successful, a non-negative integer that should be used
* as the <handle> argument for the RLMSendSerial() and RLMCloseSerial()
* functions. If unsuccessful, a negative integer will be returned.
*/
int RLMOpenSerial(void *ptr,const char *devname,int speed,
int parity,int word_length);
/*
* Output data on a tty device.
*
* Output data of length <len> pointed to by <data> on the tty device
* indicated by the <handle> value returned by the RLMOpenSerial() function.
*/
void RLMSendSerial(void *ptr,int handle,const char *data,int len);
/*
* Close a tty device.
*
* Close the tty device indicated by the <handle> value returned by the
* RLMOpenSerial() function.
*/
void RLMCloseSerial(void *ptr,int handle);
/*
* Convienence Functions
*/
/*
* Get a string indicating the system time.
*
* Returns a pointer to a null-terminated string indicating the system time,
* formatted as per the <format> argument. The following wildcards are
* supported:
* d the day as number without a leading zero (1-31)
* dd the day as number with a leading zero (01-31)
* ddd the abbreviated localized day name (e.g. 'Mon'..'Sun').
* dddd the long localized day name (e.g. 'Monday'..'Sunday').
* M the month as number without a leading zero (1-12)
* MM the month as number with a leading zero (01-12)
* MMM the abbreviated localized month name (e.g. 'Jan'..'Dec').
* MMMM the long localized month name (e.g. 'January'..'December').
* yy the year as two digit number (00-99)
* yyyy the year as four digit number (1752-8000)
* h the hour without a leading zero (0..23 or 1..12 if AM/PM
* display)
* hh the hour with a leading zero (00..23 or 01..12 if AM/PM display)
* m the minute without a leading zero (0..59)
* mm the minute with a leading zero (00..59)
* s the second whithout a leading zero (0..59)
* ss the second whith a leading zero (00..59)
* z the milliseconds without leading zeroes (0..999)
* zzz the milliseconds with leading zeroes (000..999)
* AP use AM/PM display. AP will be replaced by either "AM" or "PM".
* ap use am/pm display. ap will be replaced by either "am" or "pm".
*
* RETURNS: A pointer to a null terminated string. This string is statically
* allocated, and may be reused in subsequent calls to the utility functions.
*/
const char *RLMDateTime(void *ptr,int offset_msecs,const char *format);
/*
* Resolve standard Rivendell Now & Next wildcards, with the possiblity
* to encode the PAD fields.
*
* Returns a pointer to a null-terminated string resulting from resolving
* the 'standard' Rivendell Now & Next wildcards in accordance with the
* data values in the <now> and <next> parameters. The following wildcards
* are supported:
*
* Now Next Field
* ----------------------------------------------
* %n %N The Rivendell cart number
* %h %H Event length (in milliseconds)
* %g %G The Rivendell group name
* %t %T Title
* %a %A Artist
* %l %L Album
* %y %Y Year
* %b %B Record Label
* %c %C Client
* %e %E Agency
* %m %M Composer
* %p %P Publisher
* %r %R Conductor
* %s %S Song ID
* %u %U User Definied
* %o %O Outcue
* %i %I Description
* %D(<dt>) The current date/time, formatted according to <dt>. <dt>
* can be any of the wildcards supported by the RLMDateTime()
* function (see above).
*
* Additionally, an encoding can be specified to allow PAD fields to be
* escaped for a particular format. Available encodings are:
*
* RLM_ENCODE_NONE - Perform no character escaping.
* RLM_ENCODE_XML - Escape reserved characters as per XML-v1.0
* RLM_ENCODE_URL - Escape reserved characters as per RFC 2396 Section 2.4
*
* RETURNS: A pointer to a null terminated string. This string is statically
* allocated, and may be reused in subsequent calls to the utility functions.
*/
const char *RLMResolveNowNextEncoded(void *ptr,const struct rlm_pad *now,
const struct rlm_pad *next,
const char *format,int encoding);
/*
* Resolve standard Rivendell Now & Next wildcards
*
* (NOTE: This function is deprecated, and included merely to keep old code
* working. It should *not* be used in new code. For a better alternative,
* see the RLMResolveNowNextEncoded() function above).
*
* Returns a pointer to a null-terminated string resulting from resolving
* the 'standard' Rivendell Now & Next wildcards in accordance with the
* data values in the <now> and <next> parameters. The following wildcards
* are supported:
*
* Now Next Field
* ----------------------------------------------
* %n %N The Rivendell cart number
* %h %H Event length (in milliseconds)
* %g %G The Rivendell group name
* %t %T Title
* %a %A Artist
* %l %L Album
* %y %Y Year
* %b %B Record Label
* %c %C Client
* %e %E Agency
* %m %M Composer
* %p %P Publisher
* %r %R Conductor
* %s %S Song ID
* %u %U User Definied
* %o %O Outcue
* %d %D Cut Description
*
* RETURNS: A pointer to a null terminated string. This string is statically
* allocated, and may be reused in subsequent calls to the utility functions.
*/
const char *RLMResolveNowNext(void *ptr,const struct rlm_pad *now,
const struct rlm_pad *next,const char *format);
void RLMLog(void *ptr,int prio,const char *msg);
void RLMStartTimer(void *ptr,int timernum,int msecs,int mode);
void RLMStopTimer(void *ptr,int timernum);
int RLMGetIntegerValue(void *ptr,const char *filename,const char *section,
const char *label,int default_value);
int RLMGetHexValue(void *ptr,const char *filename,
const char *section,const char *label,int default_value);
int RLMGetBooleanValue(void *ptr,const char *filename,
const char *section,const char *label,
int default_value);
const char *RLMGetStringValue(void *ptr,const char *filename,
const char *section,const char *label,
const char *default_value);
#ifdef __cplusplus
}
#endif
#endif /* RLM_H */

217
rlm/rlm_ando.c Normal file
View File

@@ -0,0 +1,217 @@
/* rlm_ando.c
*
* (C) Copyright 2009 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.
*
* This is a Rivendell Loadable Module. It sends Now&Next PAD data to an
* ANDO Media Streaming system. Options are specified in the configuration
* file pointed to by the plugin argument.
*
* To compile this module, just do:
*
* gcc -shared -o rlm_ando.rlm rlm_ando.c
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <rlm/rlm.h>
int rlm_ando_devs;
char *rlm_ando_addresses;
uint16_t *rlm_ando_ports;
char *rlm_ando_titles;
char *rlm_ando_artists;
char *rlm_ando_albums;
char *rlm_ando_labels;
int *rlm_ando_masters;
int *rlm_ando_aux1s;
int *rlm_ando_aux2s;
int rlm_ando_GetLogStatus(void *ptr,const char *arg,const char *section,
const char *logname)
{
const char *tag=RLMGetStringValue(ptr,arg,section,logname,"");
if(strcasecmp(tag,"yes")==0) {
return 1;
}
if(strcasecmp(tag,"on")==0) {
return 1;
}
if(strcasecmp(tag,"true")==0) {
return 1;
}
if(strcasecmp(tag,"no")==0) {
return 0;
}
if(strcasecmp(tag,"off")==0) {
return 0;
}
if(strcasecmp(tag,"false")==0) {
return 0;
}
if(strcasecmp(tag,"onair")==0) {
return 2;
}
return 0;
}
void rlm_ando_RLMStart(void *ptr,const char *arg)
{
char address[17];
char section[256];
char errtext[256];
int i=1;
rlm_ando_devs=0;
rlm_ando_addresses=NULL;
rlm_ando_ports=NULL;
rlm_ando_masters=NULL;
rlm_ando_aux1s=NULL;
rlm_ando_aux2s=NULL;
sprintf(section,"System%d",i++);
strncpy(address,RLMGetStringValue(ptr,arg,section,"IpAddress",""),15);
if(strlen(address)==0) {
RLMLog(ptr,LOG_WARNING,"rlm_ando: no ando destinations specified");
return;
}
while(strlen(address)>0) {
rlm_ando_addresses=
realloc(rlm_ando_addresses,(rlm_ando_devs+1)*(rlm_ando_devs+1)*16);
strcpy(rlm_ando_addresses+16*rlm_ando_devs,address);
rlm_ando_ports=realloc(rlm_ando_ports,(rlm_ando_devs+1)*sizeof(uint16_t));
rlm_ando_ports[rlm_ando_devs]=
RLMGetIntegerValue(ptr,arg,section,"UdpPort",0);
rlm_ando_titles=realloc(rlm_ando_titles,(rlm_ando_devs+1)*256);
strncpy(rlm_ando_titles+256*rlm_ando_devs,
RLMGetStringValue(ptr,arg,section,"Title",""),256);
rlm_ando_artists=realloc(rlm_ando_artists,(rlm_ando_devs+1)*256);
strncpy(rlm_ando_artists+256*rlm_ando_devs,
RLMGetStringValue(ptr,arg,section,"Artist",""),256);
rlm_ando_albums=realloc(rlm_ando_albums,(rlm_ando_devs+1)*256);
strncpy(rlm_ando_albums+256*rlm_ando_devs,
RLMGetStringValue(ptr,arg,section,"Album",""),256);
rlm_ando_labels=realloc(rlm_ando_labels,(rlm_ando_devs+1)*256);
strncpy(rlm_ando_labels+256*rlm_ando_devs,
RLMGetStringValue(ptr,arg,section,"Label",""),256);
rlm_ando_masters=realloc(rlm_ando_masters,
(rlm_ando_devs+1)*sizeof(int));
rlm_ando_masters[rlm_ando_devs]=
rlm_ando_GetLogStatus(ptr,arg,section,"MasterLog");
rlm_ando_aux1s=realloc(rlm_ando_aux1s,
(rlm_ando_devs+1)*sizeof(int));
rlm_ando_aux1s[rlm_ando_devs]=
rlm_ando_GetLogStatus(ptr,arg,section,"Aux1Log");
rlm_ando_aux2s=realloc(rlm_ando_aux2s,
(rlm_ando_devs+1)*sizeof(int));
rlm_ando_aux2s[rlm_ando_devs]=
rlm_ando_GetLogStatus(ptr,arg,section,"Aux2Log");
sprintf(errtext,"rlm_ando: configured destination \"%s:%d\"",address,
rlm_ando_ports[rlm_ando_devs]);
rlm_ando_devs++;
RLMLog(ptr,LOG_INFO,errtext);
sprintf(section,"System%d",i++);
strncpy(address,RLMGetStringValue(ptr,arg,section,"IpAddress",""),15);
}
RLMStartTimer(ptr,0,30000,RLM_TIMER_REPEATING);
}
void rlm_ando_RLMFree(void *ptr)
{
RLMStopTimer(ptr,0);
free(rlm_ando_addresses);
free(rlm_ando_ports);
free(rlm_ando_titles);
free(rlm_ando_artists);
free(rlm_ando_albums);
free(rlm_ando_labels);
free(rlm_ando_masters);
free(rlm_ando_aux1s);
free(rlm_ando_aux2s);
}
void rlm_ando_RLMPadDataSent(void *ptr,const struct rlm_svc *svc,
const struct rlm_log *log,
const struct rlm_pad *now,
const struct rlm_pad *next)
{
int i;
int flag=0;
char fmt[1024];
char msg[1500];
int hours;
int minutes;
int seconds;
for(i=0;i<rlm_ando_devs;i++) {
switch(log->log_mach) {
case 0:
flag=rlm_ando_masters[i];
break;
case 1:
flag=rlm_ando_aux1s[i];
break;
case 2:
flag=rlm_ando_aux2s[i];
break;
}
if((flag==1)||((flag==2)&&(log->log_onair!=0))) {
if(strlen(rlm_ando_labels+256*i)==0) { // Original format
snprintf(fmt,1024,"^%s~%s~%02d:%02d~%%g~%s~%%n|",
rlm_ando_artists+256*i,
rlm_ando_titles+256*i,
now->rlm_len/60000,(now->rlm_len%60000)/1000,
rlm_ando_albums+256*i);
}
else { // Enhanced format
hours=now->rlm_len/3600000;
minutes=(now->rlm_len-hours*3600000)/60000;
seconds=(now->rlm_len-hours*3600000-minutes*60000)/1000;
snprintf(fmt,1024,"^%s~%s~%02d:%02d:%02d~%%g~%%n~%s~%s|",
rlm_ando_artists+256*i,
rlm_ando_titles+256*i,
hours,minutes,seconds,
rlm_ando_albums+256*i,
rlm_ando_labels+256*i);
}
const char *str=RLMResolveNowNext(ptr,now,next,fmt);
RLMSendUdp(ptr,rlm_ando_addresses+i*16,rlm_ando_ports[i],str,strlen(str));
snprintf(msg,1500,"rlm_ando: sending pad update: \"%s\"",
(const char *)str);
RLMLog(ptr,LOG_INFO,msg);
}
}
}
void rlm_ando_RLMTimerExpired(void *ptr,int timernum)
{
int i;
switch(timernum) {
case 0: // Heartbeat
for(i=0;i<rlm_ando_devs;i++) {
RLMSendUdp(ptr,rlm_ando_addresses+i*16,rlm_ando_ports[i],"HB",2);
}
break;
}
}

316
rlm/rlm_facebook.c Normal file
View File

@@ -0,0 +1,316 @@
/* rlm_facebook.c
*
* (C) Copyright 2008 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.
*
* This is a Rivendell Loadable Module. It sends Now&Next PAD data
* to the Facebook account(s) specified in the configuration file pointed
* to by the plugin argument. For information about the Facebook service,
* see http://www.facebook.com/.
*
* This module requires the curl(1) network transfer tool, included with
* most Linux distros. It is also available at http://curl.haxx.se/.
*
* To compile this module, just do:
*
* gcc -shared -o rlm_facebook.rlm rlm_facebook.c
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <sys/types.h>
#include <unistd.h>
#include <rlm/rlm.h>
int rlm_facebook_devs;
char *rlm_facebook_addresses;
char *rlm_facebook_passwords;
char *rlm_facebook_formats;
int *rlm_facebook_masters;
int *rlm_facebook_aux1s;
int *rlm_facebook_aux2s;
char *rlm_facebook_cookies;
int rlm_facebook_BufferDiff(char *sString,int dOrigin,int dDiff,int dMaxSize)
{
int dOldSize,dNewSize;
int i;
/*
* Will it fit?
*/
dOldSize=strlen(sString);
if((dOldSize+dDiff)>=dMaxSize) {
return -1;
}
dNewSize=dOldSize+dDiff;
/*
* Adding characters
*/
if(dDiff>0) {
for(i=dOldSize;i>dOrigin;i--) {
sString[i+dDiff]=sString[i];
}
return dNewSize;
}
/*
* No Change
*/
if(dDiff==0) {
return dNewSize;
}
/*
* Deleting Characters
*/
if(dDiff<0) {
for(i=dOrigin;i<dOldSize;i++) {
sString[i]=sString[i-dDiff];
}
return dNewSize;
}
return -1;
}
int rlm_facebook_EncodeString(char *sString,int dMaxSize)
{
int i; /* General Purpose Counter */
char sAccum[4]; /* General String Buffer */
i=0;
while(sString[i]!=0) {
if(((sString[i]!=' ') && (sString[i]!='*') && (sString[i]!='-') &&
(sString[i]!='_') && (sString[i]!='.')) &&
((sString[i]<'0') ||
((sString[i]>'9') && (sString[i]<'A')) ||
((sString[i]>'Z') && (sString[i]<'a')) ||
(sString[i]>'z'))) {
if(rlm_facebook_BufferDiff(sString,i,2,dMaxSize)<0) {
return -1;
}
sprintf(sAccum,"%%%2x",sString[i]);
sString[i++]=sAccum[0];
sString[i++]=sAccum[1];
sString[i]=sAccum[2];
}
if(sString[i]==' ') {
sString[i]='+';
}
i++;
}
return strlen(sString);
}
void rlm_facebook_Login(int config)
{
char cmd[1024];
unlink(rlm_facebook_cookies+256*config); /* Cleanup from past session */
snprintf(cmd,1024,
"curl -o /dev/null -s -A Mozilla/4.0 -c %s http://www.facebook.com/",
rlm_facebook_cookies+256*config);
system(cmd);
snprintf(cmd,1024,"curl -o /dev/null -s --insecure -A Mozilla/4.0 -c %s -b %s -d persistent=1 -d email=%s -d pass=%s https://login.facebook.com/login.php",
rlm_facebook_cookies+256*config,
rlm_facebook_cookies+256*config,
rlm_facebook_addresses+256*config,
rlm_facebook_passwords+256*config);
system(cmd);
}
void rlm_facebook_Logout(int config)
{
if(fork()==0) {
execlp("curl","curl","-A","Mozilla/4.0","-b",
rlm_facebook_cookies+256*config,
"-o","/dev/null","-s",
"http://www.facebook.com/logout.php",
(char *)NULL);
exit(0);
}
}
int rlm_facebook_GetLogStatus(void *ptr,const char *arg,const char *section,
const char *logname)
{
const char *tag=RLMGetStringValue(ptr,arg,section,logname,"");
if(strcasecmp(tag,"yes")==0) {
return 1;
}
if(strcasecmp(tag,"on")==0) {
return 1;
}
if(strcasecmp(tag,"true")==0) {
return 1;
}
if(strcasecmp(tag,"no")==0) {
return 0;
}
if(strcasecmp(tag,"off")==0) {
return 0;
}
if(strcasecmp(tag,"false")==0) {
return 0;
}
if(strcasecmp(tag,"onair")==0) {
return 2;
}
return 0;
}
void rlm_facebook_RLMStart(void *ptr,const char *arg)
{
char address[256];
char section[256];
char errtext[256];
int i=1;
rlm_facebook_devs=0;
rlm_facebook_addresses=NULL;
rlm_facebook_passwords=NULL;
rlm_facebook_formats=NULL;
rlm_facebook_masters=NULL;
rlm_facebook_aux1s=NULL;
rlm_facebook_aux2s=NULL;
rlm_facebook_cookies=NULL;
sprintf(section,"Facebook%d",i++);
strncpy(address,RLMGetStringValue(ptr,arg,section,"EmailAddress",""),255);
address[255]=0;
if(strlen(address)==0) {
RLMLog(ptr,LOG_WARNING,"rlm_facebook: no facebook accounts specified");
return;
}
while(strlen(address)>0) {
rlm_facebook_addresses=realloc(rlm_facebook_addresses,
(rlm_facebook_devs+1)*(rlm_facebook_devs+1)*256);
strcpy(rlm_facebook_addresses+256*rlm_facebook_devs,address);
rlm_facebook_EncodeString(rlm_facebook_addresses+256*rlm_facebook_devs,255);
rlm_facebook_passwords=realloc(rlm_facebook_passwords,
(rlm_facebook_devs+1)*(rlm_facebook_devs+1)*256);
strcpy(rlm_facebook_passwords+256*rlm_facebook_devs,
RLMGetStringValue(ptr,arg,section,"Password",""));
rlm_facebook_EncodeString(rlm_facebook_passwords+256*rlm_facebook_devs,255);
rlm_facebook_formats=realloc(rlm_facebook_formats,(rlm_facebook_devs+1)*256);
strncpy(rlm_facebook_formats+256*rlm_facebook_devs,
RLMGetStringValue(ptr,arg,section,"FormatString",""),256);
rlm_facebook_masters=realloc(rlm_facebook_masters,
(rlm_facebook_devs+1)*sizeof(int));
rlm_facebook_masters[rlm_facebook_devs]=
rlm_facebook_GetLogStatus(ptr,arg,section,"MasterLog");
rlm_facebook_aux1s=realloc(rlm_facebook_aux1s,
(rlm_facebook_devs+1)*sizeof(int));
rlm_facebook_aux1s[rlm_facebook_devs]=
rlm_facebook_GetLogStatus(ptr,arg,section,"Aux1Log");
rlm_facebook_aux2s=realloc(rlm_facebook_aux2s,
(rlm_facebook_devs+1)*sizeof(int));
rlm_facebook_aux2s[rlm_facebook_devs]=
rlm_facebook_GetLogStatus(ptr,arg,section,"Aux2Log");
sprintf(errtext,"rlm_facebook: configured account \"%s\"",address);
rlm_facebook_cookies=
realloc(rlm_facebook_cookies,(rlm_facebook_devs+1)*256);
snprintf(rlm_facebook_cookies+rlm_facebook_devs*256,256,
"/tmp/rlm_facebook%d_cookies.txt",rlm_facebook_devs+1);
rlm_facebook_devs++;
RLMLog(ptr,LOG_INFO,errtext);
sprintf(section,"Facebook%d",i++);
strncpy(address,RLMGetStringValue(ptr,arg,section,"EmailAddress",""),255);
address[255]=0;
}
for(i=0;i<(rlm_facebook_devs);i++) {
rlm_facebook_Login(i);
}
}
void rlm_facebook_RLMFree(void *ptr)
{
int i;
for(i=0;i<(rlm_facebook_devs);i++) {
rlm_facebook_Logout(i);
}
free(rlm_facebook_addresses);
free(rlm_facebook_passwords);
free(rlm_facebook_formats);
free(rlm_facebook_masters);
free(rlm_facebook_aux1s);
free(rlm_facebook_aux2s);
free(rlm_facebook_cookies);
}
void rlm_facebook_RLMPadDataSent(void *ptr,const struct rlm_svc *svc,
const struct rlm_log *log,
const struct rlm_pad *now,
const struct rlm_pad *next)
{
int i;
int flag=0;
char str[1024];
char pad[1024];
char msg[1500];
for(i=0;i<rlm_facebook_devs;i++) {
switch(log->log_mach) {
case 0:
flag=rlm_facebook_masters[i];
break;
case 1:
flag=rlm_facebook_aux1s[i];
break;
case 2:
flag=rlm_facebook_aux2s[i];
break;
}
if((flag==1)||((flag==2)&&(log->log_onair!=0))) {
strncpy(str,RLMResolveNowNext(ptr,now,next,
rlm_facebook_formats+256*i),256);
rlm_facebook_EncodeString(str,1023);
snprintf(pad,1024,"status=%s",str);
if(strlen(now->rlm_title)!=0) {
if(fork()==0) {
execlp("curl","curl","-A","Mozilla/4.0","-b",
rlm_facebook_cookies+256*i,
"-d",pad,
"-d","test_name=INLINE_STATUS_EDITOR",
"-d","action=OTHER_UPDATE",
"-d","post_form_id=aae2d1af1c8ed0cd36ade54bc8f48427",
"-o","/dev/null","-s",
"http://www.facebook.com/updatestatus.php",(char *)NULL);
RLMLog(ptr,LOG_WARNING,"rlm_facebook: unable to execute curl(1)");
exit(0);
}
}
snprintf(msg,1500,"rlm_facebook: sending pad update: \"%s\"",
(const char *)str);
RLMLog(ptr,LOG_INFO,msg);
}
}
}

228
rlm/rlm_filewrite.c Normal file
View File

@@ -0,0 +1,228 @@
/* rlm_filewrite.c
*
* (C) Copyright 2012 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.
*
* This is a Rivendell Loadable Module. It uses Now&Next PAD data
* to write to one or more file(s) on the local system specified in the
* configuration file pointed to by the plugin argument.
*
* To compile this module, just do:
*
* gcc -shared -o rlm_filewrite.rlm rlm_filewrite.c
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <sys/types.h>
#include <unistd.h>
#include <rlm/rlm.h>
int rlm_filewrite_devs;
char *rlm_filewrite_filenames;
int *rlm_filewrite_appends;
char *rlm_filewrite_formats;
int *rlm_filewrite_encodings;
int *rlm_filewrite_masters;
int *rlm_filewrite_aux1s;
int *rlm_filewrite_aux2s;
void rlm_filewrite_ReplaceChar(char c,char *str,int pos)
{
int i;
str[pos]=c;
for(i=pos+1;i<strlen(str);i++) {
str[i]=str[i+1];
}
}
void rlm_filewrite_ProcessString(char *str)
{
int i;
for(i=0;i<(strlen(str)-1);i++) {
if(str[i]=='\\') {
if(str[i+1]=='r') {
rlm_filewrite_ReplaceChar(13,str,i);
}
else {
if(str[i+1]=='n') {
rlm_filewrite_ReplaceChar(10,str,i);
}
}
}
}
}
int rlm_filewrite_GetLogStatus(void *ptr,const char *arg,const char *section,
const char *logname)
{
const char *tag=RLMGetStringValue(ptr,arg,section,logname,"");
if(strcasecmp(tag,"yes")==0) {
return 1;
}
if(strcasecmp(tag,"on")==0) {
return 1;
}
if(strcasecmp(tag,"true")==0) {
return 1;
}
if(strcasecmp(tag,"no")==0) {
return 0;
}
if(strcasecmp(tag,"off")==0) {
return 0;
}
if(strcasecmp(tag,"false")==0) {
return 0;
}
if(strcasecmp(tag,"onair")==0) {
return 2;
}
return 0;
}
void rlm_filewrite_RLMStart(void *ptr,const char *arg)
{
char filename[256];
char section[256];
char errtext[256];
int i=1;
rlm_filewrite_devs=0;
rlm_filewrite_filenames=NULL;
rlm_filewrite_appends=NULL;
rlm_filewrite_formats=NULL;
rlm_filewrite_encodings=NULL;
rlm_filewrite_masters=NULL;
rlm_filewrite_aux1s=NULL;
rlm_filewrite_aux2s=NULL;
sprintf(section,"File%d",i++);
strncpy(filename,RLMGetStringValue(ptr,arg,section,"Filename",""),255);
filename[255]=0;
if(strlen(filename)==0) {
RLMLog(ptr,LOG_WARNING,"rlm_filewrite: no files specified");
return;
}
while(strlen(filename)>0) {
rlm_filewrite_filenames=realloc(rlm_filewrite_filenames,
(rlm_filewrite_devs+1)*(rlm_filewrite_devs+1)*256);
strcpy(rlm_filewrite_filenames+256*rlm_filewrite_devs,filename);
rlm_filewrite_appends=realloc(rlm_filewrite_appends,
(rlm_filewrite_devs+1)*sizeof(int));
rlm_filewrite_appends[rlm_filewrite_devs]=
RLMGetIntegerValue(ptr,arg,section,"Append",0);
rlm_filewrite_formats=realloc(rlm_filewrite_formats,(rlm_filewrite_devs+1)*256);
strncpy(rlm_filewrite_formats+256*rlm_filewrite_devs,
RLMGetStringValue(ptr,arg,section,"FormatString",""),256);
rlm_filewrite_masters=realloc(rlm_filewrite_masters,
(rlm_filewrite_devs+1)*sizeof(int));
rlm_filewrite_masters[rlm_filewrite_devs]=
rlm_filewrite_GetLogStatus(ptr,arg,section,"MasterLog");
rlm_filewrite_encodings=realloc(rlm_filewrite_encodings,
(rlm_filewrite_devs+1)*sizeof(int));
rlm_filewrite_encodings[rlm_filewrite_devs]=
RLMGetIntegerValue(ptr,arg,section,"Encoding",RLM_ENCODE_NONE);
rlm_filewrite_aux1s=realloc(rlm_filewrite_aux1s,
(rlm_filewrite_devs+1)*sizeof(int));
rlm_filewrite_aux1s[rlm_filewrite_devs]=
rlm_filewrite_GetLogStatus(ptr,arg,section,"Aux1Log");
rlm_filewrite_aux2s=realloc(rlm_filewrite_aux2s,
(rlm_filewrite_devs+1)*sizeof(int));
rlm_filewrite_aux2s[rlm_filewrite_devs]=
rlm_filewrite_GetLogStatus(ptr,arg,section,"Aux2Log");
sprintf(errtext,"rlm_filewrite: configured file \"%s\"",
rlm_filewrite_filenames+256*rlm_filewrite_devs);
rlm_filewrite_devs++;
RLMLog(ptr,LOG_INFO,errtext);
sprintf(section,"File%d",i++);
strncpy(filename,RLMGetStringValue(ptr,arg,section,"Filename",""),255);
filename[255]=0;
}
}
void rlm_filewrite_RLMFree(void *ptr)
{
free(rlm_filewrite_filenames);
free(rlm_filewrite_appends);
free(rlm_filewrite_formats);
free(rlm_filewrite_encodings);
free(rlm_filewrite_masters);
free(rlm_filewrite_aux1s);
free(rlm_filewrite_aux2s);
}
void rlm_filewrite_RLMPadDataSent(void *ptr,const struct rlm_svc *svc,
const struct rlm_log *log,
const struct rlm_pad *now,
const struct rlm_pad *next)
{
int i;
int flag=0;
char str[8192];
char msg[1500];
FILE *f;
for(i=0;i<rlm_filewrite_devs;i++) {
switch(log->log_mach) {
case 0:
flag=rlm_filewrite_masters[i];
break;
case 1:
flag=rlm_filewrite_aux1s[i];
break;
case 2:
flag=rlm_filewrite_aux2s[i];
break;
}
if((flag==1)||((flag==2)&&(log->log_onair!=0))) {
strncpy(str,RLMResolveNowNextEncoded(ptr,now,next,
rlm_filewrite_formats+256*i,
rlm_filewrite_encodings[i]),8192);
rlm_filewrite_ProcessString(str);
if(rlm_filewrite_appends[i]==0) {
f=fopen(rlm_filewrite_filenames+256*i,"w");
}
else {
f=fopen(rlm_filewrite_filenames+256*i,"a");
}
if(f!=NULL) {
snprintf(msg,1500,"rlm_filewrite: sending pad update: \"%s\" to \"%s\"",
str,rlm_filewrite_filenames+256*i);
fprintf(f,"%s",str);
fclose(f);
RLMLog(ptr,LOG_INFO,msg);
}
else {
snprintf(msg,1500,"rlm_filewrite: unable to open file \"%s\"",
rlm_filewrite_filenames+256*i);
RLMLog(ptr,LOG_WARNING,msg);
}
}
}
}

295
rlm/rlm_icecast2.c Normal file
View File

@@ -0,0 +1,295 @@
/* rlm_icecast2.c
*
* (C) Copyright 2008 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.
*
* This is a Rivendell Loadable Module. It uses Now&Next PAD data
* to update the metadata on an Icecast2 mountpoint specified in the
* configuration file pointed to by the plugin argument.
*
* This module requires the curl(1) network transfer tool, included with
* most Linux distros. It is also available at http://curl.haxx.se/.
*
* To compile this module, just do:
*
* gcc -shared -o rlm_icecast2.rlm rlm_icecast2.c
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <sys/types.h>
#include <unistd.h>
#include <rlm/rlm.h>
int rlm_icecast2_devs;
char *rlm_icecast2_usernames;
char *rlm_icecast2_passwords;
char *rlm_icecast2_hostnames;
int *rlm_icecast2_tcpports;
char *rlm_icecast2_mountpoints;
char *rlm_icecast2_formats;
int *rlm_icecast2_masters;
int *rlm_icecast2_aux1s;
int *rlm_icecast2_aux2s;
int rlm_icecast2_BufferDiff(char *sString,int dOrigin,int dDiff,int dMaxSize)
{
int dOldSize,dNewSize;
int i;
/*
* Will it fit?
*/
dOldSize=strlen(sString);
if((dOldSize+dDiff)>=dMaxSize) {
return -1;
}
dNewSize=dOldSize+dDiff;
/*
* Adding characters
*/
if(dDiff>0) {
for(i=dOldSize;i>dOrigin;i--) {
sString[i+dDiff]=sString[i];
}
return dNewSize;
}
/*
* No Change
*/
if(dDiff==0) {
return dNewSize;
}
/*
* Deleting Characters
*/
if(dDiff<0) {
for(i=dOrigin;i<dOldSize;i++) {
sString[i]=sString[i-dDiff];
}
return dNewSize;
}
return -1;
}
int rlm_icecast2_EncodeString(char *sString,int dMaxSize)
{
int i; /* General Purpose Counter */
char sAccum[4]; /* General String Buffer */
i=0;
while(sString[i]!=0) {
if(((sString[i]!='*') && (sString[i]!='-') &&
(sString[i]!='_') && (sString[i]!='.')) &&
((sString[i]<'0') ||
((sString[i]>'9') && (sString[i]<'A')) ||
((sString[i]>'Z') && (sString[i]<'a')) ||
(sString[i]>'z'))) {
if(rlm_icecast2_BufferDiff(sString,i,2,dMaxSize)<0) {
fprintf(stderr,"rlm_icecast2: BufferDiff() failed, maxsize: %d\n",
dMaxSize);
return -1;
}
sprintf(sAccum,"%%%2x",sString[i]);
sString[i++]=sAccum[0];
sString[i++]=sAccum[1];
sString[i]=sAccum[2];
}
if(sString[i]==' ') {
sString[i]='+';
}
i++;
if(i>=dMaxSize) {
fprintf(stderr,"rlm_icecast2: offset exceeded limit, maxsize: %d\n",
dMaxSize);
return -1;
}
}
return strlen(sString);
}
int rlm_icecast2_GetLogStatus(void *ptr,const char *arg,const char *section,
const char *logname)
{
const char *tag=RLMGetStringValue(ptr,arg,section,logname,"");
if(strcasecmp(tag,"yes")==0) {
return 1;
}
if(strcasecmp(tag,"on")==0) {
return 1;
}
if(strcasecmp(tag,"true")==0) {
return 1;
}
if(strcasecmp(tag,"no")==0) {
return 0;
}
if(strcasecmp(tag,"off")==0) {
return 0;
}
if(strcasecmp(tag,"false")==0) {
return 0;
}
if(strcasecmp(tag,"onair")==0) {
return 2;
}
return 0;
}
void rlm_icecast2_RLMStart(void *ptr,const char *arg)
{
char username[256];
char section[256];
char errtext[256];
int i=1;
rlm_icecast2_devs=0;
rlm_icecast2_usernames=NULL;
rlm_icecast2_passwords=NULL;
rlm_icecast2_formats=NULL;
rlm_icecast2_masters=NULL;
rlm_icecast2_aux1s=NULL;
rlm_icecast2_aux2s=NULL;
sprintf(section,"Icecast%d",i++);
strncpy(username,RLMGetStringValue(ptr,arg,section,"Username",""),255);
username[255]=0;
if(strlen(username)==0) {
RLMLog(ptr,LOG_WARNING,"rlm_icecast2: no icecast mountpoints specified");
return;
}
while(strlen(username)>0) {
rlm_icecast2_usernames=realloc(rlm_icecast2_usernames,
(rlm_icecast2_devs+1)*(rlm_icecast2_devs+1)*256);
strcpy(rlm_icecast2_usernames+256*rlm_icecast2_devs,username);
rlm_icecast2_passwords=realloc(rlm_icecast2_passwords,
(rlm_icecast2_devs+1)*(rlm_icecast2_devs+1)*256);
strcpy(rlm_icecast2_passwords+256*rlm_icecast2_devs,
RLMGetStringValue(ptr,arg,section,"Password",""));
rlm_icecast2_hostnames=realloc(rlm_icecast2_hostnames,
(rlm_icecast2_devs+1)*(rlm_icecast2_devs+1)*256);
strcpy(rlm_icecast2_hostnames+256*rlm_icecast2_devs,
RLMGetStringValue(ptr,arg,section,"Hostname",""));
rlm_icecast2_tcpports=realloc(rlm_icecast2_tcpports,
(rlm_icecast2_devs+1)*sizeof(int));
rlm_icecast2_tcpports[rlm_icecast2_devs]=
RLMGetIntegerValue(ptr,arg,section,"Tcpport",0);
rlm_icecast2_mountpoints=realloc(rlm_icecast2_mountpoints,
(rlm_icecast2_devs+1)*(rlm_icecast2_devs+1)*256);
strcpy(rlm_icecast2_mountpoints+256*rlm_icecast2_devs,
RLMGetStringValue(ptr,arg,section,"Mountpoint",""));
rlm_icecast2_formats=realloc(rlm_icecast2_formats,(rlm_icecast2_devs+1)*256);
strncpy(rlm_icecast2_formats+256*rlm_icecast2_devs,
RLMGetStringValue(ptr,arg,section,"FormatString",""),256);
rlm_icecast2_masters=realloc(rlm_icecast2_masters,
(rlm_icecast2_devs+1)*sizeof(int));
rlm_icecast2_masters[rlm_icecast2_devs]=
rlm_icecast2_GetLogStatus(ptr,arg,section,"MasterLog");
rlm_icecast2_aux1s=realloc(rlm_icecast2_aux1s,
(rlm_icecast2_devs+1)*sizeof(int));
rlm_icecast2_aux1s[rlm_icecast2_devs]=
rlm_icecast2_GetLogStatus(ptr,arg,section,"Aux1Log");
rlm_icecast2_aux2s=realloc(rlm_icecast2_aux2s,
(rlm_icecast2_devs+1)*sizeof(int));
rlm_icecast2_aux2s[rlm_icecast2_devs]=
rlm_icecast2_GetLogStatus(ptr,arg,section,"Aux2Log");
sprintf(errtext,"rlm_icecast2: configured mountpoint \"http://%s:%u%s\"",
rlm_icecast2_hostnames+256*rlm_icecast2_devs,
rlm_icecast2_tcpports[rlm_icecast2_devs],
rlm_icecast2_mountpoints+256*rlm_icecast2_devs);
rlm_icecast2_devs++;
RLMLog(ptr,LOG_INFO,errtext);
sprintf(section,"Icecast%d",i++);
strncpy(username,RLMGetStringValue(ptr,arg,section,"Username",""),255);
username[255]=0;
}
}
void rlm_icecast2_RLMFree(void *ptr)
{
free(rlm_icecast2_usernames);
free(rlm_icecast2_passwords);
free(rlm_icecast2_hostnames);
free(rlm_icecast2_tcpports);
free(rlm_icecast2_mountpoints);
free(rlm_icecast2_formats);
free(rlm_icecast2_masters);
free(rlm_icecast2_aux1s);
free(rlm_icecast2_aux2s);
}
void rlm_icecast2_RLMPadDataSent(void *ptr,const struct rlm_svc *svc,
const struct rlm_log *log,
const struct rlm_pad *now,
const struct rlm_pad *next)
{
int i;
int flag=0;
char str[1024];
char account[1024];
char url[1024];
char msg[1500];
for(i=0;i<rlm_icecast2_devs;i++) {
switch(log->log_mach) {
case 0:
flag=rlm_icecast2_masters[i];
break;
case 1:
flag=rlm_icecast2_aux1s[i];
break;
case 2:
flag=rlm_icecast2_aux2s[i];
break;
}
if((flag==1)||((flag==2)&&(log->log_onair!=0))) {
strncpy(str,RLMResolveNowNext(ptr,now,next,
rlm_icecast2_formats+256*i),256);
rlm_icecast2_EncodeString(str,1023);
snprintf(account,1024,"%s:%s",rlm_icecast2_usernames+256*i,
rlm_icecast2_passwords+256*i);
snprintf(url,1024,"http://%s:%d/admin/metadata?mount=%s&mode=updinfo&song=%s",
rlm_icecast2_hostnames+256*i,
rlm_icecast2_tcpports[i],
rlm_icecast2_mountpoints+256*i,str);
if(strlen(now->rlm_title)!=0) {
if(fork()==0) {
execlp("curl","curl","-u",account,"-o","/dev/null","-s",
url,(char *)NULL);
RLMLog(ptr,LOG_WARNING,"rlm_icecast2: unable to execute curl(1)");
exit(0);
}
}
snprintf(msg,1500,"rlm_icecast2: sending pad update: \"%s\"",
(const char *)str);
RLMLog(ptr,LOG_INFO,msg);
}
}
}

253
rlm/rlm_inno713.c Normal file
View File

@@ -0,0 +1,253 @@
/* rlm_inno713.c
*
* (C) Copyright 2009 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.
*
* This is a Rivendell Loadable Module. It sends Now&Next PAD
* to the Innovonics model 713 RDS encoder, as specified in the
* configuration file pointed to by the plugin argument.
*
* To compile this module, just do:
*
* gcc -shared -o rlm_inno713.rlm rlm_inno713.c
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <ctype.h>
#include <rlm/rlm.h>
int rlm_inno713_devs;
char *rlm_inno713_addresses;
uint16_t *rlm_inno713_ports;
int *rlm_inno713_handles;
char *rlm_inno713_dynamicpss;
char *rlm_inno713_pss;
char *rlm_inno713_radiotexts;
int *rlm_inno713_masters;
int *rlm_inno713_aux1s;
int *rlm_inno713_aux2s;
void rlm_inno713_Upcase(char *str)
{
int i;
for(i=0;i<strlen(str);i++) {
str[i]=toupper(str[i]);
}
}
void rlm_inno713_SendString(void *ptr,const struct rlm_pad *now,
const struct rlm_pad *next,const char *tag,
const char *fmt,const char *addr,uint16_t port,
int handle)
{
char pkt[1024];
if(strlen(fmt)>0) {
const char *str=RLMResolveNowNext(ptr,now,next,fmt);
if(strlen(str)>0) {
sprintf(pkt,"%s=%s\r\n",tag,str);
rlm_inno713_Upcase(pkt);
if(strlen(addr)>0) {
RLMSendUdp(ptr,addr,port,pkt,strlen(pkt));
}
if(handle>=0) {
RLMSendSerial(ptr,handle,pkt,strlen(pkt));
}
}
}
}
int rlm_inno713_GetLogStatus(void *ptr,const char *arg,const char *section,
const char *logname)
{
const char *tag=RLMGetStringValue(ptr,arg,section,logname,"");
if(strcasecmp(tag,"yes")==0) {
return 1;
}
if(strcasecmp(tag,"on")==0) {
return 1;
}
if(strcasecmp(tag,"true")==0) {
return 1;
}
if(strcasecmp(tag,"no")==0) {
return 0;
}
if(strcasecmp(tag,"off")==0) {
return 0;
}
if(strcasecmp(tag,"false")==0) {
return 0;
}
if(strcasecmp(tag,"onair")==0) {
return 2;
}
return 0;
}
void rlm_inno713_RLMStart(void *ptr,const char *arg)
{
char address[17];
char section[256];
char errtext[256];
char device[256];
int speed;
int parity;
int wsize;
int i=1;
rlm_inno713_devs=0;
rlm_inno713_addresses=NULL;
rlm_inno713_ports=NULL;
rlm_inno713_handles=NULL;
rlm_inno713_dynamicpss=NULL;
rlm_inno713_masters=NULL;
rlm_inno713_aux1s=NULL;
rlm_inno713_aux2s=NULL;
sprintf(section,"Rds%d",i++);
strncpy(address,RLMGetStringValue(ptr,arg,section,"IpAddress",""),15);
strncpy(device,RLMGetStringValue(ptr,arg,section,"Device",""),256);
if((strlen(address)==0)&&(strlen(device)==0)) {
RLMLog(ptr,LOG_WARNING,"rlm_inno713: no RDS connections specified");
return;
}
while((strlen(address)>0)||(strlen(device)>0)) {
rlm_inno713_addresses=
realloc(rlm_inno713_addresses,
(rlm_inno713_devs+1)*(rlm_inno713_devs+1)*16);
strcpy(rlm_inno713_addresses+16*rlm_inno713_devs,address);
rlm_inno713_ports=realloc(rlm_inno713_ports,
(rlm_inno713_devs+1)*sizeof(uint16_t));
rlm_inno713_ports[rlm_inno713_devs]=
RLMGetIntegerValue(ptr,arg,section,"UdpPort",0);
speed=RLMGetIntegerValue(ptr,arg,section,"Speed",9600);
parity=RLMGetIntegerValue(ptr,arg,section,"Parity",0);
wsize=RLMGetIntegerValue(ptr,arg,section,"WordSize",8);
rlm_inno713_handles=realloc(rlm_inno713_handles,
(rlm_inno713_devs+1)*sizeof(int));
rlm_inno713_handles[rlm_inno713_devs]=
RLMOpenSerial(ptr,device,speed,parity,wsize);
rlm_inno713_dynamicpss=realloc(rlm_inno713_dynamicpss,(rlm_inno713_devs+1)*256);
strncpy(rlm_inno713_dynamicpss+256*rlm_inno713_devs,
RLMGetStringValue(ptr,arg,section,"DynamicPsString",""),256);
rlm_inno713_pss=realloc(rlm_inno713_pss,(rlm_inno713_devs+1)*256);
strncpy(rlm_inno713_pss+256*rlm_inno713_devs,
RLMGetStringValue(ptr,arg,section,"PsString",""),256);
rlm_inno713_radiotexts=realloc(rlm_inno713_radiotexts,
(rlm_inno713_devs+1)*256);
strncpy(rlm_inno713_radiotexts+256*rlm_inno713_devs,
RLMGetStringValue(ptr,arg,section,"RadiotextString",""),256);
rlm_inno713_masters=realloc(rlm_inno713_masters,
(rlm_inno713_devs+1)*sizeof(int));
rlm_inno713_masters[rlm_inno713_devs]=
rlm_inno713_GetLogStatus(ptr,arg,section,"MasterLog");
rlm_inno713_aux1s=realloc(rlm_inno713_aux1s,
(rlm_inno713_devs+1)*sizeof(int));
rlm_inno713_aux1s[rlm_inno713_devs]=
rlm_inno713_GetLogStatus(ptr,arg,section,"Aux1Log");
rlm_inno713_aux2s=realloc(rlm_inno713_aux2s,
(rlm_inno713_devs+1)*sizeof(int));
rlm_inno713_aux2s[rlm_inno713_devs]=
rlm_inno713_GetLogStatus(ptr,arg,section,"Aux2Log");
sprintf(errtext,"rlm_inno713: configured destination \"%s:%d\"",address,
rlm_inno713_ports[rlm_inno713_devs]);
RLMLog(ptr,LOG_INFO,errtext);
if(strlen(device)>0) {
if(rlm_inno713_handles[rlm_inno713_devs]<0) {
sprintf(errtext,"rlm_inno713: unable to open serial device \"%s\"",device);
}
else {
sprintf(errtext,"rlm_inno713: configured serial device \"%s\"",device);
}
RLMLog(ptr,LOG_INFO,errtext);
}
rlm_inno713_devs++;
sprintf(section,"Rds%d",i++);
strncpy(address,RLMGetStringValue(ptr,arg,section,"IpAddress",""),15);
strncpy(device,RLMGetStringValue(ptr,arg,section,"Device",""),256);
}
}
void rlm_inno713_RLMFree(void *ptr)
{
int i;
free(rlm_inno713_addresses);
free(rlm_inno713_ports);
for(i=0;i<rlm_inno713_devs;i++) {
if(rlm_inno713_handles[i]>=0) {
RLMCloseSerial(ptr,rlm_inno713_handles[i]);
}
}
free(rlm_inno713_handles);
free(rlm_inno713_dynamicpss);
free(rlm_inno713_pss);
free(rlm_inno713_radiotexts);
free(rlm_inno713_masters);
free(rlm_inno713_aux1s);
free(rlm_inno713_aux2s);
}
void rlm_inno713_RLMPadDataSent(void *ptr,const struct rlm_svc *svc,
const struct rlm_log *log,
const struct rlm_pad *now,
const struct rlm_pad *next)
{
int i;
int flag=0;
char msg[1500];
for(i=0;i<rlm_inno713_devs;i++) {
switch(log->log_mach) {
case 0:
flag=rlm_inno713_masters[i];
break;
case 1:
flag=rlm_inno713_aux1s[i];
break;
case 2:
flag=rlm_inno713_aux2s[i];
break;
}
if((flag==1)||((flag==2)&&(log->log_onair!=0))) {
rlm_inno713_SendString(ptr,now,next,"DPS",rlm_inno713_dynamicpss+256*i,
rlm_inno713_addresses+i*16,rlm_inno713_ports[i],
rlm_inno713_handles[i]);
rlm_inno713_SendString(ptr,now,next,"PS",rlm_inno713_pss+256*i,
rlm_inno713_addresses+i*16,rlm_inno713_ports[i],
rlm_inno713_handles[i]);
rlm_inno713_SendString(ptr,now,next,"TEXT",rlm_inno713_radiotexts+256*i,
rlm_inno713_addresses+i*16,rlm_inno713_ports[i],
rlm_inno713_handles[i]);
const char *str=RLMResolveNowNext(ptr,now,next,rlm_inno713_pss+256*i);
snprintf(msg,1500,"rlm_inno713: sending pad update: \"%s\"",str);
RLMLog(ptr,LOG_INFO,msg);
}
}
}

189
rlm/rlm_liqcomp.c Normal file
View File

@@ -0,0 +1,189 @@
/* rlm_liqcomp.c
*
* (C) Copyright 2009 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.
*
* This is a Rivendell Loadable Module. It sends Now&Next PAD data to a
* Liquid Compass Internet streaming encoder. Options are specified in the
* configuration file pointed to by the plugin argument.
*
* To compile this module, just do:
*
* gcc -shared -o rlm_liqcomp.rlm rlm_liqcomp.c
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <rlm/rlm.h>
int rlm_liqcomp_devs;
char *rlm_liqcomp_addresses;
uint16_t *rlm_liqcomp_ports;
char *rlm_liqcomp_titles;
char *rlm_liqcomp_artists;
char *rlm_liqcomp_albums;
char *rlm_liqcomp_labels;
int *rlm_liqcomp_masters;
int *rlm_liqcomp_aux1s;
int *rlm_liqcomp_aux2s;
int rlm_liqcomp_GetLogStatus(void *ptr,const char *arg,const char *section,
const char *logname)
{
const char *tag=RLMGetStringValue(ptr,arg,section,logname,"");
if(strcasecmp(tag,"yes")==0) {
return 1;
}
if(strcasecmp(tag,"on")==0) {
return 1;
}
if(strcasecmp(tag,"true")==0) {
return 1;
}
if(strcasecmp(tag,"no")==0) {
return 0;
}
if(strcasecmp(tag,"off")==0) {
return 0;
}
if(strcasecmp(tag,"false")==0) {
return 0;
}
if(strcasecmp(tag,"onair")==0) {
return 2;
}
return 0;
}
void rlm_liqcomp_RLMStart(void *ptr,const char *arg)
{
char address[17];
char section[256];
char errtext[256];
int i=1;
rlm_liqcomp_devs=0;
rlm_liqcomp_addresses=NULL;
rlm_liqcomp_ports=NULL;
rlm_liqcomp_masters=NULL;
rlm_liqcomp_aux1s=NULL;
rlm_liqcomp_aux2s=NULL;
sprintf(section,"System%d",i++);
strncpy(address,RLMGetStringValue(ptr,arg,section,"IpAddress",""),15);
if(strlen(address)==0) {
RLMLog(ptr,LOG_WARNING,"rlm_liqcomp: no encoder destinations specified");
return;
}
while(strlen(address)>0) {
rlm_liqcomp_addresses=
realloc(rlm_liqcomp_addresses,(rlm_liqcomp_devs+1)*(rlm_liqcomp_devs+1)*16);
strcpy(rlm_liqcomp_addresses+16*rlm_liqcomp_devs,address);
rlm_liqcomp_ports=realloc(rlm_liqcomp_ports,(rlm_liqcomp_devs+1)*sizeof(uint16_t));
rlm_liqcomp_ports[rlm_liqcomp_devs]=
RLMGetIntegerValue(ptr,arg,section,"UdpPort",0);
rlm_liqcomp_titles=realloc(rlm_liqcomp_titles,(rlm_liqcomp_devs+1)*256);
strncpy(rlm_liqcomp_titles+256*rlm_liqcomp_devs,
RLMGetStringValue(ptr,arg,section,"Title",""),256);
rlm_liqcomp_artists=realloc(rlm_liqcomp_artists,(rlm_liqcomp_devs+1)*256);
strncpy(rlm_liqcomp_artists+256*rlm_liqcomp_devs,
RLMGetStringValue(ptr,arg,section,"Artist",""),256);
rlm_liqcomp_albums=realloc(rlm_liqcomp_albums,(rlm_liqcomp_devs+1)*256);
strncpy(rlm_liqcomp_albums+256*rlm_liqcomp_devs,
RLMGetStringValue(ptr,arg,section,"Album",""),256);
rlm_liqcomp_labels=realloc(rlm_liqcomp_labels,(rlm_liqcomp_devs+1)*256);
strncpy(rlm_liqcomp_labels+256*rlm_liqcomp_devs,
RLMGetStringValue(ptr,arg,section,"Label",""),256);
rlm_liqcomp_masters=realloc(rlm_liqcomp_masters,
(rlm_liqcomp_devs+1)*sizeof(int));
rlm_liqcomp_masters[rlm_liqcomp_devs]=
rlm_liqcomp_GetLogStatus(ptr,arg,section,"MasterLog");
rlm_liqcomp_aux1s=realloc(rlm_liqcomp_aux1s,
(rlm_liqcomp_devs+1)*sizeof(int));
rlm_liqcomp_aux1s[rlm_liqcomp_devs]=
rlm_liqcomp_GetLogStatus(ptr,arg,section,"Aux1Log");
rlm_liqcomp_aux2s=realloc(rlm_liqcomp_aux2s,
(rlm_liqcomp_devs+1)*sizeof(int));
rlm_liqcomp_aux2s[rlm_liqcomp_devs]=
rlm_liqcomp_GetLogStatus(ptr,arg,section,"Aux2Log");
sprintf(errtext,"rlm_liqcomp: configured destination \"%s:%d\"",address,
rlm_liqcomp_ports[rlm_liqcomp_devs]);
rlm_liqcomp_devs++;
RLMLog(ptr,LOG_INFO,errtext);
sprintf(section,"System%d",i++);
strncpy(address,RLMGetStringValue(ptr,arg,section,"IpAddress",""),15);
}
}
void rlm_liqcomp_RLMFree(void *ptr)
{
free(rlm_liqcomp_addresses);
free(rlm_liqcomp_ports);
free(rlm_liqcomp_titles);
free(rlm_liqcomp_artists);
free(rlm_liqcomp_albums);
free(rlm_liqcomp_labels);
free(rlm_liqcomp_masters);
free(rlm_liqcomp_aux1s);
free(rlm_liqcomp_aux2s);
}
void rlm_liqcomp_RLMPadDataSent(void *ptr,const struct rlm_svc *svc,
const struct rlm_log *log,
const struct rlm_pad *now,
const struct rlm_pad *next)
{
int i;
int flag=0;
char fmt[1500];
char msg[1500];
for(i=0;i<rlm_liqcomp_devs;i++) {
switch(log->log_mach) {
case 0:
flag=rlm_liqcomp_masters[i];
break;
case 1:
flag=rlm_liqcomp_aux1s[i];
break;
case 2:
flag=rlm_liqcomp_aux2s[i];
break;
}
if((flag==1)||((flag==2)&&(log->log_onair!=0))) {
snprintf(fmt,1500,"|%s|%s|%06u|%u|%s|%s|%s|\n",
rlm_liqcomp_titles+256*i,
rlm_liqcomp_artists+256*i,
now->rlm_cartnum,
now->rlm_len,
now->rlm_group,
rlm_liqcomp_albums+256*i,
rlm_liqcomp_labels+256*i);
const char *str=RLMResolveNowNext(ptr,now,next,fmt);
RLMSendUdp(ptr,rlm_liqcomp_addresses+i*16,rlm_liqcomp_ports[i],str,
strlen(str));
snprintf(msg,1500,"rlm_liqcomp: sending pad update: \"%s\"",
(const char *)str);
RLMLog(ptr,LOG_INFO,msg);
}
}
}

175
rlm/rlm_padpoint.c Normal file
View File

@@ -0,0 +1,175 @@
/* rlm_padpoint.c
*
* (C) Copyright 2012 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.
*
* This is a Rivendell Loadable Module. It sends Now&Next PAD data via
* UDP packets to one or more PadPoint PAD processors as specified in the
* configuration file pointed to by the plugin argument.
*
* To compile this module, just do:
*
* gcc -shared -o rlm_padpoint.rlm rlm_padpoint.c
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <rlm/rlm.h>
int rlm_padpoint_devs;
char *rlm_padpoint_addresses;
uint16_t *rlm_padpoint_ports;
int *rlm_padpoint_masters;
int *rlm_padpoint_aux1s;
int *rlm_padpoint_aux2s;
int rlm_padpoint_GetLogStatus(void *ptr,const char *arg,const char *section,
const char *logname)
{
const char *tag=RLMGetStringValue(ptr,arg,section,logname,"");
if(strcasecmp(tag,"yes")==0) {
return 1;
}
if(strcasecmp(tag,"on")==0) {
return 1;
}
if(strcasecmp(tag,"true")==0) {
return 1;
}
if(strcasecmp(tag,"no")==0) {
return 0;
}
if(strcasecmp(tag,"off")==0) {
return 0;
}
if(strcasecmp(tag,"false")==0) {
return 0;
}
if(strcasecmp(tag,"onair")==0) {
return 2;
}
return 0;
}
void rlm_padpoint_RLMStart(void *ptr,const char *arg)
{
char address[17];
char section[256];
char errtext[256];
int i=1;
rlm_padpoint_devs=0;
rlm_padpoint_addresses=NULL;
rlm_padpoint_ports=NULL;
rlm_padpoint_masters=NULL;
rlm_padpoint_aux1s=NULL;
rlm_padpoint_aux2s=NULL;
sprintf(section,"PadPoint%d",i++);
strncpy(address,RLMGetStringValue(ptr,arg,section,"IpAddress",""),15);
if(strlen(address)==0) {
RLMLog(ptr,LOG_WARNING,"rlm_padpoint: no padpoint destinations specified");
return;
}
while(strlen(address)>0) {
rlm_padpoint_addresses=
realloc(rlm_padpoint_addresses,(rlm_padpoint_devs+1)*(rlm_padpoint_devs+1)*16);
strcpy(rlm_padpoint_addresses+16*rlm_padpoint_devs,address);
rlm_padpoint_ports=realloc(rlm_padpoint_ports,(rlm_padpoint_devs+1)*sizeof(uint16_t));
rlm_padpoint_ports[rlm_padpoint_devs]=
RLMGetIntegerValue(ptr,arg,section,"UdpPort",0);
rlm_padpoint_masters=realloc(rlm_padpoint_masters,
(rlm_padpoint_devs+1)*sizeof(int));
rlm_padpoint_masters[rlm_padpoint_devs]=
rlm_padpoint_GetLogStatus(ptr,arg,section,"MasterLog");
rlm_padpoint_aux1s=realloc(rlm_padpoint_aux1s,
(rlm_padpoint_devs+1)*sizeof(int));
rlm_padpoint_aux1s[rlm_padpoint_devs]=
rlm_padpoint_GetLogStatus(ptr,arg,section,"Aux1Log");
rlm_padpoint_aux2s=realloc(rlm_padpoint_aux2s,
(rlm_padpoint_devs+1)*sizeof(int));
rlm_padpoint_aux2s[rlm_padpoint_devs]=
rlm_padpoint_GetLogStatus(ptr,arg,section,"Aux2Log");
sprintf(errtext,"rlm_padpoint: configured destination \"%s:%d\"",address,
rlm_padpoint_ports[rlm_padpoint_devs]);
rlm_padpoint_devs++;
RLMLog(ptr,LOG_INFO,errtext);
sprintf(section,"PadPoint%d",i++);
strncpy(address,RLMGetStringValue(ptr,arg,section,"IpAddress",""),15);
}
}
void rlm_padpoint_RLMFree(void *ptr)
{
free(rlm_padpoint_addresses);
free(rlm_padpoint_ports);
free(rlm_padpoint_masters);
free(rlm_padpoint_aux1s);
free(rlm_padpoint_aux2s);
}
void rlm_padpoint_RLMPadDataSent(void *ptr,const struct rlm_svc *svc,
const struct rlm_log *log,
const struct rlm_pad *now,
const struct rlm_pad *next)
{
int i;
int flag=0;
char str[1501];
char msg[2048];
for(i=0;i<rlm_padpoint_devs;i++) {
switch(log->log_mach) {
case 0:
flag=rlm_padpoint_masters[i];
break;
case 1:
flag=rlm_padpoint_aux1s[i];
break;
case 2:
flag=rlm_padpoint_aux2s[i];
break;
}
if((flag==1)||((flag==2)&&(log->log_onair!=0))) {
snprintf(str,1501,"%06u~%u~%s~%s~%s~%s~%s~%s~%s~%s~%s~%s~%s~%s~%s",
now->rlm_cartnum,
now->rlm_len,
now->rlm_year,
now->rlm_group,
now->rlm_title,
now->rlm_artist,
now->rlm_album,
now->rlm_label,
now->rlm_client,
now->rlm_agency,
now->rlm_comp,
now->rlm_pub,
now->rlm_userdef,
now->rlm_isrc,
now->rlm_isci);
RLMSendUdp(ptr,rlm_padpoint_addresses+i*16,rlm_padpoint_ports[i],
str,strlen(str));
snprintf(msg,1500,"rlm_padpoint: sending pad update: \"%s\"",str);
RLMLog(ptr,LOG_INFO,msg);
}
}
}

219
rlm/rlm_serial.c Normal file
View File

@@ -0,0 +1,219 @@
/* rlm_serial.c
*
* (C) Copyright 2008 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.
*
* This is a Rivendell Loadable Module. It sends Now&Next PAD data
* to the tty device specified in the configuration file pointed to by the
* plugin argument.
*
* To compile this module, just do:
*
* gcc -shared -o rlm_serial.rlm rlm_serial.c
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <rlm/rlm.h>
int rlm_serial_devs;
int *rlm_serial_handles;
char *rlm_serial_formats;
int *rlm_serial_encodings;
int *rlm_serial_null_updates;
int *rlm_serial_masters;
int *rlm_serial_aux1s;
int *rlm_serial_aux2s;
int rlm_serial_GetLogStatus(void *ptr,const char *arg,const char *section,
const char *logname)
{
const char *tag=RLMGetStringValue(ptr,arg,section,logname,"");
if(strcasecmp(tag,"yes")==0) {
return 1;
}
if(strcasecmp(tag,"on")==0) {
return 1;
}
if(strcasecmp(tag,"true")==0) {
return 1;
}
if(strcasecmp(tag,"no")==0) {
return 0;
}
if(strcasecmp(tag,"off")==0) {
return 0;
}
if(strcasecmp(tag,"false")==0) {
return 0;
}
if(strcasecmp(tag,"onair")==0) {
return 2;
}
return 0;
}
void rlm_serial_RLMStart(void *ptr,const char *arg)
{
int handle;
char device[256];
int speed;
int parity;
int wsize;
char section[256];
char errtext[256];
int i=1;
rlm_serial_devs=0;
rlm_serial_handles=NULL;
rlm_serial_formats=NULL;
rlm_serial_encodings=NULL;
rlm_serial_null_updates=NULL;
rlm_serial_masters=NULL;
rlm_serial_aux1s=NULL;
rlm_serial_aux2s=NULL;
sprintf(section,"Serial%d",i++);
strncpy(device,RLMGetStringValue(ptr,arg,section,"Device",""),256);
if(strlen(device)==0) {
RLMLog(ptr,LOG_WARNING,"rlm_serial: no serial devices specified");
return;
}
while(strlen(device)>0) {
speed=RLMGetIntegerValue(ptr,arg,section,"Speed",9600);
parity=RLMGetIntegerValue(ptr,arg,section,"Parity",0);
wsize=RLMGetIntegerValue(ptr,arg,section,"WordSize",8);
if((handle=RLMOpenSerial(ptr,device,speed,parity,wsize))>=0) {
rlm_serial_handles=realloc(rlm_serial_handles,
(rlm_serial_devs+1)*sizeof(int));
rlm_serial_handles[rlm_serial_devs]=handle;
rlm_serial_formats=realloc(rlm_serial_formats,(rlm_serial_devs+1)*256);
strncpy(rlm_serial_formats+256*rlm_serial_devs,
RLMGetStringValue(ptr,arg,section,"FormatString",""),256);
rlm_serial_masters=realloc(rlm_serial_masters,
(rlm_serial_devs+1)*sizeof(int));
rlm_serial_masters[rlm_serial_devs]=
rlm_serial_GetLogStatus(ptr,arg,section,"MasterLog");
rlm_serial_encodings=realloc(rlm_serial_encodings,
(rlm_serial_devs+1)*sizeof(int));
rlm_serial_encodings[rlm_serial_devs]=
RLMGetIntegerValue(ptr,arg,section,"Encoding",RLM_ENCODE_NONE);
rlm_serial_null_updates=realloc(rlm_serial_null_updates,
(rlm_serial_devs+1)*sizeof(int));
rlm_serial_null_updates[rlm_serial_devs]=
RLMGetIntegerValue(ptr,arg,section,"ProcessNullUpdates",0);
rlm_serial_aux1s=realloc(rlm_serial_aux1s,
(rlm_serial_devs+1)*sizeof(int));
rlm_serial_aux1s[rlm_serial_devs]=
rlm_serial_GetLogStatus(ptr,arg,section,"Aux1Log");
rlm_serial_aux2s=realloc(rlm_serial_aux2s,
(rlm_serial_devs+1)*sizeof(int));
rlm_serial_aux2s[rlm_serial_devs]=
rlm_serial_GetLogStatus(ptr,arg,section,"Aux2Log");
rlm_serial_devs++;
sprintf(errtext,"rlm_serial: opened device \"%s\"",device);
RLMLog(ptr,LOG_INFO,errtext);
}
else {
sprintf(errtext,"unable to open tty \"%s\"",device);
RLMLog(ptr,LOG_WARNING,errtext);
}
sprintf(section,"Serial%d",i++);
strncpy(device,RLMGetStringValue(ptr,arg,section,"Device",""),256);
}
}
void rlm_serial_RLMFree(void *ptr)
{
int i;
for(i=0;i<rlm_serial_devs;i++) {
RLMCloseSerial(ptr,rlm_serial_handles[i]);
}
free(rlm_serial_handles);
free(rlm_serial_formats);
free(rlm_serial_encodings);
free(rlm_serial_null_updates);
free(rlm_serial_masters);
free(rlm_serial_aux1s);
free(rlm_serial_aux2s);
}
void rlm_serial_RLMPadDataSent(void *ptr,const struct rlm_svc *svc,
const struct rlm_log *log,
const struct rlm_pad *now,
const struct rlm_pad *next)
{
int i;
int flag=0;
char msg[1500];
for(i=0;i<rlm_serial_devs;i++) {
switch(rlm_serial_null_updates[i]) {
case 0: /* Process all updates */
break;
case 1: /* Process only non-null NOW updates */
if(now->rlm_cartnum==0) {
return;
}
break;
case 2: /* Process only non-null NEXT updates */
if(next->rlm_cartnum==0) {
return;
}
break;
case 3: /* Process only non-null NOW and NEXT updates */
if((now->rlm_cartnum==0)||(next->rlm_cartnum==0)) {
return;
}
break;
}
switch(log->log_mach) {
case 0:
flag=rlm_serial_masters[i];
break;
case 1:
flag=rlm_serial_aux1s[i];
break;
case 2:
flag=rlm_serial_aux2s[i];
break;
}
if((flag==1)||((flag==2)&&(log->log_onair!=0))) {
const char *str=
RLMResolveNowNextEncoded(ptr,now,next,rlm_serial_formats+256*i,
rlm_serial_encodings[i]);
RLMSendSerial(ptr,rlm_serial_handles[i],str,strlen(str));
snprintf(msg,1500,"rlm_serial: sending pad update: \"%s\"",
(const char *)str);
RLMLog(ptr,LOG_INFO,msg);
}
}
}

280
rlm/rlm_shoutcast1.c Normal file
View File

@@ -0,0 +1,280 @@
/* rlm_shoutcast1.c
*
* (C) Copyright 2011 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.
*
* This is a Rivendell Loadable Module. It uses Now&Next PAD data
* to update the metadata on an Icecast2 mountpoint specified in the
* configuration file pointed to by the plugin argument.
*
* This module requires the curl(1) network transfer tool, included with
* most Linux distros. It is also available at http://curl.haxx.se/.
*
* To compile this module, just do:
*
* gcc -shared -o rlm_shoutcast1.rlm rlm_shoutcast1.c
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <sys/types.h>
#include <unistd.h>
#include <rlm/rlm.h>
int rlm_shoutcast1_devs;
char *rlm_shoutcast1_passwords;
char *rlm_shoutcast1_hostnames;
int *rlm_shoutcast1_tcpports;
char *rlm_shoutcast1_formats;
int *rlm_shoutcast1_masters;
int *rlm_shoutcast1_aux1s;
int *rlm_shoutcast1_aux2s;
int rlm_shoutcast1_BufferDiff(char *sString,int dOrigin,int dDiff,int dMaxSize)
{
int dOldSize,dNewSize;
int i;
/*
* Will it fit?
*/
dOldSize=strlen(sString);
if((dOldSize+dDiff)>=dMaxSize) {
return -1;
}
dNewSize=dOldSize+dDiff;
/*
* Adding characters
*/
if(dDiff>0) {
for(i=dOldSize;i>dOrigin;i--) {
sString[i+dDiff]=sString[i];
}
return dNewSize;
}
/*
* No Change
*/
if(dDiff==0) {
return dNewSize;
}
/*
* Deleting Characters
*/
if(dDiff<0) {
for(i=dOrigin;i<dOldSize;i++) {
sString[i]=sString[i-dDiff];
}
return dNewSize;
}
return -1;
}
int rlm_shoutcast1_EncodeString(char *sString,int dMaxSize)
{
int i; /* General Purpose Counter */
char sAccum[4]; /* General String Buffer */
i=0;
while(sString[i]!=0) {
if(((sString[i]!='*') && (sString[i]!='-') &&
(sString[i]!='_') && (sString[i]!='.')) &&
((sString[i]<'0') ||
((sString[i]>'9') && (sString[i]<'A')) ||
((sString[i]>'Z') && (sString[i]<'a')) ||
(sString[i]>'z'))) {
if(rlm_shoutcast1_BufferDiff(sString,i,2,dMaxSize)<0) {
return -1;
}
sprintf(sAccum,"%%%2x",sString[i]);
sString[i++]=sAccum[0];
sString[i++]=sAccum[1];
sString[i]=sAccum[2];
}
if(sString[i]==' ') {
sString[i]='+';
}
i++;
if(i>=dMaxSize) {
return -1;
}
}
return strlen(sString);
}
int rlm_shoutcast1_GetLogStatus(void *ptr,const char *arg,const char *section,
const char *logname)
{
const char *tag=RLMGetStringValue(ptr,arg,section,logname,"");
if(strcasecmp(tag,"yes")==0) {
return 1;
}
if(strcasecmp(tag,"on")==0) {
return 1;
}
if(strcasecmp(tag,"true")==0) {
return 1;
}
if(strcasecmp(tag,"no")==0) {
return 0;
}
if(strcasecmp(tag,"off")==0) {
return 0;
}
if(strcasecmp(tag,"false")==0) {
return 0;
}
if(strcasecmp(tag,"onair")==0) {
return 2;
}
return 0;
}
void rlm_shoutcast1_RLMStart(void *ptr,const char *arg)
{
char password[256];
char section[256];
char errtext[256];
int i=1;
rlm_shoutcast1_devs=0;
rlm_shoutcast1_passwords=NULL;
rlm_shoutcast1_formats=NULL;
rlm_shoutcast1_masters=NULL;
rlm_shoutcast1_aux1s=NULL;
rlm_shoutcast1_aux2s=NULL;
sprintf(section,"Shoutcast%d",i++);
strncpy(password,RLMGetStringValue(ptr,arg,section,"Password",""),255);
password[255]=0;
if(strlen(password)==0) {
RLMLog(ptr,LOG_WARNING,"rlm_shoutcast1: no shoutcast servers specified");
return;
}
while(strlen(password)>0) {
rlm_shoutcast1_passwords=realloc(rlm_shoutcast1_passwords,
(rlm_shoutcast1_devs+1)*(rlm_shoutcast1_devs+1)*256);
strcpy(rlm_shoutcast1_passwords+256*rlm_shoutcast1_devs,password);
rlm_shoutcast1_hostnames=realloc(rlm_shoutcast1_hostnames,
(rlm_shoutcast1_devs+1)*(rlm_shoutcast1_devs+1)*256);
strcpy(rlm_shoutcast1_hostnames+256*rlm_shoutcast1_devs,
RLMGetStringValue(ptr,arg,section,"Hostname",""));
rlm_shoutcast1_tcpports=realloc(rlm_shoutcast1_tcpports,
(rlm_shoutcast1_devs+1)*sizeof(int));
rlm_shoutcast1_tcpports[rlm_shoutcast1_devs]=
RLMGetIntegerValue(ptr,arg,section,"Tcpport",0);
rlm_shoutcast1_formats=realloc(rlm_shoutcast1_formats,(rlm_shoutcast1_devs+1)*256);
strncpy(rlm_shoutcast1_formats+256*rlm_shoutcast1_devs,
RLMGetStringValue(ptr,arg,section,"FormatString",""),256);
rlm_shoutcast1_masters=realloc(rlm_shoutcast1_masters,
(rlm_shoutcast1_devs+1)*sizeof(int));
rlm_shoutcast1_masters[rlm_shoutcast1_devs]=
rlm_shoutcast1_GetLogStatus(ptr,arg,section,"MasterLog");
rlm_shoutcast1_aux1s=realloc(rlm_shoutcast1_aux1s,
(rlm_shoutcast1_devs+1)*sizeof(int));
rlm_shoutcast1_aux1s[rlm_shoutcast1_devs]=
rlm_shoutcast1_GetLogStatus(ptr,arg,section,"Aux1Log");
rlm_shoutcast1_aux2s=realloc(rlm_shoutcast1_aux2s,
(rlm_shoutcast1_devs+1)*sizeof(int));
rlm_shoutcast1_aux2s[rlm_shoutcast1_devs]=
rlm_shoutcast1_GetLogStatus(ptr,arg,section,"Aux2Log");
sprintf(errtext,"rlm_shoutcast1: configured server \"%s:%d\"",rlm_shoutcast1_hostnames+256*rlm_shoutcast1_devs,rlm_shoutcast1_tcpports[rlm_shoutcast1_devs]);
rlm_shoutcast1_devs++;
RLMLog(ptr,LOG_INFO,errtext);
sprintf(section,"Shoutcast%d",i++);
strncpy(password,RLMGetStringValue(ptr,arg,section,"Password",""),255);
password[255]=0;
}
}
void rlm_shoutcast1_RLMFree(void *ptr)
{
free(rlm_shoutcast1_passwords);
free(rlm_shoutcast1_hostnames);
free(rlm_shoutcast1_tcpports);
free(rlm_shoutcast1_formats);
free(rlm_shoutcast1_masters);
free(rlm_shoutcast1_aux1s);
free(rlm_shoutcast1_aux2s);
}
void rlm_shoutcast1_RLMPadDataSent(void *ptr,const struct rlm_svc *svc,
const struct rlm_log *log,
const struct rlm_pad *now,
const struct rlm_pad *next)
{
int i;
int flag=0;
char str[1024];
char account[1024];
char url[1024];
char msg[1500];
char user_agent[255];
for(i=0;i<rlm_shoutcast1_devs;i++) {
switch(log->log_mach) {
case 0:
flag=rlm_shoutcast1_masters[i];
break;
case 1:
flag=rlm_shoutcast1_aux1s[i];
break;
case 2:
flag=rlm_shoutcast1_aux2s[i];
break;
}
if((flag==1)||((flag==2)&&(log->log_onair!=0))) {
strncpy(str,RLMResolveNowNext(ptr,now,next,
rlm_shoutcast1_formats+256*i),256);
rlm_shoutcast1_EncodeString(str,1023);
snprintf(account,1024,":%s",rlm_shoutcast1_passwords+256*i);
snprintf(url,1024,"http://%s:%d/admin.cgi?pass=%s&mode=updinfo&song=%s",
rlm_shoutcast1_hostnames+256*i,
rlm_shoutcast1_tcpports[i],
rlm_shoutcast1_passwords+256*i,
str);
/*
* D.N.A.S v1.9.8 refuses to process updates with the default CURL
* user-agent value, hence we lie to it.
*/
strncpy(user_agent,"User-agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.2) Gecko/20070219 Firefox/2.0.0.2",255);
if(strlen(now->rlm_title)!=0) {
if(fork()==0) {
execlp("curl","curl","-o","/dev/null","-s","--header",user_agent,
url,(char *)NULL);
RLMLog(ptr,LOG_WARNING,"rlm_shoutcast1: unable to execute curl(1)");
exit(0);
}
}
snprintf(msg,1500,"rlm_shoutcast1: sending pad update: \"%s\"",
(const char *)str);
RLMLog(ptr,LOG_INFO,msg);
}
}
}

386
rlm/rlm_spinitron_plus.c Normal file
View File

@@ -0,0 +1,386 @@
/* rlm_spinitron_plus.c
*
* (C) Copyright 2013 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.
*
* This is a Rivendell Loadable Module. It sends Now&Next PAD data
* to the Spinitron account(s) specified in the configuration file pointed
* to by the plugin argument. For information about Spinitron, see
* http://www.spinitron.com/.
*
* Inspired by the original spinitron RLM by Eric Berg, Benjamin Yu
* and Max Goldstein.
*
* This module requires the curl(1) network transfer tool, included with
* most Linux distros. It is also available at http://curl.haxx.se/.
*
* To compile this module, just do:
*
* gcc -shared -o rlm_spinitron_plus.rlm rlm_spinitron_plus.c
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <sys/types.h>
#include <unistd.h>
#include <rlm/rlm.h>
#define RLM_SPINITRON_PLUS_LOGGER_NAME "Rivendell"
int rlm_spinitron_plus_devs;
char *rlm_spinitron_plus_stations;
char *rlm_spinitron_plus_usernames;
char *rlm_spinitron_plus_passwords;
int *rlm_spinitron_plus_playlist_modes;
char *rlm_spinitron_plus_titles;
char *rlm_spinitron_plus_artists;
char *rlm_spinitron_plus_albums;
char *rlm_spinitron_plus_labels;
char *rlm_spinitron_plus_composers;
char *rlm_spinitron_plus_notes;
int *rlm_spinitron_plus_masters;
int *rlm_spinitron_plus_aux1s;
int *rlm_spinitron_plus_aux2s;
int rlm_spinitron_plus_BufferDiff(char *sString,int dOrigin,int dDiff,int dMaxSize)
{
int dOldSize,dNewSize;
int i;
/*
* Will it fit?
*/
dOldSize=strlen(sString);
if((dOldSize+dDiff)>=dMaxSize) {
return -1;
}
dNewSize=dOldSize+dDiff;
/*
* Adding characters
*/
if(dDiff>0) {
for(i=dOldSize;i>dOrigin;i--) {
sString[i+dDiff]=sString[i];
}
return dNewSize;
}
/*
* No Change
*/
if(dDiff==0) {
return dNewSize;
}
/*
* Deleting Characters
*/
if(dDiff<0) {
for(i=dOrigin;i<dOldSize;i++) {
sString[i]=sString[i-dDiff];
}
return dNewSize;
}
return -1;
}
int rlm_spinitron_plus_EncodeString(char *sString,int dMaxSize)
{
int i; /* General Purpose Counter */
char sAccum[4]; /* General String Buffer */
i=0;
while(sString[i]!=0) {
if(((sString[i]!=' ') && (sString[i]!='*') && (sString[i]!='-') &&
(sString[i]!='_') && (sString[i]!='.')) &&
((sString[i]<'0') ||
((sString[i]>'9') && (sString[i]<'A')) ||
((sString[i]>'Z') && (sString[i]<'a')) ||
(sString[i]>'z'))) {
if(rlm_spinitron_plus_BufferDiff(sString,i,2,dMaxSize)<0) {
return -1;
}
sprintf(sAccum,"%%%2x",sString[i]);
sString[i++]=sAccum[0];
sString[i++]=sAccum[1];
sString[i]=sAccum[2];
}
if(sString[i]==' ') {
sString[i]='+';
}
i++;
}
return strlen(sString);
}
int rlm_spinitron_plus_GetLogStatus(void *ptr,const char *arg,
const char *section,const char *logname)
{
const char *tag=RLMGetStringValue(ptr,arg,section,logname,"");
if(strcasecmp(tag,"yes")==0) {
return 1;
}
if(strcasecmp(tag,"on")==0) {
return 1;
}
if(strcasecmp(tag,"true")==0) {
return 1;
}
if(strcasecmp(tag,"no")==0) {
return 0;
}
if(strcasecmp(tag,"off")==0) {
return 0;
}
if(strcasecmp(tag,"false")==0) {
return 0;
}
if(strcasecmp(tag,"onair")==0) {
return 2;
}
return 0;
}
void rlm_spinitron_plus_RLMStart(void *ptr,const char *arg)
{
char station[256];
char section[256];
char errtext[256];
char mode[256];
int pmode;
int i=1;
rlm_spinitron_plus_devs=0;
rlm_spinitron_plus_stations=NULL;
rlm_spinitron_plus_usernames=NULL;
rlm_spinitron_plus_passwords=NULL;
rlm_spinitron_plus_playlist_modes=NULL;
rlm_spinitron_plus_titles=NULL;
rlm_spinitron_plus_artists=NULL;
rlm_spinitron_plus_albums=NULL;
rlm_spinitron_plus_labels=NULL;
rlm_spinitron_plus_composers=NULL;
rlm_spinitron_plus_notes=NULL;
rlm_spinitron_plus_masters=NULL;
rlm_spinitron_plus_aux1s=NULL;
rlm_spinitron_plus_aux2s=NULL;
sprintf(section,"Spinitron%d",i++);
strncpy(station,RLMGetStringValue(ptr,arg,section,"Station",""),255);
station[255]=0;
if(strlen(station)==0) {
RLMLog(ptr,LOG_WARNING,"rlm_spinitron_plus: no spinitron accounts specified");
return;
}
while(strlen(station)>0) {
rlm_spinitron_plus_stations=realloc(rlm_spinitron_plus_stations,
(rlm_spinitron_plus_devs+1)*(rlm_spinitron_plus_devs+1)*256);
strcpy(rlm_spinitron_plus_stations+256*rlm_spinitron_plus_devs,station);
rlm_spinitron_plus_EncodeString(rlm_spinitron_plus_stations+256*rlm_spinitron_plus_devs,255);
rlm_spinitron_plus_usernames=realloc(rlm_spinitron_plus_usernames,
(rlm_spinitron_plus_devs+1)*(rlm_spinitron_plus_devs+1)*256);
strcpy(rlm_spinitron_plus_usernames+256*rlm_spinitron_plus_devs,
RLMGetStringValue(ptr,arg,section,"Username",""));
rlm_spinitron_plus_EncodeString(rlm_spinitron_plus_usernames+256*rlm_spinitron_plus_devs,255);
rlm_spinitron_plus_passwords=realloc(rlm_spinitron_plus_passwords,
(rlm_spinitron_plus_devs+1)*(rlm_spinitron_plus_devs+1)*256);
strcpy(rlm_spinitron_plus_passwords+256*rlm_spinitron_plus_devs,
RLMGetStringValue(ptr,arg,section,"Password",""));
rlm_spinitron_plus_EncodeString(rlm_spinitron_plus_passwords+256*rlm_spinitron_plus_devs,255);
pmode=3;
strcpy(mode,RLMGetStringValue(ptr,arg,section,"PlaylistMode",""));
if(strcasecmp(mode,"full")==0) {
pmode=0;
}
if(strcasecmp(mode,"assist")==0) {
pmode=2;
}
rlm_spinitron_plus_playlist_modes=
realloc(rlm_spinitron_plus_playlist_modes,
(rlm_spinitron_plus_devs+1)*sizeof(int));
rlm_spinitron_plus_playlist_modes[rlm_spinitron_plus_devs]=pmode;
rlm_spinitron_plus_titles=realloc(rlm_spinitron_plus_titles,(rlm_spinitron_plus_devs+1)*256);
strncpy(rlm_spinitron_plus_titles+256*rlm_spinitron_plus_devs,
RLMGetStringValue(ptr,arg,section,"Title",""),256);
rlm_spinitron_plus_artists=realloc(rlm_spinitron_plus_artists,(rlm_spinitron_plus_devs+1)*256);
strncpy(rlm_spinitron_plus_artists+256*rlm_spinitron_plus_devs,
RLMGetStringValue(ptr,arg,section,"Artist",""),256);
rlm_spinitron_plus_albums=realloc(rlm_spinitron_plus_albums,(rlm_spinitron_plus_devs+1)*256);
strncpy(rlm_spinitron_plus_albums+256*rlm_spinitron_plus_devs,
RLMGetStringValue(ptr,arg,section,"Album",""),256);
rlm_spinitron_plus_labels=realloc(rlm_spinitron_plus_labels,(rlm_spinitron_plus_devs+1)*256);
strncpy(rlm_spinitron_plus_labels+256*rlm_spinitron_plus_devs,
RLMGetStringValue(ptr,arg,section,"Label",""),256);
rlm_spinitron_plus_composers=realloc(rlm_spinitron_plus_composers,(rlm_spinitron_plus_devs+1)*256);
strncpy(rlm_spinitron_plus_composers+256*rlm_spinitron_plus_devs,
RLMGetStringValue(ptr,arg,section,"Composer",""),256);
rlm_spinitron_plus_notes=realloc(rlm_spinitron_plus_notes,(rlm_spinitron_plus_devs+1)*256);
strncpy(rlm_spinitron_plus_notes+256*rlm_spinitron_plus_devs,
RLMGetStringValue(ptr,arg,section,"Notes",""),256);
rlm_spinitron_plus_masters=realloc(rlm_spinitron_plus_masters,
(rlm_spinitron_plus_devs+1)*sizeof(int));
rlm_spinitron_plus_masters[rlm_spinitron_plus_devs]=
rlm_spinitron_plus_GetLogStatus(ptr,arg,section,"MasterLog");
rlm_spinitron_plus_aux1s=realloc(rlm_spinitron_plus_aux1s,
(rlm_spinitron_plus_devs+1)*sizeof(int));
rlm_spinitron_plus_aux1s[rlm_spinitron_plus_devs]=
rlm_spinitron_plus_GetLogStatus(ptr,arg,section,"Aux1Log");
rlm_spinitron_plus_aux2s=realloc(rlm_spinitron_plus_aux2s,
(rlm_spinitron_plus_devs+1)*sizeof(int));
rlm_spinitron_plus_aux2s[rlm_spinitron_plus_devs]=
rlm_spinitron_plus_GetLogStatus(ptr,arg,section,"Aux2Log");
sprintf(errtext,"rlm_spinitron_plus: configured account for station \"%s\"",
station);
rlm_spinitron_plus_devs++;
RLMLog(ptr,LOG_INFO,errtext);
sprintf(section,"Spinitron%d",i++);
strncpy(station,RLMGetStringValue(ptr,arg,section,"Station",""),255);
station[255]=0;
}
}
void rlm_spinitron_plus_RLMFree(void *ptr)
{
free(rlm_spinitron_plus_stations);
free(rlm_spinitron_plus_usernames);
free(rlm_spinitron_plus_passwords);
free(rlm_spinitron_plus_playlist_modes);
free(rlm_spinitron_plus_titles);
free(rlm_spinitron_plus_artists);
free(rlm_spinitron_plus_albums);
free(rlm_spinitron_plus_labels);
free(rlm_spinitron_plus_composers);
free(rlm_spinitron_plus_notes);
free(rlm_spinitron_plus_masters);
free(rlm_spinitron_plus_aux1s);
free(rlm_spinitron_plus_aux2s);
}
void rlm_spinitron_plus_RLMPadDataSent(void *ptr,const struct rlm_svc *svc,
const struct rlm_log *log,
const struct rlm_pad *now,
const struct rlm_pad *next)
{
int i;
int flag=0;
char title[1024];
char artist[1024];
char album[1024];
char label[1024];
char composer[1024];
char notes[1024];
char msg[8192];
char sysmsg[8192];
int pm;
for(i=0;i<rlm_spinitron_plus_devs;i++) {
switch(log->log_mach) {
case 0:
flag=rlm_spinitron_plus_masters[i];
break;
case 1:
flag=rlm_spinitron_plus_aux1s[i];
break;
case 2:
flag=rlm_spinitron_plus_aux2s[i];
break;
}
if((flag==1)||((flag==2)&&(log->log_onair!=0))) {
strncpy(title,RLMResolveNowNext(ptr,now,next,
rlm_spinitron_plus_titles+256*i),256);
rlm_spinitron_plus_EncodeString(title,1023);
strncpy(artist,RLMResolveNowNext(ptr,now,next,
rlm_spinitron_plus_artists+256*i),256);
rlm_spinitron_plus_EncodeString(artist,1023);
strncpy(album,RLMResolveNowNext(ptr,now,next,
rlm_spinitron_plus_albums+256*i),256);
rlm_spinitron_plus_EncodeString(album,1023);
strncpy(label,RLMResolveNowNext(ptr,now,next,
rlm_spinitron_plus_labels+256*i),256);
rlm_spinitron_plus_EncodeString(label,1023);
strncpy(composer,RLMResolveNowNext(ptr,now,next,
rlm_spinitron_plus_composers+256*i),256);
rlm_spinitron_plus_EncodeString(composer,1023);
strncpy(notes,RLMResolveNowNext(ptr,now,next,
rlm_spinitron_plus_notes+256*i),256);
rlm_spinitron_plus_EncodeString(notes,1023);
if(rlm_spinitron_plus_playlist_modes[i]==3) {
switch(log->log_mode) {
case RLM_LOGMODE_AUTOMATIC:
pm=0;
break;
case RLM_LOGMODE_LIVEASSIST:
case RLM_LOGMODE_MANUAL:
default:
pm=2;
break;
}
}
else {
pm=rlm_spinitron_plus_playlist_modes[i];
}
if(strlen(now->rlm_title)!=0) {
snprintf(msg,8192,
"https://spinitron.com/member/logthis.php?un=%s&pw=%s&sn=%s&aw=%s&dn=%s&ln=%s&sc=%s&se=%s&df=%s&st=%s&sd=%d&pm=%d",
rlm_spinitron_plus_usernames+256*i,
rlm_spinitron_plus_passwords+256*i,
title,
artist,
album,
label,
composer,
notes,
RLM_SPINITRON_PLUS_LOGGER_NAME,
rlm_spinitron_plus_stations+256*i,
now->rlm_len/1000,
pm);
if(fork()==0) {
execlp("curl","curl",msg,(char *)NULL);
RLMLog(ptr,LOG_WARNING,"rlm_spinitron_plus: unable to execute curl(1)");
exit(0);
}
snprintf(sysmsg,8192,"rlm_spinitron_plus: sending pad update: \"%s\"",
(const char *)msg);
RLMLog(ptr,LOG_DEBUG,sysmsg);
}
}
}
}

205
rlm/rlm_spottrap.c Normal file
View File

@@ -0,0 +1,205 @@
/* rlm_spottrap.c
*
* (C) Copyright 2012 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.
*
* This is a Rivendell Loadable Module. It processes Now&Next PAD data
* on the basis of Group and Length as specified in the configuration file
* pointed to by the plugin argument.
*
* To compile this module, just do:
*
* gcc -shared -o rlm_spottrap.rlm rlm_spottrap.c
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <rlm/rlm.h>
int rlm_spottrap_devs;
char *rlm_spottrap_groups;
char *rlm_spottrap_addresses;
int *rlm_spottrap_minimums;
int *rlm_spottrap_maximums;
uint16_t *rlm_spottrap_ports;
char *rlm_spottrap_formats;
char *rlm_spottrap_default_formats;
int *rlm_spottrap_masters;
int *rlm_spottrap_aux1s;
int *rlm_spottrap_aux2s;
int rlm_spottrap_GetLogStatus(void *ptr,const char *arg,const char *section,
const char *logname)
{
const char *tag=RLMGetStringValue(ptr,arg,section,logname,"");
if(strcasecmp(tag,"yes")==0) {
return 1;
}
if(strcasecmp(tag,"on")==0) {
return 1;
}
if(strcasecmp(tag,"true")==0) {
return 1;
}
if(strcasecmp(tag,"no")==0) {
return 0;
}
if(strcasecmp(tag,"off")==0) {
return 0;
}
if(strcasecmp(tag,"false")==0) {
return 0;
}
if(strcasecmp(tag,"onair")==0) {
return 2;
}
return 0;
}
void rlm_spottrap_RLMStart(void *ptr,const char *arg)
{
char address[17];
char section[256];
char errtext[256];
int i=1;
rlm_spottrap_devs=0;
rlm_spottrap_groups=NULL;
rlm_spottrap_addresses=NULL;
rlm_spottrap_minimums=NULL;
rlm_spottrap_maximums=NULL;
rlm_spottrap_ports=NULL;
rlm_spottrap_formats=NULL;
rlm_spottrap_default_formats=NULL;
rlm_spottrap_masters=NULL;
rlm_spottrap_aux1s=NULL;
rlm_spottrap_aux2s=NULL;
sprintf(section,"Rule%d",i++);
strncpy(address,RLMGetStringValue(ptr,arg,section,"IpAddress",""),15);
if(strlen(address)==0) {
RLMLog(ptr,LOG_WARNING,"rlm_spottrap: no rules specified");
return;
}
while(strlen(address)>0) {
rlm_spottrap_addresses=
realloc(rlm_spottrap_addresses,(rlm_spottrap_devs+1)*(rlm_spottrap_devs+1)*16);
strcpy(rlm_spottrap_addresses+16*rlm_spottrap_devs,address);
rlm_spottrap_groups=realloc(rlm_spottrap_groups,(rlm_spottrap_devs+1)*16);
strncpy(rlm_spottrap_groups+16*rlm_spottrap_devs,
RLMGetStringValue(ptr,arg,section,"GroupName",""),10);
rlm_spottrap_minimums=realloc(rlm_spottrap_minimums,(rlm_spottrap_devs+1)*sizeof(int));
rlm_spottrap_minimums[rlm_spottrap_devs]=
RLMGetIntegerValue(ptr,arg,section,"MinimumLength",0);
rlm_spottrap_maximums=realloc(rlm_spottrap_maximums,(rlm_spottrap_devs+1)*sizeof(int));
rlm_spottrap_maximums[rlm_spottrap_devs]=
RLMGetIntegerValue(ptr,arg,section,"MaximumLength",0);
rlm_spottrap_ports=realloc(rlm_spottrap_ports,(rlm_spottrap_devs+1)*sizeof(uint16_t));
rlm_spottrap_ports[rlm_spottrap_devs]=
RLMGetIntegerValue(ptr,arg,section,"UdpPort",0);
rlm_spottrap_formats=realloc(rlm_spottrap_formats,(rlm_spottrap_devs+1)*256);
strncpy(rlm_spottrap_formats+256*rlm_spottrap_devs,
RLMGetStringValue(ptr,arg,section,"FormatString",""),256);
rlm_spottrap_default_formats=realloc(rlm_spottrap_default_formats,
(rlm_spottrap_devs+1)*256);
strncpy(rlm_spottrap_default_formats+256*rlm_spottrap_devs,
RLMGetStringValue(ptr,arg,section,"DefaultFormatString",""),256);
rlm_spottrap_masters=realloc(rlm_spottrap_masters,
(rlm_spottrap_devs+1)*sizeof(int));
rlm_spottrap_masters[rlm_spottrap_devs]=
rlm_spottrap_GetLogStatus(ptr,arg,section,"MasterLog");
rlm_spottrap_aux1s=realloc(rlm_spottrap_aux1s,
(rlm_spottrap_devs+1)*sizeof(int));
rlm_spottrap_aux1s[rlm_spottrap_devs]=
rlm_spottrap_GetLogStatus(ptr,arg,section,"Aux1Log");
rlm_spottrap_aux2s=realloc(rlm_spottrap_aux2s,
(rlm_spottrap_devs+1)*sizeof(int));
rlm_spottrap_aux2s[rlm_spottrap_devs]=
rlm_spottrap_GetLogStatus(ptr,arg,section,"Aux2Log");
sprintf(errtext,"rlm_spottrap: configured rule for \"%s:%d\"",address,
rlm_spottrap_ports[rlm_spottrap_devs]);
rlm_spottrap_devs++;
RLMLog(ptr,LOG_INFO,errtext);
sprintf(section,"Rule%d",i++);
strncpy(address,RLMGetStringValue(ptr,arg,section,"IpAddress",""),15);
}
}
void rlm_spottrap_RLMFree(void *ptr)
{
free(rlm_spottrap_addresses);
free(rlm_spottrap_groups);
free(rlm_spottrap_minimums);
free(rlm_spottrap_maximums);
free(rlm_spottrap_ports);
free(rlm_spottrap_formats);
free(rlm_spottrap_default_formats);
free(rlm_spottrap_masters);
free(rlm_spottrap_aux1s);
free(rlm_spottrap_aux2s);
}
void rlm_spottrap_RLMPadDataSent(void *ptr,const struct rlm_svc *svc,
const struct rlm_log *log,
const struct rlm_pad *now,
const struct rlm_pad *next)
{
int i;
int flag=0;
char msg[1500];
for(i=0;i<rlm_spottrap_devs;i++) {
switch(log->log_mach) {
case 0:
flag=rlm_spottrap_masters[i];
break;
case 1:
flag=rlm_spottrap_aux1s[i];
break;
case 2:
flag=rlm_spottrap_aux2s[i];
break;
}
if((flag==1)||((flag==2)&&(log->log_onair!=0))) {
if((strcasecmp(now->rlm_group,rlm_spottrap_groups+16*i)==0)&&
(now->rlm_len>=rlm_spottrap_minimums[i])&&
(now->rlm_len<=rlm_spottrap_maximums[i])) {
const char *str=
RLMResolveNowNext(ptr,now,next,rlm_spottrap_formats+256*i);
RLMSendUdp(ptr,rlm_spottrap_addresses+i*16,rlm_spottrap_ports[i],
str,strlen(str));
snprintf(msg,1500,"rlm_spottrap: sending pad update: \"%s\"",
(const char *)str);
RLMLog(ptr,LOG_INFO,msg);
}
else {
const char *str=
RLMResolveNowNext(ptr,now,next,rlm_spottrap_default_formats+256*i);
RLMSendUdp(ptr,rlm_spottrap_addresses+i*16,rlm_spottrap_ports[i],
str,strlen(str));
snprintf(msg,1500,"rlm_spottrap: sending default pad update: \"%s\"",
(const char *)str);
RLMLog(ptr,LOG_INFO,msg);
}
}
}
}

153
rlm/rlm_test.c Normal file
View File

@@ -0,0 +1,153 @@
/* rlm_test.c
*
* (C) Copyright 2008 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.
*
* This is a sample Rivendell Loadable Module. All it does is print
* Now & Next data to standard output for each event transition.
*
* To compile this module, just do:
*
* gcc -shared -o rlm_test.rlm rlm_test.c
*/
#include <stdio.h>
#include <string.h>
#include <rlm/rlm.h>
void rlm_test_RLMStart(void *ptr,const char *arg)
{
char str[1024];
sprintf(str,"rlm_test: started on %s",
RLMDateTime(ptr,0,"MM/dd/yyyy at hh:mm:ss"));
RLMLog(ptr,LOG_NOTICE,str);
}
void rlm_test_RLMFree(void *ptr)
{
}
void rlm_test_print_carttype(int type)
{
switch(type) {
case RLM_CARTTYPE_ALL:
printf(" Type:\n");
break;
case RLM_CARTTYPE_AUDIO:
printf(" Type: AUDIO\n");
break;
case RLM_CARTTYPE_MACRO:
printf(" Type: MACRO\n");
break;
}
}
void rlm_test_RLMPadDataSent(void *ptr,const struct rlm_svc *svc,
const struct rlm_log *log,
const struct rlm_pad *now,
const struct rlm_pad *next)
{
printf("Service: %s\n",svc->svc_name);
printf("Program Code: %s\n",svc->svc_pgmcode);
printf("Log Name: %s\n",log->log_name);
if(log->log_onair==0) {
printf(" OnAir = false\n");
}
else {
printf(" OnAir = true\n");
}
switch(log->log_mode) {
case RLM_LOGMODE_LIVEASSIST:
printf(" Mode = Live Assist\n");
break;
case RLM_LOGMODE_AUTOMATIC:
printf(" Mode = Automatic\n");
break;
case RLM_LOGMODE_MANUAL:
printf(" Mode = Manual\n");
break;
}
switch(log->log_mach) {
case 0:
printf(" -- On Main Log ---------------------------------------------\n");
break;
case 1:
printf(" -- On Aux 1 Log --------------------------------------------\n");
break;
case 2:
printf(" -- On Aux 2 Log --------------------------------------------\n");
break;
}
printf("Playing NOW\n");
printf(" Cart number: %06u\n",now->rlm_cartnum);
rlm_test_print_carttype(now->rlm_carttype);
printf("Start Date/Time: %04u-%02u-%02u %02u:%02u:%02u.%03u\n",
now->rlm_start_year,now->rlm_start_mon,now->rlm_start_day,
now->rlm_start_hour,now->rlm_start_min,now->rlm_start_sec,
now->rlm_start_msec);
printf(" Length: %u mS\n",now->rlm_len);
printf(" Title: %s\n",now->rlm_title);
printf(" Artist: %s\n",now->rlm_artist);
printf(" Label: %s\n",now->rlm_label);
printf(" Conductor: %s\n",now->rlm_conductor);
printf(" SongId: %s\n",now->rlm_song_id);
printf(" Client: %s\n",now->rlm_client);
printf(" Agency: %s\n",now->rlm_agency);
printf(" Composer: %s\n",now->rlm_comp);
printf(" Publisher: %s\n",now->rlm_pub);
printf(" UserDefined: %s\n",now->rlm_userdef);
printf(" Outcue: %s\n",now->rlm_outcue);
printf("Cut Description: %s\n",now->rlm_description);
printf(" ISRC: %s\n",now->rlm_isrc);
printf(" ISCI Code: %s\n",now->rlm_isci);
printf(" Ext Data: %s\n",now->rlm_ext_data);
printf(" Ext Event ID: %s\n",now->rlm_ext_eventid);
printf(" Ext Annc Type: %s\n",now->rlm_ext_annctype);
printf("\n");
printf("Playing NEXT\n");
printf(" Cart number: %06u\n",next->rlm_cartnum);
rlm_test_print_carttype(next->rlm_carttype);
printf("Start Date/Time: %04u-%02u-%02u %02u:%02u:%02u.%03u\n",
next->rlm_start_year,next->rlm_start_mon,next->rlm_start_day,
next->rlm_start_hour,next->rlm_start_min,next->rlm_start_sec,
next->rlm_start_msec);
printf(" Length: %u mS\n",next->rlm_len);
printf(" Title: %s\n",next->rlm_title);
printf(" Artist: %s\n",next->rlm_artist);
printf(" Label: %s\n",next->rlm_label);
printf(" Conductor: %s\n",next->rlm_conductor);
printf(" SongId: %s\n",next->rlm_song_id);
printf(" Client: %s\n",next->rlm_client);
printf(" Agency: %s\n",next->rlm_agency);
printf(" Composer: %s\n",next->rlm_comp);
printf(" Publisher: %s\n",next->rlm_pub);
printf(" UserDefined: %s\n",next->rlm_userdef);
printf(" Outcue: %s\n",next->rlm_outcue);
printf("Cut Description: %s\n",next->rlm_description);
printf(" ISRC: %s\n",next->rlm_isrc);
printf(" ISCI Code: %s\n",next->rlm_isci);
printf(" Ext Data: %s\n",next->rlm_ext_data);
printf(" Ext Event ID: %s\n",next->rlm_ext_eventid);
printf(" Ext Annc Type: %s\n",next->rlm_ext_annctype);
}

264
rlm/rlm_twitter.c Normal file
View File

@@ -0,0 +1,264 @@
/* rlm_twitter.c
*
* (C) Copyright 2008 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.
*
* This is a Rivendell Loadable Module. It sends Now&Next PAD data
* to the Twitter account(s) specified in the configuration file pointed
* to by the plugin argument. For information about the Twitter service,
* see http://www.twitter.com/.
*
* This module requires the curl(1) network transfer tool, included with
* most Linux distros. It is also available at http://curl.haxx.se/.
*
* To compile this module, just do:
*
* gcc -shared -o rlm_twitter.rlm rlm_twitter.c
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <sys/types.h>
#include <unistd.h>
#include <rlm/rlm.h>
int rlm_twitter_devs;
char *rlm_twitter_addresses;
char *rlm_twitter_passwords;
char *rlm_twitter_formats;
int *rlm_twitter_masters;
int *rlm_twitter_aux1s;
int *rlm_twitter_aux2s;
int rlm_twitter_BufferDiff(char *sString,int dOrigin,int dDiff,int dMaxSize)
{
int dOldSize,dNewSize;
int i;
/*
* Will it fit?
*/
dOldSize=strlen(sString);
if((dOldSize+dDiff)>=dMaxSize) {
return -1;
}
dNewSize=dOldSize+dDiff;
/*
* Adding characters
*/
if(dDiff>0) {
for(i=dOldSize;i>dOrigin;i--) {
sString[i+dDiff]=sString[i];
}
return dNewSize;
}
/*
* No Change
*/
if(dDiff==0) {
return dNewSize;
}
/*
* Deleting Characters
*/
if(dDiff<0) {
for(i=dOrigin;i<dOldSize;i++) {
sString[i]=sString[i-dDiff];
}
return dNewSize;
}
return -1;
}
int rlm_twitter_EncodeString(char *sString,int dMaxSize)
{
int i; /* General Purpose Counter */
char sAccum[4]; /* General String Buffer */
i=0;
while(sString[i]!=0) {
if(((sString[i]!=' ') && (sString[i]!='*') && (sString[i]!='-') &&
(sString[i]!='_') && (sString[i]!='.')) &&
((sString[i]<'0') ||
((sString[i]>'9') && (sString[i]<'A')) ||
((sString[i]>'Z') && (sString[i]<'a')) ||
(sString[i]>'z'))) {
if(rlm_twitter_BufferDiff(sString,i,2,dMaxSize)<0) {
return -1;
}
sprintf(sAccum,"%%%2x",sString[i]);
sString[i++]=sAccum[0];
sString[i++]=sAccum[1];
sString[i]=sAccum[2];
}
if(sString[i]==' ') {
sString[i]='+';
}
i++;
}
return strlen(sString);
}
int rlm_twitter_GetLogStatus(void *ptr,const char *arg,const char *section,
const char *logname)
{
const char *tag=RLMGetStringValue(ptr,arg,section,logname,"");
if(strcasecmp(tag,"yes")==0) {
return 1;
}
if(strcasecmp(tag,"on")==0) {
return 1;
}
if(strcasecmp(tag,"true")==0) {
return 1;
}
if(strcasecmp(tag,"no")==0) {
return 0;
}
if(strcasecmp(tag,"off")==0) {
return 0;
}
if(strcasecmp(tag,"false")==0) {
return 0;
}
if(strcasecmp(tag,"onair")==0) {
return 2;
}
return 0;
}
void rlm_twitter_RLMStart(void *ptr,const char *arg)
{
char address[256];
char section[256];
char errtext[256];
int i=1;
rlm_twitter_devs=0;
rlm_twitter_addresses=NULL;
rlm_twitter_passwords=NULL;
rlm_twitter_formats=NULL;
rlm_twitter_masters=NULL;
rlm_twitter_aux1s=NULL;
rlm_twitter_aux2s=NULL;
sprintf(section,"Twitter%d",i++);
strncpy(address,RLMGetStringValue(ptr,arg,section,"EmailAddress",""),255);
address[255]=0;
if(strlen(address)==0) {
RLMLog(ptr,LOG_WARNING,"rlm_twitter: no twitter accounts specified");
return;
}
while(strlen(address)>0) {
rlm_twitter_addresses=realloc(rlm_twitter_addresses,
(rlm_twitter_devs+1)*(rlm_twitter_devs+1)*256);
strcpy(rlm_twitter_addresses+256*rlm_twitter_devs,address);
rlm_twitter_passwords=realloc(rlm_twitter_passwords,
(rlm_twitter_devs+1)*(rlm_twitter_devs+1)*256);
strcpy(rlm_twitter_passwords+256*rlm_twitter_devs,
RLMGetStringValue(ptr,arg,section,"Password",""));
rlm_twitter_formats=realloc(rlm_twitter_formats,(rlm_twitter_devs+1)*256);
strncpy(rlm_twitter_formats+256*rlm_twitter_devs,
RLMGetStringValue(ptr,arg,section,"FormatString",""),256);
rlm_twitter_masters=realloc(rlm_twitter_masters,
(rlm_twitter_devs+1)*sizeof(int));
rlm_twitter_masters[rlm_twitter_devs]=
rlm_twitter_GetLogStatus(ptr,arg,section,"MasterLog");
rlm_twitter_aux1s=realloc(rlm_twitter_aux1s,
(rlm_twitter_devs+1)*sizeof(int));
rlm_twitter_aux1s[rlm_twitter_devs]=
rlm_twitter_GetLogStatus(ptr,arg,section,"Aux1Log");
rlm_twitter_aux2s=realloc(rlm_twitter_aux2s,
(rlm_twitter_devs+1)*sizeof(int));
rlm_twitter_aux2s[rlm_twitter_devs]=
rlm_twitter_GetLogStatus(ptr,arg,section,"Aux2Log");
sprintf(errtext,"rlm_twitter: configured account \"%s\"",address);
rlm_twitter_devs++;
RLMLog(ptr,LOG_INFO,errtext);
sprintf(section,"Twitter%d",i++);
strncpy(address,RLMGetStringValue(ptr,arg,section,"EmailAddress",""),255);
address[255]=0;
}
}
void rlm_twitter_RLMFree(void *ptr)
{
free(rlm_twitter_addresses);
free(rlm_twitter_passwords);
free(rlm_twitter_formats);
free(rlm_twitter_masters);
free(rlm_twitter_aux1s);
free(rlm_twitter_aux2s);
}
void rlm_twitter_RLMPadDataSent(void *ptr,const struct rlm_svc *svc,
const struct rlm_log *log,
const struct rlm_pad *now,
const struct rlm_pad *next)
{
int i;
int flag=0;
char str[1024];
char account[1024];
char pad[1024];
char msg[1500];
for(i=0;i<rlm_twitter_devs;i++) {
switch(log->log_mach) {
case 0:
flag=rlm_twitter_masters[i];
break;
case 1:
flag=rlm_twitter_aux1s[i];
break;
case 2:
flag=rlm_twitter_aux2s[i];
break;
}
if((flag==1)||((flag==2)&&(log->log_onair!=0))) {
strncpy(str,RLMResolveNowNext(ptr,now,next,
rlm_twitter_formats+256*i),256);
rlm_twitter_EncodeString(str,1023);
snprintf(account,1024,"%s:%s",rlm_twitter_addresses+256*i,
rlm_twitter_passwords+256*i);
snprintf(pad,1024,"status=%s",str);
if(strlen(now->rlm_title)!=0) {
if(fork()==0) {
execlp("curl","curl","-u",account,"-d",pad,"-o","/dev/null","-s",
"http://twitter.com/statuses/update.xml",(char *)NULL);
RLMLog(ptr,LOG_WARNING,"rlm_twitter: unable to execute curl(1)");
exit(0);
}
}
snprintf(msg,1500,"rlm_twitter: sending pad update: \"%s\"",
(const char *)str);
RLMLog(ptr,LOG_INFO,msg);
}
}
}

205
rlm/rlm_udp.c Normal file
View File

@@ -0,0 +1,205 @@
/* rlm_udp.c
*
* (C) Copyright 2008 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.
*
* This is a Rivendell Loadable Module. It sends Now&Next PAD data via
* UDP packets to the destination(s) specified in the configuration file
* pointed to by the plugin argument.
*
* To compile this module, just do:
*
* gcc -shared -o rlm_udp.rlm rlm_udp.c
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <rlm/rlm.h>
int rlm_udp_devs;
char *rlm_udp_addresses;
uint16_t *rlm_udp_ports;
char *rlm_udp_formats;
int *rlm_udp_encodings;
int *rlm_udp_null_updates;
int *rlm_udp_masters;
int *rlm_udp_aux1s;
int *rlm_udp_aux2s;
int rlm_udp_GetLogStatus(void *ptr,const char *arg,const char *section,
const char *logname)
{
const char *tag=RLMGetStringValue(ptr,arg,section,logname,"");
if(strcasecmp(tag,"yes")==0) {
return 1;
}
if(strcasecmp(tag,"on")==0) {
return 1;
}
if(strcasecmp(tag,"true")==0) {
return 1;
}
if(strcasecmp(tag,"no")==0) {
return 0;
}
if(strcasecmp(tag,"off")==0) {
return 0;
}
if(strcasecmp(tag,"false")==0) {
return 0;
}
if(strcasecmp(tag,"onair")==0) {
return 2;
}
return 0;
}
void rlm_udp_RLMStart(void *ptr,const char *arg)
{
char address[17];
char section[256];
char errtext[256];
int i=1;
rlm_udp_devs=0;
rlm_udp_addresses=NULL;
rlm_udp_ports=NULL;
rlm_udp_formats=NULL;
rlm_udp_encodings=NULL;
rlm_udp_null_updates=NULL;
rlm_udp_masters=NULL;
rlm_udp_aux1s=NULL;
rlm_udp_aux2s=NULL;
sprintf(section,"Udp%d",i++);
strncpy(address,RLMGetStringValue(ptr,arg,section,"IpAddress",""),15);
if(strlen(address)==0) {
RLMLog(ptr,LOG_WARNING,"rlm_udp: no udp destinations specified");
return;
}
while(strlen(address)>0) {
rlm_udp_addresses=
realloc(rlm_udp_addresses,(rlm_udp_devs+1)*(rlm_udp_devs+1)*16);
strcpy(rlm_udp_addresses+16*rlm_udp_devs,address);
rlm_udp_ports=realloc(rlm_udp_ports,(rlm_udp_devs+1)*sizeof(uint16_t));
rlm_udp_ports[rlm_udp_devs]=
RLMGetIntegerValue(ptr,arg,section,"UdpPort",0);
rlm_udp_formats=realloc(rlm_udp_formats,(rlm_udp_devs+1)*256);
strncpy(rlm_udp_formats+256*rlm_udp_devs,
RLMGetStringValue(ptr,arg,section,"FormatString",""),256);
rlm_udp_encodings=realloc(rlm_udp_encodings,
(rlm_udp_devs+1)*sizeof(int));
rlm_udp_encodings[rlm_udp_devs]=
RLMGetIntegerValue(ptr,arg,section,"Encoding",RLM_ENCODE_NONE);
rlm_udp_null_updates=realloc(rlm_udp_null_updates,
(rlm_udp_devs+1)*sizeof(int));
rlm_udp_null_updates[rlm_udp_devs]=
RLMGetIntegerValue(ptr,arg,section,"ProcessNullUpdates",0);
rlm_udp_masters=realloc(rlm_udp_masters,
(rlm_udp_devs+1)*sizeof(int));
rlm_udp_masters[rlm_udp_devs]=
rlm_udp_GetLogStatus(ptr,arg,section,"MasterLog");
rlm_udp_aux1s=realloc(rlm_udp_aux1s,
(rlm_udp_devs+1)*sizeof(int));
rlm_udp_aux1s[rlm_udp_devs]=
rlm_udp_GetLogStatus(ptr,arg,section,"Aux1Log");
rlm_udp_aux2s=realloc(rlm_udp_aux2s,
(rlm_udp_devs+1)*sizeof(int));
rlm_udp_aux2s[rlm_udp_devs]=
rlm_udp_GetLogStatus(ptr,arg,section,"Aux2Log");
sprintf(errtext,"rlm_udp: configured destination \"%s:%d\"",address,
rlm_udp_ports[rlm_udp_devs]);
rlm_udp_devs++;
RLMLog(ptr,LOG_INFO,errtext);
sprintf(section,"Udp%d",i++);
strncpy(address,RLMGetStringValue(ptr,arg,section,"IpAddress",""),15);
}
}
void rlm_udp_RLMFree(void *ptr)
{
free(rlm_udp_addresses);
free(rlm_udp_ports);
free(rlm_udp_formats);
free(rlm_udp_encodings);
free(rlm_udp_null_updates);
free(rlm_udp_masters);
free(rlm_udp_aux1s);
free(rlm_udp_aux2s);
}
void rlm_udp_RLMPadDataSent(void *ptr,const struct rlm_svc *svc,
const struct rlm_log *log,
const struct rlm_pad *now,
const struct rlm_pad *next)
{
int i;
int flag=0;
char msg[1500];
for(i=0;i<rlm_udp_devs;i++) {
switch(rlm_udp_null_updates[i]) {
case 0: /* Process all updates */
break;
case 1: /* Process only non-null NOW updates */
if(now->rlm_cartnum==0) {
return;
}
break;
case 2: /* Process only non-null NEXT updates */
if(next->rlm_cartnum==0) {
return;
}
break;
case 3: /* Process only non-null NOW and NEXT updates */
if((now->rlm_cartnum==0)||(next->rlm_cartnum==0)) {
return;
}
break;
}
switch(log->log_mach) {
case 0:
flag=rlm_udp_masters[i];
break;
case 1:
flag=rlm_udp_aux1s[i];
break;
case 2:
flag=rlm_udp_aux2s[i];
break;
}
if((flag==1)||((flag==2)&&(log->log_onair!=0))) {
const char *str=
RLMResolveNowNextEncoded(ptr,now,next,rlm_udp_formats+256*i,
rlm_udp_encodings[i]);
RLMSendUdp(ptr,rlm_udp_addresses+i*16,rlm_udp_ports[i],str,strlen(str));
snprintf(msg,1500,"rlm_udp: sending pad update: \"%s\"",
(const char *)str);
RLMLog(ptr,LOG_INFO,msg);
}
}
}

301
rlm/rlm_xds.c Normal file
View File

@@ -0,0 +1,301 @@
/* rlm_xds.c
*
* (C) Copyright 2010 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.
*
* This is a Rivendell Loadable Module. It sends generates enhanced netcue
* (aka CIC) packets for the Citadel/X-Digital Systems copy-splitting system,
* using a configuration file pointed to by the plugin argument.
*
* To compile this module, just do:
*
* gcc -shared -o rlm_xds.rlm rlm_xds.c
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <limits.h>
#include <rlm/rlm.h>
int rlm_xds_devs;
char *rlm_xds_isci_prefixes;
char *rlm_xds_addresses;
uint16_t *rlm_xds_ports;
int *rlm_xds_handles;
char *rlm_xds_tty_buffers;
int *rlm_xds_masters;
int *rlm_xds_aux1s;
int *rlm_xds_aux2s;
unsigned rlm_xds_GetChecksum(const char *pack)
{
unsigned ret=0;
int i;
for(i=0;i<strlen(pack);i++) {
ret+=pack[i];
}
return ret;
}
const char *rlm_xds_FilterCharacters(const char *str)
{
static char ret[32];
int i;
strncpy(ret,str,31);
for(i=0;i<strlen(ret);i++) {
switch(ret[i]) {
case ' ':
case ',':
case '.':
ret[i]='_';
break;
case '"':
ret[i]=39;
break;
case '%':
case '*':
case '+':
case '/':
case ':':
case ';':
case '<':
case '=':
case '>':
case '?':
case '@':
case '[':
case '\\':
case ']':
case '^':
case '{':
case '|':
case '}':
ret[i]='-';
break;
}
}
return ret;
}
int rlm_xds_GetLogStatus(void *ptr,const char *arg,const char *section,
const char *logname)
{
const char *tag=RLMGetStringValue(ptr,arg,section,logname,"");
if(strcasecmp(tag,"yes")==0) {
return 1;
}
if(strcasecmp(tag,"on")==0) {
return 1;
}
if(strcasecmp(tag,"true")==0) {
return 1;
}
if(strcasecmp(tag,"no")==0) {
return 0;
}
if(strcasecmp(tag,"off")==0) {
return 0;
}
if(strcasecmp(tag,"false")==0) {
return 0;
}
if(strcasecmp(tag,"onair")==0) {
return 2;
}
return 0;
}
void rlm_xds_RLMStart(void *ptr,const char *arg)
{
char address[17];
char section[256];
char errtext[256];
int tty_speed;
int i=1;
rlm_xds_devs=0;
rlm_xds_addresses=NULL;
rlm_xds_ports=NULL;
rlm_xds_handles=NULL;
rlm_xds_tty_buffers=NULL;
rlm_xds_masters=NULL;
rlm_xds_aux1s=NULL;
rlm_xds_aux2s=NULL;
sprintf(section,"Udp%d",i++);
strncpy(address,RLMGetStringValue(ptr,arg,section,"IpAddress",""),15);
if(strlen(address)==0) {
RLMLog(ptr,LOG_WARNING,"rlm_xds: no xds destinations specified");
return;
}
while(strlen(address)>0) {
rlm_xds_addresses=
realloc(rlm_xds_addresses,(rlm_xds_devs+1)*(rlm_xds_devs+1)*16);
strcpy(rlm_xds_addresses+16*rlm_xds_devs,address);
rlm_xds_isci_prefixes=realloc(rlm_xds_isci_prefixes,(rlm_xds_devs+1)*32);
strncpy(rlm_xds_isci_prefixes+32*rlm_xds_devs,
RLMGetStringValue(ptr,arg,section,"IsciPrefix",""),31);
rlm_xds_ports=realloc(rlm_xds_ports,(rlm_xds_devs+1)*sizeof(uint16_t));
rlm_xds_ports[rlm_xds_devs]=
RLMGetIntegerValue(ptr,arg,section,"UdpPort",0);
rlm_xds_handles=realloc(rlm_xds_handles,(rlm_xds_devs+1)*sizeof(int));
rlm_xds_handles[rlm_xds_devs]=-1;
tty_speed=RLMGetIntegerValue(ptr,arg,section,"TtySpeed",9600);
printf("speed: %d\n",tty_speed);
rlm_xds_handles[rlm_xds_devs]=
RLMOpenSerial(ptr,RLMGetStringValue(ptr,arg,section,"TtyDevice",""),
tty_speed,RLM_PARITY_NONE,1);
rlm_xds_tty_buffers=realloc(rlm_xds_tty_buffers,(rlm_xds_devs+1)*256);
memset(rlm_xds_tty_buffers+rlm_xds_devs,0,256);
rlm_xds_masters=realloc(rlm_xds_masters,
(rlm_xds_devs+1)*sizeof(int));
rlm_xds_masters[rlm_xds_devs]=
rlm_xds_GetLogStatus(ptr,arg,section,"MasterLog");
rlm_xds_aux1s=realloc(rlm_xds_aux1s,
(rlm_xds_devs+1)*sizeof(int));
rlm_xds_aux1s[rlm_xds_devs]=
rlm_xds_GetLogStatus(ptr,arg,section,"Aux1Log");
rlm_xds_aux2s=realloc(rlm_xds_aux2s,
(rlm_xds_devs+1)*sizeof(int));
rlm_xds_aux2s[rlm_xds_devs]=
rlm_xds_GetLogStatus(ptr,arg,section,"Aux2Log");
if(rlm_xds_handles[rlm_xds_devs]<0) {
sprintf(errtext,"rlm_xds: configured destination \"%s:%d\"",address,
rlm_xds_ports[rlm_xds_devs]);
}
else {
sprintf(errtext,"rlm_xds: configured destination \"%s\"",
(const char *)RLMGetStringValue(ptr,arg,section,"TtyDevice",""));
}
rlm_xds_devs++;
RLMLog(ptr,LOG_INFO,errtext);
sprintf(section,"Udp%d",i++);
strncpy(address,RLMGetStringValue(ptr,arg,section,"IpAddress",""),15);
}
}
void rlm_xds_RLMFree(void *ptr)
{
int i;
for(i=0;i<rlm_xds_devs;i++) {
if(rlm_xds_handles[i]>=0) {
RLMCloseSerial(ptr,rlm_xds_handles[i]);
rlm_xds_handles[i]=-1;
}
}
free(rlm_xds_addresses);
free(rlm_xds_ports);
free(rlm_xds_handles);
free(rlm_xds_tty_buffers);
free(rlm_xds_isci_prefixes);
free(rlm_xds_masters);
free(rlm_xds_aux1s);
free(rlm_xds_aux2s);
}
void rlm_xds_RLMPadDataSent(void *ptr,const struct rlm_svc *svc,
const struct rlm_log *log,
const struct rlm_pad *now,
const struct rlm_pad *next)
{
int i;
int flag=0;
char packet[64];
char tty_packet[256];
char msg[1500];
if(strlen((now->rlm_ext_eventid))==0) {
return;
}
for(i=0;i<rlm_xds_devs;i++) {
switch(log->log_mach) {
case 0:
flag=rlm_xds_masters[i];
break;
case 1:
flag=rlm_xds_aux1s[i];
break;
case 2:
flag=rlm_xds_aux2s[i];
break;
}
if((flag==1)||((flag==2)&&(log->log_onair!=0))) {
packet[0]=0;
snprintf(packet,64,"0:%s:%s%s:*",svc->svc_pgmcode,
rlm_xds_isci_prefixes+i*32,
rlm_xds_FilterCharacters(now->rlm_ext_eventid));
if(rlm_xds_handles[i]<0) {
RLMSendUdp(ptr,rlm_xds_addresses+i*16,rlm_xds_ports[i],
packet,strlen(packet));
snprintf(msg,1500,"rlm_xds: sending CIC NetCue: \"%s\" to %s:%d",
(const char *)packet,rlm_xds_addresses+i*16,rlm_xds_ports[i]);
}
else {
snprintf(tty_packet,256,"NC:%u:%s\r\n",
rlm_xds_GetChecksum(packet),packet);
RLMSendSerial(ptr,rlm_xds_handles[i],tty_packet,strlen(tty_packet));
RLMSendSerial(ptr,rlm_xds_handles[i],tty_packet,strlen(tty_packet));
snprintf(msg,1500,"rlm_xds: sending CIC NetCue: \"%s\" to tty",
(const char *)packet);
}
RLMLog(ptr,LOG_INFO,msg);
}
}
}
void rlm_xds_RLMSerialDataReceived(void *ptr,int handle,
const char *data,int len)
{
int dev;
int i;
char *buffer;
for(dev=0;dev<rlm_xds_devs;dev++) {
if(handle==rlm_xds_handles[dev]) {
buffer=rlm_xds_tty_buffers+256*dev;
for(i=0;i<len;i++) {
if(data[i]==13) {
if(strcmp(buffer,"PINGRECV")==0) {
RLMSendSerial(ptr,handle,"PONGRECV\r\n",10);
}
buffer[0]=0;
}
else {
if(data[i]!=10) {
buffer[strlen(buffer)+1]=0;
buffer[strlen(buffer)]=data[i];
}
}
}
return;
}
}
fprintf(stderr,"rlm_xds: unknown tty handle %d\n",handle);
}

304
rlm/rlm_xmpad.c Normal file
View File

@@ -0,0 +1,304 @@
/* rlm_xmpad.c
*
* (C) Copyright 2008 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.
*
* This is a Rivendell Loadable Module. It sends Now&Next PAD data
* to an XM radio channel, using XM's in-house format.
* plugin argument.
*
* To compile this module, just do:
*
* gcc -shared -o rlm_xmpad.rlm rlm_xmpad.c
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <rlm/rlm.h>
#define RLM_XMPAD_DELIMITER 0x02
//#define RLM_XMPAD_DELIMITER 0x7C
int rlm_xmpad_devs;
int *rlm_xmpad_ids;
int *rlm_xmpad_handles;
int *rlm_xmpad_recordings;
char *rlm_xmpad_format1s;
char *rlm_xmpad_format2s;
int *rlm_xmpad_display_size1s;
int *rlm_xmpad_display_size2s;
int *rlm_xmpad_masters;
int *rlm_xmpad_aux1s;
int *rlm_xmpad_aux2s;
int rlm_xmpad_GetLogStatus(void *ptr,const char *arg,const char *section,
const char *logname)
{
const char *tag=RLMGetStringValue(ptr,arg,section,logname,"");
if(strcasecmp(tag,"yes")==0) {
return 1;
}
if(strcasecmp(tag,"on")==0) {
return 1;
}
if(strcasecmp(tag,"true")==0) {
return 1;
}
if(strcasecmp(tag,"no")==0) {
return 0;
}
if(strcasecmp(tag,"off")==0) {
return 0;
}
if(strcasecmp(tag,"false")==0) {
return 0;
}
if(strcasecmp(tag,"onair")==0) {
return 2;
}
return 0;
}
void rlm_xmpad_SendPad(void *ptr,int config,const char *line1,
const char *line2,int len)
{
char str[1024];
char sline1[17];
char sline2[17];
char flag1[1024];
char flag2[1024];
int i;
//
// Log it
//
sprintf(str,"rlm_xmpad: sending pad update: |%s|%s|%d|",line1,line2,len);
RLMLog(ptr,LOG_INFO,str);
//
// Generate Display Strings and Flags
//
strncpy(sline1,line1,16);
sline1[16]=0;
flag1[0]=0;
for(i=0;i<rlm_xmpad_display_size1s[config];i++) {
strcat(flag1,"1");
}
strncpy(sline2,line2,16);
sline2[16]=0;
flag2[0]=0;
for(i=0;i<rlm_xmpad_display_size2s[config];i++) {
strcat(flag2,"1");
}
//
// Generate PAD Data
// The B-4 packet
//
sprintf(str,"B-4%c%d%c%d%c%d%c%d%c%d%c%d%c%s%c%s%c%s%c%s%c%s%c%s%c%u\n",
RLM_XMPAD_DELIMITER,!(rlm_xmpad_recordings[config]),
RLM_XMPAD_DELIMITER,1,
RLM_XMPAD_DELIMITER,len/432,
RLM_XMPAD_DELIMITER,0,
RLM_XMPAD_DELIMITER,rlm_xmpad_display_size1s[config],
RLM_XMPAD_DELIMITER,rlm_xmpad_display_size2s[config],
RLM_XMPAD_DELIMITER,flag1,
RLM_XMPAD_DELIMITER,flag2,
RLM_XMPAD_DELIMITER,sline2,
RLM_XMPAD_DELIMITER,flag1,
RLM_XMPAD_DELIMITER,flag2,
RLM_XMPAD_DELIMITER,sline1,
RLM_XMPAD_DELIMITER,rlm_xmpad_ids[config]);
RLMSendSerial(ptr,rlm_xmpad_handles[config],str,strlen(str));
RLMSendSerial(ptr,rlm_xmpad_handles[config],str,strlen(str));
RLMSendSerial(ptr,rlm_xmpad_handles[config],str,strlen(str));
//
// The A4 Packet
//
sprintf(str,"A4%c%d%c%s\n",RLM_XMPAD_DELIMITER,1,RLM_XMPAD_DELIMITER,line1);
RLMSendSerial(ptr,rlm_xmpad_handles[config],str,strlen(str));
//
// The A5 Packet
//
sprintf(str,"A5%c%d%c%s\n",RLM_XMPAD_DELIMITER,1,RLM_XMPAD_DELIMITER,line2);
RLMSendSerial(ptr,rlm_xmpad_handles[config],str,strlen(str));
}
void rlm_xmpad_RLMStart(void *ptr,const char *arg)
{
int handle;
char device[256];
int speed;
int parity;
int wsize;
char section[256];
char errtext[256];
int i=1;
int interval;
rlm_xmpad_devs=0;
rlm_xmpad_ids=NULL;
rlm_xmpad_handles=NULL;
rlm_xmpad_recordings=NULL;
rlm_xmpad_format1s=NULL;
rlm_xmpad_format2s=NULL;
rlm_xmpad_display_size1s=NULL;
rlm_xmpad_display_size2s=NULL;
rlm_xmpad_masters=NULL;
rlm_xmpad_aux1s=NULL;
rlm_xmpad_aux2s=NULL;
sprintf(section,"Serial%d",i++);
strncpy(device,RLMGetStringValue(ptr,arg,section,"Device",""),256);
if(strlen(device)==0) {
RLMLog(ptr,LOG_WARNING,"rlm_xmpad: no serial devices specified");
return;
}
while(strlen(device)>0) {
speed=RLMGetIntegerValue(ptr,arg,section,"Speed",9600);
parity=RLMGetIntegerValue(ptr,arg,section,"Parity",0);
wsize=RLMGetIntegerValue(ptr,arg,section,"WordSize",8);
if((handle=RLMOpenSerial(ptr,device,speed,parity,wsize))>=0) {
rlm_xmpad_handles=realloc(rlm_xmpad_handles,
(rlm_xmpad_devs+1)*sizeof(int));
rlm_xmpad_handles[rlm_xmpad_devs]=handle;
rlm_xmpad_ids=realloc(rlm_xmpad_ids,(rlm_xmpad_devs+1)*sizeof(int));
rlm_xmpad_ids[rlm_xmpad_devs]=
RLMGetIntegerValue(ptr,arg,section,"ProgramID",0);
rlm_xmpad_format1s=realloc(rlm_xmpad_format1s,(rlm_xmpad_devs+1)*256);
strncpy(rlm_xmpad_format1s+256*rlm_xmpad_devs,
RLMGetStringValue(ptr,arg,section,"FormatString1",""),256);
rlm_xmpad_format2s=realloc(rlm_xmpad_format2s,(rlm_xmpad_devs+1)*256);
strncpy(rlm_xmpad_format2s+256*rlm_xmpad_devs,
RLMGetStringValue(ptr,arg,section,"FormatString2",""),256);
rlm_xmpad_display_size1s=realloc(rlm_xmpad_display_size1s,
(rlm_xmpad_devs+1)*sizeof(int));
rlm_xmpad_display_size1s[rlm_xmpad_devs]=
RLMGetIntegerValue(ptr,arg,section,"DisplaySize1",8);
rlm_xmpad_display_size2s=realloc(rlm_xmpad_display_size2s,
(rlm_xmpad_devs+1)*sizeof(int));
rlm_xmpad_display_size2s[rlm_xmpad_devs]=
RLMGetIntegerValue(ptr,arg,section,"DisplaySize2",10);
rlm_xmpad_recordings=realloc(rlm_xmpad_recordings,
(rlm_xmpad_devs+1)*sizeof(int));
rlm_xmpad_recordings[rlm_xmpad_devs]=
RLMGetBooleanValue(ptr,arg,section,"Recording",1);
rlm_xmpad_masters=realloc(rlm_xmpad_masters,
(rlm_xmpad_devs+1)*sizeof(int));
rlm_xmpad_masters[rlm_xmpad_devs]=
rlm_xmpad_GetLogStatus(ptr,arg,section,"MasterLog");
rlm_xmpad_aux1s=realloc(rlm_xmpad_aux1s,
(rlm_xmpad_devs+1)*sizeof(int));
rlm_xmpad_aux1s[rlm_xmpad_devs]=
rlm_xmpad_GetLogStatus(ptr,arg,section,"Aux1Log");
rlm_xmpad_aux2s=realloc(rlm_xmpad_aux2s,
(rlm_xmpad_devs+1)*sizeof(int));
rlm_xmpad_aux2s[rlm_xmpad_devs]=
rlm_xmpad_GetLogStatus(ptr,arg,section,"Aux2Log");
interval=RLMGetIntegerValue(ptr,arg,section,"HeartbeatInterval",30);
if(interval>0) {
RLMStartTimer(ptr,rlm_xmpad_devs,1000*interval,RLM_TIMER_REPEATING);
}
rlm_xmpad_devs++;
sprintf(errtext,"rlm_xmpad: opened device \"%s\"",device);
RLMLog(ptr,LOG_INFO,errtext);
}
else {
sprintf(errtext,"unable to open tty \"%s\"",device);
RLMLog(ptr,LOG_WARNING,errtext);
}
sprintf(section,"Serial%d",i++);
strncpy(device,RLMGetStringValue(ptr,arg,section,"Device",""),256);
}
}
void rlm_xmpad_RLMFree(void *ptr)
{
int i;
for(i=0;i<rlm_xmpad_devs;i++) {
RLMCloseSerial(ptr,rlm_xmpad_handles[i]);
}
free(rlm_xmpad_handles);
free(rlm_xmpad_ids);
free(rlm_xmpad_format1s);
free(rlm_xmpad_format2s);
free(rlm_xmpad_display_size1s);
free(rlm_xmpad_display_size2s);
free(rlm_xmpad_recordings);
free(rlm_xmpad_masters);
free(rlm_xmpad_aux1s);
free(rlm_xmpad_aux2s);
}
/*
void rlm_xmpad_RLMPadDataSent(void *ptr,const char *svcname,int onair,
int lognum,const struct rlm_pad *now,
const struct rlm_pad *next)
*/
void rlm_xmpad_RLMPadDataSent(void *ptr,const struct rlm_svc *svc,
const struct rlm_log *log,
const struct rlm_pad *now,
const struct rlm_pad *next)
{
int i;
int flag=0;
char str1[33];
char str2[33];
char msg[1500];
if(now->rlm_cartnum==0) { // Suppress null PAD frames
return;
}
for(i=0;i<rlm_xmpad_devs;i++) {
switch(log->log_mach) {
case 0:
flag=rlm_xmpad_masters[i];
break;
case 1:
flag=rlm_xmpad_aux1s[i];
break;
case 2:
flag=rlm_xmpad_aux2s[i];
break;
}
if((flag==1)||((flag==2)&&(log->log_onair!=0))) {
strncpy(str1,RLMResolveNowNext(ptr,now,next,rlm_xmpad_format1s+256*i),32);
str1[32]=0;
strncpy(str2,RLMResolveNowNext(ptr,now,next,rlm_xmpad_format2s+256*i),32);
str2[32]=0;
rlm_xmpad_SendPad(ptr,i,str1,str2,now->rlm_len);
snprintf(msg,1500,"rlm_xmpad: sending pad update: \"%s | %s\"",
(const char *)str1,(const char *)str2);
RLMLog(ptr,LOG_INFO,msg);
}
}
}
void rlm_xmpad_RLMTimerExpired(void *ptr,int timernum)
{
RLMSendSerial(ptr,rlm_xmpad_handles[timernum],"H0\n",3);
}