id3 0.4.1 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
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