Edited 11/6/2019 - Updated Version of Script Code. Added locking feature to avoid race condition when two or more recordings begin at the same time.
I've tried several different Home Theater DVR/PVR software solutions beginning with Windows Media Center then MythTv and TVHeadend. Each offered valuable features but tended to use a lot of resources and in the event of updates or problems I found trouble shooting support a bit sparse.
I have found that I only used the basic recording functions so I set out to write my own scripts which would enable me to use the command line to schedule a recording. I've been working on making the process as simple as possible... The goal being to simply enter a single command with the necessary arguments for the system to understand what I want to record and when.
I own several SiliconDust tuners which are connected to different antennas so that I can have reliable reception of as many stations as possible. So I needed to include the logic to let the system choose a tuner that is both 'connected to an appropriate antenna' and 'not in use'.
Presently, my PVR system consists of a single script that draws information from a text file that contains the real RF channel and the MPEG2-PID that is associated with the Virtual Channel. There is one text file for each known virtual channel. Each of the virtual channel map files also includes a list of tuner and their sub-tuners ordered by preference. The main script checks for the 'lock' status of a tuner before beginning a recording. If the preferred tuner is locked by another user or recording process, the script will proceed to check the next tuner in the list.
Presently, I schedule the running of the recording script using the built-in Unix/Linux command 'at'.
script: recordTV.sh
Code:
#!/bin/bash
#
#
#
# Set Recording time-stamp to Recording File Name
REC_TS=$(date +%Y%m%d%H%M)
#
LOCKKEY=$(date +%T%N)
#
LOG_FILE=/home/tom/bin/PVR_scripts/logs/PVR_scripts.log
touch -a $LOG_FILE
#
if [ -z $1 ]
then
echo $(date +%T%N) Exiting; No Virtual Channel was specified >> $LOG_FILE
exit
else
VC=$1
fi
#
if [ -z $2 ]
then
echo $(date +%T%N) Exiting; No File Name was specified >> $LOG_FILE
exit
else
REC_FN=/home/tom/Videos/$2
fi
#
if [ -z $3 ]
then
echo $(date +%T%N) Exiting; Recording duration not specified >> $LOG_FILE
exit
else
RecDur=$3
fi
#
#
#Load Virtual Channel configutation to array
declare -a VCarray
if [ -f /home/tom/bin/PVR_scripts/VirtualChannelMaps/VirtualChan$VC.txt ]
then
mapfile -t VCarray < /home/tom/bin/PVR_scripts/VirtualChannelMaps/VirtualChan${VC}.txt
else
echo $(date +%T%N) Virtual Channel ${VC} configuration file missing >> $LOG_FILE
exit
fi
#
#
arrayindex=2
FT=0
function SetLock () {
if [ ! -f /home/tom/bin/FindFreeTuner.lock ]
then
touch /home/tom/bin/FindFreeTuner.lock
chmod 666 /home/tom/bin/FindFreeTuner.lock
echo $(date +%T%N) Lock is set by ${VC} >> $LOG_FILE
FindFreeTuner
else
if [ $FT -gt 9 ]
then
echo $(date +%T%N) FindFreeTuner.lock file has not been removed - by ${VC} >> $LOG_FILE
exit
else
let FT=${FT}+1
echo $(date +%T%N) FT=${FT} by ${VC} >> $LOG_FILE
sleep 1s
SetLock
fi
fi
}
function FindFreeTuner () {
if [ $arrayindex -gt 20 ]
then
echo $(date +%T%N) "No free tuners available" by ${VC} >> $LOG_FILE
exit
else
LockStatus=$(/usr/local/bin/hdhomerun_config ${VCarray[$arrayindex]} get /${VCarray[$arrayindex+1]}/lockkey)
if [[ ${LockStatus} = "none" ]]
then
ConfigTuner
else
echo $(date +%T%N) HDHR ${VCarray[$arrayindex]} ${VCarray[$arrayindex+1]} is locked by $LockStatus - by ${VC} >> $LOG_FILE
let arrayindex=${arrayindex}+2
FindFreeTuner
fi
fi
}
#
function ConfigTuner () {
/usr/local/bin/hdhomerun_config ${VCarray[$arrayindex]} set /${VCarray[$arrayindex+1]}/lockkey $LOCKKEY
echo $(date +%T%N) tuner ${VCarray[$arrayindex]} sub-tuner ${VCarray[$arrayindex+1]} VC ${VC} TS-PID ${VCarray[1]} lockkey $LOCKKEY >> $LOG_FILE
rm /home/tom/bin/FindFreeTuner.lock
echo $(date +%T%N) Lock has been unset by ${VC} >> $LOG_FILE
/usr/local/bin/hdhomerun_config ${VCarray[$arrayindex]} key $LOCKKEY set /${VCarray[$arrayindex+1]}/channel auto:${VCarray[0]}
/usr/local/bin/hdhomerun_config ${VCarray[$arrayindex]} key $LOCKKEY set /${VCarray[$arrayindex+1]}/program ${VCarray[1]}
echo $(date +%T%N) Normal start of recording CH $VC >> $LOG_FILE
/usr/local/bin/hdhomerun_config ${VCarray[$arrayindex]} key $LOCKKEY save /${VCarray[$arrayindex+1]} ${REC_FN}.mpg &
HDHR_PID=$!
echo $(date +%T%N) $HDHR_PID by ${VC} >> $LOG_FILE
#
sleep ${RecDur}m
#
#Release tuner
/usr/local/bin/hdhomerun_config ${VCarray[$arrayindex]} key ${LOCKKEY} set /${VCarray[$arrayindex+1]}/channel none
/usr/local/bin/hdhomerun_config ${VCarray[$arrayindex]} key ${LOCKKEY} set /${VCarray[$arrayindex+1]}/lockkey none
#
#Send normal termination signal to hdhomerun_config
kill -15 $HDHR_PID
echo $(date +%T%N) Normal end of recording by ${VC} >> $LOG_FILE
#
exit
}
echo $(date +%T%N) ${VC} Checking for lock file >> $LOG_FILE
SetLock
exit
Sample VirtualChannelMap file 'VirtualChan4.1.txt'
Code:
30
3
1032E7DB
tuner0
1032E7DB
tuner1
1052349B
tuner0
1052349B
tuner1
1019D817
tuner0
1019D817
tuner1
101A5A4B
tuner0
101A5A4B
tuner1
101AE560
tuner0
101AE560
tuner1
Use of the script as shown below will schedule a recording of virtual channel 4.1 to a file named 'RecordingFileName'.mpg and the recording will run for 62 minutes. The recording will begin at 6:59 PM on October 30, 2019.
Code:
commandprompt:~$ at 18:59 10302019
warning: commands will be executed using /bin/sh
at> recordTV.sh 4.1 RecordingFileName 62
at> <EOT>
job 1204 at Wed Oct 30 18:59:00 2019
commandprompt::~$
The <EOT> control character is entered using CTL+d key combination.