#!/bin/bash
# -----------------------------------------------------------------------
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License Version 2
#
# FIND DETAILED SETUP INFORMATION ON http://freevo.sr-club.de/nvram-wakeup.php
# (c.) Georg Künzel
# Version 0.5
#
# -----------------------------------------------------------------------
# adjust the following variables to your personal needs

# does nvram-wakeup needs a reebot to function properly (0=no/1=yes)? 
NEED_REBOOT=1 # if set to 1 you need a section "PowerOff" in your lilo.conf 
# only if your hardware needs reboot: choose your bootloader 
BOOTLOADER="lilo" # "lilo" oder "grub" are supported
# only if your using grub as bootloader: entry nr of the poweroff-section in grub.conf
ENTRYNR=1 # counting starts at "0", so "1" is your second entry

PATH_TO_YOUR_LOCAL_CONF=/etc/freevo/ # path to the local_conf.py file your freevo is using
UPSOON=/var/cache/freevo/upsoon # choose freevo's upsoon file
PATHTONVRAM=/usr/local/bin/ # path to the nvram-wakeup binary
# Assuming BIOS is set to UTC time, how many seconds have to be added/subtracted from your local time to reach UTC ?
UTCADJUST="- 3600" # for Germany which is UTC+1h the value has to be "- 3600"
# convert this to your language freevo is running with
# perform a "cat /var/cache/freevo/upsoon" to see what freevo outputs
SEARCHSTRING[1]="Today:"
SEARCHSTRING[2]="Tomorrow:"
SEARCHSTRING[3]="This.Week:"
STRING_AT="at" # e.g. "- Nameoftheshow at 12:00AM"
#                                      ^^

# -----------------------------------------------------------------------
# ONLY EDIT BEYOND THIS LINE IF YOU ARE REALLY FAMILIAR WITH THIS SCRIPT!

# set Debuglevel (0/1)
DEBUG=0
# grep record-padding from local_conf.py
RECORDPADDING=`grep "^TV_RECORD_PADDING.*=" ${PATH_TO_YOUR_LOCAL_CONF}/local_conf.py| sed "s/TV_RECORD_PADDING.*=//"|bc`
# grep remote port from local_conf.py
REMOTE_CONTROL_PORT=`grep "^REMOTE_CONTROL_PORT.*=" ${PATH_TO_YOUR_LOCAL_CONF}/local_conf.py| sed -e "s/REMOTE_CONTROL_PORT.*=//;s/\"//g;s/ //g"`
# grep remote host from local_conf.py
REMOTE_CONTROL_HOST=`grep "^REMOTE_CONTROL_HOST.*=" ${PATH_TO_YOUR_LOCAL_CONF}/local_conf.py| sed -e "s/REMOTE_CONTROL_HOST.*=//;s/'//g;s/\"//g;s/ //g"`
# grep external idle time from local_conf.py
MAXIDLE=`grep "^IDLETIMER_EXTERNAL_DELAY.*=" ${PATH_TO_YOUR_LOCAL_CONF}/local_conf.py| sed -e "s/IDLETIMER_EXTERNAL_DELAY.*=//;s/'//g;s/\"//g;s/ //g"|bc`
# min. seconds between shutdown and next recording; if sec until next recording are less, no shutdown will be performed
SECUNTILSTART=`expr ${RECORDPADDING} + 900` # seconds
# if this file is present, no check via cron will be performed, manual freevo shutdown will work anyway
CHECKLOCK=/tmp/idletimer_lock_* # files will be removed on every shutdown !
# tmp. files for this script
TMP_PS=/tmp/idletimer_ps 
TMP_IDLE=/tmp/idletimer_idlesec
# this should match the seconds until this script is executed again via cron 
CHECKINTERVAL=60
# local for this script 
LANG="en"
# seconds to add for today, tomorrow, this week and in three days 
TOADD[1]=0
TOADD[2]=86400
TOADD[3]=172800
TOADD[4]=259200

# OK, all variables set, lets roll...

# first time running this script ?
touch ${TMP_IDLE}
# maybe recordserver isn't running, no upsoon-file present
touch ${UPSOON}

typeset -i OTHERPS IDLE NEWIDLE HOUR TOADD WAKEUP MAXIDLE CHECKINTERVAL
# check if mplayer, xine, etc. is running
ps -Af  > ${TMP_PS}
OTHERPS=`egrep "\/[a-z]*\/(tvtime|xine|mplayer|mencoder|radio|xmms|transcode|cdrecord|cdrdao|cdparanoia|cdda2|gogo|growisofs|dvd+rw|mkisofs|normalize|readcd|tcscan|tcprobe|tcextract|tcdecode|tccat|tcrequant|dvdbackup|mjpegtools|subtitleripper|dvdauthor|streamanalyze|a52dec|mad|oggenc|lsdvd|jpegtran|flac)" ${TMP_PS}|wc -l`
# remove temp. file
rm -f ${TMP_PS}
# set to standard
SHUTDOWN=0
# is there an active lockfile (manually or automatically written)
CHECKLOCKCOUNT=`ls -l ${CHECKLOCK} 2>/dev/null|wc -l`
if [ ${OTHERPS} -eq 0 -a ${CHECKLOCKCOUNT} -eq 0 -o "$1" == "shutdown" ]
then
	# no relevant process running, increase idle time
	NEWIDLE=`expr $(cat ${TMP_IDLE}|awk '{print $1}') + ${CHECKINTERVAL}`
	if [ ${NEWIDLE} -gt ${MAXIDLE} -o "$1" == "shutdown" ]
	then
		#  max. idle time exceeded, check for wakeup time and shutdown
		NOW=`date +%s`
		# check values that have been grabbed from local_conf
		if [ "${RECORDPADDING}" == "" ]
		then
			RECORDPADDING=0
		fi
		if [ "${REMOTE_CONTROL_PORT}" == "" ]
		then
			REMOTE_CONTROL_PORT=16310
		fi
		if [ "${REMOTE_CONTROL_HOST}" == "" ]
		then
			REMOTE_CONTROL_HOST="localhost"
		fi
		# simulate user input to force creation of upsoon file
		# show main menu 
		echo -e -n 'MENU' >/dev/udp/${REMOTE_CONTROL_HOST}/${REMOTE_CONTROL_PORT}
		# go up, 10 times should be enough even with all main menu plugins activated
		for i in 1 2 3 4 5 6 7 8 9 10
			do
				echo -e -n 'UP' >/dev/udp/${REMOTE_CONTROL_HOST}/${REMOTE_CONTROL_PORT}
			done
		# open TV menu, upsoon file gets refreshed
		echo -e -n 'SELECT' >/dev/udp/${REMOTE_CONTROL_HOST}/${REMOTE_CONTROL_PORT}
		# done 1st time, do it again: show main menu 
		echo -e -n 'MENU' >/dev/udp/${REMOTE_CONTROL_HOST}/${REMOTE_CONTROL_PORT}
		# open TV menu, upsoon file gets refreshed
		echo -e -n 'SELECT' >/dev/udp/${REMOTE_CONTROL_HOST}/${REMOTE_CONTROL_PORT}
		# give freevo some time to write the file
		sleep 3
		typeset -i i
		i=1
		for VAR in ${SEARCHSTRING[*]}
		do
			# we found a heading (today/tomorrow/this week) in upsoon, lets open it
			if grep "^${VAR}" ${UPSOON} &>/dev/null
			then
				ITEM=0
				# read the upsoon-file
				while read LINE
				do
					# approaching the heading...
					SHOW=`echo "${LINE}"|grep "^- "|wc -l`
					if echo "${LINE}"|grep "^${VAR}" &>/dev/null
					then
						ITEM=1
					# is there a valid entry in the heading ?
					elif [ ${SHOW} -eq 1 -a ${ITEM} -eq 1 ]
					then
						TIME=`echo ${LINE}|sed "s/- .* ${STRING_AT} //"`
						# check string [0-9][0-9]:[0-9][0-9][A/P]M if AM or PM
						if echo ${TIME}|grep "PM" 1>/dev/null
						then
							# add 12h if time is PM
							HOUR=`expr ${TIME:0:2}`
                                                        if [ ${HOUR} -ne 12 ]
                                                        then
                                                                HOUR=`expr ${TIME:0:2} + 12`
                                                        fi
						else
							HOUR=`expr ${TIME:0:2} + 0`
						fi
						MINUTES=${TIME:3:2}
						# this day/month is "wrong", will be corrected with $TOADD
						SCHEDULED="`date +%F` ${HOUR}:${MINUTES}:00"
						# this is the wakeup date in epoch notation
						WAKEUP=$(expr `date -u -d "${SCHEDULED}" +%s` + ${TOADD[${i}]} - ${RECORDPADDING} ${UTCADJUST})
						# is the start still in the future
						if [ "${WAKEUP}" -gt "${NOW}" ]
						then
							# we found a valid entry, leave loop 
							SHUTDOWN=1
							if [ ${DEBUG} -eq 1 ]
							then
								echo "NEXT RECORDING: ${LINE}"
							fi
							break 2
						fi
					# ooops, we left the valid section, seems as a new heading started
					elif [ ${SHOW} -eq 0 -a ${ITEM} -eq 1 ]
					then
						break
					fi
				done < ${UPSOON}
			fi
			# we need this count for $TOADD[4] only...
			i=$i+1
		done
		# no entry in upsoon found, check again in three days...
 		if [ ${SHUTDOWN} -eq 0 ]
		then
			WAKEUP=$(expr `date +%s` + ${TOADD[$i]} - ${RECORDPADDING} ${UTCADJUST})
		fi
		# set wakeup time in bios
		${PATHTONVRAM}/nvram-wakeup --directisa -s ${WAKEUP}
		# reset for next recording
		echo "0" > ${TMP_IDLE}
		# remove lock file  
		rm -f ${CHECKLOCK}
		DIFF=`expr $WAKEUP - $NOW`
		if [ ${DEBUG} -eq 1 ]
		then
			echo "NOW: $NOW"
			echo "WAKEUP: $WAKEUP"
			echo "DIFF: $DIFF"
			echo "DIFF IN MINUTES: " `expr $DIFF / 60`
			echo "DIFF IN HOURS: " `expr $DIFF / 3600`
			echo "SECUNTILSTART: ${SECUNTILSTART}"
		fi
		if [ ${DIFF} -lt ${SECUNTILSTART} ]
		then
			# time until next recording will start is less than $SECUNTILSTART
			if [ ${DEBUG} -eq 1 ]
			then
				echo "LESS THAN SECUNTILSTART: `expr ${SECUNTILSTART} - $DIFF`"
			fi
			if [ "$1" == "shutdown" ]
			then
				# if user wants to shutdown, just perform reboot; do nothing when running from cron
				/sbin/shutdown -r now
			fi
		else
			# there is enough time left until next rec starts, please shutdown
			if [ ${DEBUG} -eq 1 ]
			then
				echo "MORE THAN SECUNTILSTART: `expr $DIFF - ${SECUNTILSTART}`"
			fi
			if [ ${NEED_REBOOT} -eq 0 ]
			then
				# nvram-wakeup doesn't needs a reboot 
				# perform shutdown now ! See you again at $WAKEUP. Good bye!
				/sbin/shutdown -h now
			else
				if [ "${BOOTLOADER}" == "grub" ]
				then
					# grub will boot entry $ENTRYNR
					echo "savedefault --default=${ENTRYNR} --once quit" | /sbin/grub
				else
					# lilo will boot system and immediately switch to runlevel 0
					/sbin/lilo -R PowerOff
				fi
				# perform reboot now ! See you again at $WAKEUP. Good bye!
				/sbin/shutdown -r now
			fi	
		fi
	else
		# increase idle time
		if [ ${DEBUG} -eq 1 ]
		then
			echo "NEWIDLE: ${NEWIDLE}"
			echo "MAXIDLE: ${MAXIDLE}"
		fi
		echo "${NEWIDLE}" > ${TMP_IDLE}
	fi
else
	if [ ${DEBUG} -eq 1 ]
	then
		echo "WORKING"
	fi
	# reset, still working
	echo "0" > ${TMP_IDLE}
fi