From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on dcvr.yhbt.net X-Spam-Level: X-Spam-ASN: AS22989 208.118.235.0/24 X-Spam-Status: No, score=-4.9 required=3.0 tests=AWL,BAYES_00,RCVD_IN_DNSWL_HI, URIBL_BLOCKED shortcircuit=no autolearn=unavailable version=3.3.2 X-Original-To: dtas-all@80x24.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by dcvr.yhbt.net (Postfix) with ESMTPS id 3CC381FA5C for ; Tue, 19 May 2015 09:21:43 +0000 (UTC) Received: from localhost ([::1]:44662 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YudiY-0003dZ-EJ for dtas-all@80x24.org; Tue, 19 May 2015 05:21:42 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52043) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YudiU-0003d7-Ve for dtas-all@nongnu.org; Tue, 19 May 2015 05:21:40 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1YudiR-0003hU-Po for dtas-all@nongnu.org; Tue, 19 May 2015 05:21:38 -0400 Received: from dcvr.yhbt.net ([64.71.152.64]:49930) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YudiR-0003hO-HY for dtas-all@nongnu.org; Tue, 19 May 2015 05:21:35 -0400 Received: from localhost (dcvr.yhbt.net [127.0.0.1]) by dcvr.yhbt.net (Postfix) with ESMTP id 5323C1FA5C; Tue, 19 May 2015 09:21:34 +0000 (UTC) From: Eric Wong To: Subject: [PATCH] source/splitfx: allow watching extra external scripts Date: Tue, 19 May 2015 09:21:33 +0000 Message-Id: <1432027293-14883-1-git-send-email-e@80x24.org> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 64.71.152.64 Cc: Eric Wong X-BeenThere: dtas-all@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dtas-all-bounces+dtas-all=80x24.org@nongnu.org Sender: dtas-all-bounces+dtas-all=80x24.org@nongnu.org Since writing nested shell commands inside YAML is subject to all sorts of strange quoting rules, encourage users to rely on external scripts which the YAML file refers to instead. These scripts can be written in any reasonable scripting language capable of executing other commands. This allows transparently monitoring things such as `my-script.rb' in the below example when playing my-splitfx.yml via dtas-player: --------------------- my-splitfx.yml ----------------------- infile: input.flac command: $INDIR/my-script.rb "$INFILE" ... --------------------- my-script.rb -------------------------- #!/usr/bin/ruby require 'shellwords' infile = ARGV.shift ch = %W(sox #{infile} -p).concat((ENV['TRIMFX'] || '').shellsplit) fx = %W(highpass 25 gain 9) l = ch.dup.concat(%W(remix 1v1)).concat(fx).concat(%w(contrast 30)) r = ch.dup.concat(%W(remix 2v1)).concat(fx).concat(%w(contrast 0)) cmd = %W(sox -M |#{l.shelljoin} |#{r.shelljoin}) cmd.concat((ENV['SOXFMT'] || '-p').shellsplit) cmd.concat(%w(- stats)) warn cmd.inspect exec *cmd --- lib/dtas/source/splitfx.rb | 14 ++++++++++++++ lib/dtas/splitfx.rb | 10 +++++----- lib/dtas/watchable.rb | 21 ++++++++++++++++----- 3 files changed, 35 insertions(+), 10 deletions(-) diff --git a/lib/dtas/source/splitfx.rb b/lib/dtas/source/splitfx.rb index b7b9b86..02c3a9d 100644 --- a/lib/dtas/source/splitfx.rb +++ b/lib/dtas/source/splitfx.rb @@ -17,6 +17,7 @@ class DTAS::Source::SplitFX < DTAS::Source::Sox # :nodoc: def initialize(sox = DTAS::Source::Sox.new) command_init(SPLITFX_DEFAULTS) + @watch_extra = [] @sox = sox end @@ -65,6 +66,19 @@ class DTAS::Source::SplitFX < DTAS::Source::Sox # :nodoc: e = @env.merge!(player_format.to_env) @sfx.infile_env(e, @sox.infile) + # watch any scripts or files the command in the YAML file refers to + if c = @sfx.command + @sfx.expand_cmd(e, c).each do |f| + File.readable?(f) and @watch_extra << f + end + end + + # allow users to specify explicit depdendencies to watch for edit + case extra = @ymlhash['deps'] + when Array, String + @watch_extra.concat(Array(extra)) + end + # make sure these are visible to the "current" command... e["TRIMFX"] = trimfx e["RGFX"] = rg_state.effect(self) || nil diff --git a/lib/dtas/splitfx.rb b/lib/dtas/splitfx.rb index 5a1431a..cc459ae 100644 --- a/lib/dtas/splitfx.rb +++ b/lib/dtas/splitfx.rb @@ -14,7 +14,7 @@ class DTAS::SplitFX # :nodoc: '$TRIMFX $FX $RATEFX $DITHERFX' include DTAS::Process include DTAS::XS - attr_reader :infile, :env + attr_reader :infile, :env, :command class UTrim attr_reader :env, :comments @@ -229,11 +229,11 @@ class DTAS::SplitFX # :nodoc: sub_env_s = sub_env.inject("") { |s,(k,v)| s << "#{k}=#{v} " } env['SOXFMT'] = '-tsox' sub_env['OUTFMT'] = env.delete('OUTFMT') - show_cmd = [ _expand_cmd(env, player_cmd), '|', '(', "#{sub_env_s};", - _expand_cmd(env.merge(sub_env), command), ')' ].flatten + show_cmd = [ expand_cmd(env, player_cmd), '|', '(', "#{sub_env_s};", + expand_cmd(env.merge(sub_env), command), ')' ].flatten command = "#{player_cmd} | (#{sub_env_s}; #{command})" else - show_cmd = _expand_cmd(env, command) + show_cmd = expand_cmd(env, command) end echo = "echo #{xs(show_cmd)}" @@ -397,7 +397,7 @@ class DTAS::SplitFX # :nodoc: env["INBASE"] = xs(base) end - def _expand_cmd(env, command) + def expand_cmd(env, command) Shellwords.split(command).map do |arg| qx(env, "printf %s \"#{arg}\"") end diff --git a/lib/dtas/watchable.rb b/lib/dtas/watchable.rb index cc6c018..36e8644 100644 --- a/lib/dtas/watchable.rb +++ b/lib/dtas/watchable.rb @@ -18,7 +18,8 @@ module DTAS::Watchable def readable_iter or_call = false while event = take(true) # drain the buffer - if (event.mask & FLAGS) != 0 && @watching[1] == event.name + w = @watches[event.wd] or next + if (event.mask & FLAGS) != 0 && w[event.name] or_call = true end end @@ -31,19 +32,29 @@ module DTAS::Watchable end # we must watch the directory, since - def watch_file(path, blk) + def watch_files(paths, blk) + @watches = {} # wd -> { basename -> true } @on_readable = blk - @watching = File.split(File.expand_path(path)) - add_watch(@watching[0], FLAGS) + @dir2wd = {} + Array(paths).each do |path| + watchdir, watchbase = File.split(File.expand_path(path)) + wd = @dir2wd[watchdir] ||= add_watch(watchdir, FLAGS) + m = @watches[wd] ||= {} + m[watchbase] = true + end end end def watch_begin(blk) @ino = InotifyReadableIter.new - @ino.watch_file(@infile, blk) + @ino.watch_files(@watch_extra << @infile, blk) @ino end + def watch_extra(paths) + @ino.watch_extra(paths) + end + # Closing the inotify descriptor (instead of using inotify_rm_watch) # is cleaner because it avoids EINVAL on race conditions in case # a directory is deleted: https://lkml.org/lkml/2007/7/9/3 -- EW