# included script to provide platter search # artist, album, song, date, number of random tracks to take, # scope (misc or album), inventory # # returns list of matching lines package Search; use Globals; use Globals qw(@CUSTOM); use Globals qw($delim); use Globals qw($debug); use Globals qw(%PLATTERS); use strict; my $artist = undef; my $title = undef; my $album = undef; my $dateFrom = undef; my $dateTo = undef; my $scope = undef; my $random = undef; my $exclTypes = undef; my $exact = 0; my $searchFor = undef; #artist|album|track my @inv = (); my @filter = (); my %ABCS; return 1; sub setArtist { my ($thisartist) = @_; $thisartist =~ s/^The //i; $thisartist =~ s/, The$//i; $artist = $thisartist; } sub setTitle { $title = $_[0]; } sub setAlbum { $album = $_[0]; } sub setDateFrom { ($dateFrom) = @_ unless ($_[0] =~ /^1900$/); } sub setDateTo { ($dateTo) = @_ unless ($_[0] =~ /^2525$/); } sub setScope { ($scope) = @_; $scope = 'all' if (!$scope); } sub setRandom { ($random) = @_; } sub setInv { @inv = @_; } sub setExact { ($exact) = @_; } sub setFilter { @filter = @_; } sub setExclTypes { ($exclTypes) = @_; } sub searchFor { ($searchFor) = @_; } sub go { my @result = (); #load abcs if ($searchFor eq 'artist') { %ABCS = getABCs() } # decide if we can skip opening the inventories my $pureArtistSearch = ($searchFor eq 'artist' && !$title && !$album && !$dateFrom && !$dateTo && $scope eq 'all'); # loop through each platter @inv = keys %PLATTERS if (!@inv); foreach (@inv) { my $platter = $_; my $base; # Check the artist cache if (open (ARTIST, "../inventory/".$platter.".artist")) { my $useplatter; while () { chomp; my $thisArtist = $_; if (!$artist || ($exact && # want exact match $thisArtist =~ /^\Q$artist\E$/i) || (!$exact && # not exact $thisArtist =~ /\Q$artist\E/i)) { if (!$exact && # but we weren't doing an exact search $thisArtist =~ /^\Q$artist\E$/i && $searchFor eq 'artist' && $artist) { # bail out just returning the artist name for redirect return (makeNice($thisArtist)); } if ($pureArtistSearch) { # store in result push (@result, makeABC($thisArtist)); } else { # examine this platter further $useplatter = 1; print "Using $platter\n" if ($debug); last; } } } next if !$useplatter; } if (!$pureArtistSearch) { # Only continue with full inv search if artist cache didn't populate the results # Open the inventory open (PLATTER, "../inventory/".$platter.".inv"); while () { chomp; my $raw = $_; if ($raw =~ /^http\:\/\//) { # is the base url $base = $raw; next; } my ($folder, $trackartist, $trackalbum, $year, $track, $url) = split ($delim, $raw); # apply filter my $filetype = substr($url, rindex($url, '.')+1); next if ($exclTypes =~ /$filetype,/); if ($#filter > -1) { my $match = 0; #print "$filetype\n"; foreach( @filter ) { if (/^$filetype$/i) { $match = 1; last; } } if (!$match) { next; } } # Match Scope if ($scope && $scope ne "all") { if (length ($trackalbum) == 0) { next if ($scope eq 'album'); } else { next if ($scope eq 'misc'); } } # Match Track Title if ($title) { unless (($exact && # want exact match $track =~ /^(\d{2} - |)\Q$title\E(\.[^\.]*|)$/i) || (!($exact) && # not exact $track =~ /\Q$title\E/i)) { next; } } # Match Artist if ($artist) { unless ($exact && # want exact match ($folder =~ /^\Q$artist\E$/i || # artist folder ($trackartist =~ /^\Q$artist\E$/i )) # track artist (not on album searches) || (!($exact) && # not exact ($folder =~ /\Q$artist\E/i || # artist folder $trackartist =~ /\Q$artist\E/i))) { # track artist next; } } # Set the album to misc if needed if (!$trackalbum) { $trackalbum = 'Miscellany'; } # Match Album Title if ($album) { unless (($exact && # want exact match ($trackalbum =~ /^\Q$album\E\//i || $album =~ /^\Q$trackalbum\E(\/|$)/i)) # allow subfolders and parents || (!$exact && # not exact $trackalbum =~ /\Q$album\E/i)) { next; } } # Match Dates if (($dateFrom || $dateTo)) { if (defined $year && (($dateFrom && $year < $dateFrom ) || ($dateTo && $year > $dateTo ))) { next; } } # Store Result if ($searchFor eq 'artist') { if ($folder) { foreach (@CUSTOM) { $folder = undef if (/^$folder$/) } if ($folder && !($trackartist && $scope eq 'misc')) {push(@result, makeABC($folder))} } if ($trackartist && $trackartist ne $folder && !($scope eq 'album')) { push(@result, makeABC($trackartist)); } } elsif ($searchFor eq 'album') { my $partalbum = $trackalbum; while ($partalbum =~ s/(.*)\/.+/$1/) { my $parentalbum = $1; my $parentyear; if ($parentalbum =~ / \((\d{4})\)(\/|)/) { $parentyear = $1; } push(@result, "$parentyear$delim$parentalbum$delim$platter"); } # misc is always merged my $albumline = "$year$delim$trackalbum$delim"; $albumline.=$platter unless ($trackalbum eq "Miscellany"); push(@result, $albumline); } elsif ($searchFor eq 'track') { push(@result, "$raw$delim$platter"); } } close PLATTER; } } # remove duplicates from artist and album searches #print join ("\n", keys %ABCS); @result = removeDup(@result) if ($searchFor ne 'track'); # take random selection of results if ($random>0) { my %done; my @randomlist; if ($random > $#result+1) { $random = $#result+1; } while ($random > 0) { my $index; do { $index = int(rand($#result+1)); } while (exists $done{$index}); push(@randomlist, $result[$index]); $done{$index} = 1; $random--; } return @randomlist; } else { return @result; } } sub removeDup( @_ ) { my @result = sort( @_ ); my $last; my $i=0; while ($i<=$#result) { if ($last eq $result[$i]) { splice @result, $i, 1; } else { $last = $result[$i]; $i++; } } return @result; } sub makeABC( @_ ) { my ($entry) = @_; $entry =~ s/^\W*//; if ($ABCS{$entry}) { $entry = ucfirst($ABCS{$entry}.$delim.$entry); } return $entry; }