dtas 0.0.0
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/.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
|