diff options
Diffstat (limited to 'bin')
-rwxr-xr-x | bin/dtas-archive | 14 | ||||
-rwxr-xr-x | bin/dtas-console | 76 | ||||
-rwxr-xr-x | bin/dtas-ctl | 2 | ||||
-rwxr-xr-x | bin/dtas-cueedit | 2 | ||||
-rwxr-xr-x | bin/dtas-enq | 2 | ||||
-rwxr-xr-x | bin/dtas-mlib | 2 | ||||
-rwxr-xr-x | bin/dtas-msinkctl | 5 | ||||
-rwxr-xr-x | bin/dtas-partstats | 12 | ||||
-rwxr-xr-x | bin/dtas-player | 3 | ||||
-rwxr-xr-x | bin/dtas-readahead | 42 | ||||
-rwxr-xr-x | bin/dtas-sinkedit | 7 | ||||
-rwxr-xr-x | bin/dtas-sourceedit | 7 | ||||
-rwxr-xr-x | bin/dtas-splitfx | 23 | ||||
-rwxr-xr-x | bin/dtas-tl | 93 | ||||
-rwxr-xr-x | bin/dtas-xdelay | 2 |
15 files changed, 166 insertions, 126 deletions
diff --git a/bin/dtas-archive b/bin/dtas-archive index f47f05a..7c0e4f7 100755 --- a/bin/dtas-archive +++ b/bin/dtas-archive @@ -1,5 +1,5 @@ #!/usr/bin/env ruby -# Copyright (C) 2015-2016 all contributors <dtas-all@nongnu.org> +# Copyright (C) all contributors <dtas-all@nongnu.org> # License: GPL-3.0+ <https://www.gnu.org/licenses/gpl-3.0.txt> # frozen_string_literal: true usage = "#$0 SOURCE DESTINATION" @@ -29,6 +29,8 @@ repeat = 1 stats = false keep_going = false compression = [] +comment = [] +match = nil OptionParser.new('', 24, ' ') do |op| op.banner = usage @@ -36,6 +38,7 @@ OptionParser.new('', 24, ' ') do |op| op.on('-C', '--compression [FACTOR]', 'compression factor for sox') { |c| compression = [ '-C', c ] } + op.on('--comment=TEXT', String) { |c| comment.push('--comment', c) } op.on('-j', '--jobs [JOBS]', Integer) { |j| jobs = j } op.on('-S', '--stats', 'save stats on the file') { stats = true } op.on('-k', '--keep-going', 'continue after error') { keep_going = true } @@ -45,6 +48,7 @@ OptionParser.new('', 24, ' ') do |op| op.on('-r', '--repeat [COUNT]', 'number of times to check', Integer) do |r| repeat = r end + op.on('-m', '--match=REGEX', String) { |s| match = Regexp.new(s) } op.on('-s', '--quiet', '--silent') { silent = true } op.on('-h', '--help') do puts(op.to_s) @@ -53,6 +57,9 @@ OptionParser.new('', 24, ' ') do |op| op.parse!(ARGV) end +match ||= %r/./ +comment.push('--comment', '') if comment.empty? + dst = ARGV.pop src = ARGV.dup @@ -63,6 +70,7 @@ src.each do |s| src_st = File.stat(s) if src_st.directory? Find.find(s) do |path| + path =~ match or next File.file?(path) or next dir = File.dirname(path) dir_st = File.stat(dir) @@ -137,7 +145,7 @@ thrs = jobs.times.map do |i| if dry_run || !silent names = job.map { |x| Shellwords.escape(x) } - cmd = [ 'sox', *names ] + cmd = [ 'sox', names[0], *compression, *comment, names[1] ] if stats cmd << 'stats' cmd << "2>#{Shellwords.escape(stats_out)}" @@ -151,7 +159,7 @@ thrs = jobs.times.map do |i| end end - cmd = [ 'sox', input, *compression, output ] + cmd = [ 'sox', input, *compression, *comment, output ] if stats cmd << 'stats' cmd = [ *cmd, { err: stats_out } ] diff --git a/bin/dtas-console b/bin/dtas-console index 00b5cd8..eedd0f0 100755 --- a/bin/dtas-console +++ b/bin/dtas-console @@ -1,5 +1,5 @@ #!/usr/bin/env ruby -# Copyright (C) 2013-2019 all contributors <dtas-all@nongnu.org> +# Copyright (C) all contributors <dtas-all@nongnu.org> # License: GPL-3.0+ <https://www.gnu.org/licenses/gpl-3.0.txt> # frozen_string_literal: true # @@ -11,21 +11,24 @@ require 'dtas/sigevent' require 'dtas/process' require 'dtas/format' include DTAS::Process -require 'yaml' begin require 'curses' rescue LoadError abort "please install the 'curses' RubyGem to use #$0" end +# workaround https://bugs.debian.org/958973 +$VERBOSE = nil if RUBY_VERSION.to_f < 3.0 + tsec = false se = DTAS::Sigevent.new trap(:WINCH) { se.signal } w = DTAS::UNIXClient.new w.req_ok('watch') c = DTAS::UNIXClient.new -cur = YAML.load(c.req('current')) +cur = DTAS.yaml_load(c.req('current')) readable = [ se, w, $stdin ] +set_title = (ENV['DISPLAY'] || ENV['WAYLAND_DISPLAY']) ? $stdout : nil # current rg mode rg_mode = DTAS::RGState::RG_MODE.keys.unshift("off") @@ -34,6 +37,7 @@ if (rg = cur["rg"]) && (rg = rg["mode"]) else rg_mode_i = 0 end +show_info = false def update_tfmt(prec, tsec) if tsec @@ -53,8 +57,6 @@ tfmt = update_tfmt(prec_step[prec_nr], tsec) events = [] interval = 1.0 / 10 ** prec_nr -pause = nil - def show_events(lineno, screen, events) Curses.setpos(lineno += 1, 0) Curses.clrtoeol @@ -114,14 +116,14 @@ def rg_string(rg, current) rv end -def may_fail(res, events) +def may_fail(c, req, events) + res = c.req(req) events << res if res != "OK" end pre_mute_vol = 1.0 enc_locale = Encoding.find("locale") $stdout.set_encoding(enc_locale) -enc_opts = { undef: :replace, invalid: :replace, replace: '?' } begin Curses.init_screen Curses.nonl @@ -135,7 +137,6 @@ begin pfmt = cur['format'] elapsed = samples = 0 fmt = total = '' - paused = false if current = cur['current'] infile = current['infile'] || current['command'] elapsed = DTAS.now - current['spawn_at'] @@ -150,7 +151,6 @@ begin end elsif cur['paused'] && infile = cur['current_paused'] fmt = "[paused] (#{fmt_to_s(pfmt)})" - paused = true infile = infile['command'] if Hash === infile if Array === infile infile, elapsed = infile @@ -169,7 +169,12 @@ begin # FS encoding != locale encoding, but we need to display an FS path # name to whatever locale the terminal is encoded to, so force it # and risk mojibake... - infile.encode(enc_locale, enc_opts) + infile.encode(enc_locale, + undef: :replace, invalid: :replace, replace: '?') + if set_title + dir, base = File.split(infile) + set_title.syswrite("\033]0;#{base} dtas-console\07") + end Curses.setpos(lineno += 1, 0) Curses.clrtoeol Curses.addstr(infile) @@ -206,6 +211,27 @@ begin Curses.addstr(extra.join(' ')) pre_mute_vol = cur_vol if cur_vol != 0 + if show_info && current && comments = current['comments'] + Curses.setpos(lineno += 1, 0) + Curses.clrtoeol + Curses.addstr('comments:') + comments.each do |k,v| + v = v.split(/\n+/) + k = k.dump if /[[:cntrl:]]/ =~ k + if first = v.shift + Curses.setpos(lineno += 1, 0) + Curses.clrtoeol + first = first.dump if /[[:cntrl:]]/ =~ first + Curses.addstr(" #{k}: #{first}") + v.each do |val| + val = val.dump if /[[:cntrl:]]/ =~ val + Curses.setpos(lineno += 1, 0) + Curses.clrtoeol + Curses.addstr(" #{val}") + end + end + end + end show_events(lineno, screen, events) Curses.refresh # draw and wait @@ -220,29 +246,28 @@ begin case event when "pause" if current - pause = current['infile'] || current['command'] + current['infile'] || current['command'] end when %r{\Afile } - pause = nil end events << "#{Time.now.strftime(tfmt)} #{event}" # something happened, refresh current # we could be more intelligent here, maybe, but too much work. - cur = YAML.load(c.req('current')) + cur = DTAS.yaml_load(c.req('current')) when $stdin # keybindings taken from mplayer / vi case key = Curses.getch - when "j" then c.req_ok("seek -5") - when "k" then c.req_ok("seek +5") + when "j" then may_fail(c, "seek -5", events) + when "k" then may_fail(c, "seek +5", events) when "q" then exit(0) - when Curses::KEY_DOWN then c.req_ok("seek -60") - when Curses::KEY_UP then c.req_ok("seek +60") - when Curses::KEY_LEFT then c.req_ok("seek -10") - when Curses::KEY_RIGHT then c.req_ok("seek +10") - when Curses::KEY_BACKSPACE then c.req_ok("seek 0") + when Curses::KEY_DOWN then may_fail(c, "seek -60", events) + when Curses::KEY_UP then may_fail(c, "seek +60", events) + when Curses::KEY_LEFT then may_fail(c, "seek -10", events) + when Curses::KEY_RIGHT then may_fail(c, "seek +10", events) + when Curses::KEY_BACKSPACE then may_fail(c, "seek 0", events) # yes, some of us have long audio files - when Curses::KEY_PPAGE then c.req_ok("seek +600") - when Curses::KEY_NPAGE then c.req_ok("seek -600") + when Curses::KEY_PPAGE then may_fail(c, "seek +600", events) + when Curses::KEY_NPAGE then may_fail(c, "seek -600", events) when '9' then c.req_ok('rg volume-=0.01') when '0' then c.req_ok('rg volume+=0.01') when '=' then c.req_ok('rg volume=1') @@ -253,8 +278,8 @@ begin when "f" then c.req_ok("rg fallback_gain-=1") when ">" then c.req_ok("tl next") when "<" then c.req_ok("tl prev") - when "!" then may_fail(c.req("cue prev"), events) - when "@" then may_fail(c.req("cue next"), events) + when "!" then may_fail(c, "cue prev", events) + when "@" then may_fail(c, "cue next", events) when "o" then tfmt = update_tfmt(prec_step[prec_nr], tsec = !tsec) when " " c.req("play_pause") @@ -276,6 +301,9 @@ begin interval = 1.0 / 10 ** prec_nr end when 27 # TODO readline/edit mode? + when 'i' + show_info = !show_info + Curses.clear if !show_info else Curses.setpos(screen.maxy - 1, 0) Curses.clrtoeol diff --git a/bin/dtas-ctl b/bin/dtas-ctl index 171576f..2d55e16 100755 --- a/bin/dtas-ctl +++ b/bin/dtas-ctl @@ -1,5 +1,5 @@ #!/usr/bin/env ruby -# Copyright (C) 2013-2016 all contributors <dtas-all@nongnu.org> +# Copyright (C) 2013-2020 all contributors <dtas-all@nongnu.org> # License: GPL-3.0+ <https://www.gnu.org/licenses/gpl-3.0.txt> # frozen_string_literal: true require 'dtas/unix_client' diff --git a/bin/dtas-cueedit b/bin/dtas-cueedit index 127b1a0..e176271 100755 --- a/bin/dtas-cueedit +++ b/bin/dtas-cueedit @@ -1,5 +1,5 @@ #!/usr/bin/env ruby -# Copyright (C) 2013-2016 all contributors <dtas-all@nongnu.org> +# Copyright (C) 2013-2020 all contributors <dtas-all@nongnu.org> # License: GPL-3.0+ <https://www.gnu.org/licenses/gpl-3.0.txt> # frozen_string_literal: true require 'tempfile' diff --git a/bin/dtas-enq b/bin/dtas-enq index f054687..f49d3f7 100755 --- a/bin/dtas-enq +++ b/bin/dtas-enq @@ -1,5 +1,5 @@ #!/usr/bin/env ruby -# Copyright (C) 2013-2016 all contributors <dtas-all@nongnu.org> +# Copyright (C) 2013-2020 all contributors <dtas-all@nongnu.org> # License: GPL-3.0+ <https://www.gnu.org/licenses/gpl-3.0.txt> # frozen_string_literal: true require 'dtas/unix_client' diff --git a/bin/dtas-mlib b/bin/dtas-mlib index 45c3d01..7a07794 100755 --- a/bin/dtas-mlib +++ b/bin/dtas-mlib @@ -1,5 +1,5 @@ #!/usr/bin/env ruby -# Copyright (C) 2015-2016 all contributors <dtas-all@nongnu.org> +# Copyright (C) 2015-2020 all contributors <dtas-all@nongnu.org> # License: GPL-3.0+ <https://www.gnu.org/licenses/gpl-3.0.txt> # frozen_string_literal: true usage = "#$0 [-d DATABASE-URI] ACTION [ARGS]" diff --git a/bin/dtas-msinkctl b/bin/dtas-msinkctl index 9abf2dc..79c7f26 100755 --- a/bin/dtas-msinkctl +++ b/bin/dtas-msinkctl @@ -1,8 +1,7 @@ #!/usr/bin/env ruby -# Copyright (C) 2013-2016 all contributors <dtas-all@nongnu.org> +# Copyright (C) all contributors <dtas-all@nongnu.org> # License: GPL-3.0+ <https://www.gnu.org/licenses/gpl-3.0.txt> # frozen_string_literal: true -require 'yaml' require 'dtas/unix_client' usage = "#$0 <active-set|active-add|active-sub|nonblock|active> SINK" c = DTAS::UNIXClient.new @@ -29,7 +28,7 @@ def filter(c, player_sinks, key) rv = [] player_sinks.each do |name| buf = c.req("sink cat #{name}") - sink = YAML.load(buf) + sink = DTAS.yaml_load(buf) rv << sink["name"] if sink[key] end rv diff --git a/bin/dtas-partstats b/bin/dtas-partstats index 388f7ba..6a0c9d4 100755 --- a/bin/dtas-partstats +++ b/bin/dtas-partstats @@ -1,5 +1,5 @@ #!/usr/bin/env ruby -# Copyright (C) 2013-2016 all contributors <dtas-all@nongnu.org> +# Copyright (C) all contributors <dtas-all@nongnu.org> # License: GPL-3.0+ <https://www.gnu.org/licenses/gpl-3.0.txt> # frozen_string_literal: true # TODO @@ -8,17 +8,11 @@ # - configurable output formatting # - Sequel/SQLite support require 'dtas/partstats' +require 'etc' infile = ARGV[0] or abort "usage: #$0 INFILE" ps = DTAS::PartStats.new(infile) -def nproc - require 'etc' - Etc.nprocessors -rescue NoMethodError - `nproc 2>/dev/null || echo 2`.to_i -end - -opts = { jobs: nproc } +opts = { jobs: Etc.nprocessors } stats = ps.run(opts) headers = ps.key_idx.to_a diff --git a/bin/dtas-player b/bin/dtas-player index ccb3969..c926e5f 100755 --- a/bin/dtas-player +++ b/bin/dtas-player @@ -1,9 +1,8 @@ #!/usr/bin/env ruby -# Copyright (C) 2013-2016 all contributors <dtas-all@nongnu.org> +# Copyright (C) all contributors <dtas-all@nongnu.org> # License: GPL-3.0+ <https://www.gnu.org/licenses/gpl-3.0.txt> # frozen_string_literal: true Thread.abort_on_exception = $stderr.sync = $stdout.sync = true -require 'yaml' require 'dtas/player' sock = (ENV["DTAS_PLAYER_SOCK"] || File.expand_path("~/.dtas/player.sock")) state = (ENV["DTAS_PLAYER_STATE"] || diff --git a/bin/dtas-readahead b/bin/dtas-readahead index 93ab8c9..c61d317 100755 --- a/bin/dtas-readahead +++ b/bin/dtas-readahead @@ -1,5 +1,5 @@ #!/usr/bin/env ruby -# Copyright (C) 2015-2019 all contributors <dtas-all@nongnu.org> +# Copyright (C) all contributors <dtas-all@nongnu.org> # License: GPL-3.0+ <https://www.gnu.org/licenses/gpl-3.0.txt> # frozen_string_literal: true # @@ -12,13 +12,11 @@ end @ffprobe = 'ffprobe' @avprobe = 'avprobe' -require 'yaml' require 'io/wait' require 'dtas/unix_client' require 'dtas/process' include DTAS::Process -include DTAS::SpawnFix trap(:CHLD) { DTAS::Process.reaper {} } trap(:INT) { exit(0) } trap(:TERM) { exit(0) } @@ -27,21 +25,9 @@ w.req_ok('watch') c = DTAS::UNIXClient.new @max_ra = 30 * 1024 * 1024 null = DTAS.null -@redir = { err: null, out: null, in: null }.freeze +@redir = { err: null, out: null, in: null, rlimit_cpu: [ 1, 2 ] }.freeze require 'pp' -if RUBY_VERSION.to_r >= '2.3'.to_r - # Old Rubies did FIONREAD, which breaks on SOCK_SEQPACKET - def wait_read(w, timeout) - w.to_io.wait_readable(timeout) - end -else - def wait_read(w, timeout) - r = IO.select([w], nil, nil, timeout) - r ? r[0] : nil - end -end - def seek_to_cur_pos(cur_pid, fp) cur_fd = [] fpst = fp.stat @@ -57,7 +43,7 @@ def seek_to_cur_pos(cur_pid, fp) end end rescue Errno::ENOENT => e # race, process is dead - return false + return nil rescue => e warn "error reading FDs from for PID:#{cur_pid}: #{e.message}" end @@ -71,7 +57,7 @@ def seek_to_cur_pos(cur_pid, fp) end pos rescue Errno::ENOENT => e # race, process is dead - return false + return nil end def children_of(ppid) @@ -122,7 +108,7 @@ def do_ra(fp, pos, w) len -= n # stop reading immediately if there's an event - if wait_read(w, 0) + if w.to_io.wait_readable(0) adj = @todo_ra pos += size break @@ -141,8 +127,8 @@ def do_open(path) when "---\n" buf << fp.read(fp.size - 4) Dir.chdir(File.dirname(path)) do - yml = YAML.load(buf) - x = yml['infile'] and return File.open(File.expand_path(x).freeze) + yml = DTAS.yaml_load(buf) + x = yml['infile'] and return File.open(-File.expand_path(x)) end end end @@ -156,12 +142,12 @@ begin @todo_ra = @max_ra t0 = DTAS.now fp = nil - cur = YAML.load(c.req('current')) + cur = DTAS.yaml_load(c.req('current')) while @todo_ra > 0 && fp.nil? if current = cur['current'] track = current['infile'] break unless track.kind_of?(String) - track.freeze + track = -track fp = work[track] ||= do_open(track) cur_pid = current['pid'] if fp @@ -178,7 +164,7 @@ begin end # queue has priority, work on it, first - queue = YAML.load(c.req('queue cat')) + queue = DTAS.yaml_load(c.req('queue cat')) while @todo_ra > 0 && track = queue.shift next unless track.kind_of?(String) fp = nil @@ -198,7 +184,7 @@ begin repeat = c.req('tl repeat').split[-1] while @todo_ra > 0 && idx && (cid = ids[idx]) fp = nil - track = c.req("tl get #{cid}").sub!(/\A1 \d+=/, '').freeze + track = -(c.req("tl get #{cid}").sub!(/\A1 \d+=/, '')) begin fp = work[track] ||= do_open(track) rescue SystemCallError @@ -210,7 +196,7 @@ begin end end idx or break - cur = YAML.load(c.req('current')) + cur = DTAS.yaml_load(c.req('current')) current = cur['current'] or break end if current @@ -220,10 +206,10 @@ begin timeout = 0 if timeout < 0 else work.each_value(&:close).clear - fp.close if fp && !fp.closed? + fp.close if fp fp = timeout = nil end - r = wait_read(w, timeout) + r = w.to_io.wait_readable(timeout) p w.res_wait if r rescue EOFError abort "dtas-player exited" diff --git a/bin/dtas-sinkedit b/bin/dtas-sinkedit index 61bb959..252270f 100755 --- a/bin/dtas-sinkedit +++ b/bin/dtas-sinkedit @@ -1,5 +1,5 @@ #!/usr/bin/env ruby -# Copyright (C) 2013-2016 all contributors <dtas-all@nongnu.org> +# Copyright (C) all contributors <dtas-all@nongnu.org> # License: GPL-3.0+ <https://www.gnu.org/licenses/gpl-3.0.txt> # frozen_string_literal: true require 'optparse' @@ -36,10 +36,10 @@ st_in = $stdin.stat buf = c.req(%W(sink cat #{name})) abort(buf) if buf =~ /\AERR/ -orig = YAML.load(buf) +orig = DTAS.yaml_load(buf) commit_update = lambda do |buf| - sink = YAML.load(buf) + sink = DTAS.yaml_load(buf) cmd = %W(sink ed #{name}) update_cmd_env(cmd, orig, sink) @@ -68,7 +68,6 @@ if st_in.file? || st_in.pipe? buf = $stdin.read commit_update.call(buf) else - include DTAS::SpawnFix tmp = tmpyaml tmp_path = tmp.path do_update = lambda { commit_update.call(File.read(tmp_path)) } diff --git a/bin/dtas-sourceedit b/bin/dtas-sourceedit index 713c466..1b3f4ee 100755 --- a/bin/dtas-sourceedit +++ b/bin/dtas-sourceedit @@ -1,5 +1,5 @@ #!/usr/bin/env ruby -# Copyright (C) 2013-2016 all contributors <dtas-all@nongnu.org> +# Copyright (C) all contributors <dtas-all@nongnu.org> # License: GPL-3.0+ <https://www.gnu.org/licenses/gpl-3.0.txt> # frozen_string_literal: true require 'optparse' @@ -36,10 +36,10 @@ st_in = $stdin.stat buf = c.req(%W(source cat #{name})) abort(buf) if buf =~ /\AERR/ -orig = YAML.load(buf) +orig = DTAS.yaml_load(buf) commit_update = lambda do |buf| - source = YAML.load(buf) + source = DTAS.yaml_load(buf) cmd = %W(source ed #{name}) update_cmd_env(cmd, orig, source) @@ -55,7 +55,6 @@ if st_in.file? || st_in.pipe? buf = $stdin.read commit_update.call(buf) else - include DTAS::SpawnFix tmp = tmpyaml tmp_path = tmp.path do_update = lambda { commit_update.call(File.read(tmp_path)) } diff --git a/bin/dtas-splitfx b/bin/dtas-splitfx index 839d273..17d915d 100755 --- a/bin/dtas-splitfx +++ b/bin/dtas-splitfx @@ -1,19 +1,20 @@ #!/usr/bin/env ruby -# Copyright (C) 2013-2016 all contributors <dtas-all@nongnu.org> +# Copyright (C) all contributors <dtas-all@nongnu.org> # License: GPL-3.0+ <https://www.gnu.org/licenses/gpl-3.0.txt> # frozen_string_literal: true -require 'yaml' require 'optparse' require 'dtas/splitfx' usage = "#$0 [-n|--dry-run][-j [JOBS]][-s|--silent] SPLITFX_FILE.yml [TARGET]" overrides = {} # FIXME: not tested default_target = "flac" -opts = { jobs: 1 } +opts = { jobs: nil } OptionParser.new('', 24, ' ') do |op| op.banner = usage op.on('-n', '--dry-run') { opts[:dryrun] = true } op.on('-j', '--jobs [JOBS]', Integer) { |val| opts[:jobs] = val } # nil==inf op.on('-s', '--quiet', '--silent') { opts[:silent] = true } + op.on('-S', '--stats', 'run stats every track') { opts[:stats] = true } + op.on('-f', '--filter FILTER') { |val| (opts[:filter] ||= []) << val } op.on('-D', '--no-dither') { opts[:no_dither] = true } op.on('-O', '--outdir OUTDIR') { |val| opts[:outdir] = val } op.on('-C', '--compression FACTOR') { |val| opts[:compression] = val } @@ -23,6 +24,9 @@ OptionParser.new('', 24, ' ') do |op| end op.on('-b', '--bits RATE', Integer) { |val| opts[:bits] = val } op.on('-t', '--trim POSITION') { |val| opts[:trim] = val.tr(',', ' ') } + op.on('-E', '--err-suffix SUFFIX') do |val| + opts[:err_suffix] = val.start_with?('.') ? val.freeze : ".#{val}" + end op.on('-p', '--sox-pipe') do opts[:sox_pipe] = true default_target = 'sox' @@ -30,13 +34,22 @@ OptionParser.new('', 24, ' ') do |op| op.parse!(ARGV) end +if opts[:sox_pipe] && opts[:err_suffix] + abort '--err-suffix and --sox-pipe are mutually exclusive' +end + +if opts[:jobs].nil? + require 'etc' + opts[:jobs] = Etc.nprocessors +end + args = [] ARGV.each do |arg| case arg when %r{\A(\w+)=(.*)\z} key, val = $1, $2 # only one that makes sense is infile=another_file - overrides[key] = YAML.load(val) + overrides[key] = DTAS.yaml_load(val) when %r{\A(\w+)\.(\w+)=(.*)\z} # comments.ARTIST='blah' top, key, val = $1, $2, $3 @@ -51,5 +64,5 @@ trap(:INT) { exit 130 } file = args.shift or abort usage target = args.shift || default_target splitfx = DTAS::SplitFX.new -splitfx.import(YAML.load(File.read(file)), overrides) +splitfx.import(DTAS.yaml_load(File.read(file)), overrides) splitfx.run(target, opts) diff --git a/bin/dtas-tl b/bin/dtas-tl index 1ce18de..c7f4c83 100755 --- a/bin/dtas-tl +++ b/bin/dtas-tl @@ -1,5 +1,5 @@ #!/usr/bin/env ruby -# Copyright (C) 2013-2016 all contributors <dtas-all@nongnu.org> +# Copyright (C) all contributors <dtas-all@nongnu.org> # License: GPL-3.0+ <https://www.gnu.org/licenses/gpl-3.0.txt> # frozen_string_literal: true # encoding: binary @@ -7,6 +7,8 @@ # itself is also unstable, but better than this one probably). require 'dtas/unix_client' require 'shellwords' +$stdout.binmode +$stderr.binmode def get_track_ids(c) track_ids = c.req("tl tracks") @@ -16,14 +18,18 @@ def get_track_ids(c) track_ids end -def fix_enc!(str, enc) - str.force_encoding(enc) - str.force_encoding(Encoding::ASCII_8BIT) unless str.valid_encoding? +def each_track(c) + get_track_ids(c).each_slice(128) do |track_ids| + res = c.req("tl get #{track_ids.join(' ')}") + res = Shellwords.split(res.sub!(/\A\d+ /, '')) + while line = res.shift + yield line + end + end end def do_edit(c) require 'dtas/edit_client' - require 'yaml' require 'tempfile' extend DTAS::EditClient tmp = Tempfile.new(%w(dtas-tl-edit .txt)) @@ -31,19 +37,14 @@ def do_edit(c) tmp_path = tmp.path orig = [] orig_idx = {} - enc = Encoding.default_external - get_track_ids(c).each_slice(128) do |track_ids| - res = c.req("tl get #{track_ids.join(' ')}") - res = Shellwords.split(res.sub!(/\A\d+ /, '')) - while line = res.shift - line.sub!(/\A(\d+)=/n, '') or abort "unexpected line=#{line.inspect}\n" - fix_enc!(line, enc) - track_id = $1.to_i - orig_idx[track_id] = orig.size - orig << track_id - tmp.write("#{Shellwords.escape(line)} =#{track_id}\n") - end + each_track(c) do |line| + line.sub!(/\A(\d+)=/n, '') or abort "unexpected line=#{line.inspect}\n" + track_id = $1.to_i + orig_idx[track_id] = orig.size + orig << track_id + line = Shellwords.escape(line) if line.include?("\n") + tmp.write("#{line} =#{track_id}\n") end tmp.flush @@ -51,7 +52,7 @@ def do_edit(c) # jump to the line of the currently playing track if using vi or vim # Patches for other editors welcome: dtas-all@nongnu.org if ed =~ /vim?\z/ - cur = YAML.load(c.req('current')) + cur = DTAS.yaml_load(c.req('current')) if tl = cur['tracklist'] if pos = tl['pos'] ed += " +#{pos + 1}" @@ -100,14 +101,8 @@ def do_edit(c) non_existent = [] add.each do |path, after_id| orig = path - path = Shellwords.split(path)[0] - path = File.expand_path(path) - unless File.exist?(path) - path = orig.dup - fix_enc!(path, enc) - path = Shellwords.split(path)[0] - path = File.expand_path(path) - end + path = File.expand_path(orig) + path = File.expand_path(Shellwords.split(path)[0]) unless File.exist?(path) if File.exist?(path) cmd = %W(tl add #{path}) @@ -140,15 +135,35 @@ end c = DTAS::UNIXClient.new case cmd = ARGV[0] -when "cat" - enc = Encoding.default_external - get_track_ids(c).each_slice(128) do |track_ids| - res = c.req("tl get #{track_ids.join(' ')}") - res = Shellwords.split(res.sub!(/\A\d+ /, '')) - while line = res.shift - fix_enc!(line, enc) - print "#{line}\n" +when 'cat' + each_track(c) { |line| print "#{line}\n" } +when 'prune' + c2 = nil + pending = 0 + each_track(c) do |line| + line.sub!(/\A(\d+)=/n, '') or abort "unexpected line=#{line.inspect}\n" + track_id = $1.to_i + ok = false + begin + st = File.stat(line) + ok = st.readable? && st.size? + rescue Errno::ENOENT, Errno::ENOTDIR, Errno::EACCES => e + warn "# #{line}: #{e.class}" + # raise other exceptions end + unless ok + c2 ||= DTAS::UNIXClient.new + if pending > 5 + c2.res_wait + pending -= 1 + end + pending += 1 + c2.req_start("tl remove #{track_id}") + end + end + while pending > 0 + c2.res_wait + pending -= 1 end when 'aac' # add-after-current ARGV.shift @@ -173,11 +188,11 @@ when "reto" re = ARGV[1] time = ARGV[2] re = Regexp.quote(re) if fixed - re = ignorecase ? %r{#{re}}i : %r{#{re}} - get_track_ids(c).each do |track_id| - res = c.req("tl get #{track_id}") - res.sub!(/\A1 \d+=/, '') - if re =~ res + re = ignorecase ? %r{#{re}}in : %r{#{re}}n + each_track(c) do |line| + line.sub!(/\A(\d+)=/n, '') or abort "unexpected line=#{line.inspect}\n" + track_id = $1 + if re =~ line req = %W(tl goto #{track_id}) req << time if time res = c.req(req) diff --git a/bin/dtas-xdelay b/bin/dtas-xdelay index 138f521..060752c 100755 --- a/bin/dtas-xdelay +++ b/bin/dtas-xdelay @@ -1,5 +1,5 @@ #!/usr/bin/env ruby -# Copyright (C) 2013-2016 all contributors <dtas-all@nongnu.org> +# Copyright (C) 2013-2020 all contributors <dtas-all@nongnu.org> # License: GPL-3.0+ <https://www.gnu.org/licenses/gpl-3.0.txt> # frozen_string_literal: true USAGE = "Usage: #$0 [-x FREQ] [-l] /dev/fd/LO /dev/fd/HI DELAY [DELAY ...]" |