'''Rationale''' I ([peterc]) hate my city's shock jock monoculture, and the non-talkback stations here are more likely to put me back to sleep than wake me up. Cron + a sound card + Tcl MP3 selector script + mpg123 + a 5 metre headphone extension cable + external PC speakers = No more terrible early morning radio! '''mp3select.sh script''' #!/usr/local/ActiveTcl-8.5/bin/tclsh8.5 package require fileutil ######## # Essentials proc shuffle {list} { set n 1 set slist {} foreach item $list { set index [expr {int(rand()*$n)}] set slist [linsert $slist $index $item] incr n } return $slist } proc lvarpop {upVar {index 0}} { upvar $upVar list; if {![info exists list]} { return "-1" } set top [lindex $list $index]; set list [concat [lrange $list 0 [expr $index - 1]] [lrange $list [expr $index +1] end]] return $top; } ######## # General proc get_dirs {} { if {![file exists $::dirs_file]} { puts "Error: $::dirs_file does not exist!" ; exit } if {![file readable $::dirs_file]} { puts "Error: $::dirs_file unreadable!" ; exit } set DF [open $::dirs_file "r"] fconfigure $DF -encoding binary -translation binary -buffering none set dirs [read $DF] close $DF return $dirs } ######## # Core proc random_from_all {items} { # Create list set fl [list] set dirs [get_dirs] foreach d $dirs { set mp3 [fileutil::findByPattern $d *.mp3] foreach f $mp3 { lappend fl $f } } # puts "Full list:\n$fl\n"; set fl [shuffle $fl] set c 0 ; while {$c < $items} { lappend pl [lvarpop fl 0] ; incr c } return $pl } proc ordered_from_random_dirs {items} { # Create list set fl [list] set dl [list] set dq [list] set pl [list] set dirs [get_dirs] foreach d $dirs { set found [fileutil::findByPattern $d *] foreach f $found { if {[file isdirectory $f] && [regexp $d $f] } { lappend dl $f } } } # Shuffle directories set dl [shuffle $dl] set c 0 ; while {$c < $items} { lappend dq [lvarpop dl 0] ; incr c } # Collect files inside directories foreach d $dq { set mp3 [lsort [fileutil::findByPattern $d -glob *.mp3]] foreach f $mp3 { lappend pl $f } } return $pl } proc set_directories_file {value} { set ::dirs_file $value } ######## # Main interp alias {} -rdof {} ordered_from_random_dirs ;# Random Dirs, Ordered Files interp alias {} -rdrf {} random_from_all ;# Random Dirs, Random Files interp alias {} -cf {} set_directories_file ;# Sets the set ::dirs_file "~/.mp3select/dirs.conf" foreach {opt value} $argv { foreach f [$opt $value] { puts $f ; set didsomething 1 } } if {![info exists didsomething]} { puts "Syntax:\n" puts " mp3select.sh opt value opt value \[...\]\n" puts "Options:\n" puts " -rdof X : Random Dirs, Ordered Files; to play X random audioplays." puts " -rdrf X : Random Files; for playing X random tracks." puts " -cf /path/file : Sets the path to the file with root directories.\n" puts "Example:\n" puts " mp3select.sh -rdrf 10 -cf ~/punk.cf -rdof 3\n" puts " This selects 10 random songs from the dirs in the default file," puts " changes the dirs file to ~/punk.cf then selects 3 random albums.\n" puts "Notes:\n" puts " mp3select.sh will not select a song twice in the same option track" puts " selection. The -cf setting applies to the next -rdof/-rdrf" puts " file selection/s but not previous ones. Multiple -cf may be used." } '''dirs.conf (and other conf/cf files''' Each file contains a list of root directories for your MP3 files, one per line. eg: /home/someuser/Music/The The /home/someuser/Music/Sisters of Mercy These root directories are searched recursively for playable MP3 files. You can list an unlimited number of root directories in each file, and of course, specify any number of conf/cf files on the command-line. '''License''' Originally by [peterc]. Standard BSD style license. '''Use examples''' Set up in Cron (using crontab -e): 0 7 * * * * /pathto/mp3select.sh -rdrf 30 >/tmp/pl.txt && mpg123 -q -@ /tmp/pl.txt >/dev/null 2>&1 While I'm using the mpg123 app here, you can use MPlayer (using -playlist somefile.cf -really-quiet); or anything capable of reading a playlist/queue from a file. ---- !!!!!! %| enter categories here |% !!!!!!