#!/usr/local/bin/perl # # yet another juke box # use Socket; use ExtUtils::testlib; use Curses; use MPEG::MP3Play qw(:msg :state); use Data::Dumper; do "/usr/local/scripts/genres"; sub gdbGetGenreKeys { my(@genres) = sort (keys (%Genres)); return @genres; } sub gdbGetArtistKeys { my($genre) = @_; my(@artists) = sort yajb_caseignore (keys(%{$GenreDb{$genre}})); return @artists; } sub gdbGetAlbumKeys { my($genre,$artist) = @_; my(@albums) = keys( %{${$GenreDb{$genre}}{$artist}} ); return @albums; } sub gdbGetSongRefs { my($genre,$artist,$album) = @_; my(@songs) = @{${${$GenreDb{$genre}}{$artist}}{$album}}; return @songs; } sub do_fix_genre_table { my($filename) = @_; if (!(open(F,"<$filename"))) { print "can't open $filename\n"; exit(1); } read(F,$gt,(-s $filename)); close(F); @gtable = split("\n",$gt); foreach $line(@gtable) { if (!($line =~ "=")) { print "skip $line\n"; next; } print "do $line\n"; ($artist,$genre) = split('=',$line); $artist = yajb_trimfb($artist); $genre = yajb_trimfb($genre); @albums = gdbGetAlbumKeys("all",$artist); foreach $album(@albums) { @songs = gdbGetSongRefs("all",$artist,$album); foreach $song(@songs) { yajb_edit_id3($genre, GENRE(), %$song); print "id3 $genre ".$$song{SONG()}."\n"; } } } yajb_writeDB(); } sub do_genre_table { my(%db); my($song,$genre,$tmp,$artist,$album); my(@genres,@artists,@albums,@songs); @artists = gdbGetArtistKeys("all"); foreach $artist(@artists) { # yajb_log("do_genre_table: $artist"); @albums = gdbGetAlbumKeys("all",$artist); foreach $album(@albums) { # yajb_log("do_genre_table: Artist:$artist Album:$album"); @songs = gdbGetSongRefs("all",$artist,$album); foreach $song(@songs) { $genre = normalize_genre($$song{GENRE()}); # yajb_log("do_genre_table: Artist:$artist Album:$album Genre:$genre Song:$$song{SONG()}"); ${$db{$artist}}{$genre} = 1; } } } $tmp = ""; foreach $artist(sort(keys(%db))) { $tmp .= sprintf("%-30s: ",$artist); $i=0; foreach $genre(sort(keys(%{$db{$artist}}))) { if ($i > 0) { $tmp .= ", "; } $i++; $tmp .= $genre; } $tmp .= "\n"; } open(F,">/tmp/genre_table"); print F $tmp; close(F); } sub mydowncase { local($string) = @_; local($seq,$i,$n,$rstring,$ch,$ch2); $n = length($string); for($i = 0 ; $i < $n ; $i++) { $ch = substr($string, $i, 1); $seq = unpack('C', $ch); if (65 <= $seq && $seq <= 90) { $ch = pack('C', $seq + 32); } $rstring .= $ch; } return $rstring; } sub yajb_dumphash { my($label,%hasharray) = @_; yajb_log($label); my($key); foreach $key(sort (keys(%hasharray))) { yajb_log($key.":".$hasharray{$key}); } } sub screensavertouch { $screensavertimer = time(); if ($screensaverison) { $screensaverison = 0; yajb_system("setterm -blank 0 > $mytty"); } } sub screensaver { if ($screensaverison == 0) { if ((time() - $screensavertimer) > 5) { $screensaverison = 1; yajb_system("setterm -blank 5 > $mytty"); return undef; } } return 1; } sub yajb_caseignore { return lc($a) cmp lc($b); } sub yajb_clear { yajb_stop(); @Playlist = (); $Playlistcursor = -1; $NeedScreenUpdate = 1; yajb_clear_status(); yajb_zerocursors($playlistwinprops{'windownumber'}); } sub yajb_rewind { local($repeat) = @_; yajb_log("yajb_rewind $repeat"); if (!$yajb_playing) { return; } if ($repeat > 0) { $mp3->stop; $mp3->close; decrementPlaylistcursor(); decrementPlaylistcursor(); $yajb_playing=0; } else { $mp3->stop; yajb_play(); } } sub decrementPlaylistcursor { $Playlistcursor -= 1; if ($Playlistcursor < -1) { $Playlistcursor = -1; } if ($Playlistcursor < $WPROPS{@windows[3]}{'start'}) { $WPROPS{@windows[3]}{'start'} = $Playlistcursor - 1; } if ($WPROPS{@windows[3]}{'start'} < 0) { $WPROPS{@windows[3]}{'start'} = 0; } $NeedScreenUpdate = 1; } sub incrementPlaylistcursor { $Playlistcursor += 1; if ($Playlistcursor > $#Playlist) { $Playlistcursor = 0; } if ($Playlistcursor < $WPROPS{@windows[3]}{'start'}) { $WPROPS{@windows[3]}{'start'} = $Playlistcursor - 1; } if ($Playlistcursor > ($WPROPS{@windows[3]}{'start'} + 8)) { $WPROPS{@windows[3]}{'start'} += 7; } if ($WPROPS{@windows[3]}{'start'} > scalar(@Playlist) - 7) { $WPROPS{@windows[3]}{'start'} = scalar(@Playlist) - 7; } if ($WPROPS{@windows[3]}{'start'} < 0) { $WPROPS{@windows[3]}{'start'} = 0; } $NeedScreenUpdate = 1; } sub yajb_play { if ($yajb_playing) { $mp3->play; if ($yajb_paused) { $yajb_paused = 0; yajb_addstr($statusy, 66, " "); yajb_refresh(); } } else { yajb_add2playlist(); } } sub yajb_forward { if (!$yajb_playing) { return; } $mp3->stop; $yajb_playing = 0; yajb_player(); } sub yajb_stop { if (!$yajb_playing) { return; } $mp3->stop; $yajb_playing = 0; yajb_clear_status(); } sub yajb_clear_status { yajb_addstr($statusy, 0, ''); clrtoeol(); yajb_addstr($statusy+1, 0, ''); clrtoeol(); refresh(); } sub yajb_pause { if (!$yajb_playing) { return; } if ($yajb_paused) { yajb_play(); } else { $mp3->pause; $yajb_paused = 1; yajb_disp_pause(); } } sub yajb_disp_pause { if ($yajb_paused) { my($tmp) = " Paused"; eval { attron(A_BLINK) }; yajb_addstr($statusy, 66, $tmp); eval { attroff(A_BLINK) }; yajb_refresh(); } } sub yajb_lock { yajb_log("yajb_lock"); $yajb_lock = 1; yajb_disp_lock(); } sub yajb_unlock { yajb_log("yajb_unlock"); yajb_undisp_lock(); $yajb_lock = 0; } sub yajb_disp_lock { if ($yajb_lock) { my($tmp) = " Locked"; # eval { attron(A_BLINK) }; yajb_addstr($statusy, 66, $tmp); # eval { attroff(A_BLINK) }; yajb_refresh(); } } sub yajb_undisp_lock { if ($yajb_lock) { # eval { attroff(A_BLINK) }; yajb_addstr($statusy, 66, " "); yajb_refresh(); } } sub yajb_one { } sub yajb_two { } sub yajb_three { } sub yajb_four { } sub yajb_five { } sub yajb_six { } sub yajb_seven { } sub yajb_eight { } sub yajb_nine { } sub yajb_zero { if ($currentwindownumber == $playlistwinprops{'windownumber'}) { yajb_deletefromplaylist(); } } sub yajb_display { #help? } sub yajb_enter { yajb_add2playlist(); } sub yajb_index { } sub yajb_category { } sub yajb_guide { } sub yajb_up { yajb_cursorup(1); } sub yajb_right { yajb_cursorright(); } sub yajb_down { yajb_cursordown(1); } sub yajb_left { yajb_cursorleft(); } sub yajb_genre_up { yajb_log("yajb_genre_up "); } sub yajb_genre_down { yajb_log("yajb_genre_down "); $currentwindownumber = 0; $menumode = 0; # $SAVEY = $SAVEY4GENRE; # $SAVEX = $SAVEX4GENRE; # $SAVEKEY = $SAVEKEY4GENRE; yajb_paint_genres(); yajb_refresh(); $NeedScreenUpdate = 1; } sub yajb_genre_right_old { $adjust = 1; @numitems[$currentwindownumber] = scalar(@Genres); $WPROPS{@windows[$currentwindownumber]}{'cursor'} += $adjust; if ($WPROPS{@windows[$currentwindownumber]}{'cursor'} > $WPROPS{@windows[$currentwindownumber]}{'end'}) { $WPROPS{@windows[$currentwindownumber]}{'end'} += $adjust; } if ($WPROPS{@windows[$currentwindownumber]}{'cursor'} > @numitems[$currentwindownumber]-1) { $WPROPS{@windows[$currentwindownumber]}{'cursor'} = @numitems[$currentwindownumber]-1; } if ($WPROPS{@windows[$currentwindownumber]}{'end'} > @numitems[$currentwindownumber]-1) { $WPROPS{@windows[$currentwindownumber]}{'end'} = @numitems[$currentwindownumber]-1; } $WPROPS{@windows[$currentwindownumber]}{'start'} = $WPROPS{@windows[$currentwindownumber]}{'end'} - 4; if ($WPROPS{@windows[$currentwindownumber]}{'start'} < 0) { $WPROPS{@windows[$currentwindownumber]}{'start'} = 0; } $NeedScreenUpdate = 1; } sub yajb_genre_right { $adjust = 1; yajb_updatecursors(); @numitems[$currentwindownumber] = scalar(@Genres); # yajb_log("gr1: cursor:".$WPROPS{@windows[$currentwindownumber]}{'cursor'}); $WPROPS{@windows[$currentwindownumber]}{'cursor'} += $adjust; if ($WPROPS{@windows[$currentwindownumber]}{'cursor'} > @numitems[$currentwindownumber]-1) { $WPROPS{@windows[$currentwindownumber]}{'cursor'} = @numitems[$currentwindownumber]-1; $WPROPS{@windows[$currentwindownumber]}{'cursor'} = 0; } # yajb_log("gr2: cursor:".$WPROPS{@windows[$currentwindownumber]}{'cursor'}); $NeedScreenUpdate = 1; } sub yajb_genre_left { yajb_log("yajb_genre_left "); $adjust = 1; yajb_updatecursors(); @numitems[$currentwindownumber] = scalar(@Genres); $WPROPS{@windows[$currentwindownumber]}{'cursor'} -= $adjust; if ($WPROPS{@windows[$currentwindownumber]}{'cursor'} < $WPROPS{@windows[$currentwindownumber]}{'start'}) { $WPROPS{@windows[$currentwindownumber]}{'start'} -= $adjust; } if ($WPROPS{@windows[$currentwindownumber]}{'cursor'} < 0) { $WPROPS{@windows[$currentwindownumber]}{'cursor'} = 0; $WPROPS{@windows[$currentwindownumber]}{'cursor'} = @numitems[$currentwindownumber]-1; } if ($WPROPS{@windows[$currentwindownumber]}{'start'} < 0) { $WPROPS{@windows[$currentwindownumber]}{'start'} = 0; } $WPROPS{@windows[$currentwindownumber]}{'end'} = $WPROPS{@windows[$currentwindownumber]}{'start'} + 4; $NeedScreenUpdate = 1; } sub yajb_select { yajb_add2playlist(); } sub yajb_jump { } # int(rand n) + 1; = between 1 & n # splice(@{${$MusicDb{$artist}}{$album}}, $i, 1); sub xyajb_shuffle { my($n,$i); my($song,@newPlaylist); $n = $#Playlist; for ($i = 0 ; $i < $n ; $i++ ) { push(@newPlaylist, splice(@Playlist, int(rand $#Playlist))); } @Playlist = @newPlaylist; $Playlistcursor = -1; yajb_stop(); } sub yajb_shuffle { my(%albums) = (); my($song,@newPlaylist); # yajb_log("shuffle0"); foreach $song (@Playlist) { my($album)= $$song{ALBUM()}; my($artist) = $$song{ARTIST()}; # yajb_log("shuffle0: $artist.$album ".$$song{SONG()}); push(@{$albums{$artist.$album}}, $song); my($tmp) = $$song{FILE()}; } while (scalar(keys(%albums)) > 0) { foreach $album(keys(%albums)) { my($song) = shift(@{$albums{$album}}); # yajb_log("shuffle: $album ".$$song{SONG()}); push(@newPlaylist, $song); if (scalar(@{$albums{$album}}) < 1) { delete $albums{$album}; } } } @Playlist = @newPlaylist; $Playlistcursor = -1; yajb_stop(); } # sub yajb_getPlaylistSaveLocation { # my($uname) = yajb_system("uname -a | awk -F\\ '{print \$2}'"); chop $uname; # my($f) = $playlistlocation . "." . $uname; # return $f; # } sub yajb_getPlaylist { my($f) = @_; yajb_log("getPlaylist $f"); my($buf,@data,$line); open(F,"<$f"); read(F,$buf,(-s $f)); close(F); @data = split(/\n/, $buf); foreach $line (@data) { # yajb_log("getPlaylist line: ".substr($line,0,30)); my(%song) = yajb_unserialize($line); yajb_addsong2playlist(\%song); } } sub yajb_clean_playlist_name { my($name) = @_; my($i,$newname,$ch); for ($i = 0 ; $i < length($name) ; $i++) { $ch = substr($name,$i,1); if (('a' <= $ch && $ch <= 'z') || ('A' <= $ch && $ch <= 'Z') || ($ch eq ' ')) { $newname .= $ch; } } return $newname; } sub yajb_saveplaylist { my($f) = yajb_getListNameFromUser(); $f = yajb_clean_playlist_name($f); $f = $musicdir . "/yajb.playlist." . $f; yajb_log("saveplaylist $f"); open(F,">$f"); my($song); foreach $song (@Playlist) { print F yajb_serializeid3(%$song)."\n"; } close(F); } sub yajb_prepare2exit { # system "stty", "icanon", "eol", "^@"; system "stty -cbreak <$mytty >$mytty 2>&1"; # standout($b); # standend($b); endwin(); # yajb_saveplaylist(); } sub yajb_exit { yajb_prepare2exit(); exit(0); } sub yajb_exitmenu { yajb_log("yajb_exitmenu"); my(@keys) = ( " "," "," "," "," "," "); # @numitems[$menuwinprops{'windownumber'}] = scalar(@keys); if ($menumode == 1) { yajb_fillwindow($menuwin, @keys); yajb_refresh(); delwin($menuwin); yajb_initwins(); $currentwindownumber = $savecwn; $menumode = 0; } return; } sub yajb_menu { $menumode = 1; yajb_log("yajb_menu"); unhighlight(); $menuwin = subwin($menuwinprops{'lines'}, $menuwinprops{'cols'}, $menuwinprops{'y'}, $menuwinprops{'x'}); $WPROPS{$menuwin} = \%menuwinprops; @windows[7] = $menuwin; delwin($artistwin); delwin($albumwin); delwin($songwin); delwin($playlistwin); eval { box($menuwin, ACS_VLINE, ACS_HLINE,) }; $savecwn = $currentwindownumber; $currentwindownumber = $menuwinprops{'windownumber'}; } sub yajb_exitloadplaylist { yajb_log("yajb_exitloadplaylist"); my(@keys) = ( " "," "," "," "," "," "); # @numitems[$menuwinprops{'windownumber'}] = scalar(@keys); yajb_fillwindow($playselectwin, @keys); yajb_fillwindow($playsellistwin, @keys); yajb_refresh(); delwin($playselectwin); delwin($playsellistwin); yajb_initwins(); $currentwindownumber = $savecwn; $menumode = 0; return; } sub yajb_loadplaylist { $menumode = 2; yajb_log("yajb_loadplaylist"); my(@keys) = ( " "," "," "," "," "," "); yajb_fillwindow($menuwin, @keys); unhighlight(); refresh(); $playselectwin = subwin($playselectwinprops{'lines'}, $playselectwinprops{'cols'}, $playselectwinprops{'y'}, $playselectwinprops{'x'}); $playsellistwin = subwin($playsellistwinprops{'lines'}, $playsellistwinprops{'cols'}, $playsellistwinprops{'y'}, $playsellistwinprops{'x'}); $WPROPS{$playselectwin} = \%playselectwinprops; $WPROPS{$playsellistwin} = \%playsellistwinprops; @windows[5] = $playselectwin; @windows[6] = $playsellistwin; delwin($menuwin); eval { box($playselectwin, ACS_VLINE, ACS_HLINE,) }; eval { box($playsellistwin, ACS_VLINE, ACS_HLINE,) }; refresh(); my($savecwn) = $currentwindownumber; chdir $musicdir; my($tmp)= "ls -1 yajb.playlist.*"; my(@tmp)= yajb_system($tmp); @playselectlistkeys = (); foreach $tmp(@tmp) { chop $tmp; $tmp =~ s/yajb.playlist.//; push(@playselectlistkeys, $tmp); } my($playlist); %Playlists = (); my($song); foreach $song(@Playlist) { push(@SavePlaylist, $song); } @Playlist = (); foreach $playlist(@playselectlistkeys) { yajb_getPlaylist('yajb.playlist.'.$playlist); foreach $tmp(@Playlist) { # yajb_log("xxx $tmp"); push(@{$Playlists{$playlist}}, $tmp); } @Playlist = (); } foreach $song(@SavePlaylist) { push(@Playlist, $song); } # foreach $playlist(keys(%Playlists)) { # yajb_log("yyy $playlist ".$Playlists{$playlist}); # foreach $tmp(@{$Playlists{$playlist}}) { # yajb_log("zzz ".$tmp); # foreach $tmp2(keys(%{$tmp})) { # yajb_log("aaa ".$tmp2); # } # } # } $currentwindownumber = $playselectwinprops{'windownumber'} ; } sub yajb_favorite { } sub yajb_chup { yajb_cursorup($PAGE); } sub yajb_chdown { yajb_cursordown($PAGE); } sub yajb_update_volume { return; if ($volumechanged == 1) { $volumechanged = 0; my($tmp) = "id3 -RVAD ". $$SONG{'RVAD'} . " '" . $$SONG{FILE()} . "'"; yajb_system($tmp); yajb_removeFromDB(%{$SONG}); yajb_add2db(%{$SONG}); yajb_writeDB(); } } sub yajb_volup { if (!$yajb_playing) { return; } $VOLUME += 5; $VOLUME = 100 if $VOLUME > 100; $mp3->volume($VOLUME,$VOLUME,50); $$SONG{'RVAD'} = $VOLUME; $volumechanged = 1; } sub yajb_voldown { if (!$yajb_playing) { return; } $VOLUME -= 5; $VOLUME = 0 if $VOLUME < 0; $mp3->volume($VOLUME,$VOLUME,50); $$SONG{'RVAD'} = $VOLUME; $volumechanged = 1; } sub yajb_delete { yajb_deletefromplaylist(); } sub yajb_reset { yajb_resync(1); } sub yajb_edit_genre { yajb_log("yajb_edit_genre $SELECTEDARTIST"); my($song, $album); if ($currentwindownumber == $artistwinprops{'windownumber'}) { yajb_addstr($statusy, 0, ''); clrtoeol(); my($newgenre)= yajb_getTextFromUser(capitalize($SELECTEDGENRE), "Genre"); $newgenre = capitalize($newgenre); my(@aalbums)= gdbGetAlbumKeys($SELECTEDGENRE,$SELECTEDARTIST); foreach $album(@aalbums) { my(@asongs)= gdbGetSongRefs("all",$SELECTEDARTIST,$album); foreach $song ( @asongs ) { yajb_edit_id3($newgenre, GENRE(), %$song); } } } yajb_writeDB(); } sub yajb_edit { yajb_log("yajb_edit $SELECTEDARTIST $SELECTEDALBUM"); my($song, $album); if ($currentwindownumber == $artistwinprops{'windownumber'}) { yajb_addstr($statusy, 0, ''); clrtoeol(); my($newname)= yajb_getTextFromUser($SELECTEDARTIST, "Artist name"); my(@aalbums)= gdbGetAlbumKeys("all",$SELECTEDARTIST); foreach $album(@aalbums) { my(@asongs)= gdbGetSongRefs("all",$SELECTEDARTIST,$album); foreach $song ( @asongs ) { yajb_edit_id3($newname, ARTIST(), %$song); } } } elsif ($currentwindownumber == $albumwinprops{'windownumber'}) { my($newname)= yajb_getTextFromUser($SELECTEDALBUM, "Album name"); my(@asongs)= gdbGetSongRefs("all",$SELECTEDARTIST,$SELECTEDALBUM); foreach $song ( @asongs ) { yajb_log("x ".$$song{FILE()}); yajb_edit_id3($newname, ALBUM(), %$song); } } elsif ($currentwindownumber == $songwinprops{'windownumber'}) { my($idx)= $WPROPS{@windows[$currentwindownumber]}{'cursor'}; $song = @songrecs[$idx]; my($newname)= yajb_getTextFromUser("Song name"); yajb_edit_id3($newname, SONG(), %$song); } yajb_writeDB(); } sub yajb_edit_id3 { my($name, $key, %song) = @_; my($tmp) = "$ID3 "; if ($key eq "TCON") { $name = mydowncase($name); if (exists $GENRE{$name}) { $name = $GENRE{$name}; } } $tmp .= " -".$key. " \""; $tmp .= $name . "\" " . '"'. $song{FILE()} . '"'; yajb_system($tmp); yajb_removeFromDB(%song); $song{$key} = $name; yajb_add2db(%song); } sub yajb_getListNameFromUser { yajb_addstr(23, 0, "Enter playlist name:"); yajb_addstr(23, 22, ''); refresh(); echo(); my($newname); getstr($newname); yajb_addstr(23, 0, ''); clrtoeol(); yajb_addstr(24, 0, ''); clrtoeol(); refresh(); noecho(); return $newname; } sub yajb_getTextFromUser { my($oldname, $title) = @_; yajb_addstr(23, 0, "Replace:".$oldname); my($tmp)= sprintf("%-48s", " with:"); yajb_addstr(24, 0, $tmp); yajb_addstr(24, 8, ''); refresh(); echo(); my($newname); getstr($newname); yajb_addstr(23, 0, ''); clrtoeol(); yajb_addstr(24, 0, ''); clrtoeol(); refresh(); noecho(); return $newname; } sub yajb_log_data { local($msg) = @_; my($i,$n,$ch,$tmp); $n = length($msg); for($i = 0; $i < $n ; $i++ ) { $ch = substr($msg,$i,1); if ($ch ne "\n") { $tmp .= $ch; } } $tmp =~ s/ +/ /g; $tmp =~ s/'//g; $tmp =~ s/=>/=/g; $tmp =~ s/ = /=/g; $tmp =~ s/{ /{/g; $tmp =~ s/ }/}/g; $tmp =~ s/,//g; $tmp =~ s/;//g; # $tmp =~ s/position/pos/g; # $tmp =~ s/timecode/time/g; # $tmp =~ s/offset/offs/g; # $tmp =~ s/notify/ntfy/g; # $tmp =~ s/_//g; # $tmp =~ s/range/rng/g; # $tmp =~ s/code/c/g; # $tmp =~ s/method/md/g; # $tmp =~ s/name/n/g; $LOGGING=1; $ds=`date +%y%m%d-%H%M%S`; chop $ds; if ($LOGGING) { open(F, ">>/tmp/yajbdatalogfile"); print F "$ds $tmp\n"; close F; } } sub yajb_log { local($msg) = @_; $LOGGING=1; $ds=`date +%y%m%d-%H%M%S`; chop $ds; if ($LOGGING) { open(F, ">>/tmp/yajblogfile"); print F "$ds $msg\n"; close F; } } sub yajb_system_nolog { local($com) = @_; local(@ret); yajb_log("yajb_system: $com"); @ret = `$com`; # yajb_log("yajb_system returning: @ret"); return @ret; } sub yajb_system { local($com) = @_; local(@ret); yajb_log("yajb_system: $com"); @ret = `$com`; yajb_log("yajb_system returning: @ret"); return @ret; } sub yajb_add2db { my(%songdata) = @_; my($uknown) = 0; if ($songdata{ARTIST()} eq "") { $songdata{ARTIST()} = " Unknown artist"; $unknown = 1; } if ($songdata{ALBUM()} eq "") { $songdata{ALBUM()} = " Unknown album"; $unknown = 1; } if ($songdata{SONG()} eq "") { $songdata{SONG()} = " Unknown song"; $unknown = 1; } if ($songdata{GENRE()} eq "") { $songdata{GENRE()} = "unknown"; } if ($unknown == 1) { yajb_log("add2db unknown: ".$songdata{FILE()}); foreach $key(keys(%songdata)) { yajb_log($key." ".$songdata{$key}) } } my($artist) = $songdata{ARTIST()}; my($album) = $songdata{ALBUM()}; # yajb_log("add2db b4 normalize: genre: $genre"); my($genre) = normalize_genre($songdata{GENRE()}); # yajb_log("add2db after normalize: genre: $genre"); $Genres{$genre} += 1; $Genres{"all"} += 1; push(@{${${$GenreDb{$genre}}{$artist}}{$album}}, \%songdata); push(@{${${$GenreDb{"all"}}{$artist}}{$album}}, \%songdata); my(@tmp)= gdbGetSongRefs("all",$artist,$album); my($tmp); %ssfile; foreach $tmp(@tmp) { $ssfile{$tmp} = $$tmp{FILE()}; } @{${${$GenreDb{$genre}}{$artist}}{$album}} = sort songsort @tmp; @{${${$GenreDb{"all"}}{$artist}}{$album}} = sort songsort @tmp; $Albums{$album} = 0; # $tmp=""; # my($song,$genre,$tmp,$artist,$album); # foreach $genre(sort(keys(%Genres))) { # $tmp = "Genre:$genre: ". scalar(keys(%{$GenreDb{$genre}})); # foreach $artist (keys(%{$GenreDb{$genre}})) { # $tmp .= "Artist:$artist "; # foreach $album ( keys ( %{${$GenreDb{$genre}}{$artist}} )) { # $tmp .= "Album:$album "; # foreach $song (@{${${$GenreDb{$genre}}{$artist}}{$album}}) { # $tmp .= "Song:".$$song{SONG()}; # $tmp .= "\n"; # } # } # } # yajb_log($tmp); # } } sub songsort { # relies on the fact that the song file name starts with the track# return $ssfile{$a} cmp $ssfile{$b}; } sub yajb_removeFromDB { my(%song) = @_; yajb_remove1FromDB("all",%song); yajb_remove1FromDB($song{GENRE()},%song); } sub yajb_remove1FromDB { my($genre,%songrm) = @_; $genre = normalize_genre($genre); yajb_log("r1fdb: genre:$genre ".$songrm{FILE()}); my($artist) = $songrm{ARTIST()}; my($album) = $songrm{ALBUM()}; my($song) = $songrm{SONG()}; my(%songdata,$i); $i=-1; my(@songs) = gdbGetSongRefs($genre,$artist,$album); # foreach $songdata ( @{${$MusicDb{$artist}}{$album}} ) { foreach $songdata ( @songs) { my($match) = 1; $i++; foreach $key(keys(%$songdata)) { if ($$songdata{$key} ne $songrm{$key}) { $match = 0; last; } } if ($match) { yajb_log("r1fdb: genre:$genre removing: ".$songrm{FILE()}); # splice(@{${$MusicDb{$artist}}{$album}}, $i, 1); splice(@{${${$GenreDb{$genre}}{$artist}}{$album}}, $i, 1); last; } } # prune # if (scalar(@{${$MusicDb{$artist}}{$album}}) < 1) { # delete ${$MusicDb{$artist}}{$album}; if (scalar(@{${${$GenreDb{$genre}}{$artist}}{$album}}) < 1) { delete ${ $GenreDb{$genre} {$artist}} {$album}; # if (keys(%{$MusicDb{$artist}}) < 1) { # delete $MusicDb{$artist}; if (keys(%{$GenreDb{$genre}{$artist}}) < 1) { delete $GenreDb{$genre}{$artist}; if (keys(%{$GenreDb{$genre}}) < 1) { delete $GenreDb{$genre}; } } } # @Artists = sort yajb_caseignore keys %MusicDb; # @Artists = sort yajb_caseignore keys %{$GenreDb{"all"}}; } sub yajb_menu_resync { yajb_resync(1); } sub yajb_resync { my($monitor) = @_; my($file,@musicdb,@mp3files,$n,$i,$file,$tmp,$artist); my($findem)= "find $musicdir -name \"*.mp3\" -print"; $tmp = sprintf("Rereading music database...\n$findem\n"); if ($monitor) { yajb_addstr($statusy, $statusx, $tmp); refresh(); } @mp3files = yajb_system($findem); # %MusicDb = (); %GenreDb = (); # @Artists = (); %Albums = (); $ARTIST = ""; $ALBUM = ""; @mp3files = sort yajb_caseignore @mp3files; $n = scalar @mp3files; $i = 0; foreach $file(@mp3files) { chop $file; $tmp = "$ID3 ". qq("$file"); my(@id3info)= yajb_system_nolog($tmp); # construct a songdata obj for the db my(%songdata) = yajb_createsonghash($file,@id3info); # $tmp = sprintf("%d/%d %-20s %-20s %s\n",$i,$n,$songdata{ARTIST()}, # $songdata{ALBUM()}, $songdata{SONG()}); $tmp = sprintf("%d/%d",$i,$n); # yajb_log($tmp); if ($monitor) { clrtobot(); yajb_addstr($statusy+1, $statusx, $tmp); refresh(); } yajb_add2db(%songdata); yajb_log("resync: ".$songdata{SONG()}); $i++; } # @Artists = sort yajb_caseignore keys %MusicDb; # @Artists = sort yajb_caseignore keys %{$GenreDb{"all"}}; yajb_writeDB(); if ($monitor) { $tmp = "Music database initialized: $i/$n."; yajb_addstr($statusy, $statusx, $tmp); clrtobot(); refresh(); } } sub yajb_writeOne2DB { my(%song) = @_; open(MDB, ">>$musicdblocation"); print MDB yajb_serializeid3(%song)."\n"; close(MDB); } sub yajb_writeDB { my($file,@musicdb,@mp3files,$n,$i,$file,$tmp,$artist); open(MDB, ">$musicdblocation"); yajb_log("yajb_writeDB"); # foreach $artist (sort yajb_caseignore (keys(%MusicDb))) { # foreach $album(sort yajb_caseignore (keys(%{$MusicDb{$artist}}))) { # foreach $songdata ( @{${$MusicDb{$artist}}{$album}} ) { # } # } # } my($song,$genre,$tmp,$artist,$album); my(@artists,@albums,@songs); @artists = gdbGetArtistKeys("all"); foreach $artist(@artists) { # yajb_log("wdb: $artist"); @albums = gdbGetAlbumKeys("all",$artist); foreach $album(@albums) { # yajb_log("wdb: $album"); @songs = gdbGetSongRefs("all",$artist,$album); foreach $song(@songs) { # yajb_log("wdb: ".$$song{SONG()}); print MDB yajb_serializeid3(%$song)."\n"; } } } close(MDB); yajb_log("yajb_writeDB done"); } sub yajb_serializeid3 { my(%song) = @_; my($key,$data); foreach $key (sort yajb_caseignore (keys (%song))) { if ($data ne "") { $data .= '@'; } $data .= $key . ':' . yajb_escape('@', $song{$key}); } return $data; } sub yajb_escape { my($esc, $tmp) = @_; $tmp =~ s/$esc/$esc.$esc/g; return $tmp; } sub yajb_parseOneLine { my($line)= @_; my(@pairs,$key,$val,$pair,%song); @pairs = split(/@/, $line); foreach $pair(@pairs) { $key = substr($pair, 0, 4); $val = substr($pair, 5); $song{$key} = $val; } return %song; } sub yajb_unserialize { my($line) = @_; my(%song,@pairs,$key,$val,$pair); @pairs = split(/@/, $line); foreach $pair(@pairs) { $key = substr($pair, 0, 4); $val = substr($pair, 5); $song{$key} = $val; } return %song; } sub yajb_readMDBfromfile { yajb_log("yajb_readMDBfromfile"); open(MDB, "<$musicdblocation"); my($buf); read(MDB, $buf, (-s $musicdblocation)); close(MDB); my(@data); @data = split(/\n/, $buf); my($line,@pairs,$key,$val,$pair); my($i)=0; foreach $line (@data) { my(%song); %song = yajb_unserialize($line); yajb_add2db(%song); $i++; $tmp=""; $tmp = scalar(gdbGetGenreKeys()); $tmp .= " genres, "; $tmp .= scalar(gdbGetArtistKeys("all")); $tmp .= " artists, "; $tmp .= keys(%Albums); $tmp .= " albums and "; $tmp .= $i; $tmp .= " songs"; yajb_addstr($statusy,$statusx,$tmp); yajb_refresh(); } @Genres = gdbGetGenreKeys(); my($genre); $tmp=""; foreach $genre (@Genres) { $tmp .= "$genre "; } yajb_log("Genres: $tmp"); # $tmp=""; # my($song,$genre,$tmp,$artist,$album); # my(@genres,@artists,@albums,@songs); # @genres = gdbGetGenreKeys(); # foreach $genre(@genres) { # @artists = gdbGetArtistKeys($genre); # foreach $artist(@artists) { # @albums = gdbGetAlbumKeys($genre,$artist); # foreach $album(@albums) { # @songs = gdbGetSongRefs($genre,$artist,$album); # foreach $song(@songs) { # $tmp = "Genre:$genre Artist:$artist Album:$album Song:".$$song{SONG()}; # yajb_log($tmp); # } # } # } # } yajb_log("yajb_readMDBfromfile done"); } sub yajb_trimfb { local($s) = @_; $s =~ s/^ *//g; $s =~ s/ *$//g; return $s; } sub yajb_createsonghash { my($file,@id3info) = @_; my($tmp,$tmp2,$key,@data,$n,$value,%songdata); foreach $tmp (@id3info) { chop $tmp; if ($tmp =~ /^=== .... /) { ($x,$key,$tmp2) = split(/ /,$tmp); $value = yajb_trimfb(substr($tmp,9)); $songdata{$key} = $value; } } $songdata{'FILE'} = $file; # my($key); # foreach $key(sort (keys (%songdata))) { # yajb_log("csh: $key ".$songdata{$key}); # } return %songdata; } sub yajb_selectplaylist { my($cursor) = $WPROPS{$playselectwin}{'cursor'}; yajb_stop(); @Playlist = (); my($playlist)= @playselectlistkeys[$cursor]; my($songs)= @Playlists{$playlist}; my($song, @songs); foreach $song(@{$songs}) { push(@Playlist, $song); } yajb_player(); } $last_com = ""; sub yajb_handle_command { my($com,$repeat) = @_; yajb_log("command: $com, $repeat"); if ($com) { screensavertouch(); } # yajb_log("handle_command menumode $menumode"); my($sub); if ($yajb_lock) { if ($com eq "one") { $last_com .= $com; yajb_log("last_com = $last_com"); if ($last_com eq "oneoneone") { $last_com = ""; yajb_unlock(); } } else { $last_com = ""; } } elsif ($menumode == 1) { if (exists $MENUCOM{$com}) { if ($com eq 'select' || $com eq "enter") { my($cursor) = $WPROPS{$menuwin}{'cursor'}; $com = @menukeys[$cursor]; yajb_log("menucom $com"); $sub = $MENUCOM{$com}; &$sub($repeat); yajb_exitmenu(); } else { $sub = $MENUCOM{$com}; &$sub($repeat); } } } elsif ($menumode == 2) { if ($com eq 'select' || $com eq "enter") { yajb_selectplaylist(); yajb_exitloadplaylist(); } elsif (exists $PMENUCOM{$com}) { $sub = $PMENUCOM{$com}; &$sub($repeat); } } elsif ($menumode == 3 && exists $GCOM{$com}) { $sub = $GCOM{$com}; &$sub($repeat); } elsif (exists $COM{$com}) { $sub = $COM{$com}; &$sub($repeat); $NeedScreenUpdate = 1; } } sub yajb_wait_for_input { my($lin,$kin,$min,$ein); $lin = $kin = $min = $ein = ""; if ($readSocket) { vec($lin, fileno(Sx), 1) = 1; } vec($kin, fileno(Fkb), 1) = 1; if ($yajb_playing) { vec($min, $Fmp3, 1) = 1; $rin = $lin | $kin | $min; } else { $rin = $lin | $kin; } my($ssval) = screensaver(); # yajb_log("b4 select ssval=$ssval"); my($nfound)= select($rin, "", "", $ssval); # screensaver(); # my($nfound)= select($rin, "", "", 5); # yajb_log("after select"); if (!$nfound) { # yajb_log("wait_for_input timedout, no select"); yajb_player(); return; } if ($readSocket && vec($rin, fileno(Sx), 1) == 1) { my($com,$repeat) = yajb_getcommandlirc(); if ($com) { yajb_handle_command($com,$repeat); } } if (vec($rin, fileno(Fkb), 1) == 1) { my($com)= yajb_getcommandkeyboard(); if ($com) { yajb_handle_command($com,0); } } if ($yajb_playing && (vec($rin, $Fmp3, 1) == 1)) { yajb_player(); } # yajb_player(); return; } sub yajb_getcommandlirc { my($buf); sysread(Sx, $buf, 999); my($code, $repeat, $button, $remote); ($code, $repeat, $button, $remote) = split('\s', $buf); return ($button,$repeat); } sub yajb_readkey { my($buf); sysread(Fkb, $buf, 1); return ($buf); } sub yajb_getcommandkeyboard { my($ch, $och, $com); $ch = yajb_readkey(); $och = ord($ch); if ($och == 27) { $ch = yajb_readkey(); $och = ord($ch); if ($och == 91) { $ch = yajb_readkey(); $och = ord($ch); } if ($och == 53 || $och == 54) { yajb_readkey(); } } if ($menumode == 1) { if (exists($KMENUCOM{$och})) { $com = $KMENUCOM{$och} } } else { if (exists($KCOM{$och})) { $com = $KCOM{$och} } } return $com; } sub trimforwindow { my($window,$key) = @_; my($width) = $WPROPS{$window}{'cols'} -2; my($format) = "%-" . $width . "s"; $key = substr($key,0, $width); $key = sprintf($format, $key); return $key; } sub pg_findstart { my($n,$cursor,$start) = @_; my($tmp,$i,$genre); for($i = $start ; $i < $n ; $i++) { $genre = @Genres[$i]; if (length($tmp)+length($genre)+1 < 79) { $tmp .= $genre."|"; } else { last; } } if ($i > $cursor+1 || $i == $n) { return $start; } else { return pg_findstart($n,$cursor,$start+1); } } sub yajb_paint_genres { my($window) = $genrewin; my($i); my($cursor) = $WPROPS{$window}{'cursor'}; # my($keyctr) = $WPROPS{$window}{'start'}; my($width) = 79; my($numkeys) = scalar(@Genres); my($data,$x,$savex); $x = 0; my($start) = pg_findstart($numkeys,$cursor,0); for ($i = $start ; $i < $numkeys; $i++ ) { # yajb_log("pg: i:$i"); if ((length($data) + length(@Genres[$i]) + 1) < 79) { if ($i == $cursor) { eval { attron(A_BOLD) }; if ($currentwindownumber == $genrewinprops{'windownumber'} ) { $SAVEY = 0; $SAVEX = length($data); $SAVEKEY = capitalize(@Genres[$i]); $SELECTEDGENRE = @Genres[$i]; clear_selections(); } } $data .= @Genres[$i] . '|'; yajb_addstr(0, $x, capitalize(@Genres[$i])); # yajb_log("pg: i:$i \@Genres[i]:".@Genres[$i]); if ($i == $cursor) { eval { attroff(A_BOLD) }; } yajb_addstr(0, $x+length(@Genres[$i]), '|'); $x += length(@Genres[$i]) + 1; $savex = $x-1; } else { last; } } yajb_addstr(0, $savex, " "); clrtoeol(); refresh(); } sub capitalize { local($string) = @_; local($lastch,$seq,$i,$n,$rstring,$ch,$ch2); $n = length($string); for($i = 0 ; $i < $n ; $i++) { $lastch = $ch; $ch = substr($string, $i, 1); if ($i == 0 || $lastch eq " ") { $seq = unpack('C', $ch); if (97 <= $seq && $seq <= 122) { $ch = pack('C', $seq - 32); } } $rstring .= $ch; } return $rstring; } # A = 65 # Z = 90 # a = 97 # z = 122 sub clear_selections { $SELECTEDARTISTDISP = ""; $SELECTEDARTIST = ""; $SELECTEDARTISTX = ""; $SELECTEDARTISTY = ""; $SELECTEDALBUMDISP = ""; $SELECTEDALBUM = ""; $SELECTEDALBUMX = ""; $SELECTEDALBUMY = ""; $WPROPS{$artistwin}{'cursor'} = 0; $WPROPS{$albumwin}{'cursor'} = 0; } sub yajb_fillwindow { my($window, @keys) = @_; # yajb_log("fw1: w:".$windownumber{$window}." #items:".scalar(@keys)); my($i); @numitems[$windownumber{$window}] = scalar(@keys); my($cursor) = $WPROPS{$window}{'cursor'}; my($lines) = $WPROPS{$window}{'lines'}-2; my($keyctr) = $WPROPS{$window}{'start'}; my($y) = $WPROPS{$window}{'y'} + 1; my($x) = $WPROPS{$window}{'x'} + 1; my($width) = $WPROPS{$window}{'cols'} - 2; my($end) = $WPROPS{$window}{'end'}; if ($WPROPS{$window}{'windownumber'} eq $playlistwinprops{'windownumber'}) { # yajb_log("fw:1 w:$window keyctr:$keyctr cursor:$cursor end:$end"); if ($WPROPS{$window}{'windownumber'} eq $currentwindownumber && ($cursor > ($keyctr + $lines))) { $cursor = $keyctr; $WPROPS{$window}{'cursor'} = $keyctr; $WPROPS{$window}{'start'} = $keyctr; # yajb_log("fw: xyz"); # $WPROPS{$window}{'end'} = # $WPROPS{$window}{'start'} + # $WPROPS{$window}{'lines'} - 3; } } for($i = 0 ; $i < $lines ; $i++ ) { # yajb_log("fw2"); my($key) = @keys[$keyctr]; # yajb_log("fw: i:$i keyctr:$keyctr key:$key"); my($tmp) = trimforwindow($window,$key); # if ($WPROPS{$window}{'windownumber'} eq $playlistwinprops{'windownumber'}) { # yajb_log("fw:2 keyctr:$keyctr cursor:$cursor end:$end"); # } if ($keyctr eq $cursor && $WPROPS{$window}{'windownumber'} eq $currentwindownumber) { $SAVEY = $y; $SAVEX = $x; $SAVEKEY = $tmp; if ($currentwindownumber eq $artistwinprops{'windownumber'} ) { $SELECTEDARTISTDISP = $tmp; $SELECTEDARTIST = @keys[$keyctr]; $SELECTEDARTISTX = $x; $SELECTEDARTISTY = $y; } if ($currentwindownumber eq $albumwinprops{'windownumber'} ) { $SELECTEDALBUMDISP = $tmp; $SELECTEDALBUM = @keys[$keyctr]; $SELECTEDALBUMX = $x; $SELECTEDALBUMY = $y; } } if ($keyctr eq $Playlistcursor && $WPROPS{$window}{'windownumber'} eq $playlistwinprops{'windownumber'} ) { eval {attron(A_BOLD)}; } # yajb_log("fw3"); yajb_addstr($y, $x, $tmp); # yajb_log("fw: $y $x $tmp"); if ($keyctr eq $Playlistcursor && $WPROPS{$window}{'windownumber'} eq $playlistwinprops{'windownumber'}) { eval {attroff(A_BOLD)}; } $WPROPS{$window}{'end'} = $keyctr; $keyctr++; $y++; # yajb_log("fw4"); } # if ($currentwindownumber eq "2" && # $WPROPS{$window}{'windownumber'} eq $currentwindownumber) { # yajb_log(@songfile[$cursor]); # } # yajb_log("fw5"); } sub yajb_cursorup { my($adjust) = @_; $WPROPS{@windows[$currentwindownumber]}{'cursor'} -= $adjust; if ($WPROPS{@windows[$currentwindownumber]}{'cursor'} < $WPROPS{@windows[$currentwindownumber]}{'start'}) { $WPROPS{@windows[$currentwindownumber]}{'start'} -= $adjust; } if ($WPROPS{@windows[$currentwindownumber]}{'cursor'} < 0) { $WPROPS{@windows[$currentwindownumber]}{'cursor'} = 0; } if ($WPROPS{@windows[$currentwindownumber]}{'start'} < 0) { $WPROPS{@windows[$currentwindownumber]}{'start'} = 0; } $WPROPS{@windows[$currentwindownumber]}{'end'} = $WPROPS{@windows[$currentwindownumber]}{'start'} + $WPROPS{@windows[$currentwindownumber]}{'lines'}-3; yajb_updatecursors(); } sub yajb_goto_bottom { my($win) = @_; $WPROPS{@windows[$win]}{'end'} = $#Playlist; $WPROPS{@windows[$win]}{'start'} = $WPROPS{@windows[$win]}{'end'} - 8; if ($WPROPS{@windows[$win]}{'start'} < 0) { $WPROPS{@windows[$win]}{'start'} = 0; } } sub yajb_cursordown { my($adjust) = @_; # yajb_log("cd1: cwn:$currentwindownumber cursor:".$WPROPS{@windows[$currentwindownumber]}{'cursor'}." start:".$WPROPS{@windows[$currentwindownumber]}{'start'}); $WPROPS{@windows[$currentwindownumber]}{'cursor'} += $adjust; # yajb_log("cd2: cwn:$currentwindownumber cursor:".$WPROPS{@windows[$currentwindownumber]}{'cursor'}." start:".$WPROPS{@windows[$currentwindownumber]}{'start'}); if ($WPROPS{@windows[$currentwindownumber]}{'cursor'} > $WPROPS{@windows[$currentwindownumber]}{'end'}) { $WPROPS{@windows[$currentwindownumber]}{'end'} += $adjust; } if ($WPROPS{@windows[$currentwindownumber]}{'cursor'} > @numitems[$currentwindownumber]-1) { $WPROPS{@windows[$currentwindownumber]}{'cursor'} = @numitems[$currentwindownumber]-1; } # yajb_log("cd3: cwn:$currentwindownumber cursor:".$WPROPS{@windows[$currentwindownumber]}{'cursor'}." start:".$WPROPS{@windows[$currentwindownumber]}{'start'}); if ($WPROPS{@windows[$currentwindownumber]}{'end'} > @numitems[$currentwindownumber]-1) { $WPROPS{@windows[$currentwindownumber]}{'end'} = @numitems[$currentwindownumber]-1; } $WPROPS{@windows[$currentwindownumber]}{'start'} = $WPROPS{@windows[$currentwindownumber]}{'end'} - ($WPROPS{@windows[$currentwindownumber]}{'lines'}-3); if ($WPROPS{@windows[$currentwindownumber]}{'start'} < 0) { $WPROPS{@windows[$currentwindownumber]}{'start'} = 0; } # yajb_log("cd4: cwn:$currentwindownumber cursor:".$WPROPS{@windows[$currentwindownumber]}{'cursor'}." start:".$WPROPS{@windows[$currentwindownumber]}{'start'}); yajb_updatecursors(); # yajb_log("cd5: cwn:$currentwindownumber cursor:".$WPROPS{@windows[$currentwindownumber]}{'cursor'}." start:".$WPROPS{@windows[$currentwindownumber]}{'start'}); } sub yajb_cursorright { $currentwindownumber++; if ($currentwindownumber > 3) { $currentwindownumber = 0; } } sub yajb_cursorleft { $currentwindownumber -= 1; if ($currentwindownumber < 0) { $currentwindownumber = 4; yajb_updatecursors(); } if ($currentwindownumber == $genrewinprops{'windownumber'} ) { $menumode = 3; unhighlight(); $SAVEY4GENRE = $SAVEY; $SAVEX4GENRE = $SAVEX; $SAVEKEY4GENRE = $SAVEKEY; $SAVEY = ""; } } sub yajb_updatecursors { if ($currentwindownumber eq $artistwinprops{'windownumber'} ) { yajb_zerocursors(1); yajb_zerocursors(2); $SELECTEDALBUM = ""; } elsif ($currentwindownumber eq $albumwinprops{'windownumber'} ) { yajb_zerocursors(2); } if ($currentwindownumber eq $genrewinprops{'windownumber'} ) { yajb_zerocursors(0); yajb_zerocursors(1); yajb_zerocursors(2); } } sub yajb_zerocursors { my($win) = @_; $WPROPS{@windows[$win]}{'cursor'} = 0; $WPROPS{@windows[$win]}{'start'} = 0; $WPROPS{@windows[$win]}{'end'} = $WPROPS{@windows[$win]}{'start'} + $WPROPS{@windows[$win]}{'lines'} - 3; } # @albums = sort yajb_year_sort keys(%albums); sub yajb_add2playlist { my($song, $album); $years=""; my($n) = scalar(@Playlist); if ($n == 0) { yajb_log("a2p: 1st"); } if ($currentwindownumber == $genrewinprops{'windownumber'} ) { if ($SELECTEDGENRE eq "all") { yajb_addstr($statusy, $statusx, "Operation not permitted"); clrtoeol(); refresh(); sleep(1); yajb_addstr($statusy, $statusx, ""); clrtoeol(); refresh(); } else { my(@artists) = gdbGetArtistKeys($SELECTEDGENRE); my($artist); foreach $artist(@artists) { my(@albums) = gdbGetAlbumKeys($SELECTEDGENRE,$artist); foreach $album(@albums) { yajb_log("add2playlist $album"); my(@songs) = gdbGetSongRefs($SELECTEDGENRE,$artist,$album); foreach $song ( @songs) { yajb_addsong2playlist($song); } } } } } elsif ($currentwindownumber == $artistwinprops{'windownumber'} ) { # foreach $album(keys(%{$MusicDb{$SELECTEDARTIST}})) { # $years{$album} = %{$MusicDb{$SELECTEDARTIST}}->{$album}[0]->{'TYER'}; # } # foreach $album(sort yajb_year_sort (keys(%{$MusicDb{$SELECTEDARTIST}}))) { my(@albums) = gdbGetAlbumKeys($SELECTEDGENRE,$SELECTEDARTIST); foreach $album(@albums) { yajb_log("add2playlist $album"); my(@songs) = gdbGetSongRefs($SELECTEDGENRE,$SELECTEDARTIST,$album); foreach $song ( @songs) { yajb_log("yajb_add2playlistx ".$$song{SONG()}); yajb_addsong2playlist($song); } } } elsif ($currentwindownumber == $albumwinprops{'windownumber'} ) { my(@songs) = gdbGetSongRefs($SELECTEDGENRE,$SELECTEDARTIST,$SELECTEDALBUM); foreach $song ( @songs) { yajb_log("yajb_add2playlist ".$$song{SONG()}); yajb_addsong2playlist($song); } } elsif ($currentwindownumber == $songwinprops{'windownumber'} ) { my($idx)= $WPROPS{@windows[$currentwindownumber]}{'cursor'}; $song = @{${${$GenreDb{$SELECTEDGENRE}}{$SELECTEDARTIST}}{$SELECTEDALBUM}}[$idx]; yajb_addsong2playlist($song); } # yajb_zerocursors(3); if ($n) { $WPROPS{@windows[$playlistwinprops{'windownumber'}]}{'cursor'} = scalar(@Playlist)-1; $WPROPS{@windows[$playlistwinprops{'windownumber'}]}{'start'} = (scalar(@Playlist)-1) - ($WPROPS{@windows[3]}{'lines'} - 3); } # $WPROPS{@windows[$playlistwinprops{'windownumber'}]}{'end'} = # $WPROPS{@windows[$playlistwinprops{'windownumber'}]}{'start'} + # $WPROPS{@windows[$playlistwinprops{'windownumber'}]}{'lines'} - 3; yajb_player(); } sub yajb_addsong2playlist { my($song) = @_; push(@Playlist, $song); # yajb_log("addsong2playlist ". $$song{FILE()}); yajb_goto_bottom(3); } sub yajb_deletefromplaylist { if ($currentwindownumber != $playlistwinprops{'windownumber'} ) { return; } my($idx) = $WPROPS{@windows[3]}{'cursor'}; if (!($idx >= 0 && scalar(@Playlist))) { return; } splice(@Playlist, $idx, 1); if ($WPROPS{@windows[3]}{'cursor'} > (scalar(@Playlist)-1)) { $WPROPS{@windows[3]}{'cursor'} = scalar(@Playlist)-1; } if ($WPROPS{@windows[3]}{'cursor'} < 0) { $WPROPS{@windows[3]}{'cursor'} = 0; } } sub yajb_refresh { if ($SAVEY ne "") { eval { attron(A_REVERSE) }; yajb_addstr($SAVEY, $SAVEX, $SAVEKEY); eval { attroff(A_REVERSE) }; } refresh(); } sub yajb_addstr { local($a,$b,$c) = @_; addstr($a, $b, $c); } sub yajb_player { if ($yajb_playing) { my($msg)= $mp3->get_message; if (defined $msg) { my($tmp)= sprintf("%s", Dumper($msg)); yajb_log_data($tmp); my($code)= $msg->{code}; if ($code == &XA_MSG_NOTIFY_INPUT_TIMECODE ) { my($tmp)= sprintf("%02d %02d:%02d/%02d:%02d %-65s", $VOLUME, $msg->{timecode_m}, $msg->{timecode_s}, $dur_min, $dur_sec, substr($$SONG{ARTIST()}.' / '.$$SONG{ALBUM()}.' / '.$$SONG{SONG()},0,65)); yajb_addstr($statusy, $statusx, $tmp); yajb_refresh(); yajb_disp_pause(); } elsif ($code == &XA_MSG_NOTIFY_PLAYER_STATE) { if ($msg->{state} == &XA_PLAYER_STATE_EOF) { $yajb_playing = 0; $mp3->close; yajb_player(); } } elsif ($code == 81) { $duration = $msg->{duration}; $dur_min = $duration / 60; $dur_sec = $duration % 60; } } } else { if (scalar(@Playlist)) { incrementPlaylistcursor(); $SONG = @Playlist[$Playlistcursor]; $mp3->open($$SONG{FILE()}); if (exists($$SONG{'RVAD'}) && $$SONG{'RVAD'} > 0 && $$SONG{'RVAD'} <= 100) { $VOLUME = $$SONG{'RVAD'}; } else { $VOLUME = $VOLUME_DEFAULT; } $VOLUME = $VOLUME_DEFAULT; $yajb_playing = 1; $Fmp3 = $mp3->get_command_read_pipe; $mp3->equalizer(); # delete the equalizer yajb_play(); $mp3->volume($VOLUME,$VOLUME,50); yajb_log("yajb_playing ".$$SONG{FILE()}); } } } sub unhighlight { eval {attron(A_BOLD)}; eval { attroff(A_REVERSE) }; yajb_log("unhighlight $SAVEY, $SAVEX, $SAVEKEY"); yajb_addstr($SAVEY, $SAVEX, $SAVEKEY); eval {attroff(A_BOLD)}; refresh(); } sub yajb_add1song { my($file) = @_; my($tmp)= "$ID3 ". qq("$file"); my(@id3info)= yajb_system($tmp); my(%song) = yajb_createsonghash($file,@id3info); yajb_writeOne2DB(%song); } sub yajb_initwins { @windows = (); %WPROPS = {}; $artistwin = subwin($artistwinprops{'lines'}, $artistwinprops{'cols'}, $artistwinprops{'y'}, $artistwinprops{'x'}); $WPROPS{$artistwin} = \%artistwinprops; @windows[0] = $artistwin; $albumwin = subwin($albumwinprops{'lines'}, $albumwinprops{'cols'}, $albumwinprops{'y'}, $albumwinprops{'x'}); $WPROPS{$albumwin} = \%albumwinprops; @windows[1] = $albumwin; $songwin = subwin($songwinprops{'lines'}, $songwinprops{'cols'}, $songwinprops{'y'}, $songwinprops{'x'}); $WPROPS{$songwin} = \%songwinprops; @windows[2] = $songwin; $playlistwin = subwin($playlistwinprops{'lines'}, $playlistwinprops{'cols'}, $playlistwinprops{'y'}, $playlistwinprops{'x'}); $WPROPS{$playlistwin} = \%playlistwinprops; @windows[3] = $playlistwin; $genrewin = 'genrewin'; $WPROPS{$genrewin} = \%genrewinprops; @windows[4] = $genrewin; eval { box($albumwin, ACS_VLINE, ACS_HLINE,) }; eval { box($artistwin, ACS_VLINE, ACS_HLINE,) }; eval { box($songwin, ACS_VLINE, ACS_HLINE,) }; eval { box($playlistwin, ACS_VLINE, ACS_HLINE,) }; yajb_addstr($WPROPS{$artistwin}{'y'}, $WPROPS{$artistwin}{'x'}+1, "Artists"); yajb_addstr($WPROPS{$albumwin}{'y'}, $WPROPS{$albumwin}{'x'}+1, "Albums"); yajb_addstr($WPROPS{$songwin}{'y'}, $WPROPS{$songwin}{'x'}+1, "Songs"); yajb_addstr($WPROPS{$playlistwin}{'y'}, $WPROPS{$playlistwin}{'x'}+1, "Playlist"); %windownumber = (); $windownumber{$artistwin} = 0; $windownumber{$albumwin} = 1; $windownumber{$songwin} = 2; $windownumber{$playlistwin} = 3; $windownumber{$menuwin} = 7; $windownumber{$genrewin} = 4; } sub yajb_sort_albums { my(%albums) = @_; my(@albums); my($album); $years=""; foreach $album(keys(%albums)) { $years{$album} = $albums{$album}[0]->{'TYER'}; # yajb_log("sort albums $album ". $albums{$album}[0]->{'TYER'}); } @albums = sort yajb_year_sort keys(%albums); } sub yajb_year_sort { # yajb_log("year_sort ". $years{$a}." ". $years{$b}); if ($years{$a} eq $years{$b}) { return $a cmp $b; } else { return $years{$a} cmp $years{$b}; } } sub yajb_update_screen { # yajb_log("update_screen menumode $menumode ########################################"); if ($menumode == 1) { @numitems[$menuwinprops{'windownumber'}] = scalar(@menuchoices); yajb_fillwindow($menuwin, @menuchoices); # yajb_log("us: menumode = 1"); # yajb_log("us: cwn:$currentwindownumber cursor:".$WPROPS{@windows[$currentwindownumber]}{'cursor'}); yajb_refresh(); return; } elsif ($menumode == 2) { @numitems[$playselectwinprops{'windownumber'}]= scalar(@playselectlistkeys); # yajb_log("us:"); # yajb_log(scalar(@playselectlistkeys)); # yajb_log($playselectwinprops{'windownumber'}); yajb_fillwindow($playselectwin, @playselectlistkeys); my($playlist) = @playselectlistkeys[$WPROPS{$playselectwin}{'cursor'}]; # yajb_log("update_screen playlist $playlist"); my($songs) = @Playlists{$playlist}; my($song, @songs); foreach $song(@{$songs}) { # yajb_log("update_screen song: ".$$song{SONG()}); my($tmp)= substr($$song{ARTIST()},0,20).' / '.$$song{SONG()}; push(@songs, $tmp); } @numitems[$playsellistwinprops{'windownumber'}] = scalar(@songs); yajb_fillwindow($playsellistwin, @songs); yajb_refresh(); return; } if (!$NeedScreenUpdate) { return; } # paint genres yajb_paint_genres(); # paint artist window my(@Artists) = gdbGetArtistKeys($SELECTEDGENRE); yajb_fillwindow($artistwin, @Artists); # paint album window $ARTIST = @Artists[$WPROPS{$artistwin}{'cursor'}]; @albums = gdbGetAlbumKeys($SELECTEDGENRE,$ARTIST); $tmp=""; foreach $album(@albums) { $tmp .= "$album "; } yajb_fillwindow($albumwin, @albums); # paint song window $ALBUM = @albums[$WPROPS{$albumwin}{'cursor'}]; @songs = (); $tmp=""; @songfile = (); @songrecs = (); my($song); my(@songrefss) = gdbGetSongRefs($SELECTEDGENRE,$ARTIST,$ALBUM); foreach $song(@songrefss) { $tmp .= $$song{SONG()}; push(@songs, $$song{SONG()}); push(@songfile, $$song{'FILE'}); push(@songrecs, $song); } yajb_fillwindow($songwin, @songs); # paint playlist window @playlistsongs = (); foreach $song(@Playlist) { my($tmp)= substr($$song{ARTIST()},0,20).' / '.$$song{SONG()}; push(@playlistsongs, $tmp); } # @numitems[$playlistwinprops{'windownumber'}] = scalar(@playlistsongs); yajb_fillwindow($playlistwin, @playlistsongs); # yajb_log("us4"); # yajb_log("us5"); # highlight selections if ($SELECTEDARTIST eq "") { $SELECTEDARTIST = $ARTIST; $SELECTEDARTISTDISP = trimforwindow($artistwin,$ARTIST); $SELECTEDARTISTX = $artistwinprops{'cols'} + 1; $SELECTEDARTISTX = $artistwinprops{'x'} + 1; $SELECTEDARTISTY = $artistwinprops{'y'} + 1; } if ($SELECTEDARTIST ne "" && $SELECTEDARTISTX ne "" && $SELECTEDARTISTY ne "") { eval { attron(A_BOLD) }; yajb_addstr($SELECTEDARTISTY, $SELECTEDARTISTX, $SELECTEDARTISTDISP); eval { attroff(A_BOLD) }; } if ($SELECTEDALBUM eq "") { $SELECTEDALBUM = $ALBUM; $SELECTEDALBUMDISP = trimforwindow($albumwin,$ALBUM); $SELECTEDALBUMX = $albumwinprops{'cols'} + 1; $SELECTEDALBUMY = $albumwinprops{'y'} + 1; } if ($SELECTEDALBUM ne "" && $SELECTEDALBUMX ne "" && $SELECTEDALBUMY ne "") { eval { attron(A_BOLD) }; yajb_addstr($SELECTEDALBUMY, $SELECTEDALBUMX, $SELECTEDALBUMDISP); eval { attroff(A_BOLD) }; } if ($SAVEY ne "") { eval { attron(A_REVERSE) }; yajb_addstr($SAVEY, $SAVEX, $SAVEKEY); eval { attroff(A_REVERSE) }; } refresh(); $NeedScreenUpdate = 0; # yajb_log("us6"); } # # main # open(F,">/var/run/yajb.pid"); print F $$."\n"; close(F); $screensavertimer = 0; $screensaverison = 0; # init logfile open(F, ">/tmp/yajblogfile"); print F "\n"; close(F); $musicdir="/music/music/new0510"; $musicdblocation = "/tmp/yajb.db"; $playlistlocation = "/tmp"; $ID3 = "id3"; $yajb_playing = 0; # %MusicDb = (); $ARTIST = ""; $ALBUM = ""; $SONG = ""; $VOLUME_DEFAULT = 100; $yajb_locked = 0; @menuchoices = ( "Exit", "Shuffle Playlist", "Clear Playlist", "Save Playlist", "Load Playlist", "Pause", "Play", "Stop", "Save Volume", "Resync", "Lock"); @menukeys = ( "exit", "shuffle", "clear", "saveplaylist", "loadplaylist", "pause", "play", "stop", "savevolume", "sync", "lock" ); %KMENUCOM= (); %MENUCOM = (); $KMENUCOM{'65'} = 'up'; $MENUCOM{'up'} = \&yajb_up; $KMENUCOM{'66'} = 'down'; $MENUCOM{'down'} = \&yajb_down; $KMENUCOM{'10'} = 'enter'; $MENUCOM{'enter'} = \&yajb_enter; $KMENUCOM{'13'} = 'enter'; $KMENUCOM{ord('x')} = 'exit'; $MENUCOM{'exit'} = \&yajb_exitmenu; $MENUCOM{'shuffle'} = \&yajb_shuffle; $MENUCOM{'clear'} = \&yajb_clear; $MENUCOM{'pause'} = \&yajb_pause; $MENUCOM{'stop'} = \&yajb_stop; $MENUCOM{'savevolume'} = \&yajb_savevolume; $MENUCOM{'sync'} = \&yajb_resync; $MENUCOM{'play'} = \&yajb_play; $MENUCOM{'select'} = \&yajb_enter; $MENUCOM{'saveplaylist'}= \&yajb_saveplaylist; $MENUCOM{'loadplaylist'}= \&yajb_loadplaylist; $MENUCOM{'lock'}= \&yajb_lock; %KPMENUCOM= (); %PMENUCOM = (); $KPMENUCOM{'65'} = 'up'; $PMENUCOM{'up'} = \&yajb_up; $KPMENUCOM{'66'} = 'down'; $PMENUCOM{'down'} = \&yajb_down; $KPMENUCOM{'10'} = 'enter'; $PMENUCOM{'enter'} = \&yajb_enter; $KPMENUCOM{'13'} = 'enter'; $KPMENUCOM{ord('x')} = 'exit'; $PMENUCOM{'exit'} = \&yajb_exitloadplaylist; $PMENUCOM{'select'} = \&yajb_enter; %KCOM = (); %COM = (); $KCOM{ord('<')} = 'rewind'; $COM{'rewind'} = \&yajb_rewind; $KCOM{ord('>')} = 'play'; $COM{'play'} = \&yajb_play; $KCOM{ord('f')} = 'forward'; $COM{'forward'} = \&yajb_forward; $KCOM{ord('s')} = 'stop'; $COM{'stop'} = \&yajb_stop; $KCOM{ord('p')} = 'pause'; $COM{'pause'} = \&yajb_pause; $KCOM{ord('1')} = 'one'; $COM{'one'} = \&yajb_one; $KCOM{ord('2')} = 'two'; $COM{'two'} = \&yajb_two; $KCOM{ord('3')} = 'three'; $COM{'three'} = \&yajb_three; $KCOM{ord('4')} = 'four'; $COM{'four'} = \&yajb_four; $KCOM{ord('5')} = 'five'; $COM{'five'} = \&yajb_five; $KCOM{ord('6')} = 'six'; $COM{'six'} = \&yajb_six; $KCOM{ord('7')} = 'seven'; $COM{'seven'} = \&yajb_seven; $KCOM{ord('8')} = 'eight'; $COM{'eight'} = \&yajb_eight; $KCOM{ord('9')} = 'nine'; $COM{'nine'} = \&yajb_nine; $KCOM{ord('0')} = 'zero'; $COM{'zero'} = \&yajb_zero; $KCOM{ord('d')} = 'display'; $COM{'display'} = \&yajb_display; $KCOM{'10'} = 'enter'; $COM{'enter'} = \&yajb_enter; $KCOM{'13'} = 'enter'; $COM{'enter'} = \&yajb_enter; $COM{'select'} = \&yajb_enter; $KCOM{ord('i')} = 'index'; $COM{'index'} = \&yajb_index; $KCOM{ord('c')} = 'category'; $COM{'category'}= \&yajb_category; $KCOM{ord('g')} = 'genre'; $COM{'genre'} = \&yajb_edit_genre; $KCOM{'65'} = 'up'; $COM{'up'} = \&yajb_up; $KCOM{'67'} = 'right'; $COM{'right'} = \&yajb_right; $KCOM{'66'} = 'down'; $COM{'down'} = \&yajb_down; $KCOM{'68'} = 'left'; $COM{'left'} = \&yajb_left; $KCOM{ord('j')} = 'jump'; $COM{'jump'} = \&yajb_jump; $KCOM{ord('x')} = 'exit'; $COM{'exit'} = \&yajb_exit; $KCOM{ord('c')} = 'clear'; $COM{'clear'} = \&yajb_clear; $KCOM{ord('m')} = 'menu'; $COM{'menu'} = \&yajb_menu; $KCOM{ord('a')} = 'favorite'; $COM{'favorite'}= \&yajb_favorite; $KCOM{ord('7')} = 'chup'; $COM{'chup'} = \&yajb_chup; $KCOM{'53'} = 'chup'; $COM{'chup'} = \&yajb_chup; $KCOM{ord('1')} = 'chdown'; $COM{'chdown'} = \&yajb_chdown; $KCOM{'54'} = 'chdown'; $COM{'chdown'} = \&yajb_chdown; $KCOM{ord('+')} = 'volup'; $COM{'volup'} = \&yajb_volup; $KCOM{ord('-')} = 'voldown'; $COM{'voldown'} = \&yajb_voldown; $KCOM{'127'} = 'delete'; $COM{'delete'} = \&yajb_delete; $KCOM{ord('z')} = 'reset'; $COM{'reset'} = \&yajb_reset; $KCOM{ord('e')} = 'edit'; $COM{'edit'} = \&yajb_edit; %KGCOM = (); %GCOM = (); $KGCOM{ord('<')} = 'rewind'; $GCOM{'rewind'} = \&yajb_rewind; $KGCOM{ord('>')} = 'play'; $GCOM{'play'} = \&yajb_play; $KGCOM{ord('f')} = 'forward'; $GCOM{'forward'} = \&yajb_forward; $KGCOM{ord('s')} = 'stop'; $GCOM{'stop'} = \&yajb_stop; $KGCOM{ord('p')} = 'pause'; $GCOM{'pause'} = \&yajb_pause; $KGCOM{'65'} = 'up'; $GCOM{'up'} = \&yajb_genre_up; $KGCOM{'67'} = 'right'; $GCOM{'right'} = \&yajb_genre_right; $KGCOM{'66'} = 'down'; $GCOM{'down'} = \&yajb_genre_down; $KGCOM{'68'} = 'left'; $GCOM{'left'} = \&yajb_genre_left; $KGCOM{ord('m')} = 'menu'; $GCOM{'menu'} = \&yajb_menu; $KGCOM{ord('+')} = 'volup'; $GCOM{'volup'} = \&yajb_volup; $KGCOM{ord('-')} = 'voldown'; $GCOM{'voldown'} = \&yajb_voldown; $KGCOM{'10'} = 'enter'; $GCOM{'enter'} = \&yajb_enter; $KGCOM{'13'} = 'enter'; $GCOM{'enter'} = \&yajb_enter; $GCOM{'select'} = \&yajb_enter; # # id3keys # %ID3KEYS = ( "ARTIST", "TPE1", "ALBUM", "TALB", "SONG", "TIT2", "GENRE", "TCON", "TRACK", "TRCK", "COMMENT", "COMM", "COPYRIGHT", "TCOP", "LENGTH", "TLEN", "YEAR", "TYER", "LYRIC", "USLT", "COMMERCIAL","WCOM", "WEB", "WOAR", "FILE", "FILE"); sub ARTIST { return $ID3KEYS{'ARTIST'}; } sub ALBUM { return $ID3KEYS{'ALBUM'}; } sub SONG { return $ID3KEYS{'SONG'}; } sub GENRE { return $ID3KEYS{'GENRE'}; } sub FILE { return $ID3KEYS{'FILE'}; } if (@ARGV[0] eq '-d') { $mytty = @ARGV[1]; } else { @mytty = yajb_system('tty'); $mytty = @mytty[0]; chop $mytty; } if (@ARGV[0] eq '-z') { yajb_resync(0); yajb_exit(); } if (@ARGV[0] eq '-a') { yajb_add1song(@ARGV[1]); yajb_exit(); } $do_genre_table = 0; if (@ARGV[0] eq '-g') { $do_genre_table = 1; } if (@ARGV[0] eq '-fg') { $do_genre_table = 2; } @Playlist = (); $Playlistcursor = -1; initscr(); # start_color(); # refresh(); %artistwinprops = {}; $artistwinprops{'lines'} = 11; $artistwinprops{'cols'} = 39; $artistwinprops{'y'} = 1; $artistwinprops{'x'} = 0; $artistwinprops{'cursor'} = 0; $artistwinprops{'start'} = 0; $artistwinprops{'end'} = $artistwinprops{'start'} + $artistwinprops{'lines'} - 3; $artistwinprops{'windownumber'} = 0; $artistwinprops{'#items'} = 0; $PAGE = $artistwinprops{'lines'} - 3; %albumwinprops = {}; $albumwinprops{'lines'} = 11; $albumwinprops{'cols'} = 39; $albumwinprops{'y'} = 1; $albumwinprops{'x'} = 39; $albumwinprops{'cursor'} = 0; $albumwinprops{'start'} = 0; $albumwinprops{'end'} = $albumwinprops{'start'} + $albumwinprops{'lines'} - 3; $albumwinprops{'windownumber'} = 1; $albumwinprops{'#items'} = 0; %songwinprops = {}; $songwinprops{'lines'} = 11; $songwinprops{'cols'} = 39; $songwinprops{'y'} = 12; $songwinprops{'x'} = 0; $songwinprops{'cursor'} = 0; $songwinprops{'start'} = 0; $songwinprops{'end'} = $songwinprops{'start'} + $songwinprops{'lines'} - 3; $songwinprops{'windownumber'} = 2; $songwinprops{'#items'} = 0; %playlistwinprops = {}; $playlistwinprops{'lines'} = 11; $playlistwinprops{'cols'} = 39; $playlistwinprops{'y'} = 12; $playlistwinprops{'x'} = 39; $playlistwinprops{'cursor'} = 0; $playlistwinprops{'start'} = 0; $playlistwinprops{'end'} = $playlistwinprops{'start'} + $playlistwinprops{'lines'} - 3; $playlistwinprops{'windownumber'} = 3; $playlistwinprops{'#items'} = 0; %menuwinprops = {}; $menuwinprops{'lines'} = 11; $menuwinprops{'cols'} = 39; $menuwinprops{'y'} = 5; $menuwinprops{'x'} = 20; $menuwinprops{'cursor'} = 0; $menuwinprops{'start'} = 0; $menuwinprops{'end'} = $menuwinprops{'start'} + $menuwinprops{'lines'} - 3; $menuwinprops{'windownumber'} = 7; $menuwinprops{'#items'} = 0; %playselectwinprops = {}; $playselectwinprops{'lines'} = 11; $playselectwinprops{'cols'} = 24; $playselectwinprops{'y'} = 5; $playselectwinprops{'x'} = 3; $playselectwinprops{'cursor'} = 0; $playselectwinprops{'start'} = 0; $playselectwinprops{'end'} = $playselectwinprops{'start'} + $playselectwinprops{'lines'} - 3; $playselectwinprops{'windownumber'} = 5; $playselectwinprops{'#items'} = 0; %playsellistwinprops = {}; $playsellistwinprops{'lines'} = 18; $playsellistwinprops{'cols'} = 49; $playsellistwinprops{'y'} = 2; $playsellistwinprops{'x'} = 27; $playsellistwinprops{'cursor'} = 0; $playsellistwinprops{'start'} = 0; $playsellistwinprops{'end'} = $playsellistwinprops{'start'} + $playsellistwinprops{'lines'} - 3; $playsellistwinprops{'windownumber'} = 6; $playsellistwinprops{'#items'} = 0; @Genres = ( 'All', 'Country', 'Rock', 'Pop', 'Christmas', 'Classical' ); %Genres = (); %genrewinprops = {}; $genrewinprops{'lines'} = 1; $genrewinprops{'cols'} = 79; $genrewinprops{'y'} = 0; $genrewinprops{'x'} = 0; $genrewinprops{'cursor'} = 0; $genrewinprops{'start'} = 0; $genrewinprops{'end'} = scalar(@Genres); $genrewinprops{'windownumber'} = 4; $genrewinprops{'#items'} = scalar(@Genres); $statusx = 0; $statusy = 23; noecho(); cbreak(); $screensavertimer = time(); yajb_initwins(); eval { attroff(A_BLINK) }; #yajb_system("das /usr/local/sbin/lircd"); socket(Sx, PF_UNIX, SOCK_STREAM, 0) or die "socket: $!"; setsockopt(Sx, SOL_SOCKET, SO_REUSEADDR, 1) or warn "Can't do setsockopt: $!\n"; $readSocket = 1; if (!connect(Sx,sockaddr_un("/dev/lircd"))) { $readSocket = 0; } # system "stty", "-icanon", "eol"; system "stty cbreak <$mytty >$mytty 2>&1"; open(Fkb, "