mp3file 0.0.4 → 1.0.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 239aaea4897a1eb4494c5a1668ef5a8ce3e40645
4
+ data.tar.gz: eeeadc21db81420c767b4dd89283d30a3fa17436
5
+ SHA512:
6
+ metadata.gz: f1ff36c98e1ad5c084664cad9cc85d5b3d9c31bfd18d559295a259876410d1f55bdc656a4bc0cf7065c5ce94fbd6db88621674b33127daed3158eeda557cf512
7
+ data.tar.gz: 1abdf307e37627eecb33a813c1f205ffcec20ea8678c3943dd1f5f80354baf96c47f2949bfa29f3ab850c740230ee29b0724a22cd12d95f505663123a3648304
@@ -0,0 +1,22 @@
1
+ # Auto detect text files and perform LF normalization
2
+ * text=auto
3
+
4
+ # Custom for Visual Studio
5
+ *.cs diff=csharp
6
+ *.sln merge=union
7
+ *.csproj merge=union
8
+ *.vbproj merge=union
9
+ *.fsproj merge=union
10
+ *.dbproj merge=union
11
+
12
+ # Standard to msysgit
13
+ *.doc diff=astextplain
14
+ *.DOC diff=astextplain
15
+ *.docx diff=astextplain
16
+ *.DOCX diff=astextplain
17
+ *.dot diff=astextplain
18
+ *.DOT diff=astextplain
19
+ *.pdf diff=astextplain
20
+ *.PDF diff=astextplain
21
+ *.rtf diff=astextplain
22
+ *.RTF diff=astextplain
@@ -0,0 +1 @@
1
+ mp3file
@@ -0,0 +1 @@
1
+ ruby-2.1
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- mp3file (0.0.4)
4
+ mp3file (1.0.0)
5
5
  bindata
6
6
 
7
7
  GEM
@@ -0,0 +1,14 @@
1
+ # Mp3file
2
+
3
+ This is a pure-Ruby MP3 metadata extractor. We use it to identify the
4
+ bitrate and duration of songs that people upload to [http://www.reverbnation.com].
5
+
6
+ It handles a bunch of things:
7
+ * ID3v1 tags
8
+ * ID3v2 tags (although it doesn't actually parse the frames)
9
+ * VBR files (with Xing headers)
10
+ * Multiple ID3v2 tags (because these exist in the wild)
11
+
12
+ Don't think of this as an example of good code. This is some of the
13
+ most terrible, ugly, brutally hacky code I think I've ever written. I
14
+ apologize to anyone who looks at it.
@@ -0,0 +1,80 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $LOAD_PATH << File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))
4
+ require 'mp3file'
5
+
6
+ ARGV.each do |file|
7
+ begin
8
+ mp3 = Mp3file::MP3File.new(file)
9
+
10
+ puts("File: #{mp3.file.path}")
11
+ puts(" Size: #{mp3.file_size} bytes Audio_size: #{mp3.audio_size} bytes")
12
+ puts(" #{mp3.mpeg_version} #{mp3.layer}")
13
+ puts(" Bitrate: #{mp3.bitrate} kbps Samplerate: #{mp3.samplerate} Hz Mode: #{mp3.mode}")
14
+ puts(" Duration: #{mp3.length} s")
15
+ puts(" Frames: #{mp3.num_frames} Samples: #{mp3.total_samples}")
16
+
17
+ header = mp3.first_header
18
+ puts(" First MPEG frame at #{mp3.first_header_offset} bytes:")
19
+ puts(" #{header.version} #{header.layer}")
20
+ puts(" Bitrate: #{header.bitrate} bps Samplerate: #{header.samplerate} Hz")
21
+ puts(" Mode: #{header.mode} Mode Extension: #{header.mode_extension} Emphasis: #{header.emphasis}")
22
+ puts(" CRC: #{header.has_crc} Padding: #{header.has_padding}")
23
+ puts(" Copyright: #{header.copyright} Original: #{header.original}")
24
+ puts(" Samples: #{header.samples} Frame size: #{header.frame_size} Side bytes: #{header.side_bytes}")
25
+
26
+ if mp3.xing_header
27
+ xing = mp3.xing_header
28
+ puts(" Xing header:")
29
+ puts(" Frames: #{xing.frames} Bytes: #{xing.bytes} Quality: #{xing.quality} TOC: #{xing.toc ? 'present' : 'not present'}")
30
+ end
31
+
32
+ if mp3.vbri_header
33
+ puts(" VBRI header!")
34
+ end
35
+
36
+ if mp3.id3v1tag?
37
+ tag = mp3.id3v1_tag
38
+ puts(" ID3v1 tag:")
39
+ puts(" Title: #{tag.title.inspect}")
40
+ puts(" Artist: #{tag.artist.inspect}")
41
+ puts(" Album: #{tag.album.inspect}")
42
+ puts(" Year: #{tag.year.inspect}")
43
+ puts(" Comment: #{tag.comment.inspect}")
44
+ puts(" Genre: #{tag.genre.inspect} (#{tag.genre_id.inspect})")
45
+ end
46
+
47
+ if mp3.id3v2tag?
48
+ tag = mp3.id3v2_tag
49
+ puts(" ID3v2 tag:")
50
+ puts(" Size: #{tag.size} bytes")
51
+ puts(" Version: #{tag.version.inspect}")
52
+ puts(" Unused byes: #{tag.unused_bytes.inspect}")
53
+ if !tag.frames.empty?
54
+ puts(" Frames:")
55
+ tag.frames.each do |frame|
56
+ puts(" ID: #{frame.frame_id.inspect} size: #{frame.frame_size}")
57
+ end
58
+ end
59
+ end
60
+
61
+ mp3.extra_id3v2_tags.each do |offset, tag2|
62
+ puts(" Extra ID3v2 tag:")
63
+ puts(" Offset: #{offset} bytes")
64
+ puts(" Size: #{tag2.size} bytes")
65
+ puts(" Version: #{tag2.version.inspect}")
66
+ puts(" Unused byes: #{tag2.unused_bytes.inspect}")
67
+ if !tag2.frames.empty?
68
+ puts(" Frames:")
69
+ tag2.frames.each do |frame|
70
+ puts(" ID: #{frame.frame_id.inspect} size: #{frame.frame_size}")
71
+ end
72
+ end
73
+ end
74
+
75
+ puts
76
+ rescue
77
+ $stderr.puts("Exception reading MP3 file %s: %s (%p)\n\t%s" %
78
+ [ file, $!.message, $!.class, $!.backtrace.join("\n\t") ])
79
+ end
80
+ end
@@ -2,7 +2,7 @@ module Mp3file
2
2
  class InvalidID3v1TagError < Mp3fileError; end
3
3
 
4
4
  class ID3v1Tag
5
- attr_accessor(:title, :artist, :album, :year, :comment, :track, :genre)
5
+ attr_accessor(:title, :artist, :album, :year, :comment, :track, :genre_id, :genre)
6
6
 
7
7
  class ID3v1TagFormat < BinData::Record
8
8
  string(:tag_id, :length => 3, :check_value => lambda { value == 'TAG' })
@@ -35,24 +35,38 @@ module Mp3file
35
35
  Samba Folklore Ballad Power\ Ballad Rhythmic\ Soul Freestyle Duet Punk\ Rock
36
36
  Drum\ Solo A\ capella Euro-House Dance\ Hall }
37
37
 
38
- def initialize(io)
39
- @tag = nil
38
+ def self.parse(io)
39
+ tag_data = nil
40
+
40
41
  begin
41
- @tag = ID3v1TagFormat.read(io)
42
+ tag_data = ID3v1TagFormat.read(io)
42
43
  rescue BinData::ValidityError => ve
43
44
  raise InvalidID3v1TagError, ve.message
44
45
  end
45
46
 
46
- @title = @tag.title.split("\x00").first
47
- @artist = @tag.artist.split("\x00").first
48
- @album = @tag.album.split("\x00").first
49
- @year = @tag.year
50
- split_comment = @tag.comment.split("\x00").reject { |s| s == '' }
47
+ if tag_data.nil?
48
+ nil
49
+ else
50
+ new.tap { |rv| rv.load_format(tag_data) }
51
+ end
52
+ end
53
+
54
+ def load_format(tag_data)
55
+ @title = tag_data.title.split("\x00").first
56
+ @artist = tag_data.artist.split("\x00").first
57
+ @album = tag_data.album.split("\x00").first
58
+ @year = tag_data.year
59
+ split_comment = tag_data.comment.split("\x00").reject { |s| s == '' }
51
60
  @comment = split_comment.first
52
61
  if split_comment.size > 1
53
62
  @track = split_comment.last.bytes.first
54
63
  end
55
- @genre = GENRES[@tag.genre_id]
64
+ @genre_id = tag_data.genre_id
65
+ @genre = GENRES[tag_data.genre_id]
66
+ end
67
+
68
+ def initialize
69
+ @title = @artist = @album = @year = @comment = @track = @genre_id = @genre = nil
56
70
  end
57
71
  end
58
72
  end
@@ -11,11 +11,11 @@ module Mp3file::ID3v2
11
11
  bit1(:tag_alter_preserve)
12
12
  bit1(:file_alter_preserve)
13
13
  bit1(:read_only)
14
- bit5(:unused1, :check_value => lambda { value == 0 })
14
+ bit5(:unused1) # , :check_value => lambda { value == 0 })
15
15
  bit1(:compression)
16
16
  bit1(:encryption)
17
17
  bit1(:has_group)
18
- bit5(:unused2, :check_value => lambda { value == 0 })
18
+ bit5(:unused2) # , :check_value => lambda { value == 0 })
19
19
  uint8(:encryption_type, :onlyif => lambda { encryption == 1 })
20
20
  uint8(:group_id, :onlyif => lambda { has_group == 1 })
21
21
  end
@@ -23,21 +23,24 @@ module Mp3file::ID3v2
23
23
  class ID3v240FrameHeaderFormat < BinData::Record
24
24
  string(:frame_id, :length => 4)
25
25
  uint32be(:frame_size)
26
- bit1(:unused1, :check_value => lambda { value == 0 })
26
+ bit1(:unused1) # , :check_value => lambda { value == 0 })
27
27
  bit1(:tag_alter_preserve)
28
28
  bit1(:file_alter_preserve)
29
29
  bit1(:read_only)
30
- bit4(:unused2, :check_value => lambda { value == 0 })
31
- bit1(:unused3, :check_value => lambda { value == 0 })
30
+
31
+ bit4(:unused2) # , :check_value => lambda { value == 0 })
32
+
33
+ bit1(:unused3) # , :check_value => lambda { value == 0 })
32
34
  bit1(:group)
33
- bit2(:unused4, :check_value => lambda { value == 0 })
35
+ bit2(:unused4) # , :check_value => lambda { value == 0 })
36
+
34
37
  bit1(:compression)
35
38
  bit1(:encryption)
36
39
  bit1(:unsynchronized)
37
40
  bit1(:data_length_indicator)
38
41
  end
39
42
 
40
- attr_reader(:frame_id, :size,
43
+ attr_reader(:frame_id, :header_size, :frame_size, :size,
41
44
  :preserve_on_altered_tag, :preserve_on_altered_file,
42
45
  :read_only, :compressed, :encrypted, :encryption_type,
43
46
  :group, :unsynchronized, :data_length)
@@ -57,8 +60,10 @@ module Mp3file::ID3v2
57
60
  begin
58
61
  if @tag.version >= ID3V2_2_0 && @tag.version < ID3V2_3_0
59
62
  header = ID3v220FrameHeaderFormat.read(io)
63
+ @header_size = 6
60
64
  elsif @tag.version >= ID3V2_3_0 && @tag.version < ID3V2_4_0
61
65
  header = ID3v230FrameHeaderFormat.read(io)
66
+ @header_size = 10
62
67
  @preserve_on_altered_tag = header.tag_alter_preserve == 1
63
68
  @preserve_on_altered_file = header.file_alter_preserve == 1
64
69
  @read_only = header.read_only == 1
@@ -72,13 +77,15 @@ module Mp3file::ID3v2
72
77
  end
73
78
  elsif @tag.version >= ID3V2_4_0
74
79
  header = ID3v240FrameHeaderFormat.read(io)
80
+ @header_size = 10
75
81
  end
76
82
  rescue BinData::ValidityError => ve
77
83
  raise InvalidID3v2TagError, ve.message
78
84
  end
79
85
 
80
86
  @frame_id = header.frame_id
81
- @size = BitPaddedInt.unpad_number(header.frame_size)
87
+ @frame_size = BitPaddedInt.unpad_number(header.frame_size)
88
+ @size = @header_size + @frame_size
82
89
  end
83
90
  end
84
91
  end
@@ -7,19 +7,53 @@ module Mp3file::ID3v2
7
7
  def_delegators(:@header, :version, :unsynchronized, :extended_header,
8
8
  :compression, :experimental, :footer)
9
9
 
10
- attr_reader(:header, :frames)
10
+ attr_reader(:header, :frames, :unused_bytes)
11
+
12
+ FRAME_HEADER_NAME_REGEX = /[A-Z][A-Z0-9]{2,3}/
11
13
 
12
14
  def initialize(io)
13
15
  @header = Header.new(io)
14
- @frames = []
16
+ load_frames(io)
17
+ used_bytes = @frames.inject(0) { |m, f| m += f.size }
18
+ @unused_bytes = @header.tag_size - used_bytes
15
19
  end
16
20
 
17
- def load_frames
21
+ def load_frames(io)
18
22
  @frames = []
23
+
24
+ data = io.read(@header.tag_size)
25
+ data.force_encoding("ASCII-8BIT")
26
+ offset = 0
27
+
28
+ frame_offset, frame = get_next_frame_header(data, offset)
29
+ while frame
30
+ @frames << frame
31
+ offset = frame_offset + frame.size
32
+ frame_offset, frame = get_next_frame_header(data, offset)
33
+ end
19
34
  end
20
35
 
21
36
  def size
22
37
  @header.tag_size + 10
23
38
  end
39
+
40
+ def get_next_frame_header(data, offset)
41
+ md = data.match(FRAME_HEADER_NAME_REGEX, offset)
42
+
43
+ while md
44
+ frame_offset = md.begin(0)
45
+ io = StringIO.new(data[frame_offset, 32])
46
+ frame = FrameHeader.new(io, self)
47
+
48
+ if frame.frame_id.to_s =~ FRAME_HEADER_NAME_REGEX
49
+ return [ frame_offset, frame ]
50
+ else
51
+ frame_offset = md.end(0) + 1
52
+ md = data.match(FRAME_HEADER_NAME_REGEX, frame_offset)
53
+ end
54
+ end
55
+
56
+ [ nil, nil ]
57
+ end
24
58
  end
25
59
  end
@@ -9,7 +9,7 @@ module Mp3file
9
9
  attr_reader(:mpeg_version, :layer, :bitrate, :samplerate, :mode)
10
10
  attr_reader(:num_frames, :total_samples, :length)
11
11
 
12
- attr_accessor(:id3v1_tag)
12
+ attr_accessor(:id3v1_tag, :id3v2_tag, :extra_id3v2_tags)
13
13
 
14
14
  def initialize(file_path)
15
15
  file_path = Pathname.new(file_path).expand_path if file_path.is_a?(String)
@@ -73,30 +73,57 @@ module Mp3file
73
73
 
74
74
  # Try to read an ID3v1 tag.
75
75
  @id3v1_tag = nil
76
- @file.seek(-128, IO::SEEK_END)
77
76
  begin
78
- @id3v1_tag = ID3v1Tag.new(@file)
79
- rescue InvalidID3v1TagError => e
77
+ @file.seek(-128, IO::SEEK_END)
78
+ @id3v1_tag = ID3v1Tag.parse(@file)
79
+ rescue Mp3file::InvalidID3v1TagError
80
80
  @id3v1_tag = nil
81
+ ensure
82
+ @file.seek(0, IO::SEEK_SET)
81
83
  end
82
- @file.seek(0, IO::SEEK_SET)
83
84
 
84
85
  # Try to detect an ID3v2 header.
85
- @id3v2_header = nil
86
+ @id3v2_tag = nil
86
87
  begin
87
- @id3v2_header = ID3v2::Header.new(@file)
88
- rescue ID3v2::InvalidID3v2TagError => e
89
- @id3v2_header = nil
88
+ @id3v2_tag = ID3v2::Tag.new(@file)
89
+ rescue ID3v2::InvalidID3v2TagError # => e
90
+ # $stderr.puts "Error parsing ID3v2 tag: %s\n\t%s" %
91
+ # [ e.message, e.backtrace.join("\n\t") ]
92
+ @id3v2_tag = nil
90
93
  @file.seek(0, IO::SEEK_SET)
91
94
  end
92
95
 
93
96
  # Skip past the ID3v2 header if it's present.
94
- if @id3v2_header
95
- @file.seek(@id3v2_header.tag_size + 10, IO::SEEK_SET)
97
+ if @id3v2_tag
98
+ @file.seek(@id3v2_tag.size, IO::SEEK_SET)
96
99
  end
97
100
 
98
- # Try to find the first MP3 header.
99
- @first_header_offset, @first_header = get_next_header(@file)
101
+ # Some files have more than one ID3v2 tag. If we can't find an
102
+ # MP3 header in the next 4k, try reading another ID3v2 tag and
103
+ # repeat.
104
+ @extra_id3v2_tags = []
105
+ begin
106
+ # Try to find the first MP3 header.
107
+ @first_header_offset, @first_header = get_next_header(@file)
108
+ rescue InvalidMP3FileError
109
+ end_of_tags = @id3v2_tag.size + @extra_id3v2_tags.map(&:last).map(&:size).reduce(:+).to_i
110
+ @file.seek(end_of_tags, IO::SEEK_SET)
111
+
112
+ tag = nil
113
+ begin
114
+ tag = ID3v2::Tag.new(@file)
115
+ rescue ID3v2::InvalidID3v2TagError
116
+ tag = nil
117
+ @file.seek(end_of_tags, IO::SEEK_SET)
118
+ end
119
+
120
+ if tag
121
+ @extra_id3v2_tags << [ end_of_tags, tag ]
122
+ retry
123
+ else
124
+ raise
125
+ end
126
+ end
100
127
 
101
128
  @mpeg_version = @first_header.version
102
129
  @layer = @first_header.layer
@@ -117,7 +144,7 @@ module Mp3file
117
144
  @file.seek(@first_header.side_bytes, IO::SEEK_CUR)
118
145
  begin
119
146
  @xing_header = XingHeader.new(@file)
120
- rescue InvalidXingHeaderError => ve
147
+ rescue InvalidXingHeaderError
121
148
  @file.seek(@first_header_offset + 4, IO::SEEK_CUR)
122
149
  end
123
150
 
@@ -155,7 +182,7 @@ module Mp3file
155
182
  begin
156
183
  header = MP3Header.new(file)
157
184
  header_offset = file.tell - 4
158
- rescue InvalidMP3HeaderError => e
185
+ rescue InvalidMP3HeaderError
159
186
  header_offset += 1
160
187
  if header_offset - initial_header_offset > 4096
161
188
  raise InvalidMP3FileError, "Could not find a valid MP3 header in the first 4096 bytes."
@@ -1,3 +1,3 @@
1
1
  module Mp3file
2
- VERSION = "0.0.4"
2
+ VERSION = "1.0.0"
3
3
  end
@@ -5,7 +5,7 @@ include CommonHelpers
5
5
 
6
6
  describe Mp3file::ID3v1Tag do
7
7
  it "rejects an ID3v1 tag if it doesn't begin with TAG" do
8
- lambda { Mp3file::ID3v1Tag.new(StringIO.new("\x00" * 128)) }.
8
+ lambda { Mp3file::ID3v1Tag.parse(StringIO.new("\x00" * 128)) }.
9
9
  should(raise_error(Mp3file::InvalidID3v1TagError))
10
10
  end
11
11
 
@@ -17,7 +17,7 @@ describe Mp3file::ID3v1Tag do
17
17
  year = "1996"
18
18
  comment = "This is a comment"; comment += "\x00" * (30 - comment.size)
19
19
  genre = 17.chr
20
- Mp3file::ID3v1Tag.new(StringIO.new('TAG' + title + artist + album + year + comment + genre))
20
+ Mp3file::ID3v1Tag.parse(StringIO.new('TAG' + title + artist + album + year + comment + genre))
21
21
  end
22
22
 
23
23
  its(:title) { should == 'Big Dipper' }
@@ -38,7 +38,7 @@ describe Mp3file::ID3v1Tag do
38
38
  comment = "This is a comment"; comment += "\x00" * (29 - comment.size)
39
39
  tracknum = 3.chr
40
40
  genre = 17.chr
41
- Mp3file::ID3v1Tag.new(StringIO.new('TAG' + title + artist + album + year + comment + tracknum + genre))
41
+ Mp3file::ID3v1Tag.parse(StringIO.new('TAG' + title + artist + album + year + comment + tracknum + genre))
42
42
  end
43
43
 
44
44
  its(:title) { should == 'Big Dipper' }
@@ -51,7 +51,7 @@ describe Mp3file::ID3v1Tag do
51
51
  end
52
52
 
53
53
  describe "When created with a blank ID3v1 tag" do
54
- subject { Mp3file::ID3v1Tag.new(StringIO.new("TAG" + ("\x00" * 125))) }
54
+ subject { Mp3file::ID3v1Tag.parse(StringIO.new("TAG" + ("\x00" * 125))) }
55
55
  its(:title) { should == nil }
56
56
  its(:artist) { should == nil }
57
57
  its(:album) { should == nil }
@@ -26,13 +26,13 @@ describe Mp3file::ID3v2::FrameHeader do
26
26
  context "with ID3v2.3 tags" do
27
27
  let(:tag) { Mp3file::ID3v2::Tag.new(StringIO.new("ID3\x03\x00\x00\x00\x00\x00\x00")) }
28
28
 
29
- describe("A header with invalid flag bits set") do
30
- it("Should raise an error") do
31
- io = StringIO.new("TIT2\x00\x00\x00\x09\x01\x00")
32
- lambda { Mp3file::ID3v2::FrameHeader.new(io, tag) }.
33
- should(raise_error(Mp3file::ID3v2::InvalidID3v2TagError))
34
- end
35
- end
29
+ # describe("A header with invalid flag bits set") do
30
+ # it("Should raise an error") do
31
+ # io = StringIO.new("TIT2\x00\x00\x00\x09\x01\x00")
32
+ # lambda { Mp3file::ID3v2::FrameHeader.new(io, tag) }.
33
+ # should(raise_error(Mp3file::ID3v2::InvalidID3v2TagError))
34
+ # end
35
+ # end
36
36
 
37
37
  describe("A 9-byte TIT2 frame header.") do
38
38
  subject { Mp3file::ID3v2::FrameHeader.new(StringIO.new("TIT2\x00\x00\x00\x09\x00\x00"), tag) }
@@ -68,12 +68,12 @@ describe Mp3file::ID3v2::FrameHeader do
68
68
  context "with ID3v2.4 tags" do
69
69
  let(:tag) { Mp3file::ID3v2::Tag.new(StringIO.new("ID3\x04\x00\x00\x00\x00\x00\x00")) }
70
70
 
71
- describe("A header with invalid flag bits set") do
72
- it("Should raise an error") do
73
- io = StringIO.new("TIT2\x00\x00\x00\x09\x01\x00")
74
- lambda { Mp3file::ID3v2::FrameHeader.new(io, tag) }.
75
- should(raise_error(Mp3file::ID3v2::InvalidID3v2TagError))
76
- end
77
- end
71
+ # describe("A header with invalid flag bits set") do
72
+ # it("Should raise an error") do
73
+ # io = StringIO.new("TIT2\x00\x00\x00\x09\x01\x00")
74
+ # lambda { Mp3file::ID3v2::FrameHeader.new(io, tag) }.
75
+ # should(raise_error(Mp3file::ID3v2::InvalidID3v2TagError))
76
+ # end
77
+ # end
78
78
  end
79
79
  end
@@ -5,11 +5,7 @@ include CommonHelpers
5
5
 
6
6
  describe Mp3file::ID3v2::Tag do
7
7
  describe "An empty tag" do
8
- subject do
9
- t = Mp3file::ID3v2::Tag.new(StringIO.new("ID3\x03\x00\x00\x00\x00\x00\x00"))
10
- t.load_frames
11
- t
12
- end
8
+ subject { Mp3file::ID3v2::Tag.new(StringIO.new("ID3\x03\x00\x00\x00\x00\x00\x00")) }
13
9
  its(:version) { should == Mp3file::ID3v2::ID3V2_3_0 }
14
10
  its(:unsynchronized) { should == false }
15
11
  its(:extended_header) { should == false }
@@ -70,7 +70,7 @@ describe Mp3file::MP3File do
70
70
 
71
71
  describe "A 96 kbps 34 kHz Joint Stereo CBR file with an ID3v2 tag" do
72
72
  subject { Mp3file::MP3File.new(fixture_file('bret_id3v2.mp3')) }
73
- # its(:id3v2tag?) { should == true }
73
+ its(:id3v2tag?) { should == true }
74
74
  its(:id3v1tag?) { should == false }
75
75
  its("file.path") { should == fixture_file('bret_id3v2.mp3').to_s }
76
76
  its("file.closed?") { should == true }
metadata CHANGED
@@ -1,62 +1,74 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mp3file
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
5
- prerelease:
4
+ version: 1.0.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Andrew Watts
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2011-08-02 00:00:00.000000000 -04:00
13
- default_executable:
11
+ date: 2014-11-05 00:00:00.000000000 Z
14
12
  dependencies:
15
13
  - !ruby/object:Gem::Dependency
16
14
  name: rspec
17
- requirement: &12412640 !ruby/object:Gem::Requirement
18
- none: false
15
+ requirement: !ruby/object:Gem::Requirement
19
16
  requirements:
20
- - - ! '>='
17
+ - - ">="
21
18
  - !ruby/object:Gem::Version
22
19
  version: '0'
23
20
  type: :development
24
21
  prerelease: false
25
- version_requirements: *12412640
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
26
27
  - !ruby/object:Gem::Dependency
27
28
  name: rake
28
- requirement: &12412220 !ruby/object:Gem::Requirement
29
- none: false
29
+ requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ! '>='
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
33
  version: '0'
34
34
  type: :development
35
35
  prerelease: false
36
- version_requirements: *12412220
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
37
41
  - !ruby/object:Gem::Dependency
38
42
  name: bindata
39
- requirement: &12449280 !ruby/object:Gem::Requirement
40
- none: false
43
+ requirement: !ruby/object:Gem::Requirement
41
44
  requirements:
42
- - - ! '>='
45
+ - - ">="
43
46
  - !ruby/object:Gem::Version
44
47
  version: '0'
45
48
  type: :runtime
46
49
  prerelease: false
47
- version_requirements: *12449280
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
48
55
  description: Reads MP3 headers and returns their information.
49
56
  email:
50
57
  - ahwatts@gmail.com
51
- executables: []
58
+ executables:
59
+ - mp3info
52
60
  extensions: []
53
61
  extra_rdoc_files: []
54
62
  files:
55
- - .gitignore
56
- - .rvmrc
63
+ - ".gitattributes"
64
+ - ".gitignore"
65
+ - ".ruby-gemset"
66
+ - ".ruby-version"
57
67
  - Gemfile
58
68
  - Gemfile.lock
69
+ - README.md
59
70
  - Rakefile
71
+ - bin/mp3info
60
72
  - doc/id3v2.2.0.txt
61
73
  - doc/id3v2.3.0.txt
62
74
  - doc/id3v2.4.0-frames.txt
@@ -90,29 +102,42 @@ files:
90
102
  - spec/mp3file/mp3_file_spec.rb
91
103
  - spec/mp3file/mp3_header_spec.rb
92
104
  - spec/mp3file/xing_header_spec.rb
93
- has_rdoc: true
94
105
  homepage: http://rubygems.org/gems/mp3file
95
106
  licenses: []
107
+ metadata: {}
96
108
  post_install_message:
97
109
  rdoc_options: []
98
110
  require_paths:
99
111
  - lib
100
112
  required_ruby_version: !ruby/object:Gem::Requirement
101
- none: false
102
113
  requirements:
103
- - - ! '>='
114
+ - - ">="
104
115
  - !ruby/object:Gem::Version
105
116
  version: '0'
106
117
  required_rubygems_version: !ruby/object:Gem::Requirement
107
- none: false
108
118
  requirements:
109
- - - ! '>='
119
+ - - ">="
110
120
  - !ruby/object:Gem::Version
111
121
  version: '0'
112
122
  requirements: []
113
123
  rubyforge_project: mp3file
114
- rubygems_version: 1.6.2
124
+ rubygems_version: 2.4.2
115
125
  signing_key:
116
- specification_version: 3
126
+ specification_version: 4
117
127
  summary: Reads MP3 headers and returns their information.
118
- test_files: []
128
+ test_files:
129
+ - spec/common_helpers.rb
130
+ - spec/files/bret_96.mp3
131
+ - spec/files/bret_id3v1.mp3
132
+ - spec/files/bret_id3v2.mp3
133
+ - spec/files/bret_vbr_6.mp3
134
+ - spec/files/zeroes.mp3
135
+ - spec/mp3file/id3v1_tag_spec.rb
136
+ - spec/mp3file/id3v2/bit_padded_int_spec.rb
137
+ - spec/mp3file/id3v2/frame_header_spec.rb
138
+ - spec/mp3file/id3v2/header_spec.rb
139
+ - spec/mp3file/id3v2/tag_spec.rb
140
+ - spec/mp3file/id3v2/version_spec.rb
141
+ - spec/mp3file/mp3_file_spec.rb
142
+ - spec/mp3file/mp3_header_spec.rb
143
+ - spec/mp3file/xing_header_spec.rb
data/.rvmrc DELETED
@@ -1 +0,0 @@
1
- rvm 1.9.2@mp3file