id3lib-ruby 0.4.1 → 0.5.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/CHANGES CHANGED
@@ -1,5 +1,18 @@
1
1
  = id3lib-ruby changes
2
2
 
3
+ === 0.5.0 (2006-12-16)
4
+
5
+ * Warn when encountering nil field instead of raising exception (bug 6446).
6
+ * Corrected allowed fields - they are now generated from id3lib's source.
7
+ * Renamed :id field to :identifier because of confusion with frame ID.
8
+ * Added INSTALL document for installation instructions.
9
+ * Fixed memory leak in extension, where iterator was never released.
10
+ According to tests, there is no memory leak anymore.
11
+ * Added two patches for id3lib in mswin32 gem:
12
+ * unicode16: fixes Unicode writing bug
13
+ * convert_i-leak: fixes memory leak in Unicode conversion function
14
+ * Updated to SWIG 1.3.31.
15
+
3
16
  === 0.4.1 (r53)
4
17
 
5
18
  * Added :description to the allowed fields of :TXXX frames (patch 5484).
data/INSTALL ADDED
@@ -0,0 +1,57 @@
1
+ = id3lib-ruby installation instructions
2
+
3
+ == Binary package (Windows)
4
+
5
+ There are precompiled binary gems available for Windows, so the installation
6
+ is as simple as typing the following and selecting the newest mswin32 gem:
7
+
8
+ gem install id3lib-ruby
9
+
10
+ == Source package
11
+
12
+ For other systems, there is a RubyGems package or a compressed archive.
13
+
14
+ === Prerequisites
15
+
16
+ Before installing id3lib-ruby, you need to install the underlying id3lib
17
+ library and, depending on your system, set CONFIGURE_ARGS.
18
+
19
+ ==== Debian
20
+
21
+ Install libid3-dev and be sure to have ruby1.8-dev installed, otherwise you
22
+ won't be able to build Ruby extensions.
23
+
24
+ sudo aptitude install libid3-dev
25
+
26
+ ==== Gentoo
27
+
28
+ sudo emerge -n id3lib
29
+
30
+ ==== OS X with Fink
31
+
32
+ Install id3lib4-dev:
33
+
34
+ sudo apt-get install id3lib4-dev
35
+
36
+ Fink puts the library and header files in /sw. In order to enable the
37
+ id3lib-ruby install program to find them, do:
38
+
39
+ export CONFIGURE_ARGS="--with-opt-dir=/sw"
40
+
41
+ ==== Manual compilation
42
+
43
+ Download, compile and install id3lib. When installing in /usr/local, you
44
+ have to set CONFIGURE_ARGS:
45
+
46
+ export CONFIGURE_ARGS="--with-opt-dir=/usr/local"
47
+
48
+ === Installing id3lib-ruby
49
+
50
+ Now you're ready to install id3lib-ruby. If you use RubyGems, run the
51
+ following and select the newest version marked "ruby":
52
+
53
+ sudo gem install id3lib-ruby
54
+
55
+ Or if you install from the archive, unpack it and do:
56
+
57
+ sudo ruby setup.rb
data/README CHANGED
@@ -21,23 +21,14 @@ See TODO for planned features.
21
21
  The CHANGES file contains a list of changes between versions.
22
22
 
23
23
 
24
- == Online Information
25
-
26
- The home of id3lib-ruby is http://id3lib-ruby.rubyforge.org
27
-
28
-
29
24
  == Installation
30
25
 
31
- Note that id3lib has to be installed before running any of the following
32
- commands, unless you use the Windows binary gem.
33
-
34
- Installation through RubyGems:
26
+ See INSTALL.
35
27
 
36
- gem install id3lib-ruby
37
28
 
38
- Manual installation:
29
+ == Online Information
39
30
 
40
- ruby setup.rb
31
+ The home of id3lib-ruby is http://id3lib-ruby.rubyforge.org
41
32
 
42
33
 
43
34
  == Usage
data/Rakefile CHANGED
@@ -10,8 +10,6 @@ require 'rake/testtask'
10
10
  require 'rake/rdoctask'
11
11
 
12
12
 
13
- PKG_VERSION = '0.4.1'
14
-
15
13
  FILES_COMMON = FileList[
16
14
  'lib/**/*.rb',
17
15
  'test/test_*.rb',
@@ -21,6 +19,10 @@ FILES_COMMON = FileList[
21
19
  '*.rb'
22
20
  ]
23
21
 
22
+ FILES_DOC = FileList[
23
+ 'README', 'INSTALL', 'TODO', 'CHANGES'
24
+ ]
25
+
24
26
  FILES_EXT = FileList[
25
27
  'ext/*.rb',
26
28
  'ext/*.cxx',
@@ -56,8 +58,8 @@ Rake::RDocTask.new :rdoc do |rdoc|
56
58
  rdoc.rdoc_dir = 'doc'
57
59
  rdoc.title = 'id3lib-ruby'
58
60
  rdoc.options = RDOC_OPTS
61
+ rdoc.rdoc_files.include(FILES_DOC)
59
62
  rdoc.rdoc_files.include('lib/**/*.rb')
60
- rdoc.rdoc_files.include('README', 'TODO', 'CHANGES')
61
63
  end
62
64
  task :doc => [:rdoc]
63
65
 
@@ -65,7 +67,7 @@ task :doc => [:rdoc]
65
67
  if defined? Gem
66
68
  spec = Gem::Specification.new do |s|
67
69
  s.name = 'id3lib-ruby'
68
- s.version = PKG_VERSION
70
+ s.version = File.read('lib/id3lib.rb')[/VERSION = '(.*)'/, 1]
69
71
  s.summary =
70
72
  'id3lib-ruby provides a Ruby interface to the id3lib C++ library for ' +
71
73
  'easily editing ID3 tags (v1 and v2) like with pyid3lib.'
@@ -74,7 +76,7 @@ if defined? Gem
74
76
  s.extensions = ['ext/extconf.rb']
75
77
  s.test_files = FileList['test/test_*.rb']
76
78
  s.has_rdoc = true
77
- s.extra_rdoc_files = FileList['README', 'CHANGES', 'TODO']
79
+ s.extra_rdoc_files = FILES_DOC
78
80
  s.rdoc_options = RDOC_OPTS
79
81
  s.author = 'Robin Stocker'
80
82
  s.email = 'robinstocker@rubyforge.org'
@@ -95,9 +97,9 @@ if defined? Gem
95
97
 
96
98
  desc "Build mswin32 gem."
97
99
  task :gem_mswin32 => [:ext_mswin32] do
98
- Gem::Builder.new(spec_mswin32).build
99
- mkdir_p "pkg"
100
- mv "id3lib-ruby-#{PKG_VERSION}-mswin32.gem", "pkg/"
100
+ gemfile = Gem::Builder.new(spec_mswin32).build
101
+ mkpath "pkg"
102
+ mv gemfile, "pkg/"
101
103
  end
102
104
 
103
105
  end # defined? Gem
@@ -105,7 +107,7 @@ end # defined? Gem
105
107
 
106
108
  task :web => [:web_doc] do
107
109
  puts "# Now execute the following:"
108
- puts "scp web/* robinstocker@rubyforge.org:/var/www/gforge-projects/id3lib-ruby/"
110
+ puts "scp web/index.html web/logo.png web/red.css robinstocker@rubyforge.org:/var/www/gforge-projects/id3lib-ruby/"
109
111
  puts "scp -r web/doc robinstocker@rubyforge.org:/var/www/gforge-projects/id3lib-ruby/"
110
112
  end
111
113
 
@@ -115,10 +117,11 @@ Rake::RDocTask.new :web_doc do |rdoc|
115
117
  rdoc.title = 'id3lib-ruby'
116
118
  rdoc.options = RDOC_OPTS.clone
117
119
  rdoc.options << '--main' << 'ID3Lib::Tag'
118
- rdoc.rdoc_files.include('README', 'TODO', 'CHANGES')
120
+ rdoc.rdoc_files.include(FILES_DOC)
119
121
  rdoc.rdoc_files.include('lib/**/*.rb')
120
122
  end
121
123
 
124
+ desc "Generate syntax-highlighted HTML of usage.rb."
122
125
  task :usage_html do
123
126
  require 'syntax/convertors/html'
124
127
  convertor = Syntax::Convertors::HTML.for_syntax('ruby')
@@ -1,71 +1,84 @@
1
+ #!/usr/bin/ruby
2
+
1
3
  require 'enumerator'
4
+ require 'pathname'
5
+
6
+
7
+ id3lib_dir = Pathname.new(ARGV.first || '/home/robin/tmp/id3lib-3.8.3')
8
+
9
+ globals_file = File.read(id3lib_dir + 'include/id3/globals.h')
10
+ field_file = File.read(id3lib_dir + 'src/field.cpp')
11
+
12
+ def field_symbol(enum_name)
13
+ f = enum_name[/ID3FN_(.*)/, 1].downcase
14
+ if f == 'id'
15
+ :identifier
16
+ else
17
+ f.to_sym
18
+ end
19
+ end
20
+
21
+
22
+ field_groups = {}
23
+ allowed_fields = {}
2
24
 
3
- file = ARGV.first || '/usr/local/include/id3/globals.h'
25
+ field_file.scan(/ID3_FieldDef (\w+)[^\{]+\{(.+?)\};/m) do |group, body|
26
+ fields = []
27
+ body.scan(/\{\W+(\w+)/) do |field_name, _|
28
+ next if field_name == "ID3FN_NOFIELD"
29
+ fields << field_name
30
+ end
31
+ fields.uniq!
32
+ fields.map!{ |f| field_symbol(f) }
33
+ field_groups[group] = fields
34
+ end
35
+
36
+ field_file.scan(/ID3_FrameDef ID3_FrameDefs[^\{]+\{(.+?)\};/m) do |body, _|
37
+ body.each_line do |line|
38
+ values = line.split(/\s*,\s*/)
39
+ next unless values.size > 1
40
+ frame = values[2].delete('"')
41
+ group = values[5]
42
+ next if frame.empty?
43
+ allowed_fields[frame.to_sym] = field_groups[group]
44
+ end
45
+ end
4
46
 
5
- data = IO.read(file)
6
47
 
7
- fields = []
8
- frames = []
9
- genres = []
48
+ field_info = []
49
+ frame_info = []
50
+ genre_info = []
10
51
 
11
- data.scan(/ID3_ENUM\((\w+)\)\s+\{\s+(.+?)\s+\}/m) do |name, enum|
52
+ globals_file.scan(/ID3_ENUM\((\w+)\)\s+\{\s+(.+?)\s+\}/m) do |name, enum|
12
53
  case name
13
54
  when 'ID3_FieldID'
14
55
  id = 0
15
56
  enum.scan(/([^\s,]+)(?: = (\d+),|,)\s*\/\*\*< ([^*]+)\s+\*\//m) do |field, newid, description|
16
57
  id = newid.to_i if newid
17
- field.sub!('ID3FN_', '')
18
- field.downcase!
19
- fields << [id, field.to_sym, description]
58
+
59
+ field = field_symbol(field)
60
+ field_info << [id, field, description]
61
+
20
62
  id += 1
21
63
  end
22
64
  when 'ID3_FrameID'
23
65
  id = 0
24
66
  enum.scan(/\/\* (\S+) \*\/ [^\s,]+(?: = (\d+),|,)\s*\/\*\*< ([^*]+)\s+\*\//m) do |frame, newid, description|
25
67
  id = newid.to_i if newid
26
- if frame == '????'
27
- frame = :____
28
- else
29
- frame = frame.to_sym
30
- end
31
- possible_fields =
32
- case frame
33
- when :____ : []
34
- when :AENC : [:owner, :data]
35
- when :APIC : [:textenc, :mimetype, :picturetype, :description, :data]
36
- when :ASPI, :COMR, :EQUA, :ETCO, :LINK,
37
- :MCDI, :MLLT, :OWNE, :POSS, :RBUF,
38
- :RVA2, :RVAD, :RVRB, :SEEK
39
- [:data]
40
- when :COMM : [:textenc, :language, :description, :text]
41
- when :ENCR : [:owner, :id, :data]
42
- when :EQU2 : [:id, :text]
43
- when :GEOB : [:textenc, :mimetype, :filename, :description, :data]
44
- when :GRID : [:owner, :id, :data]
45
- when :IPLS : [:textenc, :text]
46
- when :PRIV : [:owner, :data]
47
- when :PCNT : [:counter]
48
- when :POPM : [:email, :rating, :counter]
49
- when :SIGN : [:id, :data]
50
- when :SYLT : [:textenc, :language, :timestampformat, :contenttype, :description, :data]
51
- when :SYTC : [:timestampformat, :data]
52
- when :UFID : [:owner, :data]
53
- when :USER : [:textenc, :language, :text]
54
- when :USLT : [:textenc, :language, :description, :text]
55
- when :WCOM, :WCOP, :WOAF, :WOAR, :WOAS, :WORS, :WPAY, :WPUB : [:text]
56
- when :WXXX : [:textenc, :description, :url]
57
- else [:textenc, :text]
58
- end
59
- frames << [id, frame, description, possible_fields]
68
+ frame = (frame == '????') ? :____ : frame.to_sym
69
+
70
+ fields = allowed_fields[frame] || []
71
+
72
+ frame_info << [id, frame, description, fields]
60
73
  id += 1
61
74
  end
62
75
  end
63
76
  end
64
77
 
65
- data.scan(/(ID3_v1_genre_description).+?\{(.+?)\}/m) do |name, list|
78
+ globals_file.scan(/(ID3_v1_genre_description).+?\{(.+?)\}/m) do |name, list|
66
79
  id = 0
67
- list.scan(/"(.+?)"/) do |genre|
68
- genres << genre.first
80
+ list.scan(/"([^"]+)"/) do |genre|
81
+ genre_info << genre.first
69
82
  id += 1
70
83
  end
71
84
  end
@@ -76,7 +89,7 @@ def indent level, text
76
89
  end
77
90
 
78
91
  indent 4, "Frames = ["
79
- frames.each do |f|
92
+ frame_info.each do |f|
80
93
  comment = case f[1]
81
94
  when :____ : "# Special frames"
82
95
  when :TALB : "# Text information frames"
@@ -89,25 +102,25 @@ end
89
102
  indent 4, "]"
90
103
 
91
104
  indent 4, "FramesByID = {"
92
- frames.each do |f|
105
+ frame_info.each do |f|
93
106
  indent 6, f[1].inspect + " => Frames[" + f[0].to_s + "],"
94
107
  end
95
108
  indent 4, "}"
96
109
 
97
110
  indent 4, "Fields = ["
98
- fields.each do |f|
111
+ field_info.each do |f|
99
112
  indent 6, f.inspect + ","
100
113
  end
101
114
  indent 4, "]"
102
115
 
103
116
  indent 4, "FieldsByID = {"
104
- fields.each do |f|
117
+ field_info.each do |f|
105
118
  indent 6, f[1].inspect.ljust(16) + " => Fields[" + f[0].to_s + "],"
106
119
  end
107
120
  indent 4, "}"
108
121
 
109
122
  indent 4, "Genres = ["
110
- genres.each_slice(4) do |gs|
123
+ genre_info.each_slice(4) do |gs|
111
124
  indent 6, "# Winamp extensions" if gs.first == "Folk"
112
125
  indent 6, gs.map{ |g| g.inspect }.join(", ") + ","
113
126
  end
@@ -54,17 +54,18 @@ public:
54
54
  %rename (find) Find;
55
55
  ID3_Frame * Find(ID3_FrameID name) const;
56
56
 
57
- %rename (iterator_new) CreateIterator;
57
+ %rename (create_iterator) CreateIterator;
58
+ %newobject CreateIterator;
58
59
  ID3_Tag::Iterator * CreateIterator();
60
+ };
59
61
 
60
- // Needed because SWIG does not support nested classes yet.
61
- %extend
62
- {
63
- ID3_Frame * iterator_next_frame(ID3_Tag::Iterator *iterator)
64
- {
65
- return iterator->GetNext();
66
- }
67
- }
62
+ %rename (Tag_Iterator) ID3_Tag::Iterator;
63
+ class ID3_Tag::Iterator
64
+ {
65
+ public:
66
+
67
+ %rename (get_next) GetNext;
68
+ virtual ID3_Frame * GetNext() = 0;
68
69
  };
69
70
 
70
71
 
@@ -1,6 +1,6 @@
1
1
  /* ----------------------------------------------------------------------------
2
2
  * This file was automatically generated by SWIG (http://www.swig.org).
3
- * Version 1.3.29
3
+ * Version 1.3.31
4
4
  *
5
5
  * This file is not intended to be easily readable and contains a number of
6
6
  * coding conventions designed to improve portability and efficiency. Do not make
@@ -119,7 +119,7 @@ private:
119
119
  #endif
120
120
 
121
121
  /* Deal with Microsoft's attempt at deprecating C standard runtime functions */
122
- #if !defined(SWIG_NO_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER)
122
+ #if !defined(SWIG_NO_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE)
123
123
  # define _CRT_SECURE_NO_DEPRECATE
124
124
  #endif
125
125
 
@@ -216,7 +216,7 @@ private:
216
216
  #endif
217
217
 
218
218
  /* Deal with Microsoft's attempt at deprecating C standard runtime functions */
219
- #if !defined(SWIG_NO_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER)
219
+ #if !defined(SWIG_NO_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE)
220
220
  # define _CRT_SECURE_NO_DEPRECATE
221
221
  #endif
222
222
 
@@ -229,7 +229,7 @@ private:
229
229
 
230
230
  /* This should only be incremented when either the layout of swig_type_info changes,
231
231
  or for whatever reason, the runtime changes incompatibly */
232
- #define SWIG_RUNTIME_VERSION "2"
232
+ #define SWIG_RUNTIME_VERSION "3"
233
233
 
234
234
  /* define SWIG_TYPE_TABLE_NAME as "SWIG_TYPE_TABLE" */
235
235
  #ifdef SWIG_TYPE_TABLE
@@ -828,6 +828,21 @@ SWIG_UnpackDataName(const char *c, void *ptr, size_t sz, const char *name) {
828
828
  #endif
829
829
  #endif
830
830
 
831
+ /* RSTRING_LEN, etc are new in Ruby 1.9, but ->ptr and ->len no longer work */
832
+ /* Define these for older versions so we can just write code the new way */
833
+ #ifndef RSTRING_LEN
834
+ # define RSTRING_LEN(x) RSTRING(x)->len
835
+ #endif
836
+ #ifndef RSTRING_PTR
837
+ # define RSTRING_PTR(x) RSTRING(x)->ptr
838
+ #endif
839
+ #ifndef RARRAY_LEN
840
+ # define RARRAY_LEN(x) RARRAY(x)->len
841
+ #endif
842
+ #ifndef RARRAY_PTR
843
+ # define RARRAY_PTR(x) RARRAY(x)->ptr
844
+ #endif
845
+
831
846
  /*
832
847
  * Need to be very careful about how these macros are defined, especially
833
848
  * when compiling C++ code or C code with an ANSI C compiler.
@@ -871,10 +886,10 @@ SWIG_UnpackDataName(const char *c, void *ptr, size_t sz, const char *name) {
871
886
  #define StringValue(s) RB_STRING_VALUE(s)
872
887
  #endif
873
888
  #ifndef StringValuePtr
874
- #define StringValuePtr(s) RSTRING(RB_STRING_VALUE(s))->ptr
889
+ #define StringValuePtr(s) RSTRING_PTR(RB_STRING_VALUE(s))
875
890
  #endif
876
891
  #ifndef StringValueLen
877
- #define StringValueLen(s) RSTRING(RB_STRING_VALUE(s))->len
892
+ #define StringValueLen(s) RSTRING_LEN(RB_STRING_VALUE(s))
878
893
  #endif
879
894
  #ifndef SafeStringValue
880
895
  #define SafeStringValue(v) do {\
@@ -1303,7 +1318,7 @@ SWIG_Ruby_NewPointerObj(void *ptr, swig_type_info *type, int flags)
1303
1318
  downcast methods. */
1304
1319
  if (obj != Qnil) {
1305
1320
  VALUE value = rb_iv_get(obj, "__swigtype__");
1306
- char* type_name = RSTRING(value)->ptr;
1321
+ char* type_name = RSTRING_PTR(value);
1307
1322
 
1308
1323
  if (strcmp(type->name, type_name) == 0) {
1309
1324
  return obj;
@@ -1544,7 +1559,8 @@ static swig_module_info swig_module = {swig_types, 6, 0, 0, 0, 0};
1544
1559
 
1545
1560
  static VALUE mAPI;
1546
1561
 
1547
- #define SWIGVERSION 0x010329
1562
+ #define SWIGVERSION 0x010331
1563
+ #define SWIG_VERSION SWIGVERSION
1548
1564
 
1549
1565
 
1550
1566
  #define SWIG_as_voidptr(a) const_cast< void * >(static_cast< const void * >(a))
@@ -1558,7 +1574,7 @@ static VALUE mAPI;
1558
1574
 
1559
1575
 
1560
1576
  SWIGINTERN swig_type_info*
1561
- SWIG_pchar_descriptor()
1577
+ SWIG_pchar_descriptor(void)
1562
1578
  {
1563
1579
  static int init = 0;
1564
1580
  static swig_type_info* info = 0;
@@ -1579,7 +1595,7 @@ SWIG_AsCharPtrAndSize(VALUE obj, char** cptr, size_t* psize, int *alloc)
1579
1595
 
1580
1596
  char *cstr = STR2CSTR(obj);
1581
1597
 
1582
- size_t size = RSTRING(obj)->len + 1;
1598
+ size_t size = RSTRING_LEN(obj) + 1;
1583
1599
  if (cptr) {
1584
1600
  if (alloc) {
1585
1601
  if (*alloc == SWIG_NEWOBJ) {
@@ -1794,9 +1810,6 @@ SWIG_AsVal_bool (VALUE obj, bool *val)
1794
1810
  return SWIG_TypeError;
1795
1811
  }
1796
1812
 
1797
- SWIGINTERN ID3_Frame *ID3_Tag_iterator_next_frame(ID3_Tag *self,ID3_Tag::Iterator *iterator){
1798
- return iterator->GetNext();
1799
- }
1800
1813
 
1801
1814
  SWIGINTERNINLINE VALUE
1802
1815
  SWIG_From_int (int value)
@@ -1863,7 +1876,7 @@ _wrap_new_Tag__SWIG_0(int argc, VALUE *argv, VALUE self) {
1863
1876
  if (!SWIG_IsOK(res1)) {
1864
1877
  SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ID3_Tag" "', argument " "1"" of type '" "char const *""'");
1865
1878
  }
1866
- arg1 = buf1;
1879
+ arg1 = reinterpret_cast< char * >(buf1);
1867
1880
  result = (ID3_Tag *)new ID3_Tag((char const *)arg1);DATA_PTR(self) = result;
1868
1881
 
1869
1882
  if (alloc1 == SWIG_NEWOBJ) delete[] buf1;
@@ -1998,7 +2011,7 @@ _wrap_Tag_link__SWIG_0(int argc, VALUE *argv, VALUE self) {
1998
2011
  if (!SWIG_IsOK(res2)) {
1999
2012
  SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Link" "', argument " "2"" of type '" "char const *""'");
2000
2013
  }
2001
- arg2 = buf2;
2014
+ arg2 = reinterpret_cast< char * >(buf2);
2002
2015
  ecode3 = SWIG_AsVal_unsigned_SS_int(argv[1], &val3);
2003
2016
  if (!SWIG_IsOK(ecode3)) {
2004
2017
  SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "Link" "', argument " "3"" of type '" "flags_t""'");
@@ -2038,7 +2051,7 @@ _wrap_Tag_link__SWIG_1(int argc, VALUE *argv, VALUE self) {
2038
2051
  if (!SWIG_IsOK(res2)) {
2039
2052
  SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Link" "', argument " "2"" of type '" "char const *""'");
2040
2053
  }
2041
- arg2 = buf2;
2054
+ arg2 = reinterpret_cast< char * >(buf2);
2042
2055
  result = (arg1)->Link((char const *)arg2);
2043
2056
  vresult = SWIG_From_size_t(static_cast< size_t >(result));
2044
2057
  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -2394,7 +2407,7 @@ _wrap_Tag_get_filename(int argc, VALUE *argv, VALUE self) {
2394
2407
  }
2395
2408
  arg1 = reinterpret_cast< ID3_Tag * >(argp1);
2396
2409
  result = (char *)((ID3_Tag const *)arg1)->GetFileName();
2397
- vresult = SWIG_FromCharPtr(result);
2410
+ vresult = SWIG_FromCharPtr((const char *)result);
2398
2411
  return vresult;
2399
2412
  fail:
2400
2413
  return Qnil;
@@ -2490,7 +2503,7 @@ fail:
2490
2503
 
2491
2504
 
2492
2505
  SWIGINTERN VALUE
2493
- _wrap_Tag_iterator_new(int argc, VALUE *argv, VALUE self) {
2506
+ _wrap_Tag_create_iterator(int argc, VALUE *argv, VALUE self) {
2494
2507
  ID3_Tag *arg1 = (ID3_Tag *) 0 ;
2495
2508
  ID3_Tag::Iterator *result = 0 ;
2496
2509
  void *argp1 = 0 ;
@@ -2506,38 +2519,32 @@ _wrap_Tag_iterator_new(int argc, VALUE *argv, VALUE self) {
2506
2519
  }
2507
2520
  arg1 = reinterpret_cast< ID3_Tag * >(argp1);
2508
2521
  result = (ID3_Tag::Iterator *)(arg1)->CreateIterator();
2509
- vresult = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_ID3_Tag__Iterator, 0 | 0 );
2522
+ vresult = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_ID3_Tag__Iterator, SWIG_POINTER_OWN | 0 );
2510
2523
  return vresult;
2511
2524
  fail:
2512
2525
  return Qnil;
2513
2526
  }
2514
2527
 
2515
2528
 
2529
+ swig_class cTag_Iterator;
2530
+
2516
2531
  SWIGINTERN VALUE
2517
- _wrap_Tag_iterator_next_frame(int argc, VALUE *argv, VALUE self) {
2518
- ID3_Tag *arg1 = (ID3_Tag *) 0 ;
2519
- ID3_Tag::Iterator *arg2 = (ID3_Tag::Iterator *) 0 ;
2532
+ _wrap_Tag_Iterator_get_next(int argc, VALUE *argv, VALUE self) {
2533
+ ID3_Tag::Iterator *arg1 = (ID3_Tag::Iterator *) 0 ;
2520
2534
  ID3_Frame *result = 0 ;
2521
2535
  void *argp1 = 0 ;
2522
2536
  int res1 = 0 ;
2523
- void *argp2 = 0 ;
2524
- int res2 = 0 ;
2525
2537
  VALUE vresult = Qnil;
2526
2538
 
2527
- if ((argc < 1) || (argc > 1)) {
2528
- rb_raise(rb_eArgError, "wrong # of arguments(%d for 1)",argc); SWIG_fail;
2539
+ if ((argc < 0) || (argc > 0)) {
2540
+ rb_raise(rb_eArgError, "wrong # of arguments(%d for 0)",argc); SWIG_fail;
2529
2541
  }
2530
- res1 = SWIG_ConvertPtr(self, &argp1,SWIGTYPE_p_ID3_Tag, 0 | 0 );
2542
+ res1 = SWIG_ConvertPtr(self, &argp1,SWIGTYPE_p_ID3_Tag__Iterator, 0 | 0 );
2531
2543
  if (!SWIG_IsOK(res1)) {
2532
- SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "iterator_next_frame" "', argument " "1"" of type '" "ID3_Tag *""'");
2544
+ SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "GetNext" "', argument " "1"" of type '" "ID3_Tag::Iterator *""'");
2533
2545
  }
2534
- arg1 = reinterpret_cast< ID3_Tag * >(argp1);
2535
- res2 = SWIG_ConvertPtr(argv[0], &argp2,SWIGTYPE_p_ID3_Tag__Iterator, 0 | 0 );
2536
- if (!SWIG_IsOK(res2)) {
2537
- SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "iterator_next_frame" "', argument " "2"" of type '" "ID3_Tag::Iterator *""'");
2538
- }
2539
- arg2 = reinterpret_cast< ID3_Tag::Iterator * >(argp2);
2540
- result = (ID3_Frame *)ID3_Tag_iterator_next_frame(arg1,arg2);
2546
+ arg1 = reinterpret_cast< ID3_Tag::Iterator * >(argp1);
2547
+ result = (ID3_Frame *)(arg1)->GetNext();
2541
2548
  vresult = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_ID3_Frame, 0 | 0 );
2542
2549
  return vresult;
2543
2550
  fail:
@@ -2545,6 +2552,11 @@ fail:
2545
2552
  }
2546
2553
 
2547
2554
 
2555
+ SWIGINTERN void
2556
+ free_ID3_Tag_Iterator(ID3_Tag::Iterator *arg1) {
2557
+ delete arg1;
2558
+ }
2559
+
2548
2560
  swig_class cFrame;
2549
2561
 
2550
2562
  SWIGINTERN VALUE
@@ -2784,7 +2796,7 @@ _wrap_Field_get_ascii(int argc, VALUE *argv, VALUE self) {
2784
2796
  }
2785
2797
  arg1 = reinterpret_cast< ID3_Field * >(argp1);
2786
2798
  result = (char *)((ID3_Field const *)arg1)->GetRawText();
2787
- vresult = SWIG_FromCharPtr(result);
2799
+ vresult = SWIG_FromCharPtr((const char *)result);
2788
2800
  return vresult;
2789
2801
  fail:
2790
2802
  return Qnil;
@@ -2924,7 +2936,7 @@ _wrap_Field_set_ascii(int argc, VALUE *argv, VALUE self) {
2924
2936
  if (!SWIG_IsOK(res2)) {
2925
2937
  SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Set" "', argument " "2"" of type '" "char const *""'");
2926
2938
  }
2927
- arg2 = buf2;
2939
+ arg2 = reinterpret_cast< char * >(buf2);
2928
2940
  result = (arg1)->Set((char const *)arg2);
2929
2941
  vresult = SWIG_From_size_t(static_cast< size_t >(result));
2930
2942
  if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
@@ -3039,7 +3051,7 @@ static swig_cast_info *swig_cast_initial[] = {
3039
3051
  * structures together.
3040
3052
  *
3041
3053
  * The generated swig_type_info structures are assigned staticly to an initial
3042
- * array. We just loop though that array, and handle each type individually.
3054
+ * array. We just loop through that array, and handle each type individually.
3043
3055
  * First we lookup if this type has been already loaded, and if so, use the
3044
3056
  * loaded structure instead of the generated one. Then we have to fill in the
3045
3057
  * cast linked list. The cast data is initially stored in something like a
@@ -3077,32 +3089,49 @@ extern "C" {
3077
3089
  #define SWIGRUNTIME_DEBUG
3078
3090
  #endif
3079
3091
 
3092
+
3080
3093
  SWIGRUNTIME void
3081
3094
  SWIG_InitializeModule(void *clientdata) {
3082
3095
  size_t i;
3083
- swig_module_info *module_head;
3084
- static int init_run = 0;
3096
+ swig_module_info *module_head, *iter;
3097
+ int found;
3085
3098
 
3086
3099
  clientdata = clientdata;
3087
3100
 
3088
- if (init_run) return;
3089
- init_run = 1;
3090
-
3091
- /* Initialize the swig_module */
3092
- swig_module.type_initial = swig_type_initial;
3093
- swig_module.cast_initial = swig_cast_initial;
3101
+ /* check to see if the circular list has been setup, if not, set it up */
3102
+ if (swig_module.next==0) {
3103
+ /* Initialize the swig_module */
3104
+ swig_module.type_initial = swig_type_initial;
3105
+ swig_module.cast_initial = swig_cast_initial;
3106
+ swig_module.next = &swig_module;
3107
+ }
3094
3108
 
3095
3109
  /* Try and load any already created modules */
3096
3110
  module_head = SWIG_GetModule(clientdata);
3097
- if (module_head) {
3111
+ if (!module_head) {
3112
+ /* This is the first module loaded for this interpreter */
3113
+ /* so set the swig module into the interpreter */
3114
+ SWIG_SetModule(clientdata, &swig_module);
3115
+ module_head = &swig_module;
3116
+ } else {
3117
+ /* the interpreter has loaded a SWIG module, but has it loaded this one? */
3118
+ found=0;
3119
+ iter=module_head;
3120
+ do {
3121
+ if (iter==&swig_module) {
3122
+ found=1;
3123
+ break;
3124
+ }
3125
+ iter=iter->next;
3126
+ } while (iter!= module_head);
3127
+
3128
+ /* if the is found in the list, then all is done and we may leave */
3129
+ if (found) return;
3130
+ /* otherwise we must add out module into the list */
3098
3131
  swig_module.next = module_head->next;
3099
3132
  module_head->next = &swig_module;
3100
- } else {
3101
- /* This is the first module loaded */
3102
- swig_module.next = &swig_module;
3103
- SWIG_SetModule(clientdata, &swig_module);
3104
3133
  }
3105
-
3134
+
3106
3135
  /* Now work on filling in swig_module.types */
3107
3136
  #ifdef SWIGRUNTIME_DEBUG
3108
3137
  printf("SWIG_InitializeModule: size %d\n", swig_module.size);
@@ -3269,12 +3298,19 @@ SWIGEXPORT void Init_id3lib_api(void) {
3269
3298
  rb_define_method(cTag.klass, "set_padding", VALUEFUNC(_wrap_Tag_set_padding), -1);
3270
3299
  rb_define_method(cTag.klass, "size", VALUEFUNC(_wrap_Tag_size), -1);
3271
3300
  rb_define_method(cTag.klass, "find", VALUEFUNC(_wrap_Tag_find), -1);
3272
- rb_define_method(cTag.klass, "iterator_new", VALUEFUNC(_wrap_Tag_iterator_new), -1);
3273
- rb_define_method(cTag.klass, "iterator_next_frame", VALUEFUNC(_wrap_Tag_iterator_next_frame), -1);
3301
+ rb_define_method(cTag.klass, "create_iterator", VALUEFUNC(_wrap_Tag_create_iterator), -1);
3274
3302
  cTag.mark = 0;
3275
3303
  cTag.destroy = (void (*)(void *)) free_ID3_Tag;
3276
3304
  cTag.trackObjects = 0;
3277
3305
 
3306
+ cTag_Iterator.klass = rb_define_class_under(mAPI, "Tag_Iterator", rb_cObject);
3307
+ SWIG_TypeClientData(SWIGTYPE_p_ID3_Tag__Iterator, (void *) &cTag_Iterator);
3308
+ rb_undef_alloc_func(cTag_Iterator.klass);
3309
+ rb_define_method(cTag_Iterator.klass, "get_next", VALUEFUNC(_wrap_Tag_Iterator_get_next), -1);
3310
+ cTag_Iterator.mark = 0;
3311
+ cTag_Iterator.destroy = (void (*)(void *)) free_ID3_Tag_Iterator;
3312
+ cTag_Iterator.trackObjects = 0;
3313
+
3278
3314
  cFrame.klass = rb_define_class_under(mAPI, "Frame", rb_cObject);
3279
3315
  SWIG_TypeClientData(SWIGTYPE_p_ID3_Frame, (void *) &cFrame);
3280
3316
  rb_define_alloc_func(cFrame.klass, _wrap_Frame_allocate);
@@ -9,6 +9,7 @@ require 'id3lib/accessors'
9
9
  # Have a look at ID3Lib::Tag for an introduction on how to use this library.
10
10
  #
11
11
  module ID3Lib
12
+ VERSION = '0.5.0'
12
13
 
13
14
  # ID3 version 1. All V constants can be used with the methods
14
15
  # new, update! or strip! of ID3Lib::Tag.
@@ -33,7 +34,7 @@ module ID3Lib
33
34
  #
34
35
  # === Example of use
35
36
  #
36
- # tag = ID3Lib::Tag.read('shy_boy.mp3')
37
+ # tag = ID3Lib::Tag.new('shy_boy.mp3')
37
38
  #
38
39
  # # Remove comments
39
40
  # tag.delete_if{ |frame| frame[:id] == :COMM }
@@ -314,8 +315,8 @@ module ID3Lib
314
315
  private
315
316
 
316
317
  def read_frames
317
- iterator = @tag.iterator_new
318
- while libframe = @tag.iterator_next_frame(iterator)
318
+ iterator = @tag.create_iterator
319
+ while libframe = iterator.get_next
319
320
  self << Frame.read(libframe)
320
321
  end
321
322
  end
@@ -332,6 +333,11 @@ module ID3Lib
332
333
 
333
334
  info[FIELDS].each do |field_id|
334
335
  libfield = field(libframe, field_id)
336
+ unless libfield
337
+ warn "id3lib-ruby: Invalid field #{field_id.inspect} in " \
338
+ "#{frame[:id].inspect}, please report this as a bug."
339
+ next
340
+ end
335
341
  frame[field_id] =
336
342
  case Info::FieldType[libfield.get_type]
337
343
  when :integer
@@ -363,6 +369,7 @@ module ID3Lib
363
369
  end
364
370
 
365
371
  libfield = field(libframe, field_id)
372
+ next unless libfield
366
373
  case Info::FieldType[libfield.get_type]
367
374
  when :integer
368
375
  libfield.set_integer(value)
@@ -57,25 +57,29 @@ module ID3Lib
57
57
 
58
58
  #
59
59
  # Please note that these frames are not fully supported by id3lib:
60
- # AENC, ASPI, COMR, EQUA, ETCO, LINK, MLLT,
61
- # OWNE, POSS, RBUF, RVA2, RVAD, RVRB, SEEK
60
+ # AENC, COMR, EQUA, ETCO, MCDI, MLLT,
61
+ # OWNE, POSS, RBUF, RVAD, RVRB, SYTC
62
+ # And these are not supported at all (segfault on usage):
63
+ # ASPI, EQU2, RVA2, SEEK, SIGN, TDEN,
64
+ # TDOR, TDRC, TDRL, TDTG, TIPL, TMCL,
65
+ # TMOO, TPRO, TSOA, TSOP, TSOT, TSST
62
66
  #
63
67
  Frames = [
64
68
  # Special frames
65
69
  [0, :____, "No known frame", []],
66
- [1, :AENC, "Audio encryption", [:owner, :data]],
67
- [2, :APIC, "Attached picture", [:textenc, :mimetype, :picturetype, :description, :data]],
68
- [3, :ASPI, "Audio seek point index", [:data]],
70
+ [1, :AENC, "Audio encryption", [:data]],
71
+ [2, :APIC, "Attached picture", [:textenc, :imageformat, :mimetype, :picturetype, :description, :data]],
72
+ [3, :ASPI, "Audio seek point index", []],
69
73
  [4, :COMM, "Comments", [:textenc, :language, :description, :text]],
70
74
  [5, :COMR, "Commercial frame", [:data]],
71
- [6, :ENCR, "Encryption method registration", [:owner, :id, :data]],
72
- [7, :EQU2, "Equalisation (2)", [:id, :text]],
75
+ [6, :ENCR, "Encryption method registration", [:owner, :identifier, :data]],
76
+ [7, :EQU2, "Equalisation (2)", []],
73
77
  [8, :EQUA, "Equalization", [:data]],
74
78
  [9, :ETCO, "Event timing codes", [:data]],
75
79
  [10, :GEOB, "General encapsulated object", [:textenc, :mimetype, :filename, :description, :data]],
76
- [11, :GRID, "Group identification registration", [:owner, :id, :data]],
80
+ [11, :GRID, "Group identification registration", [:owner, :identifier, :data]],
77
81
  [12, :IPLS, "Involved people list", [:textenc, :text]],
78
- [13, :LINK, "Linked information", [:data]],
82
+ [13, :LINK, "Linked information", [:identifier, :url, :text]],
79
83
  [14, :MCDI, "Music CD identifier", [:data]],
80
84
  [15, :MLLT, "MPEG location lookup table", [:data]],
81
85
  [16, :OWNE, "Ownership frame", [:data]],
@@ -84,13 +88,13 @@ module ID3Lib
84
88
  [19, :POPM, "Popularimeter", [:email, :rating, :counter]],
85
89
  [20, :POSS, "Position synchronisation frame", [:data]],
86
90
  [21, :RBUF, "Recommended buffer size", [:data]],
87
- [22, :RVA2, "Relative volume adjustment (2)", [:data]],
91
+ [22, :RVA2, "Relative volume adjustment (2)", []],
88
92
  [23, :RVAD, "Relative volume adjustment", [:data]],
89
93
  [24, :RVRB, "Reverb", [:data]],
90
- [25, :SEEK, "Seek frame", [:data]],
91
- [26, :SIGN, "Signature frame", [:id, :data]],
94
+ [25, :SEEK, "Seek frame", []],
95
+ [26, :SIGN, "Signature frame", []],
92
96
  [27, :SYLT, "Synchronized lyric/text", [:textenc, :language, :timestampformat, :contenttype, :description, :data]],
93
- [28, :SYTC, "Synchronized tempo codes", [:timestampformat, :data]],
97
+ [28, :SYTC, "Synchronized tempo codes", [:data]],
94
98
  # Text information frames
95
99
  [29, :TALB, "Album/Movie/Show title", [:textenc, :text]],
96
100
  [30, :TBPM, "BPM (beats per minute)", [:textenc, :text]],
@@ -98,13 +102,13 @@ module ID3Lib
98
102
  [32, :TCON, "Content type", [:textenc, :text]],
99
103
  [33, :TCOP, "Copyright message", [:textenc, :text]],
100
104
  [34, :TDAT, "Date", [:textenc, :text]],
101
- [35, :TDEN, "Encoding time", [:textenc, :text]],
105
+ [35, :TDEN, "Encoding time", []],
102
106
  [36, :TDLY, "Playlist delay", [:textenc, :text]],
103
- [37, :TDOR, "Original release time", [:textenc, :text]],
104
- [38, :TDRC, "Recording time", [:textenc, :text]],
105
- [39, :TDRL, "Release time", [:textenc, :text]],
106
- [40, :TDTG, "Tagging time", [:textenc, :text]],
107
- [41, :TIPL, "Involved people list", [:textenc, :text]],
107
+ [37, :TDOR, "Original release time", []],
108
+ [38, :TDRC, "Recording time", []],
109
+ [39, :TDRL, "Release time", []],
110
+ [40, :TDTG, "Tagging time", []],
111
+ [41, :TIPL, "Involved people list", []],
108
112
  [42, :TENC, "Encoded by", [:textenc, :text]],
109
113
  [43, :TEXT, "Lyricist/Text writer", [:textenc, :text]],
110
114
  [44, :TFLT, "File type", [:textenc, :text]],
@@ -115,9 +119,9 @@ module ID3Lib
115
119
  [49, :TKEY, "Initial key", [:textenc, :text]],
116
120
  [50, :TLAN, "Language(s)", [:textenc, :text]],
117
121
  [51, :TLEN, "Length", [:textenc, :text]],
118
- [52, :TMCL, "Musician credits list", [:textenc, :text]],
122
+ [52, :TMCL, "Musician credits list", []],
119
123
  [53, :TMED, "Media type", [:textenc, :text]],
120
- [54, :TMOO, "Mood", [:textenc, :text]],
124
+ [54, :TMOO, "Mood", []],
121
125
  [55, :TOAL, "Original album/movie/show title", [:textenc, :text]],
122
126
  [56, :TOFN, "Original filename", [:textenc, :text]],
123
127
  [57, :TOLY, "Original lyricist(s)/text writer(s)", [:textenc, :text]],
@@ -129,19 +133,19 @@ module ID3Lib
129
133
  [63, :TPE3, "Conductor/performer refinement", [:textenc, :text]],
130
134
  [64, :TPE4, "Interpreted, remixed, or otherwise modified by", [:textenc, :text]],
131
135
  [65, :TPOS, "Part of a set", [:textenc, :text]],
132
- [66, :TPRO, "Produced notice", [:textenc, :text]],
136
+ [66, :TPRO, "Produced notice", []],
133
137
  [67, :TPUB, "Publisher", [:textenc, :text]],
134
138
  [68, :TRCK, "Track number/Position in set", [:textenc, :text]],
135
139
  [69, :TRDA, "Recording dates", [:textenc, :text]],
136
140
  [70, :TRSN, "Internet radio station name", [:textenc, :text]],
137
141
  [71, :TRSO, "Internet radio station owner", [:textenc, :text]],
138
142
  [72, :TSIZ, "Size", [:textenc, :text]],
139
- [73, :TSOA, "Album sort order", [:textenc, :text]],
140
- [74, :TSOP, "Performer sort order", [:textenc, :text]],
141
- [75, :TSOT, "Title sort order", [:textenc, :text]],
143
+ [73, :TSOA, "Album sort order", []],
144
+ [74, :TSOP, "Performer sort order", []],
145
+ [75, :TSOT, "Title sort order", []],
142
146
  [76, :TSRC, "ISRC (international standard recording code)", [:textenc, :text]],
143
147
  [77, :TSSE, "Software/Hardware and settings used for encoding", [:textenc, :text]],
144
- [78, :TSST, "Set subtitle", [:textenc, :text]],
148
+ [78, :TSST, "Set subtitle", []],
145
149
  [79, :TXXX, "User defined text information", [:textenc, :description, :text]],
146
150
  [80, :TYER, "Year", [:textenc, :text]],
147
151
  # Special frames again
@@ -149,15 +153,15 @@ module ID3Lib
149
153
  [82, :USER, "Terms of use", [:textenc, :language, :text]],
150
154
  [83, :USLT, "Unsynchronized lyric/text transcription", [:textenc, :language, :description, :text]],
151
155
  # URL link frames
152
- [84, :WCOM, "Commercial information", [:text]],
153
- [85, :WCOP, "Copyright/Legal infromation", [:text]],
154
- [86, :WOAF, "Official audio file webpage", [:text]],
155
- [87, :WOAR, "Official artist/performer webpage", [:text]],
156
- [88, :WOAS, "Official audio source webpage", [:text]],
157
- [89, :WORS, "Official internet radio station homepage", [:text]],
158
- [90, :WPAY, "Payment", [:text]],
159
- [91, :WPUB, "Official publisher webpage", [:text]],
160
- [92, :WXXX, "User defined URL link", [:textenc, :description, :url]],
156
+ [84, :WCOM, "Commercial information", [:url]],
157
+ [85, :WCOP, "Copyright/Legal infromation", [:url]],
158
+ [86, :WOAF, "Official audio file webpage", [:url]],
159
+ [87, :WOAR, "Official artist/performer webpage", [:url]],
160
+ [88, :WOAS, "Official audio source webpage", [:url]],
161
+ [89, :WORS, "Official internet radio station homepage", [:url]],
162
+ [90, :WPAY, "Payment", [:url]],
163
+ [91, :WPUB, "Official publisher webpage", [:url]],
164
+ [92, :WXXX, "User defined URL link", [:textenc, :description, :url]]
161
165
  ]
162
166
 
163
167
  FramesByID = {
@@ -272,7 +276,7 @@ module ID3Lib
272
276
  [12, :imageformat, "Image format field"],
273
277
  [13, :mimetype, "Mimetype field"],
274
278
  [14, :counter, "Counter field"],
275
- [15, :id, "Identifier/Symbol field"],
279
+ [15, :identifier, "Identifier/Symbol field"],
276
280
  [16, :volumeadj, "Volume adjustment field"],
277
281
  [17, :numbits, "Number of bits field"],
278
282
  [18, :volchgright, "Volume chage on the right channel"],
@@ -299,7 +303,7 @@ module ID3Lib
299
303
  :imageformat => Fields[12],
300
304
  :mimetype => Fields[13],
301
305
  :counter => Fields[14],
302
- :id => Fields[15],
306
+ :identifier => Fields[15],
303
307
  :volumeadj => Fields[16],
304
308
  :numbits => Fields[17],
305
309
  :volchgright => Fields[18],
@@ -119,6 +119,7 @@ class TestWriting < Test::Unit::TestCase
119
119
  pic = {
120
120
  :id => :APIC,
121
121
  :mimetype => 'image/jpeg',
122
+ :imageformat => '',
122
123
  :picturetype => 3,
123
124
  :description => 'A pretty picture.',
124
125
  :textenc => 0,
metadata CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.0
3
3
  specification_version: 1
4
4
  name: id3lib-ruby
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.4.1
7
- date: 2006-08-24 00:00:00 +02:00
6
+ version: 0.5.0
7
+ date: 2006-12-16 00:00:00 +01:00
8
8
  summary: id3lib-ruby provides a Ruby interface to the id3lib C++ library for easily editing ID3 tags (v1 and v2) like with pyid3lib.
9
9
  require_paths:
10
10
  - lib
@@ -47,8 +47,9 @@ files:
47
47
  - ext/id3lib_api.i
48
48
  - ext/Rakefile
49
49
  - README
50
- - CHANGES
50
+ - INSTALL
51
51
  - TODO
52
+ - CHANGES
52
53
  test_files:
53
54
  - test/test_unicode.rb
54
55
  - test/test_writing.rb
@@ -60,8 +61,9 @@ rdoc_options:
60
61
  - README
61
62
  extra_rdoc_files:
62
63
  - README
63
- - CHANGES
64
+ - INSTALL
64
65
  - TODO
66
+ - CHANGES
65
67
  executables: []
66
68
 
67
69
  extensions: