dtas 0.3.0 → 0.4.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 +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
|