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.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/Documentation/dtas-console.txt +15 -0
- data/Documentation/dtas-player_protocol.txt +5 -3
- data/Documentation/dtas-sourceedit.txt +14 -7
- data/GIT-VERSION-GEN +3 -3
- data/INSTALL +3 -3
- data/README +6 -5
- data/Rakefile +16 -7
- data/bin/dtas-console +48 -3
- data/bin/dtas-cueedit +1 -1
- data/bin/dtas-sinkedit +12 -28
- data/bin/dtas-sourceedit +15 -30
- data/lib/dtas.rb +1 -1
- data/lib/dtas/command.rb +0 -5
- data/lib/dtas/compat_onenine.rb +2 -2
- data/lib/dtas/disclaimer.rb +4 -3
- data/lib/dtas/edit_client.rb +48 -0
- data/lib/dtas/format.rb +2 -9
- data/lib/dtas/player.rb +64 -28
- data/lib/dtas/player/client_handler.rb +39 -20
- data/lib/dtas/process.rb +16 -15
- data/lib/dtas/replaygain.rb +19 -3
- data/lib/dtas/sink.rb +1 -2
- data/lib/dtas/source.rb +1 -141
- data/lib/dtas/source/av.rb +29 -0
- data/lib/dtas/source/av_ff_common.rb +127 -0
- data/lib/dtas/source/{command.rb → cmd.rb} +1 -1
- data/lib/dtas/source/ff.rb +30 -0
- data/lib/dtas/source/file.rb +94 -0
- data/lib/dtas/source/{mp3.rb → mp3gain.rb} +1 -1
- data/lib/dtas/source/sox.rb +114 -0
- data/lib/dtas/unix_client.rb +1 -9
- data/test/player_integration.rb +5 -17
- data/test/test_format.rb +10 -14
- data/test/test_format_change.rb +4 -8
- data/test/test_player_integration.rb +50 -62
- data/test/test_process.rb +33 -0
- data/test/test_rg_integration.rb +45 -35
- data/test/test_sink_pipe_size.rb +20 -0
- data/test/test_sink_tee_integration.rb +2 -4
- data/test/{test_source.rb → test_source_av.rb} +16 -16
- data/test/test_source_sox.rb +115 -0
- metadata +23 -12
- 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::
|
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
|
data/lib/dtas/unix_client.rb
CHANGED
@@ -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 =
|
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
|
|
data/test/player_integration.rb
CHANGED
@@ -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
|
-
|
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.
|
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.
|
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.
|
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
|
data/test/test_format.rb
CHANGED
@@ -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
|
data/test/test_format_change.rb
CHANGED
@@ -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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
51
|
-
assert_equal "default",
|
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.
|
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.
|
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.
|
69
|
-
assert_equal "default sleepy",
|
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.
|
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.
|
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.
|
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.
|
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.
|
119
|
-
assert_equal "OK", s.readpartial(666)
|
110
|
+
s.req_ok("sink ed default active=true command='cat >/dev/null'")
|
120
111
|
|
121
|
-
s.
|
122
|
-
|
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.
|
131
|
-
|
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.
|
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.
|
145
|
-
|
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.
|
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.
|
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.
|
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.
|
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.
|
178
|
-
|
179
|
-
s.
|
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.
|
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.
|
205
|
-
assert_equal pwd, s.readpartial(6666)
|
180
|
+
assert_equal pwd, s.req("pwd")
|
206
181
|
|
207
|
-
s.
|
208
|
-
assert_equal "OK", s.readpartial(6)
|
182
|
+
s.req_ok("cd /")
|
209
183
|
|
210
|
-
s.
|
211
|
-
assert_equal "/", s.readpartial(6)
|
184
|
+
assert_equal "/", s.req("pwd")
|
212
185
|
|
213
|
-
s.
|
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.
|
218
|
-
|
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
|