#!/bin/sh # ############################################################################### # # Simple script to ease playing Digitally Imported and SKY.fm Internet radio # # Author: Lasse Collin # # This file has been put into the public domain. # You can do whatever you want with this file. # # Last updated: 2009-11-28 22:00+0200 # ############################################################################### # Program name to display in messages. This looks nicer than $0 which # contains the full path. PROG=${0##*/} # Don't let environment variables mess up with the config. unset BITRATE PREMIUM PLAYER MENU CHANNEL # Read the config file if it exists. CONF=~/.difmplayrc [ -f "$CONF" ] && . "$CONF" # Message to display with -h. HELP="Usage: $PROG [OPTION]... [CHANNEL] Play a stream from Digitally Imported or SKY.fm Internet radio. For high-quality streams, premium subscription is required. -b BITRATE Set the bitrate as kbit/s. 256, 128, and 96 are MP3. 64, 32, and 24 are AAC+. Only 96 and 24 are available without premium subscription. The default is 256 if using premium, otherwise the default is 96. -i PREMIUM Set the premium ID (a hexadecimal string) needed to construct URLs for premium streams. You can find this string by looking at the URLs of the channels when logged in DI.fm or SKY.fm website. -p PLAYER Set the command to use as the audio player. It has to accept an URL to the playlist (.pls) as the last argument. Wordsplitting is applied to PLAYER, which makes it possible to pass additional command line options to the player program. The default is \`mplayer -playlist'. -m Display a menu using \`dialog' to select the channel and bitrate. The default selections can be specified in the config file or on the command line. -n Don't display a menu even if config file has MENU=yes or the -m option was already used. -l Display the list of available channels. (May be outdated.) -h Display this help message. CHANNEL may be an abbreviated name of the channel. The abbreviation has to be unique except when setting the default selection for the menu. Default settings can be set in ~/.difmplayrc. It is read as an \`sh' script. Supported configuration variable names are BITRATE, PREMIUM, PLAYER, MENU (valid values being \`yes' and \`no'), and CHANNEL. Report bugs to (in English or Finnish). difmplay home page: " # List of supported channels (to show the channel list and to quickly catch # typos). You can get an up to date list by logging into di.fm, saving the # HTML code into a file (e.g. di.html), and using the sed + xargs command: # # sed -n 's|^.*href="/listen/\([^/]\+\)/premium.*$|\1|p' di.html | xargs # # Note that the HTML code contains your premium ID so don't distribute # saved HTML file! After getting the list, you need to split it correctly # for di.fm and sky.fm. The first and last character in these strings must # be a space for validation with `case'. CHANNELS_DI=" discohouse dubstep classictrance techhouse psychill \ chilloutdreams eurodance club trance vocaltrance electro house \ soulfulhouse progressive classiceurodance chillout lounge ambient goapsy \ minimal drumandbass techno hardcore hardstyle exposurenyc funkyhouse \ tribalhouse harddance spacemusic djmixes classictechno breaks gabber \ futuresynthpop replay " CHANNELS_SKY=" bebop tophits classical datempolounge newage world guitar \ solopiano smoothjazz uptemposmoothjazz urbanjamz rootsreggae the80s hit70s \ classicrock altrock indierock oldies classicrap pianojazz bossanova country \ lovemusic beatles soundtracks christian jazz salsa " # Parse the command line arguments. while getopts 'b:hi:lmnp:' ARG "$@"; do case $ARG in b) BITRATE=$OPTARG ;; h) echo "$HELP" exit 0 ;; i) PREMIUM=$OPTARG ;; l) # Behave differently depending on if stdout is # a terminal or not. if tty -s 0>&1; then # column is not in POSIX but many systems # have it. echo "$CHANNELS_DI$CHANNELS_SKY" \ | tr ' ' '\n' | column else # Not writing to a terminal, so make it easier # to pipe the channel list to other programs. echo "$CHANNELS_DI$CHANNELS_SKY" \ | tr ' ' '\n' | sed '/^$/d' fi exit 0 ;; m) MENU=yes ;; n) MENU=no ;; p) PLAYER=$OPTARG ;; *) echo "Try \`$PROG -h' for help." >&2 exit 1 ;; esac done # Set the defaults for settings not specified in the config file or # on the command line. if [ -z "$BITRATE" ]; then if [ -z "$PREMIUM" ]; then BITRATE=96 else BITRATE=256 fi fi MENU=${MENU:-no} PLAYER=${PLAYER:-'mplayer -playlist'} # Non-option arguments currently include only the channel name. shift $(expr $OPTIND - 1) case $# in 0) # Using the default channel from the config file. if [ -z "$CHANNEL" -a "$MENU" = "no" ]; then echo "$PROG: No channel was specified in the config" \ "file or on the command line." exit 1 fi ;; 1) CHANNEL=$1 ;; *) echo "$PROG: Too many command line arguments." >&2 echo "Try \`$PROG -h' for help." >&2 exit 1 ;; esac # Validate the bitrate. case $BITRATE in 24|96) ;; 32|64|128|256) if [ -z "$PREMIUM" ]; then echo "$PROG: Without premium account, only bitrates" \ "96 and 24 are available." >&2 exit 1 fi ;; *) echo "$PROG: Supported bitrates are" \ "256, 128, 96, 64, 32, and 24." >&2 exit 1 ;; esac # Roughly validate the channel name so that it doesn't cause us problems. case $CHANNEL in *" "*|*"'"*) echo "$PROG: Channel name must not contain spaces or" \ "quote characters." >&2 echo "Use \`$PROG -l' to view the list of channels." >&2 exit 1 ;; esac # See if the given channel name matches a known channel name. The channel # name can be abbreviated, and it has to be unique unless we are going to # display a menu. MATCH= for ARG in $CHANNELS_DI$CHANNELS_SKY; do case $ARG in "$CHANNEL") # Exact channel name was found. MATCH=$ARG break ;; "$CHANNEL"*) # Abbreviated channel name was found. if [ -n "$MATCH" ]; then # If we are using a menu, don't complain # about ambiguous channel names, but keep # looking for exact match. [ "$MENU" = "yes" ] && continue echo "$PROG: \`$CHANNEL' is ambiguous." >&2 echo "Use \`$PROG -l' to view the list" \ "of channels." >&2 exit 1 fi MATCH=$ARG ;; esac done # If we are going to display a menu, it's OK if we found no channel name. if [ -z "$MATCH" -a "$MENU" = "no" ]; then echo "$PROG: Unknown channel name: $CHANNEL" >&2 echo "Use \`$PROG -l' to view the list of channels." >&2 exit 1 fi CHANNEL=$MATCH # Display the menu if requested. if [ "$MENU" = "yes" ]; then # Ask the channel. MENUCMD="dialog --backtitle $PROG --default-item '$CHANNEL'" MENUCMD="$MENUCMD --menu 'Select the channel:' 19 32 12" for ARG in $CHANNELS_DI$CHANNELS_SKY; do MENUCMD="$MENUCMD $ARG ''" done CHANNEL=$(eval "$MENUCMD" 3>&1 1>&2 2>&3) || exit 1 # Ask bitrate. Show only 96 and 24 if not using premium. MENUCMD="dialog --backtitle $PROG --default-item $BITRATE" MENUCMD="$MENUCMD --menu 'Select the bitrate:' 13 32 6" if [ -z "$PREMIUM" ]; then MENUCMD="$MENUCMD 96 'MP3 96 kbps' 24 'AAC+ 24 kbps'" else MENUCMD="$MENUCMD 256 'MP3 256 kbps' 128 'MP3 128 kbps'" MENUCMD="$MENUCMD 96 'MP3 96 kbps' 64 'AAC+64 kbps'" MENUCMD="$MENUCMD 32 'AAC+ 32 kbps' 24 'AAC+ 24 kbps'" fi BITRATE=$(eval "$MENUCMD" 3>&1 1>&2 2>&3) || exit 1 echo fi # Construct the URL of the playlist. If the subscription is from DI.fm, # also SKY.fm channels are played from DI.fm URL (won't work with SKY.fm # URL). But the free streams require using SKY.fm URL. URL="http://www.di.fm" case $BITRATE in 24|96) case $CHANNELS_SKY in *" $CHANNEL "*) URL="http://www.sky.fm" ;; esac ;; esac case $BITRATE in 256) URL="$URL/listen/$CHANNEL/premium.pls?$PREMIUM" ;; 128) URL="$URL/listen/$CHANNEL/128k.pls?$PREMIUM" ;; 96) URL="$URL/mp3/$CHANNEL.pls" ;; 64) URL="$URL/listen/$CHANNEL/64k.pls?$PREMIUM" ;; 32) URL="$URL/listen/$CHANNEL/32k.pls?$PREMIUM" ;; 24) URL="$URL/aacplus/$CHANNEL.pls" ;; esac # Try to play it. exec $PLAYER "$URL" # Just in case it failed, make sure we give a reasonable exit status. exit 1