taglib-ruby 0.4.0-x86-mingw32

Sign up to get free protection for your applications and to get access to all the features.
Files changed (85) hide show
  1. data/.yardopts +9 -0
  2. data/CHANGES.md +53 -0
  3. data/Gemfile +4 -0
  4. data/Guardfile +8 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +87 -0
  7. data/Rakefile +29 -0
  8. data/docs/default/fulldoc/html/css/common.css +1 -0
  9. data/docs/taglib/base.rb +202 -0
  10. data/docs/taglib/id3v1.rb +5 -0
  11. data/docs/taglib/id3v2.rb +444 -0
  12. data/docs/taglib/mpeg.rb +120 -0
  13. data/docs/taglib/ogg.rb +77 -0
  14. data/docs/taglib/vorbis.rb +62 -0
  15. data/ext/extconf_common.rb +29 -0
  16. data/ext/taglib_base/extconf.rb +4 -0
  17. data/ext/taglib_base/includes.i +115 -0
  18. data/ext/taglib_base/taglib_base.i +139 -0
  19. data/ext/taglib_base/taglib_base_wrap.cxx +5153 -0
  20. data/ext/taglib_id3v1/extconf.rb +4 -0
  21. data/ext/taglib_id3v1/taglib_id3v1.i +11 -0
  22. data/ext/taglib_id3v1/taglib_id3v1_wrap.cxx +3110 -0
  23. data/ext/taglib_id3v2/extconf.rb +4 -0
  24. data/ext/taglib_id3v2/relativevolumeframe.i +35 -0
  25. data/ext/taglib_id3v2/taglib_id3v2.i +112 -0
  26. data/ext/taglib_id3v2/taglib_id3v2_wrap.cxx +9033 -0
  27. data/ext/taglib_mpeg/extconf.rb +4 -0
  28. data/ext/taglib_mpeg/taglib_mpeg.i +75 -0
  29. data/ext/taglib_mpeg/taglib_mpeg_wrap.cxx +4726 -0
  30. data/ext/taglib_ogg/extconf.rb +4 -0
  31. data/ext/taglib_ogg/taglib_ogg.i +36 -0
  32. data/ext/taglib_ogg/taglib_ogg_wrap.cxx +3631 -0
  33. data/ext/taglib_vorbis/extconf.rb +4 -0
  34. data/ext/taglib_vorbis/taglib_vorbis.i +48 -0
  35. data/ext/taglib_vorbis/taglib_vorbis_wrap.cxx +3083 -0
  36. data/ext/valgrind-suppressions.txt +170 -0
  37. data/ext/win.cmake +5 -0
  38. data/lib/libtag.dll +0 -0
  39. data/lib/taglib.rb +14 -0
  40. data/lib/taglib/base.rb +19 -0
  41. data/lib/taglib/id3v1.rb +1 -0
  42. data/lib/taglib/id3v2.rb +20 -0
  43. data/lib/taglib/mpeg.rb +7 -0
  44. data/lib/taglib/ogg.rb +1 -0
  45. data/lib/taglib/version.rb +10 -0
  46. data/lib/taglib/vorbis.rb +7 -0
  47. data/lib/taglib_base.so +0 -0
  48. data/lib/taglib_id3v1.so +0 -0
  49. data/lib/taglib_id3v2.so +0 -0
  50. data/lib/taglib_mpeg.so +0 -0
  51. data/lib/taglib_ogg.so +0 -0
  52. data/lib/taglib_vorbis.so +0 -0
  53. data/taglib-ruby.gemspec +122 -0
  54. data/tasks/docs_coverage.rake +26 -0
  55. data/tasks/ext.rake +81 -0
  56. data/tasks/gemspec_check.rake +19 -0
  57. data/tasks/swig.rake +43 -0
  58. data/test/data/Makefile +15 -0
  59. data/test/data/add-relative-volume.cpp +40 -0
  60. data/test/data/crash.mp3 +0 -0
  61. data/test/data/globe_east_540.jpg +0 -0
  62. data/test/data/id3v1-create.cpp +31 -0
  63. data/test/data/id3v1.mp3 +0 -0
  64. data/test/data/relative-volume.mp3 +0 -0
  65. data/test/data/sample.mp3 +0 -0
  66. data/test/data/unicode.mp3 +0 -0
  67. data/test/data/vorbis-create.cpp +42 -0
  68. data/test/data/vorbis.oga +0 -0
  69. data/test/fileref_open_test.rb +32 -0
  70. data/test/fileref_properties_test.rb +21 -0
  71. data/test/fileref_write_test.rb +62 -0
  72. data/test/helper.rb +10 -0
  73. data/test/id3v1_tag_test.rb +36 -0
  74. data/test/id3v2_frames_test.rb +115 -0
  75. data/test/id3v2_memory_test.rb +87 -0
  76. data/test/id3v2_relative_volume_test.rb +62 -0
  77. data/test/id3v2_tag_test.rb +59 -0
  78. data/test/id3v2_unicode_test.rb +47 -0
  79. data/test/id3v2_write_test.rb +100 -0
  80. data/test/mpeg_file_test.rb +76 -0
  81. data/test/tag_test.rb +21 -0
  82. data/test/unicode_filename_test.rb +29 -0
  83. data/test/vorbis_file_test.rb +54 -0
  84. data/test/vorbis_tag_test.rb +79 -0
  85. metadata +191 -0
@@ -0,0 +1,120 @@
1
+ module TagLib::MPEG
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
+ #
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
+
21
+ # Load an MPEG file.
22
+ #
23
+ # @param [String] filename
24
+ # @param [Boolean] read_properties if audio properties should be
25
+ # read
26
+ def initialize(filename, read_properties=true)
27
+ end
28
+
29
+ # Returns a tag that contains attributes from both the ID3v2 and
30
+ # ID3v1 tag, with ID3v2 attributes having precendence.
31
+ #
32
+ # @return [TagLib::Tag]
33
+ # @return [nil] if not present
34
+ def tag
35
+ end
36
+
37
+ # Returns the ID3v1 tag.
38
+ #
39
+ # @param create if a new tag should be created when none exists
40
+ # @return [TagLib::ID3v1::Tag]
41
+ # @return [nil] if not present
42
+ def id3v1_tag(create=false)
43
+ end
44
+
45
+ # Returns the ID3v2 tag.
46
+ #
47
+ # @param create if a new tag should be created when none exists
48
+ # @return [TagLib::ID3v2::Tag]
49
+ # @return [nil] if not present
50
+ def id3v2_tag(create=false)
51
+ end
52
+
53
+ # Returns audio properties.
54
+ #
55
+ # @return [TagLib::MPEG::Properties]
56
+ def audio_properties
57
+ end
58
+ end
59
+
60
+ # Audio properties for MPEG files.
61
+ class Properties < TagLib::AudioProperties
62
+ # @return [TagLib::MPEG::XingHeader] Xing header
63
+ # @return [nil] if not present
64
+ def xing_header
65
+ end
66
+
67
+ # @return [TagLib::MPEG::Header constant] MPEG version,
68
+ # e.g. {TagLib::MPEG::Header::Version1}
69
+ def version
70
+ end
71
+
72
+ # @return [Integer] MPEG layer (1-3)
73
+ def layer
74
+ end
75
+
76
+ # @return [true] if MPEG protection bit is set
77
+ def protection_enabled
78
+ end
79
+
80
+ # @return [TagLib::MPEG::Header constant] channel mode,
81
+ # e.g. {TagLib::MPEG::Header::JointStereo}
82
+ def channel_mode
83
+ end
84
+
85
+ # @return [true] if copyrighted bit is set
86
+ def copyrighted?
87
+ end
88
+
89
+ # @return [true] if original bit is set
90
+ def original?
91
+ end
92
+ end
93
+
94
+ # MPEG header.
95
+ class Header
96
+ Version1 = 0
97
+ Version2 = 1
98
+ Version2_5 = 2
99
+
100
+ Stereo = 0
101
+ JointStereo = 1
102
+ DualChannel = 2
103
+ SingleChannel = 3
104
+ end
105
+
106
+ # Xing VBR header.
107
+ class XingHeader
108
+ # @return [true] if a valid Xing header is present
109
+ def valid?
110
+ end
111
+
112
+ # @return [Integer] total number of frames
113
+ def total_frames
114
+ end
115
+
116
+ # @return [Integer] total size of stream in bytes
117
+ def total_size
118
+ end
119
+ end
120
+ end
@@ -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,62 @@
1
+ module TagLib::Ogg::Vorbis
2
+
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
+ #
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
+
24
+ # Load an Ogg Vorbis file.
25
+ #
26
+ # @param [String] filename
27
+ # @param [Boolean] read_properties if audio properties should be
28
+ # read
29
+ def initialize(filename, read_properties=true)
30
+ end
31
+
32
+ # Returns the VorbisComment tag.
33
+ #
34
+ # @return [TagLib::Ogg::XiphComment]
35
+ def tag
36
+ end
37
+
38
+ # Returns audio properties.
39
+ #
40
+ # @return [TagLib::Ogg::Vorbis::Properties]
41
+ def audio_properties
42
+ end
43
+ end
44
+
45
+ # Ogg Vorbis audio properties.
46
+ class Properties < TagLib::AudioProperties
47
+ # @return [Integer] Vorbis version
48
+ attr_reader :vorbis_version
49
+
50
+ # @return [Integer] maximum bitrate from Vorbis identification
51
+ # header
52
+ attr_reader :bitrate_maximum
53
+
54
+ # @return [Integer] nominal bitrate from Vorbis identification
55
+ # header
56
+ attr_reader :bitrate_nominal
57
+
58
+ # @return [Integer] minimum bitrate from Vorbis identification
59
+ # header
60
+ attr_reader :bitrate_minimum
61
+ end
62
+ end
@@ -0,0 +1,29 @@
1
+ # Default opt dirs to help mkmf find taglib
2
+ configure_args = "--with-opt-dir=/usr/local:/opt/local:/sw "
3
+ ENV['CONFIGURE_ARGS'] = configure_args + ENV.fetch('CONFIGURE_ARGS', "")
4
+
5
+ require 'mkmf'
6
+
7
+ def error msg
8
+ message msg + "\n"
9
+ abort
10
+ end
11
+
12
+ dir_config('tag')
13
+
14
+ if not have_library('stdc++')
15
+ error "You must have libstdc++ installed."
16
+ end
17
+
18
+ if not have_library('tag')
19
+ error <<-DESC
20
+ You must have taglib installed in order to use taglib-ruby.
21
+
22
+ Debian/Ubuntu: sudo apt-get install libtag1-dev
23
+ Fedora/RHEL: sudo yum install taglib-devel
24
+ Brew: brew install taglib
25
+ MacPorts: sudo port install taglib
26
+ DESC
27
+ end
28
+
29
+ $CFLAGS << " -DSWIG_TYPE_TABLE=taglib"
@@ -0,0 +1,4 @@
1
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..'))
2
+ require 'extconf_common'
3
+
4
+ create_makefile('taglib_base')
@@ -0,0 +1,115 @@
1
+ %trackobjects;
2
+
3
+ // Undefine macros we don't need for wrapping
4
+ #define TAGLIB_EXPORT
5
+ #define TAGLIB_IGNORE_MISSING_DESTRUCTOR
6
+
7
+ // Replaces the typemap from swigtype.swg and just adds the line
8
+ // SWIG_RubyUnlinkObjects. This is done to be safe in the case when a
9
+ // disowned object is deleted by C++ (e.g. with remove_frame).
10
+ %typemap(in, noblock=1) SWIGTYPE *DISOWN (int res = 0) {
11
+ res = SWIG_ConvertPtr($input, %as_voidptrptr(&$1), $descriptor, SWIG_POINTER_DISOWN | %convertptr_flags);
12
+ if (!SWIG_IsOK(res)) {
13
+ %argument_fail(res,"$type", $symname, $argnum);
14
+ }
15
+ SWIG_RubyUnlinkObjects(%as_voidptr($1));
16
+ }
17
+
18
+ %{
19
+ #include <taglib/tstring.h>
20
+ #include <taglib/tstringlist.h>
21
+ #include <taglib/tfile.h>
22
+
23
+ #if defined(HAVE_RUBY_ENCODING_H) && HAVE_RUBY_ENCODING_H
24
+ # include <ruby/encoding.h>
25
+ # define ASSOCIATE_UTF8_ENCODING(value) rb_enc_associate(value, rb_utf8_encoding());
26
+ # define CONVERT_TO_UTF8(value) rb_str_export_to_enc(value, rb_utf8_encoding())
27
+ #else
28
+ # define ASSOCIATE_UTF8_ENCODING(value) /* nothing */
29
+ # define CONVERT_TO_UTF8(value) value
30
+ #endif
31
+
32
+ VALUE taglib_bytevector_to_ruby_string(const TagLib::ByteVector &byteVector) {
33
+ if (byteVector.isNull()) {
34
+ return Qnil;
35
+ } else {
36
+ return rb_tainted_str_new(byteVector.data(), byteVector.size());
37
+ }
38
+ }
39
+
40
+ TagLib::ByteVector ruby_string_to_taglib_bytevector(VALUE s) {
41
+ return TagLib::ByteVector(RSTRING_PTR(s), RSTRING_LEN(s));
42
+ }
43
+
44
+ VALUE taglib_string_to_ruby_string(const TagLib::String & string) {
45
+ if (string.isNull()) {
46
+ return Qnil;
47
+ } else {
48
+ VALUE result = rb_tainted_str_new2(string.toCString(true));
49
+ ASSOCIATE_UTF8_ENCODING(result);
50
+ return result;
51
+ }
52
+ }
53
+
54
+ TagLib::String ruby_string_to_taglib_string(VALUE s) {
55
+ return TagLib::String(RSTRING_PTR(CONVERT_TO_UTF8(s)), TagLib::String::UTF8);
56
+ }
57
+
58
+ VALUE taglib_string_list_to_ruby_array(const TagLib::StringList & list) {
59
+ VALUE ary = rb_ary_new2(list.size());
60
+ for (TagLib::StringList::ConstIterator it = list.begin(); it != list.end(); it++) {
61
+ VALUE s = taglib_string_to_ruby_string(*it);
62
+ rb_ary_push(ary, s);
63
+ }
64
+ return ary;
65
+ }
66
+
67
+ TagLib::StringList ruby_array_to_taglib_string_list(VALUE ary) {
68
+ TagLib::StringList result = TagLib::StringList();
69
+ for (long i = 0; i < RARRAY_LEN(ary); i++) {
70
+ VALUE e = RARRAY_PTR(ary)[i];
71
+ TagLib::String s = ruby_string_to_taglib_string(e);
72
+ result.append(s);
73
+ }
74
+ return result;
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
+ #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
108
+ #else
109
+ return StringValuePtr(s);
110
+ #endif
111
+ }
112
+
113
+ %}
114
+
115
+ // vim: set filetype=cpp sw=2 ts=2 expandtab:
@@ -0,0 +1,139 @@
1
+ %module "TagLib"
2
+ %{
3
+ #include <taglib/taglib.h>
4
+ #include <taglib/tbytevector.h>
5
+ #include <taglib/tlist.h>
6
+ #include <taglib/fileref.h>
7
+ #include <taglib/tag.h>
8
+ %}
9
+
10
+ %include "includes.i"
11
+
12
+ namespace TagLib {
13
+ class StringList;
14
+ class ByteVector;
15
+
16
+ class String {
17
+ public:
18
+ enum Type { Latin1 = 0, UTF16 = 1, UTF16BE = 2, UTF8 = 3, UTF16LE = 4 };
19
+ };
20
+
21
+ class FileName;
22
+
23
+ typedef wchar_t wchar;
24
+ typedef unsigned char uchar;
25
+ typedef unsigned int uint;
26
+ typedef unsigned long ulong;
27
+ }
28
+
29
+
30
+ // Rename setters to Ruby convention (combining SWIG rename functions
31
+ // does not seem to be possible, thus resort to some magic)
32
+ %rename("%(command: ruby -e 'print(ARGV[0][3..-1].split(/(?=[A-Z])/).join(\"_\").downcase + \"=\")' )s",
33
+ regexmatch$name="^set[A-Z]") "";
34
+
35
+ // isFoo -> foo?
36
+ %rename("%(command: ruby -e 'print(ARGV[0][2..-1].split(/(?=[A-Z])/).join(\"_\").downcase + \"?\")' )s",
37
+ regexmatch$name="^is[A-Z]") "";
38
+
39
+ // ByteVector
40
+ %typemap(out) TagLib::ByteVector {
41
+ $result = taglib_bytevector_to_ruby_string($1);
42
+ }
43
+ %typemap(out) TagLib::ByteVector * {
44
+ $result = taglib_bytevector_to_ruby_string(*($1));
45
+ }
46
+ %typemap(in) TagLib::ByteVector & (TagLib::ByteVector tmp) {
47
+ tmp = ruby_string_to_taglib_bytevector($input);
48
+ $1 = &tmp;
49
+ }
50
+ %typemap(in) TagLib::ByteVector * (TagLib::ByteVector tmp) {
51
+ tmp = ruby_string_to_taglib_bytevector($input);
52
+ $1 = &tmp;
53
+ }
54
+ %typemap(typecheck) const TagLib::ByteVector & = char *;
55
+
56
+ // String
57
+ %typemap(out) TagLib::String {
58
+ $result = taglib_string_to_ruby_string($1);
59
+ }
60
+ // tmp is used for having a local variable that is destroyed at the end
61
+ // of the function. Doing "new TagLib::String" would be a big no-no.
62
+ %typemap(in) TagLib::String (TagLib::String tmp) {
63
+ tmp = ruby_string_to_taglib_string($input);
64
+ $1 = &tmp;
65
+ }
66
+ %typemap(typecheck) TagLib::String = char *;
67
+ %apply TagLib::String { TagLib::String &, const TagLib::String & };
68
+
69
+ // StringList
70
+ %typemap(out) TagLib::StringList {
71
+ $result = taglib_string_list_to_ruby_array($1);
72
+ }
73
+ %typemap(in) TagLib::StringList (TagLib::StringList tmp) {
74
+ tmp = ruby_array_to_taglib_string_list($input);
75
+ $1 = &tmp;
76
+ }
77
+ %apply TagLib::StringList { TagLib::StringList &, const TagLib::StringList & };
78
+
79
+ %typemap(out) TagLib::FileName {
80
+ $result = taglib_filename_to_ruby_string($1);
81
+ }
82
+ %typemap(in) TagLib::FileName {
83
+ $1 = ruby_string_to_taglib_filename($input);
84
+ if ((const char *)(TagLib::FileName)($1) == NULL) {
85
+ SWIG_exception_fail(SWIG_MemoryError, "Failed to allocate memory for file name.");
86
+ }
87
+ }
88
+ %typemap(typecheck) TagLib::FileName = char *;
89
+ %feature("valuewrapper") TagLib::FileName;
90
+
91
+ %ignore TagLib::List::operator[];
92
+ %ignore TagLib::List::operator=;
93
+ %include <taglib/tlist.h>
94
+
95
+ %include <taglib/tag.h>
96
+
97
+ %include <taglib/audioproperties.h>
98
+
99
+ %ignore TagLib::FileName;
100
+ %include <taglib/tfile.h>
101
+
102
+ %ignore TagLib::FileRef::operator=;
103
+ %ignore TagLib::FileRef::operator!=;
104
+ %warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) TagLib::FileRef::FileTypeResolver;
105
+ %include <taglib/fileref.h>
106
+
107
+ %begin %{
108
+ static void free_taglib_fileref(void *ptr);
109
+ %}
110
+ %header %{
111
+ static void free_taglib_fileref(void *ptr) {
112
+ TagLib::FileRef *fileref = (TagLib::FileRef *) ptr;
113
+
114
+ TagLib::Tag *tag = fileref->tag();
115
+ if (tag) {
116
+ SWIG_RubyUnlinkObjects(tag);
117
+ SWIG_RubyRemoveTracking(tag);
118
+ }
119
+
120
+ TagLib::AudioProperties *properties = fileref->audioProperties();
121
+ if (properties) {
122
+ SWIG_RubyUnlinkObjects(properties);
123
+ SWIG_RubyRemoveTracking(properties);
124
+ }
125
+
126
+ SWIG_RubyUnlinkObjects(ptr);
127
+ SWIG_RubyRemoveTracking(ptr);
128
+
129
+ delete fileref;
130
+ }
131
+ %}
132
+
133
+ %extend TagLib::FileRef {
134
+ void close() {
135
+ free_taglib_fileref($self);
136
+ }
137
+ }
138
+
139
+ // vim: set filetype=cpp sw=2 ts=2 expandtab: