dtas 0.0.0 → 0.1.I

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/.gitignore +1 -0
  3. data/Documentation/dtas-console.txt +15 -0
  4. data/Documentation/dtas-player_protocol.txt +5 -3
  5. data/Documentation/dtas-sourceedit.txt +14 -7
  6. data/GIT-VERSION-GEN +3 -3
  7. data/INSTALL +3 -3
  8. data/README +6 -5
  9. data/Rakefile +16 -7
  10. data/bin/dtas-console +48 -3
  11. data/bin/dtas-cueedit +1 -1
  12. data/bin/dtas-sinkedit +12 -28
  13. data/bin/dtas-sourceedit +15 -30
  14. data/lib/dtas.rb +1 -1
  15. data/lib/dtas/command.rb +0 -5
  16. data/lib/dtas/compat_onenine.rb +2 -2
  17. data/lib/dtas/disclaimer.rb +4 -3
  18. data/lib/dtas/edit_client.rb +48 -0
  19. data/lib/dtas/format.rb +2 -9
  20. data/lib/dtas/player.rb +64 -28
  21. data/lib/dtas/player/client_handler.rb +39 -20
  22. data/lib/dtas/process.rb +16 -15
  23. data/lib/dtas/replaygain.rb +19 -3
  24. data/lib/dtas/sink.rb +1 -2
  25. data/lib/dtas/source.rb +1 -141
  26. data/lib/dtas/source/av.rb +29 -0
  27. data/lib/dtas/source/av_ff_common.rb +127 -0
  28. data/lib/dtas/source/{command.rb → cmd.rb} +1 -1
  29. data/lib/dtas/source/ff.rb +30 -0
  30. data/lib/dtas/source/file.rb +94 -0
  31. data/lib/dtas/source/{mp3.rb → mp3gain.rb} +1 -1
  32. data/lib/dtas/source/sox.rb +114 -0
  33. data/lib/dtas/unix_client.rb +1 -9
  34. data/test/player_integration.rb +5 -17
  35. data/test/test_format.rb +10 -14
  36. data/test/test_format_change.rb +4 -8
  37. data/test/test_player_integration.rb +50 -62
  38. data/test/test_process.rb +33 -0
  39. data/test/test_rg_integration.rb +45 -35
  40. data/test/test_sink_pipe_size.rb +20 -0
  41. data/test/test_sink_tee_integration.rb +2 -4
  42. data/test/{test_source.rb → test_source_av.rb} +16 -16
  43. data/test/test_source_sox.rb +115 -0
  44. metadata +23 -12
  45. data/.rsync_doc +0 -3
@@ -0,0 +1,30 @@
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_relative '../../dtas'
5
+ require_relative 'av_ff_common'
6
+
7
+ # ffmpeg support
8
+ # note: only tested with the compatibility wrapper in the Debian 7.0 package
9
+ # (so still using avconv/avprobe)
10
+ class DTAS::Source::Ff # :nodoc:
11
+ include DTAS::Source::AvFfCommon
12
+
13
+ FF_DEFAULTS = COMMAND_DEFAULTS.merge(
14
+ "command" =>
15
+ 'ffmpeg -v error $SSPOS -i "$INFILE" $AMAP -f sox - |' \
16
+ 'sox -p $SOXFMT - $RGFX',
17
+
18
+ # I haven't tested this much since av is in Debian stable and ff is not
19
+ "tryorder" => 2,
20
+ )
21
+
22
+ def initialize
23
+ command_init(FF_DEFAULTS)
24
+ @av_ff_probe = "ffprobe"
25
+ end
26
+
27
+ def source_defaults
28
+ FF_DEFAULTS
29
+ end
30
+ end
@@ -0,0 +1,94 @@
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_relative '../../dtas'
5
+ require_relative '../source'
6
+ require_relative '../command'
7
+ require_relative '../format'
8
+ require_relative '../process'
9
+
10
+ module DTAS::Source::File # :nodoc:
11
+ attr_reader :infile
12
+ attr_reader :offset
13
+ attr_accessor :tryorder
14
+ require_relative 'common' # dtas/source/common
15
+ require_relative 'mp3gain'
16
+ include DTAS::Command
17
+ include DTAS::Process
18
+ include DTAS::Source::Common
19
+ include DTAS::Source::Mp3gain
20
+
21
+ FILE_SIVS = %w(infile comments command env) # for the "current" command
22
+ SRC_SIVS = %w(command env tryorder)
23
+
24
+ def source_file_dup(infile, offset)
25
+ rv = dup
26
+ rv.__file_init(infile, offset)
27
+ rv
28
+ end
29
+
30
+ def __file_init(infile, offset)
31
+ @env = @env.dup
32
+ @format = nil
33
+ @infile = infile
34
+ @offset = offset
35
+ @comments = nil
36
+ @samples = nil
37
+ @rg = nil
38
+ end
39
+
40
+ # this exists mainly to make the mpris interface easier, but it's not
41
+ # necessary, the mpris interface also knows the sample rate
42
+ def offset_us
43
+ (offset_samples / format.rate.to_f) * 1000000
44
+ end
45
+
46
+ # returns any offset in samples (relative to the original source file),
47
+ # likely zero unless seek was used
48
+ def offset_samples
49
+ return 0 unless @offset
50
+ case @offset
51
+ when /\A\d+s\z/
52
+ @offset.to_i
53
+ else
54
+ format.hhmmss_to_samples(@offset)
55
+ end
56
+ end
57
+
58
+ # A user may be downloading the file and start playing
59
+ # it before the download completes, this refreshes
60
+ def samples!
61
+ @samples = nil
62
+ samples
63
+ end
64
+
65
+ def comments
66
+ @comments ||= __load_comments
67
+ end
68
+
69
+ def to_hash
70
+ rv = ivars_to_hash(FILE_SIVS)
71
+ rv["samples"] = samples
72
+ rv
73
+ end
74
+
75
+ def replaygain
76
+ @rg ||= DTAS::ReplayGain.new(comments) ||
77
+ DTAS::ReplayGain.new(mp3gain_comments)
78
+ end
79
+
80
+ def to_source_cat
81
+ ivars_to_hash(SRC_SIVS)
82
+ end
83
+
84
+ def load!(src_hsh)
85
+ SRC_SIVS.each do |field|
86
+ val = src_hsh[field] and instance_variable_set("@#{field}", val)
87
+ end
88
+ end
89
+
90
+ def to_state_hash
91
+ defaults = source_defaults # see dtas/source/{av,sox}.rb
92
+ to_source_cat.delete_if { |k,v| v == defaults[k] }
93
+ end
94
+ end
@@ -3,7 +3,7 @@
3
3
  # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
4
4
  require_relative '../process'
5
5
 
6
- module DTAS::Source::Mp3 # :nodoc:
6
+ module DTAS::Source::Mp3gain # :nodoc:
7
7
  include DTAS::Process
8
8
  # we use dBFS = 1.0 as scale (not 32768)
9
9
  def __mp3gain_peak(str)
@@ -0,0 +1,114 @@
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_relative '../../dtas'
5
+ require_relative '../source'
6
+ require_relative '../replaygain'
7
+
8
+ # this is usually one input file
9
+ class DTAS::Source::Sox # :nodoc:
10
+ require_relative 'file'
11
+
12
+ include DTAS::Source::File
13
+
14
+ SOX_DEFAULTS = COMMAND_DEFAULTS.merge(
15
+ "command" => 'exec sox "$INFILE" $SOXFMT - $TRIMFX $RGFX',
16
+ "tryorder" => 0,
17
+ )
18
+
19
+ # we use this to be less noisy when seeking a file
20
+ @last_failed = nil
21
+ def self.try_to_fail_harder(infile, s, cmd)
22
+ msg = nil
23
+ case s
24
+ when %r{\A0\s*\z} then msg = "detected zero samples"
25
+ when Process::Status then msg = "failed with #{s.exitstatus}"
26
+ end
27
+ if msg
28
+ return if @last_failed == infile
29
+ @last_failed = infile
30
+ return warn("`#{Shellwords.join(cmd)}' #{msg}")
31
+ end
32
+ true
33
+ end
34
+
35
+ def initialize
36
+ command_init(SOX_DEFAULTS)
37
+ end
38
+
39
+ def try(infile, offset = nil)
40
+ err = ""
41
+ cmd = %W(soxi -s #{infile})
42
+ s = qx(@env, cmd, err_str: err, no_raise: true)
43
+ return if err =~ /soxi FAIL formats:/
44
+ self.class.try_to_fail_harder(infile, s, cmd) or return
45
+ source_file_dup(infile, offset)
46
+ end
47
+
48
+ def precision
49
+ qx(@env, %W(soxi -p #@infile), err: "/dev/null").to_i # sox.git f4562efd0aa3
50
+ rescue # fallback to parsing the whole output
51
+ s = qx(@env, %W(soxi #@infile), err: "/dev/null")
52
+ s =~ /Precision\s+:\s*(\d+)-bit/
53
+ v = $1.to_i
54
+ return v if v > 0
55
+ raise TypeError, "could not determine precision for #@infile"
56
+ end
57
+
58
+ def format
59
+ @format ||= begin
60
+ fmt = DTAS::Format.new
61
+ path = @infile
62
+ fmt.channels = qx(@env, %W(soxi -c #{path})).to_i
63
+ fmt.type = qx(@env, %W(soxi -t #{path})).strip
64
+ fmt.rate = qx(@env, %W(soxi -r #{path})).to_i
65
+ fmt.bits ||= precision
66
+ fmt
67
+ end
68
+ end
69
+
70
+ # This is the number of samples according to the samples in the source
71
+ # file itself, not the decoded output
72
+ def samples
73
+ @samples ||= qx(@env, %W(soxi -s #@infile)).to_i
74
+ rescue => e
75
+ warn e.message
76
+ 0
77
+ end
78
+
79
+ # just run soxi -a
80
+ def __load_comments
81
+ tmp = {}
82
+ case @infile
83
+ when String
84
+ qx(@env, %W(soxi -a #@infile)).split(/\n/).each do |line|
85
+ key, value = line.split(/=/, 2)
86
+ key && value or next
87
+ # TODO: multi-line/multi-value/repeated tags
88
+ tmp[key.upcase] = value
89
+ end
90
+ end
91
+ tmp
92
+ end
93
+
94
+ def spawn(player_format, rg_state, opts)
95
+ raise "BUG: #{self.inspect}#spawn called twice" if @to_io
96
+ e = @env.merge!(player_format.to_env)
97
+ e["INFILE"] = @infile
98
+
99
+ # make sure these are visible to the "current" command...
100
+ e["TRIMFX"] = @offset ? "trim #@offset" : nil
101
+ e["RGFX"] = rg_state.effect(self) || nil
102
+ e.merge!(@rg.to_env) if @rg
103
+
104
+ @pid = dtas_spawn(e, command_string, opts)
105
+ end
106
+
107
+ def to_hsh
108
+ to_hash.delete_if { |k,v| v == SOX_DEFAULTS[k] }
109
+ end
110
+
111
+ def source_defaults
112
+ SOX_DEFAULTS
113
+ end
114
+ end
@@ -14,15 +14,7 @@ class DTAS::UNIXClient # :nodoc:
14
14
  end
15
15
 
16
16
  def initialize(path = self.class.default_path)
17
- @to_io = begin
18
- raise if ENV["_DTAS_NOSEQPACKET"]
19
- Socket.new(:AF_UNIX, :SOCK_SEQPACKET, 0)
20
- rescue
21
- warn("get your operating system developers to support " \
22
- "SOCK_SEQPACKET for AF_UNIX sockets")
23
- warn("falling back to SOCK_DGRAM, reliability possibly compromised")
24
- Socket.new(:AF_UNIX, :SOCK_DGRAM, 0)
25
- end
17
+ @to_io = Socket.new(:AF_UNIX, :SOCK_SEQPACKET, 0)
26
18
  @to_io.connect(Socket.pack_sockaddr_un(path))
27
19
  end
28
20
 
@@ -4,6 +4,7 @@
4
4
  require './test/helper'
5
5
  require 'dtas/player'
6
6
  require 'dtas/state_file'
7
+ require 'dtas/unix_client'
7
8
  require 'yaml'
8
9
  require 'tempfile'
9
10
  require 'shellwords'
@@ -46,18 +47,8 @@ module PlayerIntegration
46
47
  end
47
48
  end
48
49
 
49
- module PlayerClient
50
- def preq(args)
51
- args = Shellwords.join(args) if Array === args
52
- send(args, Socket::MSG_EOR)
53
- end
54
- end
55
-
56
50
  def client_socket
57
- s = Socket.new(:AF_UNIX, :SOCK_SEQPACKET, 0)
58
- s.connect(Socket.pack_sockaddr_un(@sock_path))
59
- s.extend(PlayerClient)
60
- s
51
+ DTAS::UNIXClient.new(@sock_path)
61
52
  end
62
53
 
63
54
  def wait_pid_dead(pid, time = 5)
@@ -79,8 +70,7 @@ module PlayerIntegration
79
70
  def default_sink_pid(s)
80
71
  default_pid = Tempfile.new(%w(dtas-test .pid))
81
72
  pf = "echo $$ >> #{default_pid.path}; "
82
- s.send("sink ed default command='#{pf}#@cmd'", Socket::MSG_EOR)
83
- assert_equal "OK", s.readpartial(666)
73
+ s.req_ok("sink ed default command='#{pf}#@cmd'")
84
74
  default_pid
85
75
  end
86
76
 
@@ -108,13 +98,11 @@ module PlayerIntegration
108
98
  end
109
99
 
110
100
  def dethrottle_decoder(s)
111
- s.send("sink ed default active=false", Socket::MSG_EOR)
112
- assert_equal "OK", s.readpartial(666)
101
+ s.req_ok("sink ed default active=false")
113
102
  end
114
103
 
115
104
  def stop_playback(pid_file, s)
116
- s.send("skip", Socket::MSG_EOR)
117
- assert_equal "OK", s.readpartial(666)
105
+ s.req_ok("skip")
118
106
  pid = read_pid_file(pid_file)
119
107
  wait_pid_dead(pid)
120
108
  end
@@ -34,20 +34,6 @@ class TestFormat < Minitest::Unit::TestCase
34
34
  assert_nil hash["channels"]
35
35
  end
36
36
 
37
- def test_from_file
38
- Tempfile.open(%w(tmp .wav)) do |tmp|
39
- # generate an empty file with 1s of audio
40
- cmd = %W(sox -r 96000 -b 24 -c 2 -n #{tmp.path} trim 0 1)
41
- system(*cmd)
42
- assert $?.success?, "#{cmd.inspect} failed: #$?"
43
- fmt = DTAS::Format.new
44
- fmt.from_file tmp.path
45
- assert_equal 96000, fmt.rate
46
- assert_equal 2, fmt.channels
47
- tmp.unlink
48
- end
49
- end
50
-
51
37
  def test_bytes_per_sample
52
38
  fmt = DTAS::Format.new
53
39
  assert_equal 4, fmt.bytes_per_sample
@@ -58,4 +44,14 @@ class TestFormat < Minitest::Unit::TestCase
58
44
  fmt.type = "s16"
59
45
  assert_equal 2, fmt.bytes_per_sample
60
46
  end
47
+
48
+ def test_valid_type
49
+ fmt = DTAS::Format.new
50
+ %w(s16 s24 s32 f32 f64).each do |t|
51
+ assert fmt.valid_type?(t)
52
+ end
53
+ %w(flac wav wtf).each do |t|
54
+ refute fmt.valid_type?(t)
55
+ end
56
+ end
61
57
  end
@@ -13,15 +13,12 @@ class TestFormatChange < Minitest::Unit::TestCase
13
13
  d = "#{dir}/dump.$CHANNELS.$RATE"
14
14
  f44100 = File.open("#{dir}/dump.2.44100", IO::RDWR|IO::CREAT)
15
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)
16
+ s.req_ok("sink ed dump active=true command='cat > #{d}'")
18
17
  noise, len = tmp_noise
19
- s.preq(%W(enq #{noise.path}))
20
- assert_equal "OK", s.readpartial(666)
18
+ s.req_ok(%W(enq #{noise.path}))
21
19
  wait_files_not_empty(default_pid, f44100)
22
20
 
23
- s.preq("format rate=88200")
24
- assert_equal "OK", s.readpartial(666)
21
+ s.req_ok("format rate=88200")
25
22
 
26
23
  wait_files_not_empty(f88200)
27
24
 
@@ -29,8 +26,7 @@ class TestFormatChange < Minitest::Unit::TestCase
29
26
 
30
27
  Timeout.timeout(len) do
31
28
  begin
32
- s.preq("current")
33
- cur = YAML.load(s.readpartial(6666))
29
+ cur = YAML.load(s.req("current"))
34
30
  end while cur["sinks"] && sleep(0.01)
35
31
  end
36
32
 
@@ -22,9 +22,8 @@ class TestPlayerIntegration < Minitest::Unit::TestCase
22
22
  default_pid = default_sink_pid(s)
23
23
  Tempfile.open('junk') do |junk|
24
24
  pink = "sox -n $SOXFMT - synth 0.0001 pinknoise | tee -i #{junk.path}"
25
- s.send("enq-cmd \"#{pink}\"", Socket::MSG_EOR)
25
+ s.req_ok("enq-cmd \"#{pink}\"")
26
26
  wait_files_not_empty(junk)
27
- assert_equal "OK", s.readpartial(666)
28
27
  end
29
28
  wait_files_not_empty(default_pid)
30
29
  pid = read_pid_file(default_pid)
@@ -36,8 +35,7 @@ class TestPlayerIntegration < Minitest::Unit::TestCase
36
35
  default_pid = default_sink_pid(s)
37
36
  cmd = Tempfile.new(%w(sox-cmd .pid))
38
37
  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)
38
+ s.req_ok("enq-cmd \"#{pink}\"")
41
39
  wait_files_not_empty(cmd, default_pid)
42
40
  pid = read_pid_file(default_pid)
43
41
  Process.kill(:KILL, pid)
@@ -47,31 +45,28 @@ class TestPlayerIntegration < Minitest::Unit::TestCase
47
45
 
48
46
  def test_sink_activate
49
47
  s = client_socket
50
- s.send("sink ls", Socket::MSG_EOR)
51
- assert_equal "default", s.readpartial(666)
48
+ res = s.req("sink ls")
49
+ assert_equal "default", res
52
50
 
53
51
  # setup two outputs
54
52
 
55
53
  # make the default sink trickle
56
54
  default_pid = Tempfile.new(%w(dtas-test .pid))
57
55
  pf = "echo $$ >> #{default_pid.path}; "
58
- s.send("sink ed default command='#{pf}#@cmd'", Socket::MSG_EOR)
59
- assert_equal "OK", s.readpartial(666)
56
+ s.req_ok("sink ed default command='#{pf}#@cmd'")
60
57
 
61
58
  # make a sleepy sink trickle, too
62
59
  sleepy_pid = Tempfile.new(%w(dtas-test .pid))
63
60
  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)
61
+ s.req_ok("sink ed sleepy command='#{pf}#@cmd' active=true")
66
62
 
67
63
  # ensure both sinks were created
68
- s.send("sink ls", Socket::MSG_EOR)
69
- assert_equal "default sleepy", s.readpartial(666)
64
+ res = s.req("sink ls")
65
+ assert_equal "default sleepy", res
70
66
 
71
67
  # generate pinknoise
72
68
  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)
69
+ s.req_ok("enq-cmd \"#{pinknoise}\"")
75
70
 
76
71
  # wait for sinks to start
77
72
  wait_files_not_empty(sleepy_pid, default_pid)
@@ -80,8 +75,7 @@ class TestPlayerIntegration < Minitest::Unit::TestCase
80
75
  sleepy = File.read(sleepy_pid).to_i
81
76
  assert_operator sleepy, :>, 0
82
77
  Process.kill(0, sleepy)
83
- s.send("sink ed sleepy active=false", Socket::MSG_EOR)
84
- assert_equal "OK", s.readpartial(666)
78
+ s.req_ok("sink ed sleepy active=false")
85
79
  wait_pid_dead(sleepy)
86
80
 
87
81
  # ensure default sink is still alive
@@ -93,8 +87,7 @@ class TestPlayerIntegration < Minitest::Unit::TestCase
93
87
  sleepy_pid.sync = true
94
88
  sleepy_pid.seek(0)
95
89
  sleepy_pid.truncate(0)
96
- s.send("sink ed sleepy active=true", Socket::MSG_EOR)
97
- assert_equal "OK", s.readpartial(666)
90
+ s.req_ok("sink ed sleepy active=true")
98
91
 
99
92
  # wait for sleepy sink
100
93
  wait_files_not_empty(sleepy_pid)
@@ -105,8 +98,7 @@ class TestPlayerIntegration < Minitest::Unit::TestCase
105
98
  Process.kill(0, sleepy)
106
99
 
107
100
  # stop playing current track
108
- s.send("skip", Socket::MSG_EOR)
109
- assert_equal "OK", s.readpartial(666)
101
+ s.req_ok("skip")
110
102
 
111
103
  wait_pid_dead(sleepy)
112
104
  wait_pid_dead(default)
@@ -115,22 +107,17 @@ class TestPlayerIntegration < Minitest::Unit::TestCase
115
107
  def test_env_change
116
108
  s = client_socket
117
109
  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)
110
+ s.req_ok("sink ed default active=true command='cat >/dev/null'")
120
111
 
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)
112
+ s.req_ok("env FOO=BAR")
113
+ s.req_ok(["enq-cmd", "echo $FOO | tee #{tmp.path}"])
125
114
  wait_files_not_empty(tmp)
126
115
  assert_equal "BAR\n", tmp.read
127
116
 
128
117
  tmp.rewind
129
118
  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)
119
+ s.req_ok("env FOO#")
120
+ s.req_ok(["enq-cmd", "echo -$FOO- | tee #{tmp.path}"])
134
121
  wait_files_not_empty(tmp)
135
122
  assert_equal "--\n", tmp.read
136
123
  end
@@ -138,31 +125,25 @@ class TestPlayerIntegration < Minitest::Unit::TestCase
138
125
  def test_sink_env
139
126
  s = client_socket
140
127
  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)
128
+ s.req_ok("sink ed default active=true command='echo -$FOO- > #{tmp.path}'")
143
129
 
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)
130
+ s.req_ok("sink ed default env.FOO=BAR")
131
+ s.req_ok(["enq-cmd", "echo HI"])
148
132
  wait_files_not_empty(tmp)
149
133
  assert_equal "-BAR-\n", tmp.read
150
134
 
151
135
  tmp.rewind
152
136
  tmp.truncate(0)
153
- s.preq("sink ed default env#FOO")
154
- assert_equal "OK", s.readpartial(666)
137
+ s.req_ok("sink ed default env#FOO")
155
138
 
156
139
  Timeout.timeout(5) do
157
140
  begin
158
- s.preq("current")
159
- yaml = s.readpartial(66666)
141
+ yaml = s.req("current")
160
142
  cur = YAML.load(yaml)
161
143
  end while cur["sinks"] && sleep(0.01)
162
144
  end
163
145
 
164
- s.preq(["enq-cmd", "echo HI"])
165
- assert_equal "OK", s.readpartial(666)
146
+ s.req_ok(["enq-cmd", "echo HI"])
166
147
  wait_files_not_empty(tmp)
167
148
  assert_equal "--\n", tmp.read
168
149
  end
@@ -171,15 +152,11 @@ class TestPlayerIntegration < Minitest::Unit::TestCase
171
152
  s = client_socket
172
153
  default_sink_pid(s)
173
154
  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)
155
+ s.req_ok "sink ed dump active=true command='sox $SOXFMT - #{dump.path}'"
176
156
  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)
157
+ s.req_ok("enq-head #{noise.path}")
158
+ s.req_ok("enq-head #{noise.path} 4")
159
+ s.req_ok("enq-head #{noise.path} 3")
183
160
  dethrottle_decoder(s)
184
161
  expect = Tempfile.new(%W(expect .sox))
185
162
 
@@ -188,8 +165,7 @@ class TestPlayerIntegration < Minitest::Unit::TestCase
188
165
  assert system(c)
189
166
  Timeout.timeout(len) do
190
167
  begin
191
- s.preq("current")
192
- yaml = s.readpartial(66666)
168
+ yaml = s.req("current")
193
169
  cur = YAML.load(yaml)
194
170
  end while cur["sinks"] && sleep(0.01)
195
171
  end
@@ -201,20 +177,32 @@ class TestPlayerIntegration < Minitest::Unit::TestCase
201
177
  s = client_socket
202
178
  pwd = Dir.pwd
203
179
 
204
- s.preq("pwd")
205
- assert_equal pwd, s.readpartial(6666)
180
+ assert_equal pwd, s.req("pwd")
206
181
 
207
- s.preq("cd /")
208
- assert_equal "OK", s.readpartial(6)
182
+ s.req_ok("cd /")
209
183
 
210
- s.preq("pwd")
211
- assert_equal "/", s.readpartial(6)
184
+ assert_equal "/", s.req("pwd")
212
185
 
213
- s.preq("cd /this-better-be-totally-non-existent-on-any-system-#{rand}")
214
- err = s.readpartial(666)
186
+ err = s.req("cd /this-better-be-totally-non-existent-on-any-system-#{rand}")
215
187
  assert_match(%r{\AERR }, err, err)
216
188
 
217
- s.preq("pwd")
218
- assert_equal "/", s.readpartial(6)
189
+ assert_equal "/", s.req("pwd")
190
+ end
191
+
192
+ def test_source_ed
193
+ s = client_socket
194
+ assert_equal "sox av ff", s.req("source ls")
195
+ s.req_ok("source ed av tryorder=-1")
196
+ assert_equal "av sox ff", s.req("source ls")
197
+ s.req_ok("source ed av tryorder=")
198
+ assert_equal "sox av ff", s.req("source ls")
199
+
200
+ s.req_ok("source ed sox command=true")
201
+ sox = YAML.load(s.req("source cat sox"))
202
+ assert_equal "true", sox["command"]
203
+
204
+ s.req_ok("source ed sox command=")
205
+ sox = YAML.load(s.req("source cat sox"))
206
+ assert_equal DTAS::Source::Sox::SOX_DEFAULTS["command"], sox["command"]
219
207
  end
220
208
  end