diff options
-rw-r--r-- | Documentation/dtas-sourceedit.txt | 16 | ||||
-rwxr-xr-x | bin/dtas-sourceedit | 84 | ||||
-rw-r--r-- | lib/dtas/source/splitfx.rb | 4 | ||||
-rw-r--r-- | lib/dtas/watchable.rb (renamed from lib/dtas/source/watchable.rb) | 2 |
4 files changed, 81 insertions, 25 deletions
diff --git a/Documentation/dtas-sourceedit.txt b/Documentation/dtas-sourceedit.txt index 4335f14..cff3bbc 100644 --- a/Documentation/dtas-sourceedit.txt +++ b/Documentation/dtas-sourceedit.txt @@ -17,6 +17,22 @@ a pipe or file, it is parsed as YAML and fed to the dtas-player(1) instance non-interactively. This is useful for loading various profiles from the filesystem. +On Linux machines with the sleepy_penguin RubyGem installed, inotify(7) +is used to monitor the file for changes while the text exitor is running. +Each time a user finishes saving a file, changes are committed immediately. +This behavior may be disabled by using the -N or --no-watch command-line +switch. + +# OPTIONS +-N, \--no-watch +: Disable inotify(7) support on Linux systems + +-n, \--dry-run +: Only print commands which would be sent to dtas-player + +-V, \--verbose +: Print out commands as they are sent to dtas-player + # EXAMPLES Invoking dtas-sourceedit will spawn your favorite text editor on "sox": diff --git a/bin/dtas-sourceedit b/bin/dtas-sourceedit index b411b11..1980141 100755 --- a/bin/dtas-sourceedit +++ b/bin/dtas-sourceedit @@ -1,16 +1,32 @@ #!/usr/bin/env ruby -# Copyright (C) 2013-2014, Eric Wong <e@80x24.org> and all contributors +# Copyright (C) 2013-2015, all contributors <dtas-all@nongnu.org> # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt) +require 'optparse' require 'dtas/edit_client' +require 'dtas/sigevent' +require 'dtas/watchable' include DTAS::EditClient c = client_socket sources = c.req('source ls') || "(unknown)" -usage = "Usage: #{DTAS_PROGNAME} [-n|--dry-run][-V|--verbose] SOURCENAME\n" \ - "available SOURCENAME values: #{sources}" +usage = "Usage: #{DTAS_PROGNAME} [OPTIONS] SOURCENAME\n" \ + "available SOURCENAME values: #{sources}\n" \ -# use a real option parser if we have anything more complex -dry_run = !!(ARGV.delete('-n') || ARGV.delete('--dry-run')) -verbose = !!(ARGV.delete('-V') || ARGV.delete('--verbose')) +dry_run = verbose = false +watch = defined?(DTAS::Watchable) +OptionParser.new('', 24, ' ') do |op| + op.banner = usage + watch and + op.on('-N', '--no-watch', 'disable inotify support') { watch = false } + + op.on('-n', '--dry-run', 'only print commands, do not run them') { + dry_run = true + } + op.on('-V', '--verbose', 'print out commands sent to change the source') { + verbose = true + } + op.on('-h', '--help') { puts(op.to_s); exit } + op.parse!(ARGV) +end ARGV.size <= 1 or abort usage name = ARGV[0] || "sox" @@ -21,27 +37,51 @@ buf = c.req(%W(source cat #{name})) abort(buf) if buf =~ /\AERR/ orig = YAML.load(buf) +commit_update = lambda do |buf| + source = YAML.load(buf) + cmd = %W(source ed #{name}) + update_cmd_env(cmd, orig, source) + + # nil OK + %w(tryorder command).each { |field| cmd << "#{field}=#{source[field]}" } + + warn(Shellwords.join(cmd)) if verbose || dry_run + c.req_ok(cmd) unless dry_run + orig = source +end + if st_in.file? || st_in.pipe? buf = $stdin.read + commit_update.call(buf) else tmp = tmpyaml + tmp_path = tmp.path + do_update = lambda { commit_update.call(File.read(tmp_path)) } tmp.write(buf << DTAS_DISCLAIMER) - cmd = "#{editor} #{tmp.path}" - system(cmd) or abort "#{cmd} failed: #$?" - buf = File.read(tmp.path) -end + cmd = "#{editor} #{tmp_path}" -source = YAML.load(buf) -cmd = %W(source ed #{name}) -update_cmd_env(cmd, orig, source) + sev = DTAS::Sigevent.new + rset = [ sev ] + if watch + ino = DTAS::Watchable::InotifyReadableIter.new + ino.watch_file(tmp_path, do_update) + rset << ino + end -# nil OK -%w(tryorder command).each do |field| - cmd << "#{field}=#{source[field]}" + trap(:CHLD) { sev.signal } + pid = Process.spawn(cmd) + begin + r = IO.select(rset) or next + r[0].each do |io| + case io + when sev + _, status = Process.waitpid2(pid) + status.success? or abort "#{cmd} failed: #{status.inspect}" + do_update.call + exit + when ino + ino.readable_iter # calls do_update + end + end + end while true end - -if verbose || dry_run - warn Shellwords.join(cmd) -end - -c.req_ok(cmd) unless dry_run diff --git a/lib/dtas/source/splitfx.rb b/lib/dtas/source/splitfx.rb index 19b2c16..80d8473 100644 --- a/lib/dtas/source/splitfx.rb +++ b/lib/dtas/source/splitfx.rb @@ -3,12 +3,12 @@ require 'yaml' require_relative 'sox' require_relative '../splitfx' -require_relative 'watchable' +require_relative '../watchable' class DTAS::Source::SplitFX < DTAS::Source::Sox # :nodoc: MAX_YAML_SIZE = 512 * 1024 attr_writer :sox, :sfx - include DTAS::Source::Watchable if defined?(DTAS::Source::Watchable) + include DTAS::Watchable if defined?(DTAS::Watchable) SPLITFX_DEFAULTS = SOX_DEFAULTS.merge( "command" => "#{SOX_DEFAULTS["command"]} $FX", diff --git a/lib/dtas/source/watchable.rb b/lib/dtas/watchable.rb index 3ff9ef8..d4c384c 100644 --- a/lib/dtas/source/watchable.rb +++ b/lib/dtas/watchable.rb @@ -7,7 +7,7 @@ end # used to restart DTAS::Source::SplitFX processing in dtas-player # if the YAML file is edited -module DTAS::Source::Watchable +module DTAS::Watchable class InotifyReadableIter < SleepyPenguin::Inotify def self.new super(:CLOEXEC) |