mirror of
https://github.com/ElvishArtisan/rivendell.git
synced 2026-01-11 23:25:57 +01:00
Merge remote-tracking branch 'upstream/rlm2' into rlm2
Conflicts: ChangeLog
This commit is contained in:
@@ -21,7 +21,8 @@
|
||||
## Use automake to process this into a Makefile.in
|
||||
|
||||
SUBDIRS = api\
|
||||
examples
|
||||
examples\
|
||||
tests
|
||||
|
||||
CLEANFILES = *~\
|
||||
*.idb\
|
||||
|
||||
@@ -23,6 +23,10 @@
|
||||
rivendelldir = $(pyexecdir)
|
||||
rivendell_PYTHON = PyPAD.py
|
||||
|
||||
##install-exec-am:
|
||||
## ../../../helpers/install_python.sh PyPAD.py $(pyexecdir)/PyPAD.py
|
||||
##EXTRA_DIST = PyPAD.py
|
||||
|
||||
CLEANFILES = *~\
|
||||
*.idb\
|
||||
*ilk\
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
# PyPAD.py
|
||||
#
|
||||
# PAD processor for Rivendell
|
||||
@@ -46,6 +44,7 @@ TYPE_NEXT='next'
|
||||
FIELD_START_DATETIME='startDateTime'
|
||||
FIELD_CART_NUMBER='cartNumber'
|
||||
FIELD_CART_TYPE='cartType'
|
||||
FIELD_CUT_NUMBER='cutNumber'
|
||||
FIELD_LENGTH='length'
|
||||
FIELD_YEAR='year'
|
||||
FIELD_GROUP_NAME='groupName'
|
||||
@@ -128,7 +127,7 @@ class Update(object):
|
||||
|
||||
def __replaceWildcard(self,wildcard,sfield,stype,string,esc):
|
||||
try:
|
||||
if isinstance(self.__fields['padUpdate'][stype][sfield],unicode):
|
||||
if isinstance(self.__fields['padUpdate'][stype][sfield],str):
|
||||
string=string.replace('%'+wildcard,self.escape(self.__fields['padUpdate'][stype][sfield],esc))
|
||||
else:
|
||||
string=string.replace('%'+wildcard,str(self.__fields['padUpdate'][stype][sfield]))
|
||||
@@ -164,19 +163,9 @@ class Update(object):
|
||||
dt_pattern=pattern[3:-1]
|
||||
|
||||
try:
|
||||
dt_pattern=dt_pattern.replace('dddd',dt.strftime('%A'))
|
||||
dt_pattern=dt_pattern.replace('ddd',dt.strftime('%a'))
|
||||
dt_pattern=dt_pattern.replace('dd',dt.strftime('%d'))
|
||||
dt_pattern=dt_pattern.replace('d',str(dt.day))
|
||||
|
||||
dt_pattern=dt_pattern.replace('MMMM',dt.strftime('%B'))
|
||||
dt_pattern=dt_pattern.replace('MMM',dt.strftime('%b'))
|
||||
dt_pattern=dt_pattern.replace('MM',dt.strftime('%m'))
|
||||
dt_pattern=dt_pattern.replace('M',str(dt.month))
|
||||
|
||||
dt_pattern=dt_pattern.replace('yyyy',dt.strftime('%Y'))
|
||||
dt_pattern=dt_pattern.replace('yy',dt.strftime('%y'))
|
||||
|
||||
#
|
||||
# Process Times
|
||||
#
|
||||
miltime=(dt_pattern.find('ap')<0)and(dt_pattern.find('AP')<0)
|
||||
if not miltime:
|
||||
if dt.hour<13:
|
||||
@@ -200,6 +189,23 @@ class Update(object):
|
||||
|
||||
dt_pattern=dt_pattern.replace('ss',dt.strftime('%S'))
|
||||
dt_pattern=dt_pattern.replace('s',str(dt.second))
|
||||
|
||||
#
|
||||
# Process Dates
|
||||
#
|
||||
dt_pattern=dt_pattern.replace('MMMM',dt.strftime('%B'))
|
||||
dt_pattern=dt_pattern.replace('MMM',dt.strftime('%b'))
|
||||
dt_pattern=dt_pattern.replace('MM',dt.strftime('%m'))
|
||||
dt_pattern=dt_pattern.replace('M',str(dt.month))
|
||||
|
||||
dt_pattern=dt_pattern.replace('dddd',dt.strftime('%A'))
|
||||
dt_pattern=dt_pattern.replace('ddd',dt.strftime('%a'))
|
||||
dt_pattern=dt_pattern.replace('dd',dt.strftime('%d'))
|
||||
dt_pattern=dt_pattern.replace('d',str(dt.day))
|
||||
|
||||
dt_pattern=dt_pattern.replace('yyyy',dt.strftime('%Y'))
|
||||
dt_pattern=dt_pattern.replace('yy',dt.strftime('%y'))
|
||||
|
||||
except AttributeError:
|
||||
string=string.replace(pattern,'')
|
||||
return string
|
||||
@@ -226,7 +232,7 @@ class Update(object):
|
||||
"""
|
||||
Returns the date-time of the PAD update (datetime)
|
||||
"""
|
||||
return self.__fromIso8601(pad_data['padUpdate']['dateTime'])
|
||||
return self.__fromIso8601(self.__fields['padUpdate']['dateTime'])
|
||||
|
||||
def escape(self,string,esc):
|
||||
"""
|
||||
@@ -252,12 +258,33 @@ class Update(object):
|
||||
return self.__escapeJson(string)
|
||||
raise ValueError('invalid esc value')
|
||||
|
||||
def logMachine(self):
|
||||
def hostName(self):
|
||||
"""
|
||||
Returns the host name of the machine whence this PAD update
|
||||
originated (string).
|
||||
"""
|
||||
return self.__fields['padUpdate']['hostName']
|
||||
|
||||
def shortHostName(self):
|
||||
"""
|
||||
Returns the short host name of the machine whence this PAD update
|
||||
originated (string).
|
||||
"""
|
||||
return self.__fields['padUpdate']['shortHostName']
|
||||
|
||||
def machine(self):
|
||||
"""
|
||||
Returns the log machine number to which this update pertains
|
||||
(integer).
|
||||
"""
|
||||
return self.__fields['padUpdate']['logMachine']
|
||||
return self.__fields['padUpdate']['machine']
|
||||
|
||||
def mode(self):
|
||||
"""
|
||||
Returns the operating mode of the host log machine to which
|
||||
this update pertains (string).
|
||||
"""
|
||||
return self.__fields['padUpdate']['mode']
|
||||
|
||||
def onairFlag(self):
|
||||
"""
|
||||
@@ -411,6 +438,8 @@ class Update(object):
|
||||
PyPAD.FIELD_CLIENT - The 'Client' field (string)
|
||||
PyPAD.FIELD_COMPOSER - The 'Composer' field (string)
|
||||
PyPAD.FIELD_CONDUCTOR - The 'Conductor' field (string)
|
||||
PyPAD.FIELD_CUT_NUMER - The 'Cut Number' field
|
||||
(integer)
|
||||
PyPAD.FIELD_DESCRIPTION - The 'Description' field
|
||||
(string)
|
||||
PyPAD.FIELD_EXTERNAL_ANNC_TYPE - The 'EXT_ANNC_TYPE'
|
||||
@@ -437,8 +466,197 @@ class Update(object):
|
||||
"""
|
||||
return self.__fields['padUpdate'][pad_type][pad_field]
|
||||
|
||||
def resolveFilepath(self,string,dt):
|
||||
"""
|
||||
Returns a string with any Rivendell Filepath wildcards resolved
|
||||
(See Appdendix C of the Rivendell Operations Guide for a list).
|
||||
Takes two arguments:
|
||||
|
||||
string - The string to resolve.
|
||||
|
||||
dt - A Python 'datetime' object to use for the resolution.
|
||||
"""
|
||||
ret=''
|
||||
upper_case=False
|
||||
initial_case=False
|
||||
offset=0
|
||||
i=0
|
||||
|
||||
while i<len(string):
|
||||
field=''
|
||||
offset=0;
|
||||
if string[i]!='%':
|
||||
ret+=string[i]
|
||||
else:
|
||||
i=i+1
|
||||
offset=offset+1
|
||||
if string[i]=='^':
|
||||
upper_case=True
|
||||
i=i+1
|
||||
offset=offset+1
|
||||
else:
|
||||
upper_case=False
|
||||
|
||||
if string[i]=='$':
|
||||
initial_case=True
|
||||
i=i+1
|
||||
offset=offset+1
|
||||
else:
|
||||
initial_case=False
|
||||
|
||||
found=False
|
||||
if string[i]=='a': # Abbreviated weekday name
|
||||
field=dt.strftime('%a').lower()
|
||||
found=True
|
||||
|
||||
if string[i]=='A': # Full weekday name
|
||||
field=dt.strftime('%A').lower()
|
||||
found=True
|
||||
|
||||
if (string[i]=='b') or (string[i]=='h'): # Abrev. month Name
|
||||
field=dt.strftime('%b').lower()
|
||||
found=True
|
||||
|
||||
if string[i]=='B': # Full month name
|
||||
field=dt.strftime('%B').lower()
|
||||
found=True
|
||||
|
||||
if string[i]=='C': # Century
|
||||
field=dt.strftime('%C').lower()
|
||||
found=True
|
||||
|
||||
if string[i]=='d': # Day (01 - 31)
|
||||
field='%02d' % dt.day
|
||||
found=True
|
||||
|
||||
if string[i]=='D': # Date (mm-dd-yy)
|
||||
field=dt.strftime('%m-%d-%y')
|
||||
found=True
|
||||
|
||||
if string[i]=='e': # Day, padded ( 1 - 31)
|
||||
field='%2d' % dt.day
|
||||
found=True
|
||||
|
||||
if string[i]=='E': # Day, unpadded (1 - 31)
|
||||
field='%d' % dt.day
|
||||
found=True
|
||||
|
||||
if string[i]=='F': # Date (yyyy-mm-dd)
|
||||
field=dt.strftime('%F')
|
||||
found=True
|
||||
|
||||
if string[i]=='g': # Two digit year number (as per ISO 8601)
|
||||
field=dt.strftime('%g').lower()
|
||||
found=True
|
||||
|
||||
if string[i]=='G': # Four digit year number (as per ISO 8601)
|
||||
field=dt.strftime('%G').lower()
|
||||
found=True
|
||||
|
||||
if string[i]=='H': # Hour, zero padded, 24 hour
|
||||
field=dt.strftime('%H').lower()
|
||||
found=True
|
||||
|
||||
if string[i]=='I': # Hour, zero padded, 12 hour
|
||||
field=dt.strftime('%I').lower()
|
||||
found=True
|
||||
|
||||
if string[i]=='i': # Hour, space padded, 12 hour
|
||||
hour=dt.hour
|
||||
if hour>12:
|
||||
hour=hour-12
|
||||
if hour==0:
|
||||
hour=12
|
||||
field='%2d' % hour
|
||||
found=True
|
||||
|
||||
if string[i]=='J': # Hour, unpadded, 12 hour
|
||||
hour=dt.hour
|
||||
if hour>12:
|
||||
hour=hour-12
|
||||
if hour==0:
|
||||
hour=12
|
||||
field=str(hour)
|
||||
found=True
|
||||
|
||||
if string[i]=='j': # Day of year
|
||||
field=dt.strftime('%j')
|
||||
found=True
|
||||
|
||||
if string[i]=='k': # Hour, space padded, 24 hour
|
||||
field=dt.strftime('%k')
|
||||
found=True
|
||||
|
||||
if string[i]=='M': # Minute, zero padded
|
||||
field=dt.strftime('%M')
|
||||
found=True
|
||||
|
||||
if string[i]=='m': # Month (01 - 12)
|
||||
field=dt.strftime('%m')
|
||||
found=True
|
||||
|
||||
if string[i]=='p': # AM/PM string
|
||||
field=dt.strftime('%p')
|
||||
found=True
|
||||
|
||||
if string[i]=='r': # Rivendell host name
|
||||
field=self.hostName()
|
||||
found=True
|
||||
|
||||
if string[i]=='R': # Rivendell short host name
|
||||
field=self.shortHostName()
|
||||
found=True
|
||||
|
||||
if string[i]=='S': # Second (SS)
|
||||
field=dt.strftime('%S')
|
||||
found=True
|
||||
|
||||
if string[i]=='s': # Rivendell service name
|
||||
if self.hasService():
|
||||
field=self.serviceName()
|
||||
else:
|
||||
field=''
|
||||
found=True
|
||||
|
||||
if string[i]=='u': # Day of week (numeric, 1..7, 1=Monday)
|
||||
field=dt.strftime('%u')
|
||||
found=True
|
||||
|
||||
if (string[i]=='V') or (string[i]=='W'): # Week # (as per ISO 8601)
|
||||
field=dt.strftime('%V')
|
||||
found=True
|
||||
|
||||
if string[i]=='w': # Day of week (numeric, 0..6, 0=Sunday)
|
||||
field=dt.strftime('%w')
|
||||
found=True
|
||||
|
||||
if string[i]=='y': # Year (yy)
|
||||
field=dt.strftime('%y')
|
||||
found=True
|
||||
|
||||
if string[i]=='Y': # Year (yyyy)
|
||||
field=dt.strftime('%Y')
|
||||
found=True
|
||||
|
||||
if string[i]=='%':
|
||||
field='%'
|
||||
found=True
|
||||
|
||||
if not found: # No recognized wildcard, rollback!
|
||||
i=-offset
|
||||
field=string[i]
|
||||
|
||||
if upper_case:
|
||||
field=field.upper();
|
||||
if initial_case:
|
||||
field=field[0].upper()+field[1::]
|
||||
ret+=field
|
||||
upper_case=False
|
||||
initial_case=False
|
||||
i=i+1
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
class Receiver(object):
|
||||
def __init__(self):
|
||||
@@ -467,18 +685,18 @@ class Receiver(object):
|
||||
"""
|
||||
sock=socket.socket(socket.AF_INET)
|
||||
conn=sock.connect((hostname,port))
|
||||
c=""
|
||||
line=""
|
||||
c=bytes()
|
||||
line=bytes()
|
||||
msg=""
|
||||
|
||||
while 1<2:
|
||||
c=sock.recv(1)
|
||||
line+=c
|
||||
if c[0]=="\n":
|
||||
msg+=line
|
||||
if line=="\r\n":
|
||||
if c[0]==10:
|
||||
msg+=line.decode('utf-8')
|
||||
if line.decode('utf-8')=="\r\n":
|
||||
self.__PyPAD_Process(Update(json.loads(msg)))
|
||||
msg=""
|
||||
line=""
|
||||
line=bytes()
|
||||
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
## Use automake to process this into a Makefile.in
|
||||
|
||||
EXTRA_DIST = now_and_next.py\
|
||||
pypad_filewrite.py\
|
||||
pypad_udp.py
|
||||
|
||||
CLEANFILES = *~\
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/python
|
||||
#%PYTHON_BANGPATH%
|
||||
|
||||
# now_and_next.py
|
||||
#
|
||||
@@ -36,14 +36,16 @@ import PyPAD
|
||||
#
|
||||
def ProcessPad(update):
|
||||
print
|
||||
print('Filepath: '+update.resolveFilepath('string %$a',update.dateTime()))
|
||||
|
||||
if update.hasPadType(PyPAD.TYPE_NOW):
|
||||
print "Log %03d NOW: " % update.logMachine()+update.resolvePadFields("%a - %t",PyPAD.ESCAPE_NONE)
|
||||
print("Log %03d NOW: " % update.machine()+update.resolvePadFields("%a - %t",PyPAD.ESCAPE_NONE))
|
||||
else:
|
||||
print "Log %03d NOW: [none]" % update.logMachine()
|
||||
print("Log %03d NOW: [none]" % update.machine())
|
||||
if update.hasPadType(PyPAD.TYPE_NEXT):
|
||||
print "Log %03d NEXT: " % update.logMachine()+update.resolvePadFields("%A - %T",PyPAD.ESCAPE_NONE)
|
||||
print("Log %03d NEXT: " % update.machine()+update.resolvePadFields("%A - %T",PyPAD.ESCAPE_NONE))
|
||||
else:
|
||||
print "Log %03d NEXT: [none]" % update.logMachine()
|
||||
print("Log %03d NEXT: [none]" % update.machine())
|
||||
|
||||
#
|
||||
# Create an instance of 'PyPADReceiver'
|
||||
|
||||
88
apis/PyPAD/examples/pypad_filewrite.py
Executable file
88
apis/PyPAD/examples/pypad_filewrite.py
Executable file
@@ -0,0 +1,88 @@
|
||||
#%PYTHON_BANGPATH%
|
||||
|
||||
# pypad_filewrite.py
|
||||
#
|
||||
# Write PAD updates to files
|
||||
#
|
||||
# (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 configparser
|
||||
import PyPAD
|
||||
|
||||
def eprint(*args,**kwargs):
|
||||
print(*args,file=sys.stderr,**kwargs)
|
||||
|
||||
def processUpdate(update,section):
|
||||
try:
|
||||
if config.get(section,'ProcessNullUpdates')=='0':
|
||||
return True
|
||||
if config.get(section,'ProcessNullUpdates')=='1':
|
||||
return update.hasPadType(PyPAD.TYPE_NOW)
|
||||
if config.get(section,'ProcessNullUpdates')=='2':
|
||||
return update.hasPadType(PyPAD.TYPE_NEXT)
|
||||
if config.get(section,'ProcessNullUpdates')=='3':
|
||||
return update.hasPadType(PyPAD.TYPE_NOW) and update.hasPadType(PyPAD.TYPE_NEXT)
|
||||
except configparser.NoOptionError:
|
||||
return True
|
||||
|
||||
log_dict={1: 'MasterLog',2: 'Aux1Log',3: 'Aux2Log',
|
||||
101: 'VLog101',102: 'VLog102',103: 'VLog103',104: 'VLog104',
|
||||
105: 'VLog105',106: 'VLog106',107: 'VLog107',108: 'VLog108',
|
||||
109: 'VLog109',110: 'VLog110',111: 'VLog111',112: 'VLog112',
|
||||
113: 'VLog113',114: 'VLog114',115: 'VLog115',116: 'VLog116',
|
||||
117: 'VLog117',118: 'VLog118',119: 'VLog119',120: 'VLog120'}
|
||||
if config.get(section,log_dict[update.machine()]).lower()=='yes':
|
||||
return True
|
||||
if config.get(section,log_dict[update.machine()]).lower()=='no':
|
||||
return False
|
||||
if config.get(section,log_dict[update.machine()]).lower()=='onair':
|
||||
return update.onairFlag()
|
||||
|
||||
def ProcessPad(update):
|
||||
n=1
|
||||
try:
|
||||
while(True):
|
||||
section='File'+str(n)
|
||||
if processUpdate(update,section):
|
||||
fmtstr=config.get(section,'FormatString')
|
||||
mode='w'
|
||||
if config.get(section,'Append')=='1':
|
||||
mode='a'
|
||||
f=open(update.resolveFilepath(config.get(section,'Filename'),update.dateTime()),mode)
|
||||
f.write(update.resolvePadFields(fmtstr,int(config.get(section,'Encoding'))))
|
||||
f.close()
|
||||
n=n+1
|
||||
|
||||
except configparser.NoSectionError:
|
||||
return
|
||||
|
||||
#
|
||||
# Read Configuration
|
||||
#
|
||||
if len(sys.argv)>=2:
|
||||
fp=open(sys.argv[1])
|
||||
config=configparser.ConfigParser(interpolation=None)
|
||||
config.readfp(fp)
|
||||
fp.close()
|
||||
else:
|
||||
eprint('pypad_filewrite.py: you must specify a configuration file')
|
||||
sys.exit(1)
|
||||
|
||||
rcvr=PyPAD.Receiver()
|
||||
rcvr.setCallback(ProcessPad)
|
||||
rcvr.start('localhost',PyPAD.PAD_TCP_PORT)
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/python
|
||||
#%PYTHON_BANGPATH%
|
||||
|
||||
# pypad_udp.py
|
||||
#
|
||||
@@ -20,26 +20,48 @@
|
||||
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
#
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import sys
|
||||
import socket
|
||||
import ConfigParser
|
||||
import configparser
|
||||
import PyPAD
|
||||
|
||||
def eprint(*args,**kwargs):
|
||||
print(*args,file=sys.stderr,**kwargs)
|
||||
|
||||
def processUpdate(update,section):
|
||||
if config.get(section,'ProcessNullUpdates')=='0':
|
||||
return True
|
||||
if config.get(section,'ProcessNullUpdates')=='1':
|
||||
return update.hasPadType(PyPAD.TYPE_NOW)
|
||||
if config.get(section,'ProcessNullUpdates')=='2':
|
||||
return update.hasPadType(PyPAD.TYPE_NEXT)
|
||||
if config.get(section,'ProcessNullUpdates')=='3':
|
||||
return update.hasPadType(PyPAD.TYPE_NOW) and update.hasPadType(PyPAD.TYPE_NEXT)
|
||||
|
||||
log_dict={1: 'MasterLog',2: 'Aux1Log',3: 'Aux2Log',
|
||||
101: 'VLog101',102: 'VLog102',103: 'VLog103',104: 'VLog104',
|
||||
105: 'VLog105',106: 'VLog106',107: 'VLog107',108: 'VLog108',
|
||||
109: 'VLog109',110: 'VLog110',111: 'VLog111',112: 'VLog112',
|
||||
113: 'VLog113',114: 'VLog114',115: 'VLog115',116: 'VLog116',
|
||||
117: 'VLog117',118: 'VLog118',119: 'VLog119',120: 'VLog120'}
|
||||
if config.get(section,log_dict[update.machine()]).lower()=='yes':
|
||||
return True
|
||||
if config.get(section,log_dict[update.machine()]).lower()=='no':
|
||||
return False
|
||||
if config.get(section,log_dict[update.machine()]).lower()=='onair':
|
||||
return update.onairFlag()
|
||||
|
||||
def ProcessPad(update):
|
||||
n=1
|
||||
while(True):
|
||||
section='Udp'+str(n)
|
||||
try:
|
||||
fmtstr=config.get(section,'FormatString')
|
||||
send_sock.sendto(update.resolvePadFields(fmtstr,int(config.get(section,'Encoding'))),
|
||||
(config.get(section,'IpAddress'),int(config.get(section,'UdpPort'))))
|
||||
if processUpdate(update,section):
|
||||
fmtstr=config.get(section,'FormatString')
|
||||
send_sock.sendto(update.resolvePadFields(fmtstr,int(config.get(section,'Encoding'))).encode('utf-8'),
|
||||
(config.get(section,'IpAddress'),int(config.get(section,'UdpPort'))))
|
||||
n=n+1
|
||||
except ConfigParser.NoSectionError:
|
||||
except configparser.NoSectionError:
|
||||
return
|
||||
|
||||
#
|
||||
@@ -47,7 +69,7 @@ def ProcessPad(update):
|
||||
#
|
||||
if len(sys.argv)>=2:
|
||||
fp=open(sys.argv[1])
|
||||
config=ConfigParser.ConfigParser()
|
||||
config=configparser.ConfigParser(interpolation=None)
|
||||
config.readfp(fp)
|
||||
fp.close()
|
||||
else:
|
||||
|
||||
39
apis/PyPAD/tests/Makefile.am
Normal file
39
apis/PyPAD/tests/Makefile.am
Normal file
@@ -0,0 +1,39 @@
|
||||
## automake.am
|
||||
##
|
||||
## Automake.am for Rivendell PyPAD/tests
|
||||
##
|
||||
## (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 as
|
||||
## published by the Free Software Foundation; either version 2 of
|
||||
## the License, or (at your option) any later version.
|
||||
##
|
||||
## 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
|
||||
|
||||
EXTRA_DIST = filepath_test.py
|
||||
pad_test.py
|
||||
|
||||
CLEANFILES = *~\
|
||||
*.idb\
|
||||
*ilk\
|
||||
*.obj\
|
||||
*.pdb\
|
||||
*.qm\
|
||||
moc_*
|
||||
|
||||
MAINTAINERCLEANFILES = *~\
|
||||
*.tar.gz\
|
||||
aclocal.m4\
|
||||
configure\
|
||||
Makefile.in\
|
||||
moc_*
|
||||
78
apis/PyPAD/tests/filepath_test.py
Executable file
78
apis/PyPAD/tests/filepath_test.py
Executable file
@@ -0,0 +1,78 @@
|
||||
#%PYTHON_BANGPATH%
|
||||
|
||||
# filepath_test.py
|
||||
#
|
||||
# PyPAD regression test script for Rivendell
|
||||
#
|
||||
# Exercise every filepath wildcard in 'PyPAD.Update::resolveFilepath()'
|
||||
#
|
||||
# (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 PyPAD
|
||||
|
||||
def ProcessPad(update):
|
||||
print()
|
||||
print('DateTime: '+update.dateTime().isoformat(' '))
|
||||
print()
|
||||
print('Abbreviated weekday name [%a | %$a | %^a]: '+update.resolveFilepath('%a | %$a | %^a',update.dateTime()))
|
||||
print('Full weekday name [%A | %$A | %^A]: '+update.resolveFilepath('%A | %$A | %^A',update.dateTime()))
|
||||
print('Abbreviated month name [%b | %$b | %^b]: '+update.resolveFilepath('%b | %$b | %^b',update.dateTime()))
|
||||
print('Full month name [%B | %$B | %^B]: '+update.resolveFilepath('%B | %$B | %^B',update.dateTime()))
|
||||
print('Century [%C | %$C | %^C]: '+update.resolveFilepath('%C | %$C | %^C',update.dateTime()))
|
||||
print('Day of the month, zero padded [01 - 31] [%d | %$d | %^d]: '+update.resolveFilepath('%d | %$d | %^d',update.dateTime()))
|
||||
print('Date (mm-dd-yy) [%D | %$D | %^D]: '+update.resolveFilepath('%D | %$D | %^D',update.dateTime()))
|
||||
print('Day of the month, space padded [ 1 - 31] [%e | %$e | %^e]: '+update.resolveFilepath('%e | %$e | %^e',update.dateTime()))
|
||||
print('Day of the month, unpadded [ 1 - 31] [%E | %$E | %^E]: '+update.resolveFilepath('%E | %$E | %^E',update.dateTime()))
|
||||
print('Date (yyyy-mm-dd) [%F | %$F | %^F]: '+update.resolveFilepath('%F | %$F | %^F',update.dateTime()))
|
||||
print('Two digit year [%g | %$g | %^g]: '+update.resolveFilepath('%g | %$g | %^g',update.dateTime()))
|
||||
print('Four digit year [%G | %$G | %^G]: '+update.resolveFilepath('%G | %$G | %^G',update.dateTime()))
|
||||
print('Abbreviated month name [%h | %$h | %^h]: '+update.resolveFilepath('%h | %$h | %^h',update.dateTime()))
|
||||
print('Hour, 24 hour, zero padded [00 - 23] [%H | %$H | %^H]: '+update.resolveFilepath('%H | %$H | %^H',update.dateTime()))
|
||||
print('Hour, 12 hour, space padded [00 - 23] [%i | %$i | %^i]: '+update.resolveFilepath('%i | %$i | %^i',update.dateTime()))
|
||||
print('Hour, 12 hour, zero padded [00 - 23] [%I | %$I | %^I]: '+update.resolveFilepath('%I | %$I | %^I',update.dateTime()))
|
||||
print('Day of year, zero padded [%j | %$j | %^j]: '+update.resolveFilepath('%j | %$j | %^j',update.dateTime()))
|
||||
print('Hour, 12 hour, unpadded [00 - 23] [%J | %$J | %^J]: '+update.resolveFilepath('%J | %$J | %^J',update.dateTime()))
|
||||
print('Hour, 24 hour, space padded [%k | %$k | %^k]: '+update.resolveFilepath('%k | %$k | %^k',update.dateTime()))
|
||||
print('Month, zero padded (01 - 12) [%m | %$m | %^m]: '+update.resolveFilepath('%m | %$m | %^m',update.dateTime()))
|
||||
print('Minute, zero padded (00 - 59) [%M | %$M | %^M]: '+update.resolveFilepath('%M | %$M | %^M',update.dateTime()))
|
||||
print('AM/PM string [%p | %$p | %^p]: '+update.resolveFilepath('%p | %$p | %^p',update.dateTime()))
|
||||
print('Rivendell host name [%r | %$r | %^r]: '+update.resolveFilepath('%r | %$r | %^r',update.dateTime()))
|
||||
print('Rivendell short host name [%R | %$R | %^R]: '+update.resolveFilepath('%R | %$R | %^R',update.dateTime()))
|
||||
print('Rivendell service name [%s | %$s | %^s]: '+update.resolveFilepath('%s | %$s | %^s',update.dateTime()))
|
||||
print('Seconds, zero padded (SS) [%S | %$S | %^S]: '+update.resolveFilepath('%S | %$S | %^S',update.dateTime()))
|
||||
print('Day of the week, numeric, 1=Monday, 7=Sunday [%u | %$u | %^u]: '+update.resolveFilepath('%u | %$u | %^u',update.dateTime()))
|
||||
print('Week number, as per ISO 8601 [00 - 23] [%V | %$V | %^V]: '+update.resolveFilepath('%V | %$V | %^V',update.dateTime()))
|
||||
print('Two digit year [%y | %$y | %^y]: '+update.resolveFilepath('%y | %$y | %^y',update.dateTime()))
|
||||
print('Four digit year [00 - 23] [%Y | %$Y | %^Y]: '+update.resolveFilepath('%Y | %$Y | %^Y',update.dateTime()))
|
||||
print("Literal '%' [%%]: "+update.resolveFilepath('%%',update.dateTime()))
|
||||
|
||||
#
|
||||
# Create an instance of 'PyPADReceiver'
|
||||
#
|
||||
rcvr=PyPAD.Receiver()
|
||||
|
||||
#
|
||||
# Tell it to use the callback
|
||||
#
|
||||
rcvr.setCallback(ProcessPad)
|
||||
|
||||
#
|
||||
# Start the receiver, giving it the hostname or IP address and TCP port of
|
||||
# the target Rivendell system. Once started, all further processing can only
|
||||
# be done in the callback method!
|
||||
#
|
||||
rcvr.start(localhost',PyPAD.PAD_TCP_PORT)
|
||||
147
apis/PyPAD/tests/pad_test.py
Executable file
147
apis/PyPAD/tests/pad_test.py
Executable file
@@ -0,0 +1,147 @@
|
||||
#%PYTHON_BANGPATH%
|
||||
|
||||
# pad_test.py
|
||||
#
|
||||
# PyPAD regression test script for Rivendell
|
||||
#
|
||||
# Exercise every PAD accessor method of 'PyPAD.Update' for each update.
|
||||
#
|
||||
# (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 PyPAD
|
||||
|
||||
def ProcessPad(update):
|
||||
print
|
||||
print('*** Log %03d Update ***********************************************' % update.machine())
|
||||
print('** HEADER INFO **')
|
||||
print(' dateTime(): '+update.dateTime().isoformat(' '))
|
||||
print(' hostName(): '+update.hostName())
|
||||
print(' shortHostName(): '+update.shortHostName())
|
||||
print(' machine(): %d' % update.machine())
|
||||
print( ' mode(): '+update.mode())
|
||||
print(' onairFlag(): '+str(update.onairFlag()))
|
||||
print
|
||||
if update.hasLog():
|
||||
print('** LOG INFO **')
|
||||
print(' logName(): '+update.logName())
|
||||
print()
|
||||
else:
|
||||
print('**NO LOG INFO PRESENT**')
|
||||
print()
|
||||
|
||||
if update.hasService():
|
||||
print('** SERVICE INFO **')
|
||||
print(' serviceName(): '+update.serviceName())
|
||||
print('serviceDescription(): '+update.serviceDescription())
|
||||
print('serviceProgramCode(): '+update.serviceProgramCode())
|
||||
print()
|
||||
else:
|
||||
print('** NO SERVICE INFO PRESENT **')
|
||||
print()
|
||||
|
||||
if update.hasPadType(PyPAD.TYPE_NOW):
|
||||
print('** NOW PLAYING INFO **')
|
||||
try:
|
||||
print(' startDateTime(): '+update.startDateTime(PyPAD.TYPE_NOW).isoformat(' '))
|
||||
except AttributeError:
|
||||
print(' startDateTime(): None')
|
||||
print(' cartType(): '+update.padField(PyPAD.TYPE_NOW,PyPAD.FIELD_CART_TYPE))
|
||||
print(' cartNumber(): %u / ' % update.padField(PyPAD.TYPE_NOW,PyPAD.FIELD_CART_NUMBER)+update.resolvePadFields("%n",PyPAD.ESCAPE_NONE))
|
||||
print(' cutNumber(): %u / ' % update.padField(PyPAD.TYPE_NOW,PyPAD.FIELD_CUT_NUMBER)+update.resolvePadFields("%j",PyPAD.ESCAPE_NONE))
|
||||
print(' length(): %u / ' % update.padField(PyPAD.TYPE_NOW,PyPAD.FIELD_LENGTH)+update.resolvePadFields("%h",PyPAD.ESCAPE_NONE))
|
||||
try:
|
||||
print(' year(): %u / ' % update.padField(PyPAD.TYPE_NOW,PyPAD.FIELD_YEAR)+update.resolvePadFields("%y",PyPAD.ESCAPE_NONE))
|
||||
except TypeError:
|
||||
print(' year(): None / '+update.resolvePadFields("%Y",PyPAD.ESCAPE_NONE))
|
||||
print(' groupName(): '+update.padField(PyPAD.TYPE_NOW,PyPAD.FIELD_GROUP_NAME)+' / '+update.resolvePadFields('%g',PyPAD.ESCAPE_NONE))
|
||||
print(' title(): '+update.padField(PyPAD.TYPE_NOW,PyPAD.FIELD_TITLE)+' / '+update.resolvePadFields('%t',PyPAD.ESCAPE_NONE))
|
||||
print(' artist(): '+update.padField(PyPAD.TYPE_NOW,PyPAD.FIELD_ARTIST)+' / '+update.resolvePadFields('%a',PyPAD.ESCAPE_NONE))
|
||||
print(' publisher(): '+update.padField(PyPAD.TYPE_NOW,PyPAD.FIELD_PUBLISHER)+' / '+update.resolvePadFields('%p',PyPAD.ESCAPE_NONE))
|
||||
print(' composer(): '+update.padField(PyPAD.TYPE_NOW,PyPAD.FIELD_COMPOSER)+' / '+update.resolvePadFields('%m',PyPAD.ESCAPE_NONE))
|
||||
print(' album(): '+update.padField(PyPAD.TYPE_NOW,PyPAD.FIELD_ALBUM)+' / '+update.resolvePadFields('%l',PyPAD.ESCAPE_NONE))
|
||||
print(' label(): '+update.padField(PyPAD.TYPE_NOW,PyPAD.FIELD_LABEL)+' / '+update.resolvePadFields('%b',PyPAD.ESCAPE_NONE))
|
||||
print(' client(): '+update.padField(PyPAD.TYPE_NOW,PyPAD.FIELD_CLIENT)+' / '+update.resolvePadFields('%c',PyPAD.ESCAPE_NONE))
|
||||
print(' agency(): '+update.padField(PyPAD.TYPE_NOW,PyPAD.FIELD_AGENCY)+' / '+update.resolvePadFields('%e',PyPAD.ESCAPE_NONE))
|
||||
print(' conductor(): '+update.padField(PyPAD.TYPE_NOW,PyPAD.FIELD_CONDUCTOR)+' / '+update.resolvePadFields('%r',PyPAD.ESCAPE_NONE))
|
||||
print(' userDefined(): '+update.padField(PyPAD.TYPE_NOW,PyPAD.FIELD_USER_DEFINED)+' / '+update.resolvePadFields('%u',PyPAD.ESCAPE_NONE))
|
||||
print(' songId(): '+update.padField(PyPAD.TYPE_NOW,PyPAD.FIELD_SONG_ID)+' / '+update.resolvePadFields('%s',PyPAD.ESCAPE_NONE))
|
||||
print(' outcue(): '+update.padField(PyPAD.TYPE_NOW,PyPAD.FIELD_OUTCUE)+' / '+update.resolvePadFields('%o',PyPAD.ESCAPE_NONE))
|
||||
print(' description(): '+update.padField(PyPAD.TYPE_NOW,PyPAD.FIELD_DESCRIPTION)+' / '+update.resolvePadFields('%i',PyPAD.ESCAPE_NONE))
|
||||
print(' externalEventId(): '+update.padField(PyPAD.TYPE_NOW,PyPAD.FIELD_EXTERNAL_EVENT_ID))
|
||||
print(' externalData(): '+update.padField(PyPAD.TYPE_NOW,PyPAD.FIELD_EXTERNAL_DATA))
|
||||
print(' externalAnncType(): '+update.padField(PyPAD.TYPE_NOW,PyPAD.FIELD_EXTERNAL_EVENT_ID))
|
||||
print()
|
||||
|
||||
else:
|
||||
print('** NO NOW PLAYING INFO **')
|
||||
print()
|
||||
|
||||
if update.hasPadType(PyPAD.TYPE_NEXT):
|
||||
print('** NEXT PLAYING INFO **')
|
||||
try:
|
||||
print(' startDateTime(): '+update.startDateTime(PyPAD.TYPE_NEXT).isoformat(' '))
|
||||
except AttributeError:
|
||||
print(' startDateTime(): None')
|
||||
print(' cartType(): '+update.padField(PyPAD.TYPE_NEXT,PyPAD.FIELD_CART_TYPE))
|
||||
print(' cartNumber(): %u / ' % update.padField(PyPAD.TYPE_NEXT,PyPAD.FIELD_CART_NUMBER)+update.resolvePadFields("%N",PyPAD.ESCAPE_NONE))
|
||||
print(' cutNumber(): %u / ' % update.padField(PyPAD.TYPE_NEXT,PyPAD.FIELD_CUT_NUMBER)+update.resolvePadFields("%J",PyPAD.ESCAPE_NONE))
|
||||
print(' length(): %u / ' % update.padField(PyPAD.TYPE_NEXT,PyPAD.FIELD_LENGTH)+update.resolvePadFields("%H",PyPAD.ESCAPE_NONE))
|
||||
try:
|
||||
print(' year(): %u / ' % update.padField(PyPAD.TYPE_NEXT,PyPAD.FIELD_YEAR)+update.resolvePadFields("%Y",PyPAD.ESCAPE_NONE))
|
||||
except TypeError:
|
||||
print(' year(): None / '+update.resolvePadFields("%Y",PyPAD.ESCAPE_NONE))
|
||||
print(' groupName(): '+update.padField(PyPAD.TYPE_NEXT,PyPAD.FIELD_GROUP_NAME)+' / '+update.resolvePadFields('%G',PyPAD.ESCAPE_NONE))
|
||||
print(' title(): '+update.padField(PyPAD.TYPE_NEXT,PyPAD.FIELD_TITLE)+' / '+update.resolvePadFields('%T',PyPAD.ESCAPE_NONE))
|
||||
print(' artist(): '+update.padField(PyPAD.TYPE_NEXT,PyPAD.FIELD_ARTIST)+' / '+update.resolvePadFields('%A',PyPAD.ESCAPE_NONE))
|
||||
print(' publisher(): '+update.padField(PyPAD.TYPE_NEXT,PyPAD.FIELD_PUBLISHER)+' / '+update.resolvePadFields('%P',PyPAD.ESCAPE_NONE))
|
||||
print(' composer(): '+update.padField(PyPAD.TYPE_NEXT,PyPAD.FIELD_COMPOSER)+' / '+update.resolvePadFields('%M',PyPAD.ESCAPE_NONE))
|
||||
print(' album(): '+update.padField(PyPAD.TYPE_NEXT,PyPAD.FIELD_ALBUM)+' / '+update.resolvePadFields('%L',PyPAD.ESCAPE_NONE))
|
||||
print(' label(): '+update.padField(PyPAD.TYPE_NEXT,PyPAD.FIELD_LABEL)+' / '+update.resolvePadFields('%B',PyPAD.ESCAPE_NONE))
|
||||
print(' client(): '+update.padField(PyPAD.TYPE_NEXT,PyPAD.FIELD_CLIENT)+' / '+update.resolvePadFields('%C',PyPAD.ESCAPE_NONE))
|
||||
print(' agency(): '+update.padField(PyPAD.TYPE_NEXT,PyPAD.FIELD_AGENCY)+' / '+update.resolvePadFields('%E',PyPAD.ESCAPE_NONE))
|
||||
print(' conductor(): '+update.padField(PyPAD.TYPE_NEXT,PyPAD.FIELD_CONDUCTOR)+' / '+update.resolvePadFields('%R',PyPAD.ESCAPE_NONE))
|
||||
print(' userDefined(): '+update.padField(PyPAD.TYPE_NEXT,PyPAD.FIELD_USER_DEFINED)+' / '+update.resolvePadFields('%U',PyPAD.ESCAPE_NONE))
|
||||
print(' songId(): '+update.padField(PyPAD.TYPE_NEXT,PyPAD.FIELD_SONG_ID)+' / '+update.resolvePadFields('%S',PyPAD.ESCAPE_NONE))
|
||||
print(' outcue(): '+update.padField(PyPAD.TYPE_NEXT,PyPAD.FIELD_OUTCUE)+' / '+update.resolvePadFields('%O',PyPAD.ESCAPE_NONE))
|
||||
print(' description(): '+update.padField(PyPAD.TYPE_NEXT,PyPAD.FIELD_DESCRIPTION)+' / '+update.resolvePadFields('%I',PyPAD.ESCAPE_NONE))
|
||||
print(' externalEventId(): '+update.padField(PyPAD.TYPE_NEXT,PyPAD.FIELD_EXTERNAL_EVENT_ID))
|
||||
print(' externalData(): '+update.padField(PyPAD.TYPE_NEXT,PyPAD.FIELD_EXTERNAL_DATA))
|
||||
print(' externalAnncType(): '+update.padField(PyPAD.TYPE_NEXT,PyPAD.FIELD_EXTERNAL_EVENT_ID))
|
||||
print()
|
||||
|
||||
else:
|
||||
print('** NO NEXT PLAYING INFO **')
|
||||
print()
|
||||
|
||||
print ('******************************************************************')
|
||||
|
||||
#
|
||||
# Create an instance of 'PyPADReceiver'
|
||||
#
|
||||
rcvr=PyPAD.Receiver()
|
||||
|
||||
#
|
||||
# Tell it to use the callback
|
||||
#
|
||||
rcvr.setCallback(ProcessPad)
|
||||
|
||||
#
|
||||
# Start the receiver, giving it the hostname or IP address and TCP port of
|
||||
# the target Rivendell system. Once started, all further processing can only
|
||||
# be done in the callback method!
|
||||
#
|
||||
rcvr.start('localhost',PyPAD.PAD_TCP_PORT)
|
||||
Reference in New Issue
Block a user