taglib-ruby 0.2.1 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES.md +7 -0
- data/Gemfile +1 -2
- data/Gemfile.lock +9 -8
- data/README.md +22 -7
- data/Rakefile +9 -15
- data/docs/taglib/base.rb +31 -8
- data/docs/taglib/id3v1.rb +5 -0
- data/docs/taglib/mpeg.rb +8 -0
- data/docs/taglib/ogg.rb +77 -0
- data/docs/taglib/vorbis.rb +43 -0
- data/ext/taglib_base/includes.i +25 -1
- data/ext/taglib_base/taglib_base.i +46 -2
- data/ext/taglib_base/taglib_base_wrap.cxx +176 -185
- data/ext/taglib_id3v1/extconf.rb +4 -0
- data/ext/taglib_id3v1/taglib_id3v1.i +11 -0
- data/ext/taglib_id3v1/taglib_id3v1_wrap.cxx +3092 -0
- data/ext/taglib_id3v2/taglib_id3v2.i +0 -8
- data/ext/taglib_id3v2/taglib_id3v2_wrap.cxx +194 -248
- data/ext/taglib_mpeg/taglib_mpeg.i +16 -2
- data/ext/taglib_mpeg/taglib_mpeg_wrap.cxx +157 -149
- data/ext/taglib_ogg/extconf.rb +4 -0
- data/ext/taglib_ogg/taglib_ogg.i +36 -0
- data/ext/taglib_ogg/taglib_ogg_wrap.cxx +3613 -0
- data/ext/taglib_vorbis/extconf.rb +4 -0
- data/ext/taglib_vorbis/taglib_vorbis.i +48 -0
- data/ext/taglib_vorbis/taglib_vorbis_wrap.cxx +3056 -0
- data/ext/win.cmake +6 -0
- data/lib/taglib/id3v1.rb +1 -0
- data/lib/taglib/ogg.rb +1 -0
- data/lib/taglib/version.rb +2 -2
- data/lib/taglib/vorbis.rb +1 -0
- data/lib/taglib.rb +10 -0
- data/taglib-ruby.gemspec +35 -11
- data/tasks/ext.rake +79 -0
- data/tasks/swig.rake +43 -0
- data/test/data/Makefile +15 -0
- data/test/data/id3v1-create.cpp +31 -0
- data/test/data/id3v1.mp3 +0 -0
- data/test/data/vorbis-create.cpp +42 -0
- data/test/data/vorbis.oga +0 -0
- data/test/test_fileref_write.rb +38 -0
- data/test/test_id3v1_tag.rb +36 -0
- data/test/test_id3v2_frames.rb +5 -0
- data/test/test_id3v2_memory.rb +23 -0
- data/test/test_id3v2_relative_volume.rb +5 -0
- data/test/test_id3v2_tag.rb +5 -0
- data/test/test_id3v2_unicode.rb +5 -0
- data/test/test_id3v2_write.rb +6 -1
- data/test/test_mpeg_file.rb +18 -1
- data/test/test_vorbis_file.rb +44 -0
- data/test/test_vorbis_tag.rb +79 -0
- metadata +113 -137
- data/ext/Rakefile +0 -32
data/CHANGES.md
CHANGED
@@ -1,6 +1,13 @@
|
|
1
1
|
Changes in Releases of taglib-ruby
|
2
2
|
==================================
|
3
3
|
|
4
|
+
## 0.3.0 (2012-01-02)
|
5
|
+
|
6
|
+
* Add support for Ogg Vorbis
|
7
|
+
* Add support for ID3v1 (#2)
|
8
|
+
* Add #close to File classes for explicitly releasing resources
|
9
|
+
* Fix compilation on Windows
|
10
|
+
|
4
11
|
## 0.2.1 (2011-11-05)
|
5
12
|
|
6
13
|
* Fix compilation error due to missing typedef on some systems (#5)
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,35 +1,36 @@
|
|
1
1
|
GEM
|
2
2
|
remote: http://rubygems.org/
|
3
3
|
specs:
|
4
|
+
ffi (1.0.11)
|
4
5
|
git (1.2.5)
|
5
|
-
guard (0.
|
6
|
+
guard (0.9.3)
|
7
|
+
ffi (>= 0.5.0)
|
6
8
|
thor (~> 0.14.6)
|
7
|
-
guard-test (0.4.
|
9
|
+
guard-test (0.4.3)
|
8
10
|
guard (>= 0.4)
|
9
11
|
test-unit (~> 2.2)
|
10
12
|
jeweler (1.6.4)
|
11
13
|
bundler (~> 1.0)
|
12
14
|
git (>= 1.2.5)
|
13
15
|
rake
|
14
|
-
rake (0.9.2)
|
16
|
+
rake (0.9.2.2)
|
15
17
|
rake-compiler (0.7.9)
|
16
18
|
rake
|
17
|
-
rcov (0.9.11)
|
18
19
|
redcarpet (1.17.2)
|
19
20
|
shoulda (2.11.3)
|
20
|
-
test-unit (2.4.
|
21
|
+
test-unit (2.4.3)
|
21
22
|
thor (0.14.6)
|
22
|
-
yard (0.7.
|
23
|
+
yard (0.7.4)
|
23
24
|
|
24
25
|
PLATFORMS
|
25
26
|
ruby
|
27
|
+
x86-mingw32
|
26
28
|
|
27
29
|
DEPENDENCIES
|
28
30
|
bundler (~> 1.0.0)
|
29
31
|
guard-test (~> 0.4.0)
|
30
32
|
jeweler (~> 1.6.4)
|
31
33
|
rake-compiler (~> 0.7)
|
32
|
-
|
33
|
-
redcarpet
|
34
|
+
redcarpet (~> 1.0)
|
34
35
|
shoulda (~> 2.11)
|
35
36
|
yard (~> 0.7)
|
data/README.md
CHANGED
@@ -3,15 +3,24 @@ taglib-ruby
|
|
3
3
|
|
4
4
|
Ruby interface for the [TagLib C++ library][taglib].
|
5
5
|
|
6
|
-
In contrast to other libraries, this one wraps the full C++ API
|
7
|
-
|
8
|
-
|
6
|
+
In contrast to other libraries, this one wraps the full C++ API, not
|
7
|
+
only the minimal C API. This means that all tag data can be accessed,
|
8
|
+
e.g. cover art of ID3v2 or custom fields of Ogg Vorbis comments.
|
9
9
|
|
10
|
-
taglib-ruby is work in progress,
|
11
|
-
to do (contributors very welcome):
|
10
|
+
taglib-ruby is work in progress, but the following is already available:
|
12
11
|
|
13
|
-
*
|
14
|
-
*
|
12
|
+
* Reading/writing common tag data of all formats that TagLib supports
|
13
|
+
* Reading/writing ID3v1 and ID3v2 including ID3v2.4 and Unicode
|
14
|
+
* Reading/writing Ogg Vorbis comments
|
15
|
+
* Reading audio properties (e.g. bitrate) of the above formats
|
16
|
+
|
17
|
+
Some things are still left to do (contributors very welcome):
|
18
|
+
|
19
|
+
* Pre-compiled Gem for Windows:
|
20
|
+
* Unicode filename support
|
21
|
+
* More coverage of the library
|
22
|
+
|
23
|
+
[![flattr this project][flattr-img]][flattr-link]
|
15
24
|
|
16
25
|
Installation
|
17
26
|
------------
|
@@ -61,6 +70,9 @@ track.to_s #=> "7/10"
|
|
61
70
|
cover = tag.frame_list('APIC').first
|
62
71
|
cover.mime_type #=> "image/jpeg"
|
63
72
|
cover.picture #=> "\xFF\xD8\xFF\xE0\x00\x10JFIF..."
|
73
|
+
|
74
|
+
# Close file to release resources
|
75
|
+
file.close
|
64
76
|
```
|
65
77
|
|
66
78
|
And here's an example for writing one:
|
@@ -83,6 +95,7 @@ apic.picture = File.open("cover.jpg", 'rb'){ |f| f.read }
|
|
83
95
|
tag.add_frame(apic)
|
84
96
|
|
85
97
|
file.save
|
98
|
+
file.close
|
86
99
|
```
|
87
100
|
|
88
101
|
### Encoding
|
@@ -139,3 +152,5 @@ see LICENSE.txt for details.
|
|
139
152
|
Copyright (c) 2010, 2011 Robin Stocker.
|
140
153
|
|
141
154
|
[taglib]: http://developer.kde.org/~wheeler/taglib.html
|
155
|
+
[flattr-img]: http://api.flattr.com/button/flattr-badge-large.png
|
156
|
+
[flattr-link]: https://flattr.com/submit/auto?user_id=robinst&url=https://github.com/robinst/taglib-ruby&title=taglib-ruby&tags=github&category=software
|
data/Rakefile
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
3
|
require 'rubygems'
|
4
|
+
require "rubygems/package_task"
|
4
5
|
require 'bundler'
|
5
6
|
begin
|
6
7
|
Bundler.setup(:default, :development)
|
@@ -13,7 +14,7 @@ require 'rake'
|
|
13
14
|
|
14
15
|
require 'jeweler'
|
15
16
|
require './lib/taglib/version.rb'
|
16
|
-
Jeweler::Tasks.new do |gem|
|
17
|
+
jeweler_tasks = Jeweler::Tasks.new do |gem|
|
17
18
|
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
18
19
|
gem.name = "taglib-ruby"
|
19
20
|
gem.summary = %Q{Ruby interface for the taglib C++ library}
|
@@ -31,16 +32,15 @@ not only the minimal C API. This means that all tags can be accessed.
|
|
31
32
|
gem.authors = ["Robin Stocker"]
|
32
33
|
gem.extensions = ['ext/taglib_base/extconf.rb',
|
33
34
|
'ext/taglib_mpeg/extconf.rb',
|
34
|
-
'ext/
|
35
|
+
'ext/taglib_id3v1/extconf.rb',
|
36
|
+
'ext/taglib_id3v2/extconf.rb',
|
37
|
+
'ext/taglib_ogg/extconf.rb',
|
38
|
+
'ext/taglib_vorbis/extconf.rb']
|
39
|
+
gem.extra_rdoc_files = ["README.md", "CHANGES.md", "LICENSE.txt"]
|
35
40
|
# dependencies defined in Gemfile
|
36
41
|
end
|
37
42
|
Jeweler::RubygemsDotOrgTasks.new
|
38
43
|
|
39
|
-
require 'rake/extensiontask'
|
40
|
-
Rake::ExtensionTask.new("taglib_base")
|
41
|
-
Rake::ExtensionTask.new("taglib_mpeg")
|
42
|
-
Rake::ExtensionTask.new("taglib_id3v2")
|
43
|
-
|
44
44
|
require 'rake/testtask'
|
45
45
|
Rake::TestTask.new(:test) do |test|
|
46
46
|
test.libs << 'lib' << 'test'
|
@@ -48,14 +48,6 @@ Rake::TestTask.new(:test) do |test|
|
|
48
48
|
test.verbose = true
|
49
49
|
end
|
50
50
|
|
51
|
-
require 'rcov/rcovtask'
|
52
|
-
Rcov::RcovTask.new do |test|
|
53
|
-
test.libs << 'test'
|
54
|
-
test.pattern = 'test/**/test_*.rb'
|
55
|
-
test.verbose = true
|
56
|
-
test.rcov_opts << '--exclude "gems/*"'
|
57
|
-
end
|
58
|
-
|
59
51
|
task :default => :test
|
60
52
|
|
61
53
|
require 'yard'
|
@@ -64,4 +56,6 @@ YARD::Rake::YardocTask.new do |t|
|
|
64
56
|
t.options = ['--title', "taglib-ruby #{version}"]
|
65
57
|
end
|
66
58
|
|
59
|
+
$gemspec = jeweler_tasks.jeweler.gemspec.dup
|
60
|
+
|
67
61
|
FileList['tasks/**/*.rake'].each { |task| import task }
|
data/docs/taglib/base.rb
CHANGED
@@ -7,6 +7,7 @@
|
|
7
7
|
# * Reading properties of MPEG files: {TagLib::MPEG::File}
|
8
8
|
# * Reading/writing ID3v2 tags: {TagLib::MPEG::File} and
|
9
9
|
# {TagLib::MPEG::File#id3v2_tag}
|
10
|
+
# * Reading/writing Ogg Vorbis tags: {TagLib::Ogg::Vorbis::File}.
|
10
11
|
#
|
11
12
|
# ## String Encodings
|
12
13
|
#
|
@@ -60,10 +61,36 @@ module TagLib
|
|
60
61
|
# @return [TagLib::Tag] the tag
|
61
62
|
def tag
|
62
63
|
end
|
64
|
+
|
65
|
+
# Closes the file and releases all objects that were read from the
|
66
|
+
# file.
|
67
|
+
#
|
68
|
+
# @see TagLib::File#close
|
69
|
+
#
|
70
|
+
# @return [void]
|
71
|
+
def close
|
72
|
+
end
|
63
73
|
end
|
64
74
|
|
65
75
|
# @abstract Base class for files, see subclasses.
|
66
76
|
class File
|
77
|
+
# Closes the file and releases all objects that were read from the
|
78
|
+
# file.
|
79
|
+
#
|
80
|
+
# After this method has been called, no other methods on this object
|
81
|
+
# may be called. So it's a good idea to always use it like this:
|
82
|
+
#
|
83
|
+
# file.close
|
84
|
+
# file = nil
|
85
|
+
#
|
86
|
+
# This method should always be called as soon as you're finished
|
87
|
+
# with a file. Otherwise the file will only be closed when GC is
|
88
|
+
# run, which may be much later. On Windows, this is especially
|
89
|
+
# important as the file is locked until it is closed.
|
90
|
+
#
|
91
|
+
# @return [void]
|
92
|
+
def close
|
93
|
+
end
|
67
94
|
end
|
68
95
|
|
69
96
|
# @abstract Base class for tags.
|
@@ -112,19 +139,15 @@ module TagLib
|
|
112
139
|
Accurate = 2
|
113
140
|
|
114
141
|
# @return [Integer] length of the file in seconds
|
115
|
-
|
116
|
-
end
|
142
|
+
attr_reader :length
|
117
143
|
|
118
144
|
# @return [Integer] bit rate in kb/s (kilobit per second)
|
119
|
-
|
120
|
-
end
|
145
|
+
attr_reader :bitrate
|
121
146
|
|
122
147
|
# @return [Integer] sample rate in Hz
|
123
|
-
|
124
|
-
end
|
148
|
+
attr_reader :sample_rate
|
125
149
|
|
126
150
|
# @return [Integer] number of channels
|
127
|
-
|
128
|
-
end
|
151
|
+
attr_reader :channels
|
129
152
|
end
|
130
153
|
end
|
data/docs/taglib/mpeg.rb
CHANGED
@@ -17,6 +17,14 @@ module TagLib::MPEG
|
|
17
17
|
def tag
|
18
18
|
end
|
19
19
|
|
20
|
+
# Returns the ID3v1 tag.
|
21
|
+
#
|
22
|
+
# @param create if a new tag should be created when none exists
|
23
|
+
# @return [TagLib::ID3v1::Tag]
|
24
|
+
# @return [nil] if not present
|
25
|
+
def id3v1_tag(create=false)
|
26
|
+
end
|
27
|
+
|
20
28
|
# Returns the ID3v2 tag.
|
21
29
|
#
|
22
30
|
# @param create if a new tag should be created when none exists
|
data/docs/taglib/ogg.rb
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
module TagLib::Ogg
|
2
|
+
|
3
|
+
# @abstract Base class for Ogg files, see subclasses.
|
4
|
+
class File < TagLib::File
|
5
|
+
end
|
6
|
+
|
7
|
+
# Xiph comments (aka VorbisComment), a metadata format used for Ogg
|
8
|
+
# Vorbis and other codecs.
|
9
|
+
#
|
10
|
+
# A Xiph comment is structured as a set of fields. Each field has a
|
11
|
+
# name and a value. Multiple fields with the same name are allowed, so
|
12
|
+
# you can also view it as a map from names to a list of values.
|
13
|
+
class XiphComment < TagLib::Tag
|
14
|
+
|
15
|
+
# Add a name-value pair to the comment.
|
16
|
+
#
|
17
|
+
# @param [String] name field name
|
18
|
+
# @param [String] value field value
|
19
|
+
# @param [Boolean] replace if true, all existing fields with the
|
20
|
+
# given name will be replaced
|
21
|
+
# @return [void]
|
22
|
+
def add_field(name, value, replace=true)
|
23
|
+
end
|
24
|
+
|
25
|
+
# Check if the comment contains a field.
|
26
|
+
#
|
27
|
+
# @param [String] name field name
|
28
|
+
# @return [Boolean]
|
29
|
+
def contains?(name)
|
30
|
+
end
|
31
|
+
|
32
|
+
# Count the number of fields.
|
33
|
+
#
|
34
|
+
# @return [Integer] the number of fields in the comment (name-value
|
35
|
+
# pairs)
|
36
|
+
def field_count
|
37
|
+
end
|
38
|
+
|
39
|
+
# Get the contents of the comment as a hash, with the key being a
|
40
|
+
# field name String and the value a list of field values for that
|
41
|
+
# key. Example result:
|
42
|
+
#
|
43
|
+
# { 'TITLE' => ["Title"],
|
44
|
+
# 'GENRE' => ["Rock", "Pop"] }
|
45
|
+
#
|
46
|
+
# Note that the returned hash is read-only. Changing it will have no
|
47
|
+
# effect on the comment; use {#add_field} and {#remove_field} for
|
48
|
+
# that.
|
49
|
+
#
|
50
|
+
# @return [Hash<String, Array<String>>] a hash from field names to
|
51
|
+
# value lists
|
52
|
+
def field_list_map
|
53
|
+
end
|
54
|
+
|
55
|
+
# Remove one or more fields.
|
56
|
+
#
|
57
|
+
# @overload remove_field(name)
|
58
|
+
# Removes all fields with the given name.
|
59
|
+
#
|
60
|
+
# @param [String] name field name
|
61
|
+
#
|
62
|
+
# @overload remove_field(name, value)
|
63
|
+
# Removes the field with the given name and value.
|
64
|
+
#
|
65
|
+
# @param [String] name field name
|
66
|
+
# @param [String] value field value
|
67
|
+
#
|
68
|
+
# @return [void]
|
69
|
+
def remove_field
|
70
|
+
end
|
71
|
+
|
72
|
+
# @return [String] vendor ID of the encoder used
|
73
|
+
attr_reader :vendor_id
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module TagLib::Ogg::Vorbis
|
2
|
+
|
3
|
+
# The file class for `.ogg` and other `.oga` files.
|
4
|
+
class File < TagLib::Ogg::File
|
5
|
+
# Load an Ogg Vorbis file.
|
6
|
+
#
|
7
|
+
# @param [String] filename
|
8
|
+
# @param [Boolean] read_properties if audio properties should be
|
9
|
+
# read
|
10
|
+
def initialize(filename, read_properties=true)
|
11
|
+
end
|
12
|
+
|
13
|
+
# Returns the VorbisComment tag.
|
14
|
+
#
|
15
|
+
# @return [TagLib::Ogg::XiphComment]
|
16
|
+
def tag
|
17
|
+
end
|
18
|
+
|
19
|
+
# Returns audio properties.
|
20
|
+
#
|
21
|
+
# @return [TagLib::Ogg::Vorbis::Properties]
|
22
|
+
def audio_properties
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# Ogg Vorbis audio properties.
|
27
|
+
class Properties < TagLib::AudioProperties
|
28
|
+
# @return [Integer] Vorbis version
|
29
|
+
attr_reader :vorbis_version
|
30
|
+
|
31
|
+
# @return [Integer] maximum bitrate from Vorbis identification
|
32
|
+
# header
|
33
|
+
attr_reader :bitrate_maximum
|
34
|
+
|
35
|
+
# @return [Integer] nominal bitrate from Vorbis identification
|
36
|
+
# header
|
37
|
+
attr_reader :bitrate_nominal
|
38
|
+
|
39
|
+
# @return [Integer] minimum bitrate from Vorbis identification
|
40
|
+
# header
|
41
|
+
attr_reader :bitrate_minimum
|
42
|
+
end
|
43
|
+
end
|
data/ext/taglib_base/includes.i
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
%trackobjects;
|
2
2
|
|
3
|
-
// Undefine
|
3
|
+
// Undefine macros we don't need for wrapping
|
4
4
|
#define TAGLIB_EXPORT
|
5
|
+
#define TAGLIB_IGNORE_MISSING_DESTRUCTOR
|
5
6
|
|
6
7
|
// Replaces the typemap from swigtype.swg and just adds the line
|
7
8
|
// SWIG_RubyUnlinkObjects. This is done to be safe in the case when a
|
@@ -15,6 +16,10 @@
|
|
15
16
|
}
|
16
17
|
|
17
18
|
%{
|
19
|
+
#include <taglib/tstring.h>
|
20
|
+
#include <taglib/tstringlist.h>
|
21
|
+
#include <taglib/tfile.h>
|
22
|
+
|
18
23
|
#if defined(HAVE_RUBY_ENCODING_H) && HAVE_RUBY_ENCODING_H
|
19
24
|
# include <ruby/encoding.h>
|
20
25
|
# define ASSOCIATE_UTF8_ENCODING(value) rb_enc_associate(value, rb_utf8_encoding());
|
@@ -68,6 +73,25 @@ TagLib::StringList ruby_array_to_taglib_string_list(VALUE ary) {
|
|
68
73
|
}
|
69
74
|
return result;
|
70
75
|
}
|
76
|
+
|
77
|
+
VALUE taglib_filename_to_ruby_string(TagLib::FileName filename) {
|
78
|
+
#ifdef _WIN32
|
79
|
+
const char *s = (const char *) filename;
|
80
|
+
return rb_tainted_str_new2(s);
|
81
|
+
#else
|
82
|
+
return rb_tainted_str_new2(filename);
|
83
|
+
#endif
|
84
|
+
}
|
85
|
+
|
86
|
+
TagLib::FileName ruby_string_to_taglib_filename(VALUE s) {
|
87
|
+
#ifdef _WIN32
|
88
|
+
const char *filename = StringValuePtr(s);
|
89
|
+
return TagLib::FileName(filename);
|
90
|
+
#else
|
91
|
+
return StringValuePtr(s);
|
92
|
+
#endif
|
93
|
+
}
|
94
|
+
|
71
95
|
%}
|
72
96
|
|
73
97
|
// vim: set filetype=cpp sw=2 ts=2 expandtab:
|