dtas 0.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gemtest +0 -0
- data/.gitignore +9 -0
- data/.rsync_doc +3 -0
- data/COPYING +674 -0
- data/Documentation/.gitignore +3 -0
- data/Documentation/GNUmakefile +46 -0
- data/Documentation/dtas-console.txt +42 -0
- data/Documentation/dtas-ctl.txt +64 -0
- data/Documentation/dtas-cueedit.txt +24 -0
- data/Documentation/dtas-enq.txt +29 -0
- data/Documentation/dtas-msinkctl.txt +45 -0
- data/Documentation/dtas-player.txt +110 -0
- data/Documentation/dtas-player_effects.txt +45 -0
- data/Documentation/dtas-player_protocol.txt +181 -0
- data/Documentation/dtas-sinkedit.txt +41 -0
- data/Documentation/dtas-sourceedit.txt +33 -0
- data/Documentation/dtas-xdelay.txt +57 -0
- data/Documentation/troubleshooting.txt +13 -0
- data/GIT-VERSION-GEN +30 -0
- data/GNUmakefile +9 -0
- data/HACKING +12 -0
- data/INSTALL +53 -0
- data/README +103 -0
- data/Rakefile +97 -0
- data/TODO +4 -0
- data/bin/dtas-console +160 -0
- data/bin/dtas-ctl +10 -0
- data/bin/dtas-cueedit +78 -0
- data/bin/dtas-enq +13 -0
- data/bin/dtas-msinkctl +51 -0
- data/bin/dtas-player +34 -0
- data/bin/dtas-sinkedit +58 -0
- data/bin/dtas-sourceedit +48 -0
- data/bin/dtas-xdelay +85 -0
- data/dtas-linux.gemspec +18 -0
- data/dtas-mpris.gemspec +16 -0
- data/examples/dtas_state.yml +18 -0
- data/lib/dtas.rb +7 -0
- data/lib/dtas/buffer.rb +90 -0
- data/lib/dtas/buffer/read_write.rb +102 -0
- data/lib/dtas/buffer/splice.rb +142 -0
- data/lib/dtas/command.rb +43 -0
- data/lib/dtas/compat_onenine.rb +18 -0
- data/lib/dtas/disclaimer.rb +18 -0
- data/lib/dtas/format.rb +151 -0
- data/lib/dtas/pipe.rb +39 -0
- data/lib/dtas/player.rb +393 -0
- data/lib/dtas/player/client_handler.rb +463 -0
- data/lib/dtas/process.rb +87 -0
- data/lib/dtas/replaygain.rb +41 -0
- data/lib/dtas/rg_state.rb +99 -0
- data/lib/dtas/serialize.rb +9 -0
- data/lib/dtas/sigevent.rb +10 -0
- data/lib/dtas/sigevent/efd.rb +20 -0
- data/lib/dtas/sigevent/pipe.rb +28 -0
- data/lib/dtas/sink.rb +121 -0
- data/lib/dtas/source.rb +147 -0
- data/lib/dtas/source/command.rb +40 -0
- data/lib/dtas/source/common.rb +14 -0
- data/lib/dtas/source/mp3.rb +37 -0
- data/lib/dtas/state_file.rb +33 -0
- data/lib/dtas/unix_accepted.rb +76 -0
- data/lib/dtas/unix_client.rb +51 -0
- data/lib/dtas/unix_server.rb +110 -0
- data/lib/dtas/util.rb +15 -0
- data/lib/dtas/writable_iter.rb +22 -0
- data/perl/dtas-graph +129 -0
- data/pkg.mk +26 -0
- data/setup.rb +1586 -0
- data/test/covshow.rb +30 -0
- data/test/helper.rb +76 -0
- data/test/player_integration.rb +121 -0
- data/test/test_buffer.rb +216 -0
- data/test/test_format.rb +61 -0
- data/test/test_format_change.rb +49 -0
- data/test/test_player.rb +47 -0
- data/test/test_player_client_handler.rb +86 -0
- data/test/test_player_integration.rb +220 -0
- data/test/test_rg_integration.rb +117 -0
- data/test/test_rg_state.rb +32 -0
- data/test/test_sink.rb +32 -0
- data/test/test_sink_tee_integration.rb +34 -0
- data/test/test_source.rb +102 -0
- data/test/test_unixserver.rb +66 -0
- data/test/test_util.rb +15 -0
- metadata +208 -0
@@ -0,0 +1,49 @@
|
|
1
|
+
# -*- encoding: binary -*-
|
2
|
+
# Copyright (C) 2013, Eric Wong <normalperson@yhbt.net>
|
3
|
+
# License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
|
4
|
+
require './test/player_integration'
|
5
|
+
require 'tmpdir'
|
6
|
+
class TestFormatChange < Minitest::Unit::TestCase
|
7
|
+
include PlayerIntegration
|
8
|
+
|
9
|
+
def test_format_change
|
10
|
+
s = client_socket
|
11
|
+
default_pid = default_sink_pid(s)
|
12
|
+
Dir.mktmpdir do |dir|
|
13
|
+
d = "#{dir}/dump.$CHANNELS.$RATE"
|
14
|
+
f44100 = File.open("#{dir}/dump.2.44100", IO::RDWR|IO::CREAT)
|
15
|
+
f88200 = File.open("#{dir}/dump.2.88200", IO::RDWR|IO::CREAT)
|
16
|
+
s.preq("sink ed dump active=true command='cat > #{d}'")
|
17
|
+
assert_equal "OK", s.readpartial(666)
|
18
|
+
noise, len = tmp_noise
|
19
|
+
s.preq(%W(enq #{noise.path}))
|
20
|
+
assert_equal "OK", s.readpartial(666)
|
21
|
+
wait_files_not_empty(default_pid, f44100)
|
22
|
+
|
23
|
+
s.preq("format rate=88200")
|
24
|
+
assert_equal "OK", s.readpartial(666)
|
25
|
+
|
26
|
+
wait_files_not_empty(f88200)
|
27
|
+
|
28
|
+
dethrottle_decoder(s)
|
29
|
+
|
30
|
+
Timeout.timeout(len) do
|
31
|
+
begin
|
32
|
+
s.preq("current")
|
33
|
+
cur = YAML.load(s.readpartial(6666))
|
34
|
+
end while cur["sinks"] && sleep(0.01)
|
35
|
+
end
|
36
|
+
|
37
|
+
c = "sox -R -ts32 -c2 -r88200 #{dir}/dump.2.88200 " \
|
38
|
+
"-ts32 -c2 -r44100 #{dir}/part2"
|
39
|
+
assert(system(c), c)
|
40
|
+
|
41
|
+
c = "sox -R -ts32 -c2 -r44100 #{dir}/dump.2.44100 " \
|
42
|
+
"-ts32 -c2 -r44100 #{dir}/part2 #{dir}/res.sox"
|
43
|
+
assert(system(c), c)
|
44
|
+
|
45
|
+
assert_equal `soxi -s #{dir}/res.sox`, `soxi -s #{noise.path}`
|
46
|
+
File.unlink(*Dir["#{dir}/*"].to_a)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
data/test/test_player.rb
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
# -*- encoding: binary -*-
|
2
|
+
# Copyright (C) 2013, Eric Wong <normalperson@yhbt.net>
|
3
|
+
# License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
|
4
|
+
require './test/helper'
|
5
|
+
require 'tempfile'
|
6
|
+
require 'dtas/player'
|
7
|
+
|
8
|
+
class TestPlayer < Minitest::Unit::TestCase
|
9
|
+
def setup
|
10
|
+
@player = nil
|
11
|
+
tmp = Tempfile.new(%w(dtas-player-test .sock))
|
12
|
+
@path = tmp.path
|
13
|
+
File.unlink(@path)
|
14
|
+
end
|
15
|
+
|
16
|
+
def teardown
|
17
|
+
@player.close if @player
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_player_new
|
21
|
+
player = DTAS::Player.new
|
22
|
+
player.socket = @path
|
23
|
+
player.bind
|
24
|
+
assert File.socket?(@path)
|
25
|
+
ensure
|
26
|
+
player.close
|
27
|
+
refute File.socket?(@path)
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_player_serialize
|
31
|
+
@player = DTAS::Player.new
|
32
|
+
@player.socket = @path
|
33
|
+
@player.bind
|
34
|
+
hash = @player.to_hsh
|
35
|
+
assert_equal({"socket" => @path}, hash)
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_player_serialize_format
|
39
|
+
fmt = DTAS::Format.new
|
40
|
+
fmt.type = "f32"
|
41
|
+
fmt.rate = 48000
|
42
|
+
player = DTAS::Player.load("format" => fmt.to_hsh)
|
43
|
+
fhash = player.to_hsh["format"]
|
44
|
+
assert_equal "f32", fhash["type"]
|
45
|
+
assert_equal 48000, fhash["rate"]
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
# -*- encoding: binary -*-
|
2
|
+
# Copyright (C) 2013, Eric Wong <normalperson@yhbt.net>
|
3
|
+
# License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
|
4
|
+
require './test/helper'
|
5
|
+
require 'dtas/player'
|
6
|
+
|
7
|
+
class TestPlayerClientHandler < Minitest::Unit::TestCase
|
8
|
+
class MockIO < Array
|
9
|
+
alias emit push
|
10
|
+
end
|
11
|
+
|
12
|
+
include DTAS::Player::ClientHandler
|
13
|
+
|
14
|
+
def setup
|
15
|
+
@sinks = {}
|
16
|
+
@io = MockIO.new
|
17
|
+
@srv = nil # unused mock
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_delete
|
21
|
+
@sinks["default"] = DTAS::Sink.new
|
22
|
+
@targets = []
|
23
|
+
sink_handler(@io, %w(rm default))
|
24
|
+
assert @sinks.empty?
|
25
|
+
assert_equal %w(OK), @io.to_a
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_delete_noexist
|
29
|
+
sink_handler(@io, %w(rm default))
|
30
|
+
assert @sinks.empty?
|
31
|
+
assert_equal ["ERR default not found"], @io.to_a
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_env
|
35
|
+
sink_handler(@io, %w(ed default env.FOO=bar))
|
36
|
+
assert_equal "bar", @sinks["default"].env["FOO"]
|
37
|
+
sink_handler(@io, %w(ed default env.FOO=))
|
38
|
+
assert_equal "", @sinks["default"].env["FOO"]
|
39
|
+
sink_handler(@io, %w(ed default env#FOO))
|
40
|
+
assert_nil @sinks["default"].env["FOO"]
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_sink_ed
|
44
|
+
command = 'sox -t $SOX_FILETYPE -r $RATE -c $CHANNELS - \
|
45
|
+
-t s$SINK_BITS -r $SINK_RATE -c $SINK_CHANNELS - | \
|
46
|
+
aplay -D hw:DAC_1 -v -q -M --buffer-size=500000 --period-size=500 \
|
47
|
+
--disable-softvol --start-delay=100 \
|
48
|
+
--disable-format --disable-resample --disable-channels \
|
49
|
+
-t raw -c $SINK_CHANNELS -f S${SINK_BITS}_3LE -r $SINK_RATE
|
50
|
+
'
|
51
|
+
sink_handler(@io, %W(ed foo command=#{command}))
|
52
|
+
assert_equal command, @sinks["foo"].command
|
53
|
+
assert_empty @sinks["foo"].env
|
54
|
+
sink_handler(@io, %W(ed foo env.SINK_BITS=24))
|
55
|
+
sink_handler(@io, %W(ed foo env.SINK_CHANNELS=2))
|
56
|
+
sink_handler(@io, %W(ed foo env.SINK_RATE=48000))
|
57
|
+
expect = {
|
58
|
+
"SINK_BITS" => "24",
|
59
|
+
"SINK_CHANNELS" => "2",
|
60
|
+
"SINK_RATE" => "48000",
|
61
|
+
}
|
62
|
+
assert_equal expect, @sinks["foo"].env
|
63
|
+
@io.all? { |s| assert_equal "OK", s }
|
64
|
+
assert_equal 4, @io.size
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_cat
|
68
|
+
sink = DTAS::Sink.new
|
69
|
+
sink.name = "default"
|
70
|
+
sink.command += "dither -s"
|
71
|
+
@sinks["default"] = sink
|
72
|
+
sink_handler(@io, %W(cat default))
|
73
|
+
assert_equal 1, @io.size
|
74
|
+
hsh = YAML.load(@io[0])
|
75
|
+
assert_kind_of Hash, hsh
|
76
|
+
assert_equal "default", hsh["name"]
|
77
|
+
assert_match("dither -s", hsh["command"])
|
78
|
+
end
|
79
|
+
|
80
|
+
def test_ls
|
81
|
+
expect = %w(a b c d)
|
82
|
+
expect.each { |s| @sinks[s] = true }
|
83
|
+
sink_handler(@io, %W(ls))
|
84
|
+
assert_equal expect, Shellwords.split(@io[0])
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,220 @@
|
|
1
|
+
# -*- encoding: binary -*-
|
2
|
+
# Copyright (C) 2013, Eric Wong <normalperson@yhbt.net>
|
3
|
+
# License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
|
4
|
+
require './test/player_integration'
|
5
|
+
class TestPlayerIntegration < Minitest::Unit::TestCase
|
6
|
+
include PlayerIntegration
|
7
|
+
|
8
|
+
def test_cmd_rate
|
9
|
+
pid = fork do
|
10
|
+
@fmt.to_env.each { |k,v| ENV[k] = v }
|
11
|
+
exec("sox -n $SOXFMT - synth 3 pinknoise | #@cmd")
|
12
|
+
end
|
13
|
+
t = Time.now
|
14
|
+
_, _ = Process.waitpid2(pid)
|
15
|
+
elapsed = Time.now - t
|
16
|
+
assert_in_delta 3.0, elapsed, 0.5
|
17
|
+
end if ENV["MATH_IS_HARD"] # ensure our @cmd timing is accurate
|
18
|
+
|
19
|
+
def test_sink_close_after_play
|
20
|
+
s = client_socket
|
21
|
+
@cmd = "cat >/dev/null"
|
22
|
+
default_pid = default_sink_pid(s)
|
23
|
+
Tempfile.open('junk') do |junk|
|
24
|
+
pink = "sox -n $SOXFMT - synth 0.0001 pinknoise | tee -i #{junk.path}"
|
25
|
+
s.send("enq-cmd \"#{pink}\"", Socket::MSG_EOR)
|
26
|
+
wait_files_not_empty(junk)
|
27
|
+
assert_equal "OK", s.readpartial(666)
|
28
|
+
end
|
29
|
+
wait_files_not_empty(default_pid)
|
30
|
+
pid = read_pid_file(default_pid)
|
31
|
+
wait_pid_dead(pid)
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_sink_killed_during_play
|
35
|
+
s = client_socket
|
36
|
+
default_pid = default_sink_pid(s)
|
37
|
+
cmd = Tempfile.new(%w(sox-cmd .pid))
|
38
|
+
pink = "echo $$ > #{cmd.path}; sox -n $SOXFMT - synth 100 pinknoise"
|
39
|
+
s.send("enq-cmd \"#{pink}\"", Socket::MSG_EOR)
|
40
|
+
assert_equal "OK", s.readpartial(666)
|
41
|
+
wait_files_not_empty(cmd, default_pid)
|
42
|
+
pid = read_pid_file(default_pid)
|
43
|
+
Process.kill(:KILL, pid)
|
44
|
+
cmd_pid = read_pid_file(cmd)
|
45
|
+
wait_pid_dead(cmd_pid)
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_sink_activate
|
49
|
+
s = client_socket
|
50
|
+
s.send("sink ls", Socket::MSG_EOR)
|
51
|
+
assert_equal "default", s.readpartial(666)
|
52
|
+
|
53
|
+
# setup two outputs
|
54
|
+
|
55
|
+
# make the default sink trickle
|
56
|
+
default_pid = Tempfile.new(%w(dtas-test .pid))
|
57
|
+
pf = "echo $$ >> #{default_pid.path}; "
|
58
|
+
s.send("sink ed default command='#{pf}#@cmd'", Socket::MSG_EOR)
|
59
|
+
assert_equal "OK", s.readpartial(666)
|
60
|
+
|
61
|
+
# make a sleepy sink trickle, too
|
62
|
+
sleepy_pid = Tempfile.new(%w(dtas-test .pid))
|
63
|
+
pf = "echo $$ >> #{sleepy_pid.path};"
|
64
|
+
s.send("sink ed sleepy command='#{pf}#@cmd' active=true", Socket::MSG_EOR)
|
65
|
+
assert_equal "OK", s.readpartial(666)
|
66
|
+
|
67
|
+
# ensure both sinks were created
|
68
|
+
s.send("sink ls", Socket::MSG_EOR)
|
69
|
+
assert_equal "default sleepy", s.readpartial(666)
|
70
|
+
|
71
|
+
# generate pinknoise
|
72
|
+
pinknoise = "sox -n -r 44100 -c 2 -t s32 - synth 0 pinknoise"
|
73
|
+
s.send("enq-cmd \"#{pinknoise}\"", Socket::MSG_EOR)
|
74
|
+
assert_equal "OK", s.readpartial(666)
|
75
|
+
|
76
|
+
# wait for sinks to start
|
77
|
+
wait_files_not_empty(sleepy_pid, default_pid)
|
78
|
+
|
79
|
+
# deactivate sleepy sink and ensure it's gone
|
80
|
+
sleepy = File.read(sleepy_pid).to_i
|
81
|
+
assert_operator sleepy, :>, 0
|
82
|
+
Process.kill(0, sleepy)
|
83
|
+
s.send("sink ed sleepy active=false", Socket::MSG_EOR)
|
84
|
+
assert_equal "OK", s.readpartial(666)
|
85
|
+
wait_pid_dead(sleepy)
|
86
|
+
|
87
|
+
# ensure default sink is still alive
|
88
|
+
default = File.read(default_pid).to_i
|
89
|
+
assert_operator default, :>, 0
|
90
|
+
Process.kill(0, default)
|
91
|
+
|
92
|
+
# restart sleepy sink
|
93
|
+
sleepy_pid.sync = true
|
94
|
+
sleepy_pid.seek(0)
|
95
|
+
sleepy_pid.truncate(0)
|
96
|
+
s.send("sink ed sleepy active=true", Socket::MSG_EOR)
|
97
|
+
assert_equal "OK", s.readpartial(666)
|
98
|
+
|
99
|
+
# wait for sleepy sink
|
100
|
+
wait_files_not_empty(sleepy_pid)
|
101
|
+
|
102
|
+
# check sleepy restarted
|
103
|
+
sleepy = File.read(sleepy_pid).to_i
|
104
|
+
assert_operator sleepy, :>, 0
|
105
|
+
Process.kill(0, sleepy)
|
106
|
+
|
107
|
+
# stop playing current track
|
108
|
+
s.send("skip", Socket::MSG_EOR)
|
109
|
+
assert_equal "OK", s.readpartial(666)
|
110
|
+
|
111
|
+
wait_pid_dead(sleepy)
|
112
|
+
wait_pid_dead(default)
|
113
|
+
end
|
114
|
+
|
115
|
+
def test_env_change
|
116
|
+
s = client_socket
|
117
|
+
tmp = Tempfile.new(%w(env .txt))
|
118
|
+
s.preq("sink ed default active=true command='cat >/dev/null'")
|
119
|
+
assert_equal "OK", s.readpartial(666)
|
120
|
+
|
121
|
+
s.preq("env FOO=BAR")
|
122
|
+
assert_equal "OK", s.readpartial(666)
|
123
|
+
s.preq(["enq-cmd", "echo $FOO | tee #{tmp.path}"])
|
124
|
+
assert_equal "OK", s.readpartial(666)
|
125
|
+
wait_files_not_empty(tmp)
|
126
|
+
assert_equal "BAR\n", tmp.read
|
127
|
+
|
128
|
+
tmp.rewind
|
129
|
+
tmp.truncate(0)
|
130
|
+
s.preq("env FOO#")
|
131
|
+
assert_equal "OK", s.readpartial(666)
|
132
|
+
s.preq(["enq-cmd", "echo -$FOO- | tee #{tmp.path}"])
|
133
|
+
assert_equal "OK", s.readpartial(666)
|
134
|
+
wait_files_not_empty(tmp)
|
135
|
+
assert_equal "--\n", tmp.read
|
136
|
+
end
|
137
|
+
|
138
|
+
def test_sink_env
|
139
|
+
s = client_socket
|
140
|
+
tmp = Tempfile.new(%w(env .txt))
|
141
|
+
s.preq("sink ed default active=true command='echo -$FOO- > #{tmp.path}'")
|
142
|
+
assert_equal "OK", s.readpartial(666)
|
143
|
+
|
144
|
+
s.preq("sink ed default env.FOO=BAR")
|
145
|
+
assert_equal "OK", s.readpartial(666)
|
146
|
+
s.preq(["enq-cmd", "echo HI"])
|
147
|
+
assert_equal "OK", s.readpartial(666)
|
148
|
+
wait_files_not_empty(tmp)
|
149
|
+
assert_equal "-BAR-\n", tmp.read
|
150
|
+
|
151
|
+
tmp.rewind
|
152
|
+
tmp.truncate(0)
|
153
|
+
s.preq("sink ed default env#FOO")
|
154
|
+
assert_equal "OK", s.readpartial(666)
|
155
|
+
|
156
|
+
Timeout.timeout(5) do
|
157
|
+
begin
|
158
|
+
s.preq("current")
|
159
|
+
yaml = s.readpartial(66666)
|
160
|
+
cur = YAML.load(yaml)
|
161
|
+
end while cur["sinks"] && sleep(0.01)
|
162
|
+
end
|
163
|
+
|
164
|
+
s.preq(["enq-cmd", "echo HI"])
|
165
|
+
assert_equal "OK", s.readpartial(666)
|
166
|
+
wait_files_not_empty(tmp)
|
167
|
+
assert_equal "--\n", tmp.read
|
168
|
+
end
|
169
|
+
|
170
|
+
def test_enq_head
|
171
|
+
s = client_socket
|
172
|
+
default_sink_pid(s)
|
173
|
+
dump = Tempfile.new(%W(d .sox))
|
174
|
+
s.preq "sink ed dump active=true command='sox $SOXFMT - #{dump.path}'"
|
175
|
+
assert_equal "OK", s.readpartial(666)
|
176
|
+
noise, len = tmp_noise
|
177
|
+
s.preq("enq-head #{noise.path}")
|
178
|
+
assert_equal "OK", s.readpartial(666)
|
179
|
+
s.preq("enq-head #{noise.path} 4")
|
180
|
+
assert_equal "OK", s.readpartial(666)
|
181
|
+
s.preq("enq-head #{noise.path} 3")
|
182
|
+
assert_equal "OK", s.readpartial(666)
|
183
|
+
dethrottle_decoder(s)
|
184
|
+
expect = Tempfile.new(%W(expect .sox))
|
185
|
+
|
186
|
+
c = "sox #{noise.path} -t sox '|sox #{noise.path} -p trim 3' " \
|
187
|
+
"-t sox '|sox #{noise.path} -p trim 4' #{expect.path}"
|
188
|
+
assert system(c)
|
189
|
+
Timeout.timeout(len) do
|
190
|
+
begin
|
191
|
+
s.preq("current")
|
192
|
+
yaml = s.readpartial(66666)
|
193
|
+
cur = YAML.load(yaml)
|
194
|
+
end while cur["sinks"] && sleep(0.01)
|
195
|
+
end
|
196
|
+
assert(system("cmp", dump.path, expect.path),
|
197
|
+
"files don't match #{dump.path} != #{expect.path}")
|
198
|
+
end
|
199
|
+
|
200
|
+
def test_cd_pwd
|
201
|
+
s = client_socket
|
202
|
+
pwd = Dir.pwd
|
203
|
+
|
204
|
+
s.preq("pwd")
|
205
|
+
assert_equal pwd, s.readpartial(6666)
|
206
|
+
|
207
|
+
s.preq("cd /")
|
208
|
+
assert_equal "OK", s.readpartial(6)
|
209
|
+
|
210
|
+
s.preq("pwd")
|
211
|
+
assert_equal "/", s.readpartial(6)
|
212
|
+
|
213
|
+
s.preq("cd /this-better-be-totally-non-existent-on-any-system-#{rand}")
|
214
|
+
err = s.readpartial(666)
|
215
|
+
assert_match(%r{\AERR }, err, err)
|
216
|
+
|
217
|
+
s.preq("pwd")
|
218
|
+
assert_equal "/", s.readpartial(6)
|
219
|
+
end
|
220
|
+
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
# -*- encoding: binary -*-
|
2
|
+
# Copyright (C) 2013, Eric Wong <normalperson@yhbt.net>
|
3
|
+
# License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
|
4
|
+
require './test/player_integration'
|
5
|
+
class TestRgIntegration < Minitest::Unit::TestCase
|
6
|
+
include PlayerIntegration
|
7
|
+
|
8
|
+
def tmp_pluck(len = 5)
|
9
|
+
pluck = Tempfile.open(%w(pluck .flac))
|
10
|
+
cmd = %W(sox -R -n -r44100 -c2 -C0 #{pluck.path} synth #{len} pluck)
|
11
|
+
assert system(*cmd), cmd
|
12
|
+
cmd = %W(metaflac
|
13
|
+
--set-tag=REPLAYGAIN_TRACK_GAIN=-2
|
14
|
+
--set-tag=REPLAYGAIN_ALBUM_GAIN=-3.0
|
15
|
+
--set-tag=REPLAYGAIN_TRACK_PEAK=0.666
|
16
|
+
--set-tag=REPLAYGAIN_ALBUM_PEAK=0.999
|
17
|
+
#{pluck.path})
|
18
|
+
assert system(*cmd), cmd
|
19
|
+
[ pluck, len ]
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_rg_changes_added
|
23
|
+
s = client_socket
|
24
|
+
pluck, len = tmp_pluck
|
25
|
+
|
26
|
+
# create the default sink, as well as a dumper
|
27
|
+
dumper = Tempfile.open(%w(dump .sox))
|
28
|
+
dump_pid = Tempfile.new(%w(dump .pid))
|
29
|
+
default_pid = default_sink_pid(s)
|
30
|
+
dump_cmd = "echo $$ > #{dump_pid.path}; sox $SOXFMT - #{dumper.path}"
|
31
|
+
s.send("sink ed dump active=true command='#{dump_cmd}'", Socket::MSG_EOR)
|
32
|
+
assert_equal("OK", s.readpartial(666))
|
33
|
+
|
34
|
+
# start playback!
|
35
|
+
s.send("enq \"#{pluck.path}\"", Socket::MSG_EOR)
|
36
|
+
assert_equal "OK", s.readpartial(666)
|
37
|
+
|
38
|
+
# wait for playback to start
|
39
|
+
yaml = cur = nil
|
40
|
+
Timeout.timeout(5) do
|
41
|
+
begin
|
42
|
+
s.send("current", Socket::MSG_EOR)
|
43
|
+
cur = YAML.load(yaml = s.readpartial(1666))
|
44
|
+
end while cur["current_offset"] == 0 && sleep(0.01)
|
45
|
+
end
|
46
|
+
|
47
|
+
assert_nil cur["current"]["env"]["RGFX"]
|
48
|
+
|
49
|
+
assert_equal DTAS::Format.new.rate * len, cur["current_expect"]
|
50
|
+
|
51
|
+
wait_files_not_empty(dump_pid)
|
52
|
+
pid = read_pid_file(dump_pid)
|
53
|
+
|
54
|
+
check_gain = proc do |expect, mode|
|
55
|
+
s.send("rg mode=#{mode}", Socket::MSG_EOR)
|
56
|
+
assert_equal "OK", s.readpartial(666)
|
57
|
+
Timeout.timeout(5) do
|
58
|
+
begin
|
59
|
+
s.send("current", Socket::MSG_EOR)
|
60
|
+
cur = YAML.load(yaml = s.readpartial(3666))
|
61
|
+
end while cur["current"]["env"]["RGFX"] !~ expect && sleep(0.01)
|
62
|
+
end
|
63
|
+
assert_match expect, cur["current"]["env"]["RGFX"]
|
64
|
+
end
|
65
|
+
|
66
|
+
check_gain.call(%r{vol -3dB}, "album_gain")
|
67
|
+
check_gain.call(%r{vol -2dB}, "track_gain")
|
68
|
+
check_gain.call(%r{vol 1\.3}, "track_peak")
|
69
|
+
check_gain.call(%r{vol 1\.0}, "album_peak")
|
70
|
+
|
71
|
+
s.send("rg preamp+=1", Socket::MSG_EOR)
|
72
|
+
assert_equal "OK", s.readpartial(666)
|
73
|
+
s.send("rg", Socket::MSG_EOR)
|
74
|
+
rg = YAML.load(yaml = s.readpartial(3666))
|
75
|
+
assert_equal 1, rg["preamp"]
|
76
|
+
|
77
|
+
s.send("rg preamp-=1", Socket::MSG_EOR)
|
78
|
+
assert_equal "OK", s.readpartial(666)
|
79
|
+
s.send("rg", Socket::MSG_EOR)
|
80
|
+
rg = YAML.load(yaml = s.readpartial(3666))
|
81
|
+
assert_nil rg["preamp"]
|
82
|
+
|
83
|
+
s.send("rg preamp=2", Socket::MSG_EOR)
|
84
|
+
assert_equal "OK", s.readpartial(666)
|
85
|
+
s.send("rg", Socket::MSG_EOR)
|
86
|
+
rg = YAML.load(yaml = s.readpartial(3666))
|
87
|
+
assert_equal 2, rg["preamp"]
|
88
|
+
|
89
|
+
s.send("rg preamp-=0.3", Socket::MSG_EOR)
|
90
|
+
assert_equal "OK", s.readpartial(666)
|
91
|
+
s.send("rg", Socket::MSG_EOR)
|
92
|
+
rg = YAML.load(yaml = s.readpartial(3666))
|
93
|
+
assert_equal 1.7, rg["preamp"]
|
94
|
+
|
95
|
+
s.send("rg preamp-=-0.3", Socket::MSG_EOR)
|
96
|
+
assert_equal "OK", s.readpartial(666)
|
97
|
+
s.send("rg", Socket::MSG_EOR)
|
98
|
+
rg = YAML.load(yaml = s.readpartial(3666))
|
99
|
+
assert_equal 2.0, rg["preamp"]
|
100
|
+
|
101
|
+
s.send("rg preamp-=+0.3", Socket::MSG_EOR)
|
102
|
+
assert_equal "OK", s.readpartial(666)
|
103
|
+
s.send("rg", Socket::MSG_EOR)
|
104
|
+
rg = YAML.load(yaml = s.readpartial(3666))
|
105
|
+
assert_equal 1.7, rg["preamp"]
|
106
|
+
|
107
|
+
dethrottle_decoder(s)
|
108
|
+
|
109
|
+
# ensure we did not change audio length
|
110
|
+
wait_pid_dead(pid, len)
|
111
|
+
samples = `soxi -s #{dumper.path}`.to_i
|
112
|
+
assert_equal cur["current_expect"], samples
|
113
|
+
assert_equal `soxi -d #{dumper.path}`, `soxi -d #{pluck.path}`
|
114
|
+
|
115
|
+
stop_playback(default_pid, s)
|
116
|
+
end
|
117
|
+
end
|