#!/bin/bash
#
# tvtc 0.1
#
# Copyright (c) 2009, Christophe Osuna
# All rights reserved.
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * The names of its contributors may not be used to endorse or promote
# products derived from this software without specific prior written
# permission.
#
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# This script allows Neuf Cegetel clients to play and record some TV channels.
# It requires MPlayer to be installed.
#
# User doc: http://osuna.org/christophe/projets/tvtc
# Developer doc below configuration section
# -----------------------------------------------------------------------------
# Configuration
# Path to mplayer executable
mplayer=/usr/bin/mplayer
# Stream cache size in Kib (should be greater than 128)
cachesize=1024
# Temporary file to download ASX file
asxtmp=/tmp/tvtc.asx
# Temporary file to save PID
pidfile=/tmp/tvtc.pid
# Directory to save intermediate record file
tmpdir=/tmp
# Date format used when naming files - man date (1) for more details
namebeg=%F-%H%M
nameend=%H%M
# Channels (from http://televisionsurpc.neuf.fr/televisionsurpc.m3u)
# Last update: jan 7th 2009
channels=(
"france2" "France 2" "http://80.118.196.219/webtv-asx.cgi?channel=france_2"
"france3" "France 3" "http://80.118.196.219/webtv-asx.cgi?channel=france_3"
"france5" "France 5" "http://80.118.196.219/webtv-asx.cgi?channel=france_5"
"arte" "Arte" "http://80.118.196.219/webtv-asx.cgi?channel=arte"
"direct8" "Direct 8" "http://80.118.196.219/webtv-asx.cgi?channel=direct_8"
"nt1" "NT1" "http://80.118.196.219/webtv-asx.cgi?channel=nt1"
"nrj12" "NRJ 12" "http://80.118.196.219/webtv-asx.cgi?channel=nrj12"
"lcp" "La chaine parlementaire" "http://80.118.196.219/webtv-asx.cgi?channel=lcp"
"france4" "France 4" "http://80.118.196.219/webtv-asx.cgi?channel=france_4"
"bfm" "BFM TV" "http://80.118.196.219/webtv-asx.cgi?channel=bfm_tv"
"tv5" "TV5" "http://80.118.196.219/webtv-asx.cgi?channel=tv5_monde"
"franceo" "France O" "http://80.118.196.219/webtv-asx.cgi?channel=france_o"
"euronews" "Euronews" "http://80.118.196.219/webtv-asx.cgi?channel=euronews"
"aljazeera" "Aljazeera" "http://80.118.196.219/webtv-asx.cgi?channel=aljazeera"
"liberty" "Liberty TV" "http://80.118.196.219/webtv-asx.cgi?channel=liberty_tv"
"beur" "Beur TV" "http://80.118.196.219/webtv-asx.cgi?channel=beur_tv"
"nrj" "NRJ Hits" "http://80.118.196.219/webtv-asx.cgi?channel=nrj_hits"
"video_click" "Video Click" "http://80.118.196.219/webtv-asx.cgi?channel=video_click"
"kto" "KTO" "http://80.118.196.219/webtv-asx.cgi?channel=kto"
)
# Set to something to show debug messages
DEBUG=
# You shouldn't have to configure anything below
# -----------------------------------------------------------------------------
# Information for developers
#
# Neuf Cegetel streams its webtv channels using a playlist [1]. Each element in
# the playlist points to an ASX file, which contains a set of servers to stream
# a channel. So what this scripts does is simply download the ASX file, choose
# a random server and let MPlayer play or record the stream.
#
# When the user wants to record a channel, this script runs MPlayer and
# expects it to be killed either by the user (^C) or by the script itself
# (stoprec command).
#
# [1] http://televisionsurpc.neuf.fr/televisionsurpc.m3u
PATH=/bin:/usr/bin
mplayeropts="-cache $cachesize -really-quiet"
name=
url=
# TODO: do this with getopt
case $3 in
-ws)
mplayeropts="$mplayeropts -aspect 16/9"
;;
-z)
mplayeropts="$mplayeropts -vf crop=320:176:0:34"
;;
esac
# Print a debug message
# $1 message
function debug()
{
if [ x$DEBUG != x ]; then echo $1 ; fi
}
# Print help screen
function usage()
{
echo "Usage: $0 COMMAND {CHANNEL} [OPTION]"
echo ""
echo "COMMAND can be one among:"
echo " list list channels"
echo " rec CHANNEL start recording channel"
echo " stoprec stop a recording"
echo " view CHANNEL view channel"
echo ""
echo "OPTIONS:"
echo " -ws force widescreen format"
echo " -z zoom"
}
# List available channels
function list()
{
echo -e "Short name\tLong name"
echo -e "----------\t---------"
for ((i=0 ; i<${#channels[@]} ; i+=3)); do
echo -e "${channels[i]}\t\t${channels[$((i+1))]}"
done
}
# Update "name" and "url" global variables when a new short name is given
# $1 channel short name
function updateNameAndURL()
{
local i
local maxsrv
local line
if [ x$1 = x ] ; then usage; exit 1; fi
name=
url=
for ((i=0 ; i<${#channels[@]} ; i+=3)); do
if [ "${channels[$i]}" = "$1" ]; then
name=${channels[$((i+1))]}
url=${channels[$((i+2))]}
fi
done
if [ "$url" = "" ]; then
echo "Invalid channel. Aborting."
exit 1
fi
debug "ASX URL: $url"
wget --quiet --output-document=$asxtmp $url
if [ $? != 0 ]; then
echo "Unable to download ASX file ($url). Aborting.";
exit 1;
fi
# Extract URL from in a random line
maxsrv=$(grep "[ $pidfile
$mplayer $mplayeropts -nocache -dumpstream $url
rm -f $pidfile
dateend=$(date +$nameend)
cd -
mv $tmpdir/stream.dump "${1}-${datebeg}-${dateend}.avi"
}
# Stop a recording
#
# MPlayer (the process wich parent's PID is stored in $pidfile) is
# killed.
function stoprecord()
{
local pid
local ppid
ppid=$(cat $pidfile)
if [ "$ppid" = "" ]; then
echo "No recording to stop. Aborting."
exit 1
fi
kill $(ps -e -o ppid,pid | awk "/^ *$ppid/ {print \$2}")
}
# Open mplayer to view a channel
# $1 channel short name
function view()
{
updateNameAndURL $1
echo "Playing ${name}..."
debug "$mplayer $mplayeropts $url"
$mplayer $mplayeropts $url
}
case $1 in
list)
list
;;
-h|--help)
usage
;;
rec)
record $2
;;
stoprec)
stoprecord
;;
view)
view $2
;;
*)
usage
exit 1
;;
esac
]