ruby-taglib2 1.01

Sign up to get free protection for your applications and to get access to all the features.
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
+