dtas 0.11.0 → 0.12.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/.gitattributes +4 -0
- data/Documentation/GNUmakefile +1 -1
- data/Documentation/dtas-console.txt +1 -0
- data/Documentation/dtas-player_protocol.txt +19 -5
- data/Documentation/dtas-splitfx.txt +13 -0
- data/Documentation/dtas-tl.txt +16 -0
- data/GIT-VERSION-GEN +1 -1
- data/GNUmakefile +2 -2
- data/INSTALL +3 -3
- data/README +4 -0
- data/bin/dtas-archive +5 -1
- data/bin/dtas-console +13 -6
- data/bin/dtas-cueedit +1 -1
- data/bin/dtas-mlib +47 -0
- data/bin/dtas-readahead +211 -0
- data/bin/dtas-sinkedit +1 -1
- data/bin/dtas-sourceedit +1 -1
- data/bin/dtas-splitfx +15 -6
- data/bin/dtas-tl +81 -5
- data/dtas.gemspec +2 -2
- data/lib/dtas.rb +17 -0
- data/lib/dtas/buffer/read_write.rb +21 -19
- data/lib/dtas/buffer/splice.rb +1 -2
- data/lib/dtas/format.rb +2 -2
- data/lib/dtas/mlib.rb +500 -0
- data/lib/dtas/mlib/migrations/0001_initial.rb +42 -0
- data/lib/dtas/nonblock.rb +24 -0
- data/lib/dtas/parse_freq.rb +29 -0
- data/lib/dtas/parse_time.rb +5 -2
- data/lib/dtas/pipe.rb +2 -1
- data/lib/dtas/player.rb +21 -41
- data/lib/dtas/player/client_handler.rb +175 -92
- data/lib/dtas/process.rb +41 -17
- data/lib/dtas/sigevent/pipe.rb +6 -5
- data/lib/dtas/sink.rb +1 -1
- data/lib/dtas/source/splitfx.rb +14 -0
- data/lib/dtas/splitfx.rb +52 -36
- data/lib/dtas/track.rb +13 -0
- data/lib/dtas/tracklist.rb +148 -43
- data/lib/dtas/unix_accepted.rb +49 -32
- data/lib/dtas/unix_client.rb +1 -1
- data/lib/dtas/unix_server.rb +17 -9
- data/lib/dtas/watchable.rb +16 -5
- data/test/test_env.rb +16 -0
- data/test/test_mlib.rb +31 -0
- data/test/test_parse_freq.rb +18 -0
- data/test/test_player_client_handler.rb +12 -12
- data/test/test_splitfx.rb +0 -29
- data/test/test_tracklist.rb +75 -17
- data/test/test_unixserver.rb +0 -11
- metadata +16 -4
data/lib/dtas/unix_accepted.rb
CHANGED
@@ -17,55 +17,48 @@ def initialize(sock)
|
|
17
17
|
def emit(msg)
|
18
18
|
buffered = @send_buf.size
|
19
19
|
if buffered == 0
|
20
|
-
|
21
|
-
|
22
|
-
return :wait_readable
|
23
|
-
rescue Errno::EAGAIN
|
20
|
+
case rv = sendmsg_nonblock(msg)
|
21
|
+
when :wait_writable
|
24
22
|
@send_buf << msg
|
25
|
-
|
26
|
-
|
27
|
-
|
23
|
+
rv
|
24
|
+
else
|
25
|
+
:wait_readable
|
28
26
|
end
|
29
|
-
elsif buffered > 100
|
30
|
-
return RuntimeError.new("too many messages buffered")
|
31
27
|
else # buffered > 0
|
32
28
|
@send_buf << msg
|
33
|
-
|
29
|
+
:wait_writable
|
34
30
|
end
|
31
|
+
rescue => e
|
32
|
+
e
|
35
33
|
end
|
36
34
|
|
37
35
|
# flushes pending data if it got buffered
|
38
36
|
def writable_iter
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
@send_buf.
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
end while true
|
37
|
+
case sendmsg_nonblock(@send_buf[0])
|
38
|
+
when :wait_writable then return :wait_writable
|
39
|
+
else
|
40
|
+
@send_buf.shift
|
41
|
+
@send_buf.empty? ? :wait_readable : :wait_writable
|
42
|
+
end
|
43
|
+
rescue => e
|
44
|
+
e
|
48
45
|
end
|
49
46
|
|
50
47
|
def readable_iter
|
51
|
-
|
52
|
-
nread = io.nread
|
48
|
+
nread = @to_io.nread
|
53
49
|
|
54
50
|
# EOF, assume no spurious wakeups for SOCK_SEQPACKET
|
55
51
|
return nil if nread == 0
|
56
52
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
return :wait_readable
|
62
|
-
rescue EOFError, SystemCallError
|
63
|
-
return nil
|
64
|
-
end
|
53
|
+
case msg = recv_nonblock(nread)
|
54
|
+
when :wait_readable then return msg
|
55
|
+
when '', nil then return nil # EOF
|
56
|
+
else
|
65
57
|
yield(self, msg) # DTAS::Player deals with this
|
66
|
-
|
67
|
-
|
68
|
-
|
58
|
+
end
|
59
|
+
@send_buf.empty? ? :wait_readable : :wait_writable
|
60
|
+
rescue SystemCallError
|
61
|
+
nil
|
69
62
|
end
|
70
63
|
|
71
64
|
def close
|
@@ -75,4 +68,28 @@ def close
|
|
75
68
|
def closed?
|
76
69
|
@to_io.closed?
|
77
70
|
end
|
71
|
+
|
72
|
+
if RUBY_VERSION.to_f >= 2.3
|
73
|
+
def sendmsg_nonblock(msg)
|
74
|
+
@to_io.sendmsg_nonblock(msg, Socket::MSG_EOR, exception: false)
|
75
|
+
end
|
76
|
+
|
77
|
+
def recv_nonblock(len)
|
78
|
+
@to_io.recv_nonblock(len, exception: false)
|
79
|
+
end
|
80
|
+
else
|
81
|
+
def sendmsg_nonblock(msg)
|
82
|
+
@to_io.sendmsg_nonblock(msg, Socket::MSG_EOR)
|
83
|
+
rescue IO::WaitWritable
|
84
|
+
:wait_writable
|
85
|
+
end
|
86
|
+
|
87
|
+
def recv_nonblock(len)
|
88
|
+
@to_io.recv_nonblock(len)
|
89
|
+
rescue IO::WaitReadable
|
90
|
+
:wait_readable
|
91
|
+
rescue EOFError
|
92
|
+
nil
|
93
|
+
end
|
94
|
+
end
|
78
95
|
end
|
data/lib/dtas/unix_client.rb
CHANGED
data/lib/dtas/unix_server.rb
CHANGED
@@ -58,12 +58,10 @@ def write_failed(client, e)
|
|
58
58
|
|
59
59
|
def readable_iter
|
60
60
|
# we do not do anything with the block passed to us
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
rescue Errno::EAGAIN
|
66
|
-
return :wait_readable
|
61
|
+
case rv = accept_nonblock
|
62
|
+
when :wait_readable then return rv
|
63
|
+
else
|
64
|
+
@readers[DTAS::UNIXAccepted.new(rv[0])] = true
|
67
65
|
end while true
|
68
66
|
end
|
69
67
|
|
@@ -88,9 +86,7 @@ def wait_ctl(io, err)
|
|
88
86
|
# - a consumer (e.g. DTAS::Sink) just became writable, but the
|
89
87
|
# corresponding DTAS::Buffer was already readable in a previous
|
90
88
|
# call.
|
91
|
-
when nil
|
92
|
-
io.close
|
93
|
-
when StandardError
|
89
|
+
when nil, StandardError
|
94
90
|
io.close
|
95
91
|
else
|
96
92
|
raise "BUG: wait_ctl invalid: #{io} #{err.inspect}"
|
@@ -117,4 +113,16 @@ def run_once
|
|
117
113
|
wait_ctl(io, io.readable_iter { |_io, msg| yield(_io, msg) })
|
118
114
|
end
|
119
115
|
end
|
116
|
+
|
117
|
+
if RUBY_VERSION.to_f >= 2.3
|
118
|
+
def accept_nonblock
|
119
|
+
@to_io.accept_nonblock(exception: false)
|
120
|
+
end
|
121
|
+
else
|
122
|
+
def accept_nonblock
|
123
|
+
@to_io.accept_nonblock
|
124
|
+
rescue Errno::EAGAIN, Errno::ECONNABORTED, Errno::EPROTO
|
125
|
+
:wait_readable
|
126
|
+
end
|
127
|
+
end
|
120
128
|
end
|
data/lib/dtas/watchable.rb
CHANGED
@@ -18,7 +18,8 @@ def self.new
|
|
18
18
|
def readable_iter
|
19
19
|
or_call = false
|
20
20
|
while event = take(true) # drain the buffer
|
21
|
-
|
21
|
+
w = @watches[event.wd] or next
|
22
|
+
if (event.mask & FLAGS) != 0 && w[event.name]
|
22
23
|
or_call = true
|
23
24
|
end
|
24
25
|
end
|
@@ -31,19 +32,29 @@ def readable_iter
|
|
31
32
|
end
|
32
33
|
|
33
34
|
# we must watch the directory, since
|
34
|
-
def
|
35
|
+
def watch_files(paths, blk)
|
36
|
+
@watches = {} # wd -> { basename -> true }
|
35
37
|
@on_readable = blk
|
36
|
-
@
|
37
|
-
|
38
|
+
@dir2wd = {}
|
39
|
+
Array(paths).each do |path|
|
40
|
+
watchdir, watchbase = File.split(File.expand_path(path))
|
41
|
+
wd = @dir2wd[watchdir] ||= add_watch(watchdir, FLAGS)
|
42
|
+
m = @watches[wd] ||= {}
|
43
|
+
m[watchbase] = true
|
44
|
+
end
|
38
45
|
end
|
39
46
|
end
|
40
47
|
|
41
48
|
def watch_begin(blk)
|
42
49
|
@ino = InotifyReadableIter.new
|
43
|
-
@ino.
|
50
|
+
@ino.watch_files(@watch_extra << @infile, blk)
|
44
51
|
@ino
|
45
52
|
end
|
46
53
|
|
54
|
+
def watch_extra(paths)
|
55
|
+
@ino.watch_extra(paths)
|
56
|
+
end
|
57
|
+
|
47
58
|
# Closing the inotify descriptor (instead of using inotify_rm_watch)
|
48
59
|
# is cleaner because it avoids EINVAL on race conditions in case
|
49
60
|
# a directory is deleted: https://lkml.org/lkml/2007/7/9/3
|
data/test/test_env.rb
CHANGED
@@ -52,4 +52,20 @@ def test_expand
|
|
52
52
|
res = env_expand({"PATH"=>"$PATH"}, expand: true)
|
53
53
|
assert_equal ENV["PATH"], res["PATH"]
|
54
54
|
end
|
55
|
+
|
56
|
+
def test_ary
|
57
|
+
ENV['HELLO'] = 'HIHI'
|
58
|
+
ENV['PAATH'] = '/usr/local/bin:/usr/bin:/bin'
|
59
|
+
env = { 'BLAH' => [ '$HELLO/WORLD', '$PAATH', '$(echo hello world)' ] }
|
60
|
+
res = env_expand(env, expand: true)
|
61
|
+
exp = [ "HIHI/WORLD", ENV['PAATH'], 'hello world' ]
|
62
|
+
assert_equal exp, Shellwords.split(res['BLAH'])
|
63
|
+
env = {
|
64
|
+
'BLAH' => [ '$(echo hello world)' ],
|
65
|
+
'MOAR' => [ '$BLAH', 'OMG HALP SPACES' ]
|
66
|
+
}
|
67
|
+
res = env_expand(env, expand: true)
|
68
|
+
exp = ["hello\\ world", "OMG HALP SPACES"]
|
69
|
+
assert_equal exp, Shellwords.split(res['MOAR'])
|
70
|
+
end
|
55
71
|
end
|
data/test/test_mlib.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# Copyright (C) 2013-2015 all contributors <dtas-all@nongnu.org>
|
2
|
+
# License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
|
3
|
+
require_relative 'helper'
|
4
|
+
begin
|
5
|
+
require 'dtas/mlib'
|
6
|
+
require 'sequel/no_core_ext'
|
7
|
+
require 'sqlite3'
|
8
|
+
rescue LoadError => err
|
9
|
+
warn "skipping mlib test: #{err.message}"
|
10
|
+
exit 0
|
11
|
+
end
|
12
|
+
|
13
|
+
class TestMlib < Testcase
|
14
|
+
def setup
|
15
|
+
@db = Sequel.sqlite(':memory:')
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_migrate
|
19
|
+
ml = DTAS::Mlib.new(@db)
|
20
|
+
begin
|
21
|
+
$-w = false
|
22
|
+
ml.migrate
|
23
|
+
tables = @db.tables
|
24
|
+
ensure
|
25
|
+
$-w = true
|
26
|
+
end
|
27
|
+
[ :nodes, :tags, :vals, :comments ].each do |t|
|
28
|
+
assert tables.include?(t), "missing #{t}"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# Copyright (C) 2015 all contributors <dtas-all@nongnu.org>
|
2
|
+
# License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
|
3
|
+
require './test/helper'
|
4
|
+
|
5
|
+
require 'dtas/parse_freq'
|
6
|
+
|
7
|
+
class TestParseFreq < Testcase
|
8
|
+
include DTAS::ParseFreq
|
9
|
+
|
10
|
+
def test_parse_freq
|
11
|
+
assert_equal(4000, parse_freq('4k'))
|
12
|
+
assert_equal(-4000, parse_freq('-4k'))
|
13
|
+
assert_equal(-4900, parse_freq('-4.9k'))
|
14
|
+
assert_equal(-4900, parse_freq('-4.9k', :int))
|
15
|
+
|
16
|
+
assert_equal(4900.5, parse_freq('4.9005k', :float))
|
17
|
+
end
|
18
|
+
end
|
@@ -19,23 +19,23 @@ def setup
|
|
19
19
|
def test_delete
|
20
20
|
@sinks["default"] = DTAS::Sink.new
|
21
21
|
@targets = []
|
22
|
-
|
22
|
+
dpc_sink(@io, %w(rm default))
|
23
23
|
assert @sinks.empty?
|
24
24
|
assert_equal %w(OK), @io.to_a
|
25
25
|
end
|
26
26
|
|
27
27
|
def test_delete_noexist
|
28
|
-
|
28
|
+
dpc_sink(@io, %w(rm default))
|
29
29
|
assert @sinks.empty?
|
30
30
|
assert_equal ["ERR default not found"], @io.to_a
|
31
31
|
end
|
32
32
|
|
33
33
|
def test_env
|
34
|
-
|
34
|
+
dpc_sink(@io, %w(ed default env.FOO=bar))
|
35
35
|
assert_equal "bar", @sinks["default"].env["FOO"]
|
36
|
-
|
36
|
+
dpc_sink(@io, %w(ed default env.FOO=))
|
37
37
|
assert_equal "", @sinks["default"].env["FOO"]
|
38
|
-
|
38
|
+
dpc_sink(@io, %w(ed default env#FOO))
|
39
39
|
assert_nil @sinks["default"].env["FOO"]
|
40
40
|
end
|
41
41
|
|
@@ -47,12 +47,12 @@ def test_sink_ed
|
|
47
47
|
--disable-format --disable-resample --disable-channels \
|
48
48
|
-t raw -c $SINK_CHANNELS -f S${SINK_BITS}_3LE -r $SINK_RATE
|
49
49
|
'
|
50
|
-
|
50
|
+
dpc_sink(@io, %W(ed foo command=#{command}))
|
51
51
|
assert_equal command, @sinks["foo"].command
|
52
52
|
assert_empty @sinks["foo"].env
|
53
|
-
|
54
|
-
|
55
|
-
|
53
|
+
dpc_sink(@io, %W(ed foo env.SINK_BITS=24))
|
54
|
+
dpc_sink(@io, %W(ed foo env.SINK_CHANNELS=2))
|
55
|
+
dpc_sink(@io, %W(ed foo env.SINK_RATE=48000))
|
56
56
|
expect = {
|
57
57
|
"SINK_BITS" => "24",
|
58
58
|
"SINK_CHANNELS" => "2",
|
@@ -68,7 +68,7 @@ def test_cat
|
|
68
68
|
sink.name = "default"
|
69
69
|
sink.command += "dither -s"
|
70
70
|
@sinks["default"] = sink
|
71
|
-
|
71
|
+
dpc_sink(@io, %W(cat default))
|
72
72
|
assert_equal 1, @io.size
|
73
73
|
hsh = YAML.load(@io[0])
|
74
74
|
assert_kind_of Hash, hsh
|
@@ -79,12 +79,12 @@ def test_cat
|
|
79
79
|
def test_ls
|
80
80
|
expect = %w(a b c d)
|
81
81
|
expect.each { |s| @sinks[s] = true }
|
82
|
-
|
82
|
+
dpc_sink(@io, %W(ls))
|
83
83
|
assert_equal expect, Shellwords.split(@io[0])
|
84
84
|
end
|
85
85
|
|
86
86
|
def test_env_dump
|
87
|
-
|
87
|
+
dpc_env(@io, [])
|
88
88
|
res = @io[0]
|
89
89
|
result = {}
|
90
90
|
Shellwords.split(res).each do |kv|
|
data/test/test_splitfx.rb
CHANGED
@@ -70,35 +70,6 @@ def test_example
|
|
70
70
|
|
71
71
|
cmp = "cmp result.s32 expect.s32"
|
72
72
|
assert system(cmp), cmp
|
73
|
-
|
74
|
-
# try Ogg Opus, use opusenc/opusdec for now since that's available
|
75
|
-
# in Debian 7.0 (sox.git currently has opusfile support, but that
|
76
|
-
# hasn't made it into Debian, yet)
|
77
|
-
if `which opusenc 2>/dev/null`.size > 0 &&
|
78
|
-
`which opusdec 2>/dev/null`.size > 0
|
79
|
-
WAIT_ALL_MTX.synchronize do
|
80
|
-
tmp_err('opus.err.txt') { sfx.run("opusenc", opts) }
|
81
|
-
end
|
82
|
-
assert_contains_stats('opus.err.txt')
|
83
|
-
|
84
|
-
# ensure opus lengths match flac ones, we decode using opusdec
|
85
|
-
# since sox does not yet have opus support in Debian 7.0
|
86
|
-
%w(1 2).each do |nr|
|
87
|
-
cmd = "opusdec #{nr}.opus #{nr}.wav 2>/dev/null"
|
88
|
-
assert system(cmd), cmd
|
89
|
-
assert_equal `soxi -D #{nr}.flac`, `soxi -D #{nr}.wav`
|
90
|
-
end
|
91
|
-
|
92
|
-
# ensure 16/44.1kHz FLAC works (CDDA-like)
|
93
|
-
File.unlink('1.flac', '2.flac')
|
94
|
-
WAIT_ALL_MTX.synchronize do
|
95
|
-
tmp_err('flac-cdda.err.txt') { sfx.run("flac-cdda", opts) }
|
96
|
-
end
|
97
|
-
assert_contains_stats('flac-cdda.err.txt')
|
98
|
-
%w(1 2).each do |nr|
|
99
|
-
assert_equal `soxi -D #{nr}.flac`, `soxi -D #{nr}.wav`
|
100
|
-
end
|
101
|
-
end
|
102
73
|
end
|
103
74
|
end
|
104
75
|
end
|
data/test/test_tracklist.rb
CHANGED
@@ -3,10 +3,19 @@
|
|
3
3
|
require_relative 'helper'
|
4
4
|
require 'dtas/tracklist'
|
5
5
|
class TestTracklist < Testcase
|
6
|
+
|
7
|
+
def list_to_path(tl)
|
8
|
+
tl.instance_variable_get(:@list).map(&:to_path)
|
9
|
+
end
|
10
|
+
|
11
|
+
def list_add(tl, ary)
|
12
|
+
ary.reverse_each { |x| tl.add_track(x) }
|
13
|
+
end
|
14
|
+
|
6
15
|
def test_tl_add_tracks
|
7
16
|
tl = DTAS::Tracklist.new
|
8
17
|
tl.add_track("/foo.flac")
|
9
|
-
assert_equal(%w(/foo.flac), tl
|
18
|
+
assert_equal(%w(/foo.flac), list_to_path(tl))
|
10
19
|
|
11
20
|
oids = tl.tracks
|
12
21
|
assert_kind_of Array, oids
|
@@ -14,26 +23,24 @@ def test_tl_add_tracks
|
|
14
23
|
assert_equal [ [ oids[0], "/foo.flac" ] ], tl.get_tracks(oids)
|
15
24
|
|
16
25
|
tl.add_track("/bar.flac")
|
17
|
-
assert_equal(%w(/bar.flac /foo.flac), tl
|
26
|
+
assert_equal(%w(/bar.flac /foo.flac), list_to_path(tl))
|
18
27
|
|
19
28
|
tl.add_track("/after.flac", oids[0])
|
20
|
-
assert_equal(%w(/bar.flac /foo.flac /after.flac),
|
21
|
-
tl.instance_variable_get(:@list))
|
29
|
+
assert_equal(%w(/bar.flac /foo.flac /after.flac), list_to_path(tl))
|
22
30
|
end
|
23
31
|
|
24
32
|
def test_add_current
|
25
33
|
tl = DTAS::Tracklist.new
|
26
|
-
tl
|
34
|
+
list_add(tl, %w(a b c d e f g))
|
27
35
|
tl.add_track('/foo.flac', nil, true)
|
28
|
-
assert_equal '/foo.flac', tl.cur_track
|
36
|
+
assert_equal '/foo.flac', tl.cur_track.to_path
|
29
37
|
end
|
30
38
|
|
31
39
|
def test_advance_track
|
32
40
|
tl = DTAS::Tracklist.new
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
end
|
41
|
+
ary = %w(a b c d e f g)
|
42
|
+
list_add(tl, ary)
|
43
|
+
ary.each { |t| assert_equal t, tl.advance_track[0] }
|
37
44
|
assert_nil tl.advance_track
|
38
45
|
tl.repeat = true
|
39
46
|
assert_equal 'a', tl.advance_track[0]
|
@@ -46,7 +53,7 @@ def _build_mapping(tl)
|
|
46
53
|
|
47
54
|
def test_goto
|
48
55
|
tl = DTAS::Tracklist.new
|
49
|
-
tl
|
56
|
+
list_add(tl, %w(a b c d e f g))
|
50
57
|
mapping = _build_mapping(tl)
|
51
58
|
assert_equal 'f', tl.go_to(mapping['f'])
|
52
59
|
assert_equal 'f', tl.advance_track[0]
|
@@ -54,23 +61,74 @@ def test_goto
|
|
54
61
|
assert_equal 'g', tl.advance_track[0]
|
55
62
|
end
|
56
63
|
|
64
|
+
def test_shuffle
|
65
|
+
tl = DTAS::Tracklist.new
|
66
|
+
exp = %w(a b c d e f g)
|
67
|
+
list_add(tl, exp)
|
68
|
+
tl.shuffle = true
|
69
|
+
assert_equal(exp, list_to_path(tl))
|
70
|
+
assert_equal exp.size, tl.shuffle.size
|
71
|
+
assert_equal exp, tl.shuffle.map(&:to_path).sort
|
72
|
+
tl.shuffle = false
|
73
|
+
assert_equal false, tl.shuffle
|
74
|
+
|
75
|
+
tl.instance_variable_set :@pos, 3
|
76
|
+
assert_equal false, tl.shuffle = false
|
77
|
+
|
78
|
+
before = tl.cur_track
|
79
|
+
3.times do
|
80
|
+
tl.shuffle = true
|
81
|
+
assert_equal before, tl.cur_track
|
82
|
+
end
|
83
|
+
x = tl.to_hsh
|
84
|
+
assert_equal true, x['shuffle']
|
85
|
+
3.times do
|
86
|
+
loaded = DTAS::Tracklist.load(x.dup)
|
87
|
+
assert_equal before.to_path, loaded.cur_track.to_path
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
57
91
|
def test_remove_track
|
58
92
|
tl = DTAS::Tracklist.new
|
59
|
-
|
93
|
+
ary = %w(a b c d e f g)
|
94
|
+
list_add(tl, ary)
|
60
95
|
mapping = _build_mapping(tl)
|
61
|
-
|
96
|
+
ary.each { |t| assert_kind_of Integer, mapping[t] }
|
62
97
|
|
63
98
|
tl.remove_track(mapping['a'])
|
64
|
-
assert_equal %w(b c d e f g), tl
|
99
|
+
assert_equal %w(b c d e f g), list_to_path(tl)
|
65
100
|
|
66
101
|
tl.remove_track(mapping['d'])
|
67
|
-
assert_equal %w(b c e f g), tl
|
102
|
+
assert_equal %w(b c e f g), list_to_path(tl)
|
68
103
|
|
69
104
|
tl.remove_track(mapping['g'])
|
70
|
-
assert_equal %w(b c e f), tl
|
105
|
+
assert_equal %w(b c e f), list_to_path(tl)
|
71
106
|
|
72
107
|
# it'll be a while before OIDs require >128 bits, right?
|
73
108
|
tl.remove_track(1 << 128)
|
74
|
-
assert_equal %w(b c e f), tl
|
109
|
+
assert_equal %w(b c e f), list_to_path(tl), "no change"
|
110
|
+
end
|
111
|
+
|
112
|
+
def test_max
|
113
|
+
tl = DTAS::Tracklist.new
|
114
|
+
assert_kind_of Integer, tl.add_track('z')
|
115
|
+
assert_kind_of Integer, tl.max
|
116
|
+
tl.max = 1
|
117
|
+
assert_equal false, tl.add_track('y')
|
118
|
+
assert_equal 1, tl.instance_variable_get(:@list).size
|
119
|
+
tl.max = 2
|
120
|
+
assert_kind_of Integer, tl.add_track('y')
|
121
|
+
assert_equal 2, tl.instance_variable_get(:@list).size
|
122
|
+
end
|
123
|
+
|
124
|
+
def test_swap
|
125
|
+
tl = DTAS::Tracklist.new
|
126
|
+
list_add(tl, %w(a b c d e f g))
|
127
|
+
mapping = _build_mapping(tl)
|
128
|
+
assert tl.swap(mapping['a'], mapping['g'])
|
129
|
+
assert_equal %w(g b c d e f a), list_to_path(tl)
|
130
|
+
|
131
|
+
assert_nil tl.swap(-2, -3), 'no swap on invalid'
|
132
|
+
assert_equal %w(g b c d e f a), list_to_path(tl)
|
75
133
|
end
|
76
134
|
end
|