dtas 0.0.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 +7 -0
- data/.gemtest +0 -0
- data/.gitignore +9 -0
- data/.rsync_doc +3 -0
- data/COPYING +674 -0
- data/Documentation/.gitignore +3 -0
- data/Documentation/GNUmakefile +46 -0
- data/Documentation/dtas-console.txt +42 -0
- data/Documentation/dtas-ctl.txt +64 -0
- data/Documentation/dtas-cueedit.txt +24 -0
- data/Documentation/dtas-enq.txt +29 -0
- data/Documentation/dtas-msinkctl.txt +45 -0
- data/Documentation/dtas-player.txt +110 -0
- data/Documentation/dtas-player_effects.txt +45 -0
- data/Documentation/dtas-player_protocol.txt +181 -0
- data/Documentation/dtas-sinkedit.txt +41 -0
- data/Documentation/dtas-sourceedit.txt +33 -0
- data/Documentation/dtas-xdelay.txt +57 -0
- data/Documentation/troubleshooting.txt +13 -0
- data/GIT-VERSION-GEN +30 -0
- data/GNUmakefile +9 -0
- data/HACKING +12 -0
- data/INSTALL +53 -0
- data/README +103 -0
- data/Rakefile +97 -0
- data/TODO +4 -0
- data/bin/dtas-console +160 -0
- data/bin/dtas-ctl +10 -0
- data/bin/dtas-cueedit +78 -0
- data/bin/dtas-enq +13 -0
- data/bin/dtas-msinkctl +51 -0
- data/bin/dtas-player +34 -0
- data/bin/dtas-sinkedit +58 -0
- data/bin/dtas-sourceedit +48 -0
- data/bin/dtas-xdelay +85 -0
- data/dtas-linux.gemspec +18 -0
- data/dtas-mpris.gemspec +16 -0
- data/examples/dtas_state.yml +18 -0
- data/lib/dtas.rb +7 -0
- data/lib/dtas/buffer.rb +90 -0
- data/lib/dtas/buffer/read_write.rb +102 -0
- data/lib/dtas/buffer/splice.rb +142 -0
- data/lib/dtas/command.rb +43 -0
- data/lib/dtas/compat_onenine.rb +18 -0
- data/lib/dtas/disclaimer.rb +18 -0
- data/lib/dtas/format.rb +151 -0
- data/lib/dtas/pipe.rb +39 -0
- data/lib/dtas/player.rb +393 -0
- data/lib/dtas/player/client_handler.rb +463 -0
- data/lib/dtas/process.rb +87 -0
- data/lib/dtas/replaygain.rb +41 -0
- data/lib/dtas/rg_state.rb +99 -0
- data/lib/dtas/serialize.rb +9 -0
- data/lib/dtas/sigevent.rb +10 -0
- data/lib/dtas/sigevent/efd.rb +20 -0
- data/lib/dtas/sigevent/pipe.rb +28 -0
- data/lib/dtas/sink.rb +121 -0
- data/lib/dtas/source.rb +147 -0
- data/lib/dtas/source/command.rb +40 -0
- data/lib/dtas/source/common.rb +14 -0
- data/lib/dtas/source/mp3.rb +37 -0
- data/lib/dtas/state_file.rb +33 -0
- data/lib/dtas/unix_accepted.rb +76 -0
- data/lib/dtas/unix_client.rb +51 -0
- data/lib/dtas/unix_server.rb +110 -0
- data/lib/dtas/util.rb +15 -0
- data/lib/dtas/writable_iter.rb +22 -0
- data/perl/dtas-graph +129 -0
- data/pkg.mk +26 -0
- data/setup.rb +1586 -0
- data/test/covshow.rb +30 -0
- data/test/helper.rb +76 -0
- data/test/player_integration.rb +121 -0
- data/test/test_buffer.rb +216 -0
- data/test/test_format.rb +61 -0
- data/test/test_format_change.rb +49 -0
- data/test/test_player.rb +47 -0
- data/test/test_player_client_handler.rb +86 -0
- data/test/test_player_integration.rb +220 -0
- data/test/test_rg_integration.rb +117 -0
- data/test/test_rg_state.rb +32 -0
- data/test/test_sink.rb +32 -0
- data/test/test_sink_tee_integration.rb +34 -0
- data/test/test_source.rb +102 -0
- data/test/test_unixserver.rb +66 -0
- data/test/test_util.rb +15 -0
- metadata +208 -0
data/test/covshow.rb
ADDED
@@ -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
|
+
#
|
5
|
+
# this works with the __covmerge method in test/helper.rb
|
6
|
+
# run this file after all tests are run
|
7
|
+
|
8
|
+
# load the merged dump data
|
9
|
+
res = Marshal.load(IO.binread("coverage.dump"))
|
10
|
+
|
11
|
+
# Dirty little text formatter. I tried simplecov but the default
|
12
|
+
# HTML+JS is unusable without a GUI (I hate GUIs :P) and it would've
|
13
|
+
# taken me longer to search the Internets to find a plain-text
|
14
|
+
# formatter I like...
|
15
|
+
res.keys.sort.each do |filename|
|
16
|
+
cov = res[filename]
|
17
|
+
puts "==> #{filename} <=="
|
18
|
+
File.readlines(filename).each_with_index do |line, i|
|
19
|
+
n = cov[i]
|
20
|
+
if n == 0 # BAD
|
21
|
+
print(" *** 0 #{line}")
|
22
|
+
elsif n
|
23
|
+
printf("% 7u %s", n, line)
|
24
|
+
elsif line =~ /\S/ # probably a line with just "end" in it
|
25
|
+
print(" #{line}")
|
26
|
+
else # blank line
|
27
|
+
print "\n" # don't output trailing whitespace on blank lines
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/test/helper.rb
ADDED
@@ -0,0 +1,76 @@
|
|
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
|
+
$stdout.sync = $stderr.sync = Thread.abort_on_exception = true
|
5
|
+
|
6
|
+
# fork-aware coverage data gatherer, see also test/covshow.rb
|
7
|
+
if ENV["COVERAGE"]
|
8
|
+
require "coverage"
|
9
|
+
COVMATCH = %r{/lib/dtas\b.*rb\z}
|
10
|
+
COVTMP = File.open("coverage.dump", IO::CREAT|IO::RDWR)
|
11
|
+
COVTMP.binmode
|
12
|
+
COVTMP.sync = true
|
13
|
+
|
14
|
+
def __covmerge
|
15
|
+
res = Coverage.result
|
16
|
+
|
17
|
+
# we own this file (at least until somebody tries to use NFS :x)
|
18
|
+
COVTMP.flock(File::LOCK_EX)
|
19
|
+
|
20
|
+
COVTMP.rewind
|
21
|
+
prev = COVTMP.read
|
22
|
+
prev = prev.empty? ? {} : Marshal.load(prev)
|
23
|
+
res.each do |filename, counts|
|
24
|
+
# filter out stuff that's not in our project
|
25
|
+
COVMATCH =~ filename or next
|
26
|
+
|
27
|
+
merge = prev[filename] || []
|
28
|
+
merge = merge
|
29
|
+
counts.each_with_index do |count, i|
|
30
|
+
count or next
|
31
|
+
merge[i] = (merge[i] || 0) + count
|
32
|
+
end
|
33
|
+
prev[filename] = merge
|
34
|
+
end
|
35
|
+
COVTMP.rewind
|
36
|
+
COVTMP.truncate(0)
|
37
|
+
COVTMP.write(Marshal.dump(prev))
|
38
|
+
ensure
|
39
|
+
COVTMP.flock(File::LOCK_UN)
|
40
|
+
end
|
41
|
+
|
42
|
+
Coverage.start
|
43
|
+
at_exit { __covmerge }
|
44
|
+
end
|
45
|
+
|
46
|
+
gem 'minitest'
|
47
|
+
require 'minitest/autorun'
|
48
|
+
require "tempfile"
|
49
|
+
|
50
|
+
FIFOS = []
|
51
|
+
at_exit { FIFOS.each { |(pid,path)| File.unlink(path) if $$ == pid } }
|
52
|
+
def tmpfifo
|
53
|
+
tmp = Tempfile.new(%w(dtas-test .fifo))
|
54
|
+
path = tmp.path
|
55
|
+
tmp.close!
|
56
|
+
assert system(*%W(mkfifo #{path})), "mkfifo #{path}"
|
57
|
+
FIFOS << [ $$, path ]
|
58
|
+
path
|
59
|
+
end
|
60
|
+
|
61
|
+
require 'tmpdir'
|
62
|
+
class Dir
|
63
|
+
require 'fileutils'
|
64
|
+
def Dir.mktmpdir
|
65
|
+
begin
|
66
|
+
d = "#{Dir.tmpdir}/#$$.#{rand}"
|
67
|
+
Dir.mkdir(d)
|
68
|
+
rescue Errno::EEXIST
|
69
|
+
end while true
|
70
|
+
begin
|
71
|
+
yield d
|
72
|
+
ensure
|
73
|
+
FileUtils.remove_entry(d)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end unless Dir.respond_to?(:mktmpdir)
|
@@ -0,0 +1,121 @@
|
|
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 './test/helper'
|
5
|
+
require 'dtas/player'
|
6
|
+
require 'dtas/state_file'
|
7
|
+
require 'yaml'
|
8
|
+
require 'tempfile'
|
9
|
+
require 'shellwords'
|
10
|
+
require 'timeout'
|
11
|
+
|
12
|
+
module PlayerIntegration
|
13
|
+
def setup
|
14
|
+
sock_tmp = Tempfile.new(%w(dtas-test .sock))
|
15
|
+
@state_tmp = Tempfile.new(%w(dtas-test .yml))
|
16
|
+
@sock_path = sock_tmp.path
|
17
|
+
sock_tmp.close!
|
18
|
+
@player = DTAS::Player.new
|
19
|
+
@player.socket = @sock_path
|
20
|
+
@player.state_file = DTAS::StateFile.new(@state_tmp.path)
|
21
|
+
@player.bind
|
22
|
+
@out = Tempfile.new(%w(dtas-test .out))
|
23
|
+
@err = Tempfile.new(%w(dtas-test .err))
|
24
|
+
@out.sync = @err.sync = true
|
25
|
+
@pid = fork do
|
26
|
+
at_exit { @player.close }
|
27
|
+
ENV["SOX_OPTS"] = "#{ENV['SOX_OPTS']} -R"
|
28
|
+
unless $DEBUG
|
29
|
+
$stdout.reopen(@out)
|
30
|
+
$stderr.reopen(@err)
|
31
|
+
end
|
32
|
+
@player.run
|
33
|
+
end
|
34
|
+
|
35
|
+
# null playback device with delay to simulate a real device
|
36
|
+
@fmt = DTAS::Format.new
|
37
|
+
@period = 0.01
|
38
|
+
@period_size = @fmt.bytes_per_sample * @fmt.channels * @fmt.rate * @period
|
39
|
+
@cmd = "exec 2>/dev/null " \
|
40
|
+
"ruby -e " \
|
41
|
+
"\"b=%q();loop{STDIN.readpartial(#@period_size,b);sleep(#@period)}\""
|
42
|
+
|
43
|
+
# FIXME gross...
|
44
|
+
@player.instance_eval do
|
45
|
+
@sink_buf.close!
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
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
|
+
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
|
61
|
+
end
|
62
|
+
|
63
|
+
def wait_pid_dead(pid, time = 5)
|
64
|
+
Timeout.timeout(time) do
|
65
|
+
begin
|
66
|
+
Process.kill(0, pid)
|
67
|
+
sleep(0.01)
|
68
|
+
rescue Errno::ESRCH
|
69
|
+
return
|
70
|
+
end while true
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def wait_files_not_empty(*files)
|
75
|
+
files = Array(files)
|
76
|
+
Timeout.timeout(5) { sleep(0.01) until files.all? { |f| f.size > 0 } }
|
77
|
+
end
|
78
|
+
|
79
|
+
def default_sink_pid(s)
|
80
|
+
default_pid = Tempfile.new(%w(dtas-test .pid))
|
81
|
+
pf = "echo $$ >> #{default_pid.path}; "
|
82
|
+
s.send("sink ed default command='#{pf}#@cmd'", Socket::MSG_EOR)
|
83
|
+
assert_equal "OK", s.readpartial(666)
|
84
|
+
default_pid
|
85
|
+
end
|
86
|
+
|
87
|
+
def teardown
|
88
|
+
Process.kill(:TERM, @pid) if @pid
|
89
|
+
Process.waitall
|
90
|
+
refute File.exist?(@sock_path)
|
91
|
+
@state_tmp.close!
|
92
|
+
@out.close! if @out
|
93
|
+
@err.close! if @err
|
94
|
+
end
|
95
|
+
|
96
|
+
def read_pid_file(file)
|
97
|
+
file.rewind
|
98
|
+
pid = file.read.to_i
|
99
|
+
assert_operator pid, :>, 0
|
100
|
+
pid
|
101
|
+
end
|
102
|
+
|
103
|
+
def tmp_noise(len = 5)
|
104
|
+
noise = Tempfile.open(%w(junk .sox))
|
105
|
+
cmd = %W(sox -R -n -r44100 -c2 #{noise.path} synth #{len} pluck)
|
106
|
+
assert system(*cmd), cmd
|
107
|
+
[ noise, len ]
|
108
|
+
end
|
109
|
+
|
110
|
+
def dethrottle_decoder(s)
|
111
|
+
s.send("sink ed default active=false", Socket::MSG_EOR)
|
112
|
+
assert_equal "OK", s.readpartial(666)
|
113
|
+
end
|
114
|
+
|
115
|
+
def stop_playback(pid_file, s)
|
116
|
+
s.send("skip", Socket::MSG_EOR)
|
117
|
+
assert_equal "OK", s.readpartial(666)
|
118
|
+
pid = read_pid_file(pid_file)
|
119
|
+
wait_pid_dead(pid)
|
120
|
+
end
|
121
|
+
end
|
data/test/test_buffer.rb
ADDED
@@ -0,0 +1,216 @@
|
|
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 './test/helper'
|
5
|
+
require 'stringio'
|
6
|
+
require 'dtas/buffer'
|
7
|
+
|
8
|
+
class TestBuffer < Minitest::Unit::TestCase
|
9
|
+
def teardown
|
10
|
+
@to_close.each { |io| io.close unless io.closed? }
|
11
|
+
end
|
12
|
+
|
13
|
+
def setup
|
14
|
+
@to_close = []
|
15
|
+
end
|
16
|
+
|
17
|
+
def pipe
|
18
|
+
ret = IO.pipe
|
19
|
+
@to_close.concat(ret)
|
20
|
+
ret
|
21
|
+
end
|
22
|
+
|
23
|
+
def tmperr
|
24
|
+
olderr = $stderr
|
25
|
+
$stderr = newerr = StringIO.new
|
26
|
+
yield
|
27
|
+
newerr
|
28
|
+
ensure
|
29
|
+
$stderr = olderr
|
30
|
+
end
|
31
|
+
|
32
|
+
def new_buffer
|
33
|
+
buf = DTAS::Buffer.new
|
34
|
+
@to_close << buf.to_io
|
35
|
+
@to_close << buf.wr
|
36
|
+
buf
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_set_buffer_size
|
40
|
+
buf = new_buffer
|
41
|
+
buf.buffer_size = DTAS::Buffer::MAX_SIZE
|
42
|
+
assert_equal DTAS::Buffer::MAX_SIZE, buf.buffer_size
|
43
|
+
end if defined?(DTAS::Buffer::MAX_SIZE)
|
44
|
+
|
45
|
+
def test_buffer_size
|
46
|
+
buf = new_buffer
|
47
|
+
assert_operator buf.buffer_size, :>, 128
|
48
|
+
buf.buffer_size = DTAS::Buffer::MAX_SIZE
|
49
|
+
assert_equal DTAS::Buffer::MAX_SIZE, buf.buffer_size
|
50
|
+
end if defined?(DTAS::Buffer::MAX_SIZE)
|
51
|
+
|
52
|
+
def test_broadcast_1
|
53
|
+
buf = new_buffer
|
54
|
+
r, w = IO.pipe
|
55
|
+
assert_equal :wait_readable, buf.broadcast([w])
|
56
|
+
assert_equal 0, buf.bytes_xfer
|
57
|
+
buf.wr.write "HIHI"
|
58
|
+
assert_equal :wait_readable, buf.broadcast([w])
|
59
|
+
assert_equal 4, buf.bytes_xfer
|
60
|
+
assert_equal :wait_readable, buf.broadcast([w])
|
61
|
+
assert_equal 4, buf.bytes_xfer
|
62
|
+
tmp = [w]
|
63
|
+
r.close
|
64
|
+
buf.wr.write "HIHI"
|
65
|
+
newerr = tmperr { assert_nil buf.broadcast(tmp) }
|
66
|
+
assert_equal [], tmp
|
67
|
+
assert_match(%r{dropping}, newerr.string)
|
68
|
+
end
|
69
|
+
|
70
|
+
def test_broadcast_tee
|
71
|
+
buf = new_buffer
|
72
|
+
return unless buf.respond_to?(:__broadcast_tee)
|
73
|
+
blocked = []
|
74
|
+
a = pipe
|
75
|
+
b = pipe
|
76
|
+
buf.wr.write "HELLO"
|
77
|
+
assert_equal 4, buf.__broadcast_tee(blocked, [a[1], b[1]], 4)
|
78
|
+
assert_empty blocked
|
79
|
+
assert_equal "HELL", a[0].read(4)
|
80
|
+
assert_equal "HELL", b[0].read(4)
|
81
|
+
assert_equal 5, buf.__broadcast_tee(blocked, [a[1], b[1]], 5)
|
82
|
+
assert_empty blocked
|
83
|
+
assert_equal "HELLO", a[0].read(5)
|
84
|
+
assert_equal "HELLO", b[0].read(5)
|
85
|
+
max = '*' * a[0].pipe_size
|
86
|
+
assert_equal max.size, a[1].write(max)
|
87
|
+
assert_equal a[0].nread, a[0].pipe_size
|
88
|
+
a[1].nonblock = true
|
89
|
+
assert_equal 5, buf.__broadcast_tee(blocked, [a[1], b[1]], 5)
|
90
|
+
assert_equal [a[1]], blocked
|
91
|
+
a[1].nonblock = false
|
92
|
+
b[0].read(b[0].nread)
|
93
|
+
b[1].write(max)
|
94
|
+
t = Thread.new do
|
95
|
+
sleep 0.005
|
96
|
+
[ a[0].read(max.size).size, b[0].read(max.size).size ]
|
97
|
+
end
|
98
|
+
assert_equal 5, buf.__broadcast_tee(blocked, [a[1], b[1]], 5)
|
99
|
+
assert_equal [a[1]], blocked
|
100
|
+
assert_equal [ max.size, max.size ], t.value
|
101
|
+
b[0].close
|
102
|
+
tmp = [a[1], b[1]]
|
103
|
+
|
104
|
+
newerr = tmperr { assert_equal 5, buf.__broadcast_tee(blocked, tmp, 5) }
|
105
|
+
assert_equal [a[1]], blocked
|
106
|
+
assert_match(%r{dropping}, newerr.string)
|
107
|
+
assert_equal [a[1]], tmp
|
108
|
+
end
|
109
|
+
|
110
|
+
def test_broadcast
|
111
|
+
a = pipe
|
112
|
+
b = pipe
|
113
|
+
buf = new_buffer
|
114
|
+
buf.wr.write "HELLO"
|
115
|
+
assert_equal :wait_readable, buf.broadcast([a[1], b[1]])
|
116
|
+
assert_equal 5, buf.bytes_xfer
|
117
|
+
assert_equal "HELLO", a[0].read(5)
|
118
|
+
assert_equal "HELLO", b[0].read(5)
|
119
|
+
assert_equal :wait_readable, buf.broadcast([a[1], b[1]])
|
120
|
+
assert_equal 5, buf.bytes_xfer
|
121
|
+
|
122
|
+
b[1].nonblock = true
|
123
|
+
b[1].write('*' * b[1].pipe_size)
|
124
|
+
buf.wr.write "BYE"
|
125
|
+
assert_equal :wait_readable, buf.broadcast([a[1], b[1]])
|
126
|
+
assert_equal 8, buf.bytes_xfer
|
127
|
+
|
128
|
+
buf.wr.write "DROP"
|
129
|
+
b[0].close
|
130
|
+
tmp = [a[1], b[1]]
|
131
|
+
newerr = tmperr { assert_equal :wait_readable, buf.broadcast(tmp) }
|
132
|
+
assert_equal 12, buf.bytes_xfer
|
133
|
+
assert_equal [a[1]], tmp
|
134
|
+
assert_match(%r{dropping}, newerr.string)
|
135
|
+
end
|
136
|
+
|
137
|
+
def test_broadcast_total_fail
|
138
|
+
a = pipe
|
139
|
+
b = pipe
|
140
|
+
buf = new_buffer
|
141
|
+
buf.wr.write "HELLO"
|
142
|
+
a[0].close
|
143
|
+
b[0].close
|
144
|
+
tmp = [a[1], b[1]]
|
145
|
+
newerr = tmperr { assert_nil buf.broadcast(tmp) }
|
146
|
+
assert_equal [], tmp
|
147
|
+
assert_match(%r{dropping}, newerr.string)
|
148
|
+
end
|
149
|
+
|
150
|
+
def test_broadcast_mostly_fail
|
151
|
+
a = pipe
|
152
|
+
b = pipe
|
153
|
+
c = pipe
|
154
|
+
buf = new_buffer
|
155
|
+
buf.wr.write "HELLO"
|
156
|
+
b[0].close
|
157
|
+
c[0].close
|
158
|
+
tmp = [a[1], b[1], c[1]]
|
159
|
+
newerr = tmperr { assert_equal :wait_readable, buf.broadcast(tmp) }
|
160
|
+
assert_equal 5, buf.bytes_xfer
|
161
|
+
assert_equal [a[1]], tmp
|
162
|
+
assert_match(%r{dropping}, newerr.string)
|
163
|
+
end
|
164
|
+
|
165
|
+
def test_broadcast_all_full
|
166
|
+
a = pipe
|
167
|
+
b = pipe
|
168
|
+
buf = new_buffer
|
169
|
+
a[1].write('*' * a[1].pipe_size)
|
170
|
+
b[1].write('*' * b[1].pipe_size)
|
171
|
+
|
172
|
+
a[1].nonblock = true
|
173
|
+
b[1].nonblock = true
|
174
|
+
tmp = [a[1], b[1]]
|
175
|
+
|
176
|
+
buf.wr.write "HELLO"
|
177
|
+
assert_equal tmp, buf.broadcast(tmp)
|
178
|
+
assert_equal [a[1], b[1]], tmp
|
179
|
+
end
|
180
|
+
|
181
|
+
def test_serialize
|
182
|
+
buf = new_buffer
|
183
|
+
hash = buf.to_hsh
|
184
|
+
assert_empty hash
|
185
|
+
buf.buffer_size = 4096
|
186
|
+
hash = buf.to_hsh
|
187
|
+
assert_equal %w(buffer_size), hash.keys
|
188
|
+
assert_kind_of Integer, hash["buffer_size"]
|
189
|
+
assert_operator hash["buffer_size"], :>, 0
|
190
|
+
end
|
191
|
+
|
192
|
+
def test_close
|
193
|
+
buf = DTAS::Buffer.new
|
194
|
+
buf.wr.write "HI"
|
195
|
+
assert_equal 2, buf.inflight
|
196
|
+
buf.close
|
197
|
+
assert_equal 0, buf.inflight
|
198
|
+
assert_nil buf.close!
|
199
|
+
end
|
200
|
+
|
201
|
+
def test_load_nil
|
202
|
+
buf = DTAS::Buffer.load(nil)
|
203
|
+
buf.close!
|
204
|
+
end
|
205
|
+
|
206
|
+
def test_load_empty
|
207
|
+
buf = DTAS::Buffer.load({})
|
208
|
+
buf.close!
|
209
|
+
end
|
210
|
+
|
211
|
+
def test_load_size
|
212
|
+
buf = DTAS::Buffer.load({"buffer_size" => 4096})
|
213
|
+
assert_equal 4096, buf.buffer_size
|
214
|
+
buf.close!
|
215
|
+
end
|
216
|
+
end
|
data/test/test_format.rb
ADDED
@@ -0,0 +1,61 @@
|
|
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 './test/helper'
|
5
|
+
require 'tempfile'
|
6
|
+
require 'dtas/format'
|
7
|
+
|
8
|
+
class TestFormat < Minitest::Unit::TestCase
|
9
|
+
def test_initialize
|
10
|
+
fmt = DTAS::Format.new
|
11
|
+
assert_equal %w(-ts32 -c2 -r44100), fmt.to_sox_arg
|
12
|
+
hash = fmt.to_hsh
|
13
|
+
assert_equal({}, hash)
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_nonstandard
|
17
|
+
fmt = DTAS::Format.new
|
18
|
+
fmt.type = "s16"
|
19
|
+
fmt.rate = 48000
|
20
|
+
fmt.channels = 4
|
21
|
+
hash = fmt.to_hsh
|
22
|
+
assert_kind_of Hash, hash
|
23
|
+
assert_equal %w(channels rate type), hash.keys.sort
|
24
|
+
assert_equal "s16", hash["type"]
|
25
|
+
assert_equal 48000, hash["rate"]
|
26
|
+
assert_equal 4, hash["channels"]
|
27
|
+
|
28
|
+
# back to stereo
|
29
|
+
fmt.channels = 2
|
30
|
+
hash = fmt.to_hsh
|
31
|
+
assert_equal %w(rate type), hash.keys.sort
|
32
|
+
assert_equal "s16", hash["type"]
|
33
|
+
assert_equal 48000, hash["rate"]
|
34
|
+
assert_nil hash["channels"]
|
35
|
+
end
|
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
|
+
def test_bytes_per_sample
|
52
|
+
fmt = DTAS::Format.new
|
53
|
+
assert_equal 4, fmt.bytes_per_sample
|
54
|
+
fmt.type = "f64"
|
55
|
+
assert_equal 8, fmt.bytes_per_sample
|
56
|
+
fmt.type = "f32"
|
57
|
+
assert_equal 4, fmt.bytes_per_sample
|
58
|
+
fmt.type = "s16"
|
59
|
+
assert_equal 2, fmt.bytes_per_sample
|
60
|
+
end
|
61
|
+
end
|