taglib-ruby 0.3.1 → 0.4.0

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