taglib-ruby 0.1.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.
- data/Gemfile +11 -0
- data/Gemfile.lock +25 -0
- data/LICENSE.txt +20 -0
- data/README.md +109 -0
- data/Rakefile +63 -0
- data/ext/Rakefile +32 -0
- data/ext/extconf_common.rb +18 -0
- data/ext/taglib_base/extconf.rb +4 -0
- data/ext/taglib_base/includes.i +41 -0
- data/ext/taglib_base/taglib_base.i +83 -0
- data/ext/taglib_base/taglib_base_wrap.cxx +7069 -0
- data/ext/taglib_id3v2/extconf.rb +4 -0
- data/ext/taglib_id3v2/taglib_id3v2.i +111 -0
- data/ext/taglib_id3v2/taglib_id3v2_wrap.cxx +16496 -0
- data/ext/taglib_mpeg/extconf.rb +4 -0
- data/ext/taglib_mpeg/taglib_mpeg.i +60 -0
- data/ext/taglib_mpeg/taglib_mpeg_wrap.cxx +5533 -0
- data/ext/valgrind-suppressions.txt +170 -0
- data/lib/taglib.rb +3 -0
- data/lib/taglib/base.rb +1 -0
- data/lib/taglib/id3v2.rb +42 -0
- data/lib/taglib/mpeg.rb +1 -0
- data/lib/taglib/version.rb +10 -0
- data/test/data/globe_east_540.jpg +0 -0
- data/test/data/sample.mp3 +0 -0
- data/test/data/unicode.mp3 +0 -0
- data/test/helper.rb +10 -0
- data/test/test_id3v2_frames.rb +93 -0
- data/test/test_id3v2_memory.rb +54 -0
- data/test/test_id3v2_tag.rb +31 -0
- data/test/test_id3v2_unicode.rb +42 -0
- data/test/test_id3v2_write.rb +95 -0
- data/test/test_tag.rb +21 -0
- metadata +227 -0
@@ -0,0 +1,170 @@
|
|
1
|
+
{
|
2
|
+
taglib_base SWIG_InitializeModule
|
3
|
+
exp-ptrcheck:SorG
|
4
|
+
fun:Init_taglib_base
|
5
|
+
fun:dln_load
|
6
|
+
}
|
7
|
+
{
|
8
|
+
taglib_id3v2 SWIG_InitializeModule
|
9
|
+
exp-ptrcheck:SorG
|
10
|
+
fun:Init_taglib_id3v2
|
11
|
+
fun:dln_load
|
12
|
+
}
|
13
|
+
{
|
14
|
+
taglib_mpeg SWIG_InitializeModule
|
15
|
+
exp-ptrcheck:SorG
|
16
|
+
fun:Init_taglib_mpeg
|
17
|
+
fun:dln_load
|
18
|
+
}
|
19
|
+
# Ruby 1.9 VM supressions
|
20
|
+
{
|
21
|
+
r1
|
22
|
+
Memcheck:Cond
|
23
|
+
fun:gc_mark
|
24
|
+
}
|
25
|
+
{
|
26
|
+
r2
|
27
|
+
Memcheck:Cond
|
28
|
+
fun:gc_mark_children
|
29
|
+
}
|
30
|
+
{
|
31
|
+
r3
|
32
|
+
Memcheck:Cond
|
33
|
+
fun:mark_current_machine_context
|
34
|
+
}
|
35
|
+
{
|
36
|
+
r4
|
37
|
+
Memcheck:Value8
|
38
|
+
fun:gc_mark
|
39
|
+
}
|
40
|
+
{
|
41
|
+
r5
|
42
|
+
Memcheck:Value8
|
43
|
+
fun:gc_mark_children
|
44
|
+
}
|
45
|
+
{
|
46
|
+
r6
|
47
|
+
Memcheck:Value8
|
48
|
+
fun:mark_current_machine_context
|
49
|
+
}
|
50
|
+
{
|
51
|
+
r7
|
52
|
+
Memcheck:Value8
|
53
|
+
fun:vm_exec_core
|
54
|
+
}
|
55
|
+
{
|
56
|
+
r8
|
57
|
+
Memcheck:Value4
|
58
|
+
fun:find_derivation
|
59
|
+
}
|
60
|
+
{
|
61
|
+
r9
|
62
|
+
Memcheck:Value8
|
63
|
+
fun:__gconv_read_conf
|
64
|
+
}
|
65
|
+
{
|
66
|
+
r10
|
67
|
+
Memcheck:Leak
|
68
|
+
fun:malloc
|
69
|
+
fun:vm_xmalloc
|
70
|
+
fun:ruby_strdup
|
71
|
+
}
|
72
|
+
{
|
73
|
+
r11
|
74
|
+
Memcheck:Leak
|
75
|
+
fun:malloc
|
76
|
+
fun:vm_xmalloc
|
77
|
+
fun:rb_include_module
|
78
|
+
}
|
79
|
+
{
|
80
|
+
r12
|
81
|
+
Memcheck:Leak
|
82
|
+
...
|
83
|
+
fun:ruby_init
|
84
|
+
fun:main
|
85
|
+
}
|
86
|
+
{
|
87
|
+
r20
|
88
|
+
exp-ptrcheck:SorG
|
89
|
+
fun:insert_module
|
90
|
+
}
|
91
|
+
{
|
92
|
+
r21
|
93
|
+
exp-ptrcheck:SorG
|
94
|
+
fun:find_derivation
|
95
|
+
}
|
96
|
+
{
|
97
|
+
r22
|
98
|
+
exp-ptrcheck:SorG
|
99
|
+
fun:vm_exec_core
|
100
|
+
}
|
101
|
+
{
|
102
|
+
r23
|
103
|
+
exp-ptrcheck:SorG
|
104
|
+
fun:__gconv_read_conf
|
105
|
+
}
|
106
|
+
{
|
107
|
+
r24
|
108
|
+
exp-ptrcheck:SorG
|
109
|
+
fun:mark_current_machine_context
|
110
|
+
}
|
111
|
+
# Ruby 1.8 suppressions
|
112
|
+
{
|
113
|
+
r18_1
|
114
|
+
Memcheck:Cond
|
115
|
+
fun:mark_locations_array
|
116
|
+
...
|
117
|
+
fun:yycompile
|
118
|
+
}
|
119
|
+
{
|
120
|
+
r18_2
|
121
|
+
Memcheck:Cond
|
122
|
+
fun:mark_locations_array
|
123
|
+
...
|
124
|
+
fun:rb_eval
|
125
|
+
}
|
126
|
+
{
|
127
|
+
r18_3
|
128
|
+
Memcheck:Leak
|
129
|
+
fun:malloc
|
130
|
+
fun:ruby_xmalloc
|
131
|
+
fun:scope_dup
|
132
|
+
}
|
133
|
+
{
|
134
|
+
r18_4
|
135
|
+
Memcheck:Leak
|
136
|
+
fun:malloc
|
137
|
+
...
|
138
|
+
fun:yycompile
|
139
|
+
}
|
140
|
+
{
|
141
|
+
r18_5
|
142
|
+
exp-ptrcheck:SorG
|
143
|
+
fun:mark_locations_array
|
144
|
+
fun:garbage_collect
|
145
|
+
...
|
146
|
+
fun:yycompile
|
147
|
+
}
|
148
|
+
{
|
149
|
+
r18_6
|
150
|
+
exp-ptrcheck:Heap
|
151
|
+
...
|
152
|
+
fun:rb_intern
|
153
|
+
fun:rb_str_intern
|
154
|
+
fun:rb_to_id
|
155
|
+
fun:rb_mod_alias_method
|
156
|
+
}
|
157
|
+
{
|
158
|
+
r18_7
|
159
|
+
exp-ptrcheck:SorG
|
160
|
+
fun:ruby_yyparse
|
161
|
+
fun:yycompile
|
162
|
+
}
|
163
|
+
{
|
164
|
+
r18_8
|
165
|
+
exp-ptrcheck:SorG
|
166
|
+
fun:ruby_re_compile_pattern
|
167
|
+
fun:rb_reg_initialize
|
168
|
+
...
|
169
|
+
fun:rb_class_new_instance
|
170
|
+
}
|
data/lib/taglib.rb
ADDED
data/lib/taglib/base.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'taglib_base'
|
data/lib/taglib/id3v2.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'taglib_id3v2'
|
2
|
+
|
3
|
+
module TagLib
|
4
|
+
module ID3v2
|
5
|
+
class FrameList
|
6
|
+
include Enumerable
|
7
|
+
|
8
|
+
def each
|
9
|
+
it = self.begin
|
10
|
+
it_end = self.end
|
11
|
+
while it != it_end
|
12
|
+
frame = it.value
|
13
|
+
casted_frame = frame.cast
|
14
|
+
yield casted_frame
|
15
|
+
it = it.next
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
class Frame
|
20
|
+
def to_s
|
21
|
+
to_string
|
22
|
+
end
|
23
|
+
def cast
|
24
|
+
case frame_id
|
25
|
+
when "APIC" then to_attached_picture_frame
|
26
|
+
when "COMM" then to_comments_frame
|
27
|
+
when "GEOB" then to_general_encapsulated_object_frame
|
28
|
+
when "POPM" then to_popularimeter_frame
|
29
|
+
when "PRIV" then to_private_frame
|
30
|
+
when "RVAD" then to_relative_volume_frame
|
31
|
+
when "TXXX" then to_user_text_identification_frame
|
32
|
+
when /T.../ then to_text_identification_frame
|
33
|
+
when "UFID" then to_unique_file_identifier_frame
|
34
|
+
when "USLT" then to_unsynchronized_lyrics_frame
|
35
|
+
when "WXXX" then to_user_url_link_frame
|
36
|
+
when /W.../ then to_url_link_frame
|
37
|
+
else self
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/lib/taglib/mpeg.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'taglib_mpeg'
|
Binary file
|
Binary file
|
Binary file
|
data/test/helper.rb
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestID3v2Frames < Test::Unit::TestCase
|
4
|
+
context "The sample.mp3 file's frames" do
|
5
|
+
setup do
|
6
|
+
read_properties = false
|
7
|
+
# It's important that file is an instance variable, otherwise the
|
8
|
+
# tag would get garbage collected along with the file, even if tag
|
9
|
+
# itself would still be reachable. The reason is because
|
10
|
+
# TagLib::MPEG::File owns the TagLib::ID3v2::Tag and automatically
|
11
|
+
# deletes it in its destructor.
|
12
|
+
@file = TagLib::MPEG::File.new("test/data/sample.mp3", read_properties)
|
13
|
+
picture_file = File.open("test/data/globe_east_540.jpg", "rb") do |f|
|
14
|
+
@picture_data = f.read
|
15
|
+
end
|
16
|
+
@tag = @file.id3v2_tag
|
17
|
+
@frames = @tag.frame_list
|
18
|
+
end
|
19
|
+
|
20
|
+
should "be complete" do
|
21
|
+
assert_not_nil @frames
|
22
|
+
assert_equal 11, @frames.size
|
23
|
+
iterator = @frames.begin
|
24
|
+
frame = iterator.value
|
25
|
+
assert_equal "Dummy Title", frame.to_string
|
26
|
+
end
|
27
|
+
|
28
|
+
should "be enumerable" do
|
29
|
+
ids = @frames.collect{ |frame| frame.frame_id }
|
30
|
+
assert_equal ["TIT2", "TPE1", "TALB", "TRCK", "TDRC",
|
31
|
+
"COMM", "COMM", "TCON", "TXXX", "COMM", "APIC"], ids
|
32
|
+
end
|
33
|
+
|
34
|
+
should "be automatically converted" do
|
35
|
+
apic = @tag.frame_list('APIC').first
|
36
|
+
comm = @tag.frame_list('COMM').first
|
37
|
+
tit2 = @tag.frame_list('TIT2').first
|
38
|
+
assert_equal TagLib::ID3v2::AttachedPictureFrame, apic.class
|
39
|
+
assert_equal TagLib::ID3v2::CommentsFrame, comm.class
|
40
|
+
assert_equal TagLib::ID3v2::TextIdentificationFrame, tit2.class
|
41
|
+
end
|
42
|
+
|
43
|
+
context "APIC frame" do
|
44
|
+
setup do
|
45
|
+
@apic = @tag.frame_list('APIC').first
|
46
|
+
end
|
47
|
+
|
48
|
+
should "have a type" do
|
49
|
+
assert_equal TagLib::ID3v2::AttachedPictureFrame::FrontCover, @apic.type
|
50
|
+
end
|
51
|
+
|
52
|
+
should "have a description" do
|
53
|
+
assert_equal "Blue Marble", @apic.description
|
54
|
+
end
|
55
|
+
|
56
|
+
should "have a mime type" do
|
57
|
+
assert_equal "image/jpeg", @apic.mime_type
|
58
|
+
end
|
59
|
+
|
60
|
+
should "have picture bytes" do
|
61
|
+
assert_equal 61649, @apic.picture.size
|
62
|
+
if HAVE_ENCODING
|
63
|
+
assert_equal @picture_data.encoding, @apic.picture.encoding
|
64
|
+
end
|
65
|
+
assert_equal @picture_data, @apic.picture
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
context "TXXX frame" do
|
70
|
+
setup do
|
71
|
+
@txxx_frame = @tag.frame_list('TXXX').first
|
72
|
+
end
|
73
|
+
|
74
|
+
should "exist" do
|
75
|
+
assert_not_nil @txxx_frame
|
76
|
+
end
|
77
|
+
|
78
|
+
should "have to_s" do
|
79
|
+
expected = "[MusicBrainz Album Id] MusicBrainz Album Id 992dc19a-5631-40f5-b252-fbfedbc328a9"
|
80
|
+
assert_equal expected, @txxx_frame.to_s
|
81
|
+
end
|
82
|
+
|
83
|
+
should "be convertable to its concrete type" do
|
84
|
+
txxx = @txxx_frame.to_user_text_identification_frame
|
85
|
+
assert_equal TagLib::ID3v2::UserTextIdentificationFrame, txxx.class
|
86
|
+
end
|
87
|
+
|
88
|
+
should "have field_list" do
|
89
|
+
assert_equal ["MusicBrainz Album Id", "992dc19a-5631-40f5-b252-fbfedbc328a9"], @txxx_frame.field_list
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestID3v2Memory < Test::Unit::TestCase
|
4
|
+
|
5
|
+
N = 1000
|
6
|
+
|
7
|
+
context "TagLib::ID3v2" do
|
8
|
+
setup do
|
9
|
+
@file = TagLib::MPEG::File.new("test/data/sample.mp3", false)
|
10
|
+
@tag = @file.id3v2_tag
|
11
|
+
@apic = @tag.frame_list("APIC").first
|
12
|
+
end
|
13
|
+
|
14
|
+
should "not corrupt memory with FrameList" do
|
15
|
+
N.times do
|
16
|
+
@tag.frame_list
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
should "not corrupt memory with ByteVector" do
|
21
|
+
data = nil
|
22
|
+
N.times do
|
23
|
+
data = @apic.picture
|
24
|
+
end
|
25
|
+
N.times do
|
26
|
+
@apic.picture = data
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
should "not corrupt memory with StringList" do
|
31
|
+
txxx = @tag.frame_list('TXXX').first
|
32
|
+
N.times do
|
33
|
+
txxx.field_list
|
34
|
+
end
|
35
|
+
N.times do
|
36
|
+
txxx.field_list = ["one", "two", "three"]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
should "not segfault when tag is deleted along with file" do
|
41
|
+
@file = nil
|
42
|
+
begin
|
43
|
+
N.times do
|
44
|
+
GC.start
|
45
|
+
@tag.title
|
46
|
+
end
|
47
|
+
rescue => e
|
48
|
+
assert_equal "ObjectPreviouslyDeleted", e.class.to_s
|
49
|
+
else
|
50
|
+
raise "GC did not delete file, unsure if test was successful."
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestID3v2Tag < Test::Unit::TestCase
|
4
|
+
context "The sample.mp3 file" do
|
5
|
+
setup do
|
6
|
+
read_properties = false
|
7
|
+
@file = TagLib::MPEG::File.new("test/data/sample.mp3", read_properties)
|
8
|
+
end
|
9
|
+
|
10
|
+
should "have an ID3v2 tag" do
|
11
|
+
assert_not_nil @file.id3v2_tag
|
12
|
+
end
|
13
|
+
|
14
|
+
context "tag" do
|
15
|
+
setup do
|
16
|
+
@tag = @file.id3v2_tag
|
17
|
+
end
|
18
|
+
|
19
|
+
should "have basic properties" do
|
20
|
+
assert_equal 'Dummy Title', @tag.title
|
21
|
+
assert_equal 'Dummy Artist', @tag.artist
|
22
|
+
assert_equal 'Dummy Album', @tag.album
|
23
|
+
assert_equal 'Dummy Comment', @tag.comment
|
24
|
+
assert_equal 'Pop', @tag.genre
|
25
|
+
assert_equal 2000, @tag.year
|
26
|
+
assert_equal 1, @tag.track
|
27
|
+
assert_equal false, @tag.empty?
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestID3v2Unicode < Test::Unit::TestCase
|
4
|
+
context "The unicode.mp3 file" do
|
5
|
+
setup do
|
6
|
+
read_properties = false
|
7
|
+
@file = TagLib::MPEG::File.new("test/data/unicode.mp3", read_properties)
|
8
|
+
end
|
9
|
+
|
10
|
+
should "have an ID3v2 tag" do
|
11
|
+
assert_not_nil @file.id3v2_tag
|
12
|
+
end
|
13
|
+
|
14
|
+
if HAVE_ENCODING
|
15
|
+
context "tag" do
|
16
|
+
setup do
|
17
|
+
@tag = @file.id3v2_tag
|
18
|
+
end
|
19
|
+
|
20
|
+
should "return strings in the right encoding" do
|
21
|
+
assert_equal "UTF-8", @tag.title.encoding.to_s
|
22
|
+
end
|
23
|
+
|
24
|
+
should "convert strings to the right encoding" do
|
25
|
+
# Unicode Snowman in UTF-16
|
26
|
+
utf16_encoded = "\x26\x03"
|
27
|
+
utf16_encoded.force_encoding("UTF-16BE")
|
28
|
+
|
29
|
+
# It should be converted here
|
30
|
+
@tag.title = utf16_encoded
|
31
|
+
|
32
|
+
result = @tag.title
|
33
|
+
|
34
|
+
# In order for == to work, they have to be in the same
|
35
|
+
# encoding
|
36
|
+
utf8_encoded = utf16_encoded.encode("UTF-8")
|
37
|
+
assert_equal utf8_encoded, result
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|