1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
| | # Copyright (C) 2013-2014, Eric Wong <e@80x24.org> and all contributors
# License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
require_relative '../../dtas'
require_relative '../source'
require_relative '../replaygain'
require_relative '../xs'
# this is usually one input file
class DTAS::Source::Sox # :nodoc:
require_relative 'file'
include DTAS::Source::File
include DTAS::XS
extend DTAS::XS
SOX_DEFAULTS = COMMAND_DEFAULTS.merge(
"command" => 'exec sox "$INFILE" $SOXFMT - $TRIMFX $RGFX',
"tryorder" => 0,
)
# we use this to be less noisy when seeking a file
@last_failed = nil
def self.try_to_fail_harder(infile, s, cmd)
msg = nil
case s
when %r{\A0\s*\z} then msg = "detected zero samples"
when Process::Status then msg = "failed with #{s.exitstatus}"
end
if msg
return if @last_failed == infile
@last_failed = infile
return warn("`#{xs(cmd)}' #{msg}")
end
true
end
def initialize
command_init(SOX_DEFAULTS)
end
def try(infile, offset = nil)
err = ""
cmd = %W(soxi -s #{infile})
s = qx(@env.dup, cmd, err_str: err, no_raise: true)
return if err =~ /soxi FAIL formats:/
self.class.try_to_fail_harder(infile, s, cmd) or return
source_file_dup(infile, offset)
end
def format
@format ||= DTAS::Format.from_file(@env, @infile)
end
# This is the number of samples according to the samples in the source
# file itself, not the decoded output
def samples
@samples ||= qx(@env, %W(soxi -s #@infile)).to_i
rescue => e
warn e.message
0
end
# just run soxi -a
def __load_comments
tmp = {}
case @infile
when String
qx(@env, %W(soxi -a #@infile)).split(/\n/n).each do |line|
key, value = line.split(/=/n, 2)
key && value or next
# TODO: multi-line/multi-value/repeated tags
tmp[key.upcase] = value
end
end
tmp
end
def spawn(player_format, rg_state, opts)
raise "BUG: #{self.inspect}#spawn called twice" if @to_io
e = @env.merge!(player_format.to_env)
e["INFILE"] = @infile
# make sure these are visible to the "current" command...
e["TRIMFX"] = @offset ? "trim #@offset" : nil
e["RGFX"] = rg_state.effect(self) || nil
e.merge!(@rg.to_env) if @rg
@pid = dtas_spawn(e, command_string, opts)
end
def to_hsh
to_hash.delete_if { |k,v| v == SOX_DEFAULTS[k] }
end
def source_defaults
SOX_DEFAULTS
end
end
|