From a462961df2088af99e2e815ad60b8d838c9d062d Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Sun, 28 Dec 2014 00:43:07 +0000 Subject: source/splitfx: restart source on YAML modifications Since splitfx YAML files are intended to be frequently edited and modified by the user, we'll support automatically restarting the source when the user saves changes via their favorite $EDITOR This change is only for Linux users. However, sleepy_penguin supports kqueue nowadays so a patch to support such functionality would be appreciated. --- lib/dtas/player.rb | 7 ++++++ lib/dtas/source/splitfx.rb | 2 ++ lib/dtas/source/watchable.rb | 54 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+) create mode 100644 lib/dtas/source/watchable.rb (limited to 'lib/dtas') diff --git a/lib/dtas/player.rb b/lib/dtas/player.rb index 0ae8cef..ea48926 100644 --- a/lib/dtas/player.rb +++ b/lib/dtas/player.rb @@ -385,6 +385,7 @@ class DTAS::Player # :nodoc: end def next_source(source_spec) + @current.respond_to?(:watch_end) and @current.watch_end(@srv) @current = nil if source_spec case source_spec @@ -413,6 +414,12 @@ class DTAS::Player # :nodoc: dst = @sink_buf pending.dst_assoc(dst) pending.spawn(@format, @rg, out: dst.wr, in: "/dev/null") + + # watch and restart on modifications + pending.respond_to?(:watch_begin) and + @srv.wait_ctl(pending.watch_begin(method(:__current_requeue)), + :wait_readable) + @current = pending @srv.wait_ctl(dst, :wait_readable) wall(msg) diff --git a/lib/dtas/source/splitfx.rb b/lib/dtas/source/splitfx.rb index ad9e7c1..a0899f3 100644 --- a/lib/dtas/source/splitfx.rb +++ b/lib/dtas/source/splitfx.rb @@ -3,10 +3,12 @@ require 'yaml' require_relative 'sox' require_relative '../splitfx' +require_relative 'watchable' class DTAS::Source::SplitFX < DTAS::Source::Sox # :nodoc: MAX_YAML_SIZE = 512 * 1024 attr_writer :sox + include DTAS::Source::Watchable if defined?(DTAS::Source::Watchable) SPLITFX_DEFAULTS = SOX_DEFAULTS.merge("tryorder" => 3) diff --git a/lib/dtas/source/watchable.rb b/lib/dtas/source/watchable.rb new file mode 100644 index 0000000..3ff9ef8 --- /dev/null +++ b/lib/dtas/source/watchable.rb @@ -0,0 +1,54 @@ +# Copyright (C) 2014, all contributors +# License: GPLv3 or later +begin + require 'sleepy_penguin' +rescue LoadError +end + +# used to restart DTAS::Source::SplitFX processing in dtas-player +# if the YAML file is edited +module DTAS::Source::Watchable + class InotifyReadableIter < SleepyPenguin::Inotify + def self.new + super(:CLOEXEC) + end + + FLAGS = CLOSE_WRITE | MOVED_TO + + def readable_iter + or_call = false + while event = take(true) # drain the buffer + if (event.mask & FLAGS) != 0 && @watching[1] == event.name + or_call = true + end + end + if or_call && @on_readable + @on_readable.call + :delete + else + :wait_readable + end + end + + # we must watch the directory, since + def watch_file(path, blk) + @on_readable = blk + @watching = File.split(File.expand_path(path)) + add_watch(@watching[0], FLAGS) + end + end + + def watch_begin(blk) + @ino = InotifyReadableIter.new + @ino.watch_file(@infile, blk) + @ino + 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 + def watch_end(srv) + srv.wait_ctl(@ino, :delete) + @ino = @ino.close + end +end if defined?(SleepyPenguin::Inotify) -- cgit v1.2.3-24-ge0c7