2008-12-15

Reading from a character device for a specified / limited amount of time with a bash-script

Bash is awesome. I have this neat TV-tuner which encodes the video to mpeg2 on the fly (the downside is the 1 second lag, so it's not usable for game consoles). If you want to rip something, just read from the /dev/video0 and pipe it into a file. Easy.

But let's say you have a library of home-made VHS tapes which you want to save before it's too late - then you have this repetive task which to some extent requires attention - right?

What I wanted to do, was to create a script which could read from that file for a specified amount of time, and then terminate. I also wanted to make sure that it stops reading when I kill the script, or if the script was interrupted. This is what I came up with:

#!/bin/bash

# Default settings

device=/dev/video0
outfile=out.mpg
seconds=3600

# Gives the user the oppertunity to override the default settings by supplying
# arguments to the script, f.ex -d /dev/video1, or -o someotherfile.mpg, or
# -t 1800 to wait 1800 seconds (half hour) in stead of 3600 (an hour)

while getopts "d:o:t:" flag
do
 case "$flag" in
     d) device=$OPTARG;;
     o) outfile=$OPTARG;;
     t) seconds=$OPTARG;;
 esac
done

echo "Will do the following:"
echo " * Record from $device"
echo " * Into file $outfile"
echo " * Will stop after $seconds seconds"

# Issueing some commands to my TV-tuner before we start ripping
# (The TV-tuner is a Hauppauge PVR-350, but all the cards using the
# ivtv-driver should do...

v4l2-ctl -d $device -c temporal_filter=0 > /dev/null
v4l2-ctl -d $device --set-input 2 > /dev/null

# Puts the reading process into background, and saves the PID-variable

cat $device > $outfile &
THEPID=$!

# Making sure that the background process get's killed on CTRL+C or kill

trap "kill $THEPID" SIGINT SIGTERM

# Waiting for the specified amount of time

sleep $seconds

# Killing the cat background process

kill $THEPID

echo " DONE !!! "

NOTE: The script is bash-specific. On many systems, sh is symlinked to bash. But do not, by habit, run this script as 'sh script'. It will fail (because it uses bash-specific functionality, like $!), and you may have to kill the cat-process manually. Set the executable bit and run it like './script' or run 'bash script'.

No comments: