dtas 0.4.0 → 0.5.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/.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
|