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.