ruby-audioinfo 0.2.3 → 0.3.1
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.
- checksums.yaml +7 -0
- data/History.txt +8 -0
- data/Manifest.txt +1 -0
- data/Rakefile +2 -2
- data/lib/audioinfo.rb +78 -10
- data/lib/audioinfo/case_insensitive_hash.rb +16 -0
- data/test/test_audioinfo.rb +35 -0
- data/test/test_case_insensitive_hash.rb +28 -0
- data/test/test_helper.rb +1 -0
- metadata +75 -48
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: be66808c6cbe04237d1052537ff0ad4fc2f3f614
|
4
|
+
data.tar.gz: b2843c08fe747e1c77cc94490ca266559539bc45
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 8838cdedf9de87e385559086a0dbafd9bb315b3d8254673c0441ef234d9769435c4c3ee34bc88c2325e15d7a1f7108e8efd684e051e054ccbc75441550a45003
|
7
|
+
data.tar.gz: bf2999b9756f2ec4e986e28fdce3d2d169917802b99c1b565db5ed9d60bf1ceb70e2fe21a473b04af097e400c41eb64c7c9779514ba22f2bcc8d95238b6e2f9f
|
data/History.txt
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
=== 0.3 / 2013-03-26
|
2
|
+
|
3
|
+
* correctly computes bitrate on .flac files
|
4
|
+
* string encoding fixes on .flac files
|
5
|
+
* write support on .flac with "metaflac" binary
|
6
|
+
* case insensitive wrapper to flacinfo's tags hash
|
7
|
+
* uses "ffmpeg" binary for writing tags on not natively supported format
|
8
|
+
|
1
9
|
=== 0.2.3 / 2012-05-24
|
2
10
|
|
3
11
|
* fixed title method on AudioInfo::Album, now returns nil if title is not found
|
data/Manifest.txt
CHANGED
data/Rakefile
CHANGED
@@ -17,8 +17,8 @@ Hoe.spec('ruby-audioinfo') do
|
|
17
17
|
self.test_globs = ["test/test_*.rb"]
|
18
18
|
self.rsync_args = "-rv --delete"
|
19
19
|
|
20
|
-
extra_deps << ['ruby-mp3info', '>= 0.
|
21
|
-
extra_deps << ['ruby-ogginfo', '>= 0.6.
|
20
|
+
extra_deps << ['ruby-mp3info', '>= 0.8']
|
21
|
+
extra_deps << ['ruby-ogginfo', '>= 0.6.11']
|
22
22
|
extra_deps << ['mp4info', '>= 1.7.3']
|
23
23
|
extra_deps << ['moumar-wmainfo-rb', '>= 0.7']
|
24
24
|
extra_deps << ['flacinfo-rb', '>= 0.4']
|
data/lib/audioinfo.rb
CHANGED
@@ -11,6 +11,7 @@ require "apetag"
|
|
11
11
|
$: << File.expand_path(File.dirname(__FILE__))
|
12
12
|
|
13
13
|
require "audioinfo/mpcinfo"
|
14
|
+
require "audioinfo/case_insensitive_hash"
|
14
15
|
|
15
16
|
class AudioInfoError < StandardError ; end
|
16
17
|
|
@@ -35,10 +36,13 @@ class AudioInfo
|
|
35
36
|
|
36
37
|
SUPPORTED_EXTENSIONS = %w{mp3 ogg mpc wma mp4 aac m4a flac}
|
37
38
|
|
38
|
-
VERSION = "0.
|
39
|
+
VERSION = "0.3.1"
|
39
40
|
|
40
41
|
attr_reader :path, :extension, :musicbrainz_infos, :tracknum, :bitrate, :vbr
|
41
42
|
attr_reader :artist, :album, :title, :length, :date
|
43
|
+
|
44
|
+
# Part of testing API - you should not use this directly
|
45
|
+
attr_reader :info
|
42
46
|
|
43
47
|
# "block version" of #new()
|
44
48
|
def self.open(*args)
|
@@ -161,20 +165,36 @@ class AudioInfo
|
|
161
165
|
|
162
166
|
when 'flac'
|
163
167
|
@info = FlacInfo.new(filename)
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
@
|
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
|
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
|
169
188
|
@length = @info.streaminfo["total_samples"] / @info.streaminfo["samplerate"].to_f
|
170
|
-
|
189
|
+
if @length > 0
|
190
|
+
@bitrate = File.size(filename).to_f*8/@length/1024
|
191
|
+
end
|
171
192
|
@info.tags.each do |tagname, tagvalue|
|
172
193
|
next unless tagname =~ /^musicbrainz_(.+)$/
|
173
|
-
@musicbrainz_infos[$1] =
|
194
|
+
@musicbrainz_infos[$1] = get_tag.call(tagname)
|
174
195
|
end
|
175
196
|
@musicbrainz_infos["trmid"] = @info.tags["musicip_puid"]
|
176
197
|
#default_fill_musicbrainz_fields
|
177
|
-
|
178
198
|
else
|
179
199
|
raise(AudioInfoError, "unsupported extension '.#{@extension}'")
|
180
200
|
end
|
@@ -274,7 +294,27 @@ class AudioInfo
|
|
274
294
|
fields["Track"] = @tracknum.to_s
|
275
295
|
end
|
276
296
|
else
|
277
|
-
|
297
|
+
have_metaflac = system("which metaflac > /dev/null")
|
298
|
+
have_ffmpeg = system("which ffmpeg > /dev/null")
|
299
|
+
if have_metaflac and @info.is_a?(FlacInfo)
|
300
|
+
tags = {"ARTIST" => @artist,
|
301
|
+
"ALBUM" => @album,
|
302
|
+
"TITLE" => @title,
|
303
|
+
"TRACKNUMBER" => @tracknum}.inject([]) do |tags, (key, value)|
|
304
|
+
tags + ["--set-tag", "#{key}=#{value.to_s}"]
|
305
|
+
end
|
306
|
+
tag_with_shell_command("metaflac", "--remove-all", :src)
|
307
|
+
tag_with_shell_command("metaflac", tags, :src)
|
308
|
+
elsif have_ffmpeg
|
309
|
+
tags = {"artist" => @artist,
|
310
|
+
"album" => @album,
|
311
|
+
"title" => @title}.inject([]) do |tags, (key, value)|
|
312
|
+
tags + ["-metadata", "#{key}=#{value.to_s}"]
|
313
|
+
end
|
314
|
+
tag_with_shell_command("ffmpeg", "-y", "-i", :src, "-loglevel", "quiet", tags, :dst)
|
315
|
+
else
|
316
|
+
raise(AudioInfoError, "implement me")
|
317
|
+
end
|
278
318
|
end
|
279
319
|
|
280
320
|
end
|
@@ -362,4 +402,32 @@ class AudioInfo
|
|
362
402
|
# Return the stderr because faad prints info on that fd...
|
363
403
|
status.exitstatus.zero? ? err : ''
|
364
404
|
end
|
405
|
+
|
406
|
+
def shell_escape(s)
|
407
|
+
"'" + s.gsub(/'/) { "'\\''" } + "'"
|
408
|
+
end
|
409
|
+
|
410
|
+
def tag_with_shell_command(*command_arr)
|
411
|
+
expand_command = proc do |hash|
|
412
|
+
command_arr.collect do |token|
|
413
|
+
token.is_a?(Symbol) ? hash[token] : token
|
414
|
+
end.flatten
|
415
|
+
end
|
416
|
+
|
417
|
+
hash = {:src => @path}
|
418
|
+
if command_arr.include?(:dst)
|
419
|
+
Tempfile.open(["ruby-audioinfo", "."+@extension]) do |tf|
|
420
|
+
cmd = expand_command.call(hash.merge(:dst => tf.path))
|
421
|
+
tf.close
|
422
|
+
if system(*cmd)
|
423
|
+
FileUtils.mv(tf.path, @path)
|
424
|
+
else
|
425
|
+
raise(AudioInfoError, "error while running #{command_arr[0]}")
|
426
|
+
end
|
427
|
+
end
|
428
|
+
else
|
429
|
+
cmd = expand_command.call(hash)
|
430
|
+
system(*cmd) || raise(AudioInfoError, "error while running #{command_arr[0]}")
|
431
|
+
end
|
432
|
+
end
|
365
433
|
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class CaseInsensitiveHash < Hash
|
2
|
+
def initialize(hash = {})
|
3
|
+
super
|
4
|
+
hash.each do |key, value|
|
5
|
+
self[key.downcase] = value
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
def [](key)
|
10
|
+
super(key.downcase)
|
11
|
+
end
|
12
|
+
|
13
|
+
def []=(key, value)
|
14
|
+
super(key.downcase, value)
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,35 @@
|
|
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 TestAudioinfo < MiniTest::Unit::TestCase
|
10
|
+
|
11
|
+
FLAC_FILE = "#{Dir.tmpdir}/ruby-audioinfo-test.flac"
|
12
|
+
|
13
|
+
def setup
|
14
|
+
FileUtils.cp(File.join(SUPPORT_DIR, "440Hz-5sec.flac"), FLAC_FILE)
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_flac_whitelist
|
18
|
+
i = AudioInfo.new(FLAC_FILE)
|
19
|
+
assert_kind_of FlacInfo, i.info
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_flac_tags_wrapper
|
23
|
+
i = AudioInfo.new(FLAC_FILE)
|
24
|
+
assert_kind_of CaseInsensitiveHash, i.info.tags
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_flac_writing
|
28
|
+
title = "test with utf8éblèàqsf"
|
29
|
+
ai = AudioInfo.new(FLAC_FILE)
|
30
|
+
ai.title = title
|
31
|
+
ai.close
|
32
|
+
ai = AudioInfo.new(FLAC_FILE)
|
33
|
+
assert_equal title, ai.title
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require "audioinfo"
|
2
|
+
require "minitest/autorun"
|
3
|
+
|
4
|
+
class TestCaseInsensitiveHash < MiniTest::Unit::TestCase
|
5
|
+
|
6
|
+
def test_string_access
|
7
|
+
h = CaseInsensitiveHash.new
|
8
|
+
h["foo"] = "bar"
|
9
|
+
assert_equal "bar", h["foo"]
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_symbol_access
|
13
|
+
h = CaseInsensitiveHash.new
|
14
|
+
h[:foo] = "bar"
|
15
|
+
assert_equal "bar", h[:foo]
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_case_insensitive_access
|
19
|
+
h = CaseInsensitiveHash.new
|
20
|
+
h["FOO"] = "bar"
|
21
|
+
assert_equal "bar", h["foo"]
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_copy_constructor
|
25
|
+
h = CaseInsensitiveHash.new({"FOO" => "bar"})
|
26
|
+
assert_equal "bar", h["foo"]
|
27
|
+
end
|
28
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
SUPPORT_DIR = File.expand_path("support", File.dirname(__FILE__))
|
metadata
CHANGED
@@ -1,8 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby-audioinfo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
5
|
-
prerelease:
|
4
|
+
version: 0.3.1
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Guillaume Pierronnet
|
@@ -10,102 +9,124 @@ authors:
|
|
10
9
|
autorequire:
|
11
10
|
bindir: bin
|
12
11
|
cert_chain: []
|
13
|
-
date:
|
12
|
+
date: 2013-03-26 00:00:00.000000000 Z
|
14
13
|
dependencies:
|
15
14
|
- !ruby/object:Gem::Dependency
|
16
15
|
name: ruby-mp3info
|
17
|
-
requirement:
|
18
|
-
none: false
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
19
17
|
requirements:
|
20
|
-
- -
|
18
|
+
- - '>='
|
21
19
|
- !ruby/object:Gem::Version
|
22
|
-
version: 0.
|
20
|
+
version: '0.8'
|
23
21
|
type: :runtime
|
24
22
|
prerelease: false
|
25
|
-
version_requirements:
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - '>='
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: '0.8'
|
26
28
|
- !ruby/object:Gem::Dependency
|
27
29
|
name: ruby-ogginfo
|
28
|
-
requirement:
|
29
|
-
none: false
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
30
31
|
requirements:
|
31
|
-
- -
|
32
|
+
- - '>='
|
32
33
|
- !ruby/object:Gem::Version
|
33
|
-
version: 0.6.
|
34
|
+
version: 0.6.11
|
34
35
|
type: :runtime
|
35
36
|
prerelease: false
|
36
|
-
version_requirements:
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - '>='
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: 0.6.11
|
37
42
|
- !ruby/object:Gem::Dependency
|
38
43
|
name: mp4info
|
39
|
-
requirement:
|
40
|
-
none: false
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
41
45
|
requirements:
|
42
|
-
- -
|
46
|
+
- - '>='
|
43
47
|
- !ruby/object:Gem::Version
|
44
48
|
version: 1.7.3
|
45
49
|
type: :runtime
|
46
50
|
prerelease: false
|
47
|
-
version_requirements:
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - '>='
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: 1.7.3
|
48
56
|
- !ruby/object:Gem::Dependency
|
49
57
|
name: moumar-wmainfo-rb
|
50
|
-
requirement:
|
51
|
-
none: false
|
58
|
+
requirement: !ruby/object:Gem::Requirement
|
52
59
|
requirements:
|
53
|
-
- -
|
60
|
+
- - '>='
|
54
61
|
- !ruby/object:Gem::Version
|
55
62
|
version: '0.7'
|
56
63
|
type: :runtime
|
57
64
|
prerelease: false
|
58
|
-
version_requirements:
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0.7'
|
59
70
|
- !ruby/object:Gem::Dependency
|
60
71
|
name: flacinfo-rb
|
61
|
-
requirement:
|
62
|
-
none: false
|
72
|
+
requirement: !ruby/object:Gem::Requirement
|
63
73
|
requirements:
|
64
|
-
- -
|
74
|
+
- - '>='
|
65
75
|
- !ruby/object:Gem::Version
|
66
76
|
version: '0.4'
|
67
77
|
type: :runtime
|
68
78
|
prerelease: false
|
69
|
-
version_requirements:
|
79
|
+
version_requirements: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - '>='
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '0.4'
|
70
84
|
- !ruby/object:Gem::Dependency
|
71
85
|
name: apetag
|
72
|
-
requirement:
|
73
|
-
none: false
|
86
|
+
requirement: !ruby/object:Gem::Requirement
|
74
87
|
requirements:
|
75
|
-
- -
|
88
|
+
- - '>='
|
76
89
|
- !ruby/object:Gem::Version
|
77
90
|
version: 1.1.4
|
78
91
|
type: :runtime
|
79
92
|
prerelease: false
|
80
|
-
version_requirements:
|
93
|
+
version_requirements: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - '>='
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: 1.1.4
|
81
98
|
- !ruby/object:Gem::Dependency
|
82
99
|
name: rdoc
|
83
|
-
requirement:
|
84
|
-
none: false
|
100
|
+
requirement: !ruby/object:Gem::Requirement
|
85
101
|
requirements:
|
86
102
|
- - ~>
|
87
103
|
- !ruby/object:Gem::Version
|
88
104
|
version: '3.10'
|
89
105
|
type: :development
|
90
106
|
prerelease: false
|
91
|
-
version_requirements:
|
107
|
+
version_requirements: !ruby/object:Gem::Requirement
|
108
|
+
requirements:
|
109
|
+
- - ~>
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
version: '3.10'
|
92
112
|
- !ruby/object:Gem::Dependency
|
93
113
|
name: hoe
|
94
|
-
requirement:
|
95
|
-
none: false
|
114
|
+
requirement: !ruby/object:Gem::Requirement
|
96
115
|
requirements:
|
97
116
|
- - ~>
|
98
117
|
- !ruby/object:Gem::Version
|
99
|
-
version: '3.
|
118
|
+
version: '3.5'
|
100
119
|
type: :development
|
101
120
|
prerelease: false
|
102
|
-
version_requirements:
|
103
|
-
|
104
|
-
|
105
|
-
|
121
|
+
version_requirements: !ruby/object:Gem::Requirement
|
122
|
+
requirements:
|
123
|
+
- - ~>
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '3.5'
|
126
|
+
description: |-
|
127
|
+
ruby-audioinfo glue together various audio ruby libraries and presents a unified
|
106
128
|
API to the developper. Currently, supported formats are: mp3, ogg, mpc, ape,
|
107
|
-
|
108
|
-
wma, flac, aac, mp4, m4a.'
|
129
|
+
wma, flac, aac, mp4, m4a.
|
109
130
|
email:
|
110
131
|
- guillaume.pierronnet@gmail.com
|
111
132
|
- unknown
|
@@ -123,10 +144,15 @@ files:
|
|
123
144
|
- lib/audioinfo.rb
|
124
145
|
- lib/audioinfo/album.rb
|
125
146
|
- lib/audioinfo/mpcinfo.rb
|
147
|
+
- lib/audioinfo/case_insensitive_hash.rb
|
126
148
|
- test/mpcinfo.rb
|
149
|
+
- test/test_helper.rb
|
150
|
+
- test/test_case_insensitive_hash.rb
|
151
|
+
- test/test_audioinfo.rb
|
127
152
|
- .gemtest
|
128
153
|
homepage: http://ruby-audioinfo.rubyforge.org
|
129
154
|
licenses: []
|
155
|
+
metadata: {}
|
130
156
|
post_install_message:
|
131
157
|
rdoc_options:
|
132
158
|
- --main
|
@@ -134,22 +160,23 @@ rdoc_options:
|
|
134
160
|
require_paths:
|
135
161
|
- lib
|
136
162
|
required_ruby_version: !ruby/object:Gem::Requirement
|
137
|
-
none: false
|
138
163
|
requirements:
|
139
|
-
- -
|
164
|
+
- - '>='
|
140
165
|
- !ruby/object:Gem::Version
|
141
166
|
version: '0'
|
142
167
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
143
|
-
none: false
|
144
168
|
requirements:
|
145
|
-
- -
|
169
|
+
- - '>='
|
146
170
|
- !ruby/object:Gem::Version
|
147
171
|
version: '0'
|
148
172
|
requirements: []
|
149
173
|
rubyforge_project: ruby-audioinfo
|
150
|
-
rubygems_version:
|
174
|
+
rubygems_version: 2.0.0
|
151
175
|
signing_key:
|
152
|
-
specification_version:
|
176
|
+
specification_version: 4
|
153
177
|
summary: ruby-audioinfo glue together various audio ruby libraries and presents a
|
154
178
|
unified API to the developper
|
155
|
-
test_files:
|
179
|
+
test_files:
|
180
|
+
- test/test_helper.rb
|
181
|
+
- test/test_case_insensitive_hash.rb
|
182
|
+
- test/test_audioinfo.rb
|