taglib-ruby 0.3.1 → 0.4.0

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.
Files changed (44) hide show
  1. data/CHANGES.md +14 -0
  2. data/Gemfile +2 -10
  3. data/Guardfile +1 -1
  4. data/LICENSE.txt +2 -0
  5. data/README.md +10 -79
  6. data/Rakefile +6 -38
  7. data/docs/taglib/base.rb +52 -3
  8. data/docs/taglib/id3v2.rb +62 -1
  9. data/docs/taglib/mpeg.rb +17 -0
  10. data/docs/taglib/vorbis.rb +19 -0
  11. data/ext/taglib_base/includes.i +20 -2
  12. data/ext/taglib_base/taglib_base.i +4 -1
  13. data/ext/taglib_base/taglib_base_wrap.cxx +38 -2
  14. data/ext/taglib_id3v1/taglib_id3v1_wrap.cxx +20 -2
  15. data/ext/taglib_id3v2/taglib_id3v2_wrap.cxx +20 -2
  16. data/ext/taglib_mpeg/taglib_mpeg_wrap.cxx +38 -2
  17. data/ext/taglib_ogg/taglib_ogg_wrap.cxx +20 -2
  18. data/ext/taglib_vorbis/taglib_vorbis_wrap.cxx +29 -2
  19. data/ext/win.cmake +0 -1
  20. data/lib/taglib/base.rb +18 -0
  21. data/lib/taglib/mpeg.rb +6 -0
  22. data/lib/taglib/version.rb +2 -2
  23. data/lib/taglib/vorbis.rb +6 -0
  24. data/taglib-ruby.gemspec +50 -63
  25. data/tasks/ext.rake +5 -3
  26. data/tasks/gemspec_check.rake +19 -0
  27. data/test/fileref_open_test.rb +32 -0
  28. data/test/{test_fileref_properties.rb → fileref_properties_test.rb} +1 -1
  29. data/test/{test_fileref_write.rb → fileref_write_test.rb} +25 -1
  30. data/test/helper.rb +1 -1
  31. data/test/{test_id3v1_tag.rb → id3v1_tag_test.rb} +1 -1
  32. data/test/{test_id3v2_frames.rb → id3v2_frames_test.rb} +1 -1
  33. data/test/{test_id3v2_memory.rb → id3v2_memory_test.rb} +1 -1
  34. data/test/{test_id3v2_relative_volume.rb → id3v2_relative_volume_test.rb} +1 -1
  35. data/test/{test_id3v2_tag.rb → id3v2_tag_test.rb} +1 -1
  36. data/test/{test_id3v2_unicode.rb → id3v2_unicode_test.rb} +1 -1
  37. data/test/{test_id3v2_write.rb → id3v2_write_test.rb} +1 -1
  38. data/test/{test_mpeg_file.rb → mpeg_file_test.rb} +11 -1
  39. data/test/{test_tag.rb → tag_test.rb} +1 -1
  40. data/test/unicode_filename_test.rb +29 -0
  41. data/test/{test_vorbis_file.rb → vorbis_file_test.rb} +11 -1
  42. data/test/{test_vorbis_tag.rb → vorbis_tag_test.rb} +1 -1
  43. metadata +40 -66
  44. data/Gemfile.lock +0 -36
data/CHANGES.md CHANGED
@@ -1,6 +1,20 @@
1
1
  Changes in Releases of taglib-ruby
2
2
  ==================================
3
3
 
4
+ ## 0.4.0 (2012-03-18)
5
+
6
+ * Pre-compiled binary gem for Windows (Ruby 1.9) with TagLib 1.7.1
7
+ * Unicode filename support on Windows
8
+ * Add `open` class method to `FileRef` and `File` classes (use it
9
+ instead of `new` and `close`):
10
+
11
+ ```ruby
12
+ title = TagLib::FileRef.open("file.mp3") do |file|
13
+ tag = file.tag
14
+ tag.title
15
+ end
16
+ ```
17
+
4
18
  ## 0.3.1 (2012-01-22)
5
19
 
6
20
  * Fix ObjectPreviouslyDeleted exception after calling
data/Gemfile CHANGED
@@ -1,12 +1,4 @@
1
1
  source 'http://rubygems.org'
2
2
 
3
- group :development do
4
- gem 'rake-compiler', '~> 0.7'
5
-
6
- gem 'shoulda', '~> 2.11'
7
- gem 'bundler', '~> 1.0.0'
8
- gem 'jeweler', '~> 1.6.4'
9
- gem 'yard', '~> 0.7'
10
- gem 'redcarpet', '~> 1.0'
11
- gem 'guard-test', '~> 0.4.0'
12
- end
3
+ # Use dependencies from .gemspec
4
+ gemspec
data/Guardfile CHANGED
@@ -4,5 +4,5 @@
4
4
  guard :test do
5
5
  watch(%r{^lib/(.+)\.so$}) { "test" }
6
6
  watch('test/test_helper.rb') { "test" }
7
- watch(%r{^test/test_.+\.rb$})
7
+ watch(%r{^test/.+_test\.rb$})
8
8
  end
@@ -1,5 +1,7 @@
1
1
  Copyright (c) 2010-2012 Robin Stocker
2
2
 
3
+ MIT License
4
+
3
5
  Permission is hereby granted, free of charge, to any person obtaining
4
6
  a copy of this software and associated documentation files (the
5
7
  "Software"), to deal in the Software without restriction, including
data/README.md CHANGED
@@ -16,10 +16,10 @@ taglib-ruby is work in progress, but the following is already available:
16
16
 
17
17
  Some things are still left to do (contributors very welcome):
18
18
 
19
- * Pre-compiled Gem for Windows:
20
- * Unicode filename support
21
19
  * More coverage of the library
22
20
 
21
+ [![Build status][travis-img]][travis-link]
22
+
23
23
  [![flattr this project][flattr-img]][flattr-link]
24
24
 
25
25
  Installation
@@ -44,82 +44,7 @@ Complete API documentation can be found here:
44
44
 
45
45
  http://rubydoc.info/gems/taglib-ruby/frames
46
46
 
47
- What follows are some examples of how to use taglib-ruby. Here's how to
48
- read an ID3v2 tag:
49
-
50
- ```ruby
51
- require 'taglib'
52
-
53
- # Load an ID3v2 tag from a file
54
- file = TagLib::MPEG::File.new("wake_up.mp3")
55
- tag = file.id3v2_tag
56
-
57
- # Read basic attributes
58
- tag.title #=> "Wake Up"
59
- tag.artist #=> "Arcade Fire"
60
- tag.track #=> 7
61
-
62
- # Access all frames
63
- tag.frame_list.size #=> 13
64
-
65
- # Track frame
66
- track = tag.frame_list('TRCK').first
67
- track.to_s #=> "7/10"
68
-
69
- # Attached picture frame
70
- cover = tag.frame_list('APIC').first
71
- cover.mime_type #=> "image/jpeg"
72
- cover.picture #=> "\xFF\xD8\xFF\xE0\x00\x10JFIF..."
73
-
74
- # Close file to release resources
75
- file.close
76
- ```
77
-
78
- And here's an example for writing one:
79
-
80
- ```ruby
81
- file = TagLib::MPEG::File.new("joga.mp3")
82
- tag = file.id3v2_tag
83
-
84
- # Write basic attributes
85
- tag.artist = "Björk"
86
- tag.title = "Jóga"
87
-
88
- # Add attached picture frame
89
- apic = TagLib::ID3v2::AttachedPictureFrame.new
90
- apic.mime_type = "image/jpeg"
91
- apic.description = "Cover"
92
- apic.type = TagLib::ID3v2::AttachedPictureFrame::FrontCover
93
- apic.picture = File.open("cover.jpg", 'rb'){ |f| f.read }
94
-
95
- tag.add_frame(apic)
96
-
97
- file.save
98
- file.close
99
- ```
100
-
101
- ### Encoding
102
-
103
- By default, taglib stores text frames as ISO-8859-1 (Latin-1), if the
104
- text contains only characters that are available in that encoding. If
105
- not (e.g. with Cyrillic, Chinese, Japanese), it prints a warning and
106
- stores the text as UTF-8.
107
-
108
- When you already know that you want to store the text as UTF-8, you can
109
- change the default text encoding:
110
-
111
- ```ruby
112
- frame_factory = TagLib::ID3v2::FrameFactory.instance
113
- frame_factory.default_text_encoding = TagLib::String::UTF8
114
- ```
115
-
116
- Another option is using the advanced API:
117
-
118
- ```ruby
119
- title = tag.frame_list('TIT2').first
120
- title.text = "Jóga"
121
- title.text_encoding = TagLib::String::UTF8
122
- ```
47
+ Begin with the {TagLib} namespace.
123
48
 
124
49
  Release Notes
125
50
  -------------
@@ -146,11 +71,17 @@ Contributing
146
71
  License
147
72
  -------
148
73
 
74
+ Copyright (c) 2010-2012 Robin Stocker.
75
+
149
76
  taglib-ruby is distributed under the MIT License,
150
77
  see LICENSE.txt for details.
151
78
 
152
- Copyright (c) 2010-2012 Robin Stocker.
79
+ In the binary gem for Windows, a compiled [TagLib][taglib] is bundled as
80
+ a DLL. TagLib is distributed under the GNU Lesser General Public License
81
+ version 2.1 (LGPL) and Mozilla Public License (MPL).
153
82
 
154
83
  [taglib]: http://developer.kde.org/~wheeler/taglib.html
84
+ [travis-img]: https://secure.travis-ci.org/robinst/taglib-ruby.png
85
+ [travis-link]: http://travis-ci.org/robinst/taglib-ruby
155
86
  [flattr-img]: http://api.flattr.com/button/flattr-badge-large.png
156
87
  [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,8 +1,6 @@
1
1
  # encoding: utf-8
2
2
 
3
- require 'rubygems'
4
- require "rubygems/package_task"
5
- require 'bundler'
3
+ require 'bundler/gem_tasks'
6
4
  begin
7
5
  Bundler.setup(:default, :development)
8
6
  rescue Bundler::BundlerError => e
@@ -10,45 +8,14 @@ rescue Bundler::BundlerError => e
10
8
  $stderr.puts "Run `bundle install` to install missing gems"
11
9
  exit e.status_code
12
10
  end
13
- require 'rake'
14
-
15
- require 'jeweler'
16
- require './lib/taglib/version.rb'
17
- jeweler_tasks = Jeweler::Tasks.new do |gem|
18
- # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
19
- gem.name = "taglib-ruby"
20
- gem.summary = %Q{Ruby interface for the taglib C++ library}
21
- gem.description = <<-DESC
22
- Ruby interface for the taglib C++ library.
23
-
24
- In contrast to other libraries, this one wraps the C++ API using SWIG,
25
- not only the minimal C API. This means that all tags can be accessed.
26
- DESC
27
- gem.requirements = 'taglib (libtag1-dev in Debian/Ubuntu, taglib-devel in Fedora/RHEL)'
28
- gem.version = TagLib::Version::STRING
29
- gem.license = "MIT"
30
- gem.email = "robin@nibor.org"
31
- gem.homepage = "http://github.com/robinst/taglib-ruby"
32
- gem.authors = ["Robin Stocker"]
33
- gem.extensions = ['ext/taglib_base/extconf.rb',
34
- 'ext/taglib_mpeg/extconf.rb',
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"]
40
- # dependencies defined in Gemfile
41
- end
42
- Jeweler::RubygemsDotOrgTasks.new
43
11
 
44
12
  require 'rake/testtask'
45
13
  Rake::TestTask.new(:test) do |test|
46
- test.libs << 'lib' << 'test'
47
- test.pattern = 'test/**/test_*.rb'
48
- test.verbose = true
14
+ test.libs << 'test'
15
+ test.pattern = 'test/**/*_test.rb'
49
16
  end
50
17
 
51
- task :default => :test
18
+ task :default => [:compile, :test]
52
19
 
53
20
  require 'yard'
54
21
  YARD::Rake::YardocTask.new do |t|
@@ -56,6 +23,7 @@ YARD::Rake::YardocTask.new do |t|
56
23
  t.options = ['--title', "taglib-ruby #{version}"]
57
24
  end
58
25
 
59
- $gemspec = jeweler_tasks.jeweler.gemspec.dup
26
+ # Change to Bundler::GemHelper.gemspec when it's released
27
+ $gemspec = Bundler.load_gemspec('taglib-ruby.gemspec')
60
28
 
61
29
  FileList['tasks/**/*.rake'].each { |task| import task }
@@ -6,9 +6,9 @@
6
6
  # know the tagging format: {TagLib::FileRef}
7
7
  # * Reading properties of MPEG files: {TagLib::MPEG::File}
8
8
  # * Reading/writing ID3v2 tags: {TagLib::MPEG::File} and
9
- # {TagLib::MPEG::File#id3v2_tag}
9
+ # {TagLib::ID3v2::Tag}
10
10
  # * Reading/writing Ogg Vorbis tags: {TagLib::Ogg::Vorbis::File}.
11
- #
11
+ #
12
12
  # ## String Encodings
13
13
  #
14
14
  # Sometimes, it is necessary to specify which encoding should be used to
@@ -31,7 +31,48 @@ module TagLib
31
31
  #
32
32
  # Should you need more, use the file type specific classes, see
33
33
  # subclasses of {TagLib::File}.
34
+ #
35
+ # @example Reading tags
36
+ # TagLib::FileRef.open("foo.flac") do |file|
37
+ # tag = file.tag
38
+ # puts tag.artist
39
+ # puts tag.title
40
+ # end
41
+ #
42
+ # @example Reading audio properties
43
+ # TagLib::FileRef.open("bar.oga") do |file|
44
+ # prop = file.audio_properties
45
+ # puts prop.length
46
+ # puts prop.bitrate
47
+ # end
48
+ #
34
49
  class FileRef
50
+
51
+ # Creates a new file and passes it to the provided block,
52
+ # closing the file automatically at the end of the block.
53
+ #
54
+ # Note that after the block is done, the file is closed and
55
+ # all memory is released for objects read from the file
56
+ # (basically everything from the `TagLib` namespace).
57
+ #
58
+ # Using `open` is preferable to using `new` and then
59
+ # manually `close`.
60
+ #
61
+ # @example Reading a title
62
+ # title = TagLib::FileRef.open("file.oga") do |file|
63
+ # tag = file.tag
64
+ # tag.title
65
+ # end
66
+ #
67
+ # @param (see #initialize)
68
+ # @yield [file] the {FileRef} object, as obtained by {#initialize}
69
+ # @return the return value of the block
70
+ #
71
+ # @since 0.4.0
72
+ def self.open(filename, read_audio_properties=true,
73
+ audio_properties_style=TagLib::AudioProperties::Average)
74
+ end
75
+
35
76
  # Create a FileRef from a file name.
36
77
  #
37
78
  # @param [String] filename
@@ -75,11 +116,13 @@ module TagLib
75
116
  # @abstract Base class for files, see subclasses.
76
117
  class File
77
118
  # Closes the file and releases all objects that were read from the
78
- # file.
119
+ # file (basically everything from the TagLib namespace).
79
120
  #
80
121
  # After this method has been called, no other methods on this object
81
122
  # may be called. So it's a good idea to always use it like this:
82
123
  #
124
+ # file = TagLib::MPEG::File.new("file.mp3")
125
+ # # ...
83
126
  # file.close
84
127
  # file = nil
85
128
  #
@@ -88,6 +131,12 @@ module TagLib
88
131
  # run, which may be much later. On Windows, this is especially
89
132
  # important as the file is locked until it is closed.
90
133
  #
134
+ # As a better alternative to this, use the `open` class method:
135
+ #
136
+ # TagLib::MPEG::File.open("file.mp3") do |file|
137
+ # # ...
138
+ # end
139
+ #
91
140
  # @return [void]
92
141
  def close
93
142
  end
@@ -1,5 +1,66 @@
1
1
  module TagLib::ID3v2
2
- # An ID3v2 tag.
2
+ # An ID3v2 tag. A tag consists of a list of frames, identified by IDs.
3
+ #
4
+ # ## Encoding
5
+ #
6
+ # By default, taglib stores ID3v2 text frames as ISO-8859-1 (Latin-1) if the
7
+ # text contains only characters that are available in that encoding. If
8
+ # not (e.g. with Cyrillic, Chinese, Japanese), it prints a warning and
9
+ # stores the text as UTF-8.
10
+ #
11
+ # When you already know that you want to store the text as UTF-8, you can
12
+ # change the default text encoding:
13
+ #
14
+ # frame_factory = TagLib::ID3v2::FrameFactory.instance
15
+ # frame_factory.default_text_encoding = TagLib::String::UTF8
16
+ #
17
+ # Another option is using the frame API directly:
18
+ #
19
+ # title = tag.frame_list('TIT2').first
20
+ # title.text = "Joga"
21
+ # title.text_encoding = TagLib::String::UTF8
22
+ #
23
+ # @example Read ID3v2 frames from a file
24
+ # TagLib::MPEG::File.new("wake_up.mp3") do |file|
25
+ # tag = file.id3v2_tag
26
+ #
27
+ # # Read basic attributes
28
+ # tag.title #=> "Wake Up"
29
+ # tag.artist #=> "Arcade Fire"
30
+ # tag.track #=> 7
31
+ #
32
+ # # Access all frames
33
+ # tag.frame_list.size #=> 13
34
+ #
35
+ # # Track frame
36
+ # track = tag.frame_list('TRCK').first
37
+ # track.to_s #=> "7/10"
38
+ #
39
+ # # Attached picture frame
40
+ # cover = tag.frame_list('APIC').first
41
+ # cover.mime_type #=> "image/jpeg"
42
+ # cover.picture #=> "\xFF\xD8\xFF\xE0\x00\x10JFIF..."
43
+ # end
44
+ #
45
+ # @example Add frames and save file
46
+ # TagLib::MPEG::File.new("joga.mp3") do |file|
47
+ # tag = file.id3v2_tag
48
+ #
49
+ # # Write basic attributes
50
+ # tag.artist = "Björk"
51
+ # tag.title = "Jóga"
52
+ #
53
+ # # Add attached picture frame
54
+ # apic = TagLib::ID3v2::AttachedPictureFrame.new
55
+ # apic.mime_type = "image/jpeg"
56
+ # apic.description = "Cover"
57
+ # apic.type = TagLib::ID3v2::AttachedPictureFrame::FrontCover
58
+ # apic.picture = File.open("cover.jpg", 'rb'){ |f| f.read }
59
+ #
60
+ # tag.add_frame(apic)
61
+ #
62
+ # file.save
63
+ # end
3
64
  class Tag < TagLib::Tag
4
65
  # Get a list of frames. Note that the frames returned are subclasses
5
66
  # of {TagLib::ID3v2::Frame}, depending on the frame ID.
@@ -1,6 +1,23 @@
1
1
  module TagLib::MPEG
2
2
  # The file class for `.mp3` and other MPEG files.
3
+ #
4
+ # @example Reading a title
5
+ # title = TagLib::MPEG::File.open("file.mp3") do |file|
6
+ # tag = file.tag
7
+ # tag.title
8
+ # end
9
+ #
3
10
  class File < TagLib::File
11
+ # {include:TagLib::FileRef.open}
12
+ #
13
+ # @param (see #initialize)
14
+ # @yield [file] the {File} object, as obtained by {#initialize}
15
+ # @return the return value of the block
16
+ #
17
+ # @since 0.4.0
18
+ def self.open(filename, read_properties=true)
19
+ end
20
+
4
21
  # Load an MPEG file.
5
22
  #
6
23
  # @param [String] filename
@@ -1,7 +1,26 @@
1
1
  module TagLib::Ogg::Vorbis
2
2
 
3
3
  # The file class for `.ogg` and other `.oga` files.
4
+ #
5
+ # @example Reading Vorbis comments
6
+ # TagLib::Ogg::Vorbis::File.open("file.oga") do |file|
7
+ # tag = file.tag
8
+ # puts tag.title
9
+ # fields = tag.field_list_map
10
+ # puts fields['DATE']
11
+ # end
12
+ #
4
13
  class File < TagLib::Ogg::File
14
+ # {include:TagLib::FileRef.open}
15
+ #
16
+ # @param (see #initialize)
17
+ # @yield [file] the {File} object, as obtained by {#initialize}
18
+ # @return the return value of the block
19
+ #
20
+ # @since 0.4.0
21
+ def self.open(filename, read_properties=true)
22
+ end
23
+
5
24
  # Load an Ogg Vorbis file.
6
25
  #
7
26
  # @param [String] filename
@@ -85,8 +85,26 @@ VALUE taglib_filename_to_ruby_string(TagLib::FileName filename) {
85
85
 
86
86
  TagLib::FileName ruby_string_to_taglib_filename(VALUE s) {
87
87
  #ifdef _WIN32
88
- const char *filename = StringValuePtr(s);
89
- return TagLib::FileName(filename);
88
+ #if defined(HAVE_RUBY_ENCODING_H) && HAVE_RUBY_ENCODING_H
89
+ VALUE ospath;
90
+ const char *utf8;
91
+ int len;
92
+ wchar_t *wide;
93
+
94
+ ospath = rb_str_encode_ospath(s);
95
+ utf8 = StringValuePtr(ospath);
96
+ len = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, NULL, 0);
97
+ if (!(wide = (wchar_t *) xmalloc(sizeof(wchar_t) * len))) {
98
+ return TagLib::FileName((const char *) NULL);
99
+ }
100
+ MultiByteToWideChar(CP_UTF8, 0, utf8, -1, wide, len);
101
+ TagLib::FileName filename(wide);
102
+ xfree(wide);
103
+ return filename;
104
+ #else
105
+ const char *filename = StringValuePtr(s);
106
+ return TagLib::FileName(filename);
107
+ #endif
90
108
  #else
91
109
  return StringValuePtr(s);
92
110
  #endif