taglib-ruby 0.5.2 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. data/.yardopts +1 -1
  2. data/CHANGES.md +11 -0
  3. data/LICENSE.txt +0 -2
  4. data/README.md +7 -9
  5. data/docs/taglib/base.rb +35 -7
  6. data/docs/taglib/id3v2.rb +37 -5
  7. data/docs/taglib/mp4.rb +267 -0
  8. data/docs/taglib/mpeg.rb +23 -8
  9. data/ext/taglib_base/includes.i +2 -2
  10. data/ext/taglib_base/taglib_base.i +3 -0
  11. data/ext/taglib_base/taglib_base_wrap.cxx +11 -12
  12. data/ext/taglib_flac/taglib_flac_wrap.cxx +21 -25
  13. data/ext/taglib_id3v1/taglib_id3v1_wrap.cxx +4 -8
  14. data/ext/taglib_id3v2/taglib_id3v2.i +3 -0
  15. data/ext/taglib_id3v2/taglib_id3v2_wrap.cxx +528 -69
  16. data/ext/taglib_mp4/extconf.rb +4 -0
  17. data/ext/taglib_mp4/taglib_mp4.i +225 -0
  18. data/ext/taglib_mp4/taglib_mp4_wrap.cxx +4830 -0
  19. data/ext/taglib_mpeg/taglib_mpeg.i +15 -0
  20. data/ext/taglib_mpeg/taglib_mpeg_wrap.cxx +174 -88
  21. data/ext/taglib_ogg/taglib_ogg_wrap.cxx +2 -6
  22. data/ext/taglib_vorbis/taglib_vorbis_wrap.cxx +8 -12
  23. data/lib/taglib.rb +1 -0
  24. data/lib/taglib/mp4.rb +33 -0
  25. data/lib/taglib/version.rb +2 -2
  26. data/taglib-ruby.gemspec +19 -3
  27. data/tasks/ext.rake +3 -0
  28. data/tasks/swig.rake +6 -1
  29. data/test/base_test.rb +11 -0
  30. data/test/data/Makefile +5 -2
  31. data/test/data/flac-create.cpp +2 -22
  32. data/test/data/get_picture_data.cpp +22 -0
  33. data/test/data/mp4-create.cpp +38 -0
  34. data/test/data/mp4.m4a +0 -0
  35. data/test/fileref_write_test.rb +9 -0
  36. data/test/flac_file_test.rb +2 -1
  37. data/test/id3v2_header_test.rb +61 -0
  38. data/test/id3v2_write_test.rb +17 -0
  39. data/test/mp4_file_test.rb +51 -0
  40. data/test/mp4_file_write_test.rb +66 -0
  41. data/test/mp4_items_test.rb +183 -0
  42. metadata +39 -8
data/.yardopts CHANGED
@@ -1,5 +1,5 @@
1
1
  --markup markdown
2
- --markup-provider redcarpet
2
+ --markup-provider kramdown
3
3
  --charset UTF-8
4
4
  --template-path docs
5
5
  docs/**/*.rb
data/CHANGES.md CHANGED
@@ -1,6 +1,17 @@
1
1
  Changes in Releases of taglib-ruby
2
2
  ==================================
3
3
 
4
+ ## 0.6.0 (2013-04-26)
5
+
6
+ * Add support for TagLib::MP4 (#3, by @jacobvosmaer)
7
+ * Add support for TagLib::ID3v2::Header (#19, by @kaethorn)
8
+ * Support saving ID3v2.3 with TagLib::MPEG::File#save (#17)
9
+ * Note that this requires at least TagLib 1.8, and due to 1.8.0
10
+ having an incorrect version number in the headers, it currently
11
+ requires master. See issue #17 for details.
12
+ * Fix segfault when passing a non-String to a String argument
13
+ * Documentation updates
14
+
4
15
  ## 0.5.2 (2012-10-06)
5
16
 
6
17
  * Fix memory bug with TagLib::MPEG::File#tag and TagLib::FLAC::File#tag
data/LICENSE.txt CHANGED
@@ -1,5 +1,3 @@
1
- Copyright (c) 2010-2012 Robin Stocker
2
-
3
1
  MIT License
4
2
 
5
3
  Permission is hereby granted, free of charge, to any person obtaining
data/README.md CHANGED
@@ -8,16 +8,15 @@ In contrast to other libraries, this one wraps the full C++ API, not
8
8
  only the minimal C API. This means that all tag data can be accessed,
9
9
  e.g. cover art of ID3v2 or custom fields of Ogg Vorbis comments.
10
10
 
11
- taglib-ruby is work in progress, but the following is already available:
11
+ taglib-ruby currently supports the following:
12
12
 
13
13
  * Reading/writing common tag data of all formats that TagLib supports
14
14
  * Reading/writing ID3v1 and ID3v2 including ID3v2.4 and Unicode
15
15
  * Reading/writing Ogg Vorbis comments
16
+ * Reading/writing MP4 tags (.m4a)
16
17
  * Reading audio properties (e.g. bitrate) of the above formats
17
18
 
18
- Some things are still left to do (contributors very welcome):
19
-
20
- * More coverage of the library
19
+ Contributions for more coverage of the library are very welcome.
21
20
 
22
21
  [![Build status][travis-img]][travis-link]
23
22
 
@@ -41,9 +40,8 @@ Then do:
41
40
  Usage
42
41
  -----
43
42
 
44
- Complete API documentation can be found here:
45
-
46
- http://rubydoc.info/gems/taglib-ruby/frames
43
+ Complete API documentation can be found on
44
+ [rubydoc.info](http://rubydoc.info/gems/taglib-ruby/frames).
47
45
 
48
46
  Begin with the {TagLib} namespace.
49
47
 
@@ -87,7 +85,7 @@ Contributing
87
85
  License
88
86
  -------
89
87
 
90
- Copyright (c) 2010-2012 Robin Stocker.
88
+ Copyright (c) 2010-2013 Robin Stocker and others, see Git history.
91
89
 
92
90
  taglib-ruby is distributed under the MIT License,
93
91
  see LICENSE.txt for details.
@@ -96,7 +94,7 @@ In the binary gem for Windows, a compiled [TagLib][taglib] is bundled as
96
94
  a DLL. TagLib is distributed under the GNU Lesser General Public License
97
95
  version 2.1 (LGPL) and Mozilla Public License (MPL).
98
96
 
99
- [taglib]: http://developer.kde.org/~wheeler/taglib.html
97
+ [taglib]: http://taglib.github.io/
100
98
  [travis-img]: https://secure.travis-ci.org/robinst/taglib-ruby.png
101
99
  [travis-link]: http://travis-ci.org/robinst/taglib-ruby
102
100
  [flattr-img]: http://api.flattr.com/button/flattr-badge-large.png
data/docs/taglib/base.rb CHANGED
@@ -25,6 +25,21 @@
25
25
  # using the {TagLib::ID3v2::FrameFactory}.
26
26
  module TagLib
27
27
 
28
+ # Major version of TagLib the extensions were compiled against
29
+ # (major.minor.patch). Note that the value is not actually 0, but
30
+ # depends on the version of the installed library.
31
+ TAGLIB_MAJOR_VERSION = 0
32
+
33
+ # Minor version of TagLib the extensions were compiled against
34
+ # (major.minor.patch). Note that the value is not actually 0, but
35
+ # depends on the version of the installed library.
36
+ TAGLIB_MINOR_VERSION = 0
37
+
38
+ # Patch version of TagLib the extensions were compiled against
39
+ # (major.minor.patch). Note that the value is not actually 0, but
40
+ # depends on the version of the installed library.
41
+ TAGLIB_PATCH_VERSION = 0
42
+
28
43
  # This class allows to read basic tagging and audio properties from
29
44
  # files, without having to know what the file type is. Thus, it works
30
45
  # for all tagging formats that taglib supports, but only provides a
@@ -35,16 +50,20 @@ module TagLib
35
50
  #
36
51
  # @example Reading tags
37
52
  # TagLib::FileRef.open("foo.flac") do |file|
38
- # tag = file.tag
39
- # puts tag.artist
40
- # puts tag.title
53
+ # unless file.null?
54
+ # tag = file.tag
55
+ # puts tag.artist
56
+ # puts tag.title
57
+ # end
41
58
  # end
42
59
  #
43
60
  # @example Reading audio properties
44
61
  # TagLib::FileRef.open("bar.oga") do |file|
45
- # prop = file.audio_properties
46
- # puts prop.length
47
- # puts prop.bitrate
62
+ # unless file.null?
63
+ # prop = file.audio_properties
64
+ # puts prop.length
65
+ # puts prop.bitrate
66
+ # end
48
67
  # end
49
68
  #
50
69
  class FileRef
@@ -86,6 +105,11 @@ module TagLib
86
105
  audio_properties_style=TagLib::AudioProperties::Average)
87
106
  end
88
107
 
108
+ # Gets the audio properties. Before accessing it, check if there
109
+ # were problems reading the file using {#null?}. If the audio
110
+ # properties are accessed anyway, a warning will be printed and it
111
+ # will return nil.
112
+ #
89
113
  # @return [TagLib::AudioProperties] the audio properties
90
114
  def audio_properties
91
115
  end
@@ -100,7 +124,11 @@ module TagLib
100
124
  def save
101
125
  end
102
126
 
103
- # @return [TagLib::Tag] the tag
127
+ # Gets the tag. Before accessing it, check if there were problems
128
+ # reading the file using {#null?}. If the tag is accessed anyway, a
129
+ # warning will be printed and it will return nil.
130
+ #
131
+ # @return [TagLib::Tag] the tag, or nil
104
132
  def tag
105
133
  end
106
134
 
data/docs/taglib/id3v2.rb CHANGED
@@ -21,7 +21,7 @@ module TagLib::ID3v2
21
21
  # title.text_encoding = TagLib::String::UTF8
22
22
  #
23
23
  # @example Read ID3v2 frames from a file
24
- # TagLib::MPEG::File.new("wake_up.mp3") do |file|
24
+ # TagLib::MPEG::File.open("wake_up.mp3") do |file|
25
25
  # tag = file.id3v2_tag
26
26
  #
27
27
  # # Read basic attributes
@@ -43,7 +43,7 @@ module TagLib::ID3v2
43
43
  # end
44
44
  #
45
45
  # @example Add frames and save file
46
- # TagLib::MPEG::File.new("joga.mp3") do |file|
46
+ # TagLib::MPEG::File.open("joga.mp3") do |file|
47
47
  # tag = file.id3v2_tag
48
48
  #
49
49
  # # Write basic attributes
@@ -108,6 +108,38 @@ module TagLib::ID3v2
108
108
  end
109
109
  end
110
110
 
111
+ # Exposes properties defined in a standard ID3v2 header.
112
+ class Header
113
+ # The major version number (4 for a ID3v2.4.0 version tag).
114
+ # @return [Integer] major version number
115
+ attr_accessor :major_version
116
+
117
+ # The size of the tag without the size of the header.
118
+ # @return [Integer] size in bytes
119
+ attr_accessor :tag_size
120
+
121
+ # The revision version number (0 for a ID3v2.4.0 version tag).
122
+ # @return [Integer] revision version number
123
+ attr_reader :revision_number
124
+
125
+ # @return [Boolean] if unsynchronisation has been applied to all frames
126
+ attr_reader :unsynchronisation
127
+
128
+ # @return [Boolean] if an extended header is present in the tag
129
+ attr_reader :extended_header
130
+
131
+ # @return [Boolean] if the experimental indicator flag is set
132
+ attr_reader :experimental_indicator
133
+
134
+ # @return [Boolean] if a footer is present in the tag
135
+ attr_reader :footer_present
136
+
137
+ # Renders the header to binary.
138
+ # @return [TagLib::ByteVector]
139
+ def render
140
+ end
141
+ end
142
+
111
143
  # Frame factory for ID3v2 frames. Useful for setting the default text
112
144
  # encoding.
113
145
  class FrameFactory
@@ -384,7 +416,7 @@ module TagLib::ID3v2
384
416
  # @return [Array<String>] list of text strings in this frame
385
417
  attr_accessor :field_list
386
418
 
387
- # @param [String] text simple text to set
419
+ # @param [String] value simple text to set
388
420
  attr_writer :text
389
421
  end
390
422
 
@@ -424,10 +456,10 @@ module TagLib::ID3v2
424
456
  # URL link frame (`W???`), e.g. `WOAR` for "official artist/performer
425
457
  # webpage".
426
458
  class UrlLinkFrame < Frame
427
- # @param [String] text simple text to set
459
+ # @param [String] value simple text to set
428
460
  attr_writer :text
429
461
 
430
- # @param [String] URL
462
+ # @param [String] value URL
431
463
  attr_accessor :url
432
464
  end
433
465
 
@@ -0,0 +1,267 @@
1
+ module TagLib::MP4
2
+
3
+ # The file class for '.m4a' files.
4
+ #
5
+ # @example Finding an MP4 item by field name
6
+ # TagLib::MP4::File.open("file.m4a") do |mp4|
7
+ # item_list_map = mp4.tag.item_list_map
8
+ # title = item_list_map["\xC2\xA9nam"].to_string_list
9
+ # puts title.first
10
+ # end
11
+ #
12
+ # @example Add new cover art to a tag
13
+ # image_data = File.open('cover_art.jpeg', 'rb') { |f| f.read }
14
+ # cover_art = TagLib::MP4::CoverArt.new(TagLib::MP4::CoverArt::JPEG, image_data)
15
+ # item = TagLib::MP4::Item.from_cover_art_list([cover_art])
16
+ # mp4.tag.item_list_map.insert('covr', item)
17
+ # # => nil
18
+ # mp4.save
19
+ # # => true
20
+ #
21
+ # @example Extract cover art from a tag and save it to disk
22
+ # cover_art_list = mp4.tag.item_list_map['covr'].to_cover_art_list
23
+ # cover_art = cover_art_list.first
24
+ # cover_art.format
25
+ # # => 13
26
+ # cover_art.format == TagLib::MP4::CoverArt::JPEG
27
+ # # => true
28
+ # File.open('cover_art.jpeg', 'wb') do |file|
29
+ # file.write(cover_art.data)
30
+ # end
31
+ # # => 3108
32
+ #
33
+ # @example List all keys and items in the tag
34
+ # mp4.tag.item_list_map.to_a
35
+ # # => [["covr",
36
+ # # #<TagLib::MP4::Item:0x007f9bab61e3d0 @__swigtype__="_p_TagLib__MP4__Item">],
37
+ # # ["trkn",
38
+ # # #<TagLib::MP4::Item:0x007f9bab61e268 @__swigtype__="_p_TagLib__MP4__Item">],
39
+ # # ["©ART",
40
+ # # #<TagLib::MP4::Item:0x007f9bab61e128 @__swigtype__="_p_TagLib__MP4__Item">],
41
+ # # ["©alb",
42
+ # # #<TagLib::MP4::Item:0x007f9bab61df48 @__swigtype__="_p_TagLib__MP4__Item">],
43
+ # # ["©cmt",
44
+ # # #<TagLib::MP4::Item:0x007f9bab61de08 @__swigtype__="_p_TagLib__MP4__Item">],
45
+ # # ["©cpy",
46
+ # # #<TagLib::MP4::Item:0x007f9bab61dc78 @__swigtype__="_p_TagLib__MP4__Item">],
47
+ # # ["©day",
48
+ # # #<TagLib::MP4::Item:0x007f9bab61db88 @__swigtype__="_p_TagLib__MP4__Item">],
49
+ # # ["©gen",
50
+ # # #<TagLib::MP4::Item:0x007f9bab61da48 @__swigtype__="_p_TagLib__MP4__Item">],
51
+ # # ["©nam",
52
+ # # #<TagLib::MP4::Item:0x007f9bab61d930 @__swigtype__="_p_TagLib__MP4__Item">],
53
+ # # ["©too",
54
+ # # #<TagLib::MP4::Item:0x007f9bab61d818 @__swigtype__="_p_TagLib__MP4__Item">]]
55
+ class File < TagLib::File
56
+
57
+ # {include:TagLib::FileRef.open}
58
+ #
59
+ # @param (see #initialize)
60
+ # @yield [file] the {File} object, as obtained by {#initialize}
61
+ # @return the return value of the block
62
+ #
63
+ def self.open(filename, read_properties=true)
64
+ end
65
+
66
+ # Load an M4A file.
67
+ #
68
+ # @param [String] filename
69
+ # @param [Boolean] read_properties if audio properties should be
70
+ # read
71
+ # @return [TagLib::MP4::File]
72
+ def initialize(filename, read_properties=true)
73
+ end
74
+
75
+ # Returns the MP4 tag in the file
76
+ #
77
+ # @return [TagLib::MP4::Tag]
78
+ # @return [nil] if not present
79
+ def tag
80
+ end
81
+
82
+ # @return [TagLib::MP4::Properties]
83
+ def audio_properties
84
+ end
85
+ end
86
+
87
+ class Tag < TagLib::Tag
88
+ # Returns the map containing all the items in the tag
89
+ # @return [TagLib::MP4::ItemListMap]
90
+ def item_list_map
91
+ end
92
+ end
93
+
94
+ # TagLib's `MP4::Item` class is a C++ union. To create a new Item with a value
95
+ # of the right type, use one of the `Item.from_<type>`-constructors. The use
96
+ # of `Item.new` is discouraged. For more information, see [the TagLib
97
+ # documentation of `Item`](http://taglib.github.com/api/classTagLib_1_1MP4_1_1Item.html).
98
+ # @example Using a specific constructor
99
+ # item = TagLib::MP4::Item.from_string_list(['hello'])
100
+ # # => #<TagLib::MP4::Item:0x007ffd59796d60 @__swigtype__="_p_TagLib__MP4__Item">
101
+ # item.to_string_list
102
+ # # => ["hello"]
103
+ # item.to_int # Good luck!
104
+ # # => 1538916358
105
+ #
106
+ class Item
107
+ # @param [Boolean] value
108
+ # @return [TagLib::MP4::Item]
109
+ def self.from_bool(value)
110
+ end
111
+
112
+ # @param [Fixnum] number
113
+ # @return [TagLib::MP4::Item]
114
+ def self.from_int(number)
115
+ end
116
+
117
+ # @example
118
+ # TagLib::MP4::Item.from_int_pair([4, 11])
119
+ # @param [Array<Fixnum, Fixnum>] integer_pair
120
+ # @return [TagLib::MP4::Item]
121
+ def self.from_int_pair(integer_pair)
122
+ end
123
+
124
+ # @param [Array<String>] string_array
125
+ # @return [TagLib::MP4::Item]
126
+ def self.from_string_list(string_array)
127
+ end
128
+
129
+ # @return [Boolean]
130
+ def to_bool
131
+ end
132
+
133
+ # @return [Array<TagLib::MP4::CoverArt>]
134
+ def to_cover_art_list
135
+ end
136
+
137
+ # @return [Fixnum]
138
+ def to_int
139
+ end
140
+
141
+ # @return [Array<Fixnum, Fixnum>]
142
+ def to_int_pair
143
+ end
144
+
145
+ # @return [Array<String>]
146
+ def to_string_list
147
+ end
148
+
149
+ # @return [Boolean]
150
+ def valid?
151
+ end
152
+ end
153
+
154
+ # The underlying C++-structure of `ItemListMap` inherits from `std::map`.
155
+ # Consequently, `ItemListMap` behaves differently from a Ruby hash in a few
156
+ # places: the C++ memory management strategies of ItemListMap can lead to
157
+ # a situation where a Ruby object refers to a location in memory that was
158
+ # freed by C++. To prevent Ruby from crashing on us with a segmentation
159
+ # fault, we raise an `ObjectPreviouslyDeleted` exception when we try to access
160
+ # data that is no longer available.
161
+ class ItemListMap
162
+ # Return the Item under `key`, or `nil` if no Item is present.
163
+ # @param [String] key
164
+ # @return [TagLib::MP4::Item]
165
+ # @return [nil] if not present
166
+ def fetch(key)
167
+ end
168
+ alias :[] :fetch
169
+
170
+ # @example Triggering an ObjectPreviouslyDeleted exception
171
+ # remember_me = mp4.tag.item_list_map["\xC2\xA9nam"]
172
+ # mp4.tag.item_list_map.clear
173
+ # # => nil
174
+ # remember_me.to_string_list
175
+ # # ObjectPreviouslyDeleted: Expected argument 0 of type TagLib::MP4::Item const *, but got TagLib::MP4::Item #<TagLib::MP4::Item:0x007f9199...
176
+ # # in SWIG method 'toStringList'
177
+ # # from (pry):7:in `to_string_list'
178
+ #
179
+ # Remove all Items from self, destroying each Item.
180
+ # @note May free memory referred to by Ruby objects
181
+ # @return [nil]
182
+ def clear
183
+ end
184
+
185
+ # Returns true if self has an Item under `key`.
186
+ # @param [String] key
187
+ # @return [Boolean]
188
+ def contains(key)
189
+ end
190
+ alias :has_key? :contains
191
+ alias :include? :contains
192
+
193
+ # Returns true if self is empty
194
+ # @return [Boolean]
195
+ def empty?
196
+ end
197
+
198
+ # Remove and destroy the value under `key`, if present.
199
+ # @example Triggering an ObjectPreviouslyDeleted exception
200
+ # remember_me = mp4.tag.item_list_map["\xC2\xA9nam"]
201
+ # mp4.tag.item_list_map.erase("\xC2\xA9nam")
202
+ # # => nil
203
+ # remember_me.to_string_list
204
+ # # ObjectPreviouslyDeleted: Expected argument 0 of type TagLib::MP4::Item const *, but got TagLib::MP4::Item #<TagLib::MP4::Item:0x007f919a...
205
+ # # in SWIG method 'toStringList'
206
+ # # from (pry):13:in `to_string_list'
207
+ #
208
+ # @note May free memory referred to by Ruby objects
209
+ # @param [String] key
210
+ # @return [nil]
211
+ def erase(key)
212
+ end
213
+
214
+ # Insert an item at `key`, destoying the existing item under `key`.
215
+ # @example Triggering an ObjectPreviouslyDeleted exception
216
+ # remember_me = mp4.tag.item_list_map["\xC2\xA9nam"]
217
+ # mp4.tag.item_list_map.insert("\xC2\xA9nam", TagLib::MP4::Item.from_string_list(['New']))
218
+ # remember_me.to_string_list
219
+ # # ObjectPreviouslyDeleted: Expected argument 0 of type TagLib::MP4::Item const *, but got TagLib::MP4::Item #<TagLib::MP4::Item:0x007f919a...
220
+ # # in SWIG method 'toStringList'
221
+ # # from (pry):18:in `to_string_list'
222
+ # @note May free memory referred to by Ruby objects
223
+ # @param [String] key
224
+ # @param [TagLib::MP4::Item] item
225
+ # @return [nil]
226
+ def insert(key, item)
227
+ end
228
+
229
+ # The number of Items in self.
230
+ # @return [Fixnum]
231
+ def size
232
+ end
233
+
234
+ # Convert self into an array of `[key, value]` pairs.
235
+ # @return [Array<Array<String, TagLib::MP4::Item>>]
236
+ def to_a
237
+ end
238
+ end
239
+ #
240
+ class Properties < TagLib::AudioProperties
241
+ attr_reader :bits_per_sample, :encrypted?
242
+ end
243
+
244
+ # The `CoverArt` class is used to embed cover art images in MP4 tags.
245
+ #
246
+ # @example Creating a new CoverArt instance
247
+ # image_data = File.open('cover_art.jpeg', 'rb') { |f| f.read }
248
+ # cover_art = TagLib::MP4::CoverArt.new(TagLib::MP4::CoverArt::JPEG, image_data)
249
+ class CoverArt
250
+ JPEG = 0x0D
251
+ PNG = 0x0E
252
+
253
+ # Returns the format of the image data: `JPEG` or `PNG`.
254
+ # @return [Fixnum]
255
+ attr_reader :format
256
+
257
+ # Returns the raw image data
258
+ # @return [String]
259
+ attr_reader :data
260
+
261
+ # @param [Fixnum] format
262
+ # @param [String] data
263
+ # @return [TagLib::MP4::CoverArt]
264
+ def initialize(format, data)
265
+ end
266
+ end
267
+ end