about summary refs log tree commit homepage
path: root/lib/dtas
diff options
context:
space:
mode:
authorEric Wong <e@80x24.org>2014-12-27 08:01:13 +0000
committerEric Wong <e@80x24.org>2014-12-27 09:02:15 +0000
commit6c025858196b348c83ddd50e9233eb85c86c71d6 (patch)
tree83fe17ab113d09f2da7fabc383cf4c2b0e75580a /lib/dtas
parenta8bb7abac5739a060e094f19d1dbc04e2c361b81 (diff)
downloaddtas-6c025858196b348c83ddd50e9233eb85c86c71d6.tar.gz
This allows splitfx users to test CUE breakpoints and run
file-specific effects without interrupting their normal flow.
Diffstat (limited to 'lib/dtas')
-rw-r--r--lib/dtas/player.rb4
-rw-r--r--lib/dtas/source/splitfx.rb92
-rw-r--r--lib/dtas/splitfx.rb8
3 files changed, 103 insertions, 1 deletions
diff --git a/lib/dtas/player.rb b/lib/dtas/player.rb
index 39e5abf..0ae8cef 100644
--- a/lib/dtas/player.rb
+++ b/lib/dtas/player.rb
@@ -8,6 +8,7 @@ require_relative 'source'
 require_relative 'source/sox'
 require_relative 'source/av'
 require_relative 'source/ff'
+require_relative 'source/splitfx'
 require_relative 'source/cmd'
 require_relative 'sink'
 require_relative 'unix_server'
@@ -44,9 +45,10 @@ class DTAS::Player # :nodoc:
     @current = nil
     @watchers = {}
     @source_map = {
-      "sox" => DTAS::Source::Sox.new,
+      "sox" => (sox = DTAS::Source::Sox.new),
       "av" => DTAS::Source::Av.new,
       "ff" => DTAS::Source::Ff.new,
+      "splitfx" => DTAS::Source::SplitFX.new(sox),
     }
     source_map_reload
   end
diff --git a/lib/dtas/source/splitfx.rb b/lib/dtas/source/splitfx.rb
new file mode 100644
index 0000000..ad9e7c1
--- /dev/null
+++ b/lib/dtas/source/splitfx.rb
@@ -0,0 +1,92 @@
+# Copyright (C) 2014, all contributors <dtas-all@nongnu.org>
+# License: GPLv3 or later <https://www.gnu.org/licenses/gpl-3.0.txt>
+require 'yaml'
+require_relative 'sox'
+require_relative '../splitfx'
+
+class DTAS::Source::SplitFX < DTAS::Source::Sox # :nodoc:
+  MAX_YAML_SIZE = 512 * 1024
+  attr_writer :sox
+
+  SPLITFX_DEFAULTS = SOX_DEFAULTS.merge("tryorder" => 3)
+
+  def initialize(sox = DTAS::Source::Sox.new)
+    command_init(SPLITFX_DEFAULTS)
+    @sox = sox
+  end
+
+  def try(ymlfile, offset = nil)
+    @splitfx = @ymlhash = nil
+    st = File.stat(ymlfile)
+    return false if !st.file? || st.size > MAX_YAML_SIZE
+
+    # read 4 bytes first to ensure we have a YAML file with a hash:
+    buf = ""
+    File.open(ymlfile, "rb") do |fp|
+      return false if fp.read(4, buf) != "---\n"
+      buf << fp.read
+    end
+
+    sfx = DTAS::SplitFX.new
+    begin
+      Dir.chdir(File.dirname(ymlfile)) do # ugh
+        sfx.import(@ymlhash = YAML.load(buf))
+        sfx.infile.replace(File.expand_path(sfx.infile))
+      end
+      @splitfx = sfx
+    rescue
+      return false
+    end
+    @infile = ymlfile
+    sox = @sox.try(sfx.infile, offset) or return false
+    rv = source_file_dup(ymlfile, offset)
+    rv.sox = sox
+    rv.env = sfx.env
+    rv
+  end
+
+  def __load_comments
+    @ymlhash["comments"] || @sox.__load_comments
+  end
+
+  def command_string
+    @ymlhash["command"] || @sox.command_string
+  end
+
+  def spawn(player_format, rg_state, opts)
+    raise "BUG: #{self.inspect}#spawn called twice" if @to_io
+    e = @env.merge!(player_format.to_env)
+    e["INFILE"] = @sox.infile
+
+    # make sure these are visible to the "current" command...
+    e["TRIMFX"] = @offset ? "trim #@offset" : nil
+    e["RGFX"] = rg_state.effect(self) || nil
+    e.merge!(@rg.to_env) if @rg
+
+    @pid = dtas_spawn(e, command_string, opts)
+  end
+
+  def to_hsh
+    to_hash.delete_if { |k,v| v == SPLITFX_DEFAULTS[k] }
+  end
+
+  def format
+    @sox.format
+  end
+
+  def samples!
+    @sox.samples!
+  end
+
+  def samples
+    @sox.samples
+  end
+
+  def source_defaults
+    SPLITFX_DEFAULTS
+  end
+
+  def cuebreakpoints
+    @splitfx.cuebreakpoints
+  end
+end
diff --git a/lib/dtas/splitfx.rb b/lib/dtas/splitfx.rb
index ac39233..9af3faf 100644
--- a/lib/dtas/splitfx.rb
+++ b/lib/dtas/splitfx.rb
@@ -12,6 +12,7 @@ class DTAS::SplitFX # :nodoc:
         '$TRIMFX $RATEFX $DITHERFX'
   include DTAS::Process
   include DTAS::XS
+  attr_reader :infile, :env
 
   class Skip < Struct.new(:tstart) # :nodoc:
     def commit(_)
@@ -76,6 +77,7 @@ class DTAS::SplitFX # :nodoc:
     }
     @tracks = []
     @infmt = nil # wait until input is assigned
+    @cuebp = nil # for playback
   end
 
   def _bool(hash, key)
@@ -334,4 +336,10 @@ class DTAS::SplitFX # :nodoc:
     end
     false
   end
+
+  def cuebreakpoints
+    rv = @cuebp and return rv
+    require_relative 'cue_index'
+    @cuebp = @tracks.map { |t| DTAS::CueIndex.new(1, "#{t.tstart}s") }
+  end
 end