#!c:/perl/bin ####### # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. ###### # # Application: riopackTk.pl : auto-mix your mp3 files onto your rio with a fancy Tk interace (ok, not that fancy ;) # # Version: 0.0.1 (Feb 1999) # # Description: # This perl script will create a random mix of MP3 files and then auto-download # them to the rio via a command line rio application (not included) # # NOTE: this script was developed, tested and works great on my NT box with perl 5.004 # your mileage may vary. If you tweak the script to make it work on *nix, please # email me a copy for my own archives. Thanks! # # Author: steve mcnabb (s.mcnabb@sympatico.ca) # # Requirements: # * some _legal_ mp3 files to download to your rio (remember kids...piracy is illegal) # * 3'rd party command line application to actually talk to the rio...if you # don't have one of these, try looking at http://www.world.co.uk/sba/ # * a Diamond Rio portable music player (duh) # # Configuration: # 1) set "mp3 root" to be the root directory of wherever you keep your mp3s # 2) set "riobridge" to point to your command line app for copying to the rio # 3) you may need to tweak the "init_rio" and "dumpfiles" to reflect your situation # and/or the way your command line app works.. # # Please DO NOT send the author requests to fix busted scripts - if it doesn't work for you, # edit it. If it still doesn't work, edit it again. :) # # Future Plans: well, if someone figures out how to address the external flash memory cards # with a command line app, I'll add support for it to this script, and re-release it. # # Props: the Snowblind Alliance for cracking the rio protocol - cool hack guys. # $version = '0.2'; use DirHandle; use Tk; init(); sub init #set up some config { $mp3root = 'e:/mp3/'; #where are your mp3s? $threshold = '30'; #if rio isn't full but below threshold, but the next file is too big, keep looking $riobridge = 'rio'; #the command line app that copies stuff to your rio srand(time); $totalsize = undef; $auto_replace = 1; $main = new MainWindow(); $main->title("Riopack Tk $version: © 1999 Steve McNabb"); $l1= $main->Label( text => "Riopack Tk $version: © 1999 Steve McNabb")->pack( padx => 35, pady => 5); $filestats = $main->Label()->pack( side=>'left'); $dump_btn = $main->Button( text => 'Begin', command => \&find_files)->pack; $help_msg = "Rio Pack Tk 0.0.1\n © 1999 Steve McNabb (smcnabb\@interlog.com) \n (All rights reserved) \"Auto Replace\" option: if this option is set, Riopack Tk will 'auto find' a file that will fit into the remaining space if you delete a file from the list \"Reshuffle (Ctrl-R)\": rebuild a new randomized track list "; MainLoop(); } sub find_files { dodir($mp3root); @keys = keys %files; for( keys %files) { $sizes{$files{$_}} = $_ } shuffle(); for(@dump) { $_ =~ s/$mp3root//; if($longest < length($_)) { $longest = length($_)} } $main->destroy; $main = new MainWindow; $main->title("Riopack Tk $version"); add_menu(); $filestats = $main->Label( text => "Ready to dump $totalsize Mb to rio internal memory..")->pack(pady => 5); $instruct = $main->Label( text => "Click on any file and press 'delete' to remove it\n (if there is room, a new file will be selected to replace it)")->pack; $list = $main->Listbox(width => $longest, height => $#dump)->pack(pady => 10); $list->insert('end',@dump); $main->bind("",\&remove_file); $main->bind("",\&reshuffle); $main->bind("",\&dumpfiles); } sub reshuffle { @dump = (); undef $totalsize; %seen = (); srand(); shuffle(); $main->title("Riopack Tk $version"); $filestats->configure(text => "Ready to dump $totalsize Mb to rio internal memory.."); $list->delete(0.1,'end'); $list->configure( height => $#dump +1); $list->insert('end',@dump); #@dump = (); $main->bind("",\&remove_file); $main->bind("",\&reshuffle); $main->bind("",\&dumpfiles); } sub dumpfiles { $main->destroy; &init_rio; print "copying files to rio - please stand by (this can take up to 6 or 7 minutes)\n"; for(@dump) { my $fullpath = $mp3root.$_; #print "ready to dump $fullpath \n"; #print" downloading $fullpath\n"; `rio -u "$fullpath"`; print "."; } cleanup(); print "\n\a\aDone!\n"; exit; } sub add_menu { $menu_bar = $main->Frame()->pack(side => 'top', anchor => 'nw'); $file_mb = $menu_bar->Menubutton(text => 'File')->pack( side => 'left', padx => 10); $file_mb->command('-label' => "Reshuffle ", '-accelerator' => "Ctrl-R", '-command' => \&reshuffle); $file_mb->command('-label' => "Download to rio",'-accelerator' => "Ctrl-D", '-command' => \&dumpfiles); $file_mb->separator(); $file_mb->command('-label' => "Exit",'-command' => sub { exit }); $opt_mb = $menu_bar->Menubutton(text => 'Options')->pack( side => 'left',padx =>20); $opt_mb->checkbutton( -label => "Auto-Replace", -variable => \$auto_replace, -onvalue =>1, -offvalue => 0); $help_mb = $menu_bar->Menubutton(text => 'Help')->pack(side => 'left', padx =>20); $help_mb->command( -label => 'Help', '-command' => \&showhelp); } sub showhelp { $helpwin = new MainWindow; $helpwin->title("Riopack $version help"); $txt = $helpwin->Label( text => $help_msg, justify => 'left')->pack; $btn = $helpwin->Button( text => "OK",command => sub { $helpwin->destroy })->pack; } sub remove_file { $sel = $list->index('active'); @smallfiles = (); @nudump = (); $to_kill = $dump[$sel]; $dump[$sel] = undef; $killed_size = $files{$mp3root.$to_kill}; $totalsize = $totalsize - $killed_size; $remain = 32 - $totalsize; if(!$auto_replace) { $filestats->configure(text => "Ready to dump $totalsize Mb to rio"); for(@dump) { if($_) { push @nudump,$_ } } @dump = @nudump; $list->delete(0.1,'end'); $list->insert('end',@dump); $list->configure( height => $#dump+1); @nudump = (); return }; while($totalsize <= $threshold) { @smallfiles = grep { $_ <= $remain } keys %sizes; $whichfile = rand($#smallfiles-1); $file_to_add = $smallfiles[$whichfile]; next if $seen{$sizes{$file_to_add}}; if($totalsize + $file_to_add > 32) { return; } $totalsize = $totalsize + $file_to_add; $remain = 32 - $totalsize; $to_add = $sizes{$file_to_add}; $to_add =~ s/$mp3root//; push @dump, $to_add; } for(@dump) { if($_) { push @nudump,$_ } } #clean blank entries @dump = @nudump; $list->delete(0.1,'end'); $list->insert('end',@dump); $list->configure( height => $#dump+1); $filestats->configure(text => "Ready to dump $totalsize Mb to rio"); @nudump = (); } sub shuffle { $song = sprintf("%0d",rand($#keys-1)); if($seen{$song}) { shuffle() } else { $seen{$song} = 1; $keys[$song-1] =~ s/$mp3root//; my $size = $files{$keys[$song]}; if($totalsize + $size >= 32) { if($totalsize <= $threshold) { $remainING = 32 - $totalsize; @smallfiles = grep { $_ <= $remaining } keys %sizes; $smallfile = rand($#smallfiles-1); $smfilesize = $smallfiles[$smallfile]; $smfilename = $sizes{$smfilesize}; push @dump, $keys[$song-1]; shuffle(); } else {break} } else { $totalsize += $size; push @dump, $keys[$song-1]; shuffle() } } } sub dodir #recursively dig for files { my $dir = shift; my $dirhandle = new DirHandle($dir); if($dirhandle) { while($file = $dirhandle->read) { next if ($file =~ /^\.{1,2}$/); my $fullpath = $dir . "/" . $file; if (-d $fullpath) { dodir($fullpath)} else { my @stat = stat $fullpath; my $filesize = $stat[7]; my $kbfilesize = sprintf("%.2f",$filesize / 1024); my $mbfilesize = sprintf("%.2f",$kbfilesize /1024); $files{$fullpath} = $mbfilesize; } } } } sub init_rio #make sure the giveio service is running so we can copy { print "rio initialized...\n"; `net stop parport`; #stop paralell port device `net start giveio`; #start give io device (needed by my NT command line rio app)ftp steve.tralt.com #initialize rio mem `$riobridge -i`; } sub cleanup { `net stop giveio`; `net start parport`; }