In the beginning (after my real-world alarm clock broke) I (= Andreas Kupries) used cron and a wakeup script using wish and the bell to wake me up.Then I switched to
find . -name '*.ogg' -print | xargs /usr/local/bin/ogg123 -zfor random play now that I ogg'ified quite a number of my CDs.The deficiency of this command pipe: I can play about 220-230 songs in a day, but there are over 1000 in my catalog now. This means that the find/xargs combo will only reach about a quarter of all songs as random play is only in the groups created by xargs and not over the whole set.I finally decided to tackle this and created the script below. It features random shuffle over all songs (using code from the wiki) and a persistent storage containing which songs were already played, so that they are excluded the next time the musicbox starts, thus giving every song a fair chance to be played.It should be trivial to switch this over to a commandline mp3 player (for example mpg123), or snack. I hope that snack will support Ogg Vorbis soon, so that I can remove the dependency on an external application. snack now (Aug 2002) supports Ogg
#!/usr/local/bin/tclsh
# Musicbox application, playing round the clock, all of the music I
# have in certain directories. No arguments. Use ~/.musicboxrc to store
# persistent information.
#
# Internal information:
#
# 1. Array containing the names of all the files which were already
# played as keys. The values are not relevant.
#
# 2. List of files to play. Filled via 'find', but only with files not
# already played. Shuffled in random order.
#
# Only (1) is persistent.
#
# *future* Rewrite to use the snack extension (when it incorporates
# *ogg support).
proc main {} {
global played
array set played {}
# Get persistent playing information.
catch {source ~/.musicboxrc}
cd ~/.mydata/CDs
# Forever
while {1} {
# Search the music directories for unplayed files and shuffle them
set playlist [shuffle [unplayed_files]]
# If there were no new files then use the files which were
# already played as list of songs to play and reset the 'played'
# information.
if {[llength $playlist] == 0} {
set playlist [shuffle [lsort [array names played]]]
clear_played
}
play $playlist
#exit
}
}
proc unplayed_files {} {
set playlist [list]
set p [open "|find . -name *.ogg" r]
while {![eof $p]} {
if {[gets $p line] < 0} {continue}
set line [string trim $line]
if {$line == {}} {continue}
if {[isplayed $line]} {continue}
lappend playlist $line
}
return $playlist
}
proc isplayed {file} {
global played
return [info exists played($file)]
}
proc clear_played {} {
global played
unset played
array set played {}
save_played
return
}
proc K {x y} {return $x}
proc shuffle {list} {
set n [llength $list]
set slist [list]
while {$n>0} {
set j [expr {int(rand()*$n)}]
lappend slist [lindex $list $j]
incr n -1
set temp [lindex $list $n]
set list [lreplace [K $list [set list {}]] $j $j $temp]
}
return $slist
}
proc play {list} {
global played
foreach file $list {
puts stdout "Playing $file ..."
catch {exec /usr/local/bin/ogg123 $file > /dev/null}
set played($file) .
save_played
}
return
}
proc save_played {} {
global played
set f [open ~/.musicboxrc.new w]
puts $f "array set played \{[array get played]\}"
close $f
catch {file copy -force ~/.musicboxrc ~/.musicboxrc.old}
file copy -force ~/.musicboxrc.new ~/.musicboxrc
return
}
# ... go
mainHave fun.And now a little shell function giving me a command line interface to the musicbox (partially linux and site specific).
function music () {
case $1 in
on) if [ 0 -eq `ps auxw | grep musicbox | grep -v grep | wc -l` ]
then
#No musicbox running, start it.
musicbox > "$HOME/.mydata/CDs/db/collections/played.`date`" &
else
echo "Musicbox already running, ignoring command"
fi
;;
off) killall musicbox ogg123
;;
pause) killall -STOP ogg123 musicbox
;;
cont) killall -CONT ogg123 musicbox
;;
stat) here=`pwd`
cd $HOME/.mydata/CDs
find . -name '*.m3u' -print | wc -l | xargs echo '#Albums = '
find . -name '*.ogg' -print | wc -l | xargs echo '#Songs = '
cd $here
;;
played) if [ -r $HOME/.musicboxrc ]
then
echo 'source ~/.musicboxrc ;puts "Played: [array size played]"; exit' | tclsh
else
echo "Nothing played"
fi
;;
vol) rexima -v | grep pcm
;;
clear) rm -f $HOME/.musicboxrc
rm -f $HOME/.musicboxrc.new
rm -f $HOME/.musicboxrc.old
;;
*) # Assume a number and use it to control the mixer
rexima pcm $1
;;
esac
}See also peterc's Tcl MP3 Alarm Clock.TV (Nov 28 ' 08) I didn't know about this page, but I made an audio player based on tcl-cgi for use with a mobile internet device and a server which I think could pass as cool: Jukebox based on webserver with Tcl cgi scripts. If combined with Random worklist generator a correct shuffle should result, contrary to the above link, I think comparable to AK's version.

