dtas 0.4.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +4 -0
- data/Documentation/dtas-console.txt +1 -1
- data/Documentation/dtas-player_protocol.txt +34 -7
- data/Documentation/dtas-tl.txt +2 -2
- data/GIT-VERSION-GEN +11 -1
- data/GNUmakefile +54 -6
- data/INSTALL +3 -3
- data/Rakefile +34 -100
- data/bin/dtas-console +1 -0
- data/bin/dtas-sinkedit +1 -2
- data/bin/dtas-sourceedit +3 -3
- data/dtas.gemspec +15 -0
- data/lib/dtas/cue_index.rb +39 -0
- data/lib/dtas/format.rb +8 -0
- data/lib/dtas/player.rb +37 -8
- data/lib/dtas/player/client_handler.rb +87 -11
- data/lib/dtas/source/file.rb +29 -0
- data/test/test_format.rb +5 -0
- data/test/test_source_sox.rb +43 -0
- metadata +34 -94
- data/.gemtest +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a4ce17f3d71d013e20442d569236e8ea2b56a091
|
4
|
+
data.tar.gz: f8177dd1cae23bbf4f679b8cfca1062f8583f5e2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7d57e1c9be990a92163771a89075cf0432cbe6f4441f4c79ba7efe09288a41fb76b055faf37339ab6de2247a89ad9b36a0e45da5deff39f14b376e417d5e11ca
|
7
|
+
data.tar.gz: 5c3ae2d8e5d06f46afe06472b27c9de90c095e7651d69379d45b71589adb3e6d2fffdd24442b095f1e48b0335206ff98a52ff79edcd6845b92bef97fdee364d9
|
data/.gitignore
CHANGED
@@ -1,5 +1,6 @@
|
|
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
|
+
/GIT-VERSION-FILE
|
3
4
|
/Manifest.txt
|
4
5
|
/NEWS
|
5
6
|
/pkg
|
@@ -10,3 +11,6 @@
|
|
10
11
|
/man
|
11
12
|
*.gem
|
12
13
|
*.gz
|
14
|
+
.manifest
|
15
|
+
.gem-manifest
|
16
|
+
.tgz-manifest
|
@@ -32,7 +32,7 @@ Key bindings are inspired partially by mplayer(1)
|
|
32
32
|
- 9/0 - decrease/increase ReplayGain preamp
|
33
33
|
- 'f'/'F' - decrease/increase ReplayGain fallback_gain value
|
34
34
|
- 'r'/'R' - cycle forward/backwards through ReplayGain modes
|
35
|
-
- Ctrl-C - exit dtas-console
|
35
|
+
- 'q'/Ctrl-C - exit dtas-console
|
36
36
|
|
37
37
|
# ENVIRONMENT
|
38
38
|
|
@@ -80,6 +80,23 @@ Commands here should be alphabetized according to `LC_ALL=C sort'
|
|
80
80
|
* clear - clear current queue (current track/command continues running)
|
81
81
|
PENDING: this may be renamed to "queue clear" or "queue-clear"
|
82
82
|
|
83
|
+
* cue - display the index/offsets of the file based on the embedded
|
84
|
+
cue sheet, if any
|
85
|
+
|
86
|
+
* cue next - skip to the next section of the track based on the
|
87
|
+
embedded cue sheet. This may skip to the next track if there is
|
88
|
+
no embedded cue sheet or if playing the last (embedded) track
|
89
|
+
|
90
|
+
* cue prev - skip to the previous section of the track based on
|
91
|
+
the embedded cue sheet. This may just seek to the beginning
|
92
|
+
if there is no embedded cue sheet or if we are playing the first
|
93
|
+
(embedded) track.
|
94
|
+
|
95
|
+
* cue goto INTEGER - go to the embedded track with cue index denoted
|
96
|
+
by INTEGER (0 is first track as returned by "cue"). Negative
|
97
|
+
values of INTEGER allows selecting track relative to the last
|
98
|
+
track (-1 is the last track, -2 is the penultimate, and so on).
|
99
|
+
|
83
100
|
* current - output information about the currently-playing track/command
|
84
101
|
in YAML. The structure of this is unstable and subject to change.
|
85
102
|
|
@@ -111,20 +128,30 @@ Commands here should be alphabetized according to `LC_ALL=C sort'
|
|
111
128
|
Changing this will affect the $SOXFMT and $ECAFMT environments passed
|
112
129
|
to source and sink commands. Changing this implies a "restart"
|
113
130
|
Changing rate to 48000 is probably useful if you plan on playing to some
|
114
|
-
laptop sound cards.
|
131
|
+
laptop sound cards. In all cases where "bypass" is supported, it
|
132
|
+
removes the guarantee of gapless playback as the audio device(s)
|
133
|
+
will likely need to be restarted.
|
134
|
+
|
115
135
|
|
116
|
-
+ channels=UNSIGNED - (default: 2 (stereo)) - number of
|
117
|
-
to use internally. sox will internally invoke the remix
|
118
|
-
when decoding.
|
136
|
+
+ channels=(UNSIGNED|bypass) - (default: 2 (stereo)) - number of
|
137
|
+
channels to use internally. sox will internally invoke the remix
|
138
|
+
effect when decoding. This supports the value "bypass" (without
|
139
|
+
quotes) to avoid the automatic remix effect. Using "bypass" mode
|
140
|
+
removes the guarantee of gapless playback, as the audio device will
|
141
|
+
likely need to be restarted, introducing an audible gap.
|
119
142
|
+ endian=(big|little|swap) - (default: native) - there is probably no
|
120
143
|
point in changing this unless you output over a network sink to
|
121
144
|
a machine of different endianess.
|
122
|
-
+ bits=UNSIGNED - (default: implied from type) - sample precision
|
145
|
+
+ bits=(UNSIGNED|bypass) - (default: implied from type) - sample precision
|
146
|
+
(decoded)
|
123
147
|
This may be pointless and removed in the future, since the sample
|
124
|
-
precision is implied from type.
|
125
|
-
|
148
|
+
precision is implied from type. This supports the value of "bypass"
|
149
|
+
to avoid dither/truncation in later stages.
|
150
|
+
+ rate=(UNSIGNED|bypass) - (default: 44100) - sample rate of audio
|
126
151
|
Typical values of rate are 44100, 48000, 88200, 96000. Not all
|
127
152
|
DSP effects are compatible with all sampling rates/channels.
|
153
|
+
This supports the value of "bypass" as well to avoid introducing
|
154
|
+
software resamplers into the playback chain.
|
128
155
|
+ type=(s16|s24|s32|u16|u24|u32|f32|f64) - (default: s32)
|
129
156
|
change the raw PCM format. s32 currently offers the best performance
|
130
157
|
when only sox/play are used. f32 may offer better performance if
|
data/Documentation/dtas-tl.txt
CHANGED
@@ -31,7 +31,7 @@ HH:MM:SS.FRAC format.
|
|
31
31
|
* reto REGEXP [POS] - play first track with path matching REGEXP immediately,
|
32
32
|
optionally seek to POS. POS should be a timestamp in HH:MM:SS.FRAC format.
|
33
33
|
* next - play the next track in the tracklist
|
34
|
-
*
|
34
|
+
* prev - play the previous track in the tracklist
|
35
35
|
* repeat 1 - repeat the current track
|
36
36
|
* repeat false - disable repeat
|
37
37
|
* repeat true - enable repeat of the whole tracklist
|
@@ -54,7 +54,7 @@ to skip forward in the tracklist
|
|
54
54
|
|
55
55
|
to skip backwards in the tracklist
|
56
56
|
|
57
|
-
$ dtas-tl
|
57
|
+
$ dtas-tl prev
|
58
58
|
|
59
59
|
# ENVIRONMENT
|
60
60
|
|
data/GIT-VERSION-GEN
CHANGED
@@ -3,7 +3,8 @@
|
|
3
3
|
# License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
|
4
4
|
CONSTANT = "DTAS::VERSION"
|
5
5
|
RVF = "lib/dtas/version.rb"
|
6
|
-
|
6
|
+
GVF = "GIT-VERSION-FILE"
|
7
|
+
DEF_VER = "v0.5.0"
|
7
8
|
vn = DEF_VER
|
8
9
|
|
9
10
|
# First see if there is a version file (included in release tarballs),
|
@@ -28,4 +29,13 @@ if new_ruby_version != cur_ruby_version
|
|
28
29
|
File.open(RVF, "w") { |fp| fp.write(new_ruby_version) }
|
29
30
|
end
|
30
31
|
File.chmod(0644, RVF)
|
32
|
+
|
33
|
+
# generate the makefile snippet
|
34
|
+
new_make_version = "VERSION = #{vn}\n"
|
35
|
+
cur_make_version = File.read(GVF) rescue nil
|
36
|
+
if new_make_version != cur_make_version
|
37
|
+
File.open(GVF, "w") { |fp| fp.write(new_make_version) }
|
38
|
+
end
|
39
|
+
File.chmod(0644, GVF)
|
40
|
+
|
31
41
|
puts vn if $0 == __FILE__
|
data/GNUmakefile
CHANGED
@@ -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
|
all::
|
4
|
-
|
4
|
+
pkg = dtas
|
5
5
|
RUBY = ruby
|
6
6
|
GIT-VERSION-FILE: .FORCE-GIT-VERSION-FILE
|
7
7
|
@./GIT-VERSION-GEN
|
@@ -10,10 +10,9 @@ lib := lib
|
|
10
10
|
|
11
11
|
all:: test
|
12
12
|
test_units := $(wildcard test/test_*.rb)
|
13
|
-
test:
|
14
|
-
test-unit: $(test_units)
|
13
|
+
test: $(test_units)
|
15
14
|
$(test_units):
|
16
|
-
$(RUBY) -w -I $(lib) $@
|
15
|
+
$(RUBY) -w -I $(lib) $@ -v
|
17
16
|
|
18
17
|
check-warnings:
|
19
18
|
@(for i in $$(git ls-files '*.rb'| grep -v '^setup\.rb$$'); \
|
@@ -26,5 +25,54 @@ coverage:
|
|
26
25
|
$(MAKE) check
|
27
26
|
$(RUBY) ./test/covshow.rb
|
28
27
|
|
29
|
-
|
30
|
-
.
|
28
|
+
pkggem := pkg/$(pkg)-$(VERSION).gem
|
29
|
+
pkgtgz := pkg/$(pkg)-$(VERSION).tar.gz
|
30
|
+
|
31
|
+
fix-perms:
|
32
|
+
git ls-tree -r HEAD | awk '/^100644 / {print $$NF}' | xargs chmod 644
|
33
|
+
git ls-tree -r HEAD | awk '/^100755 / {print $$NF}' | xargs chmod 755
|
34
|
+
|
35
|
+
gem: $(pkggem)
|
36
|
+
|
37
|
+
install-gem: $(pkggem)
|
38
|
+
gem install $(CURDIR)/$<
|
39
|
+
|
40
|
+
$(pkggem): .gem-manifest
|
41
|
+
VERSION=$(VERSION) gem build $(pkg).gemspec
|
42
|
+
mkdir -p pkg
|
43
|
+
mv $(@F) $@
|
44
|
+
|
45
|
+
pkg_extra := GIT-VERSION-FILE lib/dtas/version.rb NEWS
|
46
|
+
NEWS:
|
47
|
+
rake -s $@
|
48
|
+
gem-man:
|
49
|
+
$(MAKE) -C Documentation/ gem-man
|
50
|
+
tgz-man:
|
51
|
+
$(MAKE) -C Documentation/ install-man mandir=$(CURDIR)/man
|
52
|
+
.PHONY: tgz-man gem-man
|
53
|
+
|
54
|
+
.gem-manifest: .manifest gem-man
|
55
|
+
(ls man/*.?; cat .manifest) | LC_ALL=C sort > $@+
|
56
|
+
cmp $@+ $@ || mv $@+ $@; rm -f $@+
|
57
|
+
.tgz-manifest: .manifest tgz-man
|
58
|
+
(ls man/*/*; cat .manifest) | LC_ALL=C sort > $@+
|
59
|
+
cmp $@+ $@ || mv $@+ $@; rm -f $@+
|
60
|
+
.manifest: NEWS fix-perms
|
61
|
+
rm -rf man
|
62
|
+
(git ls-files; \
|
63
|
+
for i in $(pkg_extra); do echo $$i; done) | \
|
64
|
+
LC_ALL=C sort > $@+
|
65
|
+
cmp $@+ $@ || mv $@+ $@; rm -f $@+
|
66
|
+
$(pkgtgz): distdir = pkg/$(pkg)-$(VERSION)
|
67
|
+
$(pkgtgz): .tgz-manifest
|
68
|
+
@test -n "$(distdir)"
|
69
|
+
$(RM) -r $(distdir)
|
70
|
+
mkdir -p $(distdir)
|
71
|
+
tar cf - $$(cat .tgz-manifest) | (cd $(distdir) && tar xf -)
|
72
|
+
cd pkg && tar cf - $(pkg)-$(VERSION) | gzip -9 > $(@F)+
|
73
|
+
mv $@+ $@
|
74
|
+
|
75
|
+
package: $(pkgtgz) $(pkggem)
|
76
|
+
|
77
|
+
.PHONY: all .FORCE-GIT-VERSION-FILE test $(test_units) NEWS
|
78
|
+
.PHONY: check-warnings fix-perms
|
data/INSTALL
CHANGED
@@ -40,10 +40,10 @@ For future upgrades of dtas (upgrades to dtas-linux will be infrequent)
|
|
40
40
|
|
41
41
|
Grab the latest tarball from our HTTP site:
|
42
42
|
|
43
|
-
http://dtas.80x24.org/2013/dtas-0.
|
43
|
+
http://dtas.80x24.org/2013/dtas-0.5.0.tar.gz
|
44
44
|
|
45
|
-
$ tar zxvf dtas-0.
|
46
|
-
$ cd dtas-0.
|
45
|
+
$ tar zxvf dtas-0.5.0.tar.gz
|
46
|
+
$ cd dtas-0.5.0
|
47
47
|
$ sudo ruby setup.rb
|
48
48
|
|
49
49
|
GNU/Linux users may optionally install "io_splice" and
|
data/Rakefile
CHANGED
@@ -1,71 +1,39 @@
|
|
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
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
end
|
22
|
-
else
|
23
|
-
warn "failed to build manpages for distribution"
|
24
|
-
end
|
25
|
-
end
|
26
|
-
File.open("NEWS", "w") do |fp|
|
27
|
-
`git tag -l`.split(/\n/).reverse.each do |tag|
|
28
|
-
%r{\Av(.+)} =~ tag or next
|
29
|
-
version = $1
|
30
|
-
header, subject, body = `git cat-file tag #{tag}`.split(/\n\n/, 3)
|
31
|
-
header = header.split(/\n/)
|
32
|
-
tagger = header.grep(/\Atagger /)[0]
|
33
|
-
time = Time.at(tagger.split(/ /)[-2].to_i).utc
|
34
|
-
date = time.strftime("%Y-%m-%d")
|
35
|
-
|
36
|
-
fp.write("# #{version} / #{date}\n\n#{subject}\n\n#{body}")
|
37
|
-
end
|
38
|
-
fp.flush
|
39
|
-
if fp.size <= 5
|
40
|
-
fp.puts "Unreleased"
|
3
|
+
require 'tempfile'
|
4
|
+
include Rake::DSL
|
5
|
+
task "NEWS" do
|
6
|
+
latest = nil
|
7
|
+
fp = Tempfile.new("NEWS", ".")
|
8
|
+
fp.sync = true
|
9
|
+
`git tag -l`.split(/\n/).reverse.each do |tag|
|
10
|
+
%r{\Av(.+)} =~ tag or next
|
11
|
+
version = $1
|
12
|
+
header, subject, body = `git cat-file tag #{tag}`.split(/\n\n/, 3)
|
13
|
+
header = header.split(/\n/)
|
14
|
+
tagger = header.grep(/\Atagger /)[0]
|
15
|
+
time = Time.at(tagger.split(/ /)[-2].to_i).utc
|
16
|
+
latest ||= time
|
17
|
+
date = time.strftime("%Y-%m-%d")
|
18
|
+
fp.puts "# #{version} / #{date}\n\n#{subject}"
|
19
|
+
if body && body.strip.size > 0
|
20
|
+
fp.puts "\n\n#{body}"
|
41
21
|
end
|
42
|
-
|
43
|
-
fp.write("\n# COPYRIGHT\n")
|
44
|
-
bdfl = 'Eric Wong <normalperson@yhbt.net>'
|
45
|
-
fp.puts "Copyright (C) 2013, #{bdfl} and all contributors"
|
46
|
-
fp.puts "License: GPLv3 or later (http://www.gnu.org/licenses/gpl-3.0.txt)"
|
22
|
+
fp.puts
|
47
23
|
end
|
24
|
+
fp.puts "Unreleased" unless fp.size > 0
|
25
|
+
fp.puts "# COPYRIGHT"
|
26
|
+
bdfl = 'Eric Wong <normalperson@yhbt.net>'
|
27
|
+
fp.puts "Copyright (C) 2013, #{bdfl} and all contributors"
|
28
|
+
fp.puts "License: GPLv3 or later (http://www.gnu.org/licenses/gpl-3.0.txt)"
|
29
|
+
fp.rewind
|
30
|
+
assert_equal fp.read, File.read("NEWS") rescue nil
|
31
|
+
fp.chmod 0644
|
32
|
+
File.rename(fp.path, "NEWS")
|
33
|
+
fp.close!
|
48
34
|
end
|
49
35
|
|
50
|
-
|
51
|
-
Hoe.plugin :git
|
52
|
-
include Rake::DSL
|
53
|
-
|
54
|
-
h = Hoe.spec('dtas') do |p|
|
55
|
-
developer 'Eric Wong', 'e@80x24.org'
|
56
|
-
|
57
|
-
self.readme_file = 'README'
|
58
|
-
self.history_file = 'NEWS'
|
59
|
-
self.urls = %w(http://dtas.80x24.org/)
|
60
|
-
self.summary = x = File.readlines("README")[0].split(/\s+/)[1].chomp
|
61
|
-
self.description = self.paragraphs_of("README", 1)
|
62
|
-
# no public APIs, no HTML, either
|
63
|
-
self.need_rdoc = false
|
64
|
-
self.extra_rdoc_files = []
|
65
|
-
license "GPLv3+"
|
66
|
-
end
|
67
|
-
|
68
|
-
task :rsync_docs do
|
36
|
+
task rsync_docs: "NEWS" do
|
69
37
|
dest = ENV["RSYNC_DEST"] || "80x24.org:/srv/dtas/"
|
70
38
|
top = %w(INSTALL NEWS README COPYING)
|
71
39
|
files = []
|
@@ -73,9 +41,9 @@ task :rsync_docs do
|
|
73
41
|
# git-set-file-times is distributed with rsync,
|
74
42
|
# Also available at: http://yhbt.net/git-set-file-times
|
75
43
|
# on Debian systems: /usr/share/doc/rsync/scripts/git-set-file-times.gz
|
76
|
-
sh("git", "set-file-times", "Documentation")
|
44
|
+
sh("git", "set-file-times", "Documentation", "examples", *top)
|
77
45
|
|
78
|
-
|
46
|
+
`git ls-files Documentation/*.txt`.split(/\n/).concat(top).each do |txt|
|
79
47
|
gz = "#{txt}.gz"
|
80
48
|
tmp = "#{gz}.#$$"
|
81
49
|
sh("gzip -9 < #{txt} > #{tmp}")
|
@@ -86,41 +54,7 @@ task :rsync_docs do
|
|
86
54
|
files << gz
|
87
55
|
end
|
88
56
|
sh("rsync --chmod=Fugo=r -av #{files.join(' ')} #{dest}")
|
89
|
-
end
|
90
|
-
|
91
|
-
task :coverage do
|
92
|
-
env = {
|
93
|
-
"COVERAGE" => "1",
|
94
|
-
"RUBYOPT" => "-r./test/helper",
|
95
|
-
}
|
96
|
-
File.open("coverage.dump", "w").close # clear
|
97
|
-
pid = Process.spawn(env, "rake")
|
98
|
-
_, status = Process.waitpid2(pid)
|
99
|
-
require './test/covshow'
|
100
|
-
exit status.exitstatus
|
101
|
-
end
|
102
|
-
|
103
|
-
base = "dtas-#{h.version}"
|
104
|
-
task tarball: "pkg/#{base}" do
|
105
|
-
Dir.chdir("pkg") do
|
106
|
-
tgz = "#{base}.tar.gz"
|
107
|
-
tmp = "#{tgz}.#$$"
|
108
|
-
sh "tar cf - #{base} | gzip -9 > #{tmp}"
|
109
|
-
File.rename(tmp, tgz)
|
110
|
-
end
|
111
|
-
end
|
112
57
|
|
113
|
-
|
114
|
-
|
115
|
-
task :fix_perms do
|
116
|
-
sh "git ls-tree -r HEAD | awk '/^100644 / {print $NF}' | xargs chmod 644"
|
117
|
-
sh "git ls-tree -r HEAD | awk '/^100755 / {print $NF}' | xargs chmod 755"
|
118
|
-
end
|
119
|
-
|
120
|
-
task dist: [ :tarball, :package ] do
|
121
|
-
Dir.chdir("pkg") do
|
122
|
-
%w(dtas-linux dtas-mpris).each do |gem|
|
123
|
-
sh "gem build ../#{gem}.gemspec"
|
124
|
-
end
|
125
|
-
end
|
58
|
+
examples = `git ls-files examples`.split("\n")
|
59
|
+
sh("rsync --chmod=Fugo=r -av #{examples.join(' ')} #{dest}/examples/")
|
126
60
|
end
|
data/bin/dtas-console
CHANGED
@@ -172,6 +172,7 @@ begin
|
|
172
172
|
case key = Curses.getch
|
173
173
|
when "j" then c.req_ok("seek -5")
|
174
174
|
when "k" then c.req_ok("seek +5")
|
175
|
+
when "q" then exit(0)
|
175
176
|
when Curses::KEY_DOWN then c.req_ok("seek -60")
|
176
177
|
when Curses::KEY_UP then c.req_ok("seek +60")
|
177
178
|
when Curses::KEY_LEFT then c.req_ok("seek -10")
|
data/bin/dtas-sinkedit
CHANGED
@@ -18,8 +18,7 @@ orig = YAML.load(buf)
|
|
18
18
|
tmp.write(buf << DTAS_DISCLAIMER)
|
19
19
|
cmd = "#{editor} #{tmp.path}"
|
20
20
|
system(cmd) or abort "#{cmd} failed: #$?"
|
21
|
-
tmp.
|
22
|
-
sink = YAML.load(tmp.read)
|
21
|
+
sink = YAML.load(File.read(tmp.path))
|
23
22
|
|
24
23
|
cmd = %W(sink ed #{name})
|
25
24
|
update_cmd_env(cmd, orig, sink)
|
data/bin/dtas-sourceedit
CHANGED
@@ -22,16 +22,16 @@ abort(buf) if buf =~ /\AERR/
|
|
22
22
|
orig = YAML.load(buf)
|
23
23
|
|
24
24
|
if st_in.file? || st_in.pipe?
|
25
|
-
|
25
|
+
buf = $stdin.read
|
26
26
|
else
|
27
27
|
tmp = tmpyaml
|
28
28
|
tmp.write(buf << DTAS_DISCLAIMER)
|
29
29
|
cmd = "#{editor} #{tmp.path}"
|
30
30
|
system(cmd) or abort "#{cmd} failed: #$?"
|
31
|
-
tmp.
|
31
|
+
buf = File.read(tmp.path)
|
32
32
|
end
|
33
33
|
|
34
|
-
source = YAML.load(
|
34
|
+
source = YAML.load(buf)
|
35
35
|
cmd = %W(source ed #{name})
|
36
36
|
update_cmd_env(cmd, orig, source)
|
37
37
|
|
data/dtas.gemspec
ADDED
@@ -0,0 +1,15 @@
|
|
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
|
+
Gem::Specification.new do |s|
|
4
|
+
manifest = File.read('.gem-manifest').split(/\n/)
|
5
|
+
s.name = %q{dtas}
|
6
|
+
s.version = ENV["VERSION"]
|
7
|
+
s.authors = ["dtas hackers"]
|
8
|
+
s.summary = "duct tape audio suite for *nix"
|
9
|
+
s.description = File.read("README").split(/\n\n/)[1].strip
|
10
|
+
s.email = %q{e@80x24.org}
|
11
|
+
s.executables = manifest.grep(%r{\Abin/}).map { |s| s.sub(%r{\Abin/}, "") }
|
12
|
+
s.files = manifest
|
13
|
+
s.homepage = 'http://dtas.80x24.org/'
|
14
|
+
s.licenses = "GPLv3+"
|
15
|
+
end
|
@@ -0,0 +1,39 @@
|
|
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 '../dtas'
|
4
|
+
class DTAS::CueIndex
|
5
|
+
attr_reader :offset
|
6
|
+
attr_reader :index
|
7
|
+
|
8
|
+
def initialize(index, offset)
|
9
|
+
@index = index.to_i
|
10
|
+
|
11
|
+
# must be compatible with the sox "trim" effect
|
12
|
+
@offset = offset # "#{INTEGER}s" (samples) or HH:MM:SS:FRAC
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_hash
|
16
|
+
{ "index" => @index, "offset" => @offset }
|
17
|
+
end
|
18
|
+
|
19
|
+
def offset_samples(format)
|
20
|
+
case @offset
|
21
|
+
when /\A(\d+)s\z/
|
22
|
+
$1.to_i
|
23
|
+
else
|
24
|
+
format.hhmmss_to_samples(@offset)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def pregap?
|
29
|
+
@index == 0
|
30
|
+
end
|
31
|
+
|
32
|
+
def track?
|
33
|
+
@index == 1
|
34
|
+
end
|
35
|
+
|
36
|
+
def subindex?
|
37
|
+
@index > 1
|
38
|
+
end
|
39
|
+
end
|
data/lib/dtas/format.rb
CHANGED
@@ -81,6 +81,14 @@ class DTAS::Format # :nodoc:
|
|
81
81
|
ivars_to_hash(SIVS)
|
82
82
|
end
|
83
83
|
|
84
|
+
def ==(other)
|
85
|
+
a = to_hash
|
86
|
+
b = other.to_hash
|
87
|
+
a["bits"] ||= bits_per_sample
|
88
|
+
b["bits"] ||= other.bits_per_sample
|
89
|
+
a == b
|
90
|
+
end
|
91
|
+
|
84
92
|
# for the _decoded_ output
|
85
93
|
def bits_per_sample
|
86
94
|
return @bits if @bits
|
data/lib/dtas/player.rb
CHANGED
@@ -33,6 +33,7 @@ class DTAS::Player # :nodoc:
|
|
33
33
|
@queue = [] # files for sources, or commands
|
34
34
|
@paused = false
|
35
35
|
@format = DTAS::Format.new
|
36
|
+
@bypass = [] # %w(rate bits channels) (not worth Hash overhead)
|
36
37
|
|
37
38
|
@sinks = {} # { user-defined name => sink }
|
38
39
|
@targets = [] # order matters
|
@@ -55,7 +56,10 @@ class DTAS::Player # :nodoc:
|
|
55
56
|
end
|
56
57
|
|
57
58
|
def wall(msg)
|
58
|
-
|
59
|
+
__wall(xs(Array(msg)))
|
60
|
+
end
|
61
|
+
|
62
|
+
def __wall(msg)
|
59
63
|
@watchers.delete_if do |io, _|
|
60
64
|
if io.closed?
|
61
65
|
true
|
@@ -84,6 +88,7 @@ class DTAS::Player # :nodoc:
|
|
84
88
|
|
85
89
|
# Arrays
|
86
90
|
rv["queue"] = @queue
|
91
|
+
rv["bypass"] = @bypass.sort!
|
87
92
|
|
88
93
|
%w(rg sink_buf format).each do |k|
|
89
94
|
rv[k] = instance_variable_get("@#{k}").to_hsh
|
@@ -123,7 +128,7 @@ class DTAS::Player # :nodoc:
|
|
123
128
|
v = v["buffer_size"]
|
124
129
|
@sink_buf.buffer_size = v
|
125
130
|
end
|
126
|
-
%w(socket queue paused).each do |k|
|
131
|
+
%w(socket queue paused bypass).each do |k|
|
127
132
|
v = hash[k] or next
|
128
133
|
instance_variable_set("@#{k}", v)
|
129
134
|
end
|
@@ -201,6 +206,8 @@ class DTAS::Player # :nodoc:
|
|
201
206
|
io.emit("OK")
|
202
207
|
when "rg"
|
203
208
|
rg_handler(io, msg)
|
209
|
+
when "cue"
|
210
|
+
cue_handler(io, msg)
|
204
211
|
when "skip"
|
205
212
|
skip_handler(io, msg)
|
206
213
|
when "sink"
|
@@ -366,31 +373,46 @@ class DTAS::Player # :nodoc:
|
|
366
373
|
def next_source(source_spec)
|
367
374
|
@current = nil
|
368
375
|
if source_spec
|
369
|
-
# restart sinks iff we were idle
|
370
|
-
spawn_sinks(source_spec) or return
|
371
|
-
|
372
376
|
case source_spec
|
373
377
|
when String
|
374
378
|
pending = try_file(source_spec) or return
|
375
|
-
|
379
|
+
msg = %W(file #{pending.infile})
|
376
380
|
when Array
|
377
381
|
pending = try_file(*source_spec) or return
|
378
|
-
|
382
|
+
msg = %W(file #{pending.infile} #{pending.offset_samples}s)
|
379
383
|
else
|
380
384
|
pending = DTAS::Source::Cmd.new(source_spec["command"])
|
381
|
-
|
385
|
+
msg = %W(command #{pending.command_string})
|
386
|
+
end
|
387
|
+
|
388
|
+
unless @bypass.empty?
|
389
|
+
new_fmt = bypass_match!(@format.dup, pending.format)
|
390
|
+
if new_fmt != @format
|
391
|
+
stop_sinks # we may fail to start below
|
392
|
+
format_update!(new_fmt)
|
393
|
+
end
|
382
394
|
end
|
383
395
|
|
396
|
+
# restart sinks iff we were idle
|
397
|
+
spawn_sinks(source_spec) or return
|
398
|
+
|
384
399
|
dst = @sink_buf
|
385
400
|
pending.dst_assoc(dst)
|
386
401
|
pending.spawn(@format, @rg, out: dst.wr, in: "/dev/null")
|
387
402
|
@current = pending
|
388
403
|
@srv.wait_ctl(dst, :wait_readable)
|
404
|
+
wall(msg)
|
389
405
|
else
|
390
406
|
player_idle
|
391
407
|
end
|
392
408
|
end
|
393
409
|
|
410
|
+
def format_update!(fmt)
|
411
|
+
ary = fmt.to_hash.inject(%w(format)) { |m,(k,v)| v ? m << "#{k}=#{v}" : m }
|
412
|
+
@format = fmt
|
413
|
+
__wall(ary.join(' ')) # do not escape '='
|
414
|
+
end
|
415
|
+
|
394
416
|
def player_idle
|
395
417
|
stop_sinks if @sink_buf.inflight == 0
|
396
418
|
@tl.reset unless @paused
|
@@ -457,4 +479,11 @@ class DTAS::Player # :nodoc:
|
|
457
479
|
@sink_buf.close!
|
458
480
|
@state_file.dump(self, true) if @state_file
|
459
481
|
end
|
482
|
+
|
483
|
+
def bypass_match!(dst_fmt, src_fmt)
|
484
|
+
@bypass.each do |k|
|
485
|
+
dst_fmt.__send__("#{k}=", src_fmt.__send__(k))
|
486
|
+
end
|
487
|
+
dst_fmt
|
488
|
+
end
|
460
489
|
end
|
@@ -295,6 +295,7 @@ module DTAS::Player::ClientHandler # :nodoc:
|
|
295
295
|
end
|
296
296
|
tmp["current_inflight"] = @sink_buf.inflight
|
297
297
|
tmp["format"] = @format.to_hash.delete_if { |_,v| v.nil? }
|
298
|
+
tmp["bypass"] = @bypass.sort!
|
298
299
|
tmp["paused"] = @paused
|
299
300
|
rg = @rg.to_hsh
|
300
301
|
tmp["rg"] = rg unless rg.empty?
|
@@ -350,6 +351,16 @@ module DTAS::Player::ClientHandler # :nodoc:
|
|
350
351
|
@paused ? do_play : do_pause
|
351
352
|
end
|
352
353
|
|
354
|
+
def seek_internal(cur, offset)
|
355
|
+
if cur.requeued
|
356
|
+
@queue[0][1] = offset
|
357
|
+
else
|
358
|
+
@queue.unshift([ cur.infile, offset ])
|
359
|
+
cur.requeued = true
|
360
|
+
__buf_reset(cur.dst) # trigger EPIPE
|
361
|
+
end
|
362
|
+
end
|
363
|
+
|
353
364
|
def do_seek(io, offset)
|
354
365
|
if @current
|
355
366
|
if @current.respond_to?(:infile)
|
@@ -363,13 +374,7 @@ module DTAS::Player::ClientHandler # :nodoc:
|
|
363
374
|
rescue ArgumentError
|
364
375
|
return io.emit("ERR bad time format")
|
365
376
|
end
|
366
|
-
|
367
|
-
@queue[0][1] = offset
|
368
|
-
else
|
369
|
-
@queue.unshift([ @current.infile, offset ])
|
370
|
-
@current.requeued = true
|
371
|
-
__buf_reset(@current.dst) # trigger EPIPE
|
372
|
-
end
|
377
|
+
seek_internal(@current, offset)
|
373
378
|
else
|
374
379
|
return io.emit("ERR unseekable")
|
375
380
|
end
|
@@ -402,20 +407,28 @@ module DTAS::Player::ClientHandler # :nodoc:
|
|
402
407
|
new_fmt.valid_type?(v) or return io.emit("ERR invalid file type")
|
403
408
|
new_fmt.type = v
|
404
409
|
when "channels", "bits", "rate"
|
405
|
-
|
406
|
-
|
410
|
+
case v
|
411
|
+
when "bypass"
|
412
|
+
@bypass << k unless @bypass.include?(k)
|
413
|
+
else
|
414
|
+
rv = set_uint(io, kv, v, false) { |u| new_fmt.__send__("#{k}=", u) }
|
415
|
+
rv == true or return rv
|
416
|
+
@bypass.delete(k)
|
417
|
+
end
|
407
418
|
when "endian"
|
408
419
|
new_fmt.valid_endian?(v) or return io.emit("ERR invalid endian")
|
409
420
|
new_fmt.endian = v
|
410
421
|
end
|
411
422
|
end
|
412
423
|
|
424
|
+
bypass_match!(new_fmt, @current.format) if @current
|
425
|
+
|
413
426
|
if new_fmt != @format
|
414
427
|
restart_pipeline # calls __current_requeue
|
415
428
|
|
416
429
|
# we must assign this after __current_requeue since __current_requeue
|
417
430
|
# relies on the old @format for calculation
|
418
|
-
|
431
|
+
format_update!(new_fmt)
|
419
432
|
end
|
420
433
|
io.emit("OK")
|
421
434
|
end
|
@@ -576,6 +589,9 @@ module DTAS::Player::ClientHandler # :nodoc:
|
|
576
589
|
offset = msg.shift # may be nil
|
577
590
|
if @tl.go_to(track_id.to_i, offset)
|
578
591
|
_tl_skip
|
592
|
+
if !(@current || @queue[0] || @paused)
|
593
|
+
next_source(_next)
|
594
|
+
end
|
579
595
|
io.emit("OK")
|
580
596
|
else
|
581
597
|
io.emit("MISSING")
|
@@ -589,11 +605,71 @@ module DTAS::Player::ClientHandler # :nodoc:
|
|
589
605
|
when "next"
|
590
606
|
_tl_skip
|
591
607
|
io.emit("OK")
|
592
|
-
when "
|
608
|
+
when "prev"
|
593
609
|
@tl.previous!
|
594
610
|
_tl_skip
|
595
611
|
io.emit("OK")
|
596
612
|
end
|
597
613
|
end
|
614
|
+
|
615
|
+
def __bp_prev_next(io, msg, cur, bp)
|
616
|
+
case type = msg[1]
|
617
|
+
when nil, "track"
|
618
|
+
bp.keep_if { |ci| ci.track? }
|
619
|
+
when "pregap"
|
620
|
+
bp.keep_if { |ci| ci.pregap? }
|
621
|
+
when "subindex" # any subindex
|
622
|
+
bp.keep_if { |ci| ci.subindex? }
|
623
|
+
when /\A\d+\z/ # exact subindex match
|
624
|
+
si = type.to_i
|
625
|
+
bp.keep_if { |ci| ci.index == si }
|
626
|
+
when "any" # anything goes
|
627
|
+
else
|
628
|
+
return io.emit("INVALID TYPE")
|
629
|
+
end
|
630
|
+
fmt = cur.format
|
631
|
+
case msg[0]
|
632
|
+
when "next"
|
633
|
+
ds = __current_decoded_samples
|
634
|
+
bp.each do |ci|
|
635
|
+
next if ci.offset_samples(fmt) < ds
|
636
|
+
seek_internal(cur, ci.offset)
|
637
|
+
return io.emit("OK")
|
638
|
+
end
|
639
|
+
# go to the next (real) track if not found
|
640
|
+
__current_drop
|
641
|
+
when "prev"
|
642
|
+
os = cur.offset_samples # where we currently started
|
643
|
+
bp.reverse_each do |ci|
|
644
|
+
next if ci.offset_samples(fmt) >= os
|
645
|
+
seek_internal(cur, ci.offset)
|
646
|
+
return io.emit("OK")
|
647
|
+
end
|
648
|
+
# offset may be nil/zero if we couldn't find a previous breakpoint
|
649
|
+
seek_internal(cur, '0')
|
650
|
+
end
|
651
|
+
io.emit("OK")
|
652
|
+
end
|
653
|
+
|
654
|
+
def cue_handler(io, msg)
|
655
|
+
cur = @current
|
656
|
+
if cur.respond_to?(:cuebreakpoints)
|
657
|
+
bp = cur.cuebreakpoints
|
658
|
+
case msg[0]
|
659
|
+
when nil
|
660
|
+
tmp = { "infile" => cur.infile, "cue" => bp.map { |ci| ci.to_hash } }
|
661
|
+
io.emit(tmp.to_yaml)
|
662
|
+
when "next", "prev"
|
663
|
+
return __bp_prev_next(io, msg, cur, bp)
|
664
|
+
when "goto"
|
665
|
+
index = msg[1] or return io.emit("NOINDEX")
|
666
|
+
ci = bp[index.to_i] or return io.emit("BADINDEX")
|
667
|
+
seek_internal(cur, ci.offset)
|
668
|
+
return io.emit("OK")
|
669
|
+
end
|
670
|
+
else
|
671
|
+
io.emit("NOCUE")
|
672
|
+
end
|
673
|
+
end
|
598
674
|
end
|
599
675
|
# :startdoc:
|
data/lib/dtas/source/file.rb
CHANGED
@@ -5,6 +5,7 @@ require_relative '../source'
|
|
5
5
|
require_relative '../command'
|
6
6
|
require_relative '../format'
|
7
7
|
require_relative '../process'
|
8
|
+
require_relative '../cue_index'
|
8
9
|
|
9
10
|
module DTAS::Source::File # :nodoc:
|
10
11
|
attr_reader :infile
|
@@ -33,6 +34,7 @@ module DTAS::Source::File # :nodoc:
|
|
33
34
|
@offset = offset
|
34
35
|
@comments = nil
|
35
36
|
@samples = nil
|
37
|
+
@cuebp = nil
|
36
38
|
@rg = nil
|
37
39
|
end
|
38
40
|
|
@@ -90,4 +92,31 @@ module DTAS::Source::File # :nodoc:
|
|
90
92
|
defaults = source_defaults # see dtas/source/{av,sox}.rb
|
91
93
|
to_source_cat.delete_if { |k,v| v == defaults[k] }
|
92
94
|
end
|
95
|
+
|
96
|
+
def cuebreakpoints
|
97
|
+
rv = @cuebp and return rv
|
98
|
+
rv = []
|
99
|
+
begin
|
100
|
+
str = qx(@env, %W(metaflac --export-cuesheet-to=- #@infile))
|
101
|
+
rescue
|
102
|
+
return rv
|
103
|
+
end
|
104
|
+
str.scan(/^ INDEX (\d+) (\S+)/) do |m|
|
105
|
+
index = m[0]
|
106
|
+
time = m[1].dup
|
107
|
+
case time
|
108
|
+
when /\A\d+\z/
|
109
|
+
time << "s" # sample count (flac 1.3.0)
|
110
|
+
else # HH:MM:SS:FF
|
111
|
+
# FF/75 CDDA frames per second, convert to fractional seconds
|
112
|
+
time.sub!(/:(\d+)\z/, "")
|
113
|
+
frames = $1.to_f
|
114
|
+
if frames > 0
|
115
|
+
time = sprintf("#{time}.%0.6g", frames / 75.0)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
rv << DTAS::CueIndex.new(index, time)
|
119
|
+
end
|
120
|
+
@cuebp = rv
|
121
|
+
end
|
93
122
|
end
|
data/test/test_format.rb
CHANGED
data/test/test_source_sox.rb
CHANGED
@@ -111,4 +111,47 @@ class TestSource < Testcase
|
|
111
111
|
tmp.unlink
|
112
112
|
end
|
113
113
|
end
|
114
|
+
|
115
|
+
def test_flac_cuesheet_cdda
|
116
|
+
return if `which metaflac`.strip.size == 0
|
117
|
+
tmp = Tempfile.new(%W(tmp .flac))
|
118
|
+
x(%W(sox -n -r44100 -b16 -c2 #{tmp.path} synth 5 pluck vol -1dB))
|
119
|
+
cue = Tempfile.new(%W(tmp .cue))
|
120
|
+
cue.puts %Q(FILE "ignored.flac" FLAC)
|
121
|
+
cue.puts " TRACK 01 AUDIO"
|
122
|
+
cue.puts " INDEX 01 00:00:00"
|
123
|
+
cue.puts " TRACK 02 AUDIO"
|
124
|
+
cue.puts " INDEX 01 00:01:40"
|
125
|
+
cue.puts " TRACK 03 AUDIO"
|
126
|
+
cue.puts " INDEX 01 00:03:00"
|
127
|
+
cue.flush
|
128
|
+
x(%W(metaflac --import-cuesheet-from=#{cue.path} #{tmp.path}))
|
129
|
+
source = DTAS::Source::Sox.new.try(tmp.path)
|
130
|
+
offsets = source.cuebreakpoints.map(&:offset)
|
131
|
+
assert_equal %w(00:00 00:01.0.533333 00:03), offsets
|
132
|
+
source.cuebreakpoints.all?(&:track?)
|
133
|
+
end
|
134
|
+
|
135
|
+
def test_flac_cuesheet_48
|
136
|
+
return if `which metaflac`.strip.size == 0
|
137
|
+
ver = `flac --version`.split(/ /)[1].strip
|
138
|
+
ver.to_f >= 1.3 or return # flac 1.3.0 fixed non-44.1k rate support
|
139
|
+
|
140
|
+
tmp = Tempfile.new(%W(tmp .flac))
|
141
|
+
x(%W(sox -n -r48000 -c2 -b24 #{tmp.path} synth 5 pluck vol -1dB))
|
142
|
+
cue = Tempfile.new(%W(tmp .cue))
|
143
|
+
cue.puts %Q(FILE "ignored.flac" FLAC)
|
144
|
+
cue.puts " TRACK 01 AUDIO"
|
145
|
+
cue.puts " INDEX 01 00:00:00"
|
146
|
+
cue.puts " TRACK 02 AUDIO"
|
147
|
+
cue.puts " INDEX 01 00:01:00"
|
148
|
+
cue.puts " TRACK 03 AUDIO"
|
149
|
+
cue.puts " INDEX 01 00:03:00"
|
150
|
+
cue.flush
|
151
|
+
x(%W(metaflac --import-cuesheet-from=#{cue.path} #{tmp.path}))
|
152
|
+
source = DTAS::Source::Sox.new.try(tmp.path)
|
153
|
+
offsets = source.cuebreakpoints.map(&:offset)
|
154
|
+
assert_equal %w(0s 48000s 144000s), offsets
|
155
|
+
source.cuebreakpoints.all?(&:track?)
|
156
|
+
end
|
114
157
|
end
|
metadata
CHANGED
@@ -1,50 +1,23 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dtas
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
|
-
-
|
7
|
+
- dtas hackers
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-09-
|
12
|
-
dependencies:
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - ~>
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: '4.0'
|
27
|
-
- !ruby/object:Gem::Dependency
|
28
|
-
name: hoe
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
31
|
-
- - ~>
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: '3.6'
|
34
|
-
type: :development
|
35
|
-
prerelease: false
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
37
|
-
requirements:
|
38
|
-
- - ~>
|
39
|
-
- !ruby/object:Gem::Version
|
40
|
-
version: '3.6'
|
41
|
-
description: '["Free Software command-line tools for audio playback, mastering, and\nwhatever
|
42
|
-
else related to audio. dtas follows the worse-is-better\nphilosophy and acts as
|
43
|
-
duct tape to combine existing command-line tools\nfor flexibility and ease-of-development. dtas
|
44
|
-
is currently implemented\nin Ruby (and some embedded shell), but may use other languages
|
45
|
-
in the\nfuture."]'
|
46
|
-
email:
|
47
|
-
- e@80x24.org
|
11
|
+
date: 2013-09-30 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: |-
|
14
|
+
Free Software command-line tools for audio playback, mastering, and
|
15
|
+
whatever else related to audio. dtas follows the worse-is-better
|
16
|
+
philosophy and acts as duct tape to combine existing command-line tools
|
17
|
+
for flexibility and ease-of-development. dtas is currently implemented
|
18
|
+
in Ruby (and some embedded shell), but may use other languages in the
|
19
|
+
future.
|
20
|
+
email: e@80x24.org
|
48
21
|
executables:
|
49
22
|
- dtas-console
|
50
23
|
- dtas-ctl
|
@@ -58,21 +31,7 @@ executables:
|
|
58
31
|
- dtas-tl
|
59
32
|
- dtas-xdelay
|
60
33
|
extensions: []
|
61
|
-
extra_rdoc_files:
|
62
|
-
- Documentation/dtas-console.txt
|
63
|
-
- Documentation/dtas-ctl.txt
|
64
|
-
- Documentation/dtas-cueedit.txt
|
65
|
-
- Documentation/dtas-enq.txt
|
66
|
-
- Documentation/dtas-msinkctl.txt
|
67
|
-
- Documentation/dtas-player.txt
|
68
|
-
- Documentation/dtas-player_effects.txt
|
69
|
-
- Documentation/dtas-player_protocol.txt
|
70
|
-
- Documentation/dtas-player_sink_examples.txt
|
71
|
-
- Documentation/dtas-sinkedit.txt
|
72
|
-
- Documentation/dtas-sourceedit.txt
|
73
|
-
- Documentation/dtas-splitfx.txt
|
74
|
-
- Documentation/dtas-tl.txt
|
75
|
-
- Documentation/dtas-xdelay.txt
|
34
|
+
extra_rdoc_files: []
|
76
35
|
files:
|
77
36
|
- .gitignore
|
78
37
|
- COPYING
|
@@ -92,10 +51,12 @@ files:
|
|
92
51
|
- Documentation/dtas-splitfx.txt
|
93
52
|
- Documentation/dtas-tl.txt
|
94
53
|
- Documentation/dtas-xdelay.txt
|
54
|
+
- GIT-VERSION-FILE
|
95
55
|
- GIT-VERSION-GEN
|
96
56
|
- GNUmakefile
|
97
57
|
- HACKING
|
98
58
|
- INSTALL
|
59
|
+
- NEWS
|
99
60
|
- README
|
100
61
|
- Rakefile
|
101
62
|
- TODO
|
@@ -112,6 +73,7 @@ files:
|
|
112
73
|
- bin/dtas-xdelay
|
113
74
|
- dtas-linux.gemspec
|
114
75
|
- dtas-mpris.gemspec
|
76
|
+
- dtas.gemspec
|
115
77
|
- examples/README
|
116
78
|
- examples/splitfx.sample.yml
|
117
79
|
- lib/dtas.rb
|
@@ -120,6 +82,7 @@ files:
|
|
120
82
|
- lib/dtas/buffer/splice.rb
|
121
83
|
- lib/dtas/command.rb
|
122
84
|
- lib/dtas/compat_onenine.rb
|
85
|
+
- lib/dtas/cue_index.rb
|
123
86
|
- lib/dtas/disclaimer.rb
|
124
87
|
- lib/dtas/edit_client.rb
|
125
88
|
- lib/dtas/format.rb
|
@@ -150,8 +113,21 @@ files:
|
|
150
113
|
- lib/dtas/unix_client.rb
|
151
114
|
- lib/dtas/unix_server.rb
|
152
115
|
- lib/dtas/util.rb
|
116
|
+
- lib/dtas/version.rb
|
153
117
|
- lib/dtas/writable_iter.rb
|
154
118
|
- lib/dtas/xs.rb
|
119
|
+
- man/dtas-console.1
|
120
|
+
- man/dtas-ctl.1
|
121
|
+
- man/dtas-enq.1
|
122
|
+
- man/dtas-msinkctl.1
|
123
|
+
- man/dtas-player.1
|
124
|
+
- man/dtas-player_protocol.7
|
125
|
+
- man/dtas-player_sink_examples.7
|
126
|
+
- man/dtas-sinkedit.1
|
127
|
+
- man/dtas-sourceedit.1
|
128
|
+
- man/dtas-splitfx.1
|
129
|
+
- man/dtas-tl.1
|
130
|
+
- man/dtas-xdelay.1
|
155
131
|
- perl/dtas-graph
|
156
132
|
- setup.rb
|
157
133
|
- test/covshow.rb
|
@@ -176,29 +152,12 @@ files:
|
|
176
152
|
- test/test_tracklist.rb
|
177
153
|
- test/test_unixserver.rb
|
178
154
|
- test/test_util.rb
|
179
|
-
- NEWS
|
180
|
-
- lib/dtas/version.rb
|
181
|
-
- man/dtas-console.1
|
182
|
-
- man/dtas-ctl.1
|
183
|
-
- man/dtas-enq.1
|
184
|
-
- man/dtas-msinkctl.1
|
185
|
-
- man/dtas-player.1
|
186
|
-
- man/dtas-player_protocol.7
|
187
|
-
- man/dtas-player_sink_examples.7
|
188
|
-
- man/dtas-sinkedit.1
|
189
|
-
- man/dtas-sourceedit.1
|
190
|
-
- man/dtas-splitfx.1
|
191
|
-
- man/dtas-tl.1
|
192
|
-
- man/dtas-xdelay.1
|
193
|
-
- .gemtest
|
194
155
|
homepage: http://dtas.80x24.org/
|
195
156
|
licenses:
|
196
157
|
- GPLv3+
|
197
158
|
metadata: {}
|
198
159
|
post_install_message:
|
199
|
-
rdoc_options:
|
200
|
-
- --main
|
201
|
-
- README
|
160
|
+
rdoc_options: []
|
202
161
|
require_paths:
|
203
162
|
- lib
|
204
163
|
required_ruby_version: !ruby/object:Gem::Requirement
|
@@ -212,28 +171,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
212
171
|
- !ruby/object:Gem::Version
|
213
172
|
version: '0'
|
214
173
|
requirements: []
|
215
|
-
rubyforge_project:
|
174
|
+
rubyforge_project:
|
216
175
|
rubygems_version: 2.1.3
|
217
176
|
signing_key:
|
218
177
|
specification_version: 4
|
219
|
-
summary:
|
220
|
-
test_files:
|
221
|
-
- test/test_util.rb
|
222
|
-
- test/test_process.rb
|
223
|
-
- test/test_sink_tee_integration.rb
|
224
|
-
- test/test_unixserver.rb
|
225
|
-
- test/test_tracklist.rb
|
226
|
-
- test/test_splitfx.rb
|
227
|
-
- test/test_source_av.rb
|
228
|
-
- test/test_source_sox.rb
|
229
|
-
- test/test_player.rb
|
230
|
-
- test/test_format_change.rb
|
231
|
-
- test/test_env.rb
|
232
|
-
- test/test_rg_integration.rb
|
233
|
-
- test/test_buffer.rb
|
234
|
-
- test/test_sink_pipe_size.rb
|
235
|
-
- test/test_format.rb
|
236
|
-
- test/test_player_integration.rb
|
237
|
-
- test/test_player_client_handler.rb
|
238
|
-
- test/test_rg_state.rb
|
239
|
-
- test/test_sink.rb
|
178
|
+
summary: duct tape audio suite for *nix
|
179
|
+
test_files: []
|
data/.gemtest
DELETED
File without changes
|