id3 0.4.0 → 0.4.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +12 -0
- data/README +0 -5
- data/docs/index.html +12 -5
- data/lib/id3.rb +111 -16
- metadata +3 -2
data/CHANGES
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
= id3 changes
|
2
|
+
|
3
|
+
=== 0.4.1 (2008-08-16)
|
4
|
+
|
5
|
+
* Included patch provided by Sergey Udaltsov for UTF-8 and UTF-16 encodings, and new parser routines
|
6
|
+
|
7
|
+
=== 0.4.0 (2008-08-16)
|
8
|
+
|
9
|
+
* Made previous version 0.4 available as a Ruby Gem , otherwise identical to 0.4
|
10
|
+
|
11
|
+
|
12
|
+
|
data/README
CHANGED
data/docs/index.html
CHANGED
@@ -114,16 +114,23 @@ without problems. <br>
|
|
114
114
|
|
115
115
|
|
116
116
|
|
117
|
-
<h3>
|
117
|
+
<h3>Downloads</h3>
|
118
118
|
|
119
119
|
|
120
120
|
<br>
|
121
121
|
<table border=1>
|
122
|
-
<tr><th>Version</th><th>gem</th><th>tar.gz</th></tr>
|
122
|
+
<tr><th>Version</th><th>gem</th><th>tar.gz</th><th>Changes</th></tr>
|
123
123
|
<tr>
|
124
|
-
<
|
125
|
-
|
126
|
-
|
124
|
+
<th>0.4.1</th>
|
125
|
+
<td><A HREF=../../id3-0.4.1.gem>id3-0.4.1.gem</A></td>
|
126
|
+
<td><A HREF=../../id3-0.4.1.tar.gz>id3-0.4.1.tar.gz</A></td>
|
127
|
+
<td>Included patch provided by Sergey Udaltsov for UTF-8 and UTF-16 encodings, and new parser routines</td>
|
128
|
+
</tr>
|
129
|
+
<tr>
|
130
|
+
<th>0.4.0</th>
|
131
|
+
<td><A HREF=../../id3-0.4.0.gem>id3-0.4.0.gem</A></td>
|
132
|
+
<td><A HREF=../../id3-0.4.0.tar.gz>id3-0.4.0.tar.gz</A></td>
|
133
|
+
<td>identical to previous 0.4 version, but now also available as a ruby gem</td>
|
127
134
|
</tr>
|
128
135
|
</table>
|
129
136
|
|
data/lib/id3.rb
CHANGED
@@ -2,10 +2,16 @@
|
|
2
2
|
# id3.rb Ruby Module for handling the following ID3-tag versions:
|
3
3
|
# ID3v1.0 , ID3v1.1, ID3v2.2.0, ID3v2.3.0, ID3v2.4.0
|
4
4
|
#
|
5
|
-
# Copyright (C) 2002
|
5
|
+
# Copyright (C) 2002..2008 by Tilo Sloboda <tilo@unixgods.org>
|
6
6
|
#
|
7
7
|
# created: 12 Oct 2002
|
8
|
-
# updated: Time-stamp: <
|
8
|
+
# updated: Time-stamp: <Sat 16-Aug-2008 11:20:33 Tilo Sloboda>
|
9
|
+
#
|
10
|
+
# Version: 0.4.1
|
11
|
+
#
|
12
|
+
# Changes:
|
13
|
+
# 0.4.1 thanks to Sergey Udaltsov for the UTF-8 UTF-16 patch
|
14
|
+
# and parser routines!
|
9
15
|
#
|
10
16
|
# Docs: http://www.id3.org/id3v2-00.txt
|
11
17
|
# http://www.id3.org/id3v2.3.0.txt
|
@@ -77,6 +83,7 @@
|
|
77
83
|
# ==============================================================================
|
78
84
|
|
79
85
|
require "md5"
|
86
|
+
require "iconv"
|
80
87
|
|
81
88
|
require 'hexdump' # load hexdump method to extend class String
|
82
89
|
require 'invert_hash' # new invert method for old Hash
|
@@ -276,6 +283,90 @@ module ID3
|
|
276
283
|
VARS = 0
|
277
284
|
PACKING = 1
|
278
285
|
|
286
|
+
BE16BOM = "\xFE\xFF"
|
287
|
+
LE16BOM = "\xFF\xFE"
|
288
|
+
|
289
|
+
def ID3.parse_string_rest(encoding, string)
|
290
|
+
case encoding
|
291
|
+
when 0
|
292
|
+
# ISO8859-1
|
293
|
+
return Iconv.iconv("ISO8859-1", "UTF-8", string);
|
294
|
+
when 1
|
295
|
+
# utf-16
|
296
|
+
bom = string[0..1]
|
297
|
+
data = string[2..string.length-1]
|
298
|
+
srcenc = bom == LE16BOM ? "UTF-16LE" : bom == BE16BOM ? "UTF-16BE" : "??"
|
299
|
+
return Iconv.iconv("UTF-8", srcenc, data);
|
300
|
+
when 2
|
301
|
+
# utf-16BE
|
302
|
+
return
|
303
|
+
Iconv.iconv("UTF-16BE", "UTF-8", data);
|
304
|
+
when 3
|
305
|
+
return string
|
306
|
+
else
|
307
|
+
raise 'Unknown encoding #{encoding}'
|
308
|
+
end
|
309
|
+
end
|
310
|
+
|
311
|
+
def ID3.parse_string_zeroend(encoding, string)
|
312
|
+
strend = encoding == 0 || encoding == 3 ? "\x00" : "\x00\x00";
|
313
|
+
|
314
|
+
endidx = string.index(strend)
|
315
|
+
if endidx.nil?
|
316
|
+
return parse_string_rest(encoding, string), string.length;
|
317
|
+
elsif endidx == 0
|
318
|
+
return "", strend.length;
|
319
|
+
else
|
320
|
+
return parse_string_rest(encoding, string[0..endidx-1]), endidx + strend.length;
|
321
|
+
end
|
322
|
+
end
|
323
|
+
|
324
|
+
def ID3.parse_a(data)
|
325
|
+
return [data]
|
326
|
+
end
|
327
|
+
|
328
|
+
def ID3.parse_Z(data)
|
329
|
+
rest = parse_string_rest(data)
|
330
|
+
return first, rest
|
331
|
+
end
|
332
|
+
|
333
|
+
def ID3.parse_CZ(data)
|
334
|
+
encoding = data[0]
|
335
|
+
rest = parse_string_rest(encoding, data[1..data.length-1])
|
336
|
+
return encoding, rest
|
337
|
+
end
|
338
|
+
|
339
|
+
def ID3.parse_CZZ(data)
|
340
|
+
encoding = data[0]
|
341
|
+
second,length = parse_string_zeroend(encoding, data[1..data.length-1])
|
342
|
+
rest = parse_string_rest(encoding, data[1 + length..data.length-1])
|
343
|
+
return encoding, second, rest
|
344
|
+
end
|
345
|
+
|
346
|
+
def ID3.parse_CZCZa(data)
|
347
|
+
encoding = data[0]
|
348
|
+
second,length = parse_string_zeroend(encoding, data[1..data.length-1])
|
349
|
+
third = data[length + 1]
|
350
|
+
fourth,nexpart2 = parse_string_zeroend(encoding, data[2 + length..data.length-1])
|
351
|
+
rest = data[2 + length + length2..data.length-1]
|
352
|
+
return encoding, second, third, fourth, rest
|
353
|
+
end
|
354
|
+
|
355
|
+
def ID3.parse_Ca3ZZ(data)
|
356
|
+
encoding = data[0]
|
357
|
+
second = data[1..3]
|
358
|
+
third,length = parse_string_zeroend(encoding,data[4..data.length-1])
|
359
|
+
rest = parse_string_rest(encoding, data[4 + length..data.length-1])
|
360
|
+
return encoding, second, third, rest
|
361
|
+
end
|
362
|
+
|
363
|
+
PARSER_CZ = lambda { |data| parse_CZ(data) }
|
364
|
+
PARSER_CZZ = lambda { |data| parse_CZZ(data) }
|
365
|
+
PARSER_Z = lambda { |data| parse_Z(data) }
|
366
|
+
PARSER_a = lambda { |data| parse_a(data) }
|
367
|
+
PARSER_CZCZa = lambda { |data| parse_CZCZa(data) }
|
368
|
+
PARSER_Ca3ZZ = lambda { |data| parse_Ca3ZZ(data) }
|
369
|
+
|
279
370
|
# not sure if it's Z* or A*
|
280
371
|
# A* does not append a \0 when writing!
|
281
372
|
|
@@ -283,21 +374,21 @@ module ID3
|
|
283
374
|
# seems like i have no version 2.4.x ID3-tags!! If you have some, send them my way!
|
284
375
|
|
285
376
|
FRAME_PARSER = {
|
286
|
-
"TEXT" => [ %w(encoding text) ,
|
287
|
-
"USERTEXT" => [ %w(encoding description value) ,
|
377
|
+
"TEXT" => [ %w(encoding text) , PARSER_CZ ] ,
|
378
|
+
"USERTEXT" => [ %w(encoding description value) , PARSER_CZZ ] ,
|
288
379
|
|
289
|
-
"PICTURE" => [ %w(encoding mimeType pictType description picture) ,
|
380
|
+
"PICTURE" => [ %w(encoding mimeType pictType description picture) , PARSER_CZCZa ] ,
|
290
381
|
|
291
|
-
"WEB" => [ "url" ,
|
292
|
-
"WWWUSER" => [ %w(encoding description url) ,
|
382
|
+
"WEB" => [ "url" , PARSER_Z ] ,
|
383
|
+
"WWWUSER" => [ %w(encoding description url) , PARSER_CZZ ] ,
|
293
384
|
|
294
|
-
"LTEXT" => [ %w(encoding language text) ,
|
295
|
-
"UNSYNCEDLYRICS" => [ %w(encoding language content text) ,
|
296
|
-
"COMMENT" => [ %w(encoding language short long) ,
|
297
|
-
"BINARY" => [ "binary" ,
|
298
|
-
"UNPARSED" => [ "raw" ,
|
385
|
+
"LTEXT" => [ %w(encoding language text) , PARSER_CZZ ] ,
|
386
|
+
"UNSYNCEDLYRICS" => [ %w(encoding language content text) , PARSER_Ca3ZZ ] ,
|
387
|
+
"COMMENT" => [ %w(encoding language short long) , PARSER_Ca3ZZ ] ,
|
388
|
+
"BINARY" => [ "binary" , PARSER_a ] ,
|
389
|
+
"UNPARSED" => [ "raw" , PARSER_a ] # how would we do value checking for this?
|
299
390
|
}
|
300
|
-
|
391
|
+
|
301
392
|
# ----------------------------------------------------------------------------
|
302
393
|
# MODULE VARIABLES
|
303
394
|
# ----------------------------------------------------------------------------
|
@@ -964,7 +1055,7 @@ module ID3
|
|
964
1055
|
framename = header[0..3]
|
965
1056
|
size = (header[4]*256**3)+(header[5]*256**2)+(header[6]*256)+header[7]
|
966
1057
|
flags= header[8..9]
|
967
|
-
# printf "frame: %s , size: %d, flags: %
|
1058
|
+
# printf "frame (at %x, frameheader %d): %s , size: %d, flags: %x %x\n", x, frameHeaderSize, framename , size, flags[0], flags[1]
|
968
1059
|
|
969
1060
|
else
|
970
1061
|
# we can't parse higher versions
|
@@ -1090,7 +1181,11 @@ module ID3
|
|
1090
1181
|
end
|
1091
1182
|
EOB
|
1092
1183
|
|
1093
|
-
@rawflags = flags.to_i
|
1184
|
+
@rawflags = flags[0].to_i << 8 | flags[1] # preserve the raw flags (for debugging only)
|
1185
|
+
|
1186
|
+
if (@rawflags & (FRAME_HEADER_FLAGS["2.4.0"]["Unsynchronisation"])) != 0
|
1187
|
+
@rawdata = @rawdata.gsub("\xFF\x00","\xFF")
|
1188
|
+
end
|
1094
1189
|
|
1095
1190
|
if (flags.to_i & FRAME_HEADER_FLAG_MASK[@version] != 0)
|
1096
1191
|
# in this case we need to skip parsing the frame... and skip to the next one...
|
@@ -1128,7 +1223,7 @@ module ID3
|
|
1128
1223
|
vars2 = vars
|
1129
1224
|
end
|
1130
1225
|
|
1131
|
-
values = self.rawdata
|
1226
|
+
values = packing.call(self.rawdata)
|
1132
1227
|
vars.each { |key|
|
1133
1228
|
self[key] = values.shift
|
1134
1229
|
}
|
metadata
CHANGED
@@ -3,9 +3,9 @@ rubygems_version: 0.9.4
|
|
3
3
|
specification_version: 1
|
4
4
|
name: id3
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.4.
|
6
|
+
version: 0.4.1
|
7
7
|
date: 2008-08-16 00:00:00 -07:00
|
8
|
-
summary: id3-0.4.
|
8
|
+
summary: id3-0.4.1 - ID3 tag library for Ruby http://www.unixgods.org/~tilo/Ruby/ID3
|
9
9
|
require_paths:
|
10
10
|
- lib
|
11
11
|
email: tools@unixgods.org
|
@@ -58,6 +58,7 @@ files:
|
|
58
58
|
- LICENSE.html
|
59
59
|
- index.html
|
60
60
|
- README
|
61
|
+
- CHANGES
|
61
62
|
test_files: []
|
62
63
|
|
63
64
|
rdoc_options:
|