ruby-cafinfo 0.1

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG ADDED
@@ -0,0 +1,3 @@
1
+ === 0.1 / 2009-03-12
2
+
3
+ * initial release: contains basic support for audio_description, data, free and magick cookie chunks.
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ Copyright (c) 2009 Oleguer Huguet Ibars
2
+
3
+ The MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README ADDED
@@ -0,0 +1,76 @@
1
+ ruby-cafinfo
2
+
3
+ by Oleguer Huguet Ibars
4
+ * http://rubyforge.org/projects/ruby-cafinfo
5
+ * git repository: git://rubyforge.org/ruby-cafinfo.git
6
+
7
+ == DESCRIPTION:
8
+
9
+ A ruby library to retrieve information of CAF (Core Audio Format) files, heavily inspired by the excellent ruby-mp3info[http://ruby-mp3info.rubyforge.org/].
10
+
11
+ From the CAF format specification:
12
+
13
+ "Apple's Core Audio Format (CAF) is a file format for storing and transporting digital
14
+ audio data. It simplifies the management and manipulation of many types of audio data
15
+ without the file-size limitations of other audio file formats."
16
+
17
+ Specs for CAF format can be found here[http://developer.apple.com/DOCUMENTATION/MusicAudio/Reference/CAFSpec/CAF_intro/CAF_intro.html].
18
+
19
+ == FEATURES:
20
+
21
+ * written in pure ruby
22
+ * read low-level informations like bitrate, length, samplerate, etc...
23
+ * only some chunk types are recognized (Audio Description, Data, Free, Magick Cookie)
24
+
25
+ == SYNOPSIS:
26
+
27
+ Using as a lib is easy:
28
+
29
+ require "cafinfo"
30
+ # read and display info
31
+ CafInfo.open("myfile.caf") do |cafinfo|
32
+ puts cafinfo
33
+ end
34
+
35
+ # read and display some attributes
36
+ CafInfo.open("myfile.caf") do |caf|
37
+ puts caf.length
38
+ puts caf.samplerate
39
+ puts caf.format
40
+ end
41
+
42
+ # extract payload audio data from a (small) CAF and write to another file
43
+ audio_pos, audio_length = CafInfo.open("myfile.caf") { |caf| caf.audio_content }
44
+ File.open("myfile.caf", "rb") do |caf_file|
45
+ File.open("myaudio.data", "wb") do |f|
46
+ caf_file.seek(audio_pos)
47
+ data = caf_file.read(audio_length)
48
+ f.write(data)
49
+ end
50
+ end
51
+
52
+ # extract payload audio data from an arbitrarily large CAF and write
53
+ # to another file, considering that data chunk may not be at the end
54
+ # of caf file
55
+ audio_pos, audio_length = CafInfo.open("myfile.caf") { |caf| caf.audio_content }
56
+ File.open("myfile.caf", "rb") do |caf_file|
57
+ File.open("myaudio-buffered.data", "wb") do |f|
58
+ caf_file.seek(audio_pos)
59
+ while buffer = caf_file.read([4096, audio_length].min) and buffer.size > 0
60
+ f.write(buffer)
61
+ audio_length -= buffer.size
62
+ end
63
+ end
64
+ end
65
+
66
+ == INSTALL:
67
+
68
+ # gem install ruby-cafinfo
69
+
70
+ == LICENSE:
71
+
72
+ MIT license
73
+
74
+ == TODO:
75
+
76
+ * support for other chunk types
data/Rakefile ADDED
@@ -0,0 +1,43 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'rake/clean'
4
+ require 'rake/gempackagetask'
5
+ require 'rake/rdoctask'
6
+ require 'rake/testtask'
7
+
8
+ spec = Gem::Specification.new do |s|
9
+ s.name = 'ruby-cafinfo'
10
+ s.version = '0.1'
11
+ s.has_rdoc = true
12
+ s.extra_rdoc_files = ['README', 'LICENSE', 'CHANGELOG']
13
+ s.summary = 'ruby-cafinfo is a ruby library to retrieve low level informations on CAF files'
14
+ s.description = s.summary
15
+ s.author = 'Oleguer Huguet Ibars'
16
+ s.email = 'olegueret@rubyforge.org'
17
+ # s.executables = ['your_executable_here']
18
+ s.files = %w(LICENSE README Rakefile) + Dir.glob("{bin,lib,spec}/**/*")
19
+ s.require_path = "lib"
20
+ #s.bindir = "bin"
21
+ s.add_dependency 'float-formats', '>=0.1.1'
22
+ s.rubyforge_project = 'ruby-cafinfo'
23
+ s.homepage = 'http://ruby-cafinfo.rubyforge.org'
24
+ end
25
+
26
+ Rake::GemPackageTask.new(spec) do |p|
27
+ p.gem_spec = spec
28
+ p.need_tar = true
29
+ p.need_zip = true
30
+ end
31
+
32
+ Rake::RDocTask.new do |rdoc|
33
+ files =['README', 'LICENSE', 'CHANGELOG', 'lib/**/*.rb']
34
+ rdoc.rdoc_files.add(files)
35
+ rdoc.main = "README" # page to start on
36
+ rdoc.title = "ruby-cafinfo Docs"
37
+ rdoc.rdoc_dir = 'doc/rdoc' # rdoc output folder
38
+ rdoc.options << '--line-numbers'
39
+ end
40
+
41
+ Rake::TestTask.new do |t|
42
+ t.test_files = FileList['test/**/*.rb']
43
+ end
data/lib/caf/chunk.rb ADDED
@@ -0,0 +1,15 @@
1
+ require 'caf/chunk/base'
2
+
3
+ module Caf
4
+ module Chunk
5
+ def self.available_chunk_types
6
+ @available_chunk_types ||= {}
7
+ end
8
+
9
+ def self.build(chunk_header)
10
+ klass = available_chunk_types[(chunk_header[:chunk_type] || "").downcase]
11
+ klass = Base if klass.nil?
12
+ klass.new(chunk_header)
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,57 @@
1
+ require 'caf/chunk/base'
2
+ require 'caf/chunk/helper'
3
+ require 'caf/errors'
4
+
5
+ module Caf::Chunk
6
+ include Helper
7
+
8
+ class AudioDescription < Base
9
+
10
+ implements 'desc'
11
+
12
+ attr_accessor :samplerate, :format_id, :format_flags, :bytes_per_packet,
13
+ :frames_per_packet, :channels_per_frame, :bits_per_channel
14
+
15
+ def initialize(chunk_header)
16
+ super chunk_header
17
+ end
18
+
19
+ def to_s
20
+ "#{chunk_type} (audio description chunk):\n"+
21
+ " -samplerate: #{samplerate}\n"+
22
+ " -format ID: #{format_id}\n"+
23
+ " -format flags: #{format_flags}\n"+
24
+ " -bytes per packet: #{bytes_per_packet}\n"+
25
+ " -frames per packet: #{frames_per_packet}\n"+
26
+ " -channels per frame: #{channels_per_frame}\n"+
27
+ " -bits per channel: #{bits_per_channel}\n"
28
+ end
29
+
30
+ def validate
31
+ raise(Caf::Error, "invalid audio description chunk: sample rate cannot be 0") if samplerate == 0
32
+ raise(Caf::Error, "invalid audio description chunk: format ID cannot be 0") if format_id == 0
33
+ raise(Caf::Error, "invalid audio description chunk: channels per frame cannot be 0") if channels_per_frame == 0
34
+ end
35
+
36
+ def fields_size
37
+ 32
38
+ end
39
+
40
+ def read_data(file)
41
+ data = file.read(self.fields_size)
42
+ raise(Caf::Error, "chunk data too short: #{self}") if file.eof?
43
+
44
+ @samplerate = Helper.read_double(data)
45
+ @format_id = Helper.read_chars(4, data, 8)
46
+ @format_flags = Helper.read_int(data, 12)
47
+ @bytes_per_packet = Helper.read_int(data, 16)
48
+ @frames_per_packet = Helper.read_int(data, 20)
49
+ @channels_per_frame = Helper.read_int(data, 24)
50
+ @bits_per_channel = Helper.read_int(data, 28)
51
+
52
+ self.validate
53
+
54
+ data.size
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,43 @@
1
+ require 'caf/chunk'
2
+ require 'caf/chunk/helper'
3
+ require 'caf/errors'
4
+
5
+ module Caf::Chunk
6
+ include Helper
7
+
8
+ class Base
9
+
10
+ def self.implements(chunk_type)
11
+ Caf::Chunk.available_chunk_types[chunk_type] = self
12
+ end
13
+
14
+ attr_reader :chunk_type, :chunk_size
15
+
16
+ def initialize(chunk_header)
17
+ @chunk_type = chunk_header[:chunk_type]
18
+ @chunk_size = chunk_header[:chunk_size]
19
+ end
20
+
21
+ def to_s
22
+ "#{chunk_type} (unknown chunk)"
23
+ end
24
+
25
+ def validate
26
+ raise(Caf::Error, "chunk must implement validate method: #{chunk_type}") unless self.instance_of?(Base)
27
+ true
28
+ end
29
+
30
+ def fields_size
31
+ raise(Caf::Error, "chunk must implement fields_size method: #{chunk_type}") unless self.instance_of?(Base)
32
+ end
33
+
34
+ def read_data(file)
35
+ file.seek(chunk_size, IO::SEEK_CUR) unless chunk_size == -1
36
+ end
37
+
38
+ def check_type_and_size(expected_klass, expected_chunk_type)
39
+ raise(Caf::Error, "expected an #{expected_chunk_type} chunk") unless self.instance_of?(expected_klass)
40
+ raise(Caf::Error, "corrupted chunk: wrong size (expected #{fields_size}, got #{chunk_size}") if fields_size != chunk_size
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,47 @@
1
+ require 'caf/chunk/base'
2
+ require 'caf/chunk/helper'
3
+ require 'caf/errors'
4
+
5
+ module Caf::Chunk
6
+ include Helper
7
+
8
+ class Data < Base
9
+
10
+ implements 'data'
11
+
12
+ attr_accessor :edit_count, :size, :position
13
+
14
+ def initialize(chunk_header)
15
+ super chunk_header
16
+ end
17
+
18
+ def to_s
19
+ "#{chunk_type} (data chunk):\n"+
20
+ " -edit count: #{edit_count}\n" +
21
+ " -data size: #{size}\n" +
22
+ " -data position: #{position}\n"
23
+ end
24
+
25
+ def validate
26
+ end
27
+
28
+ def fields_size
29
+ raise(Caf::Error, "not implemented")
30
+ end
31
+
32
+ def read_data(file)
33
+ edit = file.read(4)
34
+ @edit_count = (edit.getbyte(0) << 32) + (edit.getbyte(1) << 16) + (edit.getbyte(2) << 8) + edit.getbyte(3)
35
+ @position = file.pos
36
+ unless chunk_size == -1
37
+ @size = chunk_size - 4 # 4 bytes are from edit_count field
38
+ file.seek(@size, IO::SEEK_CUR)
39
+ else
40
+ file.seek(0, IO::SEEK_END)
41
+ @size = file.pos - @position
42
+ # TODO should update chunk_size field with @size + 4 if file is writable
43
+ end
44
+ end
45
+
46
+ end
47
+ end
@@ -0,0 +1,24 @@
1
+ require 'caf/chunk/base'
2
+ require 'caf/errors'
3
+
4
+ module Caf::Chunk
5
+ include Helper
6
+
7
+ class Free < Base
8
+
9
+ implements 'free'
10
+
11
+ def to_s
12
+ "#{chunk_type} (free chunk)"
13
+ end
14
+
15
+ def validate
16
+ true
17
+ end
18
+
19
+ def fields_size
20
+ raise(Caf::Error, "not implemented")
21
+ end
22
+
23
+ end
24
+ end
@@ -0,0 +1,35 @@
1
+ require 'rubygems'
2
+ require 'float-formats'
3
+ include FltPnt
4
+
5
+ module Caf::Chunk
6
+ module Helper
7
+
8
+ BIT_SHIFTS_8 = [64, 56, 48, 40, 32, 24, 16, 8]
9
+
10
+ def self.read_bytes(number, data, offset = 0)
11
+ buffer = 0
12
+ number_minus = number - 1
13
+ number_minus.downto(0) do |i|
14
+ buffer += (data.getbyte(offset + number_minus - i) << (8 * i))
15
+ end
16
+ buffer
17
+ end
18
+
19
+ def self.read_chars(number, data, offset = 0)
20
+ buffer = ''
21
+ 0.upto(number-1) { |i| buffer += data.getbyte(offset+i).chr }
22
+ buffer
23
+ end
24
+
25
+ def self.read_double(data, offset = 0)
26
+ num = read_bytes(8, data, offset)
27
+ IEEE_binary64.from_bits_integer(num).to_number(Float)
28
+ end
29
+
30
+ def self.read_int(data, offset = 0)
31
+ read_bytes(4, data, offset).to_i
32
+ end
33
+
34
+ end
35
+ end
@@ -0,0 +1,35 @@
1
+ require 'caf/chunk/base'
2
+ require 'caf/errors'
3
+
4
+ module Caf::Chunk
5
+ include Helper
6
+
7
+ class MagicCookie < Base
8
+
9
+ implements 'kuki'
10
+
11
+ attr_reader :size, :position #, :data
12
+
13
+ def to_s
14
+ "#{chunk_type} (magic cookie chunk)\n" +
15
+ " -cookie size: #{size}\n" +
16
+ " -cookie position: #{position}\n"
17
+ end
18
+
19
+ def validate
20
+ true
21
+ end
22
+
23
+ def fields_size
24
+ raise(Caf::Error, "not implemented")
25
+ end
26
+
27
+ def read_data(file)
28
+ @size = chunk_size
29
+ @position = file.pos
30
+ #@data = file.read(chunk_size)
31
+ super(file)
32
+ end
33
+
34
+ end
35
+ end
@@ -0,0 +1,5 @@
1
+ require 'caf/chunk/base'
2
+ require "caf/chunk/audio_description"
3
+ require 'caf/chunk/data'
4
+ require "caf/chunk/free"
5
+ require "caf/chunk/magic_cookie"
data/lib/caf/errors.rb ADDED
@@ -0,0 +1,4 @@
1
+ module Caf
2
+ # Raised on any kind of error related to ruby-cafinfo
3
+ class Error < StandardError ; end
4
+ end
@@ -0,0 +1,41 @@
1
+ class CafInfo
2
+ module HashKeys #:nodoc:
3
+ ### lets you specify hash["key"] as hash.key
4
+ ### this came from CodingInRuby on RubyGarden
5
+ ### http://www.rubygarden.org/ruby?CodingInRuby
6
+ def method_missing(meth,*args)
7
+ m = meth.id2name
8
+ if /=$/ =~ m
9
+ self[m.chop] = (args.length<2 ? args[0] : args)
10
+ else
11
+ self[m]
12
+ end
13
+ end
14
+ end
15
+
16
+ class ::String
17
+ if RUBY_VERSION < "1.9.0"
18
+ alias getbyte []
19
+ else
20
+ def getbyte(i)
21
+ self[i].ord
22
+ end
23
+ end
24
+ end
25
+
26
+ module CafFileMethods #:nodoc:
27
+ if RUBY_VERSION < "1.9.0"
28
+ def getbyte
29
+ getc
30
+ end
31
+ end
32
+
33
+ def get32bits
34
+ (getbyte << 24) + (getbyte << 16) + (getbyte << 8) + getbyte
35
+ end
36
+
37
+ def get_syncsafe
38
+ (getbyte << 21) + (getbyte << 14) + (getbyte << 7) + getbyte
39
+ end
40
+ end
41
+ end
data/lib/cafinfo.rb ADDED
@@ -0,0 +1,203 @@
1
+ #!/usr/bin/env ruby
2
+ # coding:utf-8
3
+ # License:: Mit
4
+ # Author:: Oleguer Huguet Ibars (mailto:oleguer_DOT_huguet_AT__gmail_DOT_com)
5
+ # Website:: http://ruby-cafinfo.rubyforge.org/
6
+
7
+ require "fileutils"
8
+
9
+ $:.unshift "#{File.dirname(__FILE__)}"
10
+ require 'caf/extension_modules'
11
+ require 'caf/errors'
12
+ require 'caf/chunk/types'
13
+
14
+ # ruby -d to display debugging infos
15
+
16
+ class CafInfo
17
+
18
+ VERSION = "0.1"
19
+
20
+ # the original filename
21
+ attr_reader(:filename)
22
+
23
+ # duration in seconds of audio
24
+ attr_reader(:length)
25
+
26
+ # the number of sample frames per second of the data
27
+ attr_reader(:samplerate)
28
+
29
+ # a four-character code indicating the general kind of data in the stream
30
+ attr_reader(:format)
31
+
32
+ # flags specific to each format
33
+ attr_reader(:format_flags)
34
+
35
+ # the number of bytes in a packet of data.
36
+ attr_reader(:bytes_per_packet)
37
+
38
+ # the number of sample frames in each packet of data
39
+ attr_reader(:frames_per_packet)
40
+
41
+ # the number of channels in each frame of data
42
+ attr_reader(:channels_per_frame)
43
+
44
+ # the number of bits of sample data for each channel in a frame of data.
45
+ # 0 if the data format does not contain separate samples for each channel (for instance any compressed format)
46
+ attr_reader(:bits_per_channel)
47
+
48
+ # variable bitrate => true or false
49
+ attr_reader(:vbr)
50
+
51
+ # variable frame rate => true or false
52
+ attr_reader(:vfr)
53
+
54
+ # Instantiate CafInfo object with name +filename+.
55
+ def initialize(filename)
56
+ warn("#{self.class}::new() does not take block; use #{self.class}::open() instead") if block_given?
57
+ @filename = filename
58
+ @header = {}
59
+ reload
60
+ end
61
+
62
+ # reload (or load for the first time) the file from disk
63
+ def reload
64
+ raise(Caf::Error, "empty file") unless File.size?(@filename)
65
+
66
+ @file = File.new(filename, "rb")
67
+ @file.extend(CafFileMethods)
68
+
69
+ @chunks = {}
70
+
71
+ begin
72
+ @header = read_file_header
73
+ chunk = read_audio_description_chunk
74
+ @chunks[chunk.chunk_type.to_sym] = chunk
75
+ puts "Found chunk: #{@chunks[chunk.chunk_type.to_sym]}" if $DEBUG
76
+
77
+ until @file.eof? do
78
+ chunk = read_chunk_header
79
+ chunk.read_data(@file)
80
+ @chunks[chunk.chunk_type.to_sym] = chunk
81
+
82
+ puts "Found chunk: #{chunk}" if $DEBUG
83
+ end
84
+ ensure
85
+ @file.close
86
+ end
87
+
88
+ raise(Caf::Error, "data chunk not found") if @chunks[:data].nil?
89
+ @length = (@frames_per_packet * @chunks[:data].size) / (@samplerate * @bytes_per_packet)
90
+ end
91
+
92
+ # "block version" of CafInfo::new()
93
+ def self.open(*params)
94
+ m = self.new(*params)
95
+ ret = nil
96
+ if block_given?
97
+ begin
98
+ ret = yield(m)
99
+ ensure
100
+ m.close
101
+ end
102
+ else
103
+ ret = m
104
+ end
105
+ ret
106
+ end
107
+
108
+ # write to another filename at close()
109
+ def rename(new_filename)
110
+ @filename = new_filename
111
+ end
112
+
113
+ # this method returns the "audio-only" data boundaries of the file,
114
+ # i.e. data chunk content. Returned value is an array
115
+ # [position_in_the_file, length_of_the_data]
116
+ def audio_content
117
+ [@chunks[:data].position, @chunks[:data].size]
118
+ end
119
+
120
+ # Flush pending modifications and close the file
121
+ def close
122
+ puts "close" if $DEBUG
123
+ end
124
+
125
+ # close and reopen the file, i.e. commit changes to disk and
126
+ # reload it
127
+ def flush
128
+ close
129
+ reload
130
+ end
131
+
132
+ # inspect inside CafInfo
133
+ def to_s
134
+ s = "CAF (version #{@header[:file_version]}) #{@format} #{"VFR " if @vfr}#{@vbr ? "VBR" : "CBR"} #{@samplerate} Hz length #{@length} sec."
135
+ s << ""
136
+ s
137
+ end
138
+
139
+ private
140
+
141
+ ### reads through @file to find its header
142
+ def read_file_header
143
+ header = {}
144
+ head = @file.read(8)
145
+ raise(Caf::Error, "file header too short") if @file.eof?
146
+ raise(Caf::Error, "not a CAF file") unless head.match(/^caff/)
147
+
148
+ header[:file_version] = (head.getbyte(4) << 8) + head.getbyte(5)
149
+ raise(Caf::Error, "invalid CAF file version (supported only version 1)") if header[:file_version] != 1
150
+
151
+ header[:file_flags] = (head.getbyte(6) << 8) + head.getbyte(7)
152
+ raise(Caf::Error, "invalid CAF file flags") if header[:file_flags] != 0
153
+ header
154
+ end
155
+
156
+ def read_chunk_header
157
+ header = {}
158
+ head = @file.read(12)
159
+
160
+ raise(Caf::Error, "chunk header too short: #{head.size}") if head && head.size < 12
161
+
162
+ header[:chunk_type] = head.getbyte(0).chr + head.getbyte(1).chr + head.getbyte(2).chr + head.getbyte(3).chr
163
+ header[:chunk_size] = (head.getbyte(4) << 512) + (head.getbyte(5) << 256) + (head.getbyte(6) << 128) + (head.getbyte(7) << 64)+
164
+ (head.getbyte(8) << 32) + (head.getbyte(9) << 16) + (head.getbyte(10) << 8) + head.getbyte(11)
165
+ Caf::Chunk.build(header)
166
+ end
167
+
168
+ def read_audio_description_chunk
169
+ chunk = read_chunk_header
170
+ chunk.check_type_and_size(Caf::Chunk::AudioDescription, 'audio description')
171
+
172
+ chunk.read_data(@file)
173
+
174
+ @vbr = chunk.bytes_per_packet == 0
175
+ @vfr = chunk.frames_per_packet == 0
176
+ @samplerate = chunk.samplerate.to_i
177
+ @format = chunk.format_id
178
+ @format_flags = chunk.format_flags
179
+ @bytes_per_packet = chunk.bytes_per_packet
180
+ @frames_per_packet = chunk.frames_per_packet
181
+ @channels_per_frame = chunk.channels_per_frame
182
+ @bits_per_channel = chunk.bits_per_channel
183
+
184
+ chunk
185
+ end
186
+
187
+ end
188
+
189
+ if $0 == __FILE__
190
+ error = 0
191
+ while filename = ARGV.shift
192
+ begin
193
+ info = CafInfo.new(filename)
194
+ puts filename
195
+ puts info
196
+ rescue Caf::Error => e
197
+ puts "#{filename}\nERROR: #{e}"
198
+ error = 1
199
+ end
200
+ puts
201
+ end
202
+ exit(error)
203
+ end
metadata ADDED
@@ -0,0 +1,80 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ruby-cafinfo
3
+ version: !ruby/object:Gem::Version
4
+ version: "0.1"
5
+ platform: ruby
6
+ authors:
7
+ - Oleguer Huguet Ibars
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-03-19 00:00:00 +01:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: float-formats
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 0.1.1
24
+ version:
25
+ description: ruby-cafinfo is a ruby library to retrieve low level informations on CAF files
26
+ email: olegueret@rubyforge.org
27
+ executables: []
28
+
29
+ extensions: []
30
+
31
+ extra_rdoc_files:
32
+ - README
33
+ - LICENSE
34
+ - CHANGELOG
35
+ files:
36
+ - LICENSE
37
+ - README
38
+ - Rakefile
39
+ - lib/cafinfo.rb
40
+ - lib/caf
41
+ - lib/caf/chunk
42
+ - lib/caf/chunk/audio_description.rb
43
+ - lib/caf/chunk/magic_cookie.rb
44
+ - lib/caf/chunk/base.rb
45
+ - lib/caf/chunk/free.rb
46
+ - lib/caf/chunk/types.rb
47
+ - lib/caf/chunk/data.rb
48
+ - lib/caf/chunk/helper.rb
49
+ - lib/caf/extension_modules.rb
50
+ - lib/caf/errors.rb
51
+ - lib/caf/chunk.rb
52
+ - CHANGELOG
53
+ has_rdoc: true
54
+ homepage: http://ruby-cafinfo.rubyforge.org
55
+ post_install_message:
56
+ rdoc_options: []
57
+
58
+ require_paths:
59
+ - lib
60
+ required_ruby_version: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: "0"
65
+ version:
66
+ required_rubygems_version: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ version: "0"
71
+ version:
72
+ requirements: []
73
+
74
+ rubyforge_project: ruby-cafinfo
75
+ rubygems_version: 1.3.1
76
+ signing_key:
77
+ specification_version: 2
78
+ summary: ruby-cafinfo is a ruby library to retrieve low level informations on CAF files
79
+ test_files: []
80
+