id3tag 0.10.1 → 0.14.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.
- checksums.yaml +4 -4
- data/README.md +46 -6
- data/lib/id3tag.rb +14 -4
- data/lib/id3tag/audio_file.rb +10 -4
- data/lib/id3tag/configuration.rb +43 -2
- data/lib/id3tag/configuration_struct.rb +13 -0
- data/lib/id3tag/encoding_util.rb +1 -1
- data/lib/id3tag/frames/v1/comments_frame.rb +1 -1
- data/lib/id3tag/frames/v1/text_frame.rb +1 -5
- data/lib/id3tag/frames/v2/comments_frame.rb +1 -1
- data/lib/id3tag/frames/v2/text_frame.rb +4 -6
- data/lib/id3tag/id3_v2_frame_parser.rb +13 -9
- data/lib/id3tag/tag.rb +1 -1
- data/lib/id3tag/version.rb +1 -1
- metadata +21 -110
- data/.document +0 -5
- data/.gitignore +0 -8
- data/.rspec +0 -1
- data/.travis.yml +0 -15
- data/Gemfile +0 -4
- data/Rakefile +0 -24
- data/id3tag.gemspec +0 -28
- data/spec/features/can_read_non_audio_files_spec.rb +0 -17
- data/spec/features/can_read_tag_v1_spec.rb +0 -15
- data/spec/fixtures/id3v1_and_v2.mp3 +0 -0
- data/spec/fixtures/id3v1_with_track_nr.mp3 +0 -0
- data/spec/fixtures/id3v1_without_track_nr.mp3 +0 -0
- data/spec/fixtures/id3v2.mp3 +0 -0
- data/spec/fixtures/pov_20131018-2100a.mp3.v1_tag_body +0 -0
- data/spec/fixtures/pov_20131018-2100a.mp3.v2_3_tag_body +0 -0
- data/spec/fixtures/signals_1.mp3.v2_3_tag_body +0 -0
- data/spec/id3tag_extract_tags +0 -18
- data/spec/lib/id3tag/audio_file_spec.rb +0 -131
- data/spec/lib/id3tag/frames/util/genre_name_by_id_finder_spec.rb +0 -18
- data/spec/lib/id3tag/frames/v1/comments_frame_spec.rb +0 -39
- data/spec/lib/id3tag/frames/v1/genre_frame_spec.rb +0 -20
- data/spec/lib/id3tag/frames/v1/text_frame_spec.rb +0 -14
- data/spec/lib/id3tag/frames/v1/track_nr_frame_spec.rb +0 -19
- data/spec/lib/id3tag/frames/v2/basic_frame_spec.rb +0 -140
- data/spec/lib/id3tag/frames/v2/comments_frame_spec.rb +0 -45
- data/spec/lib/id3tag/frames/v2/frame_fabricator_spec.rb +0 -70
- data/spec/lib/id3tag/frames/v2/frame_flags_spec.rb +0 -588
- data/spec/lib/id3tag/frames/v2/genre_frame/genre_parser_24_spec.rb +0 -26
- data/spec/lib/id3tag/frames/v2/genre_frame/genre_parser_pre_24_spec.rb +0 -48
- data/spec/lib/id3tag/frames/v2/genre_frame/genre_parser_spec.rb +0 -13
- data/spec/lib/id3tag/frames/v2/genre_frame_spec.rb +0 -61
- data/spec/lib/id3tag/frames/v2/picture_frame_spec.rb +0 -127
- data/spec/lib/id3tag/frames/v2/text_frame_spec.rb +0 -89
- data/spec/lib/id3tag/frames/v2/unique_file_id_frame_spec.rb +0 -31
- data/spec/lib/id3tag/frames/v2/user_text_frame_spec.rb +0 -34
- data/spec/lib/id3tag/id3_v1_frame_parser_spec.rb +0 -71
- data/spec/lib/id3tag/id3_v2_frame_parser_spec.rb +0 -32
- data/spec/lib/id3tag/id3_v2_tag_header_spec.rb +0 -149
- data/spec/lib/id3tag/id3tag_spec.rb +0 -17
- data/spec/lib/id3tag/io_util_spec.rb +0 -30
- data/spec/lib/id3tag/number_util_spec.rb +0 -32
- data/spec/lib/id3tag/string_util_spec.rb +0 -81
- data/spec/lib/id3tag/synchsafe_integer_spec.rb +0 -14
- data/spec/lib/id3tag/tag_spec.rb +0 -352
- data/spec/spec_helper.rb +0 -23
- data/spec/support/mp3_fixtures.rb +0 -4
- data/standard_documents/id3v2-00.txt +0 -1657
- data/standard_documents/id3v2.3.0.txt +0 -2022
- data/standard_documents/id3v2.4.0-frames.txt +0 -1732
- data/standard_documents/id3v2.4.0-structure.txt +0 -732
@@ -1,32 +0,0 @@
|
|
1
|
-
require "spec_helper"
|
2
|
-
describe ID3Tag::ID3V2FrameParser do
|
3
|
-
subject { described_class.new(frame_bytes, tag_major_version) }
|
4
|
-
|
5
|
-
context "parsing v2.2.x tag" do
|
6
|
-
let(:tag_major_version) { 2 }
|
7
|
-
let(:frame_bytes) { "TP2\u0000\u0000\u0004\u0000ABC" + "TP1\u0000\u0000\u0004\u0000DEF" }
|
8
|
-
it "should fabricate frames" do
|
9
|
-
expect(ID3Tag::Frames::V2::FrameFabricator).to receive(:fabricate).with('TP2', "\u0000ABC", nil, 2).once
|
10
|
-
expect(ID3Tag::Frames::V2::FrameFabricator).to receive(:fabricate).with('TP1', "\u0000DEF", nil, 2).once
|
11
|
-
subject.frames
|
12
|
-
end
|
13
|
-
end
|
14
|
-
context "parsing v2.2.3 tag" do
|
15
|
-
let(:tag_major_version) { 3 }
|
16
|
-
let(:frame_bytes) { "TIT2\u0000\u0000\u0000\u0004\u0000\u0000\u0000ABC" + "TIT1\u0000\u0000\u0000\u0004\u0000\u0000\u0000DEF" }
|
17
|
-
it "should fabricate frames" do
|
18
|
-
expect(ID3Tag::Frames::V2::FrameFabricator).to receive(:fabricate).with('TIT2', "\u0000ABC", "\u0000\u0000", 3).once
|
19
|
-
expect(ID3Tag::Frames::V2::FrameFabricator).to receive(:fabricate).with('TIT1', "\u0000DEF", "\u0000\u0000", 3).once
|
20
|
-
subject.frames
|
21
|
-
end
|
22
|
-
end
|
23
|
-
context "parsing v2.4.x tag" do
|
24
|
-
let(:tag_major_version) { 4 }
|
25
|
-
let(:frame_bytes) { "TIT2\u0000\u0000\u0000\u0004\u0000\u0000\u0000ABC" + "TIT1\u0000\u0000\u0000\u0004\u0000\u0000\u0000DEF" }
|
26
|
-
it "should fabricate frames" do
|
27
|
-
expect(ID3Tag::Frames::V2::FrameFabricator).to receive(:fabricate).with('TIT2', "\u0000ABC", "\u0000\u0000", 4).once
|
28
|
-
expect(ID3Tag::Frames::V2::FrameFabricator).to receive(:fabricate).with('TIT1', "\u0000DEF", "\u0000\u0000", 4).once
|
29
|
-
subject.frames
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
@@ -1,149 +0,0 @@
|
|
1
|
-
require "spec_helper"
|
2
|
-
|
3
|
-
describe ID3Tag::ID3v2TagHeader do
|
4
|
-
subject { described_class.new(header_data) }
|
5
|
-
|
6
|
-
describe "#major_version_number" do
|
7
|
-
context "when first bit represent 3" do
|
8
|
-
let(:header_data) { "ID3\03\00..." }
|
9
|
-
|
10
|
-
describe '#major_version_number' do
|
11
|
-
subject { super().major_version_number }
|
12
|
-
it { is_expected.to eq(3) }
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
describe "#minor_version_number" do
|
18
|
-
context "when 2nd bit represent 2" do
|
19
|
-
let(:header_data) { "ID3\03\02..." }
|
20
|
-
|
21
|
-
describe '#minor_version_number' do
|
22
|
-
subject { super().minor_version_number }
|
23
|
-
it { is_expected.to eq(2) }
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
describe "#version_number" do
|
29
|
-
let(:header_data) { "ID3\02\03..." }
|
30
|
-
|
31
|
-
describe '#version_number' do
|
32
|
-
subject { super().version_number }
|
33
|
-
it { is_expected.to eq("2.3") }
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
describe "header flags" do
|
38
|
-
context "when flags bite is 0b10000000" do
|
39
|
-
let(:header_data) { "ID3\03\00#{0b10000000.chr}" }
|
40
|
-
|
41
|
-
describe '#unsynchronisation?' do
|
42
|
-
subject { super().unsynchronisation? }
|
43
|
-
it { is_expected.to eq(true) }
|
44
|
-
end
|
45
|
-
|
46
|
-
describe '#extended_header?' do
|
47
|
-
subject { super().extended_header? }
|
48
|
-
it { is_expected.to eq(false) }
|
49
|
-
end
|
50
|
-
|
51
|
-
describe '#experimental?' do
|
52
|
-
subject { super().experimental? }
|
53
|
-
it { is_expected.to eq(false) }
|
54
|
-
end
|
55
|
-
|
56
|
-
describe '#footer_present?' do
|
57
|
-
subject { super().footer_present? }
|
58
|
-
it { is_expected.to eq(false) }
|
59
|
-
end
|
60
|
-
end
|
61
|
-
context "when flags bite is 0b01000000" do
|
62
|
-
let(:header_data) { "ID3\03\00#{0b01000000.chr}" }
|
63
|
-
|
64
|
-
describe '#unsynchronisation?' do
|
65
|
-
subject { super().unsynchronisation? }
|
66
|
-
it { is_expected.to eq(false) }
|
67
|
-
end
|
68
|
-
|
69
|
-
describe '#extended_header?' do
|
70
|
-
subject { super().extended_header? }
|
71
|
-
it { is_expected.to eq(true) }
|
72
|
-
end
|
73
|
-
|
74
|
-
describe '#experimental?' do
|
75
|
-
subject { super().experimental? }
|
76
|
-
it { is_expected.to eq(false) }
|
77
|
-
end
|
78
|
-
|
79
|
-
describe '#footer_present?' do
|
80
|
-
subject { super().footer_present? }
|
81
|
-
it { is_expected.to eq(false) }
|
82
|
-
end
|
83
|
-
end
|
84
|
-
context "when flags bite is 0b00100000" do
|
85
|
-
let(:header_data) { "ID3\03\00#{0b00100000.chr}" }
|
86
|
-
|
87
|
-
describe '#unsynchronisation?' do
|
88
|
-
subject { super().unsynchronisation? }
|
89
|
-
it { is_expected.to eq(false) }
|
90
|
-
end
|
91
|
-
|
92
|
-
describe '#extended_header?' do
|
93
|
-
subject { super().extended_header? }
|
94
|
-
it { is_expected.to eq(false) }
|
95
|
-
end
|
96
|
-
|
97
|
-
describe '#experimental?' do
|
98
|
-
subject { super().experimental? }
|
99
|
-
it { is_expected.to eq(true) }
|
100
|
-
end
|
101
|
-
|
102
|
-
describe '#footer_present?' do
|
103
|
-
subject { super().footer_present? }
|
104
|
-
it { is_expected.to eq(false) }
|
105
|
-
end
|
106
|
-
end
|
107
|
-
context "when flags bite is 0b00010000" do
|
108
|
-
let(:header_data) { "ID3\03\00#{0b00010000.chr}" }
|
109
|
-
|
110
|
-
describe '#unsynchronisation?' do
|
111
|
-
subject { super().unsynchronisation? }
|
112
|
-
it { is_expected.to eq(false) }
|
113
|
-
end
|
114
|
-
|
115
|
-
describe '#extended_header?' do
|
116
|
-
subject { super().extended_header? }
|
117
|
-
it { is_expected.to eq(false) }
|
118
|
-
end
|
119
|
-
|
120
|
-
describe '#experimental?' do
|
121
|
-
subject { super().experimental? }
|
122
|
-
it { is_expected.to eq(false) }
|
123
|
-
end
|
124
|
-
|
125
|
-
describe '#footer_present?' do
|
126
|
-
subject { super().footer_present? }
|
127
|
-
it { is_expected.to eq(true) }
|
128
|
-
end
|
129
|
-
end
|
130
|
-
end
|
131
|
-
|
132
|
-
describe "#tag_size" do
|
133
|
-
let(:header_data) { "ID3abc\x00\x00\x01\x7F" }
|
134
|
-
|
135
|
-
describe '#tag_size' do
|
136
|
-
subject { super().tag_size }
|
137
|
-
it { is_expected.to eq(255) }
|
138
|
-
end
|
139
|
-
end
|
140
|
-
|
141
|
-
describe "#inspect" do
|
142
|
-
let(:header_data) { "ID3\u0003\u0000\u0000\u0000\u0000\u0000\u0000" }
|
143
|
-
|
144
|
-
describe '#inspect' do
|
145
|
-
subject { super().inspect }
|
146
|
-
it { is_expected.to eq "<ID3Tag::ID3v2TagHeader version:2.3.0 size:0 unsync:false ext.header:false experimental:false footer:false>" }
|
147
|
-
end
|
148
|
-
end
|
149
|
-
end
|
@@ -1,17 +0,0 @@
|
|
1
|
-
require "spec_helper"
|
2
|
-
|
3
|
-
describe ID3Tag do
|
4
|
-
let(:file) { mp3_fixture('id3v2.mp3') }
|
5
|
-
describe "#read" do
|
6
|
-
it "reads file tag" do
|
7
|
-
expect(ID3Tag.read(file)).to be_instance_of(ID3Tag::Tag)
|
8
|
-
end
|
9
|
-
|
10
|
-
it "accepts block" do
|
11
|
-
expect do |b|
|
12
|
-
ID3Tag.read(file, &b)
|
13
|
-
end.to yield_control
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
@@ -1,30 +0,0 @@
|
|
1
|
-
require "spec_helper"
|
2
|
-
|
3
|
-
describe ID3Tag::IOUtil do
|
4
|
-
|
5
|
-
describe "#read_until_terminator" do
|
6
|
-
subject { ID3Tag::IOUtil.read_until_terminator(io, group_size) }
|
7
|
-
context "when reading IO and looking for UTF-8 terminator - 1 null byte" do
|
8
|
-
let(:group_size) { 1 }
|
9
|
-
context "when only 1 null byte present" do
|
10
|
-
let(:io) { StringIO.new("abcd\x00ef") }
|
11
|
-
it { is_expected.to eq("abcd") }
|
12
|
-
end
|
13
|
-
context "when no null bytes are present" do
|
14
|
-
let(:io) { StringIO.new("abcdef") }
|
15
|
-
it { is_expected.to eq("abcdef") }
|
16
|
-
end
|
17
|
-
end
|
18
|
-
context "when reading IO and looking for UTF-16 terminator - 2 null bytes" do
|
19
|
-
let(:group_size) { 2 }
|
20
|
-
context "when only 1 null byte present" do
|
21
|
-
let(:io) { StringIO.new("a\x00b\x00\x00\x00c\x00") }
|
22
|
-
it "should return content until terminator and leave cursor just right after" do
|
23
|
-
expect(subject).to eq("a\x00b\x00")
|
24
|
-
expect(io.read).to eq("c\x00")
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
end
|
@@ -1,32 +0,0 @@
|
|
1
|
-
require "spec_helper"
|
2
|
-
describe ID3Tag::NumberUtil do
|
3
|
-
describe "#convert_string_to_32bit_integer" do
|
4
|
-
context "when string with 4 bytes given" do
|
5
|
-
it "should return integer" do
|
6
|
-
expect(described_class.convert_string_to_32bit_integer("abcd")).to eq(1633837924)
|
7
|
-
end
|
8
|
-
end
|
9
|
-
|
10
|
-
context "when string with less than 4 bytes given" do
|
11
|
-
it "should raise Argument error" do
|
12
|
-
expect do
|
13
|
-
described_class.convert_string_to_32bit_integer("ab")
|
14
|
-
end.to raise_error(ArgumentError)
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
context "when non-string argument is given" do
|
19
|
-
it "should raise Argument error" do
|
20
|
-
expect do
|
21
|
-
described_class.convert_string_to_32bit_integer(Object.new)
|
22
|
-
end.to raise_error(ArgumentError)
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
describe "#convert_32bit_integer_to_string" do
|
28
|
-
it "should return 4 byte string" do
|
29
|
-
expect(described_class.convert_32bit_integer_to_string(1633837924)).to eq("abcd")
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
@@ -1,81 +0,0 @@
|
|
1
|
-
require "spec_helper"
|
2
|
-
|
3
|
-
describe ID3Tag::StringUtil do
|
4
|
-
describe "#blank?" do
|
5
|
-
subject { described_class.blank?(test_string) }
|
6
|
-
context "when test string is like ''" do
|
7
|
-
let(:test_string) { "" }
|
8
|
-
it { is_expected.to eq(true) }
|
9
|
-
end
|
10
|
-
|
11
|
-
context "when test string is like ' '" do
|
12
|
-
let(:test_string) { " " }
|
13
|
-
it { is_expected.to eq(true) }
|
14
|
-
end
|
15
|
-
|
16
|
-
context "when test string is like 'foo'" do
|
17
|
-
let(:test_string) { "foo" }
|
18
|
-
it { is_expected.to eq(false) }
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
describe "do_unsynchronization" do
|
23
|
-
let(:input) { }
|
24
|
-
subject { described_class.do_unsynchronization(input) }
|
25
|
-
|
26
|
-
context "when a false synchronization is present" do
|
27
|
-
let(:input) { "\xFF\xEE" }
|
28
|
-
it { is_expected.to eq("\xFF\x00\xEE") }
|
29
|
-
end
|
30
|
-
context "when a false synchronization is not present" do
|
31
|
-
let(:input) { "\xEE\xEE" }
|
32
|
-
it { is_expected.to eq("\xEE\xEE") }
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
describe "undo_unsynchronization" do
|
37
|
-
let(:input) { }
|
38
|
-
subject { described_class.undo_unsynchronization(input) }
|
39
|
-
|
40
|
-
context "when unsynchronization in present" do
|
41
|
-
let(:input) { "\xFF\x00\xEE\xEE" }
|
42
|
-
it { is_expected.to eq("\xFF\xEE\xEE") }
|
43
|
-
end
|
44
|
-
context "when unsynchronization in not present" do
|
45
|
-
let(:input) { "\xEE\xEE" }
|
46
|
-
it { is_expected.to eq("\xEE\xEE") }
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
describe "cut_at_null_byte" do
|
51
|
-
let(:input) { }
|
52
|
-
subject { described_class.cut_at_null_byte(input) }
|
53
|
-
|
54
|
-
context 'when content is empty' do
|
55
|
-
let(:input) { '' }
|
56
|
-
it { is_expected.to eq('') }
|
57
|
-
end
|
58
|
-
|
59
|
-
context 'when content is present' do
|
60
|
-
let(:input) { "a\u0000b" }
|
61
|
-
it { is_expected.to eq('a') }
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
describe "split_by_null_byte" do
|
66
|
-
let(:input) { }
|
67
|
-
subject { described_class.split_by_null_byte(input) }
|
68
|
-
context "when content have only 1 null byte" do
|
69
|
-
let(:input) { "a\u0000b" }
|
70
|
-
it { is_expected.to eq(["a", "b"]) }
|
71
|
-
end
|
72
|
-
context "when content have multiple null bytes" do
|
73
|
-
let(:input) { "a\u0000\u0000b" }
|
74
|
-
it { is_expected.to eq(["a", "\u0000b"]) }
|
75
|
-
end
|
76
|
-
context "when content have multiple null bytes" do
|
77
|
-
let(:input) { "abc" }
|
78
|
-
it { is_expected.to eq(["abc", ""]) }
|
79
|
-
end
|
80
|
-
end
|
81
|
-
end
|
@@ -1,14 +0,0 @@
|
|
1
|
-
require "spec_helper"
|
2
|
-
describe ID3Tag::SynchsafeInteger do
|
3
|
-
it "encodes regular integers" do
|
4
|
-
expect(described_class.encode(255)).to eq(383)
|
5
|
-
expect(described_class.encode(5)).to eq(5)
|
6
|
-
expect(described_class.encode(128)).to eq(256)
|
7
|
-
end
|
8
|
-
|
9
|
-
it "decodes synchsafe integers" do
|
10
|
-
expect(described_class.decode(383)).to eq(255)
|
11
|
-
expect(described_class.decode(5)).to eq(5)
|
12
|
-
expect(described_class.decode(256)).to eq(128)
|
13
|
-
end
|
14
|
-
end
|
data/spec/lib/id3tag/tag_spec.rb
DELETED
@@ -1,352 +0,0 @@
|
|
1
|
-
require "spec_helper"
|
2
|
-
|
3
|
-
describe ID3Tag::Tag do
|
4
|
-
describe "class method #read"
|
5
|
-
|
6
|
-
describe "#get_frame" do
|
7
|
-
subject { described_class.read(nil) }
|
8
|
-
context "when more that one frame by that ID exists" do
|
9
|
-
before :each do
|
10
|
-
allow(subject).to receive(:get_frames) { [:frame, :frame] }
|
11
|
-
end
|
12
|
-
it "should raise MultipleFrameError" do
|
13
|
-
expect { subject.get_frame(:some_unique_frame) }.to raise_error(ID3Tag::Tag::MultipleFrameError)
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
context "when only one frame by that ID exists" do
|
18
|
-
before :each do
|
19
|
-
allow(subject).to receive(:get_frames) { [:frame] }
|
20
|
-
end
|
21
|
-
it "should return the frame" do
|
22
|
-
expect(subject.get_frame(:some_unique_frame)).to eq(:frame)
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
describe "#get_frames" do
|
28
|
-
subject { described_class.read(nil) }
|
29
|
-
let(:a1) { ID3Tag::Frames::V1::TextFrame.new(:A, 'a1') }
|
30
|
-
let(:a2) { ID3Tag::Frames::V1::TextFrame.new(:A, 'a2') }
|
31
|
-
let(:b) { ID3Tag::Frames::V1::TextFrame.new(:B, 'b') }
|
32
|
-
before :each do
|
33
|
-
allow(subject).to receive(:frames) { [a1, a2, b] }
|
34
|
-
end
|
35
|
-
it "returns frames with specific IDs" do
|
36
|
-
expect(subject.get_frames(:A)).to eq([a1, a2])
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
describe "#frames" do
|
41
|
-
subject { described_class.read(nil) }
|
42
|
-
before do
|
43
|
-
allow(subject).to receive(:v1_frames) { [:v1_frame1, :v1_frame2] }
|
44
|
-
allow(subject).to receive(:v2_frames) { [:v2_frame1, :v2_frame2] }
|
45
|
-
end
|
46
|
-
it "returns v2 frames and v1 frames" do
|
47
|
-
expect(subject.frames).to eq([:v2_frame1, :v2_frame2, :v1_frame1, :v1_frame2])
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
describe "#frame_ids" do
|
52
|
-
subject { described_class.read(nil) }
|
53
|
-
let(:frame_1) { ID3Tag::Frames::V1::TextFrame.new(:AA, 'a1') }
|
54
|
-
let(:frame_2) { ID3Tag::Frames::V1::TextFrame.new(:BB, 'a2') }
|
55
|
-
before do
|
56
|
-
allow(subject).to receive(:frames) { [frame_1, frame_2] }
|
57
|
-
end
|
58
|
-
it "returns frames ids" do
|
59
|
-
expect(subject.frame_ids).to eq([:AA, :BB])
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
describe "#v1_frames" do
|
64
|
-
context "when tag reading initialized with v1 tag only" do
|
65
|
-
subject { described_class.read(nil, :v1) }
|
66
|
-
context "when file has v1 tag" do
|
67
|
-
before do
|
68
|
-
allow_any_instance_of(ID3Tag::AudioFile).to receive(:v1_tag_present?) { true }
|
69
|
-
allow_any_instance_of(ID3Tag::AudioFile).to receive(:v1_tag_body) { '' }
|
70
|
-
allow_any_instance_of(ID3Tag::ID3V1FrameParser).to receive(:frames) { [:v1_frame] }
|
71
|
-
end
|
72
|
-
it "reads v1 tags" do
|
73
|
-
expect(subject.v1_frames).to eq([:v1_frame])
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
context "when file does not have v1 tag" do
|
78
|
-
before do
|
79
|
-
allow_any_instance_of(ID3Tag::AudioFile).to receive(:v1_tag_present?) { false }
|
80
|
-
allow_any_instance_of(ID3Tag::AudioFile).to receive(:v1_tag_body) { '' }
|
81
|
-
end
|
82
|
-
it "returns empty array" do
|
83
|
-
expect(subject.v1_frames).to eq([])
|
84
|
-
end
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
context "when tag reading initialized with v2 tag only" do
|
89
|
-
subject { described_class.read(nil, :v2) }
|
90
|
-
context "when file has v1 tag" do
|
91
|
-
before do
|
92
|
-
allow_any_instance_of(ID3Tag::AudioFile).to receive(:v1_tag_present?) { true }
|
93
|
-
allow_any_instance_of(ID3Tag::AudioFile).to receive(:v1_tag_body) { '' }
|
94
|
-
end
|
95
|
-
it "reads v1 tags" do
|
96
|
-
expect(subject.v1_frames).to eq([])
|
97
|
-
end
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
context "when tag reading initialized with all versions flag" do
|
102
|
-
subject { described_class.read(nil, :all) }
|
103
|
-
context "when file has v1 tag" do
|
104
|
-
before do
|
105
|
-
allow_any_instance_of(ID3Tag::AudioFile).to receive(:v1_tag_present?) { true }
|
106
|
-
allow_any_instance_of(ID3Tag::AudioFile).to receive(:v1_tag_body) { '' }
|
107
|
-
allow_any_instance_of(ID3Tag::ID3V1FrameParser).to receive(:frames) { [:v1_frame] }
|
108
|
-
end
|
109
|
-
it "reads v1 tags" do
|
110
|
-
expect(subject.v1_frames).to eq([:v1_frame])
|
111
|
-
end
|
112
|
-
end
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
describe "#v2_frames" do
|
117
|
-
before do
|
118
|
-
allow_any_instance_of(ID3Tag::AudioFile).to receive(:v2_tag_major_version_number) { 3 }
|
119
|
-
end
|
120
|
-
context "when tag reading initialized with v2 tag only" do
|
121
|
-
subject { described_class.read(nil, :v2) }
|
122
|
-
context "when file has v2 tag" do
|
123
|
-
before do
|
124
|
-
allow_any_instance_of(ID3Tag::AudioFile).to receive(:v2_tag_present?) { true }
|
125
|
-
allow_any_instance_of(ID3Tag::AudioFile).to receive(:v2_tag_body) { '' }
|
126
|
-
allow_any_instance_of(ID3Tag::AudioFile).to receive(:v2_tag_size) { 120 }
|
127
|
-
allow_any_instance_of(ID3Tag::ID3V2FrameParser).to receive(:frames) { [:v2_frame] }
|
128
|
-
end
|
129
|
-
it "reads v2 tags" do
|
130
|
-
expect(subject.v2_frames).to eq([:v2_frame])
|
131
|
-
end
|
132
|
-
end
|
133
|
-
|
134
|
-
context "when file does not have v2 tag" do
|
135
|
-
before do
|
136
|
-
allow_any_instance_of(ID3Tag::AudioFile).to receive(:v2_tag_present?) { false }
|
137
|
-
allow_any_instance_of(ID3Tag::AudioFile).to receive(:v2_tag_body) { '' }
|
138
|
-
end
|
139
|
-
it "returns empty array" do
|
140
|
-
expect(subject.v2_frames).to eq([])
|
141
|
-
end
|
142
|
-
end
|
143
|
-
end
|
144
|
-
|
145
|
-
context "when tag reading initialized with v1 tag only" do
|
146
|
-
subject { described_class.read(nil, :v1) }
|
147
|
-
context "when file has v2 tag" do
|
148
|
-
before do
|
149
|
-
allow_any_instance_of(ID3Tag::AudioFile).to receive(:v2_tag_present?) { true }
|
150
|
-
allow_any_instance_of(ID3Tag::AudioFile).to receive(:v2_tag_body) { '' }
|
151
|
-
end
|
152
|
-
it "returns empty array" do
|
153
|
-
expect(subject.v2_frames).to eq([])
|
154
|
-
end
|
155
|
-
end
|
156
|
-
end
|
157
|
-
|
158
|
-
context "when tag reading initialized with all versions flag" do
|
159
|
-
subject { described_class.read(nil, :all) }
|
160
|
-
context "when file has v2 tag" do
|
161
|
-
before do
|
162
|
-
allow_any_instance_of(ID3Tag::AudioFile).to receive(:v2_tag_present?) { true }
|
163
|
-
allow_any_instance_of(ID3Tag::AudioFile).to receive(:v2_tag_body) { '' }
|
164
|
-
allow_any_instance_of(ID3Tag::AudioFile).to receive(:v2_tag_size) { 120 }
|
165
|
-
allow_any_instance_of(ID3Tag::ID3V2FrameParser).to receive(:frames) { [:v2_frame] }
|
166
|
-
end
|
167
|
-
it "reads v2 tags" do
|
168
|
-
expect(subject.v2_frames).to eq([:v2_frame])
|
169
|
-
end
|
170
|
-
end
|
171
|
-
end
|
172
|
-
end
|
173
|
-
|
174
|
-
describe "Tests with real-world tags" do
|
175
|
-
let(:audio_file) { double("Fake Audio file") }
|
176
|
-
|
177
|
-
subject do
|
178
|
-
described_class.new(nil, scope_version).tap do |obj|
|
179
|
-
allow(obj).to receive(:audio_file) { audio_file }
|
180
|
-
end
|
181
|
-
end
|
182
|
-
|
183
|
-
before do
|
184
|
-
allow(audio_file).to receive_messages({
|
185
|
-
:v1_tag_present? => v1_tag_present_flag,
|
186
|
-
:v2_tag_present? => v2_tag_present_flag,
|
187
|
-
:v1_tag_body => v1_tag_body,
|
188
|
-
:v1_tag_size => v1_tag_body.to_s.size,
|
189
|
-
:v2_tag_body => v2_tag_body,
|
190
|
-
:v2_tag_size => v2_tag_body.to_s.size,
|
191
|
-
:v2_tag_major_version_number => v2_tag_major_version_number
|
192
|
-
})
|
193
|
-
end
|
194
|
-
|
195
|
-
context "signals_1.mp3.v2_3_tag_body" do
|
196
|
-
let(:v1_tag_present_flag) { true }
|
197
|
-
let(:v2_tag_present_flag) { true }
|
198
|
-
let(:v1_tag_body) { }
|
199
|
-
let(:v2_tag_body) { mp3_fixture("signals_1.mp3.v2_3_tag_body").read }
|
200
|
-
let(:v2_tag_major_version_number) { 3 }
|
201
|
-
|
202
|
-
context "Reading only v2" do
|
203
|
-
let(:scope_version) { :v2 }
|
204
|
-
|
205
|
-
describe '#artist' do
|
206
|
-
subject { super().artist }
|
207
|
-
it { is_expected.to eq("Sabled Sun") }
|
208
|
-
end
|
209
|
-
|
210
|
-
describe '#title' do
|
211
|
-
subject { super().title }
|
212
|
-
it { is_expected.to eq("Sabled Sun - Signals I") }
|
213
|
-
end
|
214
|
-
|
215
|
-
describe '#album' do
|
216
|
-
subject { super().album }
|
217
|
-
it { is_expected.to eq("Signals I") }
|
218
|
-
end
|
219
|
-
|
220
|
-
describe '#year' do
|
221
|
-
subject { super().year }
|
222
|
-
it { is_expected.to eq("2013") }
|
223
|
-
end
|
224
|
-
|
225
|
-
describe '#track_nr' do
|
226
|
-
subject { super().track_nr }
|
227
|
-
it { is_expected.to eq "1" }
|
228
|
-
end
|
229
|
-
|
230
|
-
describe '#genre' do
|
231
|
-
subject { super().genre }
|
232
|
-
it { is_expected.to eq "Jazz" }
|
233
|
-
end
|
234
|
-
|
235
|
-
describe '#comments' do
|
236
|
-
subject { super().comments }
|
237
|
-
it { is_expected.to eq("Visit http://cryochamber.bandcamp.com") }
|
238
|
-
end
|
239
|
-
it "should return eng comment" do
|
240
|
-
expect(subject.comments(:eng)).to eq("Visit http://cryochamber.bandcamp.com")
|
241
|
-
end
|
242
|
-
it "should read private frames" do
|
243
|
-
expect(subject.get_frames(:PRIV).find { |f| f.owner_identifier.force_encoding(Encoding::UTF_8) == "WM/MediaClassPrimaryID" }).to be_kind_of(ID3Tag::Frames::V2::PrivateFrame)
|
244
|
-
end
|
245
|
-
end
|
246
|
-
end
|
247
|
-
|
248
|
-
context "pov_20131018-2100a.mp3" do
|
249
|
-
let(:v1_tag_present_flag) { true }
|
250
|
-
let(:v2_tag_present_flag) { true }
|
251
|
-
let(:v1_tag_body) { mp3_fixture("pov_20131018-2100a.mp3.v1_tag_body").read }
|
252
|
-
let(:v2_tag_body) { mp3_fixture("pov_20131018-2100a.mp3.v2_3_tag_body").read }
|
253
|
-
let(:v2_tag_major_version_number) { 3 }
|
254
|
-
|
255
|
-
context "Reading only v1" do
|
256
|
-
let(:scope_version) { :v1 }
|
257
|
-
|
258
|
-
describe '#artist' do
|
259
|
-
subject { super().artist }
|
260
|
-
it { is_expected.to eq("") }
|
261
|
-
end
|
262
|
-
|
263
|
-
describe '#title' do
|
264
|
-
subject { super().title }
|
265
|
-
it { is_expected.to eq("pov_20131018-2100a.mp3") }
|
266
|
-
end
|
267
|
-
|
268
|
-
describe '#album' do
|
269
|
-
subject { super().album }
|
270
|
-
it { is_expected.to eq("") }
|
271
|
-
end
|
272
|
-
|
273
|
-
describe '#year' do
|
274
|
-
subject { super().year }
|
275
|
-
it { is_expected.to eq("") }
|
276
|
-
end
|
277
|
-
|
278
|
-
describe '#track_nr' do
|
279
|
-
subject { super().track_nr }
|
280
|
-
it { is_expected.to be_nil }
|
281
|
-
end
|
282
|
-
|
283
|
-
describe '#genre' do
|
284
|
-
subject { super().genre }
|
285
|
-
it { is_expected.to eq("Blues") }
|
286
|
-
end
|
287
|
-
|
288
|
-
describe '#comments' do
|
289
|
-
subject { super().comments }
|
290
|
-
it { is_expected.to be_nil }
|
291
|
-
end
|
292
|
-
|
293
|
-
describe '#frame_ids' do
|
294
|
-
subject { super().frame_ids }
|
295
|
-
it { is_expected.to eq [:title, :artist, :album, :year, :comments, :genre] }
|
296
|
-
end
|
297
|
-
end
|
298
|
-
context "Reading only v2" do
|
299
|
-
let(:scope_version) { :v2 }
|
300
|
-
|
301
|
-
describe '#artist' do
|
302
|
-
subject { super().artist }
|
303
|
-
it { is_expected.to eq("BBC Radio 4") }
|
304
|
-
end
|
305
|
-
|
306
|
-
describe '#title' do
|
307
|
-
subject { super().title }
|
308
|
-
it { is_expected.to eq("PoV: Lisa Jardine: Machine Intelligence: 18 Oct 13") }
|
309
|
-
end
|
310
|
-
|
311
|
-
describe '#album' do
|
312
|
-
subject { super().album }
|
313
|
-
it { is_expected.to eq("A Point of View") }
|
314
|
-
end
|
315
|
-
|
316
|
-
describe '#year' do
|
317
|
-
subject { super().year }
|
318
|
-
it { is_expected.to eq("2013") }
|
319
|
-
end
|
320
|
-
|
321
|
-
describe '#track_nr' do
|
322
|
-
subject { super().track_nr }
|
323
|
-
it { is_expected.to be_nil }
|
324
|
-
end
|
325
|
-
it "should return nil for genre as this tag have incorect genre frame" do
|
326
|
-
expect(subject.genre).to eq("")
|
327
|
-
end
|
328
|
-
|
329
|
-
describe '#comments' do
|
330
|
-
subject { super().comments }
|
331
|
-
it { is_expected.to eq("Lisa Jardine compares the contributions of Ada Lovelace and Alan Turing a century later to computer science and contrasts their views on the potential of and limits to machine intelligence. \r\nProducer: Sheila Cook") }
|
332
|
-
end
|
333
|
-
it "should return eng comment" do
|
334
|
-
expect(subject.comments(:eng)).to eq("Lisa Jardine compares the contributions of Ada Lovelace and Alan Turing a century later to computer science and contrasts their views on the potential of and limits to machine intelligence. \r\nProducer: Sheila Cook")
|
335
|
-
end
|
336
|
-
it "should return blank string for latvian comments" do
|
337
|
-
expect(subject.comments(:lav)).to be_nil
|
338
|
-
end
|
339
|
-
|
340
|
-
describe '#frame_ids' do
|
341
|
-
subject { super().frame_ids }
|
342
|
-
it { is_expected.to eq [:TALB, :TPE1, :COMM, :USLT, :TCON, :TIT2, :TYER, :TCOP, :APIC] }
|
343
|
-
end
|
344
|
-
it "should have comments frame with short desc and language code" do
|
345
|
-
expect(subject.get_frames(:COMM).size).to eq(1)
|
346
|
-
expect(subject.get_frame(:COMM).language).to eq("eng")
|
347
|
-
expect(subject.get_frame(:COMM).description).to eq("")
|
348
|
-
end
|
349
|
-
end
|
350
|
-
end
|
351
|
-
end
|
352
|
-
end
|