#!/bin/bash
# angela@crystalfaeries.net http://www.kahealani.com/kahealani/angela_kahealani.html 2011-03-09 02:43:58+00:00
# http://www.crystalfaeries.net/linux/bin/istream
# Downloads and plays YouTube videos from a list of their 11-character hashcodes
# Collects from Second Life(TM)'s and SponOn3D(TM)'s viewer logs the Parcel Music and Media stream URLs
# into a playlist for Real Life listening, and manages removal from the playlist of streams you later find undesirable.
# Playlist for youtube hashcodes (1 11-char code per line):
youtube=/home/www/playlists/youtube.txt
# Playlist for streaming URLs (1 URL per line):
playlist=/home/www/playlists/shoutcast2sl.txt
# userland crontab entry-daily updates (edit according to your Second Life(TM) viewers and place uncommented in your crontab):
# 04 2 * * * grep "Starting internet stream: " $HOME/.secondlife/logs/.firestorm/logs/Firestorm.log | sed 's/^.*Starting internet stream: //' >> $playlist
# userland crontab entry-hourly updates (edit according to your Second Life(TM) viewers and place uncommented in your crontab):
# 04 * * * * grep "Starting internet stream: " $HOME/.secondlife/logs/.firestorm/logs/Firestorm.log | sed 's/^.*Starting internet stream: //' >> $playlist
# Temporary file:
exitval=1 #default to error condition because we have not yet chosen to intend to exit
appname="$(basename $0)"
tmpfile=$(mktemp /tmp/${appname}.XXXXXX) || exit $exitval
trap "rm -f $tmpfile ; exit $exitval" 0 1 2 15
#
# Get options
#
let youtube_flag=1 # false by default
let streams_flag=1 # false by default
while [ $# -ne 0 ] ; do
let arguments=$# #before we shift out any flags
if [ "$1" = "-v" ]
then # Versioning is done by date only
shift
echo "$(basename $0) Version:"
tail -n +2 $0 | head -n 6 # number of header lines displayed as help
exit $exitval # traditionally expected behaviour
fi
if [ "$1" = "-h" ]
then # help, I need somebody,
shift # help, not just anybody.
echo "$(basename $0) Usage:"
echo "If you don't specify only Youtube_downloads with the -y flag, "
echo "and you don't specify only Streaming___music with the -s flag, "
echo "then first we play youtube downloads followed by streams."
echo "Arguments after flags may be URLs or 11-character hashcodes."
echo "Danger, Danger, Will Robinson... youtube hashcodes starting with a hyphen may fail miserably."
echo "The wary programmer must investigate the handling of arguments to the echo command."
echo "After each file we give you an opportunity to enter 'rm' to remove that file,"
echo "or enter 'de' to defer that file, or enter 'ed' to edit that file."
echo "Changing stations is as easy as typing: 'q<enter>'"
echo "To remove a station from your playlist, type: 'qrm<enter>'"
echo "To stop listening, type: 'q^C'"
echo "To pause or resume listening, type: ' '"
echo "Some streams may not be resumable, so you 'resume' the next 'station'."
exit $exitval # traditionally expected behaviour
fi
if [ "$1" = "-y" ] # yes, "-y" tells us to play youtube downloads
then
shift
let youtube_flag=0 # true
fi
if [ "$1" = "-s" ] # yes, "-s" tells us to play streams
then
shift
let streams_flag=0 # true
fi
if [[ $arguments -eq $# ]]
then
break # out of loop if no more flags
fi
done # getting options
let both=1 # false
if [[ $youtube_flag -eq 0 ]]
then
if [[ $streams_flag -eq 0 ]]
then # both flags were actually specified
let both=0 # true
else # youtube only
if [ -n "$1" ] # any arguments on command line?
then # append hashcodes from command line onto youtube playlist
while [ $# -ne 0 ] ; do
echo $1 >> $youtube
exitval=$?
shift
done
fi
fi
else
if [[ $streams_flag -eq 0 ]]
then # streams only
if [ -n "$1" ] # any arguments on command line?
then # append URLs from command line onto streams playlist
while [ $# -ne 0 ] ; do
echo $1 >> $playlist
exitval=$?
shift
done
fi
else # no flags; defaults as if both flags had been specified
let youtube_flag=0 # true
let streams_flag=0 # true
let both=0 # true
fi
fi
if [[ $both -eq 0 ]]
then # we have to guess what any further arguments are
while [ $# -ne 0 ] ; do
if [ "`echo $1 | wc`" = " 1 1 12" ]
then # is a hash - youtube
echo "$1" >> $youtube
else # is a URL
echo "$1" >> $playlist
fi
exitval=$?
shift
done
fi
# done with the command line, flags turned into internal variables.
player='/usr/bin/mplayer -fs'
alert='/usr/share/sounds/gnome/default/alerts/bark.ogg'
$player $alert > /dev/null 2> /dev/null # acknowledge the CLI input.
exitval=$?
# tidy the URL playlist on disk, but youtube hashcodes are not sequential, so
# we will *not* sort the youtube list which is in order for viewing multi-segment videos.
if [[ $streams_flag -eq 0 ]]
then # we are going to stream, so tidy the stream list
sort -u < $playlist > $tmpfile
mv $tmpfile $playlist
echo ======= head:
head $playlist
echo ------- tail:
tail $playlist
echo ======= :end.
fi
exit $exitval ####### DEBUGGING EXIT ####### CODE BELOW STILL BEING (RE)WRITTEN #######
#
# 1 Infinite Loop (ref: where is the flagpole holding the pirate flag in "Pirates of Silicon Valley"? in the center of)
#
cd $HOME/Music/ # work at the relative root level of the Music itself
touch .music.txt # keep a record of what we hear so we only hear each file once
while sleep 1;do #loop forever, presuming concurrency with Second Life (TM) and streamripper
if [ $streams_flag = 0 ]
then
echo Playing Streams, as requested
else
echo Playing Local Files followed by Streams, as requested
#
# PLAY LOCAL FILES FIRST
#
# build the list of existing files
cp /dev/null "$tmpfile"
for directories in /media/cdrom $HOME/Music $HOME/Videos /media /mnt /opt ~/Downloads /usr/local/src /home/www ; do
for extensions in .asx .avi .flac .flv .mov .mp1 .mp2 .mp3 .mp4 .mpg .ogg .ra .rm .ram .wma .wmv ; do
nice find $directories -iname "*$extensions" -exec du {} \; 2>/dev/null | grep -v kartrons_whores >> "$tmpfile"
done
done
# in decreasing size order
sort -rn "$tmpfile" | cut -f 2- > /tmp/$$.music.txt
mv /tmp/$$.music.txt "$tmpfile"
# clean the list of pre-viewed files
sort -u .music.txt > /tmp/$$.music.txt
mv /tmp/$$.music.txt .music.txt
if [ -s $HOME/Music/playlists/youtube.txt ]
then # presumably at least one youtube 11-char hashcode (one per line)
echo Downloading according to playlists/youtube.txt
# watching a youtube video does download the file into the browsers cache directory, but it does not give us file extensions (.flv,.mp4),
# so we have created a shared youtube cache for system-wide use by configuring browsers like firefox to cache videos here:
pushd $HOME/Videos/www.youtube.com || pushd $HOME/Videos/www.youtube.com
# so we will use the same cache location now that we are going to explicitly download youtube videos
for f in `cat playlists/youtube.txt`;do
if [ -f "*$f*" ] # the 11 character hash code should be unique
then
echo We already have a copy on disk of "*$f*"
else
c="$(echo $f | tr A-Z a-z)" # cannonicalized to lower case
if [ -f "*$c*" ] # we may have lower cased it
then
echo We already have a copy on disk of "*$c*"
else
youtube-dl http://www.youtube.com/watch?v="$f"
fi
fi
exitval=$("$player" "$alert") > /dev/null # alert the human we're about to pop-up a player window
exitval=$("$player" "*$f*" "*$c*") # either original or cannonicallized name will do
echo -n "'rm' to remove, or new filename?: "
read a
if [ "$a" = "rm" ]
then
rm -i "*$f*" "*$c*"
else
for m in "*$f*" "*$c*";do
mv -i "$m" "$a"."$m" || mv -i "$m" "$a"
done
fi
tail -n +2 playlists/youtube.txt > "$tmpfile"
mv "$tmpfile" playlists/youtube.txt
done
popd
fi
fi # end of local files
#DEBUG:
echo "ERROR: You must upgrade my code to account for your multiple 3D world chatlogs"
exit -1
#
# UPDATE STREAMS PLAYLIST FROM SECOND LIFE (TM) SHOUTCAST2SL JUKEBOX
#
if [ -d "$HOME"/chatlogs ]
then
if [ -f "$HOME"/chatlogs/chat.txt ]
then
echo "Good: I found your chatlog."
else
echo "I can not find your chatlog, so please:"
echo "ln -s "$HOME"/.secondlife/avatar_name/ "$HOME"/chatlogs"
echo "I do not presume which 'avatar name' you use."
exit 1
fi
else
echo "I can not find your chatlogs, so please:"
echo " ln -s "$HOME"/.secondlife/avatar_name/ "$HOME"/chatlogs"
echo "I do not presume which 'avatar name' you use."
exit 1
fi
if [ -d $HOME/Music ]
then
if [ -d $HOME/Music/playlists ]
then
echo "Good: playlists directory found."
else
mkdir -p $HOME/Music/playlists
echo "Good: playlists directory created."
fi
else
mkdir -p $HOME/Music/playlists
echo "Good: playlists directory created."
fi
echo "Good: Refreshing Playlist from Second Life (TM) Public Chatlog..."
if [ -f playlists/$playlist ]
then
cp playlists/$playlist /tmp/$playlist.$$
else
touch /tmp/$playlist.$$
fi
grep "SHOUTCAST2SL JUKEBOX" "$HOME"/chatlogs/chat.txt | cut -c 64- | sort -u | grep http >> /tmp/$playlist.$$
sort -u /tmp/$playlist.$$ > playlists/$playlist
rm /tmp/$playlist.$$
echo "Good: Pruning the streams previously removed from the playlist:"
if [ -f playlists/."$playlist" ]
then
if [ -z playlists/."$playlist" ]
then
echo "OK: Empty Mute List."
else
echo -n "Good: Processing Mute List"
for u in $(cat playlists/."$playlist");do
grep -v "$u" playlists/$playlist > /tmp/$playlist.$$
mv /tmp/$playlist.$$ playlists/$playlist
echo -n "."
done
echo ""
echo "Good: Processed Mute List."
fi
else
echo "OK: NonExistant Mute List."
fi
#
# PLAY STREAMS FROM INTERNET LISTED IN PLAYIST
#
for f in $(cat playlists/$playlist);do
echo "======= Begin: $f ======="
# ping -c 1 `echo $f \
# | sed 's/http:\/\///' \
# | sed 's/\/.*$//' \
# | sed 's/:.*$//'`
# if [ $? = 0 ]
# then
exitval=$("$player" "$f")
if [ $? == 0 ]
then
echo "========= End: $f ======="
echo -n "Disposition: ('rm' to remove/mute)?: "
read a
if [ "$a" = "rm" ]
then
echo "$f" >> playlists/."$playlist"
echo "MUTED: $f"
else
echo "KEPT: $f"
fi
else
echo "$f" >> playlists/."$playlist"
echo "FAILED: $f"
fi
# else
# echo "$f" >> playlists/."$playlist"
# echo "OFFLINE: $f"
# fi
done
#
# ASK IF WE SHOULD REENABLE ALL KNOWN CHANNELS
#
echo ======= END OF PLAYLIST, READY TO START OVER =======
echo -n "Clear Mute List ('yes' to reenable all streams)?: "
read a
if [ "$a" = "yes" ]
then
mv playlists/."$playlist" playlists/."$playlist"-
cat playlists/"$playlist" playlists/."$playlist"- | sort -u > playlists/."$playlist"
mv playlists/."$playlist" playlists/"$playlist"
echo "MUTE LIST CLEARED."
else
echo "MUTE LIST RETAINED."
fi
echo ======= 1 Infinite Loop =======
done
exitval=0
exit $exitval
# if the variable "file" contains a file's basename,
# we can substitute the existing extension to be ".ext" by:
# ${file%.*}.ext
syntax highlighted by Code2HTML, v. 0.9.1