diff --git a/ChangeLog b/ChangeLog index e837776e..152dd10e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -18245,3 +18245,6 @@ * Added a 'PyPAD.Update::startDateTimeString()' method. * Added a 'pypad_spinitron.py' PyPAD script. * Removed the 'rlm_spinitron_plus' RLM. +2018-12-20 Fred Gleason + * Added a 'pypad_ando.py' PyPAD script. + * Removed the 'rlm_ando' RLM. diff --git a/apis/PyPAD/scripts/Makefile.am b/apis/PyPAD/scripts/Makefile.am index 2cd68c70..15588b42 100644 --- a/apis/PyPAD/scripts/Makefile.am +++ b/apis/PyPAD/scripts/Makefile.am @@ -22,14 +22,14 @@ install-exec-am: mkdir -p $(DESTDIR)$(prefix)/@RD_LIB_PATH@/rivendell/PyPAD + ../../../helpers/install_python.sh pypad_ando.py $(DESTDIR)$(prefix)/@RD_LIB_PATH@/rivendell/PyPAD/pypad_ando.py + cp pypad_ando.exemplar $(DESTDIR)$(prefix)/@RD_LIB_PATH@/rivendell/PyPAD/pypad_ando.exemplar ../../../helpers/install_python.sh pypad_filewrite.py $(DESTDIR)$(prefix)/@RD_LIB_PATH@/rivendell/PyPAD/pypad_filewrite.py cp pypad_filewrite.exemplar $(DESTDIR)$(prefix)/@RD_LIB_PATH@/rivendell/PyPAD/pypad_filewrite.exemplar ../../../helpers/install_python.sh pypad_live365.py $(DESTDIR)$(prefix)/@RD_LIB_PATH@/rivendell/PyPAD/pypad_live365.py cp pypad_live365.exemplar $(DESTDIR)$(prefix)/@RD_LIB_PATH@/rivendell/PyPAD/pypad_live365.exemplar - ../../../helpers/install_python.sh pypad_spinitron.py $(DESTDIR)$(prefix)/@RD_LIB_PATH@/rivendell/PyPAD/pypad_spinitron.py cp pypad_spinitron.exemplar $(DESTDIR)$(prefix)/@RD_LIB_PATH@/rivendell/PyPAD/pypad_spinitron.exemplar - ../../../helpers/install_python.sh pypad_udp.py $(DESTDIR)$(prefix)/@RD_LIB_PATH@/rivendell/PyPAD/pypad_udp.py cp pypad_udp.exemplar $(DESTDIR)$(prefix)/@RD_LIB_PATH@/rivendell/PyPAD/pypad_udp.exemplar ../../../helpers/install_python.sh pypad_urlwrite.py $(DESTDIR)$(prefix)/@RD_LIB_PATH@/rivendell/PyPAD/pypad_urlwrite.py @@ -38,6 +38,8 @@ install-exec-am: cp pypad_walltime.exemplar $(DESTDIR)$(prefix)/@RD_LIB_PATH@/rivendell/PyPAD/pypad_walltime.exemplar uninstall-local: + rm -f $(DESTDIR)$(prefix)/@RD_LIB_PATH@/rivendell/PyPAD/pypad_ando.exemplar + rm -f $(DESTDIR)$(prefix)/@RD_LIB_PATH@/rivendell/PyPAD/pypad_ando.py rm -f $(DESTDIR)$(prefix)/@RD_LIB_PATH@/rivendell/PyPAD/pypad_filewrite.exemplar rm -f $(DESTDIR)$(prefix)/@RD_LIB_PATH@/rivendell/PyPAD/pypad_filewrite.py rm -f $(DESTDIR)$(prefix)/@RD_LIB_PATH@/rivendell/PyPAD/pypad_live365.exemplar @@ -51,7 +53,9 @@ uninstall-local: rm -f $(DESTDIR)$(prefix)/@RD_LIB_PATH@/rivendell/PyPAD/pypad_walltime.exemplar rm -f $(DESTDIR)$(prefix)/@RD_LIB_PATH@/rivendell/PyPAD/pypad_walltime.py -EXTRA_DIST = pypad_filewrite.exemplar\ +EXTRA_DIST = pypad_ando.exemplar\ + pypad_ando.py\ + pypad_filewrite.exemplar\ pypad_filewrite.py\ pypad_live365.exemplar\ pypad_live365.py\ diff --git a/apis/PyPAD/scripts/pypad_ando.exemplar b/apis/PyPAD/scripts/pypad_ando.exemplar new file mode 100644 index 00000000..56aeb8d7 --- /dev/null +++ b/apis/PyPAD/scripts/pypad_ando.exemplar @@ -0,0 +1,99 @@ +; This is the configuration for the 'pypad_ando.py' script for +; Rivendell, which can be used to output Now & Next data to one or more +; ANDO Media Streaming systems, using one of the following formats: +; +; ^~~<duration>~<group>~<album>~<cartnum>| +; ^<artist>~<title>~<duration>~<group>~<cartnum>~<album>~<label>| + +; Section Header +; +; One section per remote ANDO system is configured, starting with 'System1' and +; working up consecutively +[System1] + +; IP Address +; +; The IP address of the remote ANDO port, in dotted-quad notation. +IpAddress=192.168.10.29 + +; UDP Port +; +; The UDP port number of the remote ANDO system, in the range 0 - 65,535. +UdpPort=5273 + +; Field Definitions. The string to use to populate the <title>, <artist>, +; <album> and <label> fields sent to ANDO each time RDAirPlay changes play +; state. These can include wildcards as placeholders for metadata values. +; For the list of supported wildcards. see the 'Metadata Wildcards' section +; of the Rivendell Operations Guide. +; +; The <label> field is optional, and should be left blank unless you know +; that your specific ANDO configuration requires it. +; +Title=%t +Artist=%a +Album=%l +Label= + +; Log Selection +; +; Set the status for each log to 'Yes', 'No' or 'Onair' to indicate whether +; state changes on that log should be output on this udp port. If set +; to 'Onair', then output will be generated only if RDAirPlay's OnAir flag +; is active. +MasterLog=Yes +Aux1Log=Yes +Aux2Log=Yes +VLog101=No +VLog102=No +VLog103=No +VLog104=No +VLog105=No +VLog106=No +VLog107=No +VLog108=No +VLog109=No +VLog110=No +VLog111=No +VLog112=No +VLog113=No +VLog114=No +VLog115=No +VLog116=No +VLog117=No +VLog118=No +VLog119=No +VLog120=No + + +; Additional ANDO systems can be configured by adding new sections... +;[System2] +;IpAddress=192.168.10.22 +;UdpPort=6789 +;Title=%u +;Artist=%a +;Album=%p +;Label= +;MasterLog=Yes +;Aux1Log=No +;Aux2Log=Onair +;VLog101=No +;VLog102=No +;VLog103=No +;VLog104=No +;VLog105=No +;VLog106=No +;VLog107=No +;VLog108=No +;VLog109=No +;VLog110=No +;VLog111=No +;VLog112=No +;VLog113=No +;VLog114=No +;VLog115=No +;VLog116=No +;VLog117=No +;VLog118=No +;VLog119=No +;VLog120=No diff --git a/apis/PyPAD/scripts/pypad_ando.py b/apis/PyPAD/scripts/pypad_ando.py new file mode 100755 index 00000000..8a3d09ea --- /dev/null +++ b/apis/PyPAD/scripts/pypad_ando.py @@ -0,0 +1,68 @@ +#!%PYTHON_BANGPATH% + +# pypad_ando.py +# +# Send PAD updates to an Ando AdInjector +# +# (C) Copyright 2018 Fred Gleason <fredg@paravelsystems.com> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public +# License along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# + +import sys +import socket +import configparser +import PyPAD + +def eprint(*args,**kwargs): + print(*args,file=sys.stderr,**kwargs) + +def ProcessPad(update): + n=1 + while(True): + section='System'+str(n) + try: + if update.shouldBeProcessed(section) and update.hasPadType(PyPAD.TYPE_NOW): + title=update.resolvePadFields(update.config().get(section,'Title'),PyPAD.ESCAPE_NONE) + artist=update.resolvePadFields(update.config().get(section,'Artist'),PyPAD.ESCAPE_NONE) + album=update.resolvePadFields(update.config().get(section,'Album'),PyPAD.ESCAPE_NONE) + label=update.resolvePadFields(update.config().get(section,'Label'),PyPAD.ESCAPE_NONE) + secs=update.padField(PyPAD.TYPE_NOW,PyPAD.FIELD_LENGTH) + duration=('%02d:' % (secs//60000))+('%02d' % ((secs%60000)//1000)) + group=update.padField(PyPAD.TYPE_NOW,PyPAD.FIELD_GROUP_NAME) + if update.config().get(section,'Label')=='': + msg='^'+artist+'~'+title+'~'+duration+'~'+group+'~'+album+'~'+str(update.padField(PyPAD.TYPE_NOW,PyPAD.FIELD_CART_NUMBER))+'|' + else: + msg='^'+artist+'~'+title+'~'+duration+'~'+group+'~'+str(update.padField(PyPAD.TYPE_NOW,PyPAD.FIELD_CART_NUMBER))+'~'+album+'~'+label+'|' + send_sock.sendto(msg.encode('utf-8'), + (update.config().get(section,'IpAddress'),int(update.config().get(section,'UdpPort')))) + n=n+1 + except configparser.NoSectionError: + return + +# +# 'Main' function +# +# Create Send Socket +# +send_sock=socket.socket(socket.AF_INET,socket.SOCK_DGRAM) + +rcvr=PyPAD.Receiver() +try: + rcvr.setConfigFile(sys.argv[3]) +except IndexError: + eprint('pypad_ando.py: you must specify a configuration file') + sys.exit(1) +rcvr.setCallback(ProcessPad) +rcvr.start(sys.argv[1],int(sys.argv[2])) diff --git a/apis/rlm/Makefile.am b/apis/rlm/Makefile.am index 02c7ae9e..cd2ef4c4 100644 --- a/apis/rlm/Makefile.am +++ b/apis/rlm/Makefile.am @@ -21,17 +21,16 @@ AM_CFLAGS = -fPIC -Wall -I../ -RLM_MODULES=rlm_ando.rlm\ - rlm_icecast2.rlm\ - rlm_inno713.rlm\ - rlm_liqcomp.rlm\ - rlm_serial.rlm\ - rlm_shoutcast1.rlm\ - rlm_spottrap.rlm\ - rlm_test.rlm\ - rlm_tunein.rlm\ - rlm_xds.rlm\ - rlm_xmpad.rlm +RLM_MODULES = rlm_icecast2.rlm\ + rlm_inno713.rlm\ + rlm_liqcomp.rlm\ + rlm_serial.rlm\ + rlm_shoutcast1.rlm\ + rlm_spottrap.rlm\ + rlm_test.rlm\ + rlm_tunein.rlm\ + rlm_xds.rlm\ + rlm_xmpad.rlm all: $(RLM_MODULES) @@ -52,7 +51,6 @@ header_HEADERS = rlm.h EXTRA_DIST = Makefile-example\ rlm.h\ - rlm_ando.c\ rlm_icecast2.c\ rlm_inno713.c\ rlm_liqcomp.c\ diff --git a/apis/rlm/rlm_ando.c b/apis/rlm/rlm_ando.c deleted file mode 100644 index 2fb15e19..00000000 --- a/apis/rlm/rlm_ando.c +++ /dev/null @@ -1,458 +0,0 @@ -/* 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_vlog101s; -int *rlm_ando_vlog102s; -int *rlm_ando_vlog103s; -int *rlm_ando_vlog104s; -int *rlm_ando_vlog105s; -int *rlm_ando_vlog106s; -int *rlm_ando_vlog107s; -int *rlm_ando_vlog108s; -int *rlm_ando_vlog109s; -int *rlm_ando_vlog110s; -int *rlm_ando_vlog111s; -int *rlm_ando_vlog112s; -int *rlm_ando_vlog113s; -int *rlm_ando_vlog114s; -int *rlm_ando_vlog115s; -int *rlm_ando_vlog116s; -int *rlm_ando_vlog117s; -int *rlm_ando_vlog118s; -int *rlm_ando_vlog119s; -int *rlm_ando_vlog120s; - -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; - rlm_ando_vlog101s=NULL; - rlm_ando_vlog102s=NULL; - rlm_ando_vlog103s=NULL; - rlm_ando_vlog104s=NULL; - rlm_ando_vlog105s=NULL; - rlm_ando_vlog106s=NULL; - rlm_ando_vlog107s=NULL; - rlm_ando_vlog108s=NULL; - rlm_ando_vlog109s=NULL; - rlm_ando_vlog110s=NULL; - rlm_ando_vlog111s=NULL; - rlm_ando_vlog112s=NULL; - rlm_ando_vlog113s=NULL; - rlm_ando_vlog114s=NULL; - rlm_ando_vlog115s=NULL; - rlm_ando_vlog116s=NULL; - rlm_ando_vlog117s=NULL; - rlm_ando_vlog118s=NULL; - rlm_ando_vlog119s=NULL; - rlm_ando_vlog120s=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"); - - rlm_ando_vlog101s=realloc(rlm_ando_vlog101s, - (rlm_ando_devs+1)*sizeof(int)); - rlm_ando_vlog101s[rlm_ando_devs]= - rlm_ando_GetLogStatus(ptr,arg,section,"VLog101"); - - rlm_ando_vlog102s=realloc(rlm_ando_vlog102s, - (rlm_ando_devs+1)*sizeof(int)); - rlm_ando_vlog102s[rlm_ando_devs]= - rlm_ando_GetLogStatus(ptr,arg,section,"VLog102"); - - rlm_ando_vlog103s=realloc(rlm_ando_vlog103s, - (rlm_ando_devs+1)*sizeof(int)); - rlm_ando_vlog103s[rlm_ando_devs]= - rlm_ando_GetLogStatus(ptr,arg,section,"VLog103"); - - rlm_ando_vlog104s=realloc(rlm_ando_vlog104s, - (rlm_ando_devs+1)*sizeof(int)); - rlm_ando_vlog104s[rlm_ando_devs]= - rlm_ando_GetLogStatus(ptr,arg,section,"VLog104"); - - rlm_ando_vlog105s=realloc(rlm_ando_vlog105s, - (rlm_ando_devs+1)*sizeof(int)); - rlm_ando_vlog105s[rlm_ando_devs]= - rlm_ando_GetLogStatus(ptr,arg,section,"VLog105"); - - rlm_ando_vlog106s=realloc(rlm_ando_vlog106s, - (rlm_ando_devs+1)*sizeof(int)); - rlm_ando_vlog106s[rlm_ando_devs]= - rlm_ando_GetLogStatus(ptr,arg,section,"VLog106"); - - rlm_ando_vlog107s=realloc(rlm_ando_vlog107s, - (rlm_ando_devs+1)*sizeof(int)); - rlm_ando_vlog107s[rlm_ando_devs]= - rlm_ando_GetLogStatus(ptr,arg,section,"VLog107"); - - rlm_ando_vlog108s=realloc(rlm_ando_vlog108s, - (rlm_ando_devs+1)*sizeof(int)); - rlm_ando_vlog108s[rlm_ando_devs]= - rlm_ando_GetLogStatus(ptr,arg,section,"VLog108"); - - rlm_ando_vlog109s=realloc(rlm_ando_vlog109s, - (rlm_ando_devs+1)*sizeof(int)); - rlm_ando_vlog109s[rlm_ando_devs]= - rlm_ando_GetLogStatus(ptr,arg,section,"VLog109"); - - rlm_ando_vlog110s=realloc(rlm_ando_vlog110s, - (rlm_ando_devs+1)*sizeof(int)); - rlm_ando_vlog110s[rlm_ando_devs]= - rlm_ando_GetLogStatus(ptr,arg,section,"VLog110"); - - rlm_ando_vlog111s=realloc(rlm_ando_vlog111s, - (rlm_ando_devs+1)*sizeof(int)); - rlm_ando_vlog111s[rlm_ando_devs]= - rlm_ando_GetLogStatus(ptr,arg,section,"VLog111"); - - rlm_ando_vlog112s=realloc(rlm_ando_vlog112s, - (rlm_ando_devs+1)*sizeof(int)); - rlm_ando_vlog112s[rlm_ando_devs]= - rlm_ando_GetLogStatus(ptr,arg,section,"VLog112"); - - rlm_ando_vlog113s=realloc(rlm_ando_vlog113s, - (rlm_ando_devs+1)*sizeof(int)); - rlm_ando_vlog113s[rlm_ando_devs]= - rlm_ando_GetLogStatus(ptr,arg,section,"VLog113"); - - rlm_ando_vlog114s=realloc(rlm_ando_vlog114s, - (rlm_ando_devs+1)*sizeof(int)); - rlm_ando_vlog114s[rlm_ando_devs]= - rlm_ando_GetLogStatus(ptr,arg,section,"VLog114"); - - rlm_ando_vlog115s=realloc(rlm_ando_vlog115s, - (rlm_ando_devs+1)*sizeof(int)); - rlm_ando_vlog115s[rlm_ando_devs]= - rlm_ando_GetLogStatus(ptr,arg,section,"VLog115"); - - rlm_ando_vlog116s=realloc(rlm_ando_vlog116s, - (rlm_ando_devs+1)*sizeof(int)); - rlm_ando_vlog116s[rlm_ando_devs]= - rlm_ando_GetLogStatus(ptr,arg,section,"VLog116"); - - rlm_ando_vlog117s=realloc(rlm_ando_vlog117s, - (rlm_ando_devs+1)*sizeof(int)); - rlm_ando_vlog117s[rlm_ando_devs]= - rlm_ando_GetLogStatus(ptr,arg,section,"VLog117"); - - rlm_ando_vlog118s=realloc(rlm_ando_vlog118s, - (rlm_ando_devs+1)*sizeof(int)); - rlm_ando_vlog118s[rlm_ando_devs]= - rlm_ando_GetLogStatus(ptr,arg,section,"VLog118"); - - rlm_ando_vlog119s=realloc(rlm_ando_vlog119s, - (rlm_ando_devs+1)*sizeof(int)); - rlm_ando_vlog119s[rlm_ando_devs]= - rlm_ando_GetLogStatus(ptr,arg,section,"VLog119"); - - rlm_ando_vlog120s=realloc(rlm_ando_vlog120s, - (rlm_ando_devs+1)*sizeof(int)); - rlm_ando_vlog120s[rlm_ando_devs]= - rlm_ando_GetLogStatus(ptr,arg,section,"VLog120"); - - 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); - free(rlm_ando_vlog101s); - free(rlm_ando_vlog102s); - free(rlm_ando_vlog103s); - free(rlm_ando_vlog104s); - free(rlm_ando_vlog105s); - free(rlm_ando_vlog106s); - free(rlm_ando_vlog107s); - free(rlm_ando_vlog108s); - free(rlm_ando_vlog109s); - free(rlm_ando_vlog110s); - free(rlm_ando_vlog111s); - free(rlm_ando_vlog112s); - free(rlm_ando_vlog113s); - free(rlm_ando_vlog114s); - free(rlm_ando_vlog115s); - free(rlm_ando_vlog116s); - free(rlm_ando_vlog117s); - free(rlm_ando_vlog118s); - free(rlm_ando_vlog119s); - free(rlm_ando_vlog120s); -} - - -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; - - case 100: - flag=rlm_ando_vlog101s[i]; - break; - - case 101: - flag=rlm_ando_vlog102s[i]; - break; - - case 102: - flag=rlm_ando_vlog103s[i]; - break; - - case 103: - flag=rlm_ando_vlog104s[i]; - break; - - case 104: - flag=rlm_ando_vlog105s[i]; - break; - - case 105: - flag=rlm_ando_vlog106s[i]; - break; - - case 106: - flag=rlm_ando_vlog107s[i]; - break; - - case 107: - flag=rlm_ando_vlog108s[i]; - break; - - case 108: - flag=rlm_ando_vlog109s[i]; - break; - - case 109: - flag=rlm_ando_vlog110s[i]; - break; - - case 110: - flag=rlm_ando_vlog111s[i]; - break; - - case 111: - flag=rlm_ando_vlog112s[i]; - break; - - case 112: - flag=rlm_ando_vlog113s[i]; - break; - - case 113: - flag=rlm_ando_vlog114s[i]; - break; - - case 114: - flag=rlm_ando_vlog115s[i]; - break; - - case 115: - flag=rlm_ando_vlog116s[i]; - break; - - case 116: - flag=rlm_ando_vlog117s[i]; - break; - - case 117: - flag=rlm_ando_vlog118s[i]; - break; - - case 118: - flag=rlm_ando_vlog119s[i]; - break; - - case 119: - flag=rlm_ando_vlog120s[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; - } -}