#!/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