#!/usr/bin/perl # NKMP3 (N)umeric (K)eypad (M)(P)(3), (C) 2000 Joakim Mared, joakim@mared.com # # Ver. 0.0.4 # User definable constants, set @SEARCH_DIRS and $SILENT to appropiate values # my @SEARCH_DIRS = ('/mp3', '/win/mp3album'); my $SILENT = 0; # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # use strict; use Term::ReadKey; use File::Find; use locale; $| = 1; ReadMode 4; my $key; my $loop; my $old; my $last = ''; my $toprint; my $lc = 0; my $line; my $lastword; my $entity; my $char; my $a; my $pid; my $now_playing; my $asensed; my $already_in_pl; my $playnext; my $special = 0; my $stopped = 0; my @chars; my @matches; my @entitychars; my @playlist; my @temp_playlist; my %words; my %save; my %song; my %multies = ('8' => [ 'A', 'B', 'C', '2', 'Å', 'Ä' ], '9' => [ 'D', 'E', 'F', '3' ], '4' => [ 'G', 'H', 'I', '4' ], '5' => [ 'J', 'K', 'L', '5' ], '6' => [ 'M', 'N', 'O', '6' ], '1' => [ 'P', 'Q', 'R', 'S', '7' ], '2' => [ 'T', 'U', 'V', '8' ], '3' => [ 'W', 'X', 'Y', 'Z', '9' ], '0' => [ ' ' ]); my %reverse_multies = %{build_reverse(\%multies)}; print "Building mp3 list..." unless $SILENT; find(\&wanted, @SEARCH_DIRS); system 'clear' unless $SILENT; while (1) { $loop = 0; while (not defined($key = ReadKey(0.5))) { $pid = `pidof mpg123`; unless ($pid =~ m/(\d+)/ || $stopped) { unless (scalar(@playlist) == 0) { play_next(); } } } $key = lc $key; $special = 0 if ($key ne ','); if ($key eq '+') { $already_in_pl = 0; foreach(@playlist) { if ($now_playing eq $_) { $already_in_pl = 1; } } unless ($already_in_pl) { push @playlist, $now_playing; print "Adding $now_playing to playlist\n" unless $SILENT; } } elsif ($key eq '-') { $playnext = 0; @temp_playlist = (); foreach(@playlist) { if ($now_playing ne $_) { push @temp_playlist, $_; if ($playnext) { play($_); $playnext = 0; } } else { print "Removing $now_playing from playlist\n" unless $SILENT; play_stop(); $playnext = 1; } } @playlist = @temp_playlist; if ($playnext) { if (scalar(@playlist) != 0) { play(@playlist[-1]); } } } elsif ($key eq '7') { unless ($line =~ m/\s$/ || length($line) == 0) { print "\b \b" unless $SILENT; $line =~ s/(.*?).$/$1/; } else { print "\a" unless $SILENT; } } elsif ($key eq '0') { do_autosense(); } elsif ($key eq ',') { if ($special == 0) { print "Stopping\n" unless $SILENT; play_stop(); $special++; } elsif ($special == 1) { print "Erasing playlist\n" unless $SILENT; @playlist = (); $special++; } elsif ($special == 2) { do_quit(); } } elsif ($key eq '*') { play_next(); } elsif ($key eq '/') { play_previous(); } elsif ($multies{$key}) { $toprint = $multies{$key}[0]; if ($lc == 1) { $toprint = lc($toprint); } print $toprint unless $SILENT; $line .= $toprint; } else { if ($key eq "\n") { if (length($line) == 0) { if (scalar(@matches) == 0) { print "\a" unless $SILENT; } else { @matches = play_next_match(@matches); } } else { @matches = (); do_autosense() unless ($line =~ m/\)\s$/); chop $line; $line =~ s/\s+/\.\*\?/g; $line =~ s/(.+)/\.\*\?$1\.\*\?/g; if ($line) { foreach(keys(%song)) { if (m/$line/i) { push @matches, $_; } } if (scalar(@matches) == 0) { print "\a" unless $SILENT; } else { @matches = play_next_match(@matches); } } else { print "\a" unless $SILENT; } $line = ''; $asensed = 0; } } } $last = $key; } sub do_quit { ReadMode 0; print "Good bye!\n" unless $SILENT; exit(0); } sub build_reverse { my %in = %{shift()}; my %out; my $pos_char; my @possible; foreach(keys(%in)) { @possible = @{$multies{$_}}; foreach $pos_char (@possible) { $out{$pos_char} = $_; } } return \%out; } sub do_autosense { %save = %words; $lastword = (split(/\s+/, $line))[-1]; unless (scalar(split(/\s+/, $line)) > $asensed) { print "\a" unless $SILENT; return 0; } @chars = split //, $lastword; foreach $entity (keys(%save)) { delete $save{$entity} if (length($entity) < length($lastword)); } for($a = 0;$a < length($lastword);$a++) { foreach $entity (keys(%save)) { @entitychars = split //, $entity; if ($reverse_multies{uc($entitychars[$a])} != $reverse_multies{uc($chars[$a])}) { delete $save{$entity}; } } } chomp $line; for ($a = 1;$a <= length($lastword);$a++) { chop $line; } print("\b \b" x length($lastword)) unless $SILENT; unless (scalar(keys(%save)) == 0) { print(join('|', (keys(%save))) . ' ') unless $SILENT; $line .= '(' . join('|', (keys(%save))) . ') '; $asensed++; } else { print "\a" unless $SILENT; } } sub wanted { return 0 if (m/^\.|\.\.$/); return 0 unless (-f $File::Find::name); s/\.mp3$//g; s/\Q%20\E|_/ /g; tr/a-zA-Z0-9åäöÅÄÖ //csd; $song{$_} = $File::Find::name; foreach $entity (split /\s+/) { $entity = uc $entity; $words{$entity} = $_; } } sub play_next_match { my $songname = shift; play($songname); return @_; } sub play_next { my $playnext = 0; foreach(@playlist) { if ($playnext) { play($_) if $_; last; } else { if ($_ eq $now_playing) { $playnext = 1; } } } } sub play_previous { my $old; my $toplay; foreach(@playlist) { if ($_ eq $now_playing) { $toplay = $old; play($toplay) if $toplay; } $old = $_; } } sub play { my $songname = shift; system("killall mpg123 > /dev/null 2>&1 ; mpg123 \"$song{$songname}\" > /dev/null 2>&1 &"); $now_playing = $songname; $stopped = 0; system('clear') unless $SILENT; print "Playing $song{$songname}\n" unless $SILENT; } sub play_stop { system("killall mpg123 > /dev/null 2>&1"); $stopped = 1; }