ruby-mp3info 0.6.14 → 0.6.15

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 (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