dtas 0.9.0 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (120) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -1
  3. data/Documentation/.gitignore +1 -1
  4. data/Documentation/GNUmakefile +3 -1
  5. data/Documentation/dtas-archive.txt +61 -0
  6. data/Documentation/dtas-console.txt +4 -3
  7. data/Documentation/dtas-ctl.txt +4 -3
  8. data/Documentation/dtas-cueedit.txt +4 -3
  9. data/Documentation/dtas-enq.txt +4 -3
  10. data/Documentation/dtas-env.txt +60 -0
  11. data/Documentation/dtas-msinkctl.txt +4 -3
  12. data/Documentation/dtas-player.txt +6 -3
  13. data/Documentation/dtas-player_effects.txt +4 -3
  14. data/Documentation/dtas-player_protocol.txt +27 -4
  15. data/Documentation/dtas-player_sink_examples.txt +7 -3
  16. data/Documentation/dtas-sinkedit.txt +20 -3
  17. data/Documentation/dtas-sourceedit.txt +21 -3
  18. data/Documentation/dtas-splitfx.txt +14 -5
  19. data/Documentation/dtas-tl.txt +4 -3
  20. data/Documentation/dtas-xdelay.txt +4 -3
  21. data/Documentation/update-footer.rb +52 -0
  22. data/GIT-VERSION-GEN +2 -2
  23. data/GNUmakefile +1 -1
  24. data/HACKING +3 -2
  25. data/INSTALL +6 -6
  26. data/README +1 -1
  27. data/Rakefile +2 -3
  28. data/TODO +1 -1
  29. data/bin/dtas-archive +187 -0
  30. data/bin/dtas-console +7 -1
  31. data/bin/dtas-ctl +1 -1
  32. data/bin/dtas-cueedit +3 -3
  33. data/bin/dtas-enq +1 -1
  34. data/bin/dtas-msinkctl +1 -1
  35. data/bin/dtas-partstats +10 -4
  36. data/bin/dtas-player +1 -1
  37. data/bin/dtas-sinkedit +82 -20
  38. data/bin/dtas-sourceedit +64 -22
  39. data/bin/dtas-splitfx +1 -1
  40. data/bin/dtas-tl +1 -1
  41. data/bin/dtas-xdelay +1 -1
  42. data/dtas-linux.gemspec +1 -1
  43. data/dtas-mpris.gemspec +1 -1
  44. data/dtas.gemspec +1 -1
  45. data/examples/splitfx.sample.yml +11 -3
  46. data/examples/{trimfx.sample.yml → tfx.sample.yml} +1 -1
  47. data/lib/dtas.rb +2 -1
  48. data/lib/dtas/buffer.rb +5 -5
  49. data/lib/dtas/buffer/read_write.rb +8 -5
  50. data/lib/dtas/buffer/splice.rb +29 -8
  51. data/lib/dtas/command.rb +2 -2
  52. data/lib/dtas/compat_onenine.rb +1 -1
  53. data/lib/dtas/cue_index.rb +3 -1
  54. data/lib/dtas/disclaimer.rb +1 -1
  55. data/lib/dtas/edit_client.rb +1 -1
  56. data/lib/dtas/fadefx.rb +100 -0
  57. data/lib/dtas/format.rb +4 -2
  58. data/lib/dtas/parse_time.rb +3 -1
  59. data/lib/dtas/partstats.rb +8 -10
  60. data/lib/dtas/pipe.rb +2 -1
  61. data/lib/dtas/player.rb +33 -11
  62. data/lib/dtas/player/client_handler.rb +43 -8
  63. data/lib/dtas/process.rb +6 -14
  64. data/lib/dtas/replaygain.rb +3 -3
  65. data/lib/dtas/rg_state.rb +1 -1
  66. data/lib/dtas/serialize.rb +3 -1
  67. data/lib/dtas/sigevent.rb +1 -1
  68. data/lib/dtas/sigevent/efd.rb +5 -4
  69. data/lib/dtas/sigevent/pipe.rb +4 -1
  70. data/lib/dtas/sink.rb +4 -4
  71. data/lib/dtas/source.rb +1 -1
  72. data/lib/dtas/source/av.rb +2 -2
  73. data/lib/dtas/source/av_ff_common.rb +22 -11
  74. data/lib/dtas/source/cmd.rb +3 -3
  75. data/lib/dtas/source/common.rb +3 -2
  76. data/lib/dtas/source/ff.rb +2 -2
  77. data/lib/dtas/source/file.rb +22 -4
  78. data/lib/dtas/source/mp3gain.rb +1 -1
  79. data/lib/dtas/source/sox.rb +7 -7
  80. data/lib/dtas/source/splitfx.rb +99 -0
  81. data/lib/dtas/spawn_fix.rb +10 -0
  82. data/lib/dtas/splitfx.rb +63 -24
  83. data/lib/dtas/state_file.rb +3 -1
  84. data/lib/dtas/{trimfx.rb → tfx.rb} +50 -24
  85. data/lib/dtas/tracklist.rb +2 -1
  86. data/lib/dtas/unix_accepted.rb +2 -2
  87. data/lib/dtas/unix_client.rb +2 -2
  88. data/lib/dtas/unix_server.rb +1 -1
  89. data/lib/dtas/util.rb +1 -1
  90. data/lib/dtas/watchable.rb +54 -0
  91. data/lib/dtas/writable_iter.rb +2 -1
  92. data/lib/dtas/xs.rb +2 -2
  93. data/perl/dtas-graph +1 -1
  94. data/test/covshow.rb +1 -1
  95. data/test/helper.rb +1 -1
  96. data/test/player_integration.rb +1 -1
  97. data/test/test_buffer.rb +1 -1
  98. data/test/test_env.rb +1 -1
  99. data/test/test_fadefx.rb +45 -0
  100. data/test/test_format.rb +1 -1
  101. data/test/test_format_change.rb +1 -1
  102. data/test/test_player.rb +1 -1
  103. data/test/test_player_client_handler.rb +1 -1
  104. data/test/test_player_integration.rb +8 -8
  105. data/test/test_process.rb +1 -1
  106. data/test/test_rg_integration.rb +1 -1
  107. data/test/test_rg_state.rb +1 -1
  108. data/test/test_sink.rb +1 -1
  109. data/test/test_sink_pipe_size.rb +2 -2
  110. data/test/test_sink_tee_integration.rb +1 -1
  111. data/test/test_source_av.rb +1 -1
  112. data/test/test_source_sox.rb +1 -1
  113. data/test/test_splitfx.rb +43 -13
  114. data/test/test_tfx.rb +85 -0
  115. data/test/test_tracklist.rb +1 -1
  116. data/test/test_unixserver.rb +1 -1
  117. data/test/test_util.rb +1 -1
  118. metadata +17 -6
  119. data/lib/dtas/compat_rbx.rb +0 -12
  120. data/test/test_trimfx.rb +0 -81
@@ -38,7 +38,9 @@ to use ecasound(1), too.
38
38
  # FILE FORMAT
39
39
 
40
40
  * infile - string, the pathname of the original audio file
41
- * env - hash of environment variables to set for all commands
41
+ * env - ordered hash of environment variables to set for all commands
42
+ env: !omap
43
+ FX: vol +3dB stats
42
44
  * comments - hash of common tags for all audio (e.g. ARTIST, ALBUM, YEAR)
43
45
  comments:
44
46
  ARTIST: John Smith
@@ -52,6 +54,7 @@ to use ecasound(1), too.
52
54
  highest-numbered track (default: true)
53
55
  * tracks - array, see "TRACKS" section
54
56
  * targets - hash, see "TARGETS" section
57
+ * command - used only by dtas-player(1)
55
58
 
56
59
  # TRACKS
57
60
 
@@ -96,14 +99,20 @@ dtas-splitfx sets several default environment variables for commands to
96
99
  use in targets:
97
100
 
98
101
  * INFILE - this matches the "infile" directive in the YAML file
102
+ * INDIR - the directory INFILE belongs to, without trailing slash
103
+ * INBASE - the basename of INFILE
104
+ * TBEG - the integer sample offset where the sox(1) trim effect starts
105
+ * TLEN - the integer sample count representing the length of the trim
99
106
  * TRIMFX - essential, this supplys the necessary sox(1) trim effect to
100
- each track.
107
+ each track. In other words, this is: "trim ${TBEG}s ${TLEN}s"
101
108
  * COMMENTS - expands to --comment-file=PATH for sox(1)
102
- * OUTFMT - sox(1) arguments for the output format (e.g. "-ts32 -c2 -r44100"
109
+ * OUTFMT - sox(1) arguments for the output format (e.g. "-ts32 -c2 * -r44100")
103
110
  * SUFFIX - the suffix of the output format without "." (e.g. "flac", "ogg")
104
111
  * TRACKNUMBER - the track number, useful for comments and filenames
105
112
  * RATEFX - rate effect and arguments for sox(1) resampling
106
113
  * DITHERFX - dither effect and arguments for sox(1) dithering
114
+ * FX - any user-specified sox effects which encompases the entire file.
115
+ (e.g. "highpass 35 vol +3dB stats")
107
116
 
108
117
  # TARGETS
109
118
 
@@ -163,9 +172,9 @@ For reference, the "opusenc" default target is implemented as follows:
163
172
 
164
173
  # COPYRIGHT
165
174
 
166
- Copyright 2013-2014, Eric Wong <e@80x24.org> and all contributors.\
175
+ Copyright 2013-2015 all contributors <dtas-all@nongnu.org>.\
167
176
  License: GPLv3 or later <http://www.gnu.org/licenses/gpl-3.0.txt>
168
177
 
169
178
  # SEE ALSO
170
179
 
171
- sox(1), ecasound(1), flac(1), opusenc(1)
180
+ sox(1), ecasound(1), flac(1), opusenc(1), dtas-player(1)
@@ -64,13 +64,14 @@ This defaults to ~/.dtas/player.sock
64
64
 
65
65
  # CONTACT
66
66
 
67
- All feedback welcome via plain-text mail to <dtas-all@nongnu.org>\
68
- Mailing list archives available at <ftp://lists.gnu.org/dtas-all/>\
67
+ All feedback welcome via plain-text mail to: <dtas-all@nongnu.org>\
68
+ Mailing list archives available at <http://80x24.org/dtas-all/> and
69
+ <ftp://lists.gnu.org/dtas-all/>\
69
70
  No subscription is necessary to post to the mailing list.
70
71
 
71
72
  # COPYRIGHT
72
73
 
73
- Copyright 2013-2014, Eric Wong <e@80x24.org> and all contributors.\
74
+ Copyright 2013-2015 all contributors <dtas-all@nongnu.org>.\
74
75
  License: GPLv3 or later <http://www.gnu.org/licenses/gpl-3.0.txt>
75
76
 
76
77
  # SEE ALSO
@@ -61,13 +61,14 @@ greatly appreciated.
61
61
 
62
62
  # CONTACT
63
63
 
64
- All feedback welcome via plain-text mail to <dtas-all@nongnu.org>\
65
- Mailing list archives available at <ftp://lists.gnu.org/dtas-all/>\
64
+ All feedback welcome via plain-text mail to: <dtas-all@nongnu.org>\
65
+ Mailing list archives available at <http://80x24.org/dtas-all/> and
66
+ <ftp://lists.gnu.org/dtas-all/>\
66
67
  No subscription is necessary to post to the mailing list.
67
68
 
68
69
  # COPYRIGHT
69
70
 
70
- Copyright 2013-2014, Eric Wong <e@80x24.org> and all contributors.\
71
+ Copyright 2013-2015 all contributors <dtas-all@nongnu.org>.\
71
72
  License: GPLv3 or later <http://www.gnu.org/licenses/gpl-3.0.txt>
72
73
 
73
74
  # SEE ALSO
@@ -0,0 +1,52 @@
1
+ #!/usr/bin/env ruby
2
+ # Copyright 2015 all contributors <dtas-all@nongnu.org>
3
+ # License: GPLv3 or later <http://www.gnu.org/licenses/gpl-3.0.txt>
4
+ contact = %q{
5
+ All feedback welcome via plain-text mail to: <dtas-all@nongnu.org>\
6
+ Mailing list archives available at <http://80x24.org/dtas-all/> and
7
+ <ftp://lists.gnu.org/dtas-all/>\
8
+ No subscription is necessary to post to the mailing list.
9
+ }
10
+
11
+ copyright = %q{
12
+ Copyright %s all contributors <dtas-all@nongnu.org>.\
13
+ License: GPLv3 or later <http://www.gnu.org/licenses/gpl-3.0.txt>
14
+ }
15
+
16
+ ENV['TZ'] = 'UTC'
17
+ now_year = Time.now.strftime("%Y")
18
+ ARGV.each do |file|
19
+ cmd = %W(git log --reverse --pretty=format:%ad --date=short -- #{file})
20
+ beg_year = IO.popen(cmd, &:gets).split('-')[0]
21
+ years = beg_year == now_year ? beg_year : "#{beg_year}-#{now_year}"
22
+
23
+ File.open(file, "r+") do |fp|
24
+ state = :top
25
+ sections = [ state ]
26
+ sec = { state => "" }
27
+ fp.each_line do |l|
28
+ case l
29
+ when /^(#.+)$/
30
+ state = $1.freeze
31
+ sections << state
32
+ sec[state] = ""
33
+ else
34
+ sec[state] << l
35
+ end
36
+ end
37
+
38
+ fp.truncate(0)
39
+ fp.rewind
40
+ sec["# CONTACT"] = contact
41
+ sec["# COPYRIGHT"] = sprintf(copyright, years)
42
+ while section = sections.shift
43
+ fp.puts(section) if String === section
44
+ blob = sec[section].sub(/\A\n+/, '').sub(/\n+\z/, '')
45
+ fp.puts("\n") if String === section
46
+ fp.write(blob)
47
+ fp.puts("\n")
48
+ fp.puts("\n") if sections[0]
49
+ end
50
+ fp.rewind
51
+ end
52
+ end
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env ruby
2
- # Copyright (C) 2013-2014, Eric Wong <e@80x24.org> and all contributors
2
+ # Copyright (C) 2013-2015 all contributors <dtas-all@nongnu.org>
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.9.0"
7
+ DEF_VER = "v0.10.0"
8
8
  vn = DEF_VER
9
9
 
10
10
  # First see if there is a version file (included in release tarballs),
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2013-2014, Eric Wong <e@80x24.org> and all contributors
1
+ # Copyright (C) 2013-2015 all contributors <dtas-all@nongnu.org>
2
2
  # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
3
3
  all::
4
4
  pkg = dtas
data/HACKING CHANGED
@@ -17,10 +17,11 @@ We use git(7) and develop dtas on a public mailing list like git
17
17
  developers do. Please send patches via git-send-email(1) to the public
18
18
  mailing list at <dtas-all@nongnu.org>. Pull requests should be
19
19
  formatted using git-request-pull(1).\
20
- Mailing list archives available at <ftp://lists.gnu.org/dtas-all/>\
20
+ Mailing list archives available at <http://80x24.org/dtas-all/> and
21
+ <ftp://lists.gnu.org/dtas-all/>\
21
22
  No subscription is necessary to post to the mailing list.
22
23
 
23
24
  # COPYRIGHT
24
25
 
25
- Copyright 2013-2014, Eric Wong <e@80x24.org> and all contributors.\
26
+ Copyright 2013-2015 all contributors <dtas-all@nongnu.org>.\
26
27
  License: GPLv3 or later <http://www.gnu.org/licenses/gpl-3.0.txt>
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/2014/dtas-0.9.0.tar.gz
43
+ http://dtas.80x24.org/2015/dtas-0.10.0.tar.gz
44
44
 
45
- $ tar zxvf dtas-0.9.0.tar.gz
46
- $ cd dtas-0.9.0
45
+ $ tar zxvf dtas-0.10.0.tar.gz
46
+ $ cd dtas-0.10.0
47
47
  $ sudo ruby setup.rb
48
48
 
49
49
  GNU/Linux users may optionally install "io_splice" and
@@ -56,11 +56,11 @@ GNU/Linux users may optionally install "io_splice" and
56
56
 
57
57
  Please do not hesitate to send plain-text mail to <dtas-all@nongnu.org>
58
58
  regarding installation and to share your notes/experiences.
59
- Mailing list archives available at <ftp://lists.gnu.org/dtas-all>
60
- or <http://80x24.org/dtas-all/>
59
+ Mailing list archives available at <http://80x24.org/dtas-all/> or
60
+ <ftp://lists.gnu.org/dtas-all>\
61
61
  No subscription is necessary to post to the mailing list.
62
62
 
63
63
  # COPYRIGHT
64
64
 
65
- Copyright 2013-2014, Eric Wong <e@80x24.org> and all contributors.\
65
+ Copyright 2013-2015 all contributors <dtas-all@nongnu.org>\
66
66
  License: GPLv3 or later <http://www.gnu.org/licenses/gpl-3.0.txt>
data/README CHANGED
@@ -81,7 +81,7 @@ No subscription is necessary to post to the mailing list.
81
81
 
82
82
  ## Copyright
83
83
 
84
- Copyright 2013-2014, Eric Wong <e@80x24.org> and all contributors.\
84
+ Copyright 2013-2015 all contributors <dtas-all@nongnu.org>\
85
85
  License: GPLv3 or later <http://www.gnu.org/licenses/gpl-3.0.txt>
86
86
 
87
87
  dtas is copyrighted Free Software by all contributors, see logs
data/Rakefile CHANGED
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2013-2014, Eric Wong <e@80x24.org> and all contributors
1
+ # Copyright (C) 2013-2015 all contributors <dtas-all@nongnu.org>.
2
2
  # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
3
3
  require 'tempfile'
4
4
  include Rake::DSL
@@ -23,8 +23,7 @@ task "NEWS" do
23
23
  end
24
24
  fp.puts "Unreleased" unless fp.size > 0
25
25
  fp.puts "# COPYRIGHT"
26
- bdfl = 'Eric Wong <e@80x24.org>'
27
- fp.puts "Copyright (C) 2013, #{bdfl} and all contributors"
26
+ fp.puts "Copyright (C) 2013-2015 all contributors <dtas-all@nongnu.org>"
28
27
  fp.puts "License: GPLv3 or later (http://www.gnu.org/licenses/gpl-3.0.txt)"
29
28
  fp.rewind
30
29
  assert_equal fp.read, File.read("NEWS") rescue nil
data/TODO CHANGED
@@ -5,5 +5,5 @@
5
5
 
6
6
  # COPYRIGHT
7
7
 
8
- Copyright 2013-2014, Eric Wong <e@80x24.org> and all contributors.\
8
+ Copyright 2013-2015 all contributors <dtas-all@nongnu.org>\
9
9
  License: GPLv3 or later <http://www.gnu.org/licenses/gpl-3.0.txt>
@@ -0,0 +1,187 @@
1
+ #!/usr/bin/env ruby
2
+ # Copyright (C) 2015 all contributors <dtas-all@nongnu.org>
3
+ # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
4
+ usage = "#$0 SOURCE DESTINATION"
5
+
6
+ # We could use the equivalent sox command here, but some folks working on
7
+ # dtas is more likely to write patches for sox (and thus introduce bugs
8
+ # into it), so we'll use sndfile-cmp as it lives in a different source tree
9
+ %w(sndfile-cmp sox).each do |cmd|
10
+ `which #{cmd} 2>/dev/null`.chomp.empty? and abort "#{cmd} not found in PATH"
11
+ end
12
+
13
+ RUBY_PLATFORM =~ /linux/ or
14
+ warn "#$0 is unproven without Linux kernel fadvise semantics"
15
+ have_advise = IO.instance_methods.include?(:advise)
16
+ have_advise or warn "#$0 does not work reliably without IO#advise support"
17
+
18
+ require 'shellwords'
19
+ require 'fileutils'
20
+ require 'find'
21
+ require 'optparse'
22
+ Thread.abort_on_exception = true
23
+ dry_run = false
24
+ silent = false
25
+ type = 'flac'
26
+ jobs = 1
27
+ repeat = 1
28
+ stats = false
29
+ keep_going = false
30
+
31
+ OptionParser.new('', 24, ' ') do |op|
32
+ op.banner = usage
33
+ op.on('-t', '--type [TYPE]', 'FILE-TYPE (default: flac)') { |t| type = t }
34
+ op.on('-j', '--jobs [JOBS]', Integer) { |j| jobs = j }
35
+ op.on('-S', '--stats', 'save stats on the file') { stats = true }
36
+ op.on('-k', '--keep-going', 'continue after error') { keep_going = true }
37
+ op.on('-n', '--dry-run', 'only print commands, do not run them') do
38
+ dry_run = true
39
+ end
40
+ op.on('-r', '--repeat [COUNT]', 'number of times to check', Integer) do |r|
41
+ repeat = r
42
+ end
43
+ op.on('-s', '--quiet', '--silent') { silent = true }
44
+ op.on('-h', '--help') do
45
+ puts(op.to_s)
46
+ exit
47
+ end
48
+ op.parse!(ARGV)
49
+ end
50
+
51
+ dst = ARGV.pop
52
+ src = ARGV.dup
53
+
54
+ FileUtils.mkpath(dst) unless File.exist?(dst)
55
+ src_files = Hash.new { |h,dest_dir| h[dest_dir] = [] }
56
+
57
+ src.each do |s|
58
+ src_st = File.stat(s)
59
+ if src_st.directory?
60
+ Find.find(s) do |path|
61
+ File.file?(path) or next
62
+ dir = File.dirname(path)
63
+ dir_st = File.stat(dir)
64
+ if dir_st.ino == src_st.ino && dir_st.dev == src_st.dev
65
+ src_files['.'] << path
66
+ else
67
+ dir = File.basename(File.dirname(path))
68
+ src_files[dir] << path
69
+ end
70
+ end
71
+ else
72
+ src_files['.'] << s
73
+ end
74
+ end
75
+
76
+ pairs = []
77
+ type = ".#{type}" unless type.start_with?('.')
78
+
79
+ src_files.each do |dir, files|
80
+ dir = dir == '.' ? dst : File.join(dst, dir)
81
+ if dry_run || !silent
82
+ puts "mkdir -p #{Shellwords.escape(dir)}"
83
+ end
84
+ FileUtils.mkpath(dir) unless dry_run
85
+
86
+ files.each do |path|
87
+ base = File.basename(path).sub(/\.[^\.]+\z/, type)
88
+ out = File.join(dir, base)
89
+ pairs << [ path, out ]
90
+ end
91
+ end
92
+
93
+ mtx = Mutex.new # protects fails and pairs
94
+ fails = []
95
+ mismatches = []
96
+
97
+ on_fail = lambda do |job, status|
98
+ mtx.synchronize do
99
+ pairs.clear unless keep_going
100
+ fails << [ job, status ]
101
+ end
102
+ end
103
+
104
+ on_mismatch = lambda do |job, status|
105
+ mtx.synchronize do
106
+ mismatches << [ job, status ]
107
+ end
108
+ end
109
+
110
+ exiting = false
111
+ %w(INT TERM).each do |s|
112
+ trap(s) do
113
+ warn "Caught SIG#{s}, stopping gracefully..."
114
+ exiting = true
115
+ trap(s, 'DEFAULT') # non-graceful if signaled again
116
+ end
117
+ end
118
+
119
+ thrs = jobs.times.map do |i|
120
+ Thread.new do
121
+ while job = mtx.synchronize { pairs.shift }
122
+ break if exiting
123
+
124
+ input, output = *job
125
+
126
+ unless system('soxi', '-s', input, out: IO::NULL, err: IO::NULL)
127
+ warn "skipping #{input.inspect}, not an audio file"
128
+ next
129
+ end
130
+
131
+ stats_out = "#{output.sub(/\.[\.]+\z/, '')}.stats" if stats
132
+
133
+ if dry_run || !silent
134
+ names = job.map { |x| Shellwords.escape(x) }
135
+ cmd = [ 'sox', *names ]
136
+ if stats
137
+ cmd << 'stats'
138
+ cmd << "2>#{Shellwords.escape(stats_out)}"
139
+ end
140
+
141
+ puts cmd.join(' ')
142
+ cmpcmd = "sndfile-cmp #{names[0]} #{names[1]}"
143
+ if dry_run
144
+ puts cmpcmd
145
+ next
146
+ end
147
+ end
148
+
149
+ cmd = [ 'sox', input, output ]
150
+ if stats
151
+ cmd << 'stats'
152
+ cmd = [ *cmd, { err: stats_out } ]
153
+ end
154
+ system(*cmd) or on_fail.call(job, $?)
155
+
156
+ # clear kernel caches, this relies on Linux behavior
157
+ repeat.times do
158
+ if have_advise
159
+ th = Thread.new { File.open(input) { |fp| fp.advise(:dontneed) } }
160
+ File.open(output, 'ab') do |fp|
161
+ fp.fsync
162
+ fp.advise(:dontneed)
163
+ end
164
+ th.join
165
+ end
166
+
167
+ puts cmpcmd unless silent
168
+ system('sndfile-cmp', input, output) or on_mismatch.call(job, $?)
169
+ end
170
+ st = File.stat(input)
171
+ File.utime(st.atime, st.mtime, output)
172
+ end
173
+ end
174
+ end
175
+
176
+ thrs.each(&:join)
177
+ ok = true
178
+ fails.each do |job, status|
179
+ $stderr.puts "#{job.inspect} failed: #{status.inspect}"
180
+ ok = false
181
+ end
182
+ mismatches.each do |job, status|
183
+ $stderr.puts "#{job.inspect} mismatched: #{status.inspect}"
184
+ ok = false
185
+ end
186
+
187
+ exit ok
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
- # Copyright (C) 2013-2014, Eric Wong <e@80x24.org> and all contributors
2
+ # Copyright (C) 2013-2015 all contributors <dtas-all@nongnu.org>
3
3
  # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
4
4
  #
5
5
  # Note: no idea what I'm doing, especially w.r.t. curses
@@ -104,6 +104,10 @@ def rg_string(rg, current)
104
104
  rv
105
105
  end
106
106
 
107
+ def may_fail(res, events)
108
+ events << res if res != "OK"
109
+ end
110
+
107
111
  enc_locale = Encoding.find("locale")
108
112
  $stdout.set_encoding(enc_locale)
109
113
  enc_opts = { undef: :replace, invalid: :replace, replace: '?' }
@@ -202,6 +206,8 @@ begin
202
206
  when "f" then c.req_ok("rg fallback_gain-=1")
203
207
  when ">" then c.req_ok("tl next")
204
208
  when "<" then c.req_ok("tl prev")
209
+ when "!" then may_fail(c.req("cue prev"), events)
210
+ when "@" then may_fail(c.req("cue next"), events)
205
211
  when " "
206
212
  c.req("play_pause")
207
213
  when "r" # cycle through replaygain modes