about summary refs log tree commit homepage
path: root/lib/dtas
diff options
context:
space:
mode:
Diffstat (limited to 'lib/dtas')
-rw-r--r--lib/dtas/format.rb1
-rw-r--r--lib/dtas/player.rb11
-rw-r--r--lib/dtas/player/client_handler.rb4
-rw-r--r--lib/dtas/source.rb145
-rw-r--r--lib/dtas/source/cmd.rb (renamed from lib/dtas/source/command.rb)2
-rw-r--r--lib/dtas/source/file.rb63
-rw-r--r--lib/dtas/source/mp3gain.rb (renamed from lib/dtas/source/mp3.rb)2
-rw-r--r--lib/dtas/source/sox.rb100
8 files changed, 175 insertions, 153 deletions
diff --git a/lib/dtas/format.rb b/lib/dtas/format.rb
index 83a541a..a6e424b 100644
--- a/lib/dtas/format.rb
+++ b/lib/dtas/format.rb
@@ -75,6 +75,7 @@ class DTAS::Format # :nodoc:
     ivars_to_hash(SIVS)
   end
 
+  # FIXME, move to per-source (sox/avconv/ffmpeg)
   def from_file(path)
     @channels = qx(%W(soxi -c #{path})).to_i
     @type = qx(%W(soxi -t #{path})).strip
diff --git a/lib/dtas/player.rb b/lib/dtas/player.rb
index c6d6027..57976c2 100644
--- a/lib/dtas/player.rb
+++ b/lib/dtas/player.rb
@@ -5,7 +5,8 @@ require 'yaml'
 require 'shellwords'
 require_relative '../dtas'
 require_relative 'source'
-require_relative 'source/command'
+require_relative 'source/sox'
+require_relative 'source/cmd'
 require_relative 'sink'
 require_relative 'unix_server'
 require_relative 'buffer'
@@ -304,17 +305,17 @@ class DTAS::Player # :nodoc:
 
       case source_spec
       when String
-        @current = DTAS::Source.new(source_spec)
+        @current = DTAS::Source::Sox.new(source_spec)
         echo(%W(file #{@current.infile}))
       when Array
-        @current = DTAS::Source.new(*source_spec)
+        @current = DTAS::Source::Sox.new(*source_spec)
         echo(%W(file #{@current.infile} #{@current.offset_samples}s))
       else
-        @current = DTAS::Source::Command.new(source_spec["command"])
+        @current = DTAS::Source::Cmd.new(source_spec["command"])
         echo(%W(command #{@current.command_string}))
       end
 
-      if DTAS::Source === @current
+      if DTAS::Source::Sox === @current
         @current.command = @srccmd if @srccmd
         @current.env = @srcenv.dup unless @srcenv.empty?
       end
diff --git a/lib/dtas/player/client_handler.rb b/lib/dtas/player/client_handler.rb
index cddbe4c..44f0b57 100644
--- a/lib/dtas/player/client_handler.rb
+++ b/lib/dtas/player/client_handler.rb
@@ -204,7 +204,7 @@ module DTAS::Player::ClientHandler # :nodoc:
       # this offset in the @current.format (not player @format)
       @queue.unshift([ @current.infile, "#{__current_decoded_samples}s" ])
     else
-      # DTAS::Source::Command (hash), just rerun it
+      # DTAS::Source::Cmd (hash), just rerun it
       @queue.unshift(@current.to_hsh)
     end
     # We also want to hard drop the buffer so we do not get repeated audio.
@@ -424,7 +424,7 @@ module DTAS::Player::ClientHandler # :nodoc:
     case msg.shift
     when "cat"
       io.emit({
-        "command" => @srccmd || DTAS::Source::SOURCE_DEFAULTS["command"],
+        "command" => @srccmd || DTAS::Source::Sox::SOX_DEFAULTS["command"],
         "env" => @srcenv,
       }.to_yaml)
     when "ed"
diff --git a/lib/dtas/source.rb b/lib/dtas/source.rb
index 747fa9f..1093b18 100644
--- a/lib/dtas/source.rb
+++ b/lib/dtas/source.rb
@@ -2,149 +2,6 @@
 # Copyright (C) 2013, Eric Wong <normalperson@yhbt.net>
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
 require_relative '../dtas'
-require_relative 'command'
-require_relative 'format'
-require_relative 'replaygain'
-require_relative 'process'
-require_relative 'serialize'
 
-# this is usually one input file
-class DTAS::Source # :nodoc:
-  attr_reader :infile
-  attr_reader :offset
-  require_relative 'source/common'
-  require_relative 'source/mp3'
-
-  include DTAS::Command
-  include DTAS::Process
-  include DTAS::Source::Common
-  include DTAS::Source::Mp3
-
-  SOURCE_DEFAULTS = COMMAND_DEFAULTS.merge(
-    "command" => 'exec sox "$INFILE" $SOXFMT - $TRIMFX $RGFX',
-    "comments" => nil,
-  )
-
-  SIVS = %w(infile comments command env)
-
-  def initialize(infile, offset = nil)
-    command_init(SOURCE_DEFAULTS)
-    @format = nil
-    @infile = infile
-    @offset = offset
-    @comments = nil
-    @samples = nil
-    @rg = nil
-  end
-
-  # this exists mainly to make the mpris interface easier, but it's not
-  # necessary, the mpris interface also knows the sample rate
-  def offset_us
-    (offset_samples / format.rate.to_f) * 1000000
-  end
-
-  # returns any offset in samples (relative to the original source file),
-  # likely zero unless seek was used
-  def offset_samples
-    return 0 unless @offset
-    case @offset
-    when /\A\d+s\z/
-      @offset.to_i
-    else
-      format.hhmmss_to_samples(@offset)
-    end
-  end
-
-  def precision
-    qx(%W(soxi -p #@infile), err: "/dev/null").to_i # sox.git f4562efd0aa3
-  rescue # fallback to parsing the whole output
-    s = qx(%W(soxi #@infile), err: "/dev/null")
-    s =~ /Precision\s+:\s*(\d+)-bit/
-    v = $1.to_i
-    return v if v > 0
-    raise TypeError, "could not determine precision for #@infile"
-  end
-
-  def format
-    @format ||= begin
-      fmt = DTAS::Format.new
-      fmt.from_file(@infile)
-      fmt.bits ||= precision
-      fmt
-    end
-  end
-
-  # A user may be downloading the file and start playing
-  # it before the download completes, this refreshes
-  def samples!
-    @samples = nil
-    samples
-  end
-
-  # This is the number of samples according to the samples in the source
-  # file itself, not the decoded output
-  def samples
-    @samples ||= qx(%W(soxi -s #@infile)).to_i
-  rescue => e
-    warn e.message
-    0
-  end
-
-  # just run soxi -a
-  def __load_comments
-    tmp = {}
-    case @infile
-    when String
-      err = ""
-      cmd = %W(soxi -a #@infile)
-      begin
-        qx(cmd, err: err).split(/\n/).each do |line|
-          key, value = line.split(/=/, 2)
-          key && value or next
-          # TODO: multi-line/multi-value/repeated tags
-          tmp[key.upcase] = value
-        end
-      rescue => e
-        if /FAIL formats: no handler for file extension/ =~ err
-          warn("#{xs(cmd)}: #{err}")
-        else
-          warn("#{e.message} (#{e.class})")
-        end
-        # TODO: fallbacks
-      end
-    end
-    tmp
-  end
-
-  def comments
-    @comments ||= __load_comments
-  end
-
-  def replaygain
-    @rg = DTAS::ReplayGain.new(comments) ||
-          DTAS::ReplayGain.new(mp3gain_comments)
-  end
-
-  def spawn(format, rg_state, opts)
-    raise "BUG: #{self.inspect}#spawn called twice" if @to_io
-    e = format.to_env
-    e["INFILE"] = @infile
-
-    # make sure these are visible to the "current" command...
-    @env["TRIMFX"] = @offset ? "trim #@offset" : nil
-    @env["RGFX"] = rg_state.effect(self) || nil
-    e.merge!(@rg.to_env) if @rg
-
-    @pid = dtas_spawn(e.merge!(@env), command_string, opts)
-  end
-
-  def to_hsh
-    to_hash.delete_if { |k,v| v == SOURCE_DEFAULTS[k] }
-  end
-
-  def to_hash
-    rv = ivars_to_hash(SIVS)
-    rv["samples"] = samples
-    rv
-  end
+module DTAS::Source # :nodoc:
 end
diff --git a/lib/dtas/source/command.rb b/lib/dtas/source/cmd.rb
index 930c5cf..2507101 100644
--- a/lib/dtas/source/command.rb
+++ b/lib/dtas/source/cmd.rb
@@ -6,7 +6,7 @@ require_relative '../source'
 require_relative '../command'
 require_relative '../serialize'
 
-class DTAS::Source::Command # :nodoc:
+class DTAS::Source::Cmd # :nodoc:
   require_relative '../source/common'
 
   include DTAS::Command
diff --git a/lib/dtas/source/file.rb b/lib/dtas/source/file.rb
new file mode 100644
index 0000000..472cb3d
--- /dev/null
+++ b/lib/dtas/source/file.rb
@@ -0,0 +1,63 @@
+# -*- encoding: binary -*-
+# Copyright (C) 2013, Eric Wong <normalperson@yhbt.net>
+# License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
+require_relative '../../dtas'
+require_relative '../source'
+require_relative '../command'
+require_relative '../format'
+require_relative '../process'
+
+module DTAS::Source::File # :nodoc:
+  attr_reader :infile
+  attr_reader :offset
+  require_relative 'common' # dtas/source/common
+  include DTAS::Command
+  include DTAS::Process
+  include DTAS::Source::Common
+
+  FILE_SIVS = %w(infile comments command env)
+
+  def source_file_init(infile, offset)
+    @format = nil
+    @infile = infile
+    @offset = offset
+    @comments = nil
+    @samples = nil
+    @rg = nil
+  end
+
+  # this exists mainly to make the mpris interface easier, but it's not
+  # necessary, the mpris interface also knows the sample rate
+  def offset_us
+    (offset_samples / format.rate.to_f) * 1000000
+  end
+
+  # returns any offset in samples (relative to the original source file),
+  # likely zero unless seek was used
+  def offset_samples
+    return 0 unless @offset
+    case @offset
+    when /\A\d+s\z/
+      @offset.to_i
+    else
+      format.hhmmss_to_samples(@offset)
+    end
+  end
+
+  # A user may be downloading the file and start playing
+  # it before the download completes, this refreshes
+  def samples!
+    @samples = nil
+    samples
+  end
+
+  def comments
+    @comments ||= __load_comments
+  end
+
+  def to_hash
+    rv = ivars_to_hash(FILE_SIVS)
+    rv["samples"] = samples
+    rv
+  end
+end
diff --git a/lib/dtas/source/mp3.rb b/lib/dtas/source/mp3gain.rb
index 7ceaf8a..03bc37a 100644
--- a/lib/dtas/source/mp3.rb
+++ b/lib/dtas/source/mp3gain.rb
@@ -3,7 +3,7 @@
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
 require_relative '../process'
 
-module DTAS::Source::Mp3 # :nodoc:
+module DTAS::Source::Mp3gain # :nodoc:
   include DTAS::Process
   # we use dBFS = 1.0 as scale (not 32768)
   def __mp3gain_peak(str)
diff --git a/lib/dtas/source/sox.rb b/lib/dtas/source/sox.rb
new file mode 100644
index 0000000..44b5f17
--- /dev/null
+++ b/lib/dtas/source/sox.rb
@@ -0,0 +1,100 @@
+# -*- encoding: binary -*-
+# Copyright (C) 2013, Eric Wong <normalperson@yhbt.net>
+# License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
+require_relative '../../dtas'
+require_relative '../source'
+require_relative '../replaygain'
+
+# this is usually one input file
+class DTAS::Source::Sox # :nodoc:
+  require_relative 'file'
+  require_relative 'mp3gain'
+
+  include DTAS::Source::File
+  include DTAS::Source::Mp3gain
+
+  SOX_DEFAULTS = COMMAND_DEFAULTS.merge(
+    "command" => 'exec sox "$INFILE" $SOXFMT - $TRIMFX $RGFX',
+    "comments" => nil,
+  )
+
+  def initialize(infile, offset = nil)
+    command_init(SOX_DEFAULTS)
+    source_file_init(infile, offset)
+  end
+
+  def precision
+    qx(%W(soxi -p #@infile), err: "/dev/null").to_i # sox.git f4562efd0aa3
+  rescue # fallback to parsing the whole output
+    s = qx(%W(soxi #@infile), err: "/dev/null")
+    s =~ /Precision\s+:\s*(\d+)-bit/
+    v = $1.to_i
+    return v if v > 0
+    raise TypeError, "could not determine precision for #@infile"
+  end
+
+  def format
+    @format ||= begin
+      fmt = DTAS::Format.new
+      fmt.from_file(@infile)
+      fmt.bits ||= precision
+      fmt
+    end
+  end
+
+  # This is the number of samples according to the samples in the source
+  # file itself, not the decoded output
+  def samples
+    @samples ||= qx(%W(soxi -s #@infile)).to_i
+  rescue => e
+    warn e.message
+    0
+  end
+
+  # just run soxi -a
+  def __load_comments
+    tmp = {}
+    case @infile
+    when String
+      err = ""
+      cmd = %W(soxi -a #@infile)
+      begin
+        qx(cmd, err: err).split(/\n/).each do |line|
+          key, value = line.split(/=/, 2)
+          key && value or next
+          # TODO: multi-line/multi-value/repeated tags
+          tmp[key.upcase] = value
+        end
+      rescue => e
+        if /FAIL formats: no handler for file extension/ =~ err
+          warn("#{xs(cmd)}: #{err}")
+        else
+          warn("#{e.message} (#{e.class})")
+        end
+      end
+    end
+    tmp
+  end
+
+  def replaygain
+    @rg = DTAS::ReplayGain.new(comments) ||
+          DTAS::ReplayGain.new(mp3gain_comments)
+  end
+
+  def spawn(format, rg_state, opts)
+    raise "BUG: #{self.inspect}#spawn called twice" if @to_io
+    e = format.to_env
+    e["INFILE"] = @infile
+
+    # make sure these are visible to the "current" command...
+    @env["TRIMFX"] = @offset ? "trim #@offset" : nil
+    @env["RGFX"] = rg_state.effect(self) || nil
+    e.merge!(@rg.to_env) if @rg
+
+    @pid = dtas_spawn(e.merge!(@env), command_string, opts)
+  end
+
+  def to_hsh
+    to_hash.delete_if { |k,v| v == SOX_DEFAULTS[k] }
+  end
+end