Load tag-reading modules on demand
authorMarius Gavrilescu <marius@ieval.ro>
Sat, 22 Oct 2016 17:11:22 +0000 (18:11 +0100)
committerMarius Gavrilescu <marius@ieval.ro>
Sat, 22 Oct 2016 17:11:22 +0000 (18:11 +0100)
lib/App/MusicExpo.pm
t/App-MusicExpo.t
t/musicexpo-cache.t

index c1433ca44c23566cf5ec4808f5c38a26930b9955..f2ee745352df6ba497f590da6593c9f4b9db5f4b 100644 (file)
@@ -5,13 +5,8 @@ use warnings;
 
 our $VERSION = '1.001_001';
 
-use Audio::FLAC::Header qw//;
 use HTML::Template::Compiled qw//;
 use Memoize qw/memoize/;
-use MP3::Info qw/get_mp3tag/;
-use Ogg::Vorbis::Header::PurePerl;
-use MP4::Info qw/get_mp4tag get_mp4info/;
-use Audio::Opusfile qw//;
 
 use DB_File qw//;
 use Encode qw/encode/;
@@ -54,7 +49,7 @@ sub flacinfo{
 
 sub mp3info{
        my $file=$_[0];
-       my %tag = map { encode 'UTF-8', $_ } %{get_mp3tag $file};
+       my %tag = map { encode 'UTF-8', $_ } %{MP3::Info::get_mp3tag $file};
        my @trkn = split m#/#s, $tag{TRACKNUM} // '';
 
        freeze +{
@@ -96,8 +91,8 @@ sub mp4_format ($){ ## no critic (ProhibitSubroutinePrototypes)
 
 sub mp4info{
        my $file=$_[0];
-       my %tag = map { ref() ? $_ : encode 'UTF-8', $_ } %{get_mp4tag $file};
-       my %info = %{get_mp4info $file};
+       my %tag = map { ref() ? $_ : encode 'UTF-8', $_ } %{MP4::Info::get_mp4tag $file};
+       my %info = %{MP4::Info::get_mp4info $file};
 
        freeze +{
                format => mp4_format $info{ENCODING},
@@ -132,23 +127,35 @@ sub opusinfo {
        freeze \%data;
 }
 
-my %info = (
-       '.flac' => \&flacinfo,
-       '.mp3' => \&mp3info,
-       '.ogg' => \&vorbisinfo,
-       '.oga' => \&vorbisinfo,
-       '.mp4' => \&mp4info,
-       '.aac' => \&mp4info,
-       '.m4a' => \&mp4info,
-       '.opus' => \&opusinfo,
+my @optional_modules = (
+       [ 'Audio::FLAC::Header', \&flacinfo, '.flac' ],
+       [ 'MP3::Info', \&mp3info, '.mp3' ],
+       [ 'Ogg::Vorbis::Header::PurePerl', \&vorbisinfo, '.ogg', '.oga' ],
+       [ 'MP4::Info', \&mp4info, '.mp4', '.aac', '.m4a' ],
+       [ 'Audio::Opusfile', \&opusinfo, '.opus' ]
 );
 
+my %info;
+
+for (@optional_modules) {
+       my ($module, $coderef, @extensions_handled) = @$_;
+       if (eval "require $module") {
+               $info{$_} = $coderef for @extensions_handled
+       }
+}
+
+unless (%info) {
+       warn 'No tags-reading module detected. Install one of the following modules: ' . join ', ', map { $_->[0] } @optional_modules;
+}
+
 sub normalizer{
        "$_[0]|".(stat $_[0])[9]
 }
 
 sub make_fragment{ join '-', map { lc =~ y/a-z0-9/_/csr } @_ }
 
+sub extensions_handled { keys %info }
+
 sub run {
        if ($cache) {
                tie my %cache, 'DB_File', $cache, O_RDWR|O_CREAT, 0644; ## no critic (ProhibitTie)
@@ -158,6 +165,7 @@ sub run {
        my %files;
        for my $file (@ARGV) {
                my ($basename, undef, $suffix) = fileparse $file, keys %info;
+               next unless $suffix;
                $files{$basename} //= [];
                push @{$files{$basename}}, thaw scalar $info{$suffix}->($file);
        }
index 09b2bde29c9ba1261943134b34d30f8ffd9c4f3d..ea1c49653d7c29f9edeb0cea2cdefe1abf3b6f0b 100644 (file)
@@ -2,7 +2,7 @@
 use v5.14;
 use warnings;
 
-use Test::More tests => 37;
+use Test::More tests => 46;
 
 use Scalar::Util qw/looks_like_number/;
 use Storable qw/thaw/;
@@ -19,18 +19,27 @@ my %data = (
        genre       => 'Electro'
 );
 
+my %handled = map { $_ => 1 } App::MusicExpo::extensions_handled;
+
 sub test {
        my ($format, $sub, $file) = @_;
-       my $info = thaw $sub->($file);
-       is $info->{format}, $format, "$format format";
-       for (sort keys %data) {
-               my $op = looks_like_number $data{$_} ? '==' : 'eq';
-               cmp_ok $info->{$_}, $op, $data{$_}, "$format $_"
+       my ($ext) = $file =~ /(\..+)$/;
+
+  SKIP:
+       {
+               skip "Cannot handle $ext files (tag-reading module missing)", 9 unless $handled{$ext};
+                 my $info = thaw $sub->($file);
+               is $info->{format}, $format, "$format format";
+               for (sort keys %data) {
+                       my $op = looks_like_number $data{$_} ? '==' : 'eq';
+                       cmp_ok $info->{$_}, $op, $data{$_}, "$format $_"
+               }
+               is $info->{file}, $file, "$format file";
        }
-       is $info->{file}, $file, "$format file";
 }
 
 test FLAC   => \&App::MusicExpo::flacinfo,   'empty.flac';
 test MP3    => \&App::MusicExpo::mp3info,    'empty3.mp3';
 test Vorbis => \&App::MusicExpo::vorbisinfo, 'empty.ogg';
 test AAC    => \&App::MusicExpo::mp4info,    'empty4.aac';
+test Opus   => \&App::MusicExpo::opusinfo,   'empty2.opus';
index 47e07c9069d1ce93beb9eb31c624120a9dfb317c..b703b7a035608cf81cd24fb0ed017cc46b1f3914 100644 (file)
@@ -18,9 +18,28 @@ close STDOUT;
 my $out;
 open STDOUT, '>', \$out;
 
+my %handled = map { $_ => 1 } App::MusicExpo::extensions_handled;
+
+my $prefix = '<tr><td class="title"><a href="#silence-cellule" data-hash="#silence-cellule">Cellule</a><td class="artist">Silence<td class="album">L&#39;autre endroit<td class="genre">Electro<td class="track">01/09<td class="year">2005<td class="formats">';
+
+my @lines;
+if ($handled{'.flac'} && $handled{'.ogg'}) {
+       push @lines, $prefix . '<a href="/music/empty.flac">FLAC</a> <a href="/music/empty.ogg">Vorbis</a> '
+} elsif ($handled{'.flac'}) {
+       push @lines, $prefix . '<a href="/music/empty.flac">FLAC</a> '
+} elsif ($handled{'.ogg'}) {
+       push @lines, $prefix . '<a href="/music/empty.ogg">Vorbis</a> '
+}
+
+push @lines, $prefix . '<a href="/music/empty2.opus">Opus</a> ' if $handled{'.opus'};
+push @lines, $prefix . '<a href="/music/empty3.mp3">MP3</a> ' if $handled{'.mp3'};
+push @lines, '<td class="album">L&#39;autre endroit<td class="genre">Electro<td class="track">1/9<td class="year">2005<td class="formats"><a href="/music/empty4.aac">AAC</a> ' if $handled{'.aac'};
+
+my $contents = join "\n", @lines;
+
 App::MusicExpo->run;
 
-is $out, <<'OUT', 'output is correct';
+is $out, <<"OUT", 'output is correct';
 <!DOCTYPE html>
 <title>Music</title>
 <meta charset="utf-8">
@@ -32,11 +51,7 @@ is $out, <<'OUT', 'output is correct';
 <table border>
 <thead>
 <tr><th>Title<th>Artist<th>Album<th>Genre<th>Track<th>Year<th>Type
-<tbody>
-<tr><td class="title"><a href="#silence-cellule" data-hash="#silence-cellule">Cellule</a><td class="artist">Silence<td class="album">L&#39;autre endroit<td class="genre">Electro<td class="track">01/09<td class="year">2005<td class="formats"><a href="/music/empty.flac">FLAC</a> <a href="/music/empty.ogg">Vorbis</a> 
-<tr><td class="title"><a href="#silence-cellule" data-hash="#silence-cellule">Cellule</a><td class="artist">Silence<td class="album">L&#39;autre endroit<td class="genre">Electro<td class="track">01/09<td class="year">2005<td class="formats"><a href="/music/empty2.opus">Opus</a> 
-<tr><td class="title"><a href="#silence-cellule" data-hash="#silence-cellule">Cellule</a><td class="artist">Silence<td class="album">L&#39;autre endroit<td class="genre">Electro<td class="track">01/09<td class="year">2005<td class="formats"><a href="/music/empty3.mp3">MP3</a> 
-<tr><td class="title"><a href="#silence-cellule" data-hash="#silence-cellule">Cellule</a><td class="artist">Silence<td class="album">L&#39;autre endroit<td class="genre">Electro<td class="track">1/9<td class="year">2005<td class="formats"><a href="/music/empty4.aac">AAC</a> 
+<tbody>$contents
 </table>
 OUT
 
This page took 0.015779 seconds and 4 git commands to generate.