about summary refs log tree commit homepage
path: root/lib/dtas/source/splitfx.rb
blob: adfde612896299ebe19de9f03abcffbf92a8a34c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# 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'
require_relative '../watchable'

class DTAS::Source::SplitFX < DTAS::Source::Sox # :nodoc:
  MAX_YAML_SIZE = 512 * 1024
  attr_writer :sox, :sfx
  include DTAS::Watchable if defined?(DTAS::Watchable)

  SPLITFX_DEFAULTS = SOX_DEFAULTS.merge(
    "command" => "#{SOX_DEFAULTS["command"]} $FX",
    "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
    Dir.chdir(File.dirname(ymlfile)) do # ugh
      @ymlhash = YAML.load(buf)
      @ymlhash['tracks'] ||= [ "t 0 default" ]
      sfx.import(@ymlhash)
      sfx.infile.replace(File.expand_path(sfx.infile))
    end
    @splitfx = sfx
    @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.sfx = sfx
    rv
  rescue => e
    warn "#{e.message} (#{e.class})"
    false
  end

  def __load_comments
    @ymlhash["comments"] || @sox.__load_comments
  end

  def command_string
    @ymlhash["command"] || super
  end

  def src_spawn(player_format, rg_state, opts)
    raise "BUG: #{self.inspect}#src_spawn called twice" if @to_io
    e = @env.merge!(player_format.to_env)
    @sfx.infile_env(e, @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