diff -Nru libmp3-tag-perl-1.11/Changes libmp3-tag-perl-1.12/Changes --- libmp3-tag-perl-1.11/Changes 2009-05-11 05:18:48.000000000 +0100 +++ libmp3-tag-perl-1.12/Changes 2009-11-27 06:35:24.000000000 +0000 @@ -1,3 +1,47 @@ +Release Name: 1.12 +==================== + +Music_Normalize_Fields: new short names in RUS table. + Eliminate one record which caused infinite recursion (vas i iva). + +ID3v2: replace order of encode() and func_back() when writing frames + (e.g., would break unicode genre with space in it). + "very low-level" docs had get_frame() mixed up with get_frames() + (thanks to Brendan Byrd) + new_with_parent() inserts header into parent on failure. + optional argument to _Data_to_MIME to return false on unknown. + +Tag.pm: better docs for interpolate(). + misprints in example of update_tags(). + When truncating inside interpolation, and the value is a number + round it, not truncate. + Move old meaning of %{aR} to %{a3} (truncation to 3 places). + %{aR} is not rounded now; one may truncate as in %.5{aR} to restrict width. + New method mime_Pretype(); new interpolation escape %{mP}. + Optional argument to _Data_to_MIME() to return false on unknown. + For (image) mime types we can handle ourselves, do it. + default return for mime_type() is MP3 (in absense of support modules). + Misprint in _Data_to_MIME() made it useless. + New method aspect_ratio_inverted(). + New escape %{aI} for aspect_ratio_inverted(). + Allow for rounding of duration before formatting T[=>m,?H:,m]. + +File.pm: fix mismatched C<> in POD. + +mp3info2: -F disk_n=DISKNUMBER supported, + new configuration variable frames_write_creates_dirs (default 0) to create + intermediate directories baz/boz on -F "foo > baz/boz/bar". + Use %{mP} instead of `Audio' in the -x output. + Make -x=output of MP3-related data conditional on its presence (still wrong + since MP3::Info can return such data for non-MP3 files too XXX) + +typeset_audio_dir: + new option -r + Make haveLyrics/haveAPIC symbols take less space + Macroize pre/postSectionSkip, make it and \columnsep font-size dependent + Slightly more docs in the generated code on grid/non-grid typesetting + Slightly more docs + Release Name: 1.11 ==================== @@ -8,12 +52,12 @@ "revived" by update_tags(), so we disable id3 in ExifTool [XXX: must be made conditional on the list of handlers]; genre-->None massaged to '') 'NumColors' => 'Use BitDepth'??? - rename aspect() to aspect_ratio() + rename aspect() to aspect_ratio() (undocumented) new function aspect_ratio3() rounds to 3 decimals in the fractional part map %{aR} to aspect_ratio3() [instead of aspect()] - new method bit_depth() (for images; exact semantic [8 or 24?!] not clear) + new method bit_depth() (for images; exact semantic [8 or 24?!] not clear) (undocumented) new interpolation %{bD} for bit_depth - new method _duration() (for AVI only???) + new method _duration() (for very few formats only???) (undocumented) caching MP3::Info data avoid extraneous calls Make duration-fetch methods try _duration() too. mpeg_layer_roman(), frames_padded_YN(), is_copyrighted_YN() now may return '' @@ -36,7 +80,7 @@ new methods extension_is(), can_write(), can_write_or_die(), die_cant_write(), writable_by_extension(). new methods (require Image::Size) width(), height(), img_type(), mime_type(), - aspect(). + aspect(). (undocumented) new interpolation escapes %w %h %{iT} %{mT} %{aR} for these methods. new configuration variables: `is_writable' defaults to writable_by_extension (older versions behaved as if it is 1); `writable_extensions' to diff -Nru libmp3-tag-perl-1.11/debian/changelog libmp3-tag-perl-1.12/debian/changelog --- libmp3-tag-perl-1.11/debian/changelog 2010-01-18 08:36:19.000000000 +0000 +++ libmp3-tag-perl-1.12/debian/changelog 2010-01-18 08:36:19.000000000 +0000 @@ -1,3 +1,11 @@ +libmp3-tag-perl (1.12-1) unstable; urgency=low + + * New upstream version. + * Standards-Version: 3.8.3 (no changes). + * Fix man page typos caught by lintian. + + -- Ian Beckwith Wed, 30 Dec 2009 00:42:40 +0000 + libmp3-tag-perl (1.11-1) unstable; urgency=low * New upstream version. diff -Nru libmp3-tag-perl-1.11/debian/control libmp3-tag-perl-1.12/debian/control --- libmp3-tag-perl-1.11/debian/control 2010-01-18 08:36:19.000000000 +0000 +++ libmp3-tag-perl-1.12/debian/control 2010-01-18 08:36:19.000000000 +0000 @@ -4,7 +4,7 @@ Build-Depends-Indep: perl (>= 5.8.0-7), libcompress-zlib-perl, file Build-Depends: debhelper (>= 6) Maintainer: Ian Beckwith -Standards-Version: 3.8.1 +Standards-Version: 3.8.3 Homepage: http://search.cpan.org/dist/MP3-Tag/ Package: libmp3-tag-perl diff -Nru libmp3-tag-perl-1.11/examples/mp3info2 libmp3-tag-perl-1.12/examples/mp3info2 --- libmp3-tag-perl-1.11/examples/mp3info2 2009-05-09 06:58:24.000000000 +0100 +++ libmp3-tag-perl-1.12/examples/mp3info2 2010-01-18 08:36:19.000000000 +0000 @@ -3,11 +3,12 @@ use FindBin; use lib "$FindBin::Bin"; -use MP3::Tag 0.9714; +use MP3::Tag 1.12; # Need conditional %L; %{mP} use Getopt::Std 'getopts'; use Config; +use File::Path; -$VERSION = '1.10'; +$VERSION = '1.12'; use strict; $Getopt::Std::STANDARD_HELP_VERSION = 1; @@ -79,7 +80,7 @@ } my $e_opt = MP3::Tag->get_config('extra_config_keys'); -MP3::Tag->config('extra_config_keys', @$e_opt, 'empty-F-deletes'); +MP3::Tag->config('extra_config_keys', @$e_opt, qw(empty-F-deletes frames_write_creates_dirs)); MP3::Tag->config('empty-F-deletes', 1) unless defined MP3::Tag->get_config1('empty-F-deletes'); @@ -121,7 +122,8 @@ my %F_human = qw( composer TCOM text_by TEXT orchestra TPE2 - conductor TPE3); # Only most useful, and not -l etc... + conductor TPE3 + disk_n TPOS); # Only most useful, and not -l etc... my $FNAME = qr/(?: # 1: Whole specifier \w{4} # 2: Frame name @@ -318,7 +320,17 @@ next unless defined $o; # Should not happen??? die "An attempt to extract `non-simple' frame `$set->[0]' to a file" if ref $o; - open FF, "> $v" or die "Can't open `$v' for write: $!"; + unless (open FF, "> $v") { + my $rc; + if (MP3::Tag->get_config1('frames_write_creates_dirs')) { + my ($dir) = ($v =~ m,^(.*)[\\/],s); + if (defined $dir and not -d $dir) { + mkpath $dir; # would die on error + $rc = open FF, "> $v" + } + } + die "Can't open `$v' for write: $!" unless $rc; + } binmode FF if $b; syswrite FF, $o, length $o or die "syswrite to `$v': $!" if length $o; @@ -411,8 +423,8 @@ if ($opt{x}) { print $mp3->interpolate(< module) for specified files. -It may also update the information in MP3 tags. This happens in three +It may also update the information in ID3 tags. This happens in three different cases. =over @@ -584,21 +596,25 @@ binary mode. (Whitespace is required about the C> signs.) If C> is replaced by C>, the value is set only if frame is not yet present, and if the file exists; if replaced by C>, the -value (if present) is written to F. +value (if present) is written to F (creation of intermediate directories +is controlled by configuration option C, the +default is FALSE). Additionally, C may be one of C or C or C; in this case, whole tags are written or read. For example, for C FILE>, C info is calculated from F<FILE>, which may be raw tags, as produced with C<E<gt>>, or a valid MP3 -file. (Likewise, for C<ID3v1 E<lt> FILE>, the same info is extracted from +file; if L<Image::ExifTool|Image::ExifTool> is present, the data may be +read from arbitrary multimedia file. (Likewise, for C<ID3v1 E<lt> FILE>, +the same info is extracted from C<ID3v1> tag only.) After this, in case of C<ID3v2> or C<TAGS>, C<ID3v2> frames are copied from the C<ID3v2> tag one-by-one. (With suitable modifications for C<?E<lt>>.) By default, the "VALUE" for C<-F> is C<%>-interpolated; this can be changed by option C<-E>. For user convenience, human-friendlier forms -C<composer, text_by, orchestra, conductor> can be used instead of -C<TCOM, TEXT, TPE2, TPE3>. +C<composer, text_by, orchestra, conductor, disk_n> can be used instead of +C<TCOM, TEXT, TPE2, TPE3, TPOS>. The option C<-P RECIPE> is a very powerful generalization of what can be done by options C<-F>, C<-d>, and C<-t -a -l -y -g -c -n>. It may be @@ -889,7 +905,7 @@ Suppose that a file F<Parts> in a directory of MP3 files has the following format: it has a preamble, then has a short paragraph of information per -audio file, preceeded by the track number and dot: +audio file, preceded by the track number and dot: ... @@ -949,7 +965,7 @@ two chunks of comment corresponding to two occurences of C<%c> on the right hand side.) -Finally, the fourth pattern is the same as in the preceeding example; it +Finally, the fourth pattern is the same as in the preceding example; it removes spurious punctuation at the end of the title. More examples: removing string "with violin" from the start of the diff -Nru libmp3-tag-perl-1.11/examples/typeset_audio_dir libmp3-tag-perl-1.12/examples/typeset_audio_dir --- libmp3-tag-perl-1.11/examples/typeset_audio_dir 2009-05-09 07:03:50.000000000 +0100 +++ libmp3-tag-perl-1.12/examples/typeset_audio_dir 2010-01-18 08:36:19.000000000 +0000 @@ -15,7 +15,7 @@ # use duration, year, whole dates, replace @ by %, basename of output files, # ignore 'author' on level > this in directory tree # use 'album' for titles with depth above this..., encodings, no comment,lyrics -getopts(my $opts = '2:1:TyYn@B:a:t:e:cLN:P:F:', \%opt); +getopts(my $opts = '2:1:TyYn@B:a:t:e:cLN:P:F:r:', \%opt); my(%plan, $both); sub set_plan ($) { @@ -57,6 +57,9 @@ } $opt{n} = $ENV{TYPESET_AUDIO_TRACK} || 1 if $opt{n}; +my $glob_pat = qr/\.mp3$/i; +$glob_pat = qr/$opt{r}/ if defined $opt{r}; + # booklet using precooked (broken) style cd-cover # Since it is very feature-poor, we did not try to debug a more decorated # appearance... @@ -312,7 +315,7 @@ # Callback for find(): sub print_mp3 { - return unless -f $_ and /\.mp3$/i; + return unless -f $_ and /$glob_pat/; #print STDERR "... $_\n"; my $tag = MP3::Tag->new($_); my @parts = split m<[/\\]>, $File::Find::dir; @@ -526,11 +529,13 @@ if (1 or $opt{L}) { # Allows inclusion of -L lists in non-L docs $common .= <<'EOP'; +\def\negTHINspace{\kern-.12em} % \negTHINspace is -.1666666em +\def\hasUnsyncLyrics{\global\let\ifhaveLyrics\iftrue \negTHINspace\textcircled{\textsc{l}}\negTHINspace} +\def\hasSyncLyrics{\global\let\ifhaveLyrics\iftrue \negTHINspace\textcircled{\textsc{s}}\negTHINspace} +\def\hasAPIC{\global\let\ifhaveAPIC\iftrue \negTHINspace\textcircled{\textsc{i}}\negTHINspace} + \newif\ifhaveLyrics \haveLyricsfalse \newif\ifhaveAPIC \haveAPICfalse -\def\hasUnsyncLyrics{\global\let\ifhaveLyrics\iftrue \textcircled{\textsc{l}}} -\def\hasSyncLyrics{\global\let\ifhaveLyrics\iftrue \textcircled{\textsc{s}}} -\def\hasAPIC{\global\let\ifhaveAPIC\iftrue \textcircled{\textsc{i}}} \def\reportLyricsSyntaxEtc{\ifhaveLyrics{\tiny\hasUnsyncLyrics/\hasSyncLyrics\quad---\quad has (un)syncronized lyrics\ifhaveAPIC ;\qquad \else \par \fi}\fi \ifhaveAPIC{\tiny\hasAPIC\quad---\quad @@ -611,9 +616,9 @@ \def\preSection{\pagebreak[2]\bgroup\centering\SectionFont \SectionSqueeze - \addvspace{0.2ex}% + \addvspace{\preSectionSKIP}% } -\def\postSection{\par\egroup \addvspace{.08ex}} +\def\postSection{\par\egroup \addvspace{\postSectionSKIP}} \CDbookletMargin=1.5mm \CDbookletTopMargin=1.5mm \CDsingleMargin=1.5mm @@ -650,7 +655,8 @@ EOP my $set_columns = <<'EOP'; -\columnsep 9pt +% Tested to work reasonably well with fonts between 5pt and 10pt +\RecordFont \columnsep 1.8ex \advance \columnsep -1.4pt % ex of RecordFont \columnseprule.4pt %\multicolsep 3pt plus 4pt minus 3pt % Need to put adjacent horizontal lines, so this is better: @@ -678,6 +684,7 @@ \documentclass{article} % Use 2mm margin inside 12cm x 12cm page; page numbers fit only accidentally... +% add a4paper or letterpaper if needed (e.g., on broken LaTeX installations) \usepackage[centering,landscape,width=11.6truecm,height=11.6truecm,nohead,nofoot]{geometry} \usepackage{multicol} @@ -743,7 +750,7 @@ my $normal_text_class = <<'EOP'; \documentclass[12pt]{article} -\usepackage[margin=1cm,nohead,nofoot]{geometry} +\usepackage[margin=1cm,nohead,nofoot]{geometry} % may need a4paper/letterpaper \usepackage{multicol} EOP @@ -757,21 +764,21 @@ TitleNameFont \bfseries\footnotesize TitleFont \tinyish SectionFont \bfseries\footnotesize SubSectionFont \bfseries\scriptsize - RecordFont \tinyish columns 3 global_multicol 1 rules 1)}], + RecordFont \mdseries\tinyish columns 3 global_multicol 1 rules 1)}], [$out_cdcover_std, "$class_cdcover_std$common_enc$cdcover_set$cdcover_on", {qw(TitleNameFont \bfseries\tiny TitleFont \tiny SectionFont \bfseries\small SubSectionFont \bfseries\small - RecordFont \scriptsize columns 2)}], + RecordFont \mdseries\scriptsize columns 2)}], [$out_normal_text, "$normal_text_class$set_columns$common_enc$set_headers", {qw(TitleNameFont \bfseries\normalsize TitleFont \small SectionFont \bfseries\normalsize SubSectionFont \bfseries\small - RecordFont \footnotesize columns 2 rules 1)}], + RecordFont \mdseries\footnotesize columns 2 rules 1)}], [$out_cdcover_our, "$duplex_instr_and_class$set_columns$common_enc" . "$set_headers", {qw(TitleNameFont \bfseries\normalsize TitleFont \footnotesize SectionFont \bfseries\normalsize SubSectionFont \bfseries\small - RecordFont \scriptsize columns 2 rules 1 frame 1)}]) { + RecordFont \mdseries\scriptsize columns 2 rules 1 frame 1)}]) { my($out,$txt) = ($o->[0], $o->[1]); print $out output_setup($o->[2]); if (defined $opt{B}) { @@ -780,8 +787,9 @@ \\input{$opt{B}_common}% EOQ -%\def\squeezeContunuationLines{% typesets continuation lines very squeezed +%\def\squeezeContunuationLines{% typeset continuation lines almost max-squeezed % % ARGS = BETWEEN LINES / +ITS INC / BASELINE-SKIP-in-height-of(0) / PARSKIP +% % PARSKIP is the skip between records, the rest before continuation line % \contunuationLineSkip{-0.2ex}{plus 0.24ex}{1.3}{-0.08ex plus 0.44ex}} EOP @@ -829,8 +837,9 @@ \RecordFont \RecordSqueeze % enable now - %\def\squeezeContunuationLines{% typesets continuation lines very squeezed + %\def\squeezeContunuationLines{% typesets continuation lines almost max-squeezed % % ARGS = BETWEEN LINES / +ITS INC / BASELINE-SKIP-in-height-of(0) / PARSKIP + % % PARSKIP is the skip between records, the rest before continuation line % \contunuationLineSkip{-0.2ex}{plus 0.24ex}{1.3}{-0.08ex plus 0.44ex}} { \def\preSubSectionSKIP{1.2pt} % Pre- and post- level-2 heading @@ -1022,10 +1031,13 @@ =head1 DESCRIPTION Scans directory (or directories) given on the command line, using -L<MP3::Tag> to obtain information about audio files (currently only -MP3s). Produces (one or more, depending on B<-B> option) B<TeX> files +L<MP3::Tag|MP3::Tag> to obtain information about audio files (to process +non-MP3 files, extra modules may be needed, see L<MP3::Tag>, and B<-r +FILENAME_FILTER> option must be given). Produces +(one or more, depending on B<-B> option) B<TeX> files with commands to typeset human-readable listings. Non-directories on -the command line are ignored. +the command line are ignored. (May also be used to process non-audio +files, if L<MP3::Tag|MP3::Tag> may extract the title/etc info from them.) With B<-B>, the file F<*_list.tex> contains all the data about audio files (when B<-P> with both C<short,long> is given, another similar file @@ -1113,7 +1125,10 @@ =item B<-n> Enable emit track number. Environment variable TYPESET_AUDIO_TRACK -may contain the format to interpolate for typesetting. +may contain the format to interpolate for typesetting (defaults to +C<%{mA}%{n1}>). For example, set TYPESET_AUDIO_TRACK to C<%{n1}> +to use "pure" track number instead of combination of media/disk number +and track number. =item B<-1> @@ -1147,7 +1162,7 @@ new heading. B<NOTE:> maybe this default of 2 is not very intuitive. It is -recommended to explicitely set this option to the value you feel +recommended to explicitly set this option to the value you feel appropriate (C<1e100> would play role of infinity - so any change will generate a new second-level heading). @@ -1198,6 +1213,11 @@ installation is broken and C<T2A> is not available, you may try C<T1> or C<OT1>. See L<"PROBLEMS when TYPESETTING">. +=item B<-r FILENAME_FILTER> + +sets the regular expression for filenames to look for (the default is +C<(?i:\.mp3$)>. + =back =head1 Info read from file system @@ -1333,6 +1353,11 @@ =back +Example commandline working with some of complications + + dvips -t landscape -f < All_cdbooklet-a4.dvi | psbook | pstops -pa4 "2:0(0,-6cm)+1(0,6cm)" | pstops -pa4 "2:0,1U(1w,1h)" > Output-even_flipped-a4.ps + && ps2pdf -sPAPERSIZE=a4 -dAutoRotatePages=/None Output-even_flipped-a4 + Likewise, quite often one needs to add C<-pletter> to C<ps2ps> commandlines for correct printing to letter-size paper. You can check the resulting PDF file in a viewer: the status line should show the correct paper size @@ -1400,7 +1425,10 @@ that setting C<\parskip> is a part of the action of C<\squeezeContunuationLines>. C<\columnsep> regulates the horizontal separation of columns. One can also fine-tune the vertical position -of the start of the first page.) +of the start of the first page; for backcover, also tune up C<\CDbackMargin> +and C<\CDbackTopMargin>. The definition(s) of C<\squeezeContunuationLines> +are commented out (by C<%>) in non-F<*_common.tex> files; you may uncomment +it, and tune it up separately for each TeX file.) One can combine two (or more) lists (e.g., one with the short style, and one with the long style) into one output file; the generated files diff -Nru libmp3-tag-perl-1.11/lib/MP3/Tag/File.pm libmp3-tag-perl-1.12/lib/MP3/Tag/File.pm --- libmp3-tag-perl-1.11/lib/MP3/Tag/File.pm 2010-01-18 08:36:19.000000000 +0000 +++ libmp3-tag-perl-1.12/lib/MP3/Tag/File.pm 2010-01-18 08:36:19.000000000 +0000 @@ -201,7 +201,7 @@ If $filename is defined this filename will be used and not the real filename which was set by L<MP3::Tag> with -C<MP3::Tag->new($filename)>. Otherwise the actual filename is used +C<MP3::Tag-E<gt>new($filename)>. Otherwise the actual filename is used (subject to configuration variable C<decode_encoding_filename>). Following formats will be hopefully recognized: diff -Nru libmp3-tag-perl-1.11/lib/MP3/Tag/ID3v2.pm libmp3-tag-perl-1.12/lib/MP3/Tag/ID3v2.pm --- libmp3-tag-perl-1.11/lib/MP3/Tag/ID3v2.pm 2010-01-18 08:36:19.000000000 +0000 +++ libmp3-tag-perl-1.12/lib/MP3/Tag/ID3v2.pm 2010-01-18 08:36:19.000000000 +0000 @@ -15,7 +15,7 @@ %back_splt %embedded_Descr /; -$VERSION="1.11"; +$VERSION = "1.12"; @ISA = 'MP3::Tag::__hasparent'; my $trustencoding = $ENV{MP3TAG_DECODE_UNICODE}; @@ -61,7 +61,7 @@ $frameIDs_hash = $id3v2->get_frame_ids('truename'); foreach my $frame (keys %$frameIDs_hash) { - my ($name, @info) = $id3v2->get_frame($frame); + my ($name, @info) = $id3v2->get_frames($frame); for my $info (@info) { if (ref $info) { print "$name ($frame):\n"; @@ -714,7 +714,7 @@ performed: if the audio file does not contain an ID3v2 tag, or the tag in the file is smaller than the built ID3v2 tag, the necessary 0-padding is inserted before the audio content of the file so that it -is able to accomodate the build tag (and the C<tagsize> field of +is able to accommodate the build tag (and the C<tagsize> field of $id3v2 is updated correspondingly); in any case the header length of $tag2 is set to reflect the space in the beginning of the audio file. @@ -886,7 +886,7 @@ original filename. Do not use remove_tag() if you only want to change a header, -as otherwise the file is copied unneccessary. Use write_tag() +as otherwise the file is copied unnecessarily. Use write_tag() directly, which will override an old tag. =cut @@ -1090,6 +1090,20 @@ } elsif (exists $fs->{mlen} and $fs->{mlen}>0) { $d .= " " x ($fs->{mlen}-length($d)) if length($d) < $fs->{mlen}; } + if (exists $fs->{re2b}) { + while (my ($pat, $rep) = each %{$fs->{re2b}}) { + $d =~ s/$pat/$rep/gis; + } + } + if (exists $fs->{func_back}) { + $d = $fs->{func_back}->($d); + } elsif (exists $fs->{func}) { + if ($fs->{small_max}) { # Allow the old way (byte) and a number + # No conflict possible: byte is always smaller than ord '0' + $d = pack 'C', $d if $d =~ /^\d+$/; + } + $d = $self->__format_field($fname, $fs->{name}, $d) + } if ($fs->{encoded}) { if ($encoding) { # 0 = latin1 (effectively: unknown) @@ -1114,20 +1128,6 @@ $self->fix_frames_encoding(); } } - if (exists $fs->{re2b}) { - while (my ($pat, $rep) = each %{$fs->{re2b}}) { - $d =~ s/$pat/$rep/gis; - } - } - if (exists $fs->{func_back}) { - $d = $fs->{func_back}->($d); - } elsif (exists $fs->{func}) { - if ($fs->{small_max}) { # Allow the old way (byte) and a number - # No conflict possible: byte is always smaller than ord '0' - $d = pack 'C', $d if $d =~ /^\d+$/; - } - $d = $self->__format_field($fname, $fs->{name}, $d) - } $datastring .= $d; } @@ -1547,8 +1547,9 @@ =item _Data_to_MIME -Internal method to extract MIME type from a string the image file content. -Returns C<application/octet-stream> for unrecognized data. +Internal method to extract MIME type from a string the image file +content. Returns C<application/octet-stream> for unrecognized data +(unless extra TRUE argument is given). $format = $id3v2->_Data_to_MIME($data); @@ -1563,9 +1564,12 @@ "II*\0" => 'image/tiff', "\x89PNG", qw(image/png GIF8 image/gif BM image/bmp)); -sub _Data_to_MIME ($$) { - my($self, $data) = (shift, shift); # Fname, field name remain - $MT{substr $data, 0, 4} || $MT{substr $data, 0, 2} || 'application/octet-stream'; +sub _Data_to_MIME ($$;$) { + my($self, $data, $force) = (shift, shift, shift); # Fname, field name remain + my $res = $MT{substr $data, 0, 4} || $MT{substr $data, 0, 2}; + return $res if $res; + return 'application/octet-stream' unless $force; + return; } sub _frame_select { # if $extract_content false, return all found @@ -1982,7 +1986,7 @@ C<new> tries to find a ID3v2 tag in the mp3fileobj. If it does not find a tag it returns undef. Otherwise it reads the tag header, as well as an extended header, if available. It reads the rest of the tag in a -buffer, does unsynchronizing if neccessary, and returns a +buffer, does unsynchronizing if necessary, and returns a ID3v2-object. At this moment only ID3v2.3 is supported. Any extended header with CRC data is ignored, so no CRC check is done at the moment. The ID3v2-object can be used to extract information from @@ -1999,7 +2003,7 @@ =cut sub new { - my ($class, $mp3obj, $create) = @_; + my ($class, $mp3obj, $create, $r_header) = @_; my $self={mp3=>$mp3obj}; my $header=0; bless $self, $class; @@ -2008,6 +2012,7 @@ $mp3obj->open or return unless $mp3obj->is_open; $mp3obj->seek(0,0); $mp3obj->read(\$header, 10); + $$r_header = $header if $r_header and 10 == length $header; } $self->{frame_start}=0; # default ID3v2 version @@ -2079,7 +2084,9 @@ sub new_with_parent { my ($class, $filename, $parent) = @_; - return unless my $new = $class->new($filename, undef); + my $header; + my $new = $class->new($filename, undef, \$header); + ($header and $parent and $parent->[0]{header} = $header), return unless $new; $new->{parent} = $parent; $new; } diff -Nru libmp3-tag-perl-1.11/lib/MP3/Tag/ParseData.pm libmp3-tag-perl-1.12/lib/MP3/Tag/ParseData.pm --- libmp3-tag-perl-1.11/lib/MP3/Tag/ParseData.pm 2009-04-15 03:15:28.000000000 +0100 +++ libmp3-tag-perl-1.12/lib/MP3/Tag/ParseData.pm 2010-01-18 08:36:19.000000000 +0000 @@ -97,7 +97,7 @@ using the configuration item C<parse_split>; it defaults to C<"\n">.) If the configuration item C<parse_data> has multiple options, the $strings -which are interpolated will use information set by preceeding options; +which are interpolated will use information set by preceding options; similarly, any interolated option may use information obtained by other handlers - even if these handers are later in the pecking order than C<MP3::Tag::ParseData> (which by default is the first handler). For diff -Nru libmp3-tag-perl-1.11/lib/MP3/Tag.pm libmp3-tag-perl-1.12/lib/MP3/Tag.pm --- libmp3-tag-perl-1.11/lib/MP3/Tag.pm 2010-01-18 08:36:19.000000000 +0000 +++ libmp3-tag-perl-1.12/lib/MP3/Tag.pm 2010-01-18 08:36:19.000000000 +0000 @@ -41,7 +41,7 @@ use MP3::Tag::LastResort; use vars qw/$VERSION @ISA/; -$VERSION="1.11"; +$VERSION="1.12"; @ISA = qw( MP3::Tag::User MP3::Tag::Site MP3::Tag::Vendor MP3::Tag::Implemenation ); # Make overridable *config = \%MP3::Tag::Implemenation::config; @@ -130,7 +130,7 @@ $mp3->title_set('New title'); # Edit in-memory copy $mp3->select_id3v2_frame_by_descr('TALB', 'New album name'); # Edit in memory $mp3->select_id3v2_frame_by_descr('RBUF', $n1, $n2, $n3); # Edit in memory - $mp3->update_tags(year => 1866); # Edit in-memory, and commit to file + $mp3->update_tags({year => 1866}); # Edit in-memory, and commit to file $mp3->update_tags(); # Commit to file The following low-level access code is discouraged; better use title() @@ -619,9 +619,11 @@ } } +my %hide_meth = qw(mime_type _mime_type); + for my $elt ( qw( cddb_id cdindex_id height width bit_depth mime_type img_type _duration ) ) { no strict 'refs'; - *$elt = sub (;$) { + *{$hide_meth{$elt} || $elt} = sub (;$) { my $self = shift; return $self->auto_field($elt, @_); } @@ -667,11 +669,31 @@ $w/$h; } +sub aspect_ratio_inverted ($) { + my $r = shift->aspect_ratio or return; + 1/$r; +} + sub aspect_ratio3 ($) { my $r = shift->aspect_ratio(); $r ? sprintf '%.3f', $r : $r; } +sub mime_Pretype ($) { + my $r = shift->mime_type(); + $r =~ s,/.*,,s; + ucfirst lc $r +} + +sub mime_type ($) { # _mime_type goes thru auto_field 'mime_type' + my $self = shift; + $self->get_tags; + my $h = $self->{header}; + my $t = $h && $self->_Data_to_MIME($h, 1); + return $t if $t; + return($self->_mime_type() || 'audio/mpeg'); # XXXX Can do much better +} + =item genre() $genre = $mp3->genre(); # empty string unless found @@ -1554,14 +1576,15 @@ $from->copy_frames($to->{ID3v2}, $overwrite, $keep_flags, $f_ids); } -sub _Data_to_MIME ($$) { +sub _Data_to_MIME ($$;$) { goto &MP3::Tag::ID3v2::_Data_to_MIME } =item _Data_to_MIME Internal method to extract MIME type from a string the image file content. -Returns C<application/octet-stream> for unrecognized data. +Returns C<application/octet-stream> for unrecognized data +(unless extra TRUE argument is given). $format = $id3->_Data_to_MIME($data); @@ -1716,15 +1739,26 @@ o channel_mode u frames - h height (these 4 for image files, Image::Size required) + h height (these 3 for image files, Image::Size or Image::ExifData required) w width - mT mime_type iT img_type - aR aspect_ratio3 (3 decimal places after the dot) + mT mime_type + mP mime_Pretype (the capitalized first part of mime_type) + aR aspect_ratio (width/height) + a3 aspect_ratio3 (3 decimal places after the dot) + aI aspect_ratio_inverted (height/width) bD bit_depth -Additionally, ESCAPE can be a string enclosed in curly braces C<{}>. -The interpretation is the following: + aC collection artist (from CDDB_File) + tT track title (from CDDB_File) + cC collection comment (from CDDB_File) + cT track comment (from CDDB_File) + iC CDDB id + iI CDIndex id + +(Multi-char escapes must be inclosed in braces, as in C<%{SML}> or C<%.5{aR}>. + +Additional multi-char escapes are interpretated is follows: =over 4 @@ -1735,11 +1769,6 @@ =item * -Strings C<aC>, C<tT>, C<cC>, C<cT> are replaced by the collection artist, -track title, collection comment, and track comment as obtained from -CDDB_File. Strings C<iC>, C<iI> are replaced by the CDDB and CDIndex -ids as obtained from CDDB_File or Inf. - Strings C<n1> and C<n2> are replaced by "pure track number" and "max track number" (this allows for both formats C<N1> and C<N1/N2> of "track", the latter meaning track N1 of N2); use C<n0> to pad C<n1> with leading 0 @@ -1878,7 +1907,9 @@ For strings of the form C<T[FORMAT]>, I<FORMAT> is split on comma, and the resulting list of formats is used to convert the duration of the -audio to a string using the method format_time(). +audio to a string using the method format_time(). (E.g., +C<%{T[=E<gt>m,?H:,m]}> would print duration in hours and minutes rounded +to the closest minute.) =back @@ -1918,7 +1949,7 @@ Interpolation of ID3v2 frames uses the minimal possible non-ambiguous backslashing rules: the only backslashes needed are to protect the innermost closing delimiter (C<]> or C<}>) appearing as a literal -character, or to protect backslashes I<immediately> preceeding such +character, or to protect backslashes I<immediately> preceding such literal, or the closing delimiter. E.g., the pattern equal to %{COMM(eng)[a\b\\c\}\]end\\\]\\\\]: comment `a\b\\c\\\}]end\]\\' present} @@ -1970,9 +2001,12 @@ h height w width - mT mime_type iT img_type - aR aspect_ratio3 + mT mime_type + mP mime_Pretype + aR aspect_ratio + a3 aspect_ratio3 + aI aspect_ratio_inverted bD bit_depth v mpeg_version @@ -2013,18 +2047,18 @@ my $frame_bra = # FRAM | FRAM03 | FRAM(lang)[ qr{\w{4}(?:(?:\d\d)|(?:\([^()]*(?:\([^()]+\)[^()]*)*\))?(?:(\[)|(?=[\}:|&])))}s; # 1 group for begin-descr -# used with offset by 1: 2: fill, 3: same, 4: $left, 5..6 width, 5: key +# used with offset by 1: 2: fill, 3: same, 4: $left, 5..6 width, 7: key my $pat_rx = qr/^%(?:(?:\((.)\)|([^-.1-9%a-zA-Z]))?(-)?(\d+))?(?:\.(\d+))?([talgcynfFeEABDNvLrqQSmsCpouMHwh{%])/s; # XXXX Partially repeated below, search for `talgc'??? vLrqQSmsCpouMH miss??? -my $longer_f = qr(a[CR]|tT|c[TC]|i[DIT]|n[012]|m[A12T]|bD); +my $longer_f = qr(a[3CRI]|tT|c[TC]|i[DIT]|n[012]|m[A12TP]|bD); # (a[CR]|tT|c[TC]|[mMS]L|SML|i[DIT]|n[012]|m[A12T]|bD) # a[CR]|tT|c[TC]|i[DIT]|n[012]|m[A12T]|bD # $upto TRUE: parse the part including $upto char # Very restricted backslashitis: only $upto and \ before $upto-or-end # $upto defined but FALSE: interpolate only one %-escape. -# Anyway: $_[1] is modified to remove interplated part. +# Anyway: $_[1] is modified to remove interpolated part. sub _interpolate ($$;$$) { # goto &interpolate_flags if @_ == 3; my ($self, undef, $upto, $skip) = @_; # pattern is modified, so is $_[1] @@ -2233,7 +2267,27 @@ $str = $self->$meth(); } $str = '' unless defined $str; - $str = substr $str, 0, $maxwidth if defined $maxwidth; + if (defined $maxwidth and length $str > $maxwidth) { + if ($str =~ /^(?:\+|(\-))?(\d*)(\.\d*)?$/) { + if (length($1 || '') + length $2 <= $maxwidth) { + my $w = $maxwidth - length $2 - length($1 || ''); + $w-- if $w; # Take into account decimal point... + $str = sprintf '%.*f', $w, $str + } else { # Might be a long integer benefiting from %g + my($w, $s0) = ($maxwidth, $str); + while ($w >= 1) { + $str = sprintf '%.*g', $w, $s0; + $str =~ s/(^|(?<=[-+]))0+|(?<=e)\+//gi; # 1e+07 to 1e7 + last if length $str <= $maxwidth; + $w-- + } + $str = $s0 if length $str > length $s0; # 12 vs 1e1 + $str = substr $str, 0, $maxwidth; # 1e as a truncation of 1234 is better than 12... + } + } else { + $str = substr $str, 0, $maxwidth; + } + } if (defined $minwidth) { $fill = ' ' unless defined $fill; if ($left) { @@ -2737,7 +2791,7 @@ redirectoed to the module L<MP3::Info|MP3::Info>, the returned info is subject to the same restrictions as the method get_mp3info() of this module; in particular, the information about the frame number and -frame length is only approximate +frame length is only approximate. vbr_scale() is from the VBR header; total_secs() is not necessarily an integer, but total_secs_int() and total_secs_trunc() are (first is @@ -2841,11 +2895,11 @@ descriptors. Each format descriptor is either a simple letter, or a string in braces appropriate to be put after C<%> in an interpolated string. A format descriptor can be followed by a literal string to be -put as a suffix, and can be preceeded by a question mark, which says +put as a suffix, and can be preceded by a question mark, which says that this part of format should be printed only if needed. Leftover minutes, seconds are formated 0-padded to width 2 if they are -preceeded by more coarse units. Similarly, leftover milliseconds are +preceded by more coarse units. Similarly, leftover milliseconds are printed with leading dot, and 0-padded to width 3. Two examples of useful C<@format>s are @@ -2858,20 +2912,36 @@ not print the trailing 0s of milliseconds. The first one uses C<:> as separator of hours and minutes, the second one will use C<h m>. +Optionally, the first element of the array may be of the form +C<=E<gt>U>, here C<U> is one of C<h m s>. In this case, duration is +rounded to closest hours, min or second before processing. (E.g., +1.7sec would print as C<1> with C<@format>s above, but would print as +C<2> if rounded to seconds.) + =cut +my %Unit = qw( h 3600 m 60 s 1 ); + sub format_time { my ($self, $time) = (shift, shift); $self = $self->new_fake() unless ref $self; + local $self->{ms} = $self->{ms}; # Make modifiable local $self->{ms} = int($time * 1000 + 0.5) if defined $time; - my ($out, %have) = ''; + my ($out, %have, $c) = ''; for my $f (@_) { $have{$+}++ if $f =~ /^\??({([^{}]+)}|.)/; } for my $f (@_) { + if (!$c++ and $f =~ /^=>(\w)$/) { + my $u = $Unit{$1} or die "Unexpected unit of time for rounding: `$1'"; + $time = $self->total_secs unless defined $time; + $time = $u * int($time/$u + 0.5); + $self->{ms} = 1000 * $time; + next; + } my $ff = $f; # Modifiable my $opt = ($ff =~ s/^\?//); - $ff =~ s/^({[^{}]+}|\w)// or die "<$f>"; + $ff =~ s/^({[^{}]+}|\w)// or die "unexpected time format: <<$f>>"; my ($what, $format) = ($1, ''); if ($opt) { if ($what eq 'H') { diff -Nru libmp3-tag-perl-1.11/lib/Normalize/Text/Music_Fields/Music_Fields-rus.lst libmp3-tag-perl-1.12/lib/Normalize/Text/Music_Fields/Music_Fields-rus.lst --- libmp3-tag-perl-1.11/lib/Normalize/Text/Music_Fields/Music_Fields-rus.lst 2009-04-20 05:28:00.000000000 +0100 +++ libmp3-tag-perl-1.12/lib/Normalize/Text/Music_Fields/Music_Fields-rus.lst 2009-06-19 10:34:24.000000000 +0100 @@ -70,10 +70,12 @@ Тимур Шаов Три Сучка Вадим и Валерий Мищуки -Васильев и Иващенко Вероника Долина Владимир Ланцберг +## This causes infinite loop of expansion Иващенко => Васильев и Иващенко => Иващенко +## Васильев и Иващенко + Михаил Светлов (1903-6-17--1964-7-28) Эдуард Багрицкий (1895-11-4--1939-2-16) Виктор Соснора @@ -205,6 +207,8 @@ # shortname Арс. Тарковский # shortname И. Киуру # shortname А. Апухтин +# shortname Дж. Киплинг +# shortname Дж. Лондон ## This might be wrongly expanded when combinations like ## Сергей и Татьяна Никитины, Виктор Берковский diff -Nru libmp3-tag-perl-1.11/Makefile.PL libmp3-tag-perl-1.12/Makefile.PL --- libmp3-tag-perl-1.11/Makefile.PL 2010-01-18 08:36:19.000000000 +0000 +++ libmp3-tag-perl-1.12/Makefile.PL 2010-01-18 08:36:19.000000000 +0000 @@ -3,18 +3,22 @@ use strict; my @programs_to_install = qw(mp3info2 typeset_audio_dir audio_rename); -my $install_bin = 1; -if ( grep $_ eq '-n', @ARGV - or grep /^LIB=/, @ARGV and not grep /^INSTALLSCRIPT=/, @ARGV ) { +my $lib_only = (grep /^LIB=/, @ARGV and not grep /^INSTALLSCRIPT=/, @ARGV); +my @scr = grep /^INSTALLSCRIPT=/, @ARGV; +(my $scr = pop @scr) =~ s/^INSTALLSCRIPT=//; +$scr = $Config{installscript} unless defined $scr; + +if ( grep $_ eq '-n', @ARGV or $lib_only ) { @ARGV = grep $_ ne '-n', @ARGV; + warn "I see LIB= but not no INSTALLSCRIPT=\n" if $lib_only; warn "Skipping installation of scripts...\n"; @programs_to_install = (); } else { warn <<EOW; This program comes with several scripts which I would try to install in -directory $Config{installscript}. +directory $scr. To skip, rerun with option -n given to Makefile.PL. diff -Nru libmp3-tag-perl-1.11/META.yml libmp3-tag-perl-1.12/META.yml --- libmp3-tag-perl-1.11/META.yml 2009-05-11 05:53:50.000000000 +0100 +++ libmp3-tag-perl-1.12/META.yml 2009-11-27 06:36:18.000000000 +0000 @@ -1,10 +1,21 @@ -# http://module-build.sourceforge.net/META-spec.html -#XXXXXXX This is a prototype!!! It will change in the future!!! XXXXX# -name: MP3-Tag -version: 1.11 -version_from: lib/MP3/Tag.pm -installdirs: site -requires: - -distribution_type: module -generated_by: ExtUtils::MakeMaker version 6.30 +--- #YAML:1.0 +name: MP3-Tag +version: 1.12 +abstract: ~ +author: + - "Thomas Geffert" <thg@users.sourceforge.net>, "Ilya Zakharevich" ilyaz@cpan.org +license: unknown +distribution_type: module +configure_requires: + ExtUtils::MakeMaker: 0 +build_requires: + ExtUtils::MakeMaker: 0 +requires: {} +no_index: + directory: + - t + - inc +generated_by: ExtUtils::MakeMaker version 6.54 +meta-spec: + url: http://module-build.sourceforge.net/META-spec-v1.4.html + version: 1.4 diff -Nru libmp3-tag-perl-1.11/TODO libmp3-tag-perl-1.12/TODO --- libmp3-tag-perl-1.11/TODO 2006-01-24 00:19:58.000000000 +0000 +++ libmp3-tag-perl-1.12/TODO 2009-07-19 23:18:44.000000000 +0100 @@ -40,3 +40,6 @@ when the frame is read, not when it is written * Support for v2.4 output (is input fully supported now?) + +* http://gabriel.mp3-tech.org/mp3infotag.html + http://web.archive.org/web/20010827032505/privatewww.essex.ac.uk/~djmrob/replaygain/rg_data_format.html