id3 0.4.1 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (4) hide show
  1. data/CHANGES +8 -0
  2. data/docs/index.html +13 -0
  3. data/lib/id3.rb +168 -173
  4. metadata +3 -3
data/CHANGES CHANGED
@@ -1,5 +1,13 @@
1
1
  = id3 changes
2
2
 
3
+ === 0.5.0 (2008-08-18)
4
+
5
+ * Added write support
6
+ * Fixed bug in determining the audioEnd index
7
+ * reverted UTF-16 fix because it broke the writing the tags
8
+ If you really need UTF-16 encoding, please stick with version 0.4.1 for now (read-only)
9
+
10
+
3
11
  === 0.4.1 (2008-08-16)
4
12
 
5
13
  * Included patch provided by Sergey Udaltsov for UTF-8 and UTF-16 encodings, and new parser routines
@@ -120,6 +120,19 @@ without problems.&nbsp;&nbsp; <br>
120
120
  <br>
121
121
  <table border=1>
122
122
  <tr><th>Version</th><th>gem</th><th>tar.gz</th><th>Changes</th></tr>
123
+ <tr>
124
+ <th>0.5.0</th>
125
+ <td><A HREF=../../id3-0.5.0.gem>id3-0.5.0.gem</A></td>
126
+ <td><A HREF=../../id3-0.5.0.tar.gz>id3-0.5.0.tar.gz</A></td>
127
+ <td>
128
+ <UL>
129
+ <LI>Added write support
130
+ <LI> Fixed bug in determining the audioEnd index
131
+ <LI> reverted UTF-16 fix because it broke the writing the tags
132
+ If you really need UTF-16 encoding, please stick with version 0.4.1 for now (read-only)
133
+ </UL>
134
+ </td>
135
+ </tr>
123
136
  <tr>
124
137
  <th>0.4.1</th>
125
138
  <td><A HREF=../../id3-0.4.1.gem>id3-0.4.1.gem</A></td>
data/lib/id3.rb CHANGED
@@ -2,16 +2,10 @@
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..2008 by Tilo Sloboda <tilo@unixgods.org>
5
+ # Copyright (C) 2002 .. 2008 by Tilo Sloboda <tilo@unixgods.org>
6
6
  #
7
7
  # created: 12 Oct 2002
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!
8
+ # updated: Time-stamp: <Mon 18-Aug-2008 06:16:19 Tilo Sloboda>
15
9
  #
16
10
  # Docs: http://www.id3.org/id3v2-00.txt
17
11
  # http://www.id3.org/id3v2.3.0.txt
@@ -20,8 +14,8 @@
20
14
  # http://www.id3.org/id3v2.4.0-frames.txt
21
15
  #
22
16
  # different versions of ID3 tags, support different fields.
23
- # See: http://www.unixgods.org/~tilo/ID3v2_frames_comparison.txt
24
- # See: http://www.unixgods.org/~tilo/ID3/docs/ID3_comparison.html
17
+ # See: http://www.unixgods.org/~tilo/Ruby/ID3/docs/ID3v2_frames_comparison.txt
18
+ # See: http://www.unixgods.org/~tilo/Ruby/ID3/docs/ID3_comparison.html
25
19
  #
26
20
  # License:
27
21
  # Freely available under the terms of the OpenSource "Artistic License"
@@ -42,6 +36,7 @@
42
36
  # TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF THE COPYRIGHT HOLDERS OR OTHER PARTY HAS BEEN
43
37
  # ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
44
38
  #
39
+ #
45
40
  # Author's Rant:
46
41
  # The author of this ID3-library for Ruby is not responsible in any way for
47
42
  # the definition of the ID3-standards..
@@ -71,7 +66,7 @@
71
66
  # removeID3v1tag(filename)
72
67
  #
73
68
  # Classes:
74
- # File
69
+ # AudioFile
75
70
  # Tag1
76
71
  # Tag2
77
72
  # Frame
@@ -79,13 +74,17 @@
79
74
  ################################################################################
80
75
 
81
76
  # ==============================================================================
82
- # Lading other stuff..
77
+ # Loading other stuff..
83
78
  # ==============================================================================
84
79
 
85
- require "md5"
86
- require "iconv"
80
+ require 'md5'
81
+ require 'tempfile'
82
+ require 'ftools'
83
+
84
+ # my extensions:
87
85
 
88
86
  require 'hexdump' # load hexdump method to extend class String
87
+
89
88
  require 'invert_hash' # new invert method for old Hash
90
89
 
91
90
 
@@ -97,6 +96,7 @@ class Hash # overwrite Hash.invert method
97
96
  end
98
97
  end
99
98
 
99
+ # ==============================================================================
100
100
 
101
101
  module ID3
102
102
 
@@ -283,112 +283,28 @@ module ID3
283
283
  VARS = 0
284
284
  PACKING = 1
285
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
-
370
286
  # not sure if it's Z* or A*
371
287
  # A* does not append a \0 when writing!
372
288
 
373
- # STILL NEED TO CAREFULLY VERIFY THESE AGAINST THE STANDARDS AND GET TEST-CASES!
289
+ # STILL NEED TO GET MORE TEST-CASES! e.g. Japanese ID3-Tags! or other encodings..
374
290
  # seems like i have no version 2.4.x ID3-tags!! If you have some, send them my way!
375
291
 
376
292
  FRAME_PARSER = {
377
- "TEXT" => [ %w(encoding text) , PARSER_CZ ] ,
378
- "USERTEXT" => [ %w(encoding description value) , PARSER_CZZ ] ,
293
+ "TEXT" => [ %w(encoding text) , 'CZ*' ] ,
294
+ "USERTEXT" => [ %w(encoding description value) , 'CZ*Z*' ] ,
379
295
 
380
- "PICTURE" => [ %w(encoding mimeType pictType description picture) , PARSER_CZCZa ] ,
296
+ "PICTURE" => [ %w(encoding mimeType pictType description picture) , 'CZ*CZ*a*' ] ,
381
297
 
382
- "WEB" => [ "url" , PARSER_Z ] ,
383
- "WWWUSER" => [ %w(encoding description url) , PARSER_CZZ ] ,
298
+ "WEB" => [ "url" , 'Z*' ] ,
299
+ "WWWUSER" => [ %w(encoding description url) , 'CZ*Z*' ] ,
384
300
 
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?
301
+ "LTEXT" => [ %w(encoding language text) , 'CZ*Z*' ] ,
302
+ "UNSYNCEDLYRICS" => [ %w(encoding language content text) , 'Ca3Z*Z*' ] ,
303
+ "COMMENT" => [ %w(encoding language short long) , 'Ca3Z*Z*' ] ,
304
+ "BINARY" => [ "binary" , 'a*' ] ,
305
+ "UNPARSED" => [ "raw" , 'a*' ] # how would we do value checking for this?
390
306
  }
391
-
307
+
392
308
  # ----------------------------------------------------------------------------
393
309
  # MODULE VARIABLES
394
310
  # ----------------------------------------------------------------------------
@@ -428,9 +344,8 @@ module ID3
428
344
  # MODULE FUNCTIONS:
429
345
  # ----------------------------------------------------------------------------
430
346
  # The ID3 module functions are to query or modify files directly.
431
- # They give direct acess to files, and don't parse the tags, despite their headers
432
- #
433
- #
347
+ # They check directly if a file has a ID3-tag, but they don't parse the tags!
348
+
434
349
 
435
350
  # ----------------------------------------------------------------------------
436
351
  # hasID3v1tag?
@@ -504,7 +419,8 @@ module ID3
504
419
  stat = File.stat(filename)
505
420
  if stat.file? && stat.writable? && ID3.hasID3v1tag?(filename)
506
421
 
507
- # CAREFUL: this does not check if there really is a valid tag:
422
+ # CAREFUL: this does not check if there really is a valid tag,
423
+ # that's why we need to check above!!
508
424
 
509
425
  newsize = stat.size - ID3v1tagSize
510
426
  File.open(filename, "r+") { |f| f.truncate(newsize) }
@@ -525,8 +441,8 @@ module ID3
525
441
  # revert feature would be nice to have..
526
442
  #
527
443
  # If we query and AudioFile object, we query what's currently associated with it
528
- # e.g. we're not querying the file itself, but the perhaps modified tags
529
- # To query the file itself, use the module functions
444
+ # e.g. we're not querying the file itself, but the Tag object which is perhaps modified.
445
+ # To query the file itself, use the ID3 module functions
530
446
 
531
447
  class AudioFile
532
448
 
@@ -537,12 +453,11 @@ module ID3
537
453
  attr_reader :dirname, :basename # absolute dirname and basename of the file (computed)
538
454
 
539
455
  attr_accessor :tagID3v1, :tagID3v2
540
- attr_reader :hasID3tag # either false, or a string with all version numbers found
541
456
 
542
457
  # ----------------------------------------------------------------------------
543
458
  # initialize
544
459
  #
545
- # AudioFile.new does NOT open the file, but scans it and parses the info
460
+ # AudioFile.new does NOT keep the file open, but scans it and parses the info
546
461
 
547
462
  # e.g.: ID3::AudioFile.new('mp3/a.mp3')
548
463
 
@@ -556,7 +471,7 @@ module ID3
556
471
  @tagID3v2 = nil
557
472
 
558
473
  audioStartX = 0
559
- audioEndX = File.size(filename)
474
+ audioEndX = File.size(filename) - 1 # points to the last index
560
475
 
561
476
  if ID3.hasID3v1tag?(@filename)
562
477
  @tagID3v1 = Tag1.new
@@ -572,15 +487,102 @@ module ID3
572
487
  end
573
488
 
574
489
  # audioStartX audioEndX indices into the file need to be set
575
- @audioStartX = audioStartX
576
- @audioEndX = audioEndX
490
+ @audioStartX = audioStartX # first byte of audio data
491
+ @audioEndX = audioEndX # last byte of audio data
577
492
 
578
493
  # user may compute the MD5sum of the audio content later..
579
494
  # but we're only doing this if the user requests it..
495
+ # because MD5sum computation takes a little bit time.
580
496
 
581
497
  @audioMD5sum = nil
582
498
  end
583
499
 
500
+ # ----------------------------------------------------------------------------
501
+ def audioLength
502
+ @audioEndX - @audioStartX + 1
503
+ end
504
+ # ----------------------------------------------------------------------------
505
+ # write
506
+ # write the AudioFile to file, including any ID3-tags
507
+ # We keep backups if we write to a specific filename
508
+
509
+ def write(*filename)
510
+ backups = false
511
+
512
+ if filename.size == 0 # this is an Array!!
513
+ filename = @filename
514
+ backups = true # keep backups if we write to a specific filename
515
+ else
516
+ filename = filename[0]
517
+ backups = false
518
+ end
519
+
520
+ tf = Tempfile.new( @basename )
521
+ tmpname = tf.path
522
+
523
+ # write ID3v2 tag:
524
+
525
+ if @tagID3v2
526
+ tf.write( @tagID3v2.dump )
527
+ end
528
+
529
+ # write Audio Data:
530
+
531
+ File.open( @filename ) { |f|
532
+ f.seek(@audioStartX)
533
+ tf.write( f.read(@audioEndX - @audioStartX +1) )
534
+ }
535
+
536
+ # write ID3v1 tag:
537
+
538
+ if @tagID3v1
539
+ tf.write( @tagID3v1.dump )
540
+ end
541
+
542
+ tf.close
543
+
544
+ # now some logic about moving the tempfile and replacing the original
545
+
546
+ bakname = filename + '.bak'
547
+ File.move(filename, bakname) if backups && FileTest.exists?(filename) && ! FileTest.exists?(bakname)
548
+
549
+ File.move(tmpname, filename)
550
+ tf.close(true)
551
+
552
+ # write md5sum file:
553
+
554
+ writeMD5sum if @audioMD5sum
555
+
556
+ end
557
+
558
+ # ----------------------------------------------------------------------------
559
+ # writeAudio
560
+ # only for debugging, does not write any ID3-tags, but just the audio portion
561
+
562
+ def writeAudio
563
+ tf = Tempfile.new( @basename )
564
+
565
+ File.open( @filename ) { |f|
566
+ f.seek(@audioStartX)
567
+ tf.write( f.read(@audioEndX - @audioStartX + 1) )
568
+ }
569
+ tf.close
570
+ path = tf.path
571
+
572
+ tf.open
573
+ tf.close(true)
574
+ end
575
+
576
+
577
+ # ----------------------------------------------------------------------------
578
+ # NOTE on md5sum's:
579
+ # If you don't know what an md5sum is, you can think of it as a unique
580
+ # fingerprint of a file or some data. I added the md5sum computation to
581
+ # help users keep track of their converted songs - even if the ID3-tag of
582
+ # a file changes, the md5sum of the audio data does not change..
583
+ # The md5sum can help you ensure that the audio-portion of the file
584
+ # was not changed after modifying, adding or deleting ID3-tags.
585
+
584
586
  # ----------------------------------------------------------------------------
585
587
  # audioMD5sum
586
588
  # if the user tries to access @audioMD5sum, it will be computed for him,
@@ -647,6 +649,11 @@ module ID3
647
649
 
648
650
  end
649
651
  # ----------------------------------------------------------------------------
652
+ # version aka versions
653
+ # queries the tag objects and returns the version numbers of those tags
654
+ # NOTE: this does not reflect what's currently in the file, but what's
655
+ # currently in the AudioFile object
656
+
650
657
  def version
651
658
  a = Array.new
652
659
  a.push(@tagID3v1.version) if @tagID3v1
@@ -664,6 +671,8 @@ module ID3
664
671
 
665
672
  # ==============================================================================
666
673
  # Class RestrictedOrderedHash
674
+ # this is a helper Class for ID3::Frame
675
+ #
667
676
 
668
677
  class RestrictedOrderedHash < Hash
669
678
 
@@ -740,15 +749,20 @@ module ID3
740
749
  # ==============================================================================
741
750
  # Class GenericTag
742
751
  #
743
- # as per ID3-definition, the frames are in no fixed order! that's why Hash is OK
752
+ # Helper class for Tag1 and Tag2
753
+ #
754
+ # Checks that user uses a valid key, and adds methods for size computation
755
+ #
756
+ # as per ID3-definition, the frames are in no fixed order! that's why we can derive
757
+ # this class from Hash. But in the future we may want to write certain frames first
758
+ # into the ID3-tag and therefore may want to derive it from RestrictedOrderedHash
744
759
 
745
- class GenericTag < Hash ###### should this be RestrictedOrderedHash as well?
760
+ class GenericTag < Hash
746
761
  attr_reader :version, :raw
747
762
 
748
763
  # these definitions are to prevent users from inventing their own field names..
749
764
  # but on the other hand, they should be able to create a new valid field, if
750
765
  # it's not yet in the current tag, but it's valid for that ID3-version...
751
- # ... so hiding this, is not enough!
752
766
 
753
767
  alias old_set []=
754
768
  private :old_set
@@ -810,12 +824,6 @@ module ID3
810
824
  # ----------------------------------------------------------------------
811
825
  # read reads a version 1.x ID3tag
812
826
  #
813
- # 30 title
814
- # 30 artist
815
- # 30 album
816
- # 4 year
817
- # 30 comment
818
- # 1 genre
819
827
 
820
828
  def read(filename)
821
829
  f = File.open(filename, 'r')
@@ -825,7 +833,7 @@ module ID3
825
833
  f.seek(-ID3::ID3v1tagSize, IO::SEEK_END)
826
834
  @raw = f.read(ID3::ID3v1tagSize)
827
835
 
828
- # self.parse!(raw) # we should use "parse!" instead of re-coding everything..
836
+ # self.parse!(raw) # we should use "parse!" instead of duplicating code!
829
837
 
830
838
  if (raw[ID3v1versionbyte] == 0)
831
839
  @version = "1.1"
@@ -860,6 +868,7 @@ module ID3
860
868
  #
861
869
  # always upgrade version 1.0 to 1.1 when writing
862
870
 
871
+ # not yet implemented, because AudioFile.write does the job better
863
872
 
864
873
  # ----------------------------------------------------------------------
865
874
  # this routine modifies self, e.g. the Tag1 object
@@ -896,7 +905,7 @@ module ID3
896
905
  #
897
906
  # although we provide this method, it's stongly discouraged to use it,
898
907
  # because ID3 version 1.x tags are inferior to version 2.x tags, as entries
899
- # are often truncated and hence often useless..
908
+ # are often truncated and hence ID3 v1 tags are often useless..
900
909
 
901
910
  def dump
902
911
  zeroes = "\0" * 32
@@ -1000,14 +1009,28 @@ module ID3
1000
1009
  # writes and replaces existing ID3-v2-tag if one is present
1001
1010
  # Careful, this does NOT merge or append, it overwrites!
1002
1011
 
1003
- def write(filename)
1012
+ # not yet implemented, because AudioFile.write does the job better
1013
+
1014
+ # def write(filename)
1004
1015
  # check how long the old ID3-v2 tag is
1005
1016
 
1006
1017
  # dump ID3-v2-tag
1007
1018
 
1008
1019
  # append old audio to new tag
1009
1020
 
1010
- end
1021
+ # end
1022
+
1023
+ # ----------------------------------------------------------------------------
1024
+ # writeID3v2
1025
+ # just writes the ID3v2 tag by itself into a file, no audio data is written
1026
+ #
1027
+ # for backing up ID3v2 tags and debugging only..
1028
+ #
1029
+
1030
+ # def writeID3v2
1031
+
1032
+ # end
1033
+
1011
1034
  # ----------------------------------------------------------------------
1012
1035
  # parse_frame_header
1013
1036
  #
@@ -1055,7 +1078,7 @@ module ID3
1055
1078
  framename = header[0..3]
1056
1079
  size = (header[4]*256**3)+(header[5]*256**2)+(header[6]*256)+header[7]
1057
1080
  flags= header[8..9]
1058
- # printf "frame (at %x, frameheader %d): %s , size: %d, flags: %x %x\n", x, frameHeaderSize, framename , size, flags[0], flags[1]
1081
+ # printf "frame: %s , size: %d, flags: %s\n", framename , size, flags
1059
1082
 
1060
1083
  else
1061
1084
  # we can't parse higher versions
@@ -1074,6 +1097,12 @@ module ID3
1074
1097
  end
1075
1098
  # ----------------------------------------------------------------------
1076
1099
  # dump a ID3-v2 tag into a binary array
1100
+ #
1101
+ # NOTE:
1102
+ # when "dumping" an ID3-v2 tag, I would like to have more control about
1103
+ # which frames get dumped first.. e.g. the most important frames (with the
1104
+ # most important information) should be dumped first..
1105
+ #
1077
1106
 
1078
1107
  public
1079
1108
  def dump
@@ -1083,7 +1112,8 @@ module ID3
1083
1112
  self.each { |framename,framedata|
1084
1113
  data << framedata.dump
1085
1114
  }
1086
- # add some padding perhaps
1115
+ # add some padding perhaps 32 bytes (should be defined by the user!)
1116
+ # NOTE: I noticed that iTunes adds excessive amounts of padding
1087
1117
  data << "\0" * 32
1088
1118
 
1089
1119
  # calculate the complete length of the data-section
@@ -1107,37 +1137,6 @@ module ID3
1107
1137
  # dumps ID3v2 frames into a binary array
1108
1138
  # allows to modify frame's contents if the frame was decoded..
1109
1139
  #
1110
- # NOTE: right now the class Frame is derived from Hash, which is wrong..
1111
- # It should really be derived from something like RestrictedOrderedHash
1112
- # ... a new class, which preserves the order of keys, and which does
1113
- # strict checking that all keys are present and reference correct values!
1114
- # e.g. frames["COMMENT"]
1115
- # ==> {"encoding"=>Byte, "language"=>Chars3, "text1"=>String, "text2"=>String}
1116
- #
1117
- # e.g. user should be able to create a new frame , like:
1118
- # tag2.frames["COMMENT"] = "right side"
1119
- #
1120
- # and the following checks should be done:
1121
- #
1122
- # 1) if "COMMENT" is a correct key for tag2
1123
- # 2) if the "right side" contains the correct keys
1124
- # 3) if the "right side" contains the correct value for each key
1125
- #
1126
- # In the simplest case, the "right side" might be just a string,
1127
- # but for most FrameTypes, it's a complex datastructure.. and we need
1128
- # to check it for correctness before doing the assignment..
1129
- #
1130
- # NOTE2: the class Tag2 should have hash-like accessor functions to let the user
1131
- # easily access frames and their contents..
1132
- #
1133
- # e.g. tag2[framename] would really access tag2.frames[framename]
1134
- #
1135
- # and if that works, we can make tag2.frames private and hidden!
1136
- #
1137
- # This means, that when we generate the parse and dump routines dynamically,
1138
- # we may want to create the corresponding accessor methods for Tag2 class
1139
- # as well...? or are generic ones enough?
1140
- #
1141
1140
 
1142
1141
  class Frame < RestrictedOrderedHash
1143
1142
 
@@ -1181,11 +1180,7 @@ module ID3
1181
1180
  end
1182
1181
  EOB
1183
1182
 
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
1183
+ @rawflags = flags.to_i # preserve the raw flags (for debugging only)
1189
1184
 
1190
1185
  if (flags.to_i & FRAME_HEADER_FLAG_MASK[@version] != 0)
1191
1186
  # in this case we need to skip parsing the frame... and skip to the next one...
@@ -1223,7 +1218,7 @@ module ID3
1223
1218
  vars2 = vars
1224
1219
  end
1225
1220
 
1226
- values = packing.call(self.rawdata)
1221
+ values = self.rawdata.unpack(packing)
1227
1222
  vars.each { |key|
1228
1223
  self[key] = values.shift
1229
1224
  }
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.1
7
- date: 2008-08-16 00:00:00 -07:00
8
- summary: id3-0.4.1 - ID3 tag library for Ruby http://www.unixgods.org/~tilo/Ruby/ID3
6
+ version: 0.5.0
7
+ date: 2008-08-24 00:00:00 -07:00
8
+ summary: A native ID3 tag library for Ruby, which does not depend on architecture-dependent C-libraries. It supports reading and writing ID3-tag versions 1.0, 1.1, and 2.2.x, 2,3.x, 2,4.x\n http://www.unixgods.org/~tilo/Ruby/ID3
9
9
  require_paths:
10
10
  - lib
11
11
  email: tools@unixgods.org