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.
Files changed (87) hide show
  1. checksums.yaml +7 -0
  2. data/.gemtest +0 -0
  3. data/.gitignore +9 -0
  4. data/.rsync_doc +3 -0
  5. data/COPYING +674 -0
  6. data/Documentation/.gitignore +3 -0
  7. data/Documentation/GNUmakefile +46 -0
  8. data/Documentation/dtas-console.txt +42 -0
  9. data/Documentation/dtas-ctl.txt +64 -0
  10. data/Documentation/dtas-cueedit.txt +24 -0
  11. data/Documentation/dtas-enq.txt +29 -0
  12. data/Documentation/dtas-msinkctl.txt +45 -0
  13. data/Documentation/dtas-player.txt +110 -0
  14. data/Documentation/dtas-player_effects.txt +45 -0
  15. data/Documentation/dtas-player_protocol.txt +181 -0
  16. data/Documentation/dtas-sinkedit.txt +41 -0
  17. data/Documentation/dtas-sourceedit.txt +33 -0
  18. data/Documentation/dtas-xdelay.txt +57 -0
  19. data/Documentation/troubleshooting.txt +13 -0
  20. data/GIT-VERSION-GEN +30 -0
  21. data/GNUmakefile +9 -0
  22. data/HACKING +12 -0
  23. data/INSTALL +53 -0
  24. data/README +103 -0
  25. data/Rakefile +97 -0
  26. data/TODO +4 -0
  27. data/bin/dtas-console +160 -0
  28. data/bin/dtas-ctl +10 -0
  29. data/bin/dtas-cueedit +78 -0
  30. data/bin/dtas-enq +13 -0
  31. data/bin/dtas-msinkctl +51 -0
  32. data/bin/dtas-player +34 -0
  33. data/bin/dtas-sinkedit +58 -0
  34. data/bin/dtas-sourceedit +48 -0
  35. data/bin/dtas-xdelay +85 -0
  36. data/dtas-linux.gemspec +18 -0
  37. data/dtas-mpris.gemspec +16 -0
  38. data/examples/dtas_state.yml +18 -0
  39. data/lib/dtas.rb +7 -0
  40. data/lib/dtas/buffer.rb +90 -0
  41. data/lib/dtas/buffer/read_write.rb +102 -0
  42. data/lib/dtas/buffer/splice.rb +142 -0
  43. data/lib/dtas/command.rb +43 -0
  44. data/lib/dtas/compat_onenine.rb +18 -0
  45. data/lib/dtas/disclaimer.rb +18 -0
  46. data/lib/dtas/format.rb +151 -0
  47. data/lib/dtas/pipe.rb +39 -0
  48. data/lib/dtas/player.rb +393 -0
  49. data/lib/dtas/player/client_handler.rb +463 -0
  50. data/lib/dtas/process.rb +87 -0
  51. data/lib/dtas/replaygain.rb +41 -0
  52. data/lib/dtas/rg_state.rb +99 -0
  53. data/lib/dtas/serialize.rb +9 -0
  54. data/lib/dtas/sigevent.rb +10 -0
  55. data/lib/dtas/sigevent/efd.rb +20 -0
  56. data/lib/dtas/sigevent/pipe.rb +28 -0
  57. data/lib/dtas/sink.rb +121 -0
  58. data/lib/dtas/source.rb +147 -0
  59. data/lib/dtas/source/command.rb +40 -0
  60. data/lib/dtas/source/common.rb +14 -0
  61. data/lib/dtas/source/mp3.rb +37 -0
  62. data/lib/dtas/state_file.rb +33 -0
  63. data/lib/dtas/unix_accepted.rb +76 -0
  64. data/lib/dtas/unix_client.rb +51 -0
  65. data/lib/dtas/unix_server.rb +110 -0
  66. data/lib/dtas/util.rb +15 -0
  67. data/lib/dtas/writable_iter.rb +22 -0
  68. data/perl/dtas-graph +129 -0
  69. data/pkg.mk +26 -0
  70. data/setup.rb +1586 -0
  71. data/test/covshow.rb +30 -0
  72. data/test/helper.rb +76 -0
  73. data/test/player_integration.rb +121 -0
  74. data/test/test_buffer.rb +216 -0
  75. data/test/test_format.rb +61 -0
  76. data/test/test_format_change.rb +49 -0
  77. data/test/test_player.rb +47 -0
  78. data/test/test_player_client_handler.rb +86 -0
  79. data/test/test_player_integration.rb +220 -0
  80. data/test/test_rg_integration.rb +117 -0
  81. data/test/test_rg_state.rb +32 -0
  82. data/test/test_sink.rb +32 -0
  83. data/test/test_sink_tee_integration.rb +34 -0
  84. data/test/test_source.rb +102 -0
  85. data/test/test_unixserver.rb +66 -0
  86. data/test/test_util.rb +15 -0
  87. 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
@@ -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