File Coverage

blib/lib/Audio/Metadata/TextProcessor.pm
Criterion Covered Total %
statement 79 79 100.0
branch 20 26 76.9
condition 10 12 83.3
subroutine 13 13 100.0
pod 3 3 100.0
total 125 133 93.9


line stmt bran cond sub pod time code
1             package Audio::Metadata::TextProcessor;
2             {
3             $Audio::Metadata::TextProcessor::VERSION = '0.16';
4             }
5             BEGIN {
6 1     1   28135 $Audio::Metadata::TextProcessor::VERSION = '0.15';
7             }
8              
9 1     1   9 use strict;
  1         2  
  1         33  
10 1     1   5 use warnings;
  1         2  
  1         76  
11              
12 1     1   476 use Audio::Metadata;
  1         3  
  1         33  
13 1     1   7 use Any::Moose;
  1         1  
  1         4  
14              
15              
16             has input_fh => ( is => 'ro', isa => 'FileHandle', );
17             has output_fh => ( is => 'ro', isa => 'FileHandle', );
18             has debug => ( is => 'rw', isa => 'Bool', default => 0, );
19              
20              
21             sub BUILDARGS {
22             ## Overriden.
23 2     2 1 2342 my $self = shift;
24 2         4 my ($init_params) = @_;
25              
26 2         10 my %new_args = %$init_params;
27 2         5 foreach my $mode (qw/input output/) {
28              
29 4 50       13 next if !defined $init_params->{$mode};
30 4         7 delete $new_args{$mode};
31              
32 1 100   1   10 open my $fh, $mode eq 'input' ? '<' : '>', $init_params->{$mode}
  1 50       2  
  1         7  
  4         117  
33             or die "Couldn't open $mode stream \"$init_params->{$mode}\": $!";
34 4         1276 $new_args{"${mode}_fh"} = $fh;
35             }
36              
37 2         26 return \%new_args;
38             }
39              
40              
41             sub update_from_cue {
42             ## Reads track info from a cue file and saves to tracks, based on track numbers.
43 1     1 1 10 my $self = shift;
44              
45 1         5 my @metadatas = $self->_input_cue;
46 1         256 my @file_names = grep /^\d+[_ ]?-[_ ]?.+\.(flac|ogg|mp3)$/i, glob('*.*');
47              
48 1 50       8 die @metadatas . ' tracks parsed, but ' . @file_names . ' files found'
49             unless @metadatas == @file_names;
50              
51 1         6 for (my $i = 0; $i < @file_names; $i++) {
52 3         9 my $file_name = $file_names[$i];
53 3         6 my $metadata = $metadatas[$i];
54              
55 3         24 my $metadata_writer = Audio::Metadata->new_from_path($file_name);
56 3         166 $self->_log($file_name);
57              
58 3         12 foreach my $var (keys %$metadata) {
59 12         60 $self->_log(" $var => $metadata->{$var}");
60 12         47 $metadata_writer->set_var($var => $metadata->{$var});
61             }
62 3         16 $metadata_writer->save;
63             }
64             }
65              
66              
67             sub update {
68             ## Reads metadata from specified file handle and saves to media files.
69 1     1 1 62 my $self = shift;
70              
71 1         5 my $fh = $self->input_fh;
72 1         2 my %curr_item;
73 1         22 while (my $line = <$fh>) {
74 14         21 chomp $line;
75              
76 14         52 my ($var, $value) = $line =~ /^(\S+) *(.*)$/;
77 14 100       26 if ($var) {
78 12         48 $curr_item{$var} = $value;
79             }
80             else {
81 2         8 $self->_apply_item(\%curr_item);
82 2         8 %curr_item = ();
83 2         19 next;
84             }
85             }
86 1 50       8 $self->_apply_item(\%curr_item) if %curr_item;
87             }
88              
89              
90             sub _apply_item {
91             ## Saves metadata to file in the given hash.
92 3     3   5 my $self = shift;
93 3         6 my ($item) = @_;
94              
95 3         25 my $metadata = Audio::Metadata->new_from_path($item->{_FILE_NAME});
96 3         617 my $is_changed;
97              
98 3         26 foreach my $var (grep /^[^_]/, keys %$item) {
99 1     1   992 no warnings 'uninitialized';
  1         2  
  1         379  
100 9 100       39 next if $item->{$var} eq $metadata->get_var($var);
101              
102 8         34 $metadata->set_var($var => $item->{$var});
103 8         15 $is_changed++;
104             }
105              
106 3 50       19 $metadata->save if $is_changed;
107             }
108              
109              
110             sub _input_cue {
111             ## Reads cue file from input file handle and returns track list as array of hashes.
112 1     1   4 my $class = shift;
113              
114             # Define names of properties common to the whole album, and how to map
115             # them to tags.
116 1         2 my %common_props;
117 1         6 my %common_props_map = (
118             TITLE => 'ALBUM',
119             PERFORMER => 'ARTIST',
120             );
121              
122             # Go through .CUE file, parsing common properties as well as individual ones.
123 1         2 my @tracks;
124             my $curr_track_no;
125              
126 1         4 my $fh = $class->input_fh;
127 1         18 while (<$fh>) {
128              
129 21         146 s/^\s+|\s+$//g;
130 21         92 my ($key, $value) = /^([A-Z]+)\s+"?([^"]+)"?$/s;
131 21 100 100     93 next if !$key || $key eq 'REM';
132              
133 15 100 100     99 if (!defined $curr_track_no && (my $translated_key = $common_props_map{$key})) {
    100 66        
    100          
134 2         11 $common_props{$translated_key} = $value;
135             }
136             elsif ($key eq 'TRACK') {
137 3         19 ($curr_track_no) = $value =~ /^(\d+)/;
138             }
139             elsif (defined $curr_track_no && $key ne 'INDEX') {
140 6         24 $tracks[$curr_track_no]{$key} = $value;
141             }
142             }
143              
144             return
145 1   66     18 map { { %common_props, %$_ } }
  3         22  
146             grep defined $_ && $_->{TITLE} ne 'DATA', @tracks;
147             }
148              
149              
150             sub _log {
151             ## Logs a specified message.
152 15     15   21 my $self = shift;
153              
154 15 50       58 print STDERR @_, "\n" if $self->debug;
155             }
156              
157              
158             1;
159              
160              
161             __END__