dtas 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Documentation/GNUmakefile +2 -0
- data/Documentation/dtas-player_protocol.txt +28 -1
- data/Documentation/dtas-splitfx.txt +167 -0
- data/Documentation/dtas-tl.txt +77 -0
- data/GIT-VERSION-GEN +2 -1
- data/GNUmakefile +1 -1
- data/README +2 -1
- data/Rakefile +7 -0
- data/bin/dtas-console +11 -1
- data/bin/dtas-splitfx +40 -0
- data/bin/dtas-tl +73 -0
- data/examples/README +3 -0
- data/examples/splitfx.sample.yml +19 -0
- data/lib/dtas/format.rb +11 -0
- data/lib/dtas/pipe.rb +0 -3
- data/lib/dtas/player.rb +38 -11
- data/lib/dtas/player/client_handler.rb +94 -7
- data/lib/dtas/process.rb +25 -3
- data/lib/dtas/sink.rb +0 -3
- data/lib/dtas/source/sox.rb +2 -1
- data/lib/dtas/splitfx.rb +342 -0
- data/lib/dtas/tracklist.rb +130 -0
- data/test/helper.rb +14 -1
- data/test/player_integration.rb +5 -3
- data/test/test_buffer.rb +4 -2
- data/test/test_env.rb +55 -0
- data/test/test_format.rb +1 -1
- data/test/test_format_change.rb +1 -1
- data/test/test_player.rb +1 -1
- data/test/test_player_client_handler.rb +1 -1
- data/test/test_player_integration.rb +3 -2
- data/test/test_process.rb +1 -1
- data/test/test_rg_integration.rb +4 -5
- data/test/test_rg_state.rb +1 -1
- data/test/test_sink.rb +1 -1
- data/test/test_sink_pipe_size.rb +1 -1
- data/test/test_sink_tee_integration.rb +1 -1
- data/test/test_source_av.rb +1 -1
- data/test/test_source_sox.rb +1 -1
- data/test/test_splitfx.rb +79 -0
- data/test/test_tracklist.rb +76 -0
- data/test/test_unixserver.rb +1 -1
- data/test/test_util.rb +1 -1
- metadata +23 -3
data/test/helper.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
# Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
|
2
2
|
# License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
|
3
3
|
$stdout.sync = $stderr.sync = Thread.abort_on_exception = true
|
4
|
+
require 'thread'
|
5
|
+
WAIT_ALL_MTX = Mutex.new
|
4
6
|
|
5
7
|
# fork-aware coverage data gatherer, see also test/covshow.rb
|
6
8
|
if ENV["COVERAGE"]
|
@@ -46,13 +48,24 @@ gem 'minitest'
|
|
46
48
|
require 'minitest/autorun'
|
47
49
|
require "tempfile"
|
48
50
|
|
51
|
+
Testcase = begin
|
52
|
+
Minitest::Test
|
53
|
+
rescue NameError
|
54
|
+
Minitest::Unit::TestCase
|
55
|
+
end
|
56
|
+
|
49
57
|
FIFOS = []
|
50
|
-
at_exit { FIFOS.each { |(pid,path)| File.unlink(path) if $$ == pid } }
|
51
58
|
def tmpfifo
|
52
59
|
tmp = Tempfile.new(%w(dtas-test .fifo))
|
53
60
|
path = tmp.path
|
54
61
|
tmp.close!
|
55
62
|
assert system(*%W(mkfifo #{path})), "mkfifo #{path}"
|
63
|
+
|
64
|
+
if FIFOS.empty?
|
65
|
+
at_exit do
|
66
|
+
FIFOS.each { |(pid,_path)| File.unlink(_path) if $$ == pid }
|
67
|
+
end
|
68
|
+
end
|
56
69
|
FIFOS << [ $$, path ]
|
57
70
|
path
|
58
71
|
end
|
data/test/player_integration.rb
CHANGED
@@ -74,8 +74,10 @@ module PlayerIntegration
|
|
74
74
|
end
|
75
75
|
|
76
76
|
def teardown
|
77
|
-
|
78
|
-
|
77
|
+
if @pid
|
78
|
+
Process.kill(:TERM, @pid)
|
79
|
+
Process.waitpid2(@pid)
|
80
|
+
end
|
79
81
|
refute File.exist?(@sock_path)
|
80
82
|
@state_tmp.close!
|
81
83
|
@out.close! if @out
|
@@ -92,7 +94,7 @@ module PlayerIntegration
|
|
92
94
|
def tmp_noise(len = 5)
|
93
95
|
noise = Tempfile.open(%w(junk .sox))
|
94
96
|
cmd = %W(sox -R -n -r44100 -c2 #{noise.path} synth #{len} pluck)
|
95
|
-
assert system(*cmd), cmd
|
97
|
+
assert system(*cmd), cmd.inspect
|
96
98
|
[ noise, len ]
|
97
99
|
end
|
98
100
|
|
data/test/test_buffer.rb
CHANGED
@@ -4,7 +4,7 @@ require './test/helper'
|
|
4
4
|
require 'stringio'
|
5
5
|
require 'dtas/buffer'
|
6
6
|
|
7
|
-
class TestBuffer <
|
7
|
+
class TestBuffer < Testcase
|
8
8
|
def teardown
|
9
9
|
@to_close.each { |io| io.close unless io.closed? }
|
10
10
|
end
|
@@ -118,6 +118,8 @@ class TestBuffer < Minitest::Unit::TestCase
|
|
118
118
|
assert_equal :wait_readable, buf.broadcast([a[1], b[1]])
|
119
119
|
assert_equal 5, buf.bytes_xfer
|
120
120
|
|
121
|
+
return unless b[1].respond_to?(:pipe_size)
|
122
|
+
|
121
123
|
b[1].nonblock = true
|
122
124
|
b[1].write('*' * b[1].pipe_size)
|
123
125
|
buf.wr.write "BYE"
|
@@ -175,7 +177,7 @@ class TestBuffer < Minitest::Unit::TestCase
|
|
175
177
|
buf.wr.write "HELLO"
|
176
178
|
assert_equal tmp, buf.broadcast(tmp)
|
177
179
|
assert_equal [a[1], b[1]], tmp
|
178
|
-
end
|
180
|
+
end if IO.method_defined?(:pipe_size)
|
179
181
|
|
180
182
|
def test_serialize
|
181
183
|
buf = new_buffer
|
data/test/test_env.rb
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
# Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
|
2
|
+
# License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
|
3
|
+
require_relative 'helper'
|
4
|
+
require 'dtas/process'
|
5
|
+
class TestEnv < Testcase
|
6
|
+
include DTAS::Process
|
7
|
+
def setup
|
8
|
+
@orig = ENV.to_hash
|
9
|
+
end
|
10
|
+
|
11
|
+
def teardown
|
12
|
+
ENV.clear
|
13
|
+
ENV.update(@orig)
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_expand
|
17
|
+
ENV["HELLO"] = 'HIHI'
|
18
|
+
expect = { "BLAH" => "HIHI/WORLD" }
|
19
|
+
opts = {}
|
20
|
+
|
21
|
+
env = { "BLAH" => "$HELLO/WORLD" }
|
22
|
+
assert_equal(expect, env_expand(env, opts))
|
23
|
+
|
24
|
+
env = { "BLAH" => "${HELLO}/WORLD" }
|
25
|
+
assert_equal(expect, env_expand(env, opts))
|
26
|
+
|
27
|
+
env = { "BLAH" => "$(echo $HELLO)/WORLD" }
|
28
|
+
assert_equal(expect, env_expand(env, opts))
|
29
|
+
|
30
|
+
env = { "BLAH" => "`echo $HELLO/WORLD`" }
|
31
|
+
assert_equal(expect, env_expand(env, opts))
|
32
|
+
|
33
|
+
env = { "BLAH" => "HIHI/WORLD" }
|
34
|
+
assert_equal(expect, env_expand(env, opts))
|
35
|
+
|
36
|
+
# disable expansion
|
37
|
+
env = expect = { "BLAH" => "`echo $HELLO/WORLD`" }
|
38
|
+
assert_equal(expect, env_expand(env, expand: false))
|
39
|
+
|
40
|
+
# numeric expansion always happens
|
41
|
+
env = { "BLAH" => 1 }
|
42
|
+
assert_equal({"BLAH"=>"1"}, env_expand(env, expand: false))
|
43
|
+
env = { "BLAH" => 1 }
|
44
|
+
assert_equal({"BLAH"=>"1"}, env_expand(env, {}))
|
45
|
+
|
46
|
+
expect = { "BLAH" => nil }
|
47
|
+
env = expect.dup
|
48
|
+
assert_equal expect, env_expand(env, expand:false)
|
49
|
+
assert_equal expect, env_expand(env, expand:true)
|
50
|
+
|
51
|
+
# recursive expansion
|
52
|
+
res = env_expand({"PATH"=>"$PATH"}, expand: true)
|
53
|
+
assert_equal ENV["PATH"], res["PATH"]
|
54
|
+
end
|
55
|
+
end
|
data/test/test_format.rb
CHANGED
data/test/test_format_change.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
# License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
|
3
3
|
require './test/player_integration'
|
4
4
|
require 'tmpdir'
|
5
|
-
class TestFormatChange <
|
5
|
+
class TestFormatChange < Testcase
|
6
6
|
include PlayerIntegration
|
7
7
|
|
8
8
|
def test_format_change
|
data/test/test_player.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
|
2
2
|
# License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
|
3
3
|
require './test/player_integration'
|
4
|
-
class TestPlayerIntegration <
|
4
|
+
class TestPlayerIntegration < Testcase
|
5
5
|
include PlayerIntegration
|
6
6
|
|
7
7
|
def test_cmd_rate
|
@@ -124,7 +124,8 @@ class TestPlayerIntegration < Minitest::Unit::TestCase
|
|
124
124
|
def test_sink_env
|
125
125
|
s = client_socket
|
126
126
|
tmp = Tempfile.new(%w(env .txt))
|
127
|
-
s.req_ok("sink ed default active=true
|
127
|
+
s.req_ok("sink ed default active=true " \
|
128
|
+
"command='echo -$FOO- > #{tmp.path}; cat >/dev/null'")
|
128
129
|
|
129
130
|
s.req_ok("sink ed default env.FOO=BAR")
|
130
131
|
s.req_ok(["enq-cmd", "echo HI"])
|
data/test/test_process.rb
CHANGED
data/test/test_rg_integration.rb
CHANGED
@@ -1,20 +1,20 @@
|
|
1
1
|
# Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
|
2
2
|
# License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
|
3
3
|
require './test/player_integration'
|
4
|
-
class TestRgIntegration <
|
4
|
+
class TestRgIntegration < Testcase
|
5
5
|
include PlayerIntegration
|
6
6
|
|
7
7
|
def tmp_pluck(len = 5)
|
8
8
|
pluck = Tempfile.open(%w(pluck .flac))
|
9
9
|
cmd = %W(sox -R -n -r44100 -c2 -C0 #{pluck.path} synth #{len} pluck)
|
10
|
-
assert system(*cmd), cmd
|
10
|
+
assert system(*cmd), cmd.inspect
|
11
11
|
cmd = %W(metaflac
|
12
12
|
--set-tag=REPLAYGAIN_TRACK_GAIN=-2
|
13
13
|
--set-tag=REPLAYGAIN_ALBUM_GAIN=-3.0
|
14
14
|
--set-tag=REPLAYGAIN_TRACK_PEAK=0.666
|
15
15
|
--set-tag=REPLAYGAIN_ALBUM_PEAK=0.999
|
16
16
|
#{pluck.path})
|
17
|
-
assert system(*cmd), cmd
|
17
|
+
assert system(*cmd), cmd.inspect
|
18
18
|
[ pluck, len ]
|
19
19
|
end
|
20
20
|
|
@@ -40,7 +40,7 @@ class TestRgIntegration < Minitest::Unit::TestCase
|
|
40
40
|
end while cur["current_offset"] == 0 && sleep(0.01)
|
41
41
|
end
|
42
42
|
|
43
|
-
|
43
|
+
assert_nil cur["current"]["env"]["RGFX"]
|
44
44
|
|
45
45
|
assert_equal DTAS::Format.new.rate * len, cur["current_expect"]
|
46
46
|
|
@@ -119,7 +119,6 @@ class TestRgIntegration < Minitest::Unit::TestCase
|
|
119
119
|
"REPLAYGAIN_ALBUM_GAIN" => "-3.0",
|
120
120
|
"REPLAYGAIN_TRACK_PEAK" => "0.666",
|
121
121
|
"REPLAYGAIN_ALBUM_PEAK" => "0.999",
|
122
|
-
"REPLAYGAIN_REFERENCE_LOUDNESS" => nil
|
123
122
|
}
|
124
123
|
assert_equal expect, rg
|
125
124
|
end
|
data/test/test_rg_state.rb
CHANGED
data/test/test_sink.rb
CHANGED
data/test/test_sink_pipe_size.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
|
2
2
|
# License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
|
3
3
|
require './test/player_integration'
|
4
|
-
class TestSinkTeeIntegration <
|
4
|
+
class TestSinkTeeIntegration < Testcase
|
5
5
|
include PlayerIntegration
|
6
6
|
|
7
7
|
def test_tee_integration
|
data/test/test_source_av.rb
CHANGED
data/test/test_source_sox.rb
CHANGED
@@ -0,0 +1,79 @@
|
|
1
|
+
# Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
|
2
|
+
# License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
|
3
|
+
require 'yaml'
|
4
|
+
require 'dtas/splitfx'
|
5
|
+
require 'thread'
|
6
|
+
require_relative 'helper'
|
7
|
+
|
8
|
+
class TestSplitfx < Testcase
|
9
|
+
def test_t2s
|
10
|
+
sfx = DTAS::SplitFX.new
|
11
|
+
sfx.instance_eval do
|
12
|
+
@infmt = DTAS::Format.load("rate"=>44100)
|
13
|
+
end
|
14
|
+
assert_equal 118554000, sfx.t2s_cdda('44:48.3')
|
15
|
+
assert_equal 118554030, sfx.t2s('44:48.3')
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_example
|
19
|
+
hash = YAML.load(File.read("examples/splitfx.sample.yml"))
|
20
|
+
sfx = DTAS::SplitFX.new
|
21
|
+
Dir.mktmpdir do |dir|
|
22
|
+
Dir.chdir(dir) do
|
23
|
+
# create a guitar pluck
|
24
|
+
cmd = '(for n in E2 A2 D3 G3 B3 E4; do '\
|
25
|
+
'sox -n -ts32 -c2 -r44100 - synth 4 pluck $n; done ) | ' \
|
26
|
+
'sox -ts32 -c2 -r44100 - foo.flac'
|
27
|
+
assert system(cmd), cmd.inspect
|
28
|
+
sfx.import(hash, {})
|
29
|
+
opts = { jobs: nil, silent: true }
|
30
|
+
|
31
|
+
# ensure default FLAC target works
|
32
|
+
WAIT_ALL_MTX.synchronize { sfx.run("flac", opts) }
|
33
|
+
expect = %w(1.flac 2.flac foo.flac)
|
34
|
+
assert_equal expect, Dir["*.flac"].sort
|
35
|
+
|
36
|
+
# compare results with expected output
|
37
|
+
res_cmd = "sox 1.flac 2.flac -ts32 -c2 -r44100 result.s32"
|
38
|
+
res_pid = fork { exec res_cmd }
|
39
|
+
exp_cmd = "sox foo.flac -ts32 -c2 -r44100 expect.s32 trim 4"
|
40
|
+
exp_pid = fork { exec exp_cmd }
|
41
|
+
_, s = Process.waitpid2(res_pid)
|
42
|
+
assert s.success?, "#{res_cmd}: #{s.inspect}"
|
43
|
+
_, s = Process.waitpid2(exp_pid)
|
44
|
+
assert s.success?, "#{exp_cmd}: #{s.inspect}"
|
45
|
+
cmp = "cmp result.s32 expect.s32"
|
46
|
+
assert system(cmp), cmp
|
47
|
+
|
48
|
+
# try Ogg Opus, use opusenc/opusdec for now since that's available
|
49
|
+
# in Debian 7.0 (sox.git currently has opusfile support, but that
|
50
|
+
# hasn't made it into Debian, yet)
|
51
|
+
if `which opusenc 2>/dev/null`.size > 0 &&
|
52
|
+
`which opusdec 2>/dev/null`.size > 0
|
53
|
+
err = $stderr.dup
|
54
|
+
begin
|
55
|
+
$stderr.reopen("/dev/null", "a")
|
56
|
+
WAIT_ALL_MTX.synchronize { sfx.run("opusenc", opts) }
|
57
|
+
ensure
|
58
|
+
$stderr.reopen(err)
|
59
|
+
end
|
60
|
+
|
61
|
+
# ensure opus lengths match flac ones, we decode using opusdec
|
62
|
+
# since sox does not yet have opus support in Debian 7.0
|
63
|
+
%w(1 2).each do |nr|
|
64
|
+
cmd = "opusdec #{nr}.opus #{nr}.wav 2>/dev/null"
|
65
|
+
assert system(cmd), cmd
|
66
|
+
assert_equal `soxi -D #{nr}.flac`, `soxi -D #{nr}.wav`
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
# ensure 16/44.1kHz FLAC works (CDDA-like)
|
71
|
+
File.unlink('1.flac', '2.flac')
|
72
|
+
WAIT_ALL_MTX.synchronize { sfx.run("flac-cdda", opts) }
|
73
|
+
%w(1 2).each do |nr|
|
74
|
+
assert_equal `soxi -D #{nr}.flac`, `soxi -D #{nr}.wav`
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
|
2
|
+
# License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
|
3
|
+
require_relative 'helper'
|
4
|
+
require 'dtas/tracklist'
|
5
|
+
class TestTracklist < Testcase
|
6
|
+
def test_tl_add_tracks
|
7
|
+
tl = DTAS::Tracklist.new
|
8
|
+
tl.add_track("/foo.flac")
|
9
|
+
assert_equal(%w(/foo.flac), tl.instance_variable_get(:@list))
|
10
|
+
|
11
|
+
oids = tl.tracks
|
12
|
+
assert_kind_of Array, oids
|
13
|
+
assert_equal 1, oids.size
|
14
|
+
assert_equal [ [ oids[0], "/foo.flac" ] ], tl.get_tracks(oids)
|
15
|
+
|
16
|
+
tl.add_track("/bar.flac")
|
17
|
+
assert_equal(%w(/bar.flac /foo.flac), tl.instance_variable_get(:@list))
|
18
|
+
|
19
|
+
tl.add_track("/after.flac", oids[0])
|
20
|
+
assert_equal(%w(/bar.flac /foo.flac /after.flac),
|
21
|
+
tl.instance_variable_get(:@list))
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_add_current
|
25
|
+
tl = DTAS::Tracklist.new
|
26
|
+
tl.instance_variable_get(:@list).replace(%w(a b c d e f g))
|
27
|
+
tl.add_track('/foo.flac', nil, true)
|
28
|
+
assert_equal '/foo.flac', tl.cur_track
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_advance_track
|
32
|
+
tl = DTAS::Tracklist.new
|
33
|
+
tl.instance_variable_get(:@list).replace(%w(a b c d e f g))
|
34
|
+
%w(a b c d e f g).each do |t|
|
35
|
+
assert_equal t, tl.advance_track[0]
|
36
|
+
end
|
37
|
+
assert_nil tl.advance_track
|
38
|
+
tl.repeat = true
|
39
|
+
assert_equal 'a', tl.advance_track[0]
|
40
|
+
end
|
41
|
+
|
42
|
+
def _build_mapping(tl)
|
43
|
+
tracks = tl.get_tracks(tl.tracks)
|
44
|
+
Hash[tracks.map { |(oid,name)| [ name, oid ] }]
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_goto
|
48
|
+
tl = DTAS::Tracklist.new
|
49
|
+
tl.instance_variable_get(:@list).replace(%w(a b c d e f g))
|
50
|
+
mapping = _build_mapping(tl)
|
51
|
+
assert_equal 'f', tl.go_to(mapping['f'])
|
52
|
+
assert_equal 'f', tl.advance_track[0]
|
53
|
+
assert_nil tl.go_to(1 << 128)
|
54
|
+
assert_equal 'g', tl.advance_track[0]
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_remove_track
|
58
|
+
tl = DTAS::Tracklist.new
|
59
|
+
tl.instance_variable_get(:@list).replace(%w(a b c d e f g))
|
60
|
+
mapping = _build_mapping(tl)
|
61
|
+
%w(a b c d e f g).each { |t| assert_kind_of Integer, mapping[t] }
|
62
|
+
|
63
|
+
tl.remove_track(mapping['a'])
|
64
|
+
assert_equal %w(b c d e f g), tl.instance_variable_get(:@list)
|
65
|
+
|
66
|
+
tl.remove_track(mapping['d'])
|
67
|
+
assert_equal %w(b c e f g), tl.instance_variable_get(:@list)
|
68
|
+
|
69
|
+
tl.remove_track(mapping['g'])
|
70
|
+
assert_equal %w(b c e f), tl.instance_variable_get(:@list)
|
71
|
+
|
72
|
+
# it'll be a while before OIDs require >128 bits, right?
|
73
|
+
tl.remove_track(1 << 128)
|
74
|
+
assert_equal %w(b c e f), tl.instance_variable_get(:@list), "no change"
|
75
|
+
end
|
76
|
+
end
|