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.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/Documentation/GNUmakefile +2 -0
  3. data/Documentation/dtas-player_protocol.txt +28 -1
  4. data/Documentation/dtas-splitfx.txt +167 -0
  5. data/Documentation/dtas-tl.txt +77 -0
  6. data/GIT-VERSION-GEN +2 -1
  7. data/GNUmakefile +1 -1
  8. data/README +2 -1
  9. data/Rakefile +7 -0
  10. data/bin/dtas-console +11 -1
  11. data/bin/dtas-splitfx +40 -0
  12. data/bin/dtas-tl +73 -0
  13. data/examples/README +3 -0
  14. data/examples/splitfx.sample.yml +19 -0
  15. data/lib/dtas/format.rb +11 -0
  16. data/lib/dtas/pipe.rb +0 -3
  17. data/lib/dtas/player.rb +38 -11
  18. data/lib/dtas/player/client_handler.rb +94 -7
  19. data/lib/dtas/process.rb +25 -3
  20. data/lib/dtas/sink.rb +0 -3
  21. data/lib/dtas/source/sox.rb +2 -1
  22. data/lib/dtas/splitfx.rb +342 -0
  23. data/lib/dtas/tracklist.rb +130 -0
  24. data/test/helper.rb +14 -1
  25. data/test/player_integration.rb +5 -3
  26. data/test/test_buffer.rb +4 -2
  27. data/test/test_env.rb +55 -0
  28. data/test/test_format.rb +1 -1
  29. data/test/test_format_change.rb +1 -1
  30. data/test/test_player.rb +1 -1
  31. data/test/test_player_client_handler.rb +1 -1
  32. data/test/test_player_integration.rb +3 -2
  33. data/test/test_process.rb +1 -1
  34. data/test/test_rg_integration.rb +4 -5
  35. data/test/test_rg_state.rb +1 -1
  36. data/test/test_sink.rb +1 -1
  37. data/test/test_sink_pipe_size.rb +1 -1
  38. data/test/test_sink_tee_integration.rb +1 -1
  39. data/test/test_source_av.rb +1 -1
  40. data/test/test_source_sox.rb +1 -1
  41. data/test/test_splitfx.rb +79 -0
  42. data/test/test_tracklist.rb +76 -0
  43. data/test/test_unixserver.rb +1 -1
  44. data/test/test_util.rb +1 -1
  45. 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
@@ -74,8 +74,10 @@ module PlayerIntegration
74
74
  end
75
75
 
76
76
  def teardown
77
- Process.kill(:TERM, @pid) if @pid
78
- Process.waitall
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 < Minitest::Unit::TestCase
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
@@ -4,7 +4,7 @@ require './test/helper'
4
4
  require 'tempfile'
5
5
  require 'dtas/format'
6
6
 
7
- class TestFormat < Minitest::Unit::TestCase
7
+ class TestFormat < Testcase
8
8
  def test_initialize
9
9
  fmt = DTAS::Format.new
10
10
  assert_equal %w(-ts32 -c2 -r44100), fmt.to_sox_arg
@@ -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 < Minitest::Unit::TestCase
5
+ class TestFormatChange < Testcase
6
6
  include PlayerIntegration
7
7
 
8
8
  def test_format_change
data/test/test_player.rb CHANGED
@@ -4,7 +4,7 @@ require './test/helper'
4
4
  require 'tempfile'
5
5
  require 'dtas/player'
6
6
 
7
- class TestPlayer < Minitest::Unit::TestCase
7
+ class TestPlayer < Testcase
8
8
  def setup
9
9
  @player = nil
10
10
  tmp = Tempfile.new(%w(dtas-player-test .sock))
@@ -3,7 +3,7 @@
3
3
  require './test/helper'
4
4
  require 'dtas/player'
5
5
 
6
- class TestPlayerClientHandler < Minitest::Unit::TestCase
6
+ class TestPlayerClientHandler < Testcase
7
7
  class MockIO < Array
8
8
  alias emit push
9
9
  end
@@ -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 < Minitest::Unit::TestCase
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 command='echo -$FOO- > #{tmp.path}'")
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
@@ -2,7 +2,7 @@
2
2
  # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
3
3
  require './test/helper'
4
4
  require 'dtas/process'
5
- class TestProcess < Minitest::Unit::TestCase
5
+ class TestProcess < Testcase
6
6
  include DTAS::Process
7
7
 
8
8
  def test_encoding
@@ -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 < Minitest::Unit::TestCase
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
- assert_empty cur["current"]["env"]["RGFX"]
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
@@ -3,7 +3,7 @@
3
3
  require './test/helper'
4
4
  require 'dtas/rg_state'
5
5
 
6
- class TestRGState < Minitest::Unit::TestCase
6
+ class TestRGState < Testcase
7
7
 
8
8
  def test_rg_state
9
9
  rg = DTAS::RGState.new
data/test/test_sink.rb CHANGED
@@ -4,7 +4,7 @@ require './test/helper'
4
4
  require 'dtas/sink'
5
5
  require 'yaml'
6
6
 
7
- class TestSink < Minitest::Unit::TestCase
7
+ class TestSink < Testcase
8
8
  def test_serialize_reload
9
9
  sink = DTAS::Sink.new
10
10
  sink.name = "DAC"
@@ -3,7 +3,7 @@
3
3
  begin
4
4
  require 'io/splice'
5
5
  require './test/player_integration'
6
- class TestSinkPipeSizeIntegration < Minitest::Unit::TestCase
6
+ class TestSinkPipeSizeIntegration < Testcase
7
7
  include PlayerIntegration
8
8
 
9
9
  def test_sink_pipe_size_integration
@@ -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 < Minitest::Unit::TestCase
4
+ class TestSinkTeeIntegration < Testcase
5
5
  include PlayerIntegration
6
6
 
7
7
  def test_tee_integration
@@ -4,7 +4,7 @@ require './test/helper'
4
4
  require 'dtas/source/av'
5
5
  require 'tempfile'
6
6
 
7
- class TestSourceAv < Minitest::Unit::TestCase
7
+ class TestSourceAv < Testcase
8
8
  def teardown
9
9
  @tempfiles.each { |tmp| tmp.close! }
10
10
  end
@@ -4,7 +4,7 @@ require './test/helper'
4
4
  require 'dtas/source/sox'
5
5
  require 'tempfile'
6
6
 
7
- class TestSource < Minitest::Unit::TestCase
7
+ class TestSource < Testcase
8
8
  def teardown
9
9
  @tempfiles.each { |tmp| tmp.close! }
10
10
  end
@@ -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