Index: Slim/Utils/Text.pm =================================================================== --- Slim/Utils/Text.pm (revision 4101) +++ Slim/Utils/Text.pm (working copy) @@ -139,6 +139,99 @@ return exists($sortCache{ignoreCaseArticles($item)}) ? $sortCache{ignoreCaseArticles($item)} : $item; } +# Hash containing replacements for lazy multi-tap searching. Anything not in +# here will just be translated to itself as we don't have any better idea. See +# the lazyMultiTapDecode function for further details of how this works. +my %lazyMultiTapMap = ( + 'A' => '2', + 'B' => '22', + 'C' => '222', + '2' => '2222', + 'D' => '3', + 'E' => '33', + 'F' => '333', + '3' => '3333', + 'G' => '4', + 'H' => '44', + 'I' => '444', + '4' => '4444', + 'J' => '5', + 'K' => '55', + 'L' => '555', + '5' => '5555', + 'M' => '6', + 'N' => '66', + 'O' => '666', + '6' => '6666', + 'P' => '7', + 'Q' => '77', + 'R' => '777', + 'S' => '7777', + '7' => '77777', + 'T' => '8', + 'U' => '88', + 'V' => '888', + '8' => '8888', + 'W' => '9', + 'X' => '99', + 'Y' => '999', + 'Z' => '9999', + '9' => '99999' +); + +# Convert a search string to a lazy-entry encoded search string. This includes +# both the original search term and a lazy-encoded version. Later, when +# searching, both are tried. The original search text is kept in upper-case +# and the lazy version is encoded as digits - the latter is because both the +# original and lazy encoded version is searched in case the user bothers to +# put the search string in properly and this minimises the chance of erroneous +# matching. +# +# called: +# undef +sub lazyEncode { + my $in_string = shift; + my $out_string; + + # This translates each searchable character into the number of the key that + # shares that letter on the remote. Thus, this tells us what keys the user + # will enter if he doesn't bother to multi-tap to get at the later + # characters. + # We do all this on an upper case version, since upper case is all the user + # can enter through the remote control. + $out_string = uc $in_string; + $out_string =~ tr/ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890 /222333444555666777788899991234567890 /; + + # Return a combination of the original search text and a lazy-encoded + # version. + return $in_string . "| " . $out_string; +} + +# Allow the user to put in lazy searches when adjacent characters are on the +# same key without having to press right arrow or wait a while. It does this by +# translating non-first keys into the right number of the numeric key they +# appear on. +# Decoding "PTNDP" ("STONES") should become "786637" +# and "ODW" ("MONEY") should become "66639". +# +# called: +# undef +sub lazyMultiTapDecode { + my $in_string = shift; + my $out_string = ""; + + # Loop through all the characters (back-to-front), and build up an + # output string with the appropriate replacements. + while ($in_string) { + my $in_c = chop $in_string; + my $out_c = $lazyMultiTapMap{$in_c}; + $out_c = $in_c unless $out_c; + $out_string = $out_c . $out_string; + } + + return $out_string; +} + 1; __END__ Index: Slim/DataStores/DBI/DBIStore.pm =================================================================== --- Slim/DataStores/DBI/DBIStore.pm (revision 4101) +++ Slim/DataStores/DBI/DBIStore.pm (working copy) @@ -1332,7 +1332,7 @@ } # Create a canonical title to search against. - $attributes->{'TITLESEARCH'} = Slim::Utils::Text::ignoreCaseArticles($attributes->{'TITLE'}); + $attributes->{'TITLESEARCH'} = Slim::Utils::Text::lazyEncode(Slim::Utils::Text::ignoreCaseArticles($attributes->{'TITLE'})); # Remote index. $attributes->{'REMOTE'} = Slim::Music::Info::isRemoteURL($url) ? 1 : 0; @@ -1534,7 +1534,7 @@ $albumObj->titlesort($sortable_title) if $sortable_title; # And our searchable version. - $albumObj->titlesearch(Slim::Utils::Text::ignoreCaseArticles($album)); + $albumObj->titlesearch(Slim::Utils::Text::lazyEncode(Slim::Utils::Text::ignoreCaseArticles($album))); $albumObj->compilation(1) if $attributes->{'COMPILATION'}; Index: Slim/DataStores/DBI/ContributorTrack.pm =================================================================== --- Slim/DataStores/DBI/ContributorTrack.pm (revision 4101) +++ Slim/DataStores/DBI/ContributorTrack.pm (working copy) @@ -81,7 +81,7 @@ my $sort = Slim::Utils::Text::ignoreCaseArticles(($sortedList[$i] || $name)); my $artistObj = Slim::DataStores::DBI::Contributor->find_or_create({ - namesearch => $search, + namesearch => Slim::Utils::Text::lazyEncode(Slim::Utils::Text::ignoreCaseArticles($search)), }); $artistObj->name($name); Index: Slim/Buttons/Search.pm =================================================================== --- Slim/Buttons/Search.pm (revision 4101) +++ Slim/Buttons/Search.pm (working copy) @@ -208,7 +208,8 @@ return [ $term ]; } - return [ $term, "* $term" ]; + my $lazy_term = Slim::Utils::Text::lazyMultiTapDecode($term); + return [ $term, "* $term" , $lazy_term, "* $lazy_term" ]; } 1;