ruby-taglib2 1.01

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/README ADDED
@@ -0,0 +1,178 @@
1
+ ruby-taglib2 is a compiled extension to ruby that provides access to the TagLib
2
+ library. ruby-taglib2 optionally uses the Mahoro library when available for
3
+ much more accurate detection of file formats (TagLib without Mahoro just looks
4
+ at the last few characters of the file name, while Mahoro looks at the
5
+ content).
6
+
7
+ ruby-taglib and ruby-taglib2: http://www.hakubi.us/ruby-taglib/
8
+
9
+ TagLib: http://developer.kde.org/~wheeler/taglib.html
10
+
11
+ Mahoro: http://mahoro.rubyforge.org/
12
+
13
+ #############
14
+ Installation#
15
+ #############
16
+
17
+ gem install ruby-taglib2 (gemcutter.org)
18
+
19
+ #######
20
+ Modules
21
+ #######
22
+
23
+ TagLib2
24
+
25
+ #######
26
+ Classes
27
+ #######
28
+
29
+ TagLib2::File - The central class that users of ruby-taglib2 will always use
30
+ TagLib2::Image - Stores information about images embedded in tags, can be gotten
31
+ through methods of TagLib2::File
32
+ TagLib2::FileRef - Internal use only
33
+ TagLib2::BadFile - Exception thrown when the file passed to TagLib2::File's
34
+ initializer cannot be loaded
35
+
36
+ #######
37
+ Methods
38
+ #######
39
+
40
+ All strings are to be in UTF8 format. Set KCODE to u when necessary.
41
+
42
+ TagLib2::File#title(string)
43
+ TagLib2::File#title=(string) - Get and set the title of a file
44
+
45
+ TagLib2::File#artist(string)
46
+ TagLib2::File#artist=(string) - Get and set the artist of a file
47
+
48
+ TagLib2::File#album(string)
49
+ TagLib2::File#album=(string) - Get and set the album the file is from
50
+
51
+ TagLib2::File#comment(string)
52
+ TagLib2::File#comment=(string) - Get and set a comment about the file
53
+
54
+ TagLib2::File#genre(string)
55
+ TagLib2::File#genre=(string) - Get and set a comment about the file
56
+
57
+ TagLib2::File#year(num)
58
+ TagLib2::File#year=(num) - Get and set the year of the file
59
+
60
+ TagLib2::File#track(num)
61
+ TagLib2::File#track=(num) - Get and set the the track number of the file on the
62
+ album
63
+
64
+ TagLib2::File#bitrate
65
+ TagLib2::File#sampleRate
66
+ TagLib2::File#sample_rate
67
+ TagLib2::File#channels
68
+ TagLib2::File#length - Get properties of the audio in the file
69
+
70
+ TagLib2::File#save - Save all changes to the tag
71
+
72
+ TagLib2::File#each_image
73
+ TagLib2::File#eachImage - Iterator over all images stored in the file's tag
74
+
75
+ TagLib2::File#image_count
76
+ TagLib2::File#imageCount - Number of images in the file's tag
77
+
78
+ TagLib2::File#image(num) - Returns image #num in order from eachImage
79
+
80
+ TagLib2::File#add_image(type, mimeType, description, data)
81
+ TagLib2::File#addImage(type, mimeType, description, data) - Add an image
82
+ type is an integer, the rest are strings. For
83
+ a remote image, set data to nil and place the
84
+ URL in mimeType. Otherwise mimeType should be
85
+ image/jpeg or image/png. description may be set
86
+ nil as well.
87
+
88
+ TagLib2::File#remove_image(image)
89
+ TagLib2::File#removeImage(image) - Remove an image from the tag, as returned by
90
+ #image
91
+
92
+ TagLib2::Image#type - Returns a number of the type
93
+
94
+ TagLib2::Image#description - Returns a string of the description
95
+
96
+ TagLib2::Image#mime_type
97
+ TagLib2::Image#mimeType - Returns a the mimeType of the data, or a URL
98
+
99
+ TagLib2::Image#data - Returns the actual image data, if mimeType is not a URL
100
+
101
+ ######
102
+ Images
103
+ ######
104
+
105
+ Image are only supported right now when in ID3v2 tags. Here is a list of what
106
+ the picture type numbers mean:
107
+
108
+ Picture type: 0x00 Other
109
+ 0x01 32x32 pixels 'file icon' (PNG only)
110
+ 0x02 Other file icon
111
+ 0x03 Cover (front)
112
+ 0x04 Cover (back)
113
+ 0x05 Leaflet page
114
+ 0x06 Media (e.g. label side of CD)
115
+ 0x07 Lead artist/lead performer/soloist
116
+ 0x08 Artist/performer
117
+ 0x09 Conductor
118
+ 0x0A Band/Orchestra
119
+ 0x0B Composer
120
+ 0x0C Lyricist/text writer
121
+ 0x0D Recording Location
122
+ 0x0E During recording
123
+ 0x0F During performance
124
+ 0x10 Movie/video screen capture
125
+ 0x11 A bright coloured fish
126
+ 0x12 Illustration
127
+ 0x13 Band/artist logotype
128
+ 0x14 Publisher/Studio logotype
129
+
130
+ Except where noted, all images should be of type image/jpeg or image/png.
131
+
132
+ #############
133
+ Sample of use
134
+ #############
135
+
136
+ require 'taglib2'
137
+
138
+ f = TagLib2::File.new(ARGV[0])
139
+
140
+ puts "Title: #{f.title}"
141
+ puts "Comment: #{f.comment}"
142
+ puts "Artist: #{f.artist}"
143
+ puts "Album: #{f.album}"
144
+ puts "Length: #{f.length}"
145
+ puts "Sample Rate: #{f.sampleRate}"
146
+ puts "Image Count: #{f.imageCount}"
147
+ if f.imageCount > 0
148
+ puts "Image 0 MimeType: #{f.image(0).mimeType}"
149
+ puts "Image 0 Type: #{f.image(0).type}"
150
+ puts "Image 0 Description: #{f.image(0).description}"
151
+ end
152
+
153
+ if ARGV[1] == '-setTitle'
154
+ puts "Setting Title to #{ARGV[2]}"
155
+ f.title = ARGV[2]
156
+ f.save
157
+ end
158
+
159
+ if ARGV[1] == '-dumpImage'
160
+ puts "Dumping image"
161
+ File::open(ARGV[3], 'w') do |file|
162
+ file.write(f.image(ARGV[2].to_i).data)
163
+ end
164
+ f.save
165
+ end
166
+
167
+ if ARGV[1] == '-removeImage'
168
+ puts "Removing image #{ARGV[2]}"
169
+ f.removeImage(f.image(ARGV[2].to_i))
170
+ f.save
171
+ end
172
+
173
+ if ARGV[1] == '-addImage'
174
+ puts "Adding image"
175
+ puts "f.addImage(#{ARGV[2].to_i}, #{ARGV[3]}, #{ARGV[4]}, IO::read(#{ARGV[5]}))"
176
+ f.addImage(ARGV[2].to_i, ARGV[3], ARGV[4], IO::read(ARGV[5]))
177
+ f.save
178
+ end
data/ext/extconf.rb ADDED
@@ -0,0 +1,61 @@
1
+ require 'mkmf'
2
+
3
+ # We need C++, not C, because Taglib is in C++
4
+ CONFIG['CC'] = 'g++'
5
+ CONFIG['CPP'].sub!(CONFIG['CPP'], 'g++ -E')
6
+ CONFIG['LDSHARED'].sub!(CONFIG['CC'], 'g++')
7
+
8
+ RbConfig::CONFIG['CC'] = 'g++'
9
+ RbConfig::CONFIG['CC'] = 'g++ -E'
10
+
11
+ # taglib-config does not implement libs-only-l, so we copy and paste pkg_config
12
+ # from mkmf then remove the call to taglib-config --libs-only-l
13
+ def pkg_config(pkg)
14
+ if pkgconfig = with_config("#{pkg}-config") and find_executable0(pkgconfig)
15
+ # iff package specific config command is given
16
+ get = proc {|opt| `#{pkgconfig} --#{opt}`.chomp}
17
+ elsif ($PKGCONFIG ||=
18
+ (pkgconfig = with_config("pkg-config", ("pkg-config" unless CROSS_COMPILING))) &&
19
+ find_executable0(pkgconfig) && pkgconfig) and
20
+ system("#{$PKGCONFIG} --exists #{pkg}")
21
+ # default to pkg-config command
22
+ get = proc {|opt| `#{$PKGCONFIG} --#{opt} #{pkg}`.chomp}
23
+ elsif find_executable0(pkgconfig = "#{pkg}-config")
24
+ # default to package specific config command, as a last resort.
25
+ get = proc {|opt| `#{pkgconfig} --#{opt}`.chomp}
26
+ end
27
+ if get
28
+ cflags = get['cflags']
29
+ ldflags = get['libs']
30
+ libs = ''#get['libs-only-l']
31
+ ldflags = (Shellwords.shellwords(ldflags) - Shellwords.shellwords(libs)).quote.join(" ")
32
+ $CFLAGS += " " << cflags
33
+ $LDFLAGS += " " << ldflags
34
+ $libs += " " << libs
35
+ Logging::message "package configuration for %s\n", pkg
36
+ Logging::message "cflags: %s\nldflags: %s\nlibs: %s\n\n",
37
+ cflags, ldflags, libs
38
+ [cflags, ldflags, libs]
39
+ else
40
+ Logging::message "package configuration for %s is not found\n", pkg
41
+ nil
42
+ end
43
+ end
44
+
45
+ pkg_config('taglib')
46
+
47
+ testCode = <<-EOD
48
+ #include <tag.h>
49
+ int main(int, char **)
50
+ {
51
+ return 0;
52
+ }
53
+ EOD
54
+
55
+ if try_compile(testCode)
56
+ create_makefile('taglib2')
57
+ else
58
+ puts <<-EOD
59
+ Taglib not found. Please ensure taglib-config is in your PATH.
60
+ EOD
61
+ end
@@ -0,0 +1,466 @@
1
+ #include <attachedpictureframe.h>
2
+ #include <fileref.h>
3
+ #include <flacfile.h>
4
+ #include <id3v2frame.h>
5
+ #include <id3v2tag.h>
6
+ #include <mpegfile.h>
7
+ #include <tag.h>
8
+ #include <vorbisfile.h>
9
+
10
+ // Avoid redefinition warning on Mac OS
11
+ #ifdef __APPLE__
12
+ #undef alloca
13
+ #endif
14
+
15
+ extern "C"
16
+ {
17
+ #include "ruby.h"
18
+ }
19
+
20
+ ////////////////////////
21
+ // Storage for module TagLib2 and its classes
22
+ ////////////////////////
23
+ static VALUE TagLib2Module;
24
+ static VALUE FileClass;
25
+ static VALUE RefClass;
26
+ static VALUE ImageClass;
27
+ static VALUE BadFile;
28
+ static VALUE BadTag;
29
+ static VALUE BadAudioProperties;
30
+
31
+ ////////////////////////
32
+ // Support functions useful repeatedly for bridging TagLib strings to Ruby strings
33
+ ////////////////////////
34
+ static VALUE TStrToRubyStr(const TagLib::String str)
35
+ {
36
+ const char *s = str.toCString(true);
37
+ return rb_str_new(s, strlen(s));
38
+ }
39
+
40
+ static TagLib::String RubyStrToTStr(VALUE s)
41
+ {
42
+ VALUE rStr = StringValue(s);
43
+ char *cStr = new char[RSTRING_LEN(rStr) + 1];
44
+ cStr[RSTRING_LEN(rStr)] = 0;
45
+ memcpy(cStr, RSTRING_PTR(rStr), RSTRING_LEN(rStr));
46
+ TagLib::String string(cStr, TagLib::String::UTF8);
47
+ delete[] cStr;
48
+ return string;
49
+ }
50
+
51
+ ////////////////////////
52
+ // Class to integrate Mahoro type detection into TagLib
53
+ ////////////////////////
54
+ class MahoroFileTypeResolver : public TagLib::FileRef::FileTypeResolver
55
+ {
56
+ public:
57
+ virtual TagLib::File *createFile(const char *, bool, TagLib::AudioProperties::ReadStyle) const;
58
+ };
59
+
60
+ TagLib::File *MahoroFileTypeResolver::createFile(const char *fileName, bool read,
61
+ TagLib::AudioProperties::ReadStyle style) const
62
+ {
63
+ if(RTEST(rb_const_get(TagLib2Module, rb_intern("MAHORO_PRESENT"))))
64
+ {
65
+ VALUE Mahoro = rb_const_get(rb_cObject, rb_intern("Mahoro"));
66
+ VALUE mahoro = rb_class_new_instance(0, 0, Mahoro);
67
+ rb_funcall(mahoro, rb_intern("flags="), 1,
68
+ rb_const_get(Mahoro, rb_intern("NONE")));
69
+
70
+ VALUE mime = rb_funcall(mahoro, rb_intern("file"), 1,
71
+ rb_str_new(fileName, strlen(fileName)));
72
+
73
+ if(RTEST(rb_funcall(mime, rb_intern("include?"), 1, rb_str_new("MP3", 3))))
74
+ {
75
+ return new TagLib::MPEG::File(fileName, read, style);
76
+ }
77
+
78
+ if(RTEST(rb_funcall(mime, rb_intern("include?"), 1, rb_str_new("Ogg", 3))) ||
79
+ RTEST(rb_funcall(mime, rb_intern("include?"), 1, rb_str_new("ogg", 3))) )
80
+ {
81
+ if(RTEST(rb_funcall(mime, rb_intern("include?"), 1, rb_str_new("Vorbis", 6))) ||
82
+ RTEST(rb_funcall(mime, rb_intern("include?"), 1, rb_str_new("vorbis", 6))) )
83
+ {
84
+ return new TagLib::Vorbis::File(fileName, read, style);
85
+ }
86
+ if(RTEST(rb_funcall(mime, rb_intern("include?"), 1, rb_str_new("FLAC", 6))) )
87
+ {
88
+ return new TagLib::FLAC::File(fileName, read, style);
89
+ }
90
+
91
+ }
92
+ }
93
+ return 0;
94
+ }
95
+
96
+ ////////////////////////
97
+ // Block that requires Mahoro, which we need to be able to eat the exception when
98
+ // Mahoro is not installed
99
+ ////////////////////////
100
+ static VALUE requireMahoro(VALUE)
101
+ {
102
+ return rb_require("mahoro");
103
+ }
104
+
105
+ ////////////////////////
106
+ // Deallocate class TagLib2::File::FileRef
107
+ ////////////////////////
108
+ static void freeRef(void *ref)
109
+ {
110
+ TagLib::FileRef *f = static_cast<TagLib::FileRef *>(ref);
111
+ delete f;
112
+ }
113
+
114
+ ////////////////////////
115
+ // Initialize class TagLib2::File
116
+ ////////////////////////
117
+ static VALUE FileInitialize(VALUE self, VALUE path)
118
+ {
119
+ rb_iv_set(self, "@path", path);
120
+ TagLib::FileRef *f = new TagLib::FileRef(RSTRING_PTR(StringValue(path)));
121
+
122
+ if(!f || f->isNull())
123
+ {
124
+ rb_raise(BadFile, "Unable to open file with TagLib");
125
+ return Qnil;
126
+ }
127
+
128
+ VALUE ref = Data_Wrap_Struct(RefClass, 0, freeRef, f);
129
+ rb_iv_set(self, "@ref", ref);
130
+
131
+ return self;
132
+ }
133
+
134
+ ////////////////////////
135
+ // Macros to collapse code common to most of the TagLib2::File accessors
136
+ ////////////////////////
137
+ #define GetFileRef \
138
+ TagLib::FileRef *f; \
139
+ Data_Get_Struct(rb_iv_get(self, "@ref"), TagLib::FileRef, f);
140
+
141
+ #define GetID3Tag \
142
+ TagLib::MPEG::File *mpegFile = dynamic_cast<TagLib::MPEG::File *>(f->file()); \
143
+ if(!mpegFile) \
144
+ return Qnil; \
145
+ \
146
+ TagLib::ID3v2::Tag *tag = mpegFile->ID3v2Tag(); \
147
+ if(!tag) \
148
+ return Qnil;
149
+
150
+ #define CheckTag(f) \
151
+ if(!f->tag()) \
152
+ { \
153
+ rb_raise(BadTag, "TagLib produced an invalid tag"); \
154
+ return Qnil; \
155
+ }
156
+
157
+ #define CheckProperties(f) \
158
+ if(!f->audioProperties()) \
159
+ { \
160
+ rb_raise(BadAudioProperties, "TagLib produced invalid audio properties"); \
161
+ return Qnil; \
162
+ }
163
+
164
+
165
+ #define StringAttribute(name, capName) \
166
+ static VALUE FileRead##capName(VALUE self) \
167
+ { \
168
+ GetFileRef \
169
+ CheckTag(f) \
170
+ return TStrToRubyStr(f->tag()->name()); \
171
+ } \
172
+ static VALUE FileWrite##capName(VALUE self, VALUE arg) \
173
+ { \
174
+ GetFileRef \
175
+ CheckTag(f) \
176
+ f->tag()->set##capName(RubyStrToTStr(arg)); \
177
+ return arg; \
178
+ }
179
+
180
+ #define UIntAttribute(name, capName) \
181
+ static VALUE FileRead##capName(VALUE self) \
182
+ { \
183
+ GetFileRef \
184
+ CheckTag(f) \
185
+ return UINT2NUM(f->tag()->name()); \
186
+ } \
187
+ static VALUE FileWrite##capName(VALUE self, VALUE arg) \
188
+ { \
189
+ GetFileRef \
190
+ CheckTag(f) \
191
+ f->tag()->set##capName(NUM2UINT(arg)); \
192
+ return arg; \
193
+ }
194
+
195
+ #define AttributeMethods(name, capName) \
196
+ rb_define_method(FileClass, #name, (VALUE (*)(...))FileRead##capName, 0); \
197
+ rb_define_method(FileClass, #name "=", (VALUE (*)(...))FileWrite##capName, 1);
198
+
199
+ #define IntProperty(name, capName) \
200
+ static VALUE FileRead##capName(VALUE self) \
201
+ { \
202
+ GetFileRef \
203
+ CheckProperties(f) \
204
+ return UINT2NUM(f->audioProperties()->name()); \
205
+ }
206
+
207
+ #define PropertyMethod(name, capName) \
208
+ rb_define_method(FileClass, #name, (VALUE (*)(...))FileRead##capName, 0); \
209
+
210
+ ////////////////////////
211
+ // TagLib2::File accessors
212
+ ////////////////////////
213
+
214
+ StringAttribute(title, Title)
215
+ StringAttribute(artist, Artist)
216
+ StringAttribute(album, Album)
217
+ StringAttribute(comment, Comment)
218
+ StringAttribute(genre, Genre)
219
+ UIntAttribute(year, Year)
220
+ UIntAttribute(track, Track)
221
+ IntProperty(bitrate, Bitrate)
222
+ IntProperty(sampleRate, SampleRate)
223
+ IntProperty(channels, Channels)
224
+ IntProperty(length, Length)
225
+
226
+ ////////////////////////
227
+ // TagLib2::File#save
228
+ ////////////////////////
229
+ static VALUE FileSave(VALUE self)
230
+ {
231
+ GetFileRef
232
+
233
+ f->save();
234
+ }
235
+
236
+ ////////////////////////
237
+ // TagLib2::FileSave#eachImage
238
+ ////////////////////////
239
+ static VALUE FileEachImage(VALUE self)
240
+ {
241
+ GetFileRef
242
+ GetID3Tag
243
+
244
+ VALUE apic = rb_str_new("APIC", 4);
245
+ for(TagLib::ID3v2::FrameList::ConstIterator i = tag->frameList().begin();
246
+ i != tag->frameList().end(); ++i)
247
+ {
248
+ TagLib::ID3v2::AttachedPictureFrame *f = dynamic_cast<TagLib::ID3v2::AttachedPictureFrame *>(*i);
249
+ if(f)
250
+ {
251
+ VALUE id = rb_str_new((const char *)f->frameID().data(), f->frameID().size());
252
+ if(RTEST(rb_funcall(id, rb_intern("=="), 1, apic)))
253
+ {
254
+ VALUE image = Data_Wrap_Struct(ImageClass, 0, 0, f);
255
+ rb_yield(image);
256
+ }
257
+ }
258
+ }
259
+ return self;
260
+ }
261
+
262
+ ////////////////////////
263
+ // Wrapper around FileEachImage for use with rb_iterate
264
+ ////////////////////////
265
+ static VALUE callEachImage(VALUE obj)
266
+ {
267
+ return rb_funcall(obj, rb_intern("eachImage"), 0, 0);
268
+ }
269
+
270
+ ////////////////////////
271
+ // Support block for FileImageCount
272
+ ////////////////////////
273
+ static VALUE counter(VALUE image, VALUE *count)
274
+ {
275
+ return (*count) = rb_funcall(*count, rb_intern("+"), 1, UINT2NUM(1));
276
+ }
277
+
278
+ ////////////////////////
279
+ // TagLib2::File#imageCount
280
+ ////////////////////////
281
+ static VALUE FileImageCount(VALUE self)
282
+ {
283
+ VALUE count = UINT2NUM(0);
284
+ rb_iterate(callEachImage, self, (VALUE (*)(...))counter, (VALUE)&count);
285
+ return count;
286
+ }
287
+
288
+ ////////////////////////
289
+ // Support block for FileImage
290
+ ////////////////////////
291
+ static VALUE imageFinder(VALUE image, VALUE ary)
292
+ {
293
+ VALUE count = rb_ary_entry(ary, 0);
294
+ VALUE idx = rb_ary_entry(ary, 1);
295
+ if(count == idx)
296
+ {
297
+ rb_ary_store(ary, 2, image);
298
+ rb_iter_break();
299
+ }
300
+ rb_ary_store(ary, 0, rb_funcall(count, rb_intern("+"), 1, UINT2NUM(1)));
301
+ }
302
+
303
+ ////////////////////////
304
+ // TagLib2::File#image
305
+ ////////////////////////
306
+ static VALUE FileImage(VALUE self, VALUE idx)
307
+ {
308
+ VALUE ary = rb_ary_new3(2, UINT2NUM(0), idx);
309
+ rb_iterate(callEachImage, self, (VALUE (*)(...))imageFinder, ary);
310
+ return rb_ary_entry(ary, 2);
311
+ }
312
+
313
+ ////////////////////////
314
+ // TagLib2::File#addImage
315
+ ////////////////////////
316
+ static VALUE FileAddImage(VALUE self, VALUE type, VALUE mimeType,
317
+ VALUE description, VALUE data)
318
+ {
319
+ GetFileRef
320
+ GetID3Tag
321
+ TagLib::ID3v2::AttachedPictureFrame *frame = new TagLib::ID3v2::AttachedPictureFrame;
322
+ frame->setTextEncoding(TagLib::String::UTF8);
323
+
324
+ if(RTEST(type))
325
+ {
326
+ frame->setType((TagLib::ID3v2::AttachedPictureFrame::Type)NUM2UINT(type));
327
+ }
328
+ else
329
+ {
330
+ delete frame;
331
+ rb_raise(rb_eArgError, "Type must be specified");
332
+ }
333
+
334
+ if(RTEST(mimeType))
335
+ {
336
+ frame->setMimeType(RubyStrToTStr(StringValue(mimeType)));
337
+ }
338
+ else
339
+ {
340
+ delete frame;
341
+ rb_raise(rb_eArgError, "mimeType must be specified");
342
+ }
343
+
344
+ if(RTEST(description))
345
+ {
346
+ frame->setDescription(RubyStrToTStr(StringValue(description)));
347
+ }
348
+
349
+ if(RTEST(data))
350
+ {
351
+ VALUE str = StringValue(data);
352
+ frame->setPicture(TagLib::ByteVector(RSTRING_PTR(data), RSTRING_LEN(data)));
353
+ }
354
+ tag->addFrame(frame);
355
+ }
356
+
357
+ ////////////////////////
358
+ // TagLib2::File#removeImage
359
+ ////////////////////////
360
+ static VALUE FileRemoveImage(VALUE self, VALUE image)
361
+ {
362
+ GetFileRef
363
+ GetID3Tag
364
+ TagLib::ID3v2::AttachedPictureFrame *frame;
365
+ Data_Get_Struct(image, TagLib::ID3v2::AttachedPictureFrame, frame);
366
+ tag->removeFrame(frame, true);
367
+ }
368
+
369
+ ////////////////////////
370
+ // TagLib2::Image#type
371
+ ////////////////////////
372
+ static VALUE ImageType(VALUE self)
373
+ {
374
+ TagLib::ID3v2::AttachedPictureFrame *frame;
375
+ Data_Get_Struct(self, TagLib::ID3v2::AttachedPictureFrame, frame);
376
+ return UINT2NUM(frame->type());
377
+ }
378
+
379
+ ////////////////////////
380
+ // TagLib2::Image#description
381
+ ////////////////////////
382
+ static VALUE ImageDescription(VALUE self)
383
+ {
384
+ TagLib::ID3v2::AttachedPictureFrame *frame;
385
+ Data_Get_Struct(self, TagLib::ID3v2::AttachedPictureFrame, frame);
386
+ return TStrToRubyStr(frame->description());
387
+ }
388
+
389
+ ////////////////////////
390
+ // TagLib2::Image#mimeType
391
+ ////////////////////////
392
+ static VALUE ImageMimeType(VALUE self)
393
+ {
394
+ TagLib::ID3v2::AttachedPictureFrame *frame;
395
+ Data_Get_Struct(self, TagLib::ID3v2::AttachedPictureFrame, frame);
396
+ return TStrToRubyStr(frame->mimeType());
397
+ }
398
+
399
+ ////////////////////////
400
+ // TagLib2::Image#data
401
+ ////////////////////////
402
+ static VALUE ImageData(VALUE self)
403
+ {
404
+ TagLib::ID3v2::AttachedPictureFrame *frame;
405
+ Data_Get_Struct(self, TagLib::ID3v2::AttachedPictureFrame, frame);
406
+ return rb_str_new(frame->picture().data(), frame->picture().size());
407
+ }
408
+
409
+ ////////////////////////
410
+ // TagLib2::Image#id
411
+ ////////////////////////
412
+ static VALUE ImageID(VALUE self)
413
+ {
414
+ TagLib::ID3v2::AttachedPictureFrame *frame;
415
+ Data_Get_Struct(self, TagLib::ID3v2::AttachedPictureFrame, frame);
416
+ return UINT2NUM(frame->frameID().toUInt());
417
+ }
418
+
419
+
420
+ ////////////////////////
421
+ // Main function to create module TagLib2 and its classes
422
+ ////////////////////////
423
+ extern "C" void Init_taglib2(void)
424
+ {
425
+ TagLib2Module = rb_define_module("TagLib2");
426
+
427
+ BadFile = rb_define_class_under(TagLib2Module, "BadFile", rb_eRuntimeError);
428
+ ImageClass = rb_define_class_under(TagLib2Module, "Image", rb_cObject);
429
+ FileClass = rb_define_class_under(TagLib2Module, "File", rb_cObject);
430
+ RefClass = rb_define_class_under(FileClass, "FileRef", rb_cObject);
431
+ rb_define_method(FileClass, "initialize", (VALUE (*)(...))FileInitialize, 1);
432
+ AttributeMethods(title, Title)
433
+ AttributeMethods(artist, Artist)
434
+ AttributeMethods(album, Album)
435
+ AttributeMethods(comment, Comment)
436
+ AttributeMethods(genre, Genre)
437
+ AttributeMethods(year, Year)
438
+ AttributeMethods(track, Track)
439
+ PropertyMethod(bitrate, Bitrate)
440
+ PropertyMethod(sampleRate, SampleRate)
441
+ PropertyMethod(sample_rate, SampleRate)
442
+ PropertyMethod(channels, Channels)
443
+ PropertyMethod(length, Length)
444
+ rb_define_method(FileClass, "save", (VALUE (*)(...))FileSave, 0);
445
+ rb_define_method(FileClass, "eachImage", (VALUE (*)(...))FileEachImage, 0);
446
+ rb_define_method(FileClass, "each_image", (VALUE (*)(...))FileEachImage, 0);
447
+ rb_define_method(FileClass, "imageCount", (VALUE (*)(...))FileImageCount, 0);
448
+ rb_define_method(FileClass, "image_count", (VALUE (*)(...))FileImageCount, 0);
449
+ rb_define_method(FileClass, "image", (VALUE (*)(...))FileImage, 1);
450
+ rb_define_method(FileClass, "addImage", (VALUE (*)(...))FileAddImage, 4);
451
+ rb_define_method(FileClass, "add_image", (VALUE (*)(...))FileAddImage, 4);
452
+ rb_define_method(FileClass, "removeImage", (VALUE (*)(...))FileRemoveImage, 1);
453
+ rb_define_method(FileClass, "remove_image", (VALUE (*)(...))FileRemoveImage, 1);
454
+ rb_define_method(ImageClass, "type", (VALUE (*)(...))ImageType, 0);
455
+ rb_define_method(ImageClass, "description", (VALUE (*)(...))ImageDescription, 0);
456
+ rb_define_method(ImageClass, "mimeType", (VALUE (*)(...))ImageMimeType, 0);
457
+ rb_define_method(ImageClass, "mime_type", (VALUE (*)(...))ImageMimeType, 0);
458
+ rb_define_method(ImageClass, "data", (VALUE (*)(...))ImageData, 0);
459
+ rb_define_method(ImageClass, "id", (VALUE (*)(...))ImageID, 0);
460
+
461
+ // Load Mahoro if available
462
+ int failed = 0;
463
+ VALUE ret = rb_protect(requireMahoro, Qnil, &failed);
464
+
465
+ rb_define_const(TagLib2Module, "MAHORO_PRESENT", failed ? Qfalse : Qtrue);
466
+ }
@@ -0,0 +1,6 @@
1
+ $:.unshift(File.dirname(__FILE__)) unless
2
+ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
3
+
4
+ module RubyTaglib2
5
+ VERSION = '1.01'
6
+ end
metadata ADDED
@@ -0,0 +1,58 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ruby-taglib2
3
+ version: !ruby/object:Gem::Version
4
+ version: "1.01"
5
+ platform: ruby
6
+ authors:
7
+ - Neil Stevens
8
+ - Saimon Moore
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain:
12
+ date: 2009-11-19 00:00:00 +01:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: Ruby bindings for Taglib's C Library
17
+ email: neil@hakubi.us
18
+ executables: []
19
+
20
+ extensions:
21
+ - ext/extconf.rb
22
+ extra_rdoc_files: []
23
+
24
+ files:
25
+ - README
26
+ - ext/extconf.rb
27
+ - ext/ruby-taglib2.cpp
28
+ - lib/ruby_taglib2.rb
29
+ has_rdoc: true
30
+ homepage: http://www.hakubi.us/ruby-taglib
31
+ licenses: []
32
+
33
+ post_install_message:
34
+ rdoc_options: []
35
+
36
+ require_paths:
37
+ - lib
38
+ required_ruby_version: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ">"
41
+ - !ruby/object:Gem::Version
42
+ version: 0.0.0
43
+ version:
44
+ required_rubygems_version: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: "0"
49
+ version:
50
+ requirements:
51
+ - Ruby bindings for Taglib's C Library
52
+ rubyforge_project:
53
+ rubygems_version: 1.3.5
54
+ signing_key:
55
+ specification_version: 1
56
+ summary: ruby-taglib2 is a compiled extension to ruby that provides access to the TagLib library
57
+ test_files: []
58
+