| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package MP3::TAG::ID3v1; |
|
2
|
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
# reads ID3v1 and ID3v1.1 mp3-tags |
|
4
|
|
|
|
|
|
|
# writes ID3v1.1 mp3-tags |
|
5
|
|
|
|
|
|
|
|
|
6
|
1
|
|
|
1
|
|
3
|
use strict; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
28
|
|
|
7
|
1
|
|
|
1
|
|
6
|
use vars qw /@mp3_genres @winamp_genres $AUTOLOAD %ok_length/; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
1273
|
|
|
8
|
|
|
|
|
|
|
# allowed fields in ID3v1.1 and max length of this fields (expect for track and genre which are coded later) |
|
9
|
|
|
|
|
|
|
%ok_length = (song => 30, artist => 30, album => 30, comment => 28, track => 3, genre => 30, year=>4, genreID=>1); |
|
10
|
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
=pod |
|
12
|
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
=head1 NAME |
|
14
|
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
MP3::TAG::ID3v1 - Perl extension for reading / writing ID3v1 tags of mp3-files |
|
16
|
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
=head1 SYNOPSIS |
|
18
|
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
MP3::TAG::ID3v2 is designed to be called from the MP3::Tag module. |
|
20
|
|
|
|
|
|
|
It then returns a ID3v2-tag-object, which can be used in a users |
|
21
|
|
|
|
|
|
|
program. |
|
22
|
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
use MP3::TAG::ID3v1; |
|
24
|
|
|
|
|
|
|
$id3v1 = MP3::TAG::ID3v1->new($mp3obj); |
|
25
|
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
C<$mp3obj> is a object from MP3::Tag. See according documentation. |
|
27
|
|
|
|
|
|
|
C<$tag> is undef when no tag is found in the C<$mp3obj>. |
|
28
|
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
* Reading the tag |
|
30
|
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
print " Song: " .$id3v1->song . "\n"; |
|
32
|
|
|
|
|
|
|
print " Artist: " .$id3v1->artist . "\n"; |
|
33
|
|
|
|
|
|
|
print " Album: " .$id3v1->album . "\n"; |
|
34
|
|
|
|
|
|
|
print "Comment: " .$id3v1->comment . "\n"; |
|
35
|
|
|
|
|
|
|
print " Year: " .$id3v1->year . "\n"; |
|
36
|
|
|
|
|
|
|
print " Genre: " .$id3v1->genre . "\n"; |
|
37
|
|
|
|
|
|
|
print " Track: " .$id3v1->track . "\n"; |
|
38
|
|
|
|
|
|
|
@tagdata = $mp3->all(); |
|
39
|
|
|
|
|
|
|
foreach (@tagdata) { |
|
40
|
|
|
|
|
|
|
print $_; |
|
41
|
|
|
|
|
|
|
} |
|
42
|
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
* Changing / Writing the tag |
|
44
|
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
$id3v1->comment("This is only a Test Tag"); |
|
46
|
|
|
|
|
|
|
$id3v1->song("testing"); |
|
47
|
|
|
|
|
|
|
$id3v1->artist("Artest"); |
|
48
|
|
|
|
|
|
|
$id3v1->album("Test it"); |
|
49
|
|
|
|
|
|
|
$id3v1->year("1965"); |
|
50
|
|
|
|
|
|
|
$id3v1->track("5"); |
|
51
|
|
|
|
|
|
|
$id3v1->genre("Blues"); |
|
52
|
|
|
|
|
|
|
# or at once |
|
53
|
|
|
|
|
|
|
$id3v1->all("song title","artist","album","1900","comment",10,"Ska");# |
|
54
|
|
|
|
|
|
|
$id3v1->writeTag; |
|
55
|
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
=head1 AUTHOR |
|
57
|
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
Thomas Geffert, thg@users.sourceforge.net |
|
59
|
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
=head1 DESCRIPTION |
|
61
|
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
=item new() |
|
63
|
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
$id3v1 = MP3::TAG::ID3v1->new($mp3obj[, $create]); |
|
65
|
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
Generally called from MP3::TAG, because a $mp3obj is needed. |
|
67
|
|
|
|
|
|
|
If $create is true, a new tag is created. Otherwise undef is |
|
68
|
|
|
|
|
|
|
returned, if now ID3v1 tag is found in the $mp3obj. |
|
69
|
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
=cut |
|
71
|
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
# create a ID3v1 object |
|
73
|
|
|
|
|
|
|
sub new { |
|
74
|
2
|
|
|
2
|
1
|
4
|
my ($class, $mp3obj, $create) = @_; |
|
75
|
2
|
|
|
|
|
4
|
my $self={mp3=>$mp3obj}; |
|
76
|
2
|
|
|
|
|
2
|
my $buffer; |
|
77
|
|
|
|
|
|
|
|
|
78
|
2
|
50
|
33
|
|
|
6
|
if (defined $create && $create) { |
|
79
|
0
|
|
|
|
|
0
|
$self->{new} = 1; |
|
80
|
|
|
|
|
|
|
} else { |
|
81
|
2
|
|
|
|
|
6
|
$mp3obj->seek(-128,2); |
|
82
|
2
|
|
|
|
|
6
|
$mp3obj->read(\$buffer, 128); |
|
83
|
|
|
|
|
|
|
} |
|
84
|
|
|
|
|
|
|
|
|
85
|
2
|
50
|
33
|
|
|
11
|
if ($create || substr ($buffer,0,3) eq "TAG") { |
|
86
|
2
|
|
|
|
|
5
|
bless $self, $class; |
|
87
|
2
|
|
|
|
|
4
|
$self->readTag($buffer); |
|
88
|
|
|
|
|
|
|
|
|
89
|
2
|
|
|
|
|
7
|
return $self; |
|
90
|
|
|
|
|
|
|
} else { |
|
91
|
0
|
|
|
|
|
0
|
return undef; |
|
92
|
|
|
|
|
|
|
} |
|
93
|
|
|
|
|
|
|
} |
|
94
|
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
=pod |
|
96
|
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
=item song(), artist(), album(), year(), comment(), track(), genre() |
|
98
|
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
$artist = $id3v1->artist; |
|
100
|
|
|
|
|
|
|
$artist = $id3v1->artist($artist); |
|
101
|
|
|
|
|
|
|
$album = $id3v1->album; |
|
102
|
|
|
|
|
|
|
$album = $id3v1->album($album); |
|
103
|
|
|
|
|
|
|
$year = $id3v1->year; |
|
104
|
|
|
|
|
|
|
$year = $id3v1->year($year); |
|
105
|
|
|
|
|
|
|
$comment = $id3v1->comment; |
|
106
|
|
|
|
|
|
|
$comment = $id3v1->comment($comment); |
|
107
|
|
|
|
|
|
|
$track = $id3v1->track; |
|
108
|
|
|
|
|
|
|
$track = $id3v1->track($track); |
|
109
|
|
|
|
|
|
|
$genre = $id3v1->genre; |
|
110
|
|
|
|
|
|
|
$genre = $id3v1->genre($genre); |
|
111
|
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
Use these functions to retrieve the date of these fields, |
|
113
|
|
|
|
|
|
|
or to set the data. |
|
114
|
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
$genre can be a string with the name of the genre, or a number |
|
116
|
|
|
|
|
|
|
describing the genre. |
|
117
|
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
=cut |
|
119
|
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
sub AUTOLOAD { |
|
121
|
6
|
|
|
6
|
|
81
|
my $self = shift; |
|
122
|
6
|
|
|
|
|
8
|
my $attr = $AUTOLOAD; |
|
123
|
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
# is it an allowed field |
|
125
|
6
|
|
|
|
|
23
|
$attr =~ s/.*:://; |
|
126
|
6
|
50
|
|
|
|
17
|
return unless $attr =~ /[^A-Z]/; |
|
127
|
6
|
50
|
|
|
|
15
|
warn "invalid field: ->$attr()" unless $ok_length{$attr}; |
|
128
|
|
|
|
|
|
|
|
|
129
|
6
|
100
|
|
|
|
21
|
if (my $new = shift) { |
|
130
|
2
|
|
|
|
|
8
|
$new =~ s/ *$//; |
|
131
|
2
|
|
|
|
|
4
|
$new = substr $new, 0, $ok_length{$attr}; |
|
132
|
2
|
50
|
|
|
|
5
|
if ($attr eq "genre") { |
|
133
|
0
|
0
|
|
|
|
0
|
if ($new =~ /^\d+$/) { |
|
134
|
0
|
|
|
|
|
0
|
$self->{genreID} = $new; |
|
135
|
|
|
|
|
|
|
} else { |
|
136
|
0
|
|
|
|
|
0
|
$self->{genreID} = genre2id($new); |
|
137
|
|
|
|
|
|
|
} |
|
138
|
0
|
|
|
|
|
0
|
$new = id2genre($self->{genreID}); |
|
139
|
|
|
|
|
|
|
} |
|
140
|
2
|
|
|
|
|
3
|
$self->{$attr}=$new; |
|
141
|
2
|
|
|
|
|
4
|
$self->{changed} = 1; |
|
142
|
|
|
|
|
|
|
} |
|
143
|
6
|
|
|
|
|
20
|
return $self->{$attr}; |
|
144
|
|
|
|
|
|
|
} |
|
145
|
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
=pod |
|
147
|
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
=item all() |
|
149
|
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
@tagdata = $id3v1->all; |
|
151
|
|
|
|
|
|
|
@tagdata = $id3v1->all($song, $artist, $album, $year, $comment, $track, $genre); |
|
152
|
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
Returns all information of the tag in a list. |
|
154
|
|
|
|
|
|
|
You can use this sub also to set the data of the complete tag. |
|
155
|
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
The order of the data is always song, artist, album, year, comment, track, and genre. |
|
157
|
|
|
|
|
|
|
genre has to be a string with the name of the genre, or a number identifying the genre. |
|
158
|
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
=cut |
|
160
|
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
sub all { |
|
162
|
0
|
|
|
0
|
1
|
0
|
my $self=shift; |
|
163
|
0
|
0
|
|
|
|
0
|
if ($#_ == 6) { |
|
164
|
0
|
|
|
|
|
0
|
my $new; |
|
165
|
0
|
|
|
|
|
0
|
for (qw/song artist album year comment track genre/) { |
|
166
|
0
|
|
|
|
|
0
|
$new = shift; |
|
167
|
0
|
|
|
|
|
0
|
$new =~ s/ *$//; |
|
168
|
0
|
|
|
|
|
0
|
$new = substr $new, 0, $ok_length{$_}; |
|
169
|
0
|
|
|
|
|
0
|
$self->{$_}=$new; |
|
170
|
|
|
|
|
|
|
} |
|
171
|
0
|
0
|
|
|
|
0
|
if ($self->{genre} =~ /^\d+$/) { |
|
172
|
0
|
|
|
|
|
0
|
$self->{genreID} = $self->{genre}; |
|
173
|
|
|
|
|
|
|
} else { |
|
174
|
0
|
|
|
|
|
0
|
$self->{genreID} = genre2id($self->{genre}); |
|
175
|
|
|
|
|
|
|
} |
|
176
|
0
|
|
|
|
|
0
|
$self->{genre} = id2genre($self->{genreID}); |
|
177
|
0
|
|
|
|
|
0
|
$self->{changed} = 1; |
|
178
|
|
|
|
|
|
|
} |
|
179
|
0
|
|
|
|
|
0
|
return ($self->{song},$self->{artist},$self->{album}, |
|
180
|
|
|
|
|
|
|
$self->{year},$self->{genre}, |
|
181
|
|
|
|
|
|
|
$self->{track}, $self->{comment}); |
|
182
|
|
|
|
|
|
|
} |
|
183
|
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
=pod |
|
185
|
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
=item writeTag() |
|
187
|
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
$id3v1->writeTag; |
|
189
|
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
Writes the ID3v1 tag to the file. |
|
191
|
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
=cut |
|
193
|
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
sub writeTag { |
|
195
|
2
|
|
|
2
|
1
|
6
|
my $self = shift; |
|
196
|
2
|
50
|
33
|
|
|
10
|
return undef unless exists $self->{song} && exists $self->{changed}; |
|
197
|
2
|
|
|
|
|
13
|
my $data = pack("a30a30a30a4a28xCC",$self->{song},$self->{artist},$self->{album}, |
|
198
|
|
|
|
|
|
|
$self->{year}, $self->{comment}, $self->{track}, $self->{genreID}); |
|
199
|
2
|
|
|
|
|
3
|
my $mp3obj = $self->{mp3}; |
|
200
|
2
|
|
|
|
|
2
|
my $mp3tag; |
|
201
|
2
|
|
|
|
|
17
|
$mp3obj->close; |
|
202
|
2
|
50
|
|
|
|
6
|
if ($mp3obj->open("+<")) { |
|
203
|
2
|
|
|
|
|
6
|
$mp3obj->seek(-128,2); |
|
204
|
2
|
|
|
|
|
6
|
$mp3obj->read(\$mp3tag, 3); |
|
205
|
2
|
50
|
|
|
|
6
|
if ($mp3tag eq "TAG") { |
|
206
|
2
|
|
|
|
|
7
|
$mp3obj->write($data); |
|
207
|
|
|
|
|
|
|
} else { |
|
208
|
0
|
|
|
|
|
0
|
$mp3obj->seek(0,2); |
|
209
|
0
|
|
|
|
|
0
|
$mp3obj->write("TAG$data"); |
|
210
|
|
|
|
|
|
|
} |
|
211
|
|
|
|
|
|
|
} |
|
212
|
2
|
|
|
|
|
8
|
return 1; |
|
213
|
|
|
|
|
|
|
} |
|
214
|
|
|
|
|
|
|
|
|
215
|
|
|
|
|
|
|
=pod |
|
216
|
|
|
|
|
|
|
|
|
217
|
|
|
|
|
|
|
=item removeTag() |
|
218
|
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
$id3v1->removeTag; |
|
220
|
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
Removes the ID3v1 tag from the file. |
|
222
|
|
|
|
|
|
|
|
|
223
|
|
|
|
|
|
|
=cut |
|
224
|
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
sub removeTag { |
|
226
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
|
227
|
0
|
|
|
|
|
0
|
my $mp3obj = $self->{mp3}; |
|
228
|
0
|
|
|
|
|
0
|
my $mp3tag; |
|
229
|
0
|
|
|
|
|
0
|
$mp3obj->seek(-128,2); |
|
230
|
0
|
|
|
|
|
0
|
$mp3obj->read(\$mp3tag, 3); |
|
231
|
0
|
0
|
|
|
|
0
|
if ($mp3tag eq "TAG") { |
|
232
|
0
|
|
|
|
|
0
|
$mp3obj->close; |
|
233
|
0
|
0
|
|
|
|
0
|
if ($mp3obj->open("+<")) { |
|
234
|
0
|
|
|
|
|
0
|
$mp3obj->truncate(-128); |
|
235
|
0
|
|
|
|
|
0
|
$self->all("","","","","",0,255); |
|
236
|
0
|
|
|
|
|
0
|
$mp3obj->close; |
|
237
|
0
|
|
|
|
|
0
|
$self->{changed} = 1; |
|
238
|
0
|
|
|
|
|
0
|
return 1; |
|
239
|
|
|
|
|
|
|
} |
|
240
|
0
|
|
|
|
|
0
|
return -1; |
|
241
|
|
|
|
|
|
|
} |
|
242
|
0
|
|
|
|
|
0
|
return 0; |
|
243
|
|
|
|
|
|
|
} |
|
244
|
|
|
|
|
|
|
|
|
245
|
|
|
|
|
|
|
=pod |
|
246
|
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
=item genres() |
|
248
|
|
|
|
|
|
|
|
|
249
|
|
|
|
|
|
|
@allgenres = $id3v1->genres; |
|
250
|
|
|
|
|
|
|
$genreName = $id3v1->genres($genreID); |
|
251
|
|
|
|
|
|
|
$genreID = $id3v1->genres($genreName); |
|
252
|
|
|
|
|
|
|
|
|
253
|
|
|
|
|
|
|
Returns a list of all genres, or the according name or id to |
|
254
|
|
|
|
|
|
|
a given id or name. |
|
255
|
|
|
|
|
|
|
|
|
256
|
|
|
|
|
|
|
=cut |
|
257
|
|
|
|
|
|
|
|
|
258
|
|
|
|
|
|
|
sub genres { |
|
259
|
|
|
|
|
|
|
# return an array with all genres, of if a parameter is given, the according genre |
|
260
|
0
|
|
|
0
|
1
|
0
|
my $genre = shift; |
|
261
|
0
|
0
|
|
|
|
0
|
return \@winamp_genres unless defined $genre; |
|
262
|
0
|
0
|
|
|
|
0
|
return $winamp_genres[$genre] if $genre =~ /^\d+$/; |
|
263
|
0
|
|
|
|
|
0
|
my $r; |
|
264
|
0
|
|
|
|
|
0
|
foreach (@winamp_genres) { |
|
265
|
0
|
0
|
|
|
|
0
|
if ($_ eq $genre) { |
|
266
|
0
|
|
|
|
|
0
|
$r=$_; |
|
267
|
0
|
|
|
|
|
0
|
last; |
|
268
|
|
|
|
|
|
|
} |
|
269
|
|
|
|
|
|
|
} |
|
270
|
0
|
|
|
|
|
0
|
return $r; |
|
271
|
|
|
|
|
|
|
} |
|
272
|
|
|
|
|
|
|
|
|
273
|
|
|
|
|
|
|
################# |
|
274
|
|
|
|
|
|
|
## |
|
275
|
|
|
|
|
|
|
## internal subs |
|
276
|
|
|
|
|
|
|
|
|
277
|
|
|
|
|
|
|
# actually read the tag data |
|
278
|
|
|
|
|
|
|
sub readTag { |
|
279
|
2
|
|
|
2
|
0
|
4
|
my ($self, $buffer) = @_; |
|
280
|
2
|
|
|
|
|
5
|
my $mp3obj = $self->{mp3}; |
|
281
|
2
|
|
|
|
|
2
|
my $id3v1; |
|
282
|
|
|
|
|
|
|
|
|
283
|
2
|
50
|
|
|
|
5
|
if ($self->{new}) { |
|
284
|
0
|
|
|
|
|
0
|
($self->{song}, $self->{artist}, $self->{album}, $self->{year}, |
|
285
|
|
|
|
|
|
|
$self->{comment}, $self->{track}, $self->{genre}, $self->{genreID}) = ("","","","","",0,"",255); |
|
286
|
0
|
|
|
|
|
0
|
$self->{changed} = 1; |
|
287
|
|
|
|
|
|
|
} else { |
|
288
|
2
|
|
|
|
|
21
|
(undef, $self->{song}, $self->{artist}, $self->{album}, $self->{year}, |
|
289
|
|
|
|
|
|
|
$self->{comment}, $id3v1, $self->{track}, $self->{genreID}) = |
|
290
|
|
|
|
|
|
|
unpack ("a3Z30Z30Z30Z4Z28CCC", $buffer); |
|
291
|
|
|
|
|
|
|
|
|
292
|
2
|
50
|
|
|
|
7
|
if ($id3v1!=0) { # ID3v1 tag found: track is not valid, comment two chars longer |
|
293
|
0
|
|
|
|
|
0
|
$self->{comment} .= chr($id3v1); |
|
294
|
0
|
0
|
|
|
|
0
|
$self->{comment} .= chr($self->{track}) if $self->{track}!=32; |
|
295
|
0
|
|
|
|
|
0
|
$self->{track} = 0; |
|
296
|
|
|
|
|
|
|
}; |
|
297
|
2
|
|
|
|
|
8
|
$self->{genre} = id2genre($self->{genreID}); |
|
298
|
|
|
|
|
|
|
} |
|
299
|
|
|
|
|
|
|
} |
|
300
|
|
|
|
|
|
|
|
|
301
|
|
|
|
|
|
|
# convert one byte id to genre name |
|
302
|
|
|
|
|
|
|
sub id2genre { |
|
303
|
2
|
|
|
2
|
0
|
3
|
my $id=shift; |
|
304
|
2
|
50
|
33
|
|
|
19
|
return "" unless defined $id && $id<$#winamp_genres; |
|
305
|
2
|
|
|
|
|
5
|
return $winamp_genres[$id]; |
|
306
|
|
|
|
|
|
|
} |
|
307
|
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
# convert genre name to one byte id |
|
309
|
|
|
|
|
|
|
sub genre2id { |
|
310
|
0
|
|
|
0
|
0
|
|
my $genre = shift; |
|
311
|
0
|
|
|
|
|
|
my $i=0; |
|
312
|
0
|
|
|
|
|
|
foreach (@winamp_genres) { |
|
313
|
0
|
0
|
|
|
|
|
if (uc $genre eq uc $_) { |
|
314
|
0
|
|
|
|
|
|
return $i; |
|
315
|
|
|
|
|
|
|
} |
|
316
|
0
|
|
|
|
|
|
$i++, |
|
317
|
|
|
|
|
|
|
} |
|
318
|
0
|
|
|
|
|
|
return 255; |
|
319
|
|
|
|
|
|
|
} |
|
320
|
|
|
|
|
|
|
|
|
321
|
|
|
|
|
|
|
# nothing to do for destroy |
|
322
|
0
|
|
|
0
|
|
|
sub DESTROY { |
|
323
|
|
|
|
|
|
|
} |
|
324
|
|
|
|
|
|
|
|
|
325
|
|
|
|
|
|
|
1; |
|
326
|
|
|
|
|
|
|
|
|
327
|
|
|
|
|
|
|
######## define all the genres |
|
328
|
|
|
|
|
|
|
|
|
329
|
1
|
|
|
1
|
|
17
|
BEGIN { @mp3_genres = ( 'Blues', 'Classic Rock', 'Country', 'Dance', |
|
330
|
|
|
|
|
|
|
'Disco', 'Funk', 'Grunge', 'Hip-Hop', 'Jazz', 'Metal', 'New Age', |
|
331
|
|
|
|
|
|
|
'Oldies', 'Other', 'Pop', 'R&B', 'Rap', 'Reggae', 'Rock', 'Techno', |
|
332
|
|
|
|
|
|
|
'Industrial', 'Alternative', 'Ska', 'Death Metal', 'Pranks', |
|
333
|
|
|
|
|
|
|
'Soundtrack', 'Euro-Techno', 'Ambient', 'Trip-Hop', 'Vocal', |
|
334
|
|
|
|
|
|
|
'Jazz+Funk', 'Fusion', 'Trance', 'Classical', 'Instrumental', 'Acid', |
|
335
|
|
|
|
|
|
|
'House', 'Game', 'Sound Clip', 'Gospel', 'Noise', 'AlternRock', |
|
336
|
|
|
|
|
|
|
'Bass', 'Soul', 'Punk', 'Space', 'Meditative', 'Instrumental Pop', |
|
337
|
|
|
|
|
|
|
'Instrumental Rock', 'Ethnic', 'Gothic', 'Darkwave', |
|
338
|
|
|
|
|
|
|
'Techno-Industrial', 'Electronic', 'Pop-Folk', 'Eurodance', 'Dream', |
|
339
|
|
|
|
|
|
|
'Southern Rock', 'Comedy', 'Cult', 'Gangsta', 'Top 40', |
|
340
|
|
|
|
|
|
|
'Christian Rap', 'Pop/Funk', 'Jungle', 'Native American', 'Cabaret', 'New Wave', |
|
341
|
|
|
|
|
|
|
'Psychadelic', 'Rave', 'Showtunes', 'Trailer', 'Lo-Fi', 'Tribal', |
|
342
|
|
|
|
|
|
|
'Acid Punk', 'Acid Jazz', 'Polka', 'Retro', 'Musical', 'Rock & Roll', |
|
343
|
|
|
|
|
|
|
'Hard Rock', ); |
|
344
|
|
|
|
|
|
|
|
|
345
|
1
|
|
|
|
|
46
|
@winamp_genres = ( @mp3_genres, 'Folk', 'Folk-Rock', |
|
346
|
|
|
|
|
|
|
'National Folk', 'Swing', 'Fast Fusion', 'Bebob', 'Latin', 'Revival', |
|
347
|
|
|
|
|
|
|
'Celtic', 'Bluegrass', 'Avantgarde', 'Gothic Rock', |
|
348
|
|
|
|
|
|
|
'Progressive Rock', 'Psychedelic Rock', 'Symphonic Rock', |
|
349
|
|
|
|
|
|
|
'Slow Rock', 'Big Band', 'Chorus', 'Easy Listening', |
|
350
|
|
|
|
|
|
|
'Acoustic', 'Humour', 'Speech', 'Chanson', 'Opera', |
|
351
|
|
|
|
|
|
|
'Chamber Music', 'Sonata', 'Symphony', 'Booty Bass', 'Primus', |
|
352
|
|
|
|
|
|
|
'Porn Groove', 'Satire', 'Slow Jam', 'Club', 'Tango', 'Samba', |
|
353
|
|
|
|
|
|
|
'Folklore', 'Ballad', 'Power Ballad', 'Rhythmic Soul', |
|
354
|
|
|
|
|
|
|
'Freestyle', 'Duet', 'Punk Rock', 'Drum Solo', 'Acapella', |
|
355
|
|
|
|
|
|
|
'Euro-House', 'Dance Hall', ); |
|
356
|
|
|
|
|
|
|
} |
|
357
|
|
|
|
|
|
|
|
|
358
|
|
|
|
|
|
|
=pod |
|
359
|
|
|
|
|
|
|
|
|
360
|
|
|
|
|
|
|
=head1 SEE ALSO |
|
361
|
|
|
|
|
|
|
|
|
362
|
|
|
|
|
|
|
MP3::Tag, MP3::TAG::ID3v2 |
|
363
|
|
|
|
|
|
|
|
|
364
|
|
|
|
|
|
|
ID3v1 standard - http://www.id3.org |
|
365
|
|
|
|
|
|
|
|
|
366
|
|
|
|
|
|
|
=cut |