taglib-ruby 0.1.1 → 0.2.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.
data/lib/taglib.rb CHANGED
@@ -1,3 +1,4 @@
1
+ require 'taglib/version'
1
2
  require 'taglib/base'
2
3
  require 'taglib/mpeg'
3
4
  require 'taglib/id3v2'
data/lib/taglib/id3v2.rb CHANGED
@@ -2,40 +2,18 @@ require 'taglib_id3v2'
2
2
 
3
3
  module TagLib
4
4
  module ID3v2
5
- class FrameList
6
- include Enumerable
7
-
8
- def each
9
- it = self.begin
10
- it_end = self.end
11
- while it != it_end
12
- frame = it.value
13
- casted_frame = frame.cast
14
- yield casted_frame
15
- it = it.next
16
- end
17
- end
18
- end
19
5
  class Frame
20
6
  def to_s
21
7
  to_string
22
8
  end
23
- def cast
24
- case frame_id
25
- when "APIC" then to_attached_picture_frame
26
- when "COMM" then to_comments_frame
27
- when "GEOB" then to_general_encapsulated_object_frame
28
- when "POPM" then to_popularimeter_frame
29
- when "PRIV" then to_private_frame
30
- when "RVAD" then to_relative_volume_frame
31
- when "TXXX" then to_user_text_identification_frame
32
- when /T.../ then to_text_identification_frame
33
- when "UFID" then to_unique_file_identifier_frame
34
- when "USLT" then to_unsynchronized_lyrics_frame
35
- when "WXXX" then to_user_url_link_frame
36
- when /W.../ then to_url_link_frame
37
- else self
38
- end
9
+
10
+ def inspect
11
+ # Overwrite inspect because Object#inspect calls to_s. In case
12
+ # of an unlinked frame, calling to_s would lead to calling into
13
+ # SWIG through to_string, which in turn would raise an exception
14
+ # with a message including an inspect of this object, which
15
+ # would call to_s -> stack overflow.
16
+ "#<%s:0x%x>" % [self.class.to_s, object_id << 1]
39
17
  end
40
18
  end
41
19
  end
@@ -1,8 +1,8 @@
1
1
  module TagLib
2
2
  module Version
3
3
  MAJOR = 0
4
- MINOR = 1
5
- PATCH = 1
4
+ MINOR = 2
5
+ PATCH = 0
6
6
  BUILD = nil
7
7
 
8
8
  STRING = [MAJOR, MINOR, PATCH, BUILD].compact.join('.')
data/taglib-ruby.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "taglib-ruby"
8
- s.version = "0.1.1"
8
+ s.version = "0.2.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Robin Stocker"]
12
- s.date = "2011-09-17"
12
+ s.date = "2011-10-22"
13
13
  s.description = "Ruby interface for the taglib C++ library.\n\nIn contrast to other libraries, this one wraps the C++ API using SWIG,\nnot only the minimal C API. This means that all tags can be accessed.\n"
14
14
  s.email = "robin@nibor.org"
15
15
  s.extensions = ["ext/taglib_base/extconf.rb", "ext/taglib_mpeg/extconf.rb", "ext/taglib_id3v2/extconf.rb"]
@@ -18,11 +18,18 @@ Gem::Specification.new do |s|
18
18
  "README.md"
19
19
  ]
20
20
  s.files = [
21
+ ".yardopts",
22
+ "CHANGES.md",
21
23
  "Gemfile",
22
24
  "Gemfile.lock",
25
+ "Guardfile",
23
26
  "LICENSE.txt",
24
27
  "README.md",
25
28
  "Rakefile",
29
+ "docs/default/fulldoc/html/css/common.css",
30
+ "docs/taglib/base.rb",
31
+ "docs/taglib/id3v2.rb",
32
+ "docs/taglib/mpeg.rb",
26
33
  "ext/Rakefile",
27
34
  "ext/extconf_common.rb",
28
35
  "ext/taglib_base/extconf.rb",
@@ -30,6 +37,7 @@ Gem::Specification.new do |s|
30
37
  "ext/taglib_base/taglib_base.i",
31
38
  "ext/taglib_base/taglib_base_wrap.cxx",
32
39
  "ext/taglib_id3v2/extconf.rb",
40
+ "ext/taglib_id3v2/relativevolumeframe.i",
33
41
  "ext/taglib_id3v2/taglib_id3v2.i",
34
42
  "ext/taglib_id3v2/taglib_id3v2_wrap.cxx",
35
43
  "ext/taglib_mpeg/extconf.rb",
@@ -42,15 +50,22 @@ Gem::Specification.new do |s|
42
50
  "lib/taglib/mpeg.rb",
43
51
  "lib/taglib/version.rb",
44
52
  "taglib-ruby.gemspec",
53
+ "tasks/docs_coverage.rake",
54
+ "test/data/add-relative-volume.cpp",
55
+ "test/data/crash.mp3",
45
56
  "test/data/globe_east_540.jpg",
57
+ "test/data/relative-volume.mp3",
46
58
  "test/data/sample.mp3",
47
59
  "test/data/unicode.mp3",
48
60
  "test/helper.rb",
61
+ "test/test_fileref_properties.rb",
49
62
  "test/test_id3v2_frames.rb",
50
63
  "test/test_id3v2_memory.rb",
64
+ "test/test_id3v2_relative_volume.rb",
51
65
  "test/test_id3v2_tag.rb",
52
66
  "test/test_id3v2_unicode.rb",
53
67
  "test/test_id3v2_write.rb",
68
+ "test/test_mpeg_file.rb",
54
69
  "test/test_tag.rb"
55
70
  ]
56
71
  s.homepage = "http://github.com/robinst/taglib-ruby"
@@ -69,14 +84,18 @@ Gem::Specification.new do |s|
69
84
  s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
70
85
  s.add_development_dependency(%q<jeweler>, ["~> 1.6.4"])
71
86
  s.add_development_dependency(%q<rcov>, [">= 0"])
72
- s.add_development_dependency(%q<rdoc>, ["~> 3.9"])
87
+ s.add_development_dependency(%q<yard>, ["~> 0.7"])
88
+ s.add_development_dependency(%q<redcarpet>, [">= 0"])
89
+ s.add_development_dependency(%q<guard-test>, ["~> 0.4.0"])
73
90
  else
74
91
  s.add_dependency(%q<rake-compiler>, ["~> 0.7"])
75
92
  s.add_dependency(%q<shoulda>, ["~> 2.11"])
76
93
  s.add_dependency(%q<bundler>, ["~> 1.0.0"])
77
94
  s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
78
95
  s.add_dependency(%q<rcov>, [">= 0"])
79
- s.add_dependency(%q<rdoc>, ["~> 3.9"])
96
+ s.add_dependency(%q<yard>, ["~> 0.7"])
97
+ s.add_dependency(%q<redcarpet>, [">= 0"])
98
+ s.add_dependency(%q<guard-test>, ["~> 0.4.0"])
80
99
  end
81
100
  else
82
101
  s.add_dependency(%q<rake-compiler>, ["~> 0.7"])
@@ -84,7 +103,9 @@ Gem::Specification.new do |s|
84
103
  s.add_dependency(%q<bundler>, ["~> 1.0.0"])
85
104
  s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
86
105
  s.add_dependency(%q<rcov>, [">= 0"])
87
- s.add_dependency(%q<rdoc>, ["~> 3.9"])
106
+ s.add_dependency(%q<yard>, ["~> 0.7"])
107
+ s.add_dependency(%q<redcarpet>, [">= 0"])
108
+ s.add_dependency(%q<guard-test>, ["~> 0.4.0"])
88
109
  end
89
110
  end
90
111
 
@@ -0,0 +1,26 @@
1
+ desc "Show the coverage of the actual API in ext/ by the API docs in docs/"
2
+ task :docs_coverage do |t|
3
+ def sort(objects)
4
+ objects.sort_by { |obj| obj.path }
5
+ end
6
+
7
+ YARD.parse("ext/**/*_wrap.cxx")
8
+ ext_codeobjects = sort(YARD::Registry.all)
9
+ YARD::Registry.clear
10
+ YARD.parse("docs/**/*.rb")
11
+ docs_codeobjects = sort(YARD::Registry.all(:module, :class, :method))
12
+
13
+ only_in_ext = (ext_codeobjects - docs_codeobjects)
14
+ only_in_docs = (docs_codeobjects - ext_codeobjects)
15
+
16
+ unless only_in_ext.empty?
17
+ puts
18
+ puts "=== Only in ext (to document): "
19
+ puts only_in_ext
20
+ end
21
+ unless only_in_docs.empty?
22
+ puts
23
+ puts "=== Only in docs (typo?): "
24
+ puts only_in_docs
25
+ end
26
+ end
@@ -0,0 +1,40 @@
1
+ #include <iostream>
2
+ #include <stdlib.h>
3
+
4
+ #include <taglib/taglib.h>
5
+ #include <taglib/mpegfile.h>
6
+ #include <taglib/id3v2tag.h>
7
+ #include <taglib/relativevolumeframe.h>
8
+
9
+ using namespace TagLib;
10
+
11
+ int main(int argc, char **argv) {
12
+ if (argc != 2) {
13
+ std::cout << "usage: " << argv[0] << " file.mp3" << std::endl;
14
+ exit(1);
15
+ }
16
+ char *filename = argv[1];
17
+
18
+ MPEG::File file(filename);
19
+ ID3v2::Tag *tag = file.ID3v2Tag(true);
20
+
21
+ ID3v2::RelativeVolumeFrame *rv = new ID3v2::RelativeVolumeFrame();
22
+
23
+ rv->setVolumeAdjustmentIndex(512);
24
+ rv->setVolumeAdjustmentIndex(1024, ID3v2::RelativeVolumeFrame::Subwoofer);
25
+
26
+ ID3v2::RelativeVolumeFrame::PeakVolume pv1;
27
+ pv1.bitsRepresentingPeak = 8;
28
+ pv1.peakVolume = "A"; // 0x41, 0b01000001
29
+ rv->setPeakVolume(pv1);
30
+
31
+ ID3v2::RelativeVolumeFrame::PeakVolume pv2;
32
+ pv2.bitsRepresentingPeak = 4;
33
+ pv2.peakVolume = "?"; // 0x3F, 0b00111111
34
+ rv->setPeakVolume(pv2, ID3v2::RelativeVolumeFrame::Subwoofer);
35
+
36
+ tag->addFrame(rv);
37
+ file.save();
38
+ }
39
+
40
+ // vim: set filetype=cpp sw=2 ts=2 expandtab:
Binary file
Binary file
@@ -0,0 +1,21 @@
1
+ require 'helper'
2
+
3
+ class TestFileRefProperties < Test::Unit::TestCase
4
+ context "The crash.mp3 file audio properties" do
5
+ setup do
6
+ @fileref = TagLib::FileRef.new("test/data/crash.mp3", true, TagLib::AudioProperties::Average)
7
+ @properties = @fileref.audio_properties
8
+ end
9
+
10
+ should "exist" do
11
+ assert_not_nil @properties
12
+ end
13
+
14
+ should "contain basic information" do
15
+ assert_equal 2, @properties.length
16
+ assert_equal 157, @properties.bitrate
17
+ assert_equal 44100, @properties.sample_rate
18
+ assert_equal 2, @properties.channels
19
+ end
20
+ end
21
+ end
@@ -20,8 +20,7 @@ class TestID3v2Frames < Test::Unit::TestCase
20
20
  should "be complete" do
21
21
  assert_not_nil @frames
22
22
  assert_equal 11, @frames.size
23
- iterator = @frames.begin
24
- frame = iterator.value
23
+ frame = @frames.first
25
24
  assert_equal "Dummy Title", frame.to_string
26
25
  end
27
26
 
@@ -35,9 +34,32 @@ class TestID3v2Frames < Test::Unit::TestCase
35
34
  apic = @tag.frame_list('APIC').first
36
35
  comm = @tag.frame_list('COMM').first
37
36
  tit2 = @tag.frame_list('TIT2').first
37
+ txxx = @tag.frame_list('TXXX').first
38
38
  assert_equal TagLib::ID3v2::AttachedPictureFrame, apic.class
39
39
  assert_equal TagLib::ID3v2::CommentsFrame, comm.class
40
40
  assert_equal TagLib::ID3v2::TextIdentificationFrame, tit2.class
41
+ assert_equal TagLib::ID3v2::UserTextIdentificationFrame, txxx.class
42
+ end
43
+
44
+ should "be removable" do
45
+ assert_equal 11, @tag.frame_list.size
46
+ tit2 = @tag.frame_list('TIT2').first
47
+ @tag.remove_frame(tit2)
48
+ assert_equal 10, @tag.frame_list.size
49
+ begin
50
+ tit2.to_string
51
+ flunk("Should have raised ObjectPreviouslyDeleted.")
52
+ rescue => e
53
+ assert_equal "ObjectPreviouslyDeleted", e.class.to_s
54
+ end
55
+ end
56
+
57
+ should "be removable by ID" do
58
+ frames = @tag.frame_list
59
+ @tag.remove_frames('COMM')
60
+ tit2 = frames.find{ |f| f.frame_id == 'TIT2' }
61
+ # Other frames should still be accessible
62
+ assert_equal "Dummy Title", tit2.to_s
41
63
  end
42
64
 
43
65
  context "APIC frame" do
@@ -77,12 +99,7 @@ class TestID3v2Frames < Test::Unit::TestCase
77
99
 
78
100
  should "have to_s" do
79
101
  expected = "[MusicBrainz Album Id] MusicBrainz Album Id 992dc19a-5631-40f5-b252-fbfedbc328a9"
80
- assert_equal expected, @txxx_frame.to_s
81
- end
82
-
83
- should "be convertable to its concrete type" do
84
- txxx = @txxx_frame.to_user_text_identification_frame
85
- assert_equal TagLib::ID3v2::UserTextIdentificationFrame, txxx.class
102
+ assert_equal expected, @txxx_frame.to_string
86
103
  end
87
104
 
88
105
  should "have field_list" do
@@ -0,0 +1,57 @@
1
+ require 'helper'
2
+
3
+ class TestID3v2RelativeVolumeFrame < Test::Unit::TestCase
4
+ context "The relative-volume.mp3 RVA2 frame" do
5
+ setup do
6
+ @file = TagLib::MPEG::File.new("test/data/relative-volume.mp3")
7
+ @tag = @file.id3v2_tag
8
+ @rv = @tag.frame_list('RVA2').first
9
+ end
10
+
11
+ should "exist" do
12
+ assert_not_nil @rv
13
+ end
14
+
15
+ should "have channels" do
16
+ expected = [TagLib::ID3v2::RelativeVolumeFrame::MasterVolume, TagLib::ID3v2::RelativeVolumeFrame::Subwoofer]
17
+ assert_equal expected, @rv.channels
18
+ end
19
+
20
+ should "have volume adjustments" do
21
+ assert_equal 512, @rv.volume_adjustment_index
22
+ assert_equal 1.0, @rv.volume_adjustment
23
+ assert_equal 1024, @rv.volume_adjustment_index(TagLib::ID3v2::RelativeVolumeFrame::Subwoofer)
24
+ assert_equal 2.0, @rv.volume_adjustment(TagLib::ID3v2::RelativeVolumeFrame::Subwoofer)
25
+ end
26
+
27
+ should "have peak volumes" do
28
+ master_pv = @rv.peak_volume
29
+ assert_equal 8, master_pv.bits_representing_peak
30
+ assert_equal 0b01000001.chr, master_pv.peak_volume
31
+
32
+ subwoofer_pv = @rv.peak_volume(TagLib::ID3v2::RelativeVolumeFrame::Subwoofer)
33
+ assert_equal 4, subwoofer_pv.bits_representing_peak
34
+ assert_equal 0b00111111.chr, subwoofer_pv.peak_volume
35
+ end
36
+
37
+ should "accept new volume adjustments" do
38
+ @rv.set_volume_adjustment_index(2048, TagLib::ID3v2::RelativeVolumeFrame::FrontCentre)
39
+ assert_equal 2048, @rv.volume_adjustment_index(TagLib::ID3v2::RelativeVolumeFrame::FrontCentre)
40
+ @rv.set_volume_adjustment(4.0, TagLib::ID3v2::RelativeVolumeFrame::FrontLeft)
41
+ assert_equal 4.0, @rv.volume_adjustment(TagLib::ID3v2::RelativeVolumeFrame::FrontLeft)
42
+ end
43
+
44
+ should "accept new peak volumes" do
45
+ pv = TagLib::ID3v2::PeakVolume.new
46
+ assert_equal 0, pv.bits_representing_peak
47
+ assert_equal "", pv.peak_volume
48
+ pv.bits_representing_peak = 6
49
+ pv.peak_volume = 0b110111.chr
50
+ @rv.set_peak_volume(pv, TagLib::ID3v2::RelativeVolumeFrame::BackLeft)
51
+
52
+ pv2 = @rv.peak_volume(TagLib::ID3v2::RelativeVolumeFrame::BackLeft)
53
+ assert_equal 6, pv2.bits_representing_peak
54
+ assert_equal 0b110111.chr, pv2.peak_volume
55
+ end
56
+ end
57
+ end
@@ -28,4 +28,27 @@ class TestID3v2Tag < Test::Unit::TestCase
28
28
  end
29
29
  end
30
30
  end
31
+
32
+ context "A new ID3v2::Tag" do
33
+ setup do
34
+ @tag = TagLib::ID3v2::Tag.new
35
+ end
36
+
37
+ should "be empty" do
38
+ assert @tag.empty?
39
+ end
40
+
41
+ should "have nil for string attributes" do
42
+ assert_nil @tag.title
43
+ assert_nil @tag.artist
44
+ assert_nil @tag.album
45
+ assert_nil @tag.comment
46
+ assert_nil @tag.genre
47
+ end
48
+
49
+ should "have 0 for numeric attributes" do
50
+ assert_equal 0, @tag.track
51
+ assert_equal 0, @tag.year
52
+ end
53
+ end
31
54
  end
@@ -0,0 +1,49 @@
1
+ require 'helper'
2
+
3
+ class TestMPEGFile < Test::Unit::TestCase
4
+ context "The crash.mp3 file" do
5
+ setup do
6
+ read_properties = true
7
+ @file = TagLib::MPEG::File.new("test/data/crash.mp3", read_properties)
8
+ end
9
+
10
+ context "audio properties" do
11
+ setup do
12
+ @properties = @file.audio_properties
13
+ end
14
+
15
+ should "be MPEG audio properties" do
16
+ assert_equal TagLib::MPEG::Properties, @properties.class
17
+ end
18
+
19
+ should "contain information" do
20
+ assert_equal 2, @properties.length
21
+ assert_equal 157, @properties.bitrate
22
+ assert_equal 44100, @properties.sample_rate
23
+ assert_equal 2, @properties.channels
24
+ assert_equal TagLib::MPEG::Header::Version1, @properties.version
25
+ assert_equal 3, @properties.layer
26
+ assert_equal false, @properties.protection_enabled
27
+ assert_equal TagLib::MPEG::Header::JointStereo, @properties.channel_mode
28
+ assert_equal false, @properties.copyrighted?
29
+ assert_equal true, @properties.original?
30
+ end
31
+
32
+ context "Xing header" do
33
+ setup do
34
+ @xing_header = @properties.xing_header
35
+ end
36
+
37
+ should "exist" do
38
+ assert_not_nil @xing_header
39
+ end
40
+
41
+ should "contain information" do
42
+ assert_true @xing_header.valid?
43
+ assert_equal 88, @xing_header.total_frames
44
+ assert_equal 45140, @xing_header.total_size
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end