| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | package Music::Tag::File; | 
| 2 | 1 |  |  | 1 |  | 4833 | use strict; use warnings; use utf8; | 
|  | 1 |  |  | 1 |  | 2 |  | 
|  | 1 |  |  | 1 |  | 45 |  | 
|  | 1 |  |  |  |  | 7 |  | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 39 |  | 
|  | 1 |  |  |  |  | 8 |  | 
|  | 1 |  |  |  |  | 16 |  | 
|  | 1 |  |  |  |  | 10 |  | 
| 3 |  |  |  |  |  |  | our $VERSION = '0.4101'; | 
| 4 |  |  |  |  |  |  |  | 
| 5 |  |  |  |  |  |  | # Copyright © 2007,2010 Edward Allen III. Some rights reserved. | 
| 6 |  |  |  |  |  |  | # | 
| 7 |  |  |  |  |  |  | # You may distribute under the terms of either the GNU General Public | 
| 8 |  |  |  |  |  |  | # License or the Artistic License, as specified in the README file. | 
| 9 |  |  |  |  |  |  |  | 
| 10 | 1 |  |  | 1 |  | 156 | use File::Spec; | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 115 |  | 
| 11 | 1 |  |  | 1 |  | 8 | use base qw(Music::Tag::Generic); | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 2947 |  | 
| 12 |  |  |  |  |  |  |  | 
| 13 |  |  |  |  |  |  | sub set_values { | 
| 14 | 0 |  |  | 0 | 1 | 0 | return qw( picture artist album title booklet lyrics track discnum); | 
| 15 |  |  |  |  |  |  | } | 
| 16 |  |  |  |  |  |  |  | 
| 17 |  |  |  |  |  |  | sub saved_values { | 
| 18 | 0 |  |  | 0 | 1 | 0 | return qw( picture booklet lyrics ); | 
| 19 |  |  |  |  |  |  | } | 
| 20 |  |  |  |  |  |  |  | 
| 21 |  |  |  |  |  |  | sub get_tag { | 
| 22 | 2 |  |  | 2 | 1 | 1486 | my $self     = shift; | 
| 23 | 2 |  |  |  |  | 8 | my $filename = $self->info->get_data('filename'); | 
| 24 | 2 |  |  |  |  | 128 | my @dirs     = File::Spec->splitdir( File::Spec->rel2abs($filename) ); | 
| 25 | 2 |  |  |  |  | 6 | my $fname    = pop @dirs; | 
| 26 | 2 |  |  |  |  | 383 | my $dname    = File::Spec->catdir(@dirs); | 
| 27 | 2 |  |  |  |  | 7 | my $album    = pop @dirs; | 
| 28 | 2 |  |  |  |  | 5 | my $artist   = pop @dirs; | 
| 29 |  |  |  |  |  |  |  | 
| 30 | 2 |  |  |  |  | 5 | $album =~ s/_/ /g; | 
| 31 | 2 |  |  |  |  | 15 | $album =~ s/\b(\w)/uc($1)/ge; | 
|  | 2 |  |  |  |  | 11 |  | 
| 32 | 2 |  |  |  |  | 13 | $album =~ s/ *$//g; | 
| 33 | 2 |  |  |  |  | 7 | $album =~ s/^ *//g; | 
| 34 |  |  |  |  |  |  |  | 
| 35 | 2 | 50 |  |  |  | 10 | if ( length($album) < 2 ) { | 
| 36 | 0 |  |  |  |  | 0 | $album = ""; | 
| 37 |  |  |  |  |  |  | } | 
| 38 |  |  |  |  |  |  |  | 
| 39 | 2 |  |  |  |  | 4 | $artist =~ s/_/ /g; | 
| 40 | 2 |  |  |  |  | 8 | $artist =~ s/\b(\w)/uc($1)/ge; | 
|  | 2 |  |  |  |  | 8 |  | 
| 41 | 2 |  |  |  |  | 13 | $artist =~ s/ *$//g; | 
| 42 | 2 |  |  |  |  | 10 | $artist =~ s/ *$//g; | 
| 43 | 2 | 50 |  |  |  | 8 | unless ( $self->info->has_data('track') ) { | 
| 44 | 2 | 50 |  |  |  | 75 | if ( $fname =~ /^[^\d]*(\d+)[^\d]/ ) { | 
| 45 | 0 |  |  |  |  | 0 | my $num = sprintf( "%d", $1 ); | 
| 46 | 0 |  |  |  |  | 0 | $self->info->set_data('track',$num); | 
| 47 | 0 |  |  |  |  | 0 | $self->tagchange("TRACK"); | 
| 48 |  |  |  |  |  |  | } | 
| 49 |  |  |  |  |  |  | else { | 
| 50 | 2 |  |  |  |  | 7 | $self->info->set_data('track',0); | 
| 51 | 2 |  |  |  |  | 104 | $self->tagchange("TRACK"); | 
| 52 |  |  |  |  |  |  | } | 
| 53 |  |  |  |  |  |  | } | 
| 54 | 2 | 50 |  |  |  | 234 | unless ( $self->info->has_data('title') ) { | 
| 55 | 2 |  |  |  |  | 53 | my $title = $fname; | 
| 56 | 2 |  |  |  |  | 11 | $title =~ s/\..+$//g; | 
| 57 | 2 |  |  |  |  | 9 | $title =~ s/^\d+\.?\ +//g; | 
| 58 | 2 |  |  |  |  | 7 | $title =~ s/^ *//g; | 
| 59 | 2 |  |  |  |  | 12 | $title =~ s/ *$//g; | 
| 60 | 2 |  |  |  |  | 7 | $self->info->set_data('title',$title); | 
| 61 | 2 |  |  |  |  | 92 | $self->tagchange("TITLE"); | 
| 62 |  |  |  |  |  |  | } | 
| 63 | 2 | 50 |  |  |  | 193 | unless ( $self->info->has_data('artist') ) { | 
| 64 | 2 |  |  |  |  | 53 | $self->info->set_data('artist',$artist); | 
| 65 | 2 |  |  |  |  | 76 | $self->tagchange("ARTIST"); | 
| 66 |  |  |  |  |  |  | } | 
| 67 | 2 | 50 |  |  |  | 198 | unless ( $self->info->has_data('album') ) { | 
| 68 | 2 |  |  |  |  | 305 | $self->info->set_data('album',$album); | 
| 69 | 2 |  |  |  |  | 83 | $self->tagchange("ALBUM"); | 
| 70 |  |  |  |  |  |  | } | 
| 71 | 2 | 50 |  |  |  | 183 | unless ( $self->info->has_data('disc') ) { | 
| 72 | 2 |  |  |  |  | 52 | $self->info->set_data('discnum',"1/1"); | 
| 73 | 2 |  |  |  |  | 174 | $self->tagchange("DISC"); | 
| 74 |  |  |  |  |  |  | } | 
| 75 |  |  |  |  |  |  |  | 
| 76 | 2 | 50 | 33 |  |  | 187 | if ( ( not $self->info->has_data('picture') ) or ( $self->options->{coveroverwrite} ) ) { | 
| 77 | 2 |  |  |  |  | 80 | my $fname    = File::Spec->catdir($dname, "folder.jpg"); | 
| 78 | 2 |  |  |  |  | 13 | my $pfname    = File::Spec->catdir($dname, "folder.png"); | 
| 79 | 2 |  |  |  |  | 12 | my $cfname    = File::Spec->catdir($dname, "cover.jpg"); | 
| 80 | 2 | 100 |  |  |  | 140 | if ( -e $fname ) { | 
|  |  | 50 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
| 81 | 1 |  |  |  |  | 5 | $self->tagchange( "COVER ART", "from folder.jpg" ); | 
| 82 | 1 |  |  |  |  | 69 | $self->info->set_data('picture', $self->_cover_art($fname) ); | 
| 83 |  |  |  |  |  |  | } | 
| 84 |  |  |  |  |  |  | elsif ( -e $pfname ) { | 
| 85 | 0 |  |  |  |  | 0 | $self->tagchange( "COVER ART", "from folder.png" ); | 
| 86 | 0 |  |  |  |  | 0 | $self->info->set_data('picture', $self->_cover_art($pfname) ); | 
| 87 |  |  |  |  |  |  | } | 
| 88 |  |  |  |  |  |  | elsif ( -e $cfname ) { | 
| 89 | 0 |  |  |  |  | 0 | $self->tagchange( "COVER ART", "from cover.jpg" ); | 
| 90 | 0 |  |  |  |  | 0 | $self->info->set_data('picture', $self->_cover_art($cfname) ); | 
| 91 |  |  |  |  |  |  | } | 
| 92 |  |  |  |  |  |  |  | 
| 93 |  |  |  |  |  |  | } | 
| 94 | 2 | 0 | 33 |  |  | 313 | if (    ( not $self->info->has_data('lyrics') ) | 
|  |  |  | 33 |  |  |  |  | 
| 95 |  |  |  |  |  |  | or ( $self->options->{lyricsoverwrite} ) | 
| 96 |  |  |  |  |  |  | or ( length( $self->info->lyrics ) < 10 ) ) { | 
| 97 | 2 |  |  |  |  | 54 | my $fname = $self->info->filename; | 
| 98 | 2 |  |  |  |  | 41 | $fname =~ s/\.[^\.]*$/.txt/; | 
| 99 | 2 | 50 |  |  |  | 43 | if ( -e "$fname" ) { | 
| 100 | 0 |  |  |  |  | 0 | $self->tagchange( "LYRICS", "from $fname" ); | 
| 101 | 0 |  |  |  |  | 0 | my $l = $self->_slurp_file($fname); | 
| 102 | 0 |  |  |  |  | 0 | $self->info->set_data('lyrics',$l); | 
| 103 | 0 |  |  |  |  | 0 | $l =~ s/\n\r?/ \/ /g; | 
| 104 | 0 |  |  |  |  | 0 | $self->tagchange( "LYRICS", substr( $l, 0, 40 ) ); | 
| 105 |  |  |  |  |  |  | } | 
| 106 |  |  |  |  |  |  | } | 
| 107 | 2 |  |  |  |  | 7 | local *DIR; | 
| 108 | 2 |  |  |  |  | 83 | opendir(DIR, $dname); | 
| 109 | 2 |  |  |  |  | 73 | while ( my $f = readdir(DIR) ) { | 
| 110 | 11 | 100 |  |  |  | 356 | next if $f =~ /^\./; | 
| 111 | 7 |  |  |  |  | 41 | my $fname    = File::Spec->catdir($dname, $f); | 
| 112 | 7 | 50 |  |  |  | 40 | if ($f =~ /\.pdf$/i) { | 
| 113 | 0 | 0 |  |  |  | 0 | unless ($self->info->has_data('booklet')) { | 
| 114 | 0 |  |  |  |  | 0 | $self->tagchange( "BOOKLET", "from $f" ); | 
| 115 | 0 |  |  |  |  | 0 | $self->info->set_data('booklet',$f); | 
| 116 |  |  |  |  |  |  | } | 
| 117 |  |  |  |  |  |  | } | 
| 118 |  |  |  |  |  |  | #if ($f =~ /\.txt$/i) { | 
| 119 |  |  |  |  |  |  | #unless ($self->info->has_data('lyrics')) { | 
| 120 |  |  |  |  |  |  | #$self->tagchange( "LYRICS", "from $fname" ); | 
| 121 |  |  |  |  |  |  | #my $l = $self->_slurp_file($fname); | 
| 122 |  |  |  |  |  |  | #$self->info->set_data('lyrics',$l); | 
| 123 |  |  |  |  |  |  | #$l =~ s/\n\r?/ \/ /g; | 
| 124 |  |  |  |  |  |  | #$self->tagchange( "LYRICS", substr( $l, 0, 40 ) ); | 
| 125 |  |  |  |  |  |  | #} | 
| 126 |  |  |  |  |  |  | #} | 
| 127 | 7 | 100 |  |  |  | 30 | if ($f =~ /\.jpg$/i) { | 
| 128 | 3 | 100 |  |  |  | 8 | unless ($self->info->has_data('picture')) { | 
| 129 | 1 |  |  |  |  | 37 | $self->tagchange( "COVER ART", "from $f" ); | 
| 130 | 1 |  |  |  |  | 64 | $self->info->set_data('picture', $self->_cover_art($fname) ); | 
| 131 |  |  |  |  |  |  | } | 
| 132 |  |  |  |  |  |  | } | 
| 133 |  |  |  |  |  |  | } | 
| 134 |  |  |  |  |  |  |  | 
| 135 |  |  |  |  |  |  |  | 
| 136 |  |  |  |  |  |  |  | 
| 137 | 2 |  |  |  |  | 453 | return $self; | 
| 138 |  |  |  |  |  |  | } | 
| 139 |  |  |  |  |  |  |  | 
| 140 |  |  |  |  |  |  | sub _slurp_file { | 
| 141 | 0 |  |  | 0 |  | 0 | my $self = shift; | 
| 142 | 0 |  |  |  |  | 0 | my $fname = shift; | 
| 143 | 0 |  |  |  |  | 0 | local *IN; | 
| 144 | 0 | 0 |  |  |  | 0 | open( IN, $fname ) or return ""; | 
| 145 | 0 |  |  |  |  | 0 | my $l = ""; | 
| 146 | 0 |  |  |  |  | 0 | while () { $l .= $_ } | 
|  | 0 |  |  |  |  | 0 |  | 
| 147 | 0 |  |  |  |  | 0 | close(IN); | 
| 148 | 0 |  |  |  |  | 0 | return $l; | 
| 149 |  |  |  |  |  |  | } | 
| 150 |  |  |  |  |  |  |  | 
| 151 |  |  |  |  |  |  | sub _cover_art { | 
| 152 | 2 |  |  | 2 |  | 15 | my $self    = shift; | 
| 153 | 2 |  |  |  |  | 2 | my $picture = shift; | 
| 154 | 2 |  |  |  |  | 40 | my ($vol, $root, $file) = File::Spec->splitpath($picture); | 
| 155 | 2 |  |  |  |  | 13 | my $pic = { "Picture Type" => "Cover (front)", | 
| 156 |  |  |  |  |  |  | "MIME type"    => "image/jpg", | 
| 157 |  |  |  |  |  |  | Description    => "", | 
| 158 |  |  |  |  |  |  | filename	   => $file, | 
| 159 |  |  |  |  |  |  | _Data          => "", | 
| 160 |  |  |  |  |  |  | }; | 
| 161 | 2 | 50 |  |  |  | 10 | if ( $picture =~ /\.png$/i ) { | 
| 162 | 0 |  |  |  |  | 0 | $pic->{"MIME type"} = "image/png"; | 
| 163 |  |  |  |  |  |  | } | 
| 164 | 2 |  |  |  |  | 10 | return $pic; | 
| 165 | 0 |  |  |  |  | 0 | local *IN; | 
| 166 |  |  |  |  |  |  | #unless ( open( IN, $picture ) ) { | 
| 167 |  |  |  |  |  |  | #    $self->error("Could not open $picture for read: $!"); | 
| 168 |  |  |  |  |  |  | #    return undef; | 
| 169 |  |  |  |  |  |  | #} | 
| 170 |  |  |  |  |  |  | #my $n = 0; | 
| 171 |  |  |  |  |  |  | #my $b = 1; | 
| 172 |  |  |  |  |  |  | #while ($b) { | 
| 173 |  |  |  |  |  |  | #    $b = sysread( IN, $pic->{"_Data"}, 1024, $n ); | 
| 174 |  |  |  |  |  |  | #    $n += $b; | 
| 175 |  |  |  |  |  |  | #} | 
| 176 |  |  |  |  |  |  | #close(IN); | 
| 177 |  |  |  |  |  |  | #return $pic; | 
| 178 |  |  |  |  |  |  | } | 
| 179 |  |  |  |  |  |  |  | 
| 180 |  |  |  |  |  |  | sub save_cover { | 
| 181 | 1 |  |  | 1 | 1 | 9 | my $self = shift; | 
| 182 | 1 |  |  |  |  | 4 | my ( $vol, $dir, $file ) = File::Spec->splitpath( $self->info->get_data('filename') ); | 
| 183 | 1 |  |  |  |  | 50 | my $filename = File::Spec->catpath( $vol, $dir, "folder.jpg" ); | 
| 184 |  |  |  |  |  |  |  | 
| 185 |  |  |  |  |  |  | #if ($dname eq "/") { $dname = "" } else {$dname = File::Spec->catpath($vol, $dir) } | 
| 186 | 1 |  |  |  |  | 4 | my $art = $self->info->get_data('picture'); | 
| 187 | 1 | 50 |  |  |  | 257 | if ( exists $art->{_Data} ) { | 
| 188 | 1 |  |  |  |  | 3 | local *OUT; | 
| 189 | 1 | 50 |  |  |  | 8 | if ( $art->{"MIME type"} eq "image/png" ) { | 
|  |  | 50 |  |  |  |  |  | 
| 190 | 0 |  |  |  |  | 0 | $filename = File::Spec->catpath( $vol, $dir, "folder.png" ); | 
| 191 |  |  |  |  |  |  | } | 
| 192 |  |  |  |  |  |  | elsif ( $art->{"MIME type"} eq "image/bmp" ) { | 
| 193 | 0 |  |  |  |  | 0 | $filename = File::Spec->catpath( $vol, $dir, "folder.jpg" ); | 
| 194 |  |  |  |  |  |  | } | 
| 195 | 1 |  |  |  |  | 6 | $self->status("Saving cover image to $filename"); | 
| 196 | 1 | 50 |  |  |  | 140 | unless ( open OUT, ">$filename" ) { | 
| 197 | 0 |  |  |  |  | 0 | $self->error("Error writing to $filename: $!, skipping."); | 
| 198 | 0 |  |  |  |  | 0 | return undef; | 
| 199 |  |  |  |  |  |  | } | 
| 200 | 1 |  |  |  |  | 2 | my $b = 0; | 
| 201 | 1 |  |  |  |  | 2 | my $l = length( $art->{_Data} ); | 
| 202 | 1 |  |  |  |  | 5 | while ( $b < $l ) { | 
| 203 | 4 |  |  |  |  | 75 | my $s = syswrite OUT, $art->{_Data}, 1024, $b; | 
| 204 | 4 | 50 |  |  |  | 8 | if ( defined $s ) { | 
| 205 | 4 |  |  |  |  | 7 | $b += $s; | 
| 206 |  |  |  |  |  |  | } | 
| 207 |  |  |  |  |  |  | else { | 
| 208 | 0 |  |  |  |  | 0 | $self->status("Error writing to $filename: $!, skipping."); | 
| 209 | 0 |  |  |  |  | 0 | return undef; | 
| 210 |  |  |  |  |  |  | } | 
| 211 |  |  |  |  |  |  | } | 
| 212 | 1 |  |  |  |  | 10 | close OUT; | 
| 213 |  |  |  |  |  |  | } | 
| 214 | 1 |  |  |  |  | 4 | return 1; | 
| 215 |  |  |  |  |  |  | } | 
| 216 |  |  |  |  |  |  |  | 
| 217 |  |  |  |  |  |  | sub save_lyrics { | 
| 218 | 0 |  |  | 0 | 1 | 0 | my $self  = shift; | 
| 219 | 0 |  |  |  |  | 0 | my $fname = $self->info->get_data('filename'); | 
| 220 | 0 |  |  |  |  | 0 | $fname =~ s/\.[^\.]*$/.txt/; | 
| 221 | 0 |  |  |  |  | 0 | my $lyrics = $self->info->get_data('lyrics'); | 
| 222 | 0 | 0 |  |  |  | 0 | if ($lyrics) { | 
| 223 | 0 |  |  |  |  | 0 | local *OUT; | 
| 224 | 0 |  |  |  |  | 0 | $self->status("Saving lyrics image to $fname"); | 
| 225 | 0 | 0 |  |  |  | 0 | unless ( open OUT, ">$fname" ) { | 
| 226 | 0 |  |  |  |  | 0 | $self->status("Error writing to $fname: $!, skipping."); | 
| 227 | 0 |  |  |  |  | 0 | return undef; | 
| 228 |  |  |  |  |  |  | } | 
| 229 | 0 |  |  |  |  | 0 | print OUT $lyrics; | 
| 230 | 0 |  |  |  |  | 0 | close OUT; | 
| 231 |  |  |  |  |  |  | } | 
| 232 | 0 |  |  |  |  | 0 | return 1; | 
| 233 |  |  |  |  |  |  | } | 
| 234 |  |  |  |  |  |  |  | 
| 235 |  |  |  |  |  |  | sub set_tag { | 
| 236 | 1 |  |  | 1 | 1 | 5094 | my $self = shift; | 
| 237 | 1 | 50 |  |  |  | 6 | unless ( $self->options("no_savecover")) { | 
| 238 | 1 |  |  |  |  | 24 | $self->save_cover( $self->info ); | 
| 239 |  |  |  |  |  |  | } | 
| 240 | 1 | 50 | 33 |  |  | 4 | unless ( $self->options("no_savelyrics") or $self->info->get_data('filename') =~ /\.mp3$/i ) { | 
| 241 | 0 |  |  |  |  | 0 | $self->save_lyrics( $self->info ); | 
| 242 |  |  |  |  |  |  | } | 
| 243 | 1 |  |  |  |  | 50 | return $self; | 
| 244 |  |  |  |  |  |  | } | 
| 245 |  |  |  |  |  |  |  | 
| 246 |  |  |  |  |  |  | sub default_options { | 
| 247 |  |  |  |  |  |  | { | 
| 248 | 2 |  |  | 2 | 1 | 2191 | lyricsoverwrite => 0, | 
| 249 |  |  |  |  |  |  | coveroverwrite => 0, | 
| 250 |  |  |  |  |  |  | no_savecover => 0, | 
| 251 |  |  |  |  |  |  | no_savelyrics => 0, | 
| 252 |  |  |  |  |  |  | } | 
| 253 |  |  |  |  |  |  | } | 
| 254 |  |  |  |  |  |  |  | 
| 255 |  |  |  |  |  |  | 1; | 
| 256 |  |  |  |  |  |  |  | 
| 257 |  |  |  |  |  |  | __END__ |