ruby-mp3info 0.6.14 → 0.6.15

Sign up to get free protection for your applications and to get access to all the features.
Files changed (5) hide show
  1. data/.gemtest +0 -0
  2. data/History.txt +4 -0
  3. data/lib/mp3info.rb +123 -79
  4. data/test/test_ruby-mp3info.rb +75 -23
  5. metadata +13 -30
File without changes
@@ -1,3 +1,7 @@
1
+ === 0.6.15 / 2011-07-18
2
+
3
+ * support for StringIO as input (thanks to Edd Parris)
4
+
1
5
  === 0.6.14 / 2011-06-17
2
6
 
3
7
  * Added a check for nil that was seen causing problems when processing files. (thanks to Carl Hall)
@@ -17,7 +17,7 @@ end
17
17
 
18
18
  class Mp3Info
19
19
 
20
- VERSION = "0.6.14"
20
+ VERSION = "0.6.15"
21
21
 
22
22
  LAYER = [ nil, 3, 2, 1]
23
23
  BITRATE = {
@@ -155,22 +155,45 @@ class Mp3Info
155
155
  # "close" method.
156
156
  attr_accessor(:tag2)
157
157
 
158
- # the original filename
158
+ # the original filename unless used with a StringIO
159
159
  attr_reader(:filename)
160
160
 
161
- # Test the presence of an id3v1 tag in file +filename+
162
- def self.hastag1?(filename)
163
- File.open(filename,"rb") { |f|
164
- f.seek(-TAG1_SIZE, File::SEEK_END)
165
- f.read(3) == "TAG"
166
- }
161
+ # Test the presence of an id3v1 tag in file or StringIO +filename_or_io+
162
+ def self.hastag1?(filename_or_io)
163
+ if filename_or_io.is_a?(StringIO)
164
+ io = filename_or_io
165
+ io.rewind
166
+ else
167
+ io = File.new(filename_or_io, "rb")
168
+ end
169
+
170
+ hastag1 = false
171
+ begin
172
+ io.seek(-TAG1_SIZE, File::SEEK_END)
173
+ hastag1 = io.read(3) == "TAG"
174
+ ensure
175
+ io.close if io.is_a?(File)
176
+ end
177
+ hastag1
167
178
  end
168
179
 
169
- # Test the presence of an id3v2 tag in file +filename+
170
- def self.hastag2?(filename)
171
- File.open(filename,"rb") { |f|
172
- f.read(3) == "ID3"
173
- }
180
+ # Test the presence of an id3v2 tag in file or StringIO +filename_or_io+
181
+ def self.hastag2?(filename_or_io)
182
+ if filename_or_io.is_a?(StringIO)
183
+ io = filename_or_io
184
+ io.rewind
185
+ else
186
+ io = File.new(filename_or_io,"rb")
187
+ end
188
+
189
+ hastag2 = false
190
+
191
+ begin
192
+ hastag2 = io.read(3) == "ID3"
193
+ ensure
194
+ io.close if io.is_a?(File)
195
+ end
196
+ hastag2
174
197
  end
175
198
 
176
199
  # Remove id3v1 tag from +filename+
@@ -193,24 +216,38 @@ class Mp3Info
193
216
  # Specify :parse_tags => false to disable the processing
194
217
  # of the tags (read and write).
195
218
  # Specify :parse_mp3 => false to disable processing of the mp3
196
- def initialize(filename, options = {})
219
+ def initialize(filename_or_io, options = {})
197
220
  warn("#{self.class}::new() does not take block; use #{self.class}::open() instead") if block_given?
198
- @filename = filename
221
+ @filename_or_io = filename_or_io
199
222
  options = {:parse_mp3 => true, :parse_tags => true}.update(options)
200
223
  @tag_parsing_enabled = options.delete(:parse_tags)
201
224
  @mp3_parsing_enabled = options.delete(:parse_mp3)
202
225
  @id3v2_options = options
203
226
  reload
204
227
  end
205
-
228
+
206
229
  # reload (or load for the first time) the file from disk
207
230
  def reload
208
- raise(Mp3InfoError, "empty file") unless File.size?(@filename)
209
-
210
231
  @header = {}
232
+
233
+ if @filename_or_io.is_a?(String)
234
+ @io_is_a_file = true
235
+ @io = File.new(@filename_or_io, "rb")
236
+ @io_size = @io.stat.size
237
+ @filename = @filename_or_io
238
+ elsif @filename_or_io.is_a?(StringIO)
239
+ @io_is_a_file = false
240
+ @io = @filename_or_io
241
+ @io_size = @io.size
242
+ @filename = nil
243
+ end
244
+
245
+ if @io_size == 0
246
+ raise(Mp3InfoError, "empty file or IO")
247
+ end
211
248
 
212
- @file = File.new(filename, "rb")
213
- @file.extend(Mp3FileMethods)
249
+
250
+ @io.extend(Mp3FileMethods)
214
251
  @tag1 = @tag = @tag1_orig = @tag_orig = {}
215
252
  @tag1.extend(HashKeys)
216
253
  @tag2 = ID3v2.new(@id3v2_options)
@@ -253,7 +290,9 @@ class Mp3Info
253
290
  end
254
291
 
255
292
  ensure
256
- @file.close
293
+ if @io_is_a_file
294
+ @io.close
295
+ end
257
296
  end
258
297
  end
259
298
 
@@ -302,6 +341,7 @@ class Mp3Info
302
341
 
303
342
  # write to another filename at close()
304
343
  def rename(new_filename)
344
+ raise(Mp3InfoError, "cannot rename an IO") unless @io_is_a_file
305
345
  @filename = new_filename
306
346
  end
307
347
 
@@ -311,7 +351,7 @@ class Mp3Info
311
351
  # [position_in_the_file, length_of_the_data]
312
352
  def audio_content
313
353
  pos = 0
314
- length = File.size(@filename)
354
+ length = @io_size
315
355
  if hastag1?
316
356
  length -= TAG1_SIZE
317
357
  end
@@ -328,8 +368,10 @@ class Mp3Info
328
368
  end
329
369
 
330
370
  # Flush pending modifications to tags and close the file
371
+ # not used when source IO is a StringIO
331
372
  def close
332
373
  puts "close" if $DEBUG
374
+ return unless @io_is_a_file
333
375
  if !@tag_parsing_enabled
334
376
  return
335
377
  end
@@ -352,12 +394,12 @@ class Mp3Info
352
394
 
353
395
  if @tag1 != @tag1_orig
354
396
  puts "@tag1 has changed" if $DEBUG
355
- raise(Mp3InfoError, "file is not writable") unless File.writable?(@filename)
397
+ raise(Mp3InfoError, "file is not writable") unless File.writable?(@filename_or_io)
356
398
  #@tag1_orig.update(@tag1)
357
399
  @tag1_orig = @tag1.dup
358
- File.open(@filename, 'rb+') do |file|
400
+ File.open(@filename_or_io, 'rb+') do |file|
359
401
  if @tag1_orig.empty?
360
- newsize = file.stat.size - TAG1_SIZE
402
+ newsize = @io_size - TAG1_SIZE
361
403
  file.truncate(newsize)
362
404
  else
363
405
  file.seek(-TAG1_SIZE, File::SEEK_END)
@@ -384,21 +426,21 @@ class Mp3Info
384
426
 
385
427
  if @tag2.changed?
386
428
  puts "@tag2 has changed" if $DEBUG
387
- raise(Mp3InfoError, "file is not writable") unless File.writable?(@filename)
429
+ raise(Mp3InfoError, "file is not writable") unless File.writable?(@filename_or_io)
388
430
  tempfile_name = nil
389
- File.open(@filename, 'rb+') do |file|
431
+ File.open(@filename_or_io, 'rb+') do |file|
390
432
  #if tag2 already exists, seek to end of it
391
433
  if @tag2.parsed?
392
434
  file.seek(@tag2.io_position)
393
435
  end
394
- # if @file.read(3) == "ID3"
395
- # version_maj, version_min, flags = @file.read(3).unpack("CCB4")
436
+ # if @io.read(3) == "ID3"
437
+ # version_maj, version_min, flags = @io.read(3).unpack("CCB4")
396
438
  # unsync, ext_header, experimental, footer = (0..3).collect { |i| flags[i].chr == '1' }
397
- # tag2_len = @file.get_syncsafe
398
- # @file.seek(@file.get_syncsafe - 4, IO::SEEK_CUR) if ext_header
399
- # @file.seek(tag2_len, IO::SEEK_CUR)
439
+ # tag2_len = @io.get_syncsafe
440
+ # @io.seek(@io.get_syncsafe - 4, IO::SEEK_CUR) if ext_header
441
+ # @io.seek(tag2_len, IO::SEEK_CUR)
400
442
  # end
401
- tempfile_name = @filename + ".tmp"
443
+ tempfile_name = @filename_or_io + ".tmp"
402
444
  File.open(tempfile_name, "wb") do |tempfile|
403
445
  unless @tag2.empty?
404
446
  tempfile.write(@tag2.to_bin)
@@ -410,13 +452,14 @@ class Mp3Info
410
452
  end
411
453
  end
412
454
  end
413
- File.rename(tempfile_name, @filename)
455
+ File.rename(tempfile_name, @filename_or_io)
414
456
  end
415
457
  end
416
458
 
417
459
  # close and reopen the file, i.e. commit changes to disk and
418
- # reload it
460
+ # reload it (only works with "true" files, not StringIO ones)
419
461
  def flush
462
+ return unless @io_is_a_file
420
463
  close
421
464
  reload
422
465
  end
@@ -434,16 +477,14 @@ class Mp3Info
434
477
  # counter, or whatever you like ;) +frame+ is a hash with the following keys:
435
478
  # :layer, :bitrate, :samplerate, :mpeg_version, :padding and :size (in bytes)
436
479
  def each_frame
437
- File.open(@filename, 'rb') do |file|
438
- file.seek(@first_frame_pos, File::SEEK_SET)
439
- loop do
440
- head = file.read(4).unpack("N").first
441
- frame = Mp3Info.get_frames_infos(head)
442
- file.seek(frame[:size] -4, File::SEEK_CUR)
443
- yield frame
444
- #puts "frame #{frame_count} len #{frame[:length]} br #{frame[:bitrate]} @file.pos #{@file.pos}"
445
- break if file.eof?
446
- end
480
+ @io.seek(@first_frame_pos, File::SEEK_SET)
481
+ loop do
482
+ head = @io.read(4).unpack("N").first
483
+ frame = Mp3Info.get_frames_infos(head)
484
+ @io.seek(frame[:size] -4, File::SEEK_CUR)
485
+ yield frame
486
+ #puts "frame #{frame_count} len #{frame[:length]} br #{frame[:bitrate]} @io.pos #{@io.pos}"
487
+ break if @io.eof?
447
488
  end
448
489
  end
449
490
 
@@ -481,49 +522,50 @@ private
481
522
  :size => size }
482
523
  end
483
524
 
484
- ### parses the id3 tags of the currently open @file
525
+ ### parses the id3 tags of the currently open @io
485
526
  def parse_tags
486
- return if @file.stat.size < TAG1_SIZE # file is too small
527
+ return if @io_size < TAG1_SIZE # file is too small
528
+
487
529
  @tag1_parsed = false
488
- @file.seek(0)
489
- f3 = @file.read(3)
530
+ @io.seek(0)
531
+ f3 = @io.read(3)
490
532
  # v1 tag at beginning
491
533
  if f3 == "TAG"
492
534
  gettag1
493
535
  @tag1_parsed = true
494
536
  end
495
537
 
496
- @tag2.from_io(@file) if f3 == "ID3" # v2 tag at beginning
538
+ @tag2.from_io(@io) if f3 == "ID3" # v2 tag at beginning
497
539
 
498
540
  unless @tag1_parsed # v1 tag at end
499
541
  # this preserves the file pos if tag2 found, since gettag2 leaves
500
542
  # the file at the best guess as to the first MPEG frame
501
543
  pos = (@tag2.io_position || 0)
502
544
  # seek to where id3v1 tag should be
503
- @file.seek(-TAG1_SIZE, IO::SEEK_END)
504
- if @file.read(3) == "TAG"
545
+ @io.seek(-TAG1_SIZE, IO::SEEK_END)
546
+ if @io.read(3) == "TAG"
505
547
  gettag1
506
548
  end
507
- @file.seek(pos)
549
+ @io.seek(pos)
508
550
  end
509
551
  end
510
552
 
511
- ### gets id3v1 tag information from @file
512
- ### assumes @file is pointing to char after "TAG" id
553
+ ### gets id3v1 tag information from @io
554
+ ### assumes @io is pointing to char after "TAG" id
513
555
  def gettag1
514
556
  @tag1_parsed = true
515
- @tag1["title"] = @file.read(30).unpack("A*").first
516
- @tag1["artist"] = @file.read(30).unpack("A*").first
517
- @tag1["album"] = @file.read(30).unpack("A*").first
518
- year_t = @file.read(4).to_i
557
+ @tag1["title"] = @io.read(30).unpack("A*").first
558
+ @tag1["artist"] = @io.read(30).unpack("A*").first
559
+ @tag1["album"] = @io.read(30).unpack("A*").first
560
+ year_t = @io.read(4).to_i
519
561
  @tag1["year"] = year_t unless year_t == 0
520
- comments = @file.read(30)
562
+ comments = @io.read(30)
521
563
  if comments.getbyte(-2) == 0
522
564
  @tag1["tracknum"] = comments.getbyte(-1).to_i
523
565
  comments.chop! #remove the last char
524
566
  end
525
567
  @tag1["comments"] = comments.unpack("A*").first
526
- @tag1["genre"] = @file.getbyte
568
+ @tag1["genre"] = @io.getbyte
527
569
  @tag1["genre_s"] = GENRES[@tag1["genre"]] || ""
528
570
 
529
571
  # clear empty tags
@@ -532,29 +574,30 @@ private
532
574
  @tag1.delete("tracknum") if @tag1["tracknum"] == 0
533
575
  end
534
576
 
535
- ### reads through @file from current pos until it finds a valid MPEG header
577
+ ### reads through @io from current pos until it finds a valid MPEG header
536
578
  ### returns the MPEG header as FixNum
537
579
  def find_next_frame
538
- # @file will now be sitting at the best guess for where the MPEG frame is.
580
+ # @io will now be sitting at the best guess for where the MPEG frame is.
539
581
  # It should be at byte 0 when there's no id3v2 tag.
540
582
  # It should be at the end of the id3v2 tag or the zero padding if there
541
583
  # is a id3v2 tag.
542
- #dummyproof = @file.stat.size - @file.pos => WAS TOO MUCH
543
- dummyproof = [ @file.stat.size - @file.pos, 2000000 ].min
584
+ #dummyproof = @io.stat.size - @io.pos => WAS TOO MUCH
585
+
586
+ dummyproof = [ @io_size - @io.pos, 2000000 ].min
544
587
  dummyproof.times do |i|
545
- if @file.getbyte == 0xff
546
- data = @file.read(3)
547
- raise(Mp3InfoError, "end of file reached") if @file.eof?
588
+ if @io.getbyte == 0xff
589
+ data = @io.read(3)
590
+ raise(Mp3InfoError, "end of file reached") if @io.eof?
548
591
  head = 0xff000000 + (data.getbyte(0) << 16) + (data.getbyte(1) << 8) + data.getbyte(2)
549
592
  begin
550
593
  Mp3Info.get_frames_infos(head)
551
594
  return head
552
595
  rescue Mp3InfoInternalError
553
- @file.seek(-3, IO::SEEK_CUR)
596
+ @io.seek(-3, IO::SEEK_CUR)
554
597
  end
555
598
  end
556
599
  end
557
- if @file.eof?
600
+ if @io.eof?
558
601
  raise Mp3InfoError, "cannot find a valid frame: got EOF"
559
602
  else
560
603
  raise Mp3InfoError, "cannot find a valid frame after reading #{dummyproof} bytes"
@@ -583,7 +626,7 @@ private
583
626
  head = nil
584
627
  5.times do
585
628
  head = find_next_frame()
586
- @first_frame_pos = @file.pos - 4
629
+ @first_frame_pos = @io.pos - 4
587
630
  current_frame = Mp3Info.get_frames_infos(head)
588
631
  @mpeg_version = current_frame[:mpeg_version]
589
632
  @layer = current_frame[:layer]
@@ -608,20 +651,20 @@ private
608
651
  (@channel_num == 3 ? 17 : 32) :
609
652
  (@channel_num == 3 ? 9 : 17)
610
653
 
611
- @file.seek(seek, IO::SEEK_CUR)
654
+ @io.seek(seek, IO::SEEK_CUR)
612
655
 
613
- vbr_head = @file.read(4)
656
+ vbr_head = @io.read(4)
614
657
  if vbr_head == "Xing"
615
658
  puts "Xing header (VBR) detected" if $DEBUG
616
- flags = @file.get32bits
659
+ flags = @io.get32bits
617
660
  stream_size = frame_count = 0
618
- flags[1] == 1 and frame_count = @file.get32bits
619
- flags[2] == 1 and stream_size = @file.get32bits
661
+ flags[1] == 1 and frame_count = @io.get32bits
662
+ flags[2] == 1 and stream_size = @io.get32bits
620
663
  puts "#{frame_count} frames" if $DEBUG
621
664
  raise(Mp3InfoError, "bad VBR header") if frame_count.zero?
622
665
  # currently this just skips the TOC entries if they're found
623
- @file.seek(100, IO::SEEK_CUR) if flags[0] == 1
624
- #@vbr_quality = @file.get32bits if flags[3] == 1
666
+ @io.seek(100, IO::SEEK_CUR) if flags[0] == 1
667
+ #@vbr_quality = @io.get32bits if flags[3] == 1
625
668
 
626
669
  samples_per_frame = SAMPLES_PER_FRAME[@layer][@mpeg_version]
627
670
  @length = frame_count * samples_per_frame / Float(@samplerate)
@@ -630,7 +673,8 @@ private
630
673
  @vbr = true
631
674
  else
632
675
  # for cbr, calculate duration with the given bitrate
633
- stream_size = @file.stat.size - (hastag1? ? TAG1_SIZE : 0) - (@tag2.io_position || 0)
676
+
677
+ stream_size = @io_size - (hastag1? ? TAG1_SIZE : 0) - (@tag2.io_position || 0)
634
678
  @length = ((stream_size << 3)/1000.0)/@bitrate
635
679
  # read the first 100 frames and decide if the mp3 is vbr and needs full scan
636
680
  begin
@@ -10,6 +10,8 @@ require "tempfile"
10
10
  require "zlib"
11
11
  require "yaml"
12
12
 
13
+ system("which id3v2 > /dev/null") || raise("id3v2 not found")
14
+
13
15
  class Mp3InfoTest < Test::Unit::TestCase
14
16
 
15
17
  TEMP_FILE = File.join(File.dirname(__FILE__), "test_mp3info.mp3")
@@ -86,21 +88,8 @@ class Mp3InfoTest < Test::Unit::TestCase
86
88
  end
87
89
 
88
90
  def test_detected_info
89
- Mp3Info.open(TEMP_FILE) do |info|
90
- assert_equal(1, info.mpeg_version)
91
- assert_equal(3, info.layer)
92
- assert_equal(false, info.vbr)
93
- assert_equal(128, info.bitrate)
94
- assert_equal("JStereo", info.channel_mode)
95
- assert_equal(44100, info.samplerate)
96
- assert_equal(0.1305625, info.length)
97
- assert_equal({:original => true,
98
- :error_protection => false,
99
- :padding => false,
100
- :emphasis => 0,
101
- :private => true,
102
- :mode_extension => 2,
103
- :copyright => false}, info.header)
91
+ Mp3Info.open(TEMP_FILE) do |mp3|
92
+ assert_mp3_info_are_ok(mp3)
104
93
  end
105
94
  end
106
95
 
@@ -167,13 +156,23 @@ class Mp3InfoTest < Test::Unit::TestCase
167
156
  end
168
157
 
169
158
  def test_removetag2
170
- w = write_temp_file({"TIT2" => "sdfqdsf"})
159
+ w = write_tag2_to_temp_file({"TIT2" => "sdfqdsf"})
171
160
 
172
161
  assert( Mp3Info.hastag2?(TEMP_FILE) )
173
162
  Mp3Info.removetag2(TEMP_FILE)
174
163
  assert( ! Mp3Info.hastag2?(TEMP_FILE) )
175
164
  end
176
165
 
166
+ def test_hastags
167
+ Mp3Info.open(TEMP_FILE) do |info|
168
+ info.tag1 = @tag
169
+ end
170
+ assert(Mp3Info.hastag1?(TEMP_FILE))
171
+
172
+ written_tag = write_tag2_to_temp_file(DUMMY_TAG2)
173
+ assert(Mp3Info.hastag2?(TEMP_FILE))
174
+ end
175
+
177
176
  def test_universal_tag
178
177
  2.times do
179
178
  tag = {"title" => "title"}
@@ -200,7 +199,7 @@ class Mp3InfoTest < Test::Unit::TestCase
200
199
  end
201
200
 
202
201
  def test_id3v2_version
203
- written_tag = write_temp_file(DUMMY_TAG2)
202
+ written_tag = write_tag2_to_temp_file(DUMMY_TAG2)
204
203
  assert_equal( "2.#{ID3v2::WRITE_VERSION}.0", written_tag.version )
205
204
  end
206
205
 
@@ -215,7 +214,7 @@ class Mp3InfoTest < Test::Unit::TestCase
215
214
  end
216
215
 
217
216
  def test_id3v2_basic
218
- w = write_temp_file(DUMMY_TAG2)
217
+ w = write_tag2_to_temp_file(DUMMY_TAG2)
219
218
  assert_equal(DUMMY_TAG2, w)
220
219
  id3v2_prog_test(DUMMY_TAG2, w)
221
220
  end
@@ -254,13 +253,13 @@ class Mp3InfoTest < Test::Unit::TestCase
254
253
  tag[k] = random_string(50)
255
254
  end
256
255
 
257
- got_tag = write_temp_file(tag)
256
+ got_tag = write_tag2_to_temp_file(tag)
258
257
  assert_equal(tag, got_tag)
259
258
  end
260
259
 
261
260
  def test_id3v2_bigtag
262
261
  tag = {"APIC" => random_string(1024) }
263
- assert_equal(tag, write_temp_file(tag))
262
+ assert_equal(tag, write_tag2_to_temp_file(tag))
264
263
  end
265
264
 
266
265
  def test_infinite_loop_on_seek_to_v2_end
@@ -270,7 +269,7 @@ class Mp3InfoTest < Test::Unit::TestCase
270
269
  def test_leading_char_gets_chopped
271
270
  tag2 = DUMMY_TAG2.dup
272
271
  tag2["WOAR"] = "http://foo.bar"
273
- w = write_temp_file(tag2)
272
+ w = write_tag2_to_temp_file(tag2)
274
273
  assert_equal("http://foo.bar", w["WOAR"])
275
274
 
276
275
  system(%(id3v2 --WOAR "http://foo.bar" "#{TEMP_FILE}"))
@@ -465,7 +464,7 @@ class Mp3InfoTest < Test::Unit::TestCase
465
464
  end
466
465
 
467
466
  def test_parse_tags_disabled
468
- write_temp_file(DUMMY_TAG2)
467
+ write_tag2_to_temp_file(DUMMY_TAG2)
469
468
  Mp3Info.open(TEMP_FILE, :parse_tags => false) do |mp3|
470
469
  assert mp3.tag.empty?
471
470
  assert mp3.tag1.empty?
@@ -480,6 +479,34 @@ class Mp3InfoTest < Test::Unit::TestCase
480
479
  end
481
480
  end
482
481
 
482
+ def test_string_io
483
+ io = load_string_io
484
+ Mp3Info.open(io) do |mp3|
485
+ assert_mp3_info_are_ok(mp3)
486
+ end
487
+ end
488
+
489
+ def test_trying_to_rename_a_stringio_should_raise_an_error
490
+ io = load_string_io
491
+ Mp3Info.open(io) do |mp3|
492
+ assert_raises(Mp3InfoError) do
493
+ mp3.rename("whatever_filename_is_error_should_be_raised.mp3")
494
+ end
495
+ end
496
+ end
497
+
498
+ def test_hastag_class_methods_with_a_stringio
499
+ Mp3Info.open(TEMP_FILE) do |info|
500
+ info.tag1 = @tag
501
+ end
502
+ io = load_string_io
503
+ assert(Mp3Info.hastag1?(io))
504
+
505
+ written_tag = write_tag2_to_temp_file(DUMMY_TAG2)
506
+ io = load_string_io
507
+ assert(Mp3Info.hastag2?(io))
508
+ end
509
+
483
510
  def compute_audio_content_mp3_digest(mp3)
484
511
  pos, size = mp3.audio_content
485
512
  data = File.open(mp3.filename) do |f|
@@ -489,7 +516,7 @@ class Mp3InfoTest < Test::Unit::TestCase
489
516
  Digest::MD5.new.update(data).hexdigest
490
517
  end
491
518
 
492
- def write_temp_file(tag)
519
+ def write_tag2_to_temp_file(tag)
493
520
  Mp3Info.open(TEMP_FILE) do |mp3|
494
521
  mp3.tag2.update(tag)
495
522
  end
@@ -503,6 +530,31 @@ class Mp3InfoTest < Test::Unit::TestCase
503
530
  out
504
531
  end
505
532
 
533
+ def assert_mp3_info_are_ok(mp3)
534
+ assert_equal(1, mp3.mpeg_version)
535
+ assert_equal(3, mp3.layer)
536
+ assert_equal(false, mp3.vbr)
537
+ assert_equal(128, mp3.bitrate)
538
+ assert_equal("JStereo", mp3.channel_mode)
539
+ assert_equal(44100, mp3.samplerate)
540
+ assert_equal(0.1305625, mp3.length)
541
+ assert_equal({:original => true,
542
+ :error_protection => false,
543
+ :padding => false,
544
+ :emphasis => 0,
545
+ :private => true,
546
+ :mode_extension => 2,
547
+ :copyright => false}, mp3.header)
548
+ end
549
+
550
+ def load_string_io(filename = TEMP_FILE)
551
+ io = StringIO.new
552
+ data = File.read(filename)
553
+ io.write(data)
554
+ io.rewind
555
+ io
556
+ end
557
+
506
558
  =begin
507
559
 
508
560
  def test_encoder
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-mp3info
3
3
  version: !ruby/object:Gem::Version
4
- hash: 27
4
+ hash: 25
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 6
9
- - 14
10
- version: 0.6.14
9
+ - 15
10
+ version: 0.6.15
11
11
  platform: ruby
12
12
  authors:
13
13
  - Guillaume Pierronnet
@@ -15,40 +15,23 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-06-17 00:00:00 Z
18
+ date: 2011-07-18 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
- name: hoe-yard
21
+ name: hoe
22
22
  prerelease: false
23
23
  requirement: &id001 !ruby/object:Gem::Requirement
24
24
  none: false
25
25
  requirements:
26
- - - ">="
26
+ - - ~>
27
27
  - !ruby/object:Gem::Version
28
- hash: 31
28
+ hash: 23
29
29
  segments:
30
- - 0
31
- - 1
32
30
  - 2
33
- version: 0.1.2
31
+ - 10
32
+ version: "2.10"
34
33
  type: :development
35
34
  version_requirements: *id001
36
- - !ruby/object:Gem::Dependency
37
- name: hoe
38
- prerelease: false
39
- requirement: &id002 !ruby/object:Gem::Requirement
40
- none: false
41
- requirements:
42
- - - ">="
43
- - !ruby/object:Gem::Version
44
- hash: 47
45
- segments:
46
- - 2
47
- - 8
48
- - 0
49
- version: 2.8.0
50
- type: :development
51
- version_requirements: *id002
52
35
  description: |-
53
36
  * written in pure ruby
54
37
  * read low-level informations like bitrate, length, samplerate, etc...
@@ -107,14 +90,14 @@ files:
107
90
  - lib/mp3info/extension_modules.rb
108
91
  - lib/mp3info/id3v2.rb
109
92
  - test/test_ruby-mp3info.rb
93
+ - .gemtest
110
94
  homepage:
111
95
  licenses: []
112
96
 
113
97
  post_install_message:
114
98
  rdoc_options:
115
- - --title
116
- - RubyMp3info Documentation
117
- - --quiet
99
+ - --main
100
+ - README.txt
118
101
  require_paths:
119
102
  - lib
120
103
  required_ruby_version: !ruby/object:Gem::Requirement
@@ -138,7 +121,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
138
121
  requirements: []
139
122
 
140
123
  rubyforge_project: ruby-mp3info
141
- rubygems_version: 1.8.5
124
+ rubygems_version: 1.7.2
142
125
  signing_key:
143
126
  specification_version: 3
144
127
  summary: ruby-mp3info is a pure-ruby library to retrieve low level informations on mp3 files and manipulate id3v1 and id3v2 tags