id3lib-ruby 0.3.1 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +6 -0
- data/Rakefile +16 -8
- data/ext/Rakefile +21 -0
- data/ext/generate_info.rb +114 -0
- data/ext/id3lib_api.i +179 -0
- data/ext/id3lib_api_wrap.cxx +123 -99
- data/lib/id3lib.rb +31 -24
- data/test/test_writing.rb +11 -4
- data/usage.rb +40 -0
- metadata +9 -3
data/CHANGES
CHANGED
@@ -1,5 +1,11 @@
|
|
1
1
|
= id3lib-ruby changes
|
2
2
|
|
3
|
+
=== 0.4.0 (r41)
|
4
|
+
|
5
|
+
* Fixed Unicode problems (bug 4768).
|
6
|
+
* Renamed ID3Lib::API methods to be more like the id3lib method names.
|
7
|
+
For example, the GetType() method is now named get_type instead of type.
|
8
|
+
|
3
9
|
=== 0.3.1 (r32)
|
4
10
|
|
5
11
|
* Added check and messages for -lstdc++ and -lz to extconf.rb.
|
data/Rakefile
CHANGED
@@ -10,15 +10,22 @@ require 'rake/testtask'
|
|
10
10
|
require 'rake/rdoctask'
|
11
11
|
|
12
12
|
|
13
|
-
PKG_VERSION = '0.
|
13
|
+
PKG_VERSION = '0.4.0'
|
14
14
|
|
15
|
-
|
15
|
+
FILES_COMMON = FileList[
|
16
16
|
'lib/**/*.rb',
|
17
17
|
'test/test_*.rb',
|
18
18
|
'test/data/*.mp3',
|
19
19
|
'test/data/cover.jpg',
|
20
20
|
'Rakefile',
|
21
|
-
'
|
21
|
+
'*.rb'
|
22
|
+
]
|
23
|
+
|
24
|
+
FILES_EXT = FileList[
|
25
|
+
'ext/*.rb',
|
26
|
+
'ext/*.cxx',
|
27
|
+
'ext/*.i',
|
28
|
+
'ext/Rakefile'
|
22
29
|
]
|
23
30
|
|
24
31
|
|
@@ -42,7 +49,7 @@ Rake::TestTask.new do |t|
|
|
42
49
|
end
|
43
50
|
|
44
51
|
|
45
|
-
RDOC_OPTS = ['--line-numbers', '--main', 'README']
|
52
|
+
RDOC_OPTS = ['--inline-source', '--line-numbers', '--main', 'README']
|
46
53
|
|
47
54
|
desc "Generate RDOC documentation."
|
48
55
|
Rake::RDocTask.new :rdoc do |rdoc|
|
@@ -63,7 +70,7 @@ if defined? Gem
|
|
63
70
|
'id3lib-ruby provides a Ruby interface to the id3lib C++ library for ' +
|
64
71
|
'easily editing ID3 tags (v1 and v2) like with pyid3lib.'
|
65
72
|
s.requirements << 'id3lib C++ library'
|
66
|
-
s.files =
|
73
|
+
s.files = FILES_COMMON + FILES_EXT
|
67
74
|
s.extensions = ['ext/extconf.rb']
|
68
75
|
s.test_files = FileList['test/test_*.rb']
|
69
76
|
s.has_rdoc = true
|
@@ -81,7 +88,7 @@ if defined? Gem
|
|
81
88
|
end
|
82
89
|
|
83
90
|
spec_mswin32 = spec.clone
|
84
|
-
spec_mswin32.files =
|
91
|
+
spec_mswin32.files = FILES_COMMON + FileList['ext/mswin32/id3lib_api.so']
|
85
92
|
spec_mswin32.extensions = []
|
86
93
|
spec_mswin32.require_paths = ['lib', 'ext/mswin32']
|
87
94
|
spec_mswin32.platform = Gem::Platform::WIN32
|
@@ -99,14 +106,15 @@ end # defined? Gem
|
|
99
106
|
task :web => [:web_doc] do
|
100
107
|
puts "# Now execute the following:"
|
101
108
|
puts "scp web/* robinstocker@rubyforge.org:/var/www/gforge-projects/id3lib-ruby/"
|
102
|
-
puts "scp -r web/doc robinstocker@rubyforge.org:/var/www/gforge-projects/id3lib-ruby/
|
109
|
+
puts "scp -r web/doc robinstocker@rubyforge.org:/var/www/gforge-projects/id3lib-ruby/"
|
103
110
|
end
|
104
111
|
|
105
112
|
desc "Generate RDOC documentation on web."
|
106
113
|
Rake::RDocTask.new :web_doc do |rdoc|
|
107
114
|
rdoc.rdoc_dir = 'web/doc'
|
108
115
|
rdoc.title = 'id3lib-ruby'
|
109
|
-
rdoc.options
|
116
|
+
rdoc.options = RDOC_OPTS.clone
|
117
|
+
rdoc.options << '--main' << 'ID3Lib::Tag'
|
110
118
|
rdoc.rdoc_files.include('README', 'TODO', 'CHANGES')
|
111
119
|
rdoc.rdoc_files.include('lib/**/*.rb')
|
112
120
|
end
|
data/ext/Rakefile
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
|
2
|
+
require 'rake/clean'
|
3
|
+
|
4
|
+
|
5
|
+
CLEAN.include '*.o', 'Makefile', 'mkmf.log'
|
6
|
+
CLOBBER.include 'id3lib_api.so', 'id3lib_api.bundle'
|
7
|
+
|
8
|
+
task :default => ['id3lib_api.bundle']
|
9
|
+
task :swig => ['id3lib_api_wrap.cxx']
|
10
|
+
|
11
|
+
file 'id3lib_api.bundle' => ['id3lib_api_wrap.cxx', 'Makefile'] do
|
12
|
+
sh "make"
|
13
|
+
end
|
14
|
+
|
15
|
+
file 'id3lib_api_wrap.cxx' => ['id3lib_api.i'] do
|
16
|
+
sh "swig -c++ -ruby -feature id3lib_api id3lib_api.i"
|
17
|
+
end
|
18
|
+
|
19
|
+
file 'Makefile' do
|
20
|
+
ruby "extconf.rb"
|
21
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
require 'enumerator'
|
2
|
+
|
3
|
+
file = ARGV.first || '/usr/local/include/id3/globals.h'
|
4
|
+
|
5
|
+
data = IO.read(file)
|
6
|
+
|
7
|
+
fields = []
|
8
|
+
frames = []
|
9
|
+
genres = []
|
10
|
+
|
11
|
+
data.scan(/ID3_ENUM\((\w+)\)\s+\{\s+(.+?)\s+\}/m) do |name, enum|
|
12
|
+
case name
|
13
|
+
when 'ID3_FieldID'
|
14
|
+
id = 0
|
15
|
+
enum.scan(/([^\s,]+)(?: = (\d+),|,)\s*\/\*\*< ([^*]+)\s+\*\//m) do |field, newid, description|
|
16
|
+
id = newid.to_i if newid
|
17
|
+
field.sub!('ID3FN_', '')
|
18
|
+
field.downcase!
|
19
|
+
fields << [id, field.to_sym, description]
|
20
|
+
id += 1
|
21
|
+
end
|
22
|
+
when 'ID3_FrameID'
|
23
|
+
id = 0
|
24
|
+
enum.scan(/\/\* (\S+) \*\/ [^\s,]+(?: = (\d+),|,)\s*\/\*\*< ([^*]+)\s+\*\//m) do |frame, newid, description|
|
25
|
+
id = newid.to_i if newid
|
26
|
+
if frame == '????'
|
27
|
+
frame = :____
|
28
|
+
else
|
29
|
+
frame = frame.to_sym
|
30
|
+
end
|
31
|
+
possible_fields =
|
32
|
+
case frame
|
33
|
+
when :____ : []
|
34
|
+
when :AENC : [:owner, :data]
|
35
|
+
when :APIC : [:textenc, :mimetype, :picturetype, :description, :data]
|
36
|
+
when :ASPI, :COMR, :EQUA, :ETCO, :LINK,
|
37
|
+
:MCDI, :MLLT, :OWNE, :POSS, :RBUF,
|
38
|
+
:RVA2, :RVAD, :RVRB, :SEEK
|
39
|
+
[:data]
|
40
|
+
when :COMM : [:textenc, :language, :description, :text]
|
41
|
+
when :ENCR : [:owner, :id, :data]
|
42
|
+
when :EQU2 : [:id, :text]
|
43
|
+
when :GEOB : [:textenc, :mimetype, :filename, :description, :data]
|
44
|
+
when :GRID : [:owner, :id, :data]
|
45
|
+
when :IPLS : [:textenc, :text]
|
46
|
+
when :PRIV : [:owner, :data]
|
47
|
+
when :PCNT : [:counter]
|
48
|
+
when :POPM : [:email, :rating, :counter]
|
49
|
+
when :SIGN : [:id, :data]
|
50
|
+
when :SYLT : [:textenc, :language, :timestampformat, :contenttype, :description, :data]
|
51
|
+
when :SYTC : [:timestampformat, :data]
|
52
|
+
when :UFID : [:owner, :data]
|
53
|
+
when :USER : [:textenc, :language, :text]
|
54
|
+
when :USLT : [:textenc, :language, :description, :text]
|
55
|
+
when :WCOM, :WCOP, :WOAF, :WOAR, :WOAS, :WORS, :WPAY, :WPUB : [:text]
|
56
|
+
when :WXXX : [:textenc, :description, :url]
|
57
|
+
else [:textenc, :text]
|
58
|
+
end
|
59
|
+
frames << [id, frame, description, possible_fields]
|
60
|
+
id += 1
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
data.scan(/(ID3_v1_genre_description).+?\{(.+?)\}/m) do |name, list|
|
66
|
+
id = 0
|
67
|
+
list.scan(/"(.+?)"/) do |genre|
|
68
|
+
genres << genre.first
|
69
|
+
id += 1
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
|
74
|
+
def indent level, text
|
75
|
+
puts ' ' * level + text
|
76
|
+
end
|
77
|
+
|
78
|
+
indent 4, "Frames = ["
|
79
|
+
frames.each do |f|
|
80
|
+
comment = case f[1]
|
81
|
+
when :____ : "# Special frames"
|
82
|
+
when :TALB : "# Text information frames"
|
83
|
+
when :UFID : "# Special frames again"
|
84
|
+
when :WCOM : "# URL link frames"
|
85
|
+
end
|
86
|
+
indent 6, comment if comment
|
87
|
+
indent 6, f.inspect + ","
|
88
|
+
end
|
89
|
+
indent 4, "]"
|
90
|
+
|
91
|
+
indent 4, "FramesByID = {"
|
92
|
+
frames.each do |f|
|
93
|
+
indent 6, f[1].inspect + " => Frames[" + f[0].to_s + "],"
|
94
|
+
end
|
95
|
+
indent 4, "}"
|
96
|
+
|
97
|
+
indent 4, "Fields = ["
|
98
|
+
fields.each do |f|
|
99
|
+
indent 6, f.inspect + ","
|
100
|
+
end
|
101
|
+
indent 4, "]"
|
102
|
+
|
103
|
+
indent 4, "FieldsByID = {"
|
104
|
+
fields.each do |f|
|
105
|
+
indent 6, f[1].inspect.ljust(16) + " => Fields[" + f[0].to_s + "],"
|
106
|
+
end
|
107
|
+
indent 4, "}"
|
108
|
+
|
109
|
+
indent 4, "Genres = ["
|
110
|
+
genres.each_slice(4) do |gs|
|
111
|
+
indent 6, "# Winamp extensions" if gs.first == "Folk"
|
112
|
+
indent 6, gs.map{ |g| g.inspect }.join(", ") + ","
|
113
|
+
end
|
114
|
+
indent 4, "]"
|
data/ext/id3lib_api.i
ADDED
@@ -0,0 +1,179 @@
|
|
1
|
+
%module "ID3Lib::API"
|
2
|
+
%{
|
3
|
+
#include <id3/tag.h>
|
4
|
+
%}
|
5
|
+
|
6
|
+
|
7
|
+
enum ID3_FrameID;
|
8
|
+
enum ID3_FieldID;
|
9
|
+
enum ID3_FieldType;
|
10
|
+
enum ID3_TextEnc;
|
11
|
+
enum ID3_TagType;
|
12
|
+
|
13
|
+
typedef unsigned int flags_t;
|
14
|
+
|
15
|
+
|
16
|
+
%rename (Tag) ID3_Tag;
|
17
|
+
class ID3_Tag
|
18
|
+
{
|
19
|
+
public:
|
20
|
+
|
21
|
+
ID3_Tag(const char *name = NULL);
|
22
|
+
~ID3_Tag();
|
23
|
+
|
24
|
+
%rename (has_tag_type) HasTagType;
|
25
|
+
bool HasTagType(ID3_TagType type) const;
|
26
|
+
|
27
|
+
%rename (link) Link;
|
28
|
+
size_t Link(const char *filename, flags_t flags = ID3TT_ALL);
|
29
|
+
|
30
|
+
%rename (update) Update;
|
31
|
+
flags_t Update(flags_t flags = ID3TT_ALL);
|
32
|
+
|
33
|
+
%rename (strip) Strip;
|
34
|
+
flags_t Strip(flags_t flags = ID3TT_ALL);
|
35
|
+
|
36
|
+
%rename (clear) Clear;
|
37
|
+
void Clear();
|
38
|
+
|
39
|
+
%rename (remove_frame) RemoveFrame;
|
40
|
+
ID3_Frame * RemoveFrame(const ID3_Frame *frame);
|
41
|
+
|
42
|
+
%rename (add_frame) AddFrame;
|
43
|
+
void AddFrame(const ID3_Frame *frame);
|
44
|
+
|
45
|
+
%rename (get_filename) GetFileName;
|
46
|
+
const char * GetFileName() const;
|
47
|
+
|
48
|
+
%rename (set_padding) SetPadding;
|
49
|
+
bool SetPadding(bool padding);
|
50
|
+
|
51
|
+
%rename (size) Size;
|
52
|
+
size_t Size() const;
|
53
|
+
|
54
|
+
%rename (find) Find;
|
55
|
+
ID3_Frame * Find(ID3_FrameID name) const;
|
56
|
+
|
57
|
+
%rename (iterator_new) CreateIterator;
|
58
|
+
ID3_Tag::Iterator * CreateIterator();
|
59
|
+
|
60
|
+
// Needed because SWIG does not support nested classes yet.
|
61
|
+
%extend
|
62
|
+
{
|
63
|
+
ID3_Frame * iterator_next_frame(ID3_Tag::Iterator *iterator)
|
64
|
+
{
|
65
|
+
return iterator->GetNext();
|
66
|
+
}
|
67
|
+
}
|
68
|
+
};
|
69
|
+
|
70
|
+
|
71
|
+
%rename (Frame) ID3_Frame;
|
72
|
+
class ID3_Frame
|
73
|
+
{
|
74
|
+
public:
|
75
|
+
|
76
|
+
ID3_Frame(ID3_FrameID id = ID3FID_NOFRAME);
|
77
|
+
~ID3_Frame();
|
78
|
+
|
79
|
+
%rename (get_field) GetField;
|
80
|
+
ID3_Field * GetField(ID3_FieldID name) const;
|
81
|
+
|
82
|
+
%rename (get_id) GetID;
|
83
|
+
ID3_FrameID GetID() const;
|
84
|
+
};
|
85
|
+
|
86
|
+
|
87
|
+
%rename (Field) ID3_Field;
|
88
|
+
class ID3_Field
|
89
|
+
{
|
90
|
+
public:
|
91
|
+
|
92
|
+
// Getters
|
93
|
+
|
94
|
+
%rename (get_type) GetType;
|
95
|
+
ID3_FieldType GetType() const;
|
96
|
+
|
97
|
+
%rename (get_encoding) GetEncoding;
|
98
|
+
ID3_TextEnc GetEncoding() const;
|
99
|
+
|
100
|
+
%rename (get_integer) Get;
|
101
|
+
unsigned long Get() const;
|
102
|
+
|
103
|
+
%rename (get_ascii) GetRawText;
|
104
|
+
const char * GetRawText() const;
|
105
|
+
|
106
|
+
%extend
|
107
|
+
{
|
108
|
+
VALUE get_binary()
|
109
|
+
{
|
110
|
+
return rb_str_new((const char *)self->GetRawBinary(), self->Size());
|
111
|
+
}
|
112
|
+
|
113
|
+
VALUE get_unicode()
|
114
|
+
{
|
115
|
+
const char *string = (const char *)self->GetRawUnicodeText();
|
116
|
+
if (string == NULL) return rb_str_new("", 0);
|
117
|
+
long size = self->Size();
|
118
|
+
if (size >= 2 && string[size-2] == '\0' && string[size-1] == '\0') {
|
119
|
+
// id3lib seems to be inconsistent: the Unicode strings
|
120
|
+
// don't always end in 0x0000. If they do, we don't want these
|
121
|
+
// trailing bytes.
|
122
|
+
size -= 2;
|
123
|
+
}
|
124
|
+
return rb_str_new(string, size);
|
125
|
+
}
|
126
|
+
}
|
127
|
+
|
128
|
+
// Setters
|
129
|
+
|
130
|
+
%rename (set_encoding) SetEncoding(ID3_TextEnc);
|
131
|
+
bool SetEncoding(ID3_TextEnc enc);
|
132
|
+
|
133
|
+
%rename (set_integer) Set(unsigned long);
|
134
|
+
void Set(unsigned long i);
|
135
|
+
|
136
|
+
%rename (set_ascii) Set(const char *);
|
137
|
+
size_t Set(const char *string);
|
138
|
+
|
139
|
+
%extend
|
140
|
+
{
|
141
|
+
size_t set_binary(VALUE data)
|
142
|
+
{
|
143
|
+
StringValue(data);
|
144
|
+
return self->Set((const unsigned char *)RSTRING(data)->ptr,
|
145
|
+
RSTRING(data)->len);
|
146
|
+
}
|
147
|
+
|
148
|
+
size_t set_unicode(VALUE data)
|
149
|
+
{
|
150
|
+
StringValue(data);
|
151
|
+
|
152
|
+
long len;
|
153
|
+
unicode_t *unicode;
|
154
|
+
|
155
|
+
len = RSTRING(data)->len / sizeof(unicode_t);
|
156
|
+
unicode = (unicode_t *)malloc(sizeof(unicode_t) * (len+1));
|
157
|
+
|
158
|
+
if (unicode == NULL) {
|
159
|
+
rb_raise(rb_eNoMemError, "Couldn't allocate memory for Unicode data.");
|
160
|
+
}
|
161
|
+
|
162
|
+
memcpy(unicode, RSTRING(data)->ptr, sizeof(unicode_t) * len);
|
163
|
+
// Unicode strings need 0x0000 at the end.
|
164
|
+
unicode[len] = 0;
|
165
|
+
size_t retval = self->Set(unicode);
|
166
|
+
|
167
|
+
// Free Unicode! ;)
|
168
|
+
free(unicode);
|
169
|
+
return retval;
|
170
|
+
}
|
171
|
+
}
|
172
|
+
|
173
|
+
protected:
|
174
|
+
|
175
|
+
ID3_Field();
|
176
|
+
~ID3_Field();
|
177
|
+
};
|
178
|
+
|
179
|
+
// vim: set filetype=cpp sw=4 ts=4 noexpandtab:
|
data/ext/id3lib_api_wrap.cxx
CHANGED
@@ -1795,8 +1795,8 @@ SWIG_AsVal_bool (VALUE obj, bool *val)
|
|
1795
1795
|
}
|
1796
1796
|
|
1797
1797
|
SWIGINTERN ID3_Frame *ID3_Tag_iterator_next_frame(ID3_Tag *self,ID3_Tag::Iterator *iterator){
|
1798
|
-
|
1799
|
-
|
1798
|
+
return iterator->GetNext();
|
1799
|
+
}
|
1800
1800
|
|
1801
1801
|
SWIGINTERNINLINE VALUE
|
1802
1802
|
SWIG_From_int (int value)
|
@@ -1804,49 +1804,48 @@ SWIG_From_int (int value)
|
|
1804
1804
|
return SWIG_From_long (value);
|
1805
1805
|
}
|
1806
1806
|
|
1807
|
-
SWIGINTERN VALUE
|
1808
|
-
|
1809
|
-
|
1810
|
-
SWIGINTERN VALUE
|
1811
|
-
|
1812
|
-
|
1813
|
-
|
1814
|
-
|
1815
|
-
|
1816
|
-
|
1817
|
-
|
1818
|
-
|
1819
|
-
|
1820
|
-
|
1821
|
-
|
1822
|
-
}
|
1807
|
+
SWIGINTERN VALUE ID3_Field_get_binary(ID3_Field *self){
|
1808
|
+
return rb_str_new((const char *)self->GetRawBinary(), self->Size());
|
1809
|
+
}
|
1810
|
+
SWIGINTERN VALUE ID3_Field_get_unicode(ID3_Field *self){
|
1811
|
+
const char *string = (const char *)self->GetRawUnicodeText();
|
1812
|
+
if (string == NULL) return rb_str_new("", 0);
|
1813
|
+
long size = self->Size();
|
1814
|
+
if (size >= 2 && string[size-2] == '\0' && string[size-1] == '\0') {
|
1815
|
+
// id3lib seems to be inconsistent: the Unicode strings
|
1816
|
+
// don't always end in 0x0000. If they do, we don't want these
|
1817
|
+
// trailing bytes.
|
1818
|
+
size -= 2;
|
1819
|
+
}
|
1820
|
+
return rb_str_new(string, size);
|
1821
|
+
}
|
1823
1822
|
SWIGINTERN size_t ID3_Field_set_binary(ID3_Field *self,VALUE data){
|
1824
|
-
|
1825
|
-
|
1826
|
-
|
1827
|
-
|
1823
|
+
StringValue(data);
|
1824
|
+
return self->Set((const unsigned char *)RSTRING(data)->ptr,
|
1825
|
+
RSTRING(data)->len);
|
1826
|
+
}
|
1828
1827
|
SWIGINTERN size_t ID3_Field_set_unicode(ID3_Field *self,VALUE data){
|
1829
|
-
|
1828
|
+
StringValue(data);
|
1830
1829
|
|
1831
|
-
|
1832
|
-
|
1830
|
+
long len;
|
1831
|
+
unicode_t *unicode;
|
1833
1832
|
|
1834
|
-
|
1835
|
-
|
1833
|
+
len = RSTRING(data)->len / sizeof(unicode_t);
|
1834
|
+
unicode = (unicode_t *)malloc(sizeof(unicode_t) * (len+1));
|
1836
1835
|
|
1837
|
-
|
1838
|
-
|
1839
|
-
|
1840
|
-
|
1841
|
-
|
1842
|
-
|
1843
|
-
|
1844
|
-
|
1845
|
-
|
1846
|
-
|
1847
|
-
|
1848
|
-
|
1849
|
-
|
1836
|
+
if (unicode == NULL) {
|
1837
|
+
rb_raise(rb_eNoMemError, "Couldn't allocate memory for Unicode data.");
|
1838
|
+
}
|
1839
|
+
|
1840
|
+
memcpy(unicode, RSTRING(data)->ptr, sizeof(unicode_t) * len);
|
1841
|
+
// Unicode strings need 0x0000 at the end.
|
1842
|
+
unicode[len] = 0;
|
1843
|
+
size_t retval = self->Set(unicode);
|
1844
|
+
|
1845
|
+
// Free Unicode! ;)
|
1846
|
+
free(unicode);
|
1847
|
+
return retval;
|
1848
|
+
}
|
1850
1849
|
swig_class cTag;
|
1851
1850
|
|
1852
1851
|
SWIGINTERN VALUE
|
@@ -2379,7 +2378,7 @@ fail:
|
|
2379
2378
|
|
2380
2379
|
|
2381
2380
|
SWIGINTERN VALUE
|
2382
|
-
|
2381
|
+
_wrap_Tag_get_filename(int argc, VALUE *argv, VALUE self) {
|
2383
2382
|
ID3_Tag *arg1 = (ID3_Tag *) 0 ;
|
2384
2383
|
char *result = 0 ;
|
2385
2384
|
void *argp1 = 0 ;
|
@@ -2639,7 +2638,7 @@ free_ID3_Frame(ID3_Frame *arg1) {
|
|
2639
2638
|
}
|
2640
2639
|
|
2641
2640
|
SWIGINTERN VALUE
|
2642
|
-
|
2641
|
+
_wrap_Frame_get_field(int argc, VALUE *argv, VALUE self) {
|
2643
2642
|
ID3_Frame *arg1 = (ID3_Frame *) 0 ;
|
2644
2643
|
ID3_FieldID arg2 ;
|
2645
2644
|
ID3_Field *result = 0 ;
|
@@ -2671,7 +2670,7 @@ fail:
|
|
2671
2670
|
|
2672
2671
|
|
2673
2672
|
SWIGINTERN VALUE
|
2674
|
-
|
2673
|
+
_wrap_Frame_get_id(int argc, VALUE *argv, VALUE self) {
|
2675
2674
|
ID3_Frame *arg1 = (ID3_Frame *) 0 ;
|
2676
2675
|
ID3_FrameID result;
|
2677
2676
|
void *argp1 = 0 ;
|
@@ -2697,7 +2696,7 @@ fail:
|
|
2697
2696
|
swig_class cField;
|
2698
2697
|
|
2699
2698
|
SWIGINTERN VALUE
|
2700
|
-
|
2699
|
+
_wrap_Field_get_type(int argc, VALUE *argv, VALUE self) {
|
2701
2700
|
ID3_Field *arg1 = (ID3_Field *) 0 ;
|
2702
2701
|
ID3_FieldType result;
|
2703
2702
|
void *argp1 = 0 ;
|
@@ -2721,9 +2720,9 @@ fail:
|
|
2721
2720
|
|
2722
2721
|
|
2723
2722
|
SWIGINTERN VALUE
|
2724
|
-
|
2723
|
+
_wrap_Field_get_encoding(int argc, VALUE *argv, VALUE self) {
|
2725
2724
|
ID3_Field *arg1 = (ID3_Field *) 0 ;
|
2726
|
-
|
2725
|
+
ID3_TextEnc result;
|
2727
2726
|
void *argp1 = 0 ;
|
2728
2727
|
int res1 = 0 ;
|
2729
2728
|
VALUE vresult = Qnil;
|
@@ -2733,11 +2732,11 @@ _wrap_Field_integer(int argc, VALUE *argv, VALUE self) {
|
|
2733
2732
|
}
|
2734
2733
|
res1 = SWIG_ConvertPtr(self, &argp1,SWIGTYPE_p_ID3_Field, 0 | 0 );
|
2735
2734
|
if (!SWIG_IsOK(res1)) {
|
2736
|
-
SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "
|
2735
|
+
SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GetEncoding" "', argument " "1"" of type '" "ID3_Field const *""'");
|
2737
2736
|
}
|
2738
2737
|
arg1 = reinterpret_cast< ID3_Field * >(argp1);
|
2739
|
-
result = (
|
2740
|
-
vresult =
|
2738
|
+
result = (ID3_TextEnc)((ID3_Field const *)arg1)->GetEncoding();
|
2739
|
+
vresult = SWIG_From_int(static_cast< int >(result));
|
2741
2740
|
return vresult;
|
2742
2741
|
fail:
|
2743
2742
|
return Qnil;
|
@@ -2745,9 +2744,9 @@ fail:
|
|
2745
2744
|
|
2746
2745
|
|
2747
2746
|
SWIGINTERN VALUE
|
2748
|
-
|
2747
|
+
_wrap_Field_get_integer(int argc, VALUE *argv, VALUE self) {
|
2749
2748
|
ID3_Field *arg1 = (ID3_Field *) 0 ;
|
2750
|
-
|
2749
|
+
unsigned long result;
|
2751
2750
|
void *argp1 = 0 ;
|
2752
2751
|
int res1 = 0 ;
|
2753
2752
|
VALUE vresult = Qnil;
|
@@ -2757,11 +2756,11 @@ _wrap_Field_binary(int argc, VALUE *argv, VALUE self) {
|
|
2757
2756
|
}
|
2758
2757
|
res1 = SWIG_ConvertPtr(self, &argp1,SWIGTYPE_p_ID3_Field, 0 | 0 );
|
2759
2758
|
if (!SWIG_IsOK(res1)) {
|
2760
|
-
SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "
|
2759
|
+
SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Get" "', argument " "1"" of type '" "ID3_Field const *""'");
|
2761
2760
|
}
|
2762
2761
|
arg1 = reinterpret_cast< ID3_Field * >(argp1);
|
2763
|
-
result = (
|
2764
|
-
vresult = result;
|
2762
|
+
result = (unsigned long)((ID3_Field const *)arg1)->Get();
|
2763
|
+
vresult = SWIG_From_unsigned_SS_long(static_cast< unsigned long >(result));
|
2765
2764
|
return vresult;
|
2766
2765
|
fail:
|
2767
2766
|
return Qnil;
|
@@ -2769,7 +2768,7 @@ fail:
|
|
2769
2768
|
|
2770
2769
|
|
2771
2770
|
SWIGINTERN VALUE
|
2772
|
-
|
2771
|
+
_wrap_Field_get_ascii(int argc, VALUE *argv, VALUE self) {
|
2773
2772
|
ID3_Field *arg1 = (ID3_Field *) 0 ;
|
2774
2773
|
char *result = 0 ;
|
2775
2774
|
void *argp1 = 0 ;
|
@@ -2793,7 +2792,7 @@ fail:
|
|
2793
2792
|
|
2794
2793
|
|
2795
2794
|
SWIGINTERN VALUE
|
2796
|
-
|
2795
|
+
_wrap_Field_get_binary(int argc, VALUE *argv, VALUE self) {
|
2797
2796
|
ID3_Field *arg1 = (ID3_Field *) 0 ;
|
2798
2797
|
VALUE result;
|
2799
2798
|
void *argp1 = 0 ;
|
@@ -2805,10 +2804,10 @@ _wrap_Field_unicode(int argc, VALUE *argv, VALUE self) {
|
|
2805
2804
|
}
|
2806
2805
|
res1 = SWIG_ConvertPtr(self, &argp1,SWIGTYPE_p_ID3_Field, 0 | 0 );
|
2807
2806
|
if (!SWIG_IsOK(res1)) {
|
2808
|
-
SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "
|
2807
|
+
SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "get_binary" "', argument " "1"" of type '" "ID3_Field *""'");
|
2809
2808
|
}
|
2810
2809
|
arg1 = reinterpret_cast< ID3_Field * >(argp1);
|
2811
|
-
result = (VALUE)
|
2810
|
+
result = (VALUE)ID3_Field_get_binary(arg1);
|
2812
2811
|
vresult = result;
|
2813
2812
|
return vresult;
|
2814
2813
|
fail:
|
@@ -2817,55 +2816,85 @@ fail:
|
|
2817
2816
|
|
2818
2817
|
|
2819
2818
|
SWIGINTERN VALUE
|
2820
|
-
|
2819
|
+
_wrap_Field_get_unicode(int argc, VALUE *argv, VALUE self) {
|
2821
2820
|
ID3_Field *arg1 = (ID3_Field *) 0 ;
|
2822
|
-
|
2821
|
+
VALUE result;
|
2823
2822
|
void *argp1 = 0 ;
|
2824
2823
|
int res1 = 0 ;
|
2825
|
-
|
2824
|
+
VALUE vresult = Qnil;
|
2825
|
+
|
2826
|
+
if ((argc < 0) || (argc > 0)) {
|
2827
|
+
rb_raise(rb_eArgError, "wrong # of arguments(%d for 0)",argc); SWIG_fail;
|
2828
|
+
}
|
2829
|
+
res1 = SWIG_ConvertPtr(self, &argp1,SWIGTYPE_p_ID3_Field, 0 | 0 );
|
2830
|
+
if (!SWIG_IsOK(res1)) {
|
2831
|
+
SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "get_unicode" "', argument " "1"" of type '" "ID3_Field *""'");
|
2832
|
+
}
|
2833
|
+
arg1 = reinterpret_cast< ID3_Field * >(argp1);
|
2834
|
+
result = (VALUE)ID3_Field_get_unicode(arg1);
|
2835
|
+
vresult = result;
|
2836
|
+
return vresult;
|
2837
|
+
fail:
|
2838
|
+
return Qnil;
|
2839
|
+
}
|
2840
|
+
|
2841
|
+
|
2842
|
+
SWIGINTERN VALUE
|
2843
|
+
_wrap_Field_set_encoding(int argc, VALUE *argv, VALUE self) {
|
2844
|
+
ID3_Field *arg1 = (ID3_Field *) 0 ;
|
2845
|
+
ID3_TextEnc arg2 ;
|
2846
|
+
bool result;
|
2847
|
+
void *argp1 = 0 ;
|
2848
|
+
int res1 = 0 ;
|
2849
|
+
int val2 ;
|
2826
2850
|
int ecode2 = 0 ;
|
2851
|
+
VALUE vresult = Qnil;
|
2827
2852
|
|
2828
2853
|
if ((argc < 1) || (argc > 1)) {
|
2829
2854
|
rb_raise(rb_eArgError, "wrong # of arguments(%d for 1)",argc); SWIG_fail;
|
2830
2855
|
}
|
2831
2856
|
res1 = SWIG_ConvertPtr(self, &argp1,SWIGTYPE_p_ID3_Field, 0 | 0 );
|
2832
2857
|
if (!SWIG_IsOK(res1)) {
|
2833
|
-
SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "
|
2858
|
+
SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "SetEncoding" "', argument " "1"" of type '" "ID3_Field *""'");
|
2834
2859
|
}
|
2835
2860
|
arg1 = reinterpret_cast< ID3_Field * >(argp1);
|
2836
|
-
ecode2 =
|
2861
|
+
ecode2 = SWIG_AsVal_int(argv[0], &val2);
|
2837
2862
|
if (!SWIG_IsOK(ecode2)) {
|
2838
|
-
SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "
|
2863
|
+
SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "SetEncoding" "', argument " "2"" of type '" "ID3_TextEnc""'");
|
2839
2864
|
}
|
2840
|
-
arg2 = static_cast<
|
2841
|
-
(arg1)->
|
2842
|
-
|
2865
|
+
arg2 = static_cast< ID3_TextEnc >(val2);
|
2866
|
+
result = (bool)(arg1)->SetEncoding(arg2);
|
2867
|
+
vresult = SWIG_From_bool(static_cast< bool >(result));
|
2868
|
+
return vresult;
|
2843
2869
|
fail:
|
2844
2870
|
return Qnil;
|
2845
2871
|
}
|
2846
2872
|
|
2847
2873
|
|
2848
2874
|
SWIGINTERN VALUE
|
2849
|
-
|
2875
|
+
_wrap_Field_set_integer(int argc, VALUE *argv, VALUE self) {
|
2850
2876
|
ID3_Field *arg1 = (ID3_Field *) 0 ;
|
2851
|
-
|
2852
|
-
size_t result;
|
2877
|
+
unsigned long arg2 ;
|
2853
2878
|
void *argp1 = 0 ;
|
2854
2879
|
int res1 = 0 ;
|
2855
|
-
|
2880
|
+
unsigned long val2 ;
|
2881
|
+
int ecode2 = 0 ;
|
2856
2882
|
|
2857
2883
|
if ((argc < 1) || (argc > 1)) {
|
2858
2884
|
rb_raise(rb_eArgError, "wrong # of arguments(%d for 1)",argc); SWIG_fail;
|
2859
2885
|
}
|
2860
2886
|
res1 = SWIG_ConvertPtr(self, &argp1,SWIGTYPE_p_ID3_Field, 0 | 0 );
|
2861
2887
|
if (!SWIG_IsOK(res1)) {
|
2862
|
-
SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "
|
2888
|
+
SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Set" "', argument " "1"" of type '" "ID3_Field *""'");
|
2863
2889
|
}
|
2864
2890
|
arg1 = reinterpret_cast< ID3_Field * >(argp1);
|
2865
|
-
|
2866
|
-
|
2867
|
-
|
2868
|
-
|
2891
|
+
ecode2 = SWIG_AsVal_unsigned_SS_long(argv[0], &val2);
|
2892
|
+
if (!SWIG_IsOK(ecode2)) {
|
2893
|
+
SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Set" "', argument " "2"" of type '" "unsigned long""'");
|
2894
|
+
}
|
2895
|
+
arg2 = static_cast< unsigned long >(val2);
|
2896
|
+
(arg1)->Set(arg2);
|
2897
|
+
return Qnil;
|
2869
2898
|
fail:
|
2870
2899
|
return Qnil;
|
2871
2900
|
}
|
@@ -2907,14 +2936,12 @@ fail:
|
|
2907
2936
|
|
2908
2937
|
|
2909
2938
|
SWIGINTERN VALUE
|
2910
|
-
|
2939
|
+
_wrap_Field_set_binary(int argc, VALUE *argv, VALUE self) {
|
2911
2940
|
ID3_Field *arg1 = (ID3_Field *) 0 ;
|
2912
|
-
|
2913
|
-
|
2941
|
+
VALUE arg2 = (VALUE) 0 ;
|
2942
|
+
size_t result;
|
2914
2943
|
void *argp1 = 0 ;
|
2915
2944
|
int res1 = 0 ;
|
2916
|
-
int val2 ;
|
2917
|
-
int ecode2 = 0 ;
|
2918
2945
|
VALUE vresult = Qnil;
|
2919
2946
|
|
2920
2947
|
if ((argc < 1) || (argc > 1)) {
|
@@ -2922,16 +2949,12 @@ _wrap_Field_set_encoding(int argc, VALUE *argv, VALUE self) {
|
|
2922
2949
|
}
|
2923
2950
|
res1 = SWIG_ConvertPtr(self, &argp1,SWIGTYPE_p_ID3_Field, 0 | 0 );
|
2924
2951
|
if (!SWIG_IsOK(res1)) {
|
2925
|
-
SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "
|
2952
|
+
SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "set_binary" "', argument " "1"" of type '" "ID3_Field *""'");
|
2926
2953
|
}
|
2927
2954
|
arg1 = reinterpret_cast< ID3_Field * >(argp1);
|
2928
|
-
|
2929
|
-
|
2930
|
-
|
2931
|
-
}
|
2932
|
-
arg2 = static_cast< ID3_TextEnc >(val2);
|
2933
|
-
result = (bool)(arg1)->SetEncoding(arg2);
|
2934
|
-
vresult = SWIG_From_bool(static_cast< bool >(result));
|
2955
|
+
arg2 = argv[0];
|
2956
|
+
result = ID3_Field_set_binary(arg1,arg2);
|
2957
|
+
vresult = SWIG_From_size_t(static_cast< size_t >(result));
|
2935
2958
|
return vresult;
|
2936
2959
|
fail:
|
2937
2960
|
return Qnil;
|
@@ -3242,7 +3265,7 @@ SWIGEXPORT void Init_id3lib_api(void) {
|
|
3242
3265
|
rb_define_method(cTag.klass, "clear", VALUEFUNC(_wrap_Tag_clear), -1);
|
3243
3266
|
rb_define_method(cTag.klass, "remove_frame", VALUEFUNC(_wrap_Tag_remove_frame), -1);
|
3244
3267
|
rb_define_method(cTag.klass, "add_frame", VALUEFUNC(_wrap_Tag_add_frame), -1);
|
3245
|
-
rb_define_method(cTag.klass, "
|
3268
|
+
rb_define_method(cTag.klass, "get_filename", VALUEFUNC(_wrap_Tag_get_filename), -1);
|
3246
3269
|
rb_define_method(cTag.klass, "set_padding", VALUEFUNC(_wrap_Tag_set_padding), -1);
|
3247
3270
|
rb_define_method(cTag.klass, "size", VALUEFUNC(_wrap_Tag_size), -1);
|
3248
3271
|
rb_define_method(cTag.klass, "find", VALUEFUNC(_wrap_Tag_find), -1);
|
@@ -3256,8 +3279,8 @@ SWIGEXPORT void Init_id3lib_api(void) {
|
|
3256
3279
|
SWIG_TypeClientData(SWIGTYPE_p_ID3_Frame, (void *) &cFrame);
|
3257
3280
|
rb_define_alloc_func(cFrame.klass, _wrap_Frame_allocate);
|
3258
3281
|
rb_define_method(cFrame.klass, "initialize", VALUEFUNC(_wrap_new_Frame), -1);
|
3259
|
-
rb_define_method(cFrame.klass, "
|
3260
|
-
rb_define_method(cFrame.klass, "
|
3282
|
+
rb_define_method(cFrame.klass, "get_field", VALUEFUNC(_wrap_Frame_get_field), -1);
|
3283
|
+
rb_define_method(cFrame.klass, "get_id", VALUEFUNC(_wrap_Frame_get_id), -1);
|
3261
3284
|
cFrame.mark = 0;
|
3262
3285
|
cFrame.destroy = (void (*)(void *)) free_ID3_Frame;
|
3263
3286
|
cFrame.trackObjects = 0;
|
@@ -3265,15 +3288,16 @@ SWIGEXPORT void Init_id3lib_api(void) {
|
|
3265
3288
|
cField.klass = rb_define_class_under(mAPI, "Field", rb_cObject);
|
3266
3289
|
SWIG_TypeClientData(SWIGTYPE_p_ID3_Field, (void *) &cField);
|
3267
3290
|
rb_undef_alloc_func(cField.klass);
|
3268
|
-
rb_define_method(cField.klass, "
|
3269
|
-
rb_define_method(cField.klass, "
|
3270
|
-
rb_define_method(cField.klass, "
|
3271
|
-
rb_define_method(cField.klass, "
|
3272
|
-
rb_define_method(cField.klass, "
|
3291
|
+
rb_define_method(cField.klass, "get_type", VALUEFUNC(_wrap_Field_get_type), -1);
|
3292
|
+
rb_define_method(cField.klass, "get_encoding", VALUEFUNC(_wrap_Field_get_encoding), -1);
|
3293
|
+
rb_define_method(cField.klass, "get_integer", VALUEFUNC(_wrap_Field_get_integer), -1);
|
3294
|
+
rb_define_method(cField.klass, "get_ascii", VALUEFUNC(_wrap_Field_get_ascii), -1);
|
3295
|
+
rb_define_method(cField.klass, "get_binary", VALUEFUNC(_wrap_Field_get_binary), -1);
|
3296
|
+
rb_define_method(cField.klass, "get_unicode", VALUEFUNC(_wrap_Field_get_unicode), -1);
|
3297
|
+
rb_define_method(cField.klass, "set_encoding", VALUEFUNC(_wrap_Field_set_encoding), -1);
|
3273
3298
|
rb_define_method(cField.klass, "set_integer", VALUEFUNC(_wrap_Field_set_integer), -1);
|
3274
|
-
rb_define_method(cField.klass, "set_binary", VALUEFUNC(_wrap_Field_set_binary), -1);
|
3275
3299
|
rb_define_method(cField.klass, "set_ascii", VALUEFUNC(_wrap_Field_set_ascii), -1);
|
3276
|
-
rb_define_method(cField.klass, "
|
3300
|
+
rb_define_method(cField.klass, "set_binary", VALUEFUNC(_wrap_Field_set_binary), -1);
|
3277
3301
|
rb_define_method(cField.klass, "set_unicode", VALUEFUNC(_wrap_Field_set_unicode), -1);
|
3278
3302
|
cField.mark = 0;
|
3279
3303
|
cField.trackObjects = 0;
|
data/lib/id3lib.rb
CHANGED
@@ -327,25 +327,26 @@ module ID3Lib
|
|
327
327
|
|
328
328
|
def self.read(libframe)
|
329
329
|
frame = {}
|
330
|
-
info = Info.frame_num(libframe.
|
330
|
+
info = Info.frame_num(libframe.get_id)
|
331
331
|
frame[:id] = info[ID]
|
332
|
-
|
333
|
-
textenc = field(libframe, :textenc).integer
|
334
|
-
frame[:textenc] = textenc
|
335
|
-
end
|
332
|
+
|
336
333
|
info[FIELDS].each do |field_id|
|
337
|
-
next if field_id == :textenc
|
338
334
|
libfield = field(libframe, field_id)
|
339
|
-
frame[field_id] =
|
340
|
-
libfield.
|
341
|
-
|
342
|
-
|
343
|
-
when :
|
344
|
-
|
345
|
-
when :text
|
335
|
+
frame[field_id] =
|
336
|
+
case Info::FieldType[libfield.get_type]
|
337
|
+
when :integer
|
338
|
+
libfield.get_integer
|
339
|
+
when :binary
|
340
|
+
libfield.get_binary
|
341
|
+
when :text
|
342
|
+
if libfield.get_encoding > 0
|
343
|
+
libfield.get_unicode
|
344
|
+
else
|
345
|
+
libfield.get_ascii
|
346
|
+
end
|
346
347
|
end
|
347
|
-
end
|
348
348
|
end
|
349
|
+
|
349
350
|
frame
|
350
351
|
end
|
351
352
|
|
@@ -353,29 +354,35 @@ module ID3Lib
|
|
353
354
|
if textenc = frame[:textenc]
|
354
355
|
field(libframe, :textenc).set_integer(textenc)
|
355
356
|
end
|
357
|
+
|
356
358
|
frame.each do |field_id, value|
|
357
359
|
next if field_id == :textenc
|
358
360
|
unless Info.frame(frame[:id])[FIELDS].include?(field_id)
|
359
361
|
# Ignore invalid fields
|
360
362
|
next
|
361
363
|
end
|
364
|
+
|
362
365
|
libfield = field(libframe, field_id)
|
363
|
-
|
364
|
-
|
365
|
-
libfield.
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
366
|
+
case Info::FieldType[libfield.get_type]
|
367
|
+
when :integer
|
368
|
+
libfield.set_integer(value)
|
369
|
+
when :binary
|
370
|
+
libfield.set_binary(value)
|
371
|
+
when :text
|
372
|
+
if textenc and textenc > 0 and
|
373
|
+
[:text, :description, :filename].include?(field_id)
|
374
|
+
# Special treatment for Unicode
|
375
|
+
libfield.set_encoding(textenc)
|
376
|
+
libfield.set_unicode(value)
|
377
|
+
else
|
378
|
+
libfield.set_ascii(value)
|
372
379
|
end
|
373
380
|
end
|
374
381
|
end
|
375
382
|
end
|
376
383
|
|
377
384
|
def self.field(libframe, id)
|
378
|
-
libframe.
|
385
|
+
libframe.get_field(Info.field(id)[NUM])
|
379
386
|
end
|
380
387
|
|
381
388
|
end
|
data/test/test_writing.rb
CHANGED
@@ -172,12 +172,19 @@ class TestWriting < Test::Unit::TestCase
|
|
172
172
|
|
173
173
|
def test_unicode
|
174
174
|
nihao = "\x4f\x60\x59\x7d"
|
175
|
-
|
176
|
-
|
175
|
+
frame = {
|
176
|
+
:id => :COMM,
|
177
|
+
:text => nihao,
|
178
|
+
:description => nihao,
|
179
|
+
:language => "zho",
|
180
|
+
:textenc => 1
|
181
|
+
}
|
182
|
+
@tag.comment = nil
|
183
|
+
@tag << frame
|
177
184
|
@tag.update!(ID3Lib::V2)
|
178
|
-
assert_equal
|
185
|
+
assert_equal frame, @tag.frame(:COMM)
|
179
186
|
reload!(ID3Lib::V2)
|
180
|
-
assert_equal
|
187
|
+
assert_equal frame, @tag.frame(:COMM)
|
181
188
|
end
|
182
189
|
|
183
190
|
def test_unicode_invalid_data
|
data/usage.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
|
2
|
+
require 'rubygems'
|
3
|
+
require 'id3lib'
|
4
|
+
|
5
|
+
# Load a tag from a file
|
6
|
+
tag = ID3Lib::Tag.new('talk.mp3')
|
7
|
+
|
8
|
+
# Get and set text frames with convenience methods
|
9
|
+
tag.title #=> "Talk"
|
10
|
+
tag.album = 'X&Y'
|
11
|
+
tag.track = '5/13'
|
12
|
+
|
13
|
+
# Tag is a subclass of Array and each frame is a Hash
|
14
|
+
tag[0]
|
15
|
+
#=> { :id => :TPE1, :textenc => 0, :text => "Coldplay" }
|
16
|
+
|
17
|
+
# Get the number of frames
|
18
|
+
tag.length #=> 7
|
19
|
+
|
20
|
+
# Remove all comment frames
|
21
|
+
tag.delete_if{ |frame| frame[:id] == :COMM }
|
22
|
+
|
23
|
+
# Get info about APIC frame to see which fields are allowed
|
24
|
+
ID3Lib::Info.frame(:APIC)
|
25
|
+
#=> [ 2, :APIC, "Attached picture",
|
26
|
+
#=> [:textenc, :mimetype, :picturetype, :description, :data] ]
|
27
|
+
|
28
|
+
# Add an attached picture frame
|
29
|
+
cover = {
|
30
|
+
:id => :APIC,
|
31
|
+
:mimetype => 'image/jpeg',
|
32
|
+
:picturetype => 3,
|
33
|
+
:description => 'A pretty picture',
|
34
|
+
:textenc => 0,
|
35
|
+
:data => File.read('cover.jpg')
|
36
|
+
}
|
37
|
+
tag << cover
|
38
|
+
|
39
|
+
# Last but not least, apply changes
|
40
|
+
tag.update!
|
metadata
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
|
-
rubygems_version: 0.8.
|
2
|
+
rubygems_version: 0.8.99
|
3
3
|
specification_version: 1
|
4
4
|
name: id3lib-ruby
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.
|
7
|
-
date: 2006-06-
|
6
|
+
version: 0.4.0
|
7
|
+
date: 2006-06-27 00:00:00 +02:00
|
8
8
|
summary: id3lib-ruby provides a Ruby interface to the id3lib C++ library for easily editing ID3 tags (v1 and v2) like with pyid3lib.
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -25,6 +25,7 @@ required_ruby_version: !ruby/object:Gem::Version::Requirement
|
|
25
25
|
platform: ruby
|
26
26
|
signing_key:
|
27
27
|
cert_chain:
|
28
|
+
post_install_message:
|
28
29
|
authors:
|
29
30
|
- Robin Stocker
|
30
31
|
files:
|
@@ -37,9 +38,13 @@ files:
|
|
37
38
|
- test/data/unicode.mp3
|
38
39
|
- test/data/cover.jpg
|
39
40
|
- Rakefile
|
41
|
+
- usage.rb
|
40
42
|
- setup.rb
|
41
43
|
- ext/extconf.rb
|
44
|
+
- ext/generate_info.rb
|
42
45
|
- ext/id3lib_api_wrap.cxx
|
46
|
+
- ext/id3lib_api.i
|
47
|
+
- ext/Rakefile
|
43
48
|
- README
|
44
49
|
- CHANGES
|
45
50
|
- TODO
|
@@ -47,6 +52,7 @@ test_files:
|
|
47
52
|
- test/test_writing.rb
|
48
53
|
- test/test_reading.rb
|
49
54
|
rdoc_options:
|
55
|
+
- --inline-source
|
50
56
|
- --line-numbers
|
51
57
|
- --main
|
52
58
|
- README
|