id3lib-ruby 0.4.1 → 0.5.0

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