ruby-audioinfo 0.4 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 31fa2ef2c169ce9c1395b5666d2b852d8ca67a79
4
- data.tar.gz: 3171ddb823ec69078ef2eba543038d28adf718b1
3
+ metadata.gz: b3d88409c0fcd1fc60750cc12d93527e10f078c1
4
+ data.tar.gz: 0eeb6112e45fe6e71f03cba86bd6984e601c1700
5
5
  SHA512:
6
- metadata.gz: 94576986f1b060232ac5922be0133765bf52283d0f82ca773ce56d8216026c195962a20cc0c81cc5aa6b5f8f5efd0fa44c59b8f50e04ca6e15c5493641fc4e2f
7
- data.tar.gz: f42f00f7cdd07008081d24c72935066f2545851027cc4a67b704d868ee41e990a629871daf53aa6e43a9a9d7bec05256ae51ae541989204d954e0edbaad4c067
6
+ metadata.gz: 856b773a0ea07be9223fe56d7100261b0653040c9c70ff66c121cc9126055fee2b717dd1e1c1dfd375753f5db503de0653ec39641f6ad06d3d6d2a9125c836f5
7
+ data.tar.gz: 16ecada3747678a6990459269b8bfa1054f423c72d673292b30154582d29c1378fa57a788e087b8f8dd661367c2a2dae68485485d29b79102820a6bcf39d0054
data/Rakefile CHANGED
@@ -15,7 +15,8 @@ Hoe.spec('ruby-audioinfo') do
15
15
  #history_file = "History.txt"
16
16
  self.readme_file = "README.rdoc"
17
17
  self.test_globs = ["test/test_*.rb"]
18
- self.rsync_args = "-rv --delete"
18
+ self.rsync_args = "-rv --delete"
19
+ self.license 'GPL-3.0'
19
20
 
20
21
  extra_deps << ['ruby-mp3info', '>= 0.8']
21
22
  extra_deps << ['ruby-ogginfo', '>= 0.7']
@@ -7,6 +7,7 @@ require "wmainfo"
7
7
  require "mp4info"
8
8
  require "flacinfo"
9
9
  require "apetag"
10
+ require "wavefile"
10
11
 
11
12
  $: << File.expand_path(File.dirname(__FILE__))
12
13
 
@@ -34,16 +35,16 @@ class AudioInfo
34
35
  "trackid" => "Track Id"
35
36
  }
36
37
 
37
- SUPPORTED_EXTENSIONS = %w{mp3 ogg opus spx mpc wma mp4 aac m4a flac}
38
+ SUPPORTED_EXTENSIONS = %w{mp3 ogg opus spx mpc wma mp4 aac m4a flac wav}
38
39
 
39
- VERSION = "0.4"
40
+ VERSION = "0.5.0"
40
41
 
41
42
  attr_reader :path, :extension, :musicbrainz_infos, :tracknum, :bitrate, :vbr
42
43
  attr_reader :artist, :album, :title, :length, :date
43
44
 
44
45
  # Part of testing API - you should not use this directly
45
46
  attr_reader :info
46
-
47
+
47
48
  # "block version" of #new()
48
49
  def self.open(*args)
49
50
  audio_info = self.new(*args)
@@ -81,122 +82,127 @@ class AudioInfo
81
82
 
82
83
  begin
83
84
  case @extension
84
- when 'mp3'
85
- @info = Mp3Info.new(filename)
86
- default_tag_fill
87
- #"TXXX"=>
88
- #["MusicBrainz TRM Id\000",
89
- #"MusicBrainz Artist Id\000aba64937-3334-4c65-90a1-4e6b9d4d7ada",
90
- #"MusicBrainz Album Id\000e1a223c1-cbc2-427f-a192-5d22fefd7c4c",
91
- #"MusicBrainz Album Type\000album",
92
- #"MusicBrainz Album Status\000official",
93
- #"MusicBrainz Album Artist Id\000"]
94
-
95
- if (arr = @info.tag2["TXXX"]).is_a?(Array)
96
- fields = MUSICBRAINZ_FIELDS.invert
97
- arr.each do |val|
98
- if val =~ /^MusicBrainz (.+)\000(.*)$/
99
- short_name = fields[$1]
100
- @musicbrainz_infos[short_name] = $2.gsub("\xEF\xBB\xBF".force_encoding("UTF-8"), '')
101
- end
102
- end
103
- end
104
- @bitrate = @info.bitrate
105
- i = @info.tag.tracknum
106
- @tracknum = (i.is_a?(Array) ? i.last : i).to_i
107
- @length = @info.length.to_i
108
- @date = @info.tag["date"]
109
- @vbr = @info.vbr
110
- @info.close
111
-
112
- when 'ogg', 'opus', 'spx'
113
- @info = OggInfo.new(filename)
114
- default_fill_musicbrainz_fields
115
- default_tag_fill
116
- @bitrate = @info.bitrate/1000
117
- @tracknum = @info.tag.tracknumber.to_i
118
- @length = @info.length.to_i
119
- @date = @info.tag["date"]
120
- @vbr = true
121
- @info.close
122
-
123
- when 'mpc'
124
- fill_ape_tag(filename)
125
-
126
- mpc_info = MpcInfo.new(filename)
127
- @bitrate = mpc_info.infos['bitrate']/1000
128
- @length = mpc_info.infos['length']
129
-
130
- when 'ape'
131
- fill_ape_tag(filename)
132
-
133
- when 'wma'
134
- @info = WmaInfo.new(filename, :encoding => 'utf-8')
135
- @artist = @info.tags["Author"]
136
- @album = @info.tags["AlbumTitle"]
137
- @title = @info.tags["Title"]
138
- @tracknum = @info.tags["TrackNumber"].to_i
139
- @date = @info.tags["Year"]
140
- @bitrate = @info.info["bitrate"]
141
- @length = @info.info["playtime_seconds"]
142
- MUSICBRAINZ_FIELDS.each do |key, original_key|
143
- @musicbrainz_infos[key] =
144
- @info.info["MusicBrainz/" + original_key.tr(" ", "")] ||
145
- @info.info["MusicBrainz/" + original_key]
146
- end
147
-
148
- when 'mp4', 'aac', 'm4a'
149
- @extension = 'mp4'
150
- @info = MP4Info.open(filename)
151
- @artist = @info.ART
152
- @album = @info.ALB
153
- @title = @info.NAM
154
- @tracknum = ( t = @info.TRKN ) ? t.first : 0
155
- @date = @info.DAY
156
- @bitrate = @info.BITRATE
157
- @length = @info.SECS
158
- mapping = MUSICBRAINZ_FIELDS.invert
159
-
160
- faad_info(filename).match(/^MusicBrainz (.+)$/) do
161
- name, value = $1.split(/: /, 2)
162
- key = mapping[name]
163
- @musicbrainz_infos[key] = value
164
- end
165
-
166
- when 'flac'
167
- @info = FlacInfo.new(filename)
168
- # Unfortunately, FlacInfo doesn't allow us to fiddle inside
169
- # their class, so we have to brute force it. Any other
170
- # solution (e.g. creating another abstraction or getting
171
- # methods) lands up being more messy and brittle.
172
- @info.instance_variable_set('@tags', CaseInsensitiveHash.new(@info.tags))
173
-
174
- get_tag = proc do |name|
175
- if t = @info.tags[name]
176
- t.dup.force_encoding("utf-8")
177
- else
178
- nil
179
- end
85
+ when 'mp3'
86
+ @info = Mp3Info.new(filename)
87
+ default_tag_fill
88
+ #"TXXX"=>
89
+ #["MusicBrainz TRM Id\000",
90
+ #"MusicBrainz Artist Id\000aba64937-3334-4c65-90a1-4e6b9d4d7ada",
91
+ #"MusicBrainz Album Id\000e1a223c1-cbc2-427f-a192-5d22fefd7c4c",
92
+ #"MusicBrainz Album Type\000album",
93
+ #"MusicBrainz Album Status\000official",
94
+ #"MusicBrainz Album Artist Id\000"]
95
+
96
+ if (arr = @info.tag2["TXXX"]).is_a?(Array)
97
+ fields = MUSICBRAINZ_FIELDS.invert
98
+ arr.each do |val|
99
+ if val =~ /^MusicBrainz (.+)\000(.*)$/
100
+ short_name = fields[$1]
101
+ @musicbrainz_infos[short_name] = $2.gsub("\xEF\xBB\xBF".force_encoding("UTF-8"), '')
102
+ end
180
103
  end
181
-
182
- @artist = get_tag.call("artist")
183
- @album = get_tag.call("album")
184
- @title = get_tag.call("title")
185
- @tracknum = @info.tags["tracknumber"].to_i
186
- @date = get_tag.call("date")
187
- @bitrate = 0
188
- @length = @info.streaminfo["total_samples"] / @info.streaminfo["samplerate"].to_f
189
- if @length > 0
190
- @bitrate = File.size(filename).to_f*8/@length/1024
191
- end
192
- @info.tags.each do |tagname, tagvalue|
193
- next unless tagname =~ /^musicbrainz_(.+)$/
194
- @musicbrainz_infos[$1] = get_tag.call(tagname)
104
+ end
105
+ @bitrate = @info.bitrate
106
+ i = @info.tag.tracknum
107
+ @tracknum = (i.is_a?(Array) ? i.last : i).to_i
108
+ @length = @info.length.to_i
109
+ @date = @info.tag["date"]
110
+ @vbr = @info.vbr
111
+ @info.close
112
+
113
+ when 'ogg', 'opus', 'spx'
114
+ @info = OggInfo.new(filename)
115
+ default_fill_musicbrainz_fields
116
+ default_tag_fill
117
+ @bitrate = @info.bitrate/1000
118
+ @tracknum = @info.tag.tracknumber.to_i
119
+ @length = @info.length.to_i
120
+ @date = @info.tag["date"]
121
+ @vbr = true
122
+ @info.close
123
+
124
+ when 'mpc'
125
+ fill_ape_tag(filename)
126
+ mpc_info = MpcInfo.new(filename)
127
+ @bitrate = mpc_info.infos['bitrate']/1000
128
+ @length = mpc_info.infos['length']
129
+
130
+ when 'ape'
131
+ fill_ape_tag(filename)
132
+
133
+ when 'wma'
134
+ @info = WmaInfo.new(filename, :encoding => 'utf-8')
135
+ @artist = @info.tags["Author"]
136
+ @album = @info.tags["AlbumTitle"]
137
+ @title = @info.tags["Title"]
138
+ @tracknum = @info.tags["TrackNumber"].to_i
139
+ @date = @info.tags["Year"]
140
+ @bitrate = @info.info["bitrate"]
141
+ @length = @info.info["playtime_seconds"]
142
+ MUSICBRAINZ_FIELDS.each do |key, original_key|
143
+ @musicbrainz_infos[key] =
144
+ @info.info["MusicBrainz/" + original_key.tr(" ", "")] ||
145
+ @info.info["MusicBrainz/" + original_key]
146
+ end
147
+
148
+ when 'mp4', 'aac', 'm4a'
149
+ @extension = 'mp4'
150
+ @info = MP4Info.open(filename)
151
+ @artist = @info.ART
152
+ @album = @info.ALB
153
+ @title = @info.NAM
154
+ @tracknum = ( t = @info.TRKN ) ? t.first : 0
155
+ @date = @info.DAY
156
+ @bitrate = @info.BITRATE
157
+ @length = @info.SECS
158
+ mapping = MUSICBRAINZ_FIELDS.invert
159
+
160
+ faad_info(filename).match(/^MusicBrainz (.+)$/) do
161
+ name, value = $1.split(/: /, 2)
162
+ key = mapping[name]
163
+ @musicbrainz_infos[key] = value
164
+ end
165
+
166
+ when 'flac'
167
+ @info = FlacInfo.new(filename)
168
+ # Unfortunately, FlacInfo doesn't allow us to fiddle inside
169
+ # their class, so we have to brute force it. Any other
170
+ # solution (e.g. creating another abstraction or getting
171
+ # methods) lands up being more messy and brittle.
172
+ @info.instance_variable_set('@tags', CaseInsensitiveHash.new(@info.tags))
173
+
174
+ get_tag = proc do |name|
175
+ if t = @info.tags[name]
176
+ t.dup.force_encoding("utf-8")
177
+ else
178
+ nil
195
179
  end
196
- @musicbrainz_infos["trmid"] = @info.tags["musicip_puid"]
197
- #default_fill_musicbrainz_fields
198
- else
199
- raise(AudioInfoError, "unsupported extension '.#{@extension}'")
180
+ end
181
+
182
+ @artist = get_tag.call("artist")
183
+ @album = get_tag.call("album")
184
+ @title = get_tag.call("title")
185
+ @tracknum = @info.tags["tracknumber"].to_i
186
+ @date = get_tag.call("date")
187
+ @bitrate = 0
188
+ @length = @info.streaminfo["total_samples"] / @info.streaminfo["samplerate"].to_f
189
+ if @length > 0
190
+ @bitrate = File.size(filename).to_f*8/@length/1024
191
+ end
192
+ @info.tags.each do |tagname, tagvalue|
193
+ next unless tagname =~ /^musicbrainz_(.+)$/
194
+ @musicbrainz_infos[$1] = get_tag.call(tagname)
195
+ end
196
+ @musicbrainz_infos["trmid"] = @info.tags["musicip_puid"]
197
+ #default_fill_musicbrainz_fields
198
+
199
+ when 'wav'
200
+ @info = WaveFile::Reader.info(filename)
201
+ @length = @info.duration.seconds
202
+ @bitrate = File.size(filename) * 8 / @length / 1024
203
+
204
+ else
205
+ raise(AudioInfoError, "unsupported extension '.#{@extension}'")
200
206
  end
201
207
 
202
208
  if @tracknum == 0
@@ -205,12 +211,12 @@ class AudioInfo
205
211
 
206
212
  @musicbrainz_infos.delete_if { |k, v| v.nil? }
207
213
  @hash = { "artist" => @artist,
208
- "album" => @album,
209
- "title" => @title,
210
- "tracknum" => @tracknum,
211
- "date" => @date,
212
- "length" => @length,
213
- "bitrate" => @bitrate,
214
+ "album" => @album,
215
+ "title" => @title,
216
+ "tracknum" => @tracknum,
217
+ "date" => @date,
218
+ "length" => @length,
219
+ "bitrate" => @bitrate,
214
220
  }
215
221
 
216
222
  rescue Exception, Mp3InfoError, OggInfoError, ApeTagError => e
@@ -218,7 +224,6 @@ class AudioInfo
218
224
  end
219
225
 
220
226
  @needs_commit = false
221
-
222
227
  end
223
228
 
224
229
  # set the title of the file
@@ -275,62 +280,61 @@ class AudioInfo
275
280
  def close
276
281
  if @needs_commit
277
282
  case @info
278
- when Mp3Info
279
- Mp3Info.open(@path) do |info|
280
- info.tag.artist = @artist
281
- info.tag.title = @title
282
- info.tag.album = @album
283
- info.tag.tracknum = @tracknum
284
- if @picture
285
- info.tag2.remove_pictures
286
- info.tag2.add_picture(File.binread(@picture))
287
- end
288
- end
289
- when OggInfo
290
- OggInfo.open(@path) do |ogg|
291
- { "artist" => @artist,
292
- "album" => @album,
293
- "title" => @title,
294
- "tracknumber" => @tracknum}.each do |k,v|
295
- ogg.tag[k] = v.to_s
296
- end
297
- if @picture
298
- ogg.picture = @picture
299
- end
300
- end
301
-
302
- when ApeTag
303
- ape = ApeTag.new(@path)
304
- ape.update do |fields|
305
- fields["Artist"] = @artist
306
- fields["Album"] = @album
307
- fields["Title"] = @title
308
- fields["Track"] = @tracknum.to_s
283
+ when Mp3Info
284
+ Mp3Info.open(@path) do |info|
285
+ info.tag.artist = @artist
286
+ info.tag.title = @title
287
+ info.tag.album = @album
288
+ info.tag.tracknum = @tracknum
289
+ if @picture
290
+ info.tag2.remove_pictures
291
+ info.tag2.add_picture(File.binread(@picture))
309
292
  end
310
- else
311
- have_metaflac = system("which metaflac > /dev/null")
312
- have_ffmpeg = system("which ffmpeg > /dev/null")
313
- if have_metaflac and @info.is_a?(FlacInfo)
314
- tags = {"ARTIST" => @artist,
315
- "ALBUM" => @album,
316
- "TITLE" => @title,
317
- "TRACKNUMBER" => @tracknum}.inject([]) do |tags, (key, value)|
318
- tags + ["--set-tag", "#{key}=#{value.to_s}"]
319
- end
320
- tag_with_shell_command("metaflac", "--remove-all", :src)
321
- tag_with_shell_command("metaflac", tags, :src)
322
- elsif have_ffmpeg
323
- tags = {"artist" => @artist,
324
- "album" => @album,
325
- "title" => @title}.inject([]) do |tags, (key, value)|
326
- tags + ["-metadata", "#{key}=#{value.to_s}"]
327
- end
328
- tag_with_shell_command("ffmpeg", "-y", "-i", :src, "-loglevel", "quiet", tags, :dst)
329
- else
330
- raise(AudioInfoError, "implement me")
293
+ end
294
+ when OggInfo
295
+ OggInfo.open(@path) do |ogg|
296
+ { "artist" => @artist,
297
+ "album" => @album,
298
+ "title" => @title,
299
+ "tracknumber" => @tracknum}.each do |k,v|
300
+ ogg.tag[k] = v.to_s
301
+ end
302
+ if @picture
303
+ ogg.picture = @picture
304
+ end
305
+ end
306
+
307
+ when ApeTag
308
+ ape = ApeTag.new(@path)
309
+ ape.update do |fields|
310
+ fields["Artist"] = @artist
311
+ fields["Album"] = @album
312
+ fields["Title"] = @title
313
+ fields["Track"] = @tracknum.to_s
314
+ end
315
+ else
316
+ have_metaflac = system("which metaflac > /dev/null")
317
+ have_ffmpeg = system("which ffmpeg > /dev/null")
318
+ if have_metaflac and @info.is_a?(FlacInfo)
319
+ tags = {"ARTIST" => @artist,
320
+ "ALBUM" => @album,
321
+ "TITLE" => @title,
322
+ "TRACKNUMBER" => @tracknum}.inject([]) do |tags, (key, value)|
323
+ tags + ["--set-tag", "#{key}=#{value.to_s}"]
331
324
  end
325
+ tag_with_shell_command("metaflac", "--remove-all", :src)
326
+ tag_with_shell_command("metaflac", tags, :src)
327
+ elsif have_ffmpeg
328
+ tags = {"artist" => @artist,
329
+ "album" => @album,
330
+ "title" => @title}.inject([]) do |tags, (key, value)|
331
+ tags + ["-metadata", "#{key}=#{value.to_s}"]
332
+ end
333
+ tag_with_shell_command("ffmpeg", "-y", "-i", :src, "-loglevel", "quiet", tags, :dst)
334
+ else
335
+ raise(AudioInfoError, "implement me")
336
+ end
332
337
  end
333
-
334
338
  end
335
339
  @needs_commit
336
340
  end
@@ -356,7 +360,7 @@ class AudioInfo
356
360
  ! @musicbrainz_infos.empty?
357
361
  end
358
362
 
359
- private
363
+ private
360
364
 
361
365
  def sanitize(input)
362
366
  s = input.is_a?(Array) ? input.first : input
@@ -89,7 +89,7 @@ class AudioInfo::Album
89
89
  end
90
90
  mb
91
91
  end
92
-
92
+
93
93
  # return an array of images with "folder.*" in first
94
94
  def images
95
95
  self.class.images(@path)
@@ -122,17 +122,17 @@ class AudioInfo::Album
122
122
  out = StringIO.new
123
123
  out.puts(@path)
124
124
  out.print "'#{title}'"
125
-
125
+
126
126
  unless va?
127
127
  out.print " by '#{@files.first.artist}' "
128
128
  end
129
129
 
130
130
  out.puts
131
-
131
+
132
132
  @files.sort_by { |f| f.tracknum }.each do |f|
133
133
  out.printf("%02d %s %3d %s", f.tracknum, f.extension, f.bitrate, f.title)
134
134
  if va?
135
- out.print(" "+f.artist)
135
+ out.print(" "+f.artist)
136
136
  end
137
137
  out.puts
138
138
  end
@@ -143,7 +143,4 @@ class AudioInfo::Album
143
143
  def inspect
144
144
  @infos.inspect
145
145
  end
146
-
147
146
  end
148
-
149
-
@@ -0,0 +1,27 @@
1
+ require_relative "../lib/audioinfo"
2
+ require "minitest/autorun"
3
+
4
+ require "fileutils"
5
+ require "tmpdir"
6
+
7
+ require_relative "test_helper"
8
+
9
+ class TestWav < MiniTest::Unit::TestCase
10
+
11
+ WAV_FILE = "#{Dir.tmpdir}/ruby-audioinfo-test.wav"
12
+
13
+ def setup
14
+ FileUtils.cp(File.join(SUPPORT_DIR, "piano2.wav"), WAV_FILE)
15
+ end
16
+
17
+ def test_wav_whitelist
18
+ i = AudioInfo.new(WAV_FILE)
19
+ assert_kind_of WaveFile::Info, i.info
20
+ end
21
+
22
+ def test_wav_length
23
+ i = AudioInfo.new(WAV_FILE)
24
+ assert_equal i.length, 6
25
+ end
26
+
27
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-audioinfo
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.4'
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Guillaume Pierronnet
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-10-27 00:00:00.000000000 Z
12
+ date: 2014-03-24 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: ruby-mp3info
@@ -101,28 +101,28 @@ dependencies:
101
101
  requirements:
102
102
  - - ~>
103
103
  - !ruby/object:Gem::Version
104
- version: '3.10'
104
+ version: '4.0'
105
105
  type: :development
106
106
  prerelease: false
107
107
  version_requirements: !ruby/object:Gem::Requirement
108
108
  requirements:
109
109
  - - ~>
110
110
  - !ruby/object:Gem::Version
111
- version: '3.10'
111
+ version: '4.0'
112
112
  - !ruby/object:Gem::Dependency
113
113
  name: hoe
114
114
  requirement: !ruby/object:Gem::Requirement
115
115
  requirements:
116
116
  - - ~>
117
117
  - !ruby/object:Gem::Version
118
- version: '3.5'
118
+ version: '3.7'
119
119
  type: :development
120
120
  prerelease: false
121
121
  version_requirements: !ruby/object:Gem::Requirement
122
122
  requirements:
123
123
  - - ~>
124
124
  - !ruby/object:Gem::Version
125
- version: '3.5'
125
+ version: '3.7'
126
126
  description: |-
127
127
  ruby-audioinfo glue together various audio ruby libraries and presents a unified
128
128
  API to the developper. Currently, supported formats are: mp3, ogg, mpc, ape,
@@ -149,9 +149,11 @@ files:
149
149
  - test/test_audioinfo.rb
150
150
  - test/test_case_insensitive_hash.rb
151
151
  - test/test_helper.rb
152
+ - test/test_wav.rb
152
153
  - .gemtest
153
154
  homepage: http://ruby-audioinfo.rubyforge.org
154
- licenses: []
155
+ licenses:
156
+ - GPL-3.0
155
157
  metadata: {}
156
158
  post_install_message:
157
159
  rdoc_options:
@@ -180,3 +182,4 @@ test_files:
180
182
  - test/test_audioinfo.rb
181
183
  - test/test_case_insensitive_hash.rb
182
184
  - test/test_helper.rb
185
+ - test/test_wav.rb