.\" Automatically generated by Pod::Man 2.25 (Pod::Simple 3.16) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is turned on, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .ie \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . nr % 0 . rr F .\} .el \{\ . de IX .. .\} .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "MP3INFO2 1p" .TH MP3INFO2 1p "2010-03-07" "perl v5.14.2" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" mp3info2 \- get/set MP3 tags; uses MP3::Tag to get default values. .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 2 \& # Print the information in tags and autodeduced info \& mp3info2 *.mp3 \& \& # In addition, set the year field to 1981 \& mp3info2 \-y 1981 *.mp3 \& \& # Same without printout of info, recursively in the current directory \& mp3info2 \-R \-p "" \-y 1981 . \& \& # Do not deduce any field, print (normalized) info from the tags only \& mp3info2 \-C autoinfo=ID3v2,ID3v1 *.mp3 \& \& # As above, but without normalization/autofill, the raw information in tags \& mp3info2 \-N *.mp3 \& \& # As above, but only with ID2v1 tag read \& mp3info2 \-NC autoinfo=ID3v1 *.mp3 \& \& # Get artist from CDDB_File, autodeduce other info, write it to tags \& mp3info2 \-C artist=CDDB_File \-u *.mp3 \& \& # For title, prefer information from .inf file; autodeduce rest, update \& mp3info2 \-C title=Inf,ID3v2,ID3v1,filename \-u *.mp3 \& \& # Same, and get the artist from CDDB file \& mp3info2 \-C title=Inf,ID3v2,ID3v1,filename \-C artist=CDDB_File \-u *.mp3 \& \& # Write a script for conversion of .wav to .mp3, autodeducing tags \& mp3info2 \-p "lame \-h \-\-vbr\-new \-\-tt \*(Aq%t\*(Aq \-\-tn %n \-\-ta \*(Aq%a\*(Aq \-\-tc \*(Aq%c\*(Aq \-\-tl \*(Aq%l\*(Aq \-\-ty \*(Aq%y\*(Aq \*(Aq%f\*(Aq\en" *.wav >xxx.sh .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" The program prints a message summarizing tag info (obtained via MP3::Tag module) for specified files. .PP It may also update the information in \s-1ID3\s0 tags. This happens in three different cases. .IP "\(bu" 4 If the information supplied in command-line options \f(CW\*(C`t a l y g c n\*(C'\fR differs from the content of the corresponding \s-1ID3\s0 tags (or there is no corresponding \s-1ID3\s0 tags). .IP "\(bu" 4 If options \f(CW\*(C`\-d\*(C'\fR or \f(CW\*(C`\-F\*(C'\fR were given. .IP "\(bu" 4 if \f(CW\*(C`MP3::Tag\*(C'\fR obtains the info from other means than \s-1MP3\s0 tags, and \&\f(CW\*(C`\-u\*(C'\fR forces the update of the \s-1ID3\s0 tags. .PP (All these ways are disabled by \f(CW\*(C`\-D\*(C'\fR option.) ID3v2 tag is written if needed, or if \f(CW\*(C`\-2\*(C'\fR option is given. (Automatic fill-in of deduceable fields (via the method \fIid3v2_frames_autofill()\fR) is performed unless \f(CW\*(C`\-d\*(C'\fR or \f(CW\*(C`\-N\*(C'\fR options are given.) .PP The option \f(CW\*(C`\-u\*(C'\fR writes (\f(CW\*(C`u\*(C'\fRpdates) the fetched information to the \&\s-1MP3\s0 \s-1ID3\s0 tags. This option is assumed if there are command-line options which explicitly set tag elements (\f(CW\*(C`\-a\*(C'\fR, \f(CW\*(C`\-t\*(C'\fR etc., and \f(CW\*(C`\-F\*(C'\fR, \f(CW\*(C`\-d\*(C'\fR). (Effects of this option may be overridden by giving \f(CW\*(C`\-D\*(C'\fR option.) If \f(CW\*(C`\-2\*(C'\fR option is also given, forces write of ID3v2 tag even if the info fits the ID3v1 tag (in addition, this option enables auto-update of \*(L"personal name\*(R" fields, and corresponding titles according to values of \f(CW\*(C`translate_person\*(C'\fR, \f(CW\*(C`person_frames\*(C'\fR etc. configuration settings; see \*(L"Normalization of fields\*(R"). This option is ignored if no change to tags is detected; however, one can force an update by repeating this option (useful if you expect the change the \&\*(L"format\*(R" of the tag, as opposed to its \*(L"content\*(R"). .PP The option \f(CW\*(C`\-p\*(C'\fR prints a message using the next argument as format (by default \f(CW\*(C`\e\e\*(C'\fR, \f(CW\*(C`\et\*(C'\fR, \f(CW\*(C`\en\*(C'\fR are replaced by backslash, tab and newline; governed by the value of \f(CW\*(C`\-E\*(C'\fR option); see \&\*(L"interpolate\*(R" in MP3::Tag for details of the format of \fIsprintf()\fR\-like escapes. If no option \f(CW\*(C`\-p\*(C'\fR is given, message in default format will be emitted. The value of option \f(CW\*(C`\-e\*(C'\fR is the encoding used for the output; if the value is a number, system-specific encoding is guessed (and used for the output if bit 0x1 is set); if bit 0x2 is set, then, command line options are assumed to be in the guessed encoding; if bit 0x4 is set, then, command line arguments are assumed to be in the guessed encoding. Use the value \f(CW\*(C`binary\*(C'\fR to do binary output. .PP With option \f(CW\*(C`\-D\*(C'\fR (dry run) no update is performed, no matter what the other options are. With this option, no parsing of tags is performed unless needed. .PP Use options .PP .Vb 1 \& t a l y g c n .Ve .PP to overwrite the information (title artist album year genre comment track-number) obtained via \f(CW\*(C`MP3::Tag\*(C'\fR heuristics (\f(CW\*(C`\-u\*(C'\fR switch is implied if any one of these arguments differs from what would be found otherwise; use \f(CW\*(C`\-D\*(C'\fR switch to disable auto-update). By default, the values of these options are not \f(CW\*(C`%\*(C'\fR\-interpolated; this may be changed by \&\f(CW\*(C`\-E\*(C'\fR option. .PP The option \f(CW\*(C`\-d\*(C'\fR should contain the comma-separated list of ID3v2 frames to delete. A frame specification is the same as what might be given to \f(CW"%{...}"\fR frame interpolation command, e.g., \f(CW\*(C`TIT3\*(C'\fR, \&\f(CW\*(C`COMM03\*(C'\fR, \f(CW\*(C`COMM(fra)[short title]\*(C'\fR; the difference with modify-access is that \fB\s-1ALL\s0\fR (and not the \fBfirst\fR of) matching frames are deleted. (Option \-d may be repeated.) .PP For example, \f(CW\*(C`\-d APIC\*(C'\fR would remove all picture frames. In addition, if the list contains \f(CW\*(C`ID3v1\*(C'\fR or \f(CW\*(C`ID3v2\*(C'\fR, whole tags will be deleted. .PP Likewise, the option \f(CW\*(C`\-F\*(C'\fR allows setting of arbitrary \f(CW\*(C`ID3v2\*(C'\fR frames: if one needs to set one frame, use the directive \f(CW\*(C`FRAME_spec=VALUE\*(C'\fR: .PP .Vb 1 \& \-F TIT2=The_new_Title .Ve .PP Again, on modify, \fB\s-1ALL\s0\fR matching frames are deleted first, so be carefull with .PP .Vb 1 \& \-F COMM=MyComment .Ve .PP Option \f(CW\*(C`\-F\*(C'\fR may be repeated to set more than one frame. If configuration variable \f(CW\*(C`empty\-F\-deletes\*(C'\fR is \s-1TRUE\s0 (default), empty arguments will delete the frame. .PP One can replace \f(CW\*(C`FRAME_spec=VALUE\*(C'\fR by \f(CW\*(C`FRAME_spec < FILE\*(C'\fR; in this case the value to set is read from the file named \fI\s-1FILE\s0\fR; if the frame is text-only (meaning: at most \f(CW\*(C`[encoded]Text URL Language Description\*(C'\fR fields are present), the file is read in text mode (and with starting/trailing whitespace stripped), otherwise it is read in binary mode. (Whitespace is required about the \f(CW\*(C`<\*(C'\fR signs.) If \&\f(CW\*(C`<\*(C'\fR is replaced by \f(CW\*(C`?<\*(C'\fR, the value is set only if frame is not yet present, and if the file exists; if replaced by \f(CW\*(C`>\*(C'\fR, the value (if present) is written to \fI\s-1FILE\s0\fR (creation of intermediate directories is controlled by configuration option \f(CW\*(C`frames_write_creates_dirs\*(C'\fR, the default is \s-1FALSE\s0). .PP Additionally, \f(CW\*(C`FRAME_spec\*(C'\fR may be one of \f(CW\*(C`ID3v1\*(C'\fR or \f(CW\*(C`ID3v2\*(C'\fR or \f(CW\*(C`TAGS\*(C'\fR; in this case, whole tags are written or read. For example, for \f(CW\*(C`TAGS < FILE\*(C'\fR, \f(CW\*(C`title artist album year genre comment track\*(C'\fR info is calculated from \&\fI\s-1FILE\s0\fR, which may be raw tags, as produced with \f(CW\*(C`>\*(C'\fR, or a valid \s-1MP3\s0 file; if Image::ExifTool is present, the data may be read from arbitrary multimedia file. (Likewise, for \f(CW\*(C`ID3v1 < FILE\*(C'\fR, the same info is extracted from \&\f(CW\*(C`ID3v1\*(C'\fR tag only.) After this, in case of \f(CW\*(C`ID3v2\*(C'\fR or \f(CW\*(C`TAGS\*(C'\fR, \f(CW\*(C`ID3v2\*(C'\fR frames are copied from the \f(CW\*(C`ID3v2\*(C'\fR tag one-by-one. (With suitable modifications for \f(CW\*(C`?<\*(C'\fR.) .PP By default, the \*(L"\s-1VALUE\s0\*(R" for \f(CW\*(C`\-F\*(C'\fR is \f(CW\*(C`%\*(C'\fR\-interpolated; this can be changed by option \f(CW\*(C`\-E\*(C'\fR. For user convenience, human-friendlier forms \&\f(CW\*(C`composer, text_by, orchestra, conductor, disk_n\*(C'\fR can be used instead of \&\f(CW\*(C`TCOM, TEXT, TPE2, TPE3, TPOS\*(C'\fR. .PP The option \f(CW\*(C`\-P RECIPE\*(C'\fR is a very powerful generalization of what can be done by options \f(CW\*(C`\-F\*(C'\fR, \f(CW\*(C`\-d\*(C'\fR, and \f(CW\*(C`\-t \-a \-l \-y \-g \-c \-n\*(C'\fR. It may be repeated; the values should contain the parse recipes. They become the configuration item \f(CW\*(C`parse_data\*(C'\fR of \f(CW\*(C`MP3::Tag\*(C'\fR; eventually this information is processed by MP3::Tag::ParseData module (if the latter is present in the chain of heuristics; see option \f(CW\*(C`\-C\*(C'\fR). The \&\f(CW\*(C`RECIPE\*(C'\fR is split into \f(CW\*(C`$flags, $string, @patterns\*(C'\fR on its first non-alphanumeric character; the first of \f(CW@patterns\fR which matches \&\f(CW$string\fR is going to be executed (for side effects). (See examples: \&\*(L"\s-1EXAMPLES:\s0 parse rules\*(R".) .PP If option \f(CW\*(C`\-G\*(C'\fR is specified, the file names on the command line are considered as glob patterns. This may be useful if the maximal command-line length is too low. With the option \f(CW\*(C`\-R\*(C'\fR arguments can be directories, which are searched recursively for audio (default \&\fI*.mp3\fR) files to process; use option \f(CW\*(C`\-r\*(C'\fR to reset the regular expression to look for (the default is \f(CW\*(C`(?i:\e.mp3$)\*(C'\fR). .PP The option \f(CW\*(C`\-E\*(C'\fR controls expansion of escape characters. It should contain the letters of the command-line options where \f(CW\*(C`\e\e, \en, \et\*(C'\fR are interpolated; one can append the letters of \f(CW\*(C`t a l y g c n F\*(C'\fR options requiring \f(CW\*(C`%\*(C'\fR\-interpolation after the separator \f(CW\*(C`/i:\*(C'\fR (for \&\f(CW\*(C`\-F\*(C'\fR, only the values are interpolated). The default value is \&\f(CW\*(C`p/i:Fp\*(C'\fR: only \f(CW\*(C`\-p\*(C'\fR is \f(CW\*(C`\e\*(C'\fR\-interpolated, and only \f(CW\*(C`\-F\*(C'\fR and \f(CW\*(C`\-p\*(C'\fR are subject to \f(CW\*(C`%\*(C'\fR\-interpolation. If all one wants is to \fIadd\fR to the defaults, preceed the value of \f(CW\*(C`\-E\*(C'\fR (containing added options) by \&\f(CW"+"\fR. (Some parts of the value of option \f(CW\*(C`\-P\*(C'\fR are interpolated, but this should be governed by flags, not \f(CW\*(C`\-E\*(C'\fR; do \fI\s-1NOT\s0\fR put \f(CW\*(C`P\*(C'\fR into the \f(CW\*(C`%\*(C'\fR\-interpolated part of \f(CW\*(C`\-E\*(C'\fR.) .PP If the option \f(CW\*(C`\-@\*(C'\fR is given, all characters \f(CW\*(C`@\*(C'\fR in the options are replaced by \f(CW\*(C`%\*(C'\fR. This may be convenient if the shell treats \f(CW\*(C`%\*(C'\fR specially (e.g., \s-1DOSISH\s0 shells). .PP If option \f(CW\*(C`\-I\*(C'\fR is given, no guessworking for \fIartist\fR field is performed on typeout. .PP The option \f(CW\*(C`\-C CONFIG_OPT=VALUE1,VALUE2...\*(C'\fR sets \f(CW\*(C`MP3::Tag\*(C'\fR configuration data the same way as \f(CW\*(C`MP3::Tag\-\*(C'\fR\fIconfig()\fR> would do (recall that the value is an array; separate elements by commas if more than one). The option may be repeated to set more than one value. Note that since \f(CW\*(C`ParseData\*(C'\fR is used to process \f(CW\*(C`\-P\*(C'\fR parse recipes, it should be better be kept in the \&\f(CW\*(C`autoinfo\*(C'\fR configuration (and related fields \f(CW\*(C`author\*(C'\fR etc) in presence of \f(CW\*(C`\-P\*(C'\fR. .PP If the option \f(CW\*(C`\-x\*(C'\fR is given, the technical information about the audio file is printed (\s-1MP3\s0 level, duration, number of frames, padding, copyright, and the list of ID3v2 frame names in format suitable to \f(CW\*(C`%{...}\*(C'\fR escapes). If \f(CW\*(C`\-x\*(C'\fR is repeated, content of frames is also printed out (may output non-printable chars, if it is repeated more than twice). .PP If option \f(CW\*(C`\-N\*(C'\fR is given, all the \*(L"smarts\*(R" are disabled \- no normalization of fields happens, and (by default) no attempt to deduce the values of fields from non\-ID3 information is done. This option is (currently) equivalent to having \f(CW\*(C`\-C autoinfo=ParseData,ID3v2,ID3v1\*(C'\fR as the first directive, to having no \fINormalize::Text::Music_Fields.pm\fR present on \f(CW@INC\fR path, and not calling \fIautofill()\fR method. .SH "Normalization of fields" .IX Header "Normalization of fields" (The loading of normalization module and all subsequent operations may be disabled by the option \f(CW\*(C`\-N\*(C'\fR, or by setting the environment variable \&\f(CW\*(C`MP3TAG_NORMALIZE_FIELDS\*(C'\fR to be \s-1FALSE\s0. If not prohibited, the module is attempted to be loaded if directory \fI~/.music_fields\fR is present, or \f(CW\*(C`MP3TAG_NORMALIZE_FIELDS\*(C'\fR is set and \s-1TRUE\s0.) .PP If loading of the module \f(CW\*(C`Normalize::Text::Music_Fields\*(C'\fR is successful, the following is applicable: .PP If the value of \f(CW\*(C`MP3TAG_NORMALIZE_FIELDS\*(C'\fR is defined and not 1, this value is broken into directories as a \s-1PATH\s0, and load path of \&\f(CW\*(C`Normalize::Text::Music_Fields\*(C'\fR is set to be this list of directories. Then MP3::Tag is instructed (via corresponding configuration settings) to use \f(CW\*(C`normalize_artist\*(C'\fR (etc.) methods defined by this module. These methods may normalize certain tag data. The current version defines methods for \&\*(L"normalization\*(R" of personal names, and titles (based on the composer). This normalization is driven through user-editable configuration tables. .PP In addition to automatical normalization of \s-1MP3\s0 tag data, one can use \&\*(L"fake \s-1MP3\s0 files\*(R" to manually access some features of this module. For this, use an empty file name, and \f(CW\*(C`\-D\*(C'\fR option. E.g, .PP .Vb 5 \& mp3info2 \-D \-a beethoven \-p "%a\en" "" \& mp3info2 \-D \-a beethoven \-p "%{shP[%a]}\en" "" \& mp3info2 \-D \-a beethoven \-t "sonata #28" \-p "%t\en" "" \& mp3info2 \-D \-a beethoven \-t "allegretto, Bes" \-@p "@t\en" "" \& mp3info2 \-D \-a beethoven \-t "op93" \-@p "@t\en" "" .Ve .PP will print the normalized person-name for \f(CW\*(C`beethoven\*(C'\fR, the corresponding normalized short person-name, and the normalized title for \f(CW\*(C`sonata #28\*(C'\fR of composer \f(CW\*(C`beethoven\*(C'\fR. E.g., with the shipped normalization tables, it will print .PP .Vb 5 \& Ludwig van Beethoven (1770\-1827) \& L. van Beethoven \& Piano Sonata No. 28 in A major; Op. 101 (1816) \& Allegretto for Piano Trio in B flat major; WoO 39 (1812) \& Symphony No. 8 in F major; Op. 93 (comp. 1812, f.p. Vienna, 1814\-02\-27, cond. Beethoven; pubd. 1816) .Ve .SH "The order of operation" .IX Header "The order of operation" Currently, the operations are done in the following order .IP "\(bu" 2 Deletion of ID3v1 or ID3v2 as a whole via \f(CW\*(C`\-d\*(C'\fR option; .IP "\(bu" 2 Recipies of \f(CW\*(C`\-P\*(C'\fR option are set up (to be triggered by interpolation); .IP "\(bu" 2 The setting done via \f(CW\*(C`\-a/\-t/\-l/\-y/\-g/\-c/\-n\*(C'\fR options; .IP "\(bu" 2 The settings done via \f(CW\*(C`\-F\*(C'\fR option; .IP "\(bu" 2 Deletion of individual frames via \f(CW\*(C`\-d\*(C'\fR option; .IP "\(bu" 2 autofill of ID3v2 (id) frames; .IP "\(bu" 2 Emit info based on \f(CW\*(C`\-p\*(C'\fR and \f(CW\*(C`\-x\*(C'\fR options; .IP "\(bu" 2 Trigger recipies of \f(CW\*(C`\-P\*(C'\fR (if not triggered by interpolation); .IP "\(bu" 2 Update tags if needed. .SH "Usage strategy: escalation of complexity" .IX Header "Usage strategy: escalation of complexity" The purpose of this script is to to make handling of \s-1ID3\s0 tags as simple \&\fIas possible\fR. .PP On one end of the scale, one can perform arbitrarily complex manipulations with tags using \f(CW\*(C`MP3::Tag\*(C'\fR Perl module. .PP On the other end, it is much more convenient to handle simplest manipulations with tags using this script's options \f(CW\*(C`\-t \-a \-l \-y \-g \-c \-n\*(C'\fR and \f(CW\*(C`\-p \&\-F \-d\*(C'\fR. For slightly more complicated tasks, one may need to use the more elaborate method of \fIparse rules\fR, provided to this script by the option \f(CW\*(C`\-P\*(C'\fR; the rules depend heavily on \fIinterpolation\fR, see \&\*(L"interpolate\*(R" in MP3::Tag, \*(L"interpolate_with_flags\*(R" in MP3::Tag. .PP To simplify upgrade from \*(L"simplest manipulations\*(R" to \*(L"more elaborate ones\*(R", here we provide \*(L"parse rule\*(R" \fIsynonyms\fR to the simplest options. So if you start with \f(CW\*(C`\-t \-a \-l \-y \-g \-c \-n\*(C'\fR and \f(CW\*(C`\-p \-F \-d\*(C'\fR options which \*(L"almost work\*(R" for you, you have a good chance to be able to fully achieve your aim by modifying the synonyms described below. .PP (Below we assume that \f(CW\*(C`\-E\*(C'\fR option is set to its default value, so \&\f(CW\*(C`\-F \-p\*(C'\fR are \f(CW\*(C`%\*(C'\fR\-interpolated, other options are not. Note also that if your \s-1TTY\s0's encoding is recognized by Perl, it is highly recommended to set \f(CW\*(C`\-e 3\*(C'\fR option; on \s-1DOSISH\s0 shells, better use \f(CW\*(C`\-@\*(C'\fR, and replace \&\f(CW\*(C`%\*(C'\fR's by \f(CW\*(C`@\*(C'\fR's below.) .ie n .IP """\-t VALUE""" 14 .el .IP "\f(CW\-t VALUE\fR" 14 .IX Item "-t VALUE" .Vb 1 \& \-P "mz/VALUE/%t" .Ve .ie n .IP """\-a \-l \-y \-g \-c \-n""" 14 .el .IP "\f(CW\-a \-l \-y \-g \-c \-n\fR" 14 .IX Item "-a -l -y -g -c -n" Likewise. .ie n .IP """\-F"" ""TIT2=VALUE""" 14 .el .IP "\f(CW\-F\fR ``TIT2=VALUE''" 14 .IX Item "-F TIT2=VALUE" .Vb 1 \& \-P "mzi/VALUE/%{TIT2}" .Ve .ie n .IP """\-F"" ""APIC[myDescr] < \s-1FILE\s0""" 14 .el .IP "\f(CW\-F\fR ``APIC[myDescr] < \s-1FILE\s0''" 14 .IX Item "-F APIC[myDescr] < FILE" .Vb 1 \& \-F "APIC[myDescr]=%{I(fimbB)FILE}" .Ve .Sp or .Sp .Vb 1 \& \-P "mzi/%{I(fimbB)FILE}/%{APIC[myDescr]}" .Ve .Sp (remove \f(CW\*(C`bB\*(C'\fR for text-only frames). .ie n .IP """\-F"" ""APIC[myDescr] > \s-1FILE\s0""" 14 .el .IP "\f(CW\-F\fR ``APIC[myDescr] > \s-1FILE\s0''" 14 .IX Item "-F APIC[myDescr] > FILE" .Vb 1 \& \-P "bOi,%{APIC[myDescr]},FILE" .Ve .Sp (remove \f(CW\*(C`b\*(C'\fR for text-only frames); or use \f(CW\*(C`\-e binary \-p "%{APIC[myDescr]}"\*(C'\fR with redirection, see \*(L"\s-1EXAMPLES:\s0 parse rules\*(R". .ie n .IP """\-d"" \s-1TIT2\s0" 14 .el .IP "\f(CW\-d\fR \s-1TIT2\s0" 14 .IX Item "-d TIT2" .Vb 1 \& \-P "m//%{TIT2}" .Ve .ie n .IP """\-F"" ""\s-1TIT2\s0 ?< \s-1FILE\s0""" 14 .el .IP "\f(CW\-F\fR ``\s-1TIT2\s0 ?< \s-1FILE\s0''" 14 .IX Item "-F TIT2 ?< FILE" Very tricky. This won't set distinguish empty file and non-existing one: .Sp .Vb 1 \& \-P "mzi/%{TIT2:1}0%{I(fFim)FILE}/10/10%{TIT2}/0%{U1}" .Ve .Sp (add \f(CW\*(C`bB\*(C'\fR to \f(CW\*(C`fFim\*(C'\fR for non-text-only frames); the last part may be omitted if one omits the flag \f(CW\*(C`m\*(C'\fR \- it is present to catch misprints only. .PP For details on \*(L"parse rules\*(R", see \*(L"\s-1EXAMPLES:\s0 parse rules\*(R" and \&\*(L"\s-1DESCRIPTION\s0\*(R" in MP3::Tag::ParseData. .SH "EXAMPLES: parse rules" .IX Header "EXAMPLES: parse rules" Only the \f(CW\*(C`\-P\*(C'\fR option is complicated enough to deserve comments... For full details on \fIparse rules\fR, see \&\*(L"\s-1DESCRIPTION\s0\*(R" in MP3::Tag::ParseData; for full details on interpolation, see \*(L"interpolate\*(R" in MP3::Tag, \*(L"interpolate_with_flags\*(R" in MP3::Tag. .PP For a (silly) example, one can replace \f(CW\*(C`\-a Homer \-t Iliad\*(C'\fR by .PP .Vb 1 \& \-P mz=Homer=%a \-P mz=Iliad=%t .Ve .PP A less silly example is forcing a particular way of parsing a file name via .PP .Vb 1 \& \-P "im=%{d0}/%f=%a/%n %t.%e" .Ve .PP It is broken into .PP .Vb 2 \& flags string pattern1 \& "im" "%{d0}/%f" "%a/%n %t.%e" .Ve .PP The flag letters stand for \fIinterpolate\fR, \fImust_match\fR. This interpolates the string \f(CW"%{d0}/%f"\fR and parses the result (which is the file name with one level of the directory part preserved) using the given pattern; thus the directory name becomes the artist, the leading numeric part \- the track number, and the rest of the file name (without extension) \- the title. Note that since multiple patterns are allowed, one can similarly allow for multiple formats of the names, e.g. .PP .Vb 1 \& \-P "im=%{d0}/%f=%a/%n %t.%e=%a/%t (%y).%e" .Ve .PP allows for the file basename to be also of the form \*(L"\s-1TITLE\s0 (\s-1YEAR\s0)\*(R". An alternative way to obtain the same results is .PP .Vb 1 \& \-P "im=%{d0}=%a" \-P "im=%f=%n %t.%e=%t (%y).%e" .Ve .PP which corresponds to two recipies: .PP .Vb 3 \& flags string pattern1 pattern2 \& "im" "%{d0}" "%a" \& "im" "%f" "%n %t.%e" "%t (%y).%e" .Ve .PP Of course, one could use .PP .Vb 1 \& "im" "%B" "%n %t" "%t (%y)" .Ve .PP as a replacement for the second one. .PP Note that it may be more readable to set \fIartist\fR to \f(CW\*(C`%{d0}\*(C'\fR by an explicit asignment, with arguments similar to .PP .Vb 1 \& \-E "p/i:Fpa" \-a "%{d0}" .Ve .PP (this value of \f(CW\*(C`\-E\*(C'\fR requests \f(CW\*(C`%\*(C'\fR\-interpolation of the option \f(CW\*(C`\-a\*(C'\fR in addition to the default \f(CW\*(C`\e\*(C'\fR\-interpolation of \f(CW\*(C`\-p\*(C'\fR, and \&\f(CW\*(C`%\*(C'\fR\-interpolation of \f(CW\*(C`\-F\*(C'\fR and \f(CW\*(C`\-p\*(C'\fR; one can shortcut it with \f(CW\*(C`\-E +/i:a\*(C'\fR). .PP To give more examples, .PP .Vb 1 \& \-P "if=%D/.comment=%c" .Ve .PP will read comment from the file \fI.comment\fR in the directory of the audio file; .PP .Vb 1 \& \-P "ifn=%D/.comment=%c" .Ve .PP has similar effect if the file \fI.comment\fR has one-line comments, one per track (this assumes the the track number can be found by other means). .PP Suppose that a file \fIParts\fR in a directory of \s-1MP3\s0 files has the following format: it has a preamble, then has a short paragraph of information per audio file, preceded by the track number and dot: .PP .Vb 1 \& ... \& \& 12. Rezitativ. \& (Pizarro, Rocco) \& \& 13. Duett: jetzt, Alter, jetzt hat es Eile, (Pizarro, Rocco) \& \& ... .Ve .PP The following command puts this info into the title of the \s-1ID3\s0 tag (provided the audio file names are informative enough so that MP3::Tag can deduce the track number): .PP .Vb 1 \& mp3info2 \-u \-C parse_split=\*(Aq\en(?=\ed+\e.)\*(Aq \-P \*(Aqfl;Parts;%=n. %t\*(Aq .Ve .PP If this paragraph of information has the form \f(CW\*(C`TITLE (COMMENT)\*(C'\fR with the \&\f(CW\*(C`COMMENT\*(C'\fR part being optional, then use .PP .Vb 1 \& mp3info2 \-u \-C parse_split=\*(Aq\en(?=\ed+\e.)\*(Aq \-P \*(Aqfl;Parts;%=n. %t (%c);%=n. %t\*(Aq .Ve .PP If you want to remove a dot or a comma got into the end of the title, use .PP .Vb 2 \& mp3info2 \-u \-C parse_split=\*(Aq\en(?=\ed+\e.)\*(Aq \e \& \-P \*(Aqfl;Parts;%=n. %t (%c);%=n. %t\*(Aq \-P \*(AqiR;%t;%t[.,]$\*(Aq .Ve .PP The second pattern of this invocation is converted to .PP .Vb 1 \& [\*(AqiR\*(Aq, \*(Aq%t\*(Aq => \*(Aq%t[.,]$\*(Aq] .Ve .PP which essentially applies the substitution \f(CW\*(C`s/(.*)[.,]$/$1/s\*(C'\fR to the title. .PP Now suppose that in addition to \fIParts\fR, we have a text file \fIComment\fR with additional info; we want to put this info into the comment field \fIafter\fR what is extracted from \f(CW\*(C`TITLE (COMMENT)\*(C'\fR; separate these two parts of the comment by an empty line: .PP .Vb 3 \& mp3info2 \-E C \-C \*(Aqparse_split=\en(?=\ed+\e.)\*(Aq \-C \*(Aqparse_join=\en\en\*(Aq \e \& \-P \*(Aqf;Comment;%c\*(Aq \-P \*(Aqfl;Parts;%=n. %t\*(Aq \e \& \-P \*(Aqi;%t///%c;%t (%c)///%c\*(Aq \-P \*(AqiR;%t;%t[.,]$\*(Aq .Ve .PP This assumes that the title and the comment do not contain \f(CW\*(Aq///\*(Aq\fR as a substring. Explanation: the first pattern of \f(CW\*(C`\-P\*(C'\fR, .PP .Vb 1 \& [\*(Aqf\*(Aq, \*(AqComment\*(Aq => \*(Aq%c\*(Aq], .Ve .PP reads comment from the file \f(CW\*(C`Comment\*(C'\fR into the comment field; the second, .PP .Vb 1 \& [\*(Aqfl\*(Aq, \*(AqParts\*(Aq => \*(Aq%=n. %t\*(Aq], .Ve .PP reads a chunk of \f(CW\*(C`Parts\*(C'\fR into the title field. The third one .PP .Vb 1 \& [\*(Aqi\*(Aq, \*(Aq%t///%c\*(Aq => \*(Aq%t (%c)///%c\*(Aq] .Ve .PP rearranges the title and comment \fIprovided\fR the title is of the form \f(CW\*(C`TITLE (COMMENT)\*(C'\fR. (The configuration option \f(CW\*(C`parse_join\*(C'\fR takes care of separating two chunks of comment corresponding to two occurences of \f(CW%c\fR on the right hand side.) .PP Finally, the fourth pattern is the same as in the preceding example; it removes spurious punctuation at the end of the title. .PP More examples: removing string \*(L"with violin\*(R" from the start of the comment field (removing comment altogether if nothing remains): .PP .Vb 1 \& mp3info2 \-u \-P \*(Aqiz;%c;with violin%c\*(Aq *.mp3 .Ve .PP setting the artist field without letting auto-update feature deduce other fields from other sources; .PP .Vb 1 \& mp3info2 \-C autoinfo=ParseData \-a "A. U. Thor" *.mp3 .Ve .PP setting a comment field unless it it already present: .PP .Vb 1 \& mp3info2 \-u \-P \*(Aqi;%c///with piano;///%c\*(Aq *.mp3 .Ve .PP The last example shows how to actually write \*(L"programs\*(R" in the language of the \f(CW\*(C`\-P\*(C'\fR option: the example gives a conditional assignment. With user variables (as in \f(CW\*(C`%{U8}\*(C'\fR) for temporaries, and a possibility to use regular expressions, one could provide arbitrary programmatic logic. Of course, at some level of complexity one should better switch to direct interfacing with \&\f(CW\*(C`MP3::Tag\*(C'\fR Perl module (use the code of this Perl script as an example!). .PP Here is a typical task setting \*(L"advanced\*(R" id3v2 frames: composer (\f(CW\*(C`TCOM\*(C'\fR), orchestra (\f(CW\*(C`TPE2\*(C'\fR), conductor (\f(CW\*(C`TPE3\*(C'\fR). We assume a directory tree which contains \s-1MP3\s0 files tagged with the following conventions: \f(CW\*(C`artist\*(C'\fR is actually a composer; \f(CW\*(C`comment\*(C'\fR is of one of two forms: .PP .Vb 2 \& Performers; Orchestra; Conductor \& Orchestra; Conductor .Ve .PP To set the specific \s-1MP3\s0 frames via \f(CW\*(C`\-P\*(C'\fR rules, use .PP .Vb 2 \& mp3info2 \-@P "mi/@a/@{TCOM}" \e \& \-P "mi/@c/@{U1}; @{TPE2}; @{TPE3}/@{TPE2}; @{TPE3}" \-R . .Ve .PP With \f(CW\*(C`\-F\*(C'\fR options, this can be simplified as .PP .Vb 1 \& mp3info2 \-@F "TCOM=@a" \-P "mi/@c/@{U1}; @{TPE2}; @{TPE3}/@{TPE2}; @{TPE3}" \-R . .Ve .PP or .PP .Vb 1 \& mp3info2 \-@F "composer=@a" \-P "mi/@c/@{U1}; @{TPE2}; @{TPE3}/@{TPE2}; @{TPE3}" \-R . .Ve .PP To copy \s-1ID3\s0 tags of \s-1MP3\s0 files in the current directory to files in directory \&\fI/tmp/mp3\fR with the extension \fI.tag\fR (and print \*(L"progress report\*(R"), use .PP .Vb 1 \& mp3info2 \-p "@N@E\en" \-@P "bODi,@{ID3v2}@{ID3v1},/tmp/mp3/@N.tag" \-DNR . .Ve .PP Since we did not use \f(CW\*(C`z\*(C'\fR flag, \s-1MP3\s0 files without tags are skipped. .PP Now suppose that there are two parallel file hierarchies of audio files, and of lyrics: audio files are in \fIaudio/dir_name/audio_name.mp3\fR with corresponding lyrics file in \fItext/dir_name/audio_name.mp3\fR. To attach lyrics to \s-1MP3\s0 files (in \f(CW\*(C`COMM\*(C'\fR frame with description \f(CW\*(C`lyrics\*(C'\fR in language \&\f(CW\*(C`eng\*(C'\fR \- \fIthis is a non-standard location, see below!\fR), call .PP .Vb 1 \& mp3info2 \-@P "fim;../text/@{d0}/@B.txt;@{COMM(eng)[lyrics]}" \-Ru . .Ve .PP inside the directory \fIaudio\fR. (Change \f(CW\*(C`fim\*(C'\fR to \f(CW\*(C`Ffim\*(C'\fR to ignore the audio files for which the corresponding text file does not exist.) (Of course, to follow the specifications, one should have used the field \f(CW"%{USLT(eng)[]}"\fR instead of \f(CW"%{COMM(eng)[lyrics]}"\fR; see below for variations). .PP Finish by a very simple example: all what the pattern .PP .Vb 1 \& \-P \*(Aqi;%t;%t\*(Aq .Ve .PP does is removal of trailing and leading blanks from the title (which is deduced by other means). .SH "More examples" .IX Header "More examples" With \f(CW\*(C`\-F\*(C'\fR option, one could set the \f(CW\*(C`USLT\*(C'\fR frame as .PP .Vb 1 \& mp3info2 \-@F "USLT(eng)[] < ../text/@{d0}/@B.txt" \-Ru . .Ve .PP Print out such a frame (in any language) with .PP .Vb 1 \& mp3info2 \-@p "@{USLT[]}\en" file.mp3 .Ve .PP Similarly, to print out the \s-1APIC\s0 frame with empty description, use .PP .Vb 1 \& mp3info2 \-e binary \-@p "@{APIC[]}" file.mp3 > output_picture_file .Ve .PP or (with description \*(L"cover\*(R") .PP .Vb 1 \& mp3info2 \-@P "bOi,@{APIC[cover]},output_picture_file.jpg" audio_07.mp3 .Ve .PP To set such a frame from file \fIxxx.gif\fR (with the default \f(CW\*(C`Picture Type\*(C'\fR, \&\f(CW"Cover (front)"\fR, and empty description), do one of .PP .Vb 2 \& mp3info2 \-F "APIC < xxx.gif" file.mp3 \& mp3info2 \-@F "APIC[]=@{I(fimbB)xxx.gif}" file.mp3 .Ve .PP The difference of \f(CW\*(C`APIC\*(C'\fR and \f(CW\*(C`APIC[]\*(C'\fR is that the first removes all \&\f(CW\*(C`APIC\*(C'\fR frames first, and the second removes only all \f(CW\*(C`APIC\*(C'\fR frames with empty description \- but arbitrary image type. So it may be more suitable to use the full specification, as in \f(CW\*(C`APIC(Cover (front))[]\*(C'\fR. .PP To remove \f(CW\*(C`APIC\*(C'\fR frames with empty descriptions, arbitrary \f(CW\*(C`Picture Type\*(C'\fRs (and \f(CW\*(C`MIME type\*(C'\fRs which may be correctly calculated by \fImp3info2\fR, e.g., \&\f(CW\*(C`TIFF/JPEG/GIF/PNG\*(C'\fR), use .PP .Vb 1 \& mp3info2 \-d "APIC[]" file.mp3 .Ve .PP (note that this wouldn't free disk space, unless \*(L"shrink\*(R" is forced by configuration variables). To do the same with the \*(L"Conductor\*(R" picture type only, do .PP .Vb 1 \& mp3info2 \-d "APIC(Conductor)[]" file.mp3 .Ve .PP To scan through subdirectories, and add file \fIcover.jpg\fR from the directory of the file as a \*(L"default\*(R" \f(CW\*(C`APIC\*(C'\fR frame, but only if there is no \f(CW\*(C`APIC\*(C'\fR frame, and a file exists, do .PP .Vb 1 \& mp3info2 \-@F "APIC ?< @D/cover.jpg" \-R . .Ve .PP This deletes empty frames for date, \f(CW\*(C`TCOP, TENC, WXXX[], COMM(eng)[]\*(C'\fR, and removes the leading 0 from track number from \s-1MP3\s0 file in current directory: .PP .Vb 3 \& mp3info2 \-@ \-E +/i:y \-F "TCOP=@{TCOP}" \-F "TENC=@{TENC}" \& \-F "WXXX[]=@{WXXX[]}" \-F "COMM(eng)[]=@{COMM(eng)[]}" \& \-y "@y" \-P "mi/@n/0@n/@n" *.mp3 .Ve .SH "Examples on dealing with broken encodings" .IX Header "Examples on dealing with broken encodings" One of principal weaknesses of \s-1ID3\s0 specification was that it required that data is provided in \f(CW\*(C`latin\-1\*(C'\fR encoding. Since most languages in the world are not expressible in \f(CW\*(C`latin\-1\*(C'\fR, this lead to (majority?) of \s-1ID3\s0 tags being not standard-conforming. Newer versions of the specs fixed this shortcoming, but the damage was already done. Fortunately, this script can use abilities of \f(CW\*(C`MP3::Tag\*(C'\fR to convert from non-conforming content to a conforming one. .PP The following example converts ID3v2 tags which were written in (non-standard-conforming) encoding \f(CW\*(C`cp1251\*(C'\fR to be in standard-conforming encoding. For the purpose of this example, assume that ID3v1 tags are in the same encoding (and that one wants to leave them in the encoding \f(CW\*(C`cp1251\*(C'\fR); the files to process are found in the current directory and (recursively) in its subdirectories (\f(CW\*(C`set\*(C'\fR syntax for \s-1DOSISH\s0 shells): .PP .Vb 3 \& set MP3TAG_DECODE_V1_DEFAULT=cp1251 \& set MP3TAG_DECODE_V2_DEFAULT=cp1251 \& mp3info2 \-C id3v2_fix_encoding_on_write=1 \-u2R . .Ve .PP For more information, see \*(L"\s-1ENVIRONMENT\s0\*(R" in MP3::Tag, \*(L"config\*(R" in MP3::Tag, and \*(L"\s-1CUSTOMIZATION\s0\*(R" in MP3::Tag. .SH "INCOMPATIBILITIES with \fImp3info\fP" .IX Header "INCOMPATIBILITIES with mp3info" This tool is loosely modeled on the program \fImp3info\fR; it is \*(L"mostly\*(R" backward compatible (especially when in \*(L"naive\*(R" mode via \f(CW\*(C`\-N\*(C'\fR), and allows a very significant superset of functionality. Known backward incompatibilities are: .PP .Vb 1 \& \-G \-h \-r \-d \-x .Ve .PP Missing functionality: .PP .Vb 1 \& \-f \-F \-i .Ve .PP Incompatible \f(CW\*(C`%\*(C'\fR\-\fIescapes\fR: .PP .Vb 5 \& %e %E \- absolutely different semantic \& %v \- has no trailing 0s \& %q \- has fractional part \& %r \- is a number, not a word "Variable" for VBR \& %u \- is one less (in presence of descriptor frame only?) .Ve .PP Missing \f(CW\*(C`%\*(C'\fR\-\fIescapes\fR: .PP .Vb 1 \& %b %G .Ve .PP Backslash escapes: only \f(CW\*(C`\e\e\*(C'\fR, \f(CW\*(C`\en\*(C'\fR, \f(CW\*(C`\et\*(C'\fR supported. .PP \&\f(CW\*(C`\-x\*(C'\fR prints data in a different format, not all fields are present, and ID3v2 tag names are output. .SH "ENVIRONMENT" .IX Header "ENVIRONMENT" With \f(CW\*(C`\-e\*(C'\fR 1, 2 or 3, this script may consult environment variables \&\f(CW\*(C`LC_CTYPE, LC_ALL, LANG\*(C'\fR to deduce the current encoding. No other environment variables are directly read by this script. .PP Note however, that MP3::Tag module has a rich set of defaults for encoding settings settable by environment variables; see \&\*(L"\s-1ENVIRONMENT\s0\*(R" in MP3::Tag. So these variables affect (indirectly) how this script works. .SH "OBSOLETE INTERFACE" .IX Header "OBSOLETE INTERFACE" If you do not understand what it is about, it is safe to ignore this announcement: .PP The old, pre\-version=\f(CW1.05\fR way (by triplication of a separator, without repetition of options) to provide multiple commands to \f(CW\*(C`\-F\*(C'\fR and <\-P> options is still supported, but is strongly discouraged. (It does not conflict with the current interface.) .SH "AUTHOR" .IX Header "AUTHOR" Ilya Zakharevich . .SH "Utilities to create CDDB file" .IX Header "Utilities to create CDDB file" Good \s-1CD\s0 reapers (e.g., \fIcdda2wav\fR with option \f(CW\*(C`cddb=0\*(C'\fR) create a \&\s-1CDDB\s0 file with fetched information \- as far as an Internet connection is present. However, if not available, other options exist. .PP The scripts (supplied with the distribution in \&\fI./examples\fR) can create a \*(L"stub\*(R" \s-1CDDB\s0 file basing on: .IP "\fIfulltoc2fake_cddb.pl\fR" 23 .IX Item "fulltoc2fake_cddb.pl" a dump of a full \s-1TOC\s0 of a \s-1CD\s0; create one, e.g., by .Sp .Vb 1 \& readcd \-fulltoc dev=0,1,0 \-f=audiocd .Ve .IP "\fIinf2fake_cddb.pl\fR" 23 .IX Item "inf2fake_cddb.pl" directory of \fI*.inf\fR files (e.g., created by \fIcdda2wav\fR without Internet connection); .IP "\fIdir_mp3_2fake_cddb.pl\fR" 23 .IX Item "dir_mp3_2fake_cddb.pl" a directory of \s-1MP3\s0 files ripped from a \s-1CD\s0 (via some guesswork). .PP Passing this stub to the script \fIcddb2cddb.pl\fR, it can be transformed to a \*(L"filled\*(R" \s-1CDDB\s0 file via a connection to some online database. Use \&\f(CW\*(C`\-r\*(C'\fR option if multiple records in the database match the \s-1CD\s0 signature. .PP .Vb 3 \& fulltoc2fake_cddb audiocd.toc | cddb2cddb > audio.cddb \& inf_2fake_cddb | cddb2cddb > audio.cddb \& dir_mp3_2fake_cddb | cddb2cddb \-r3 > audio.cddb # 3rd record .Ve .PP When such a \s-1CDDB\s0 file is present, it will be used by MP3::Tag module to deduce the information about an audio file. This information is (by default, transparently) used by this script. .SH "SEE ALSO" .IX Header "SEE ALSO" MP3::Tag, MP3::Tag::ParseData, audio_rename, typeset_audio_dir