about summary refs log tree commit homepage
diff options
context:
space:
mode:
authorEric Wong <normalperson@yhbt.net>2013-08-29 09:29:40 +0000
committerEric Wong <normalperson@yhbt.net>2013-08-29 09:50:36 +0000
commit0f73acc225656517526b317a05ecab7e1311141b (patch)
tree81a8a8e373df302cfa478a8af706d125dcc1cb1d
parent4bd49cda05b43fc68f9353620e3f018f1c07fcbb (diff)
downloaddtas-0f73acc225656517526b317a05ecab7e1311141b.tar.gz
We don't need it since IO#read(bytes, buf) will convert to
ASCII-8BIT anyways.  Everywhere else, we ensure path names are
already binary.  We do this mainly at the client layer before using
Shellwords to escape the paths.

We also must be careful about parsing output from soxi/avprobe
which can show us metadata in whatever encoding is in the file.
We must still handle data from parsing command output as binary,
as the encoding of file metadata tends to vary.

This also should buy us Syck compatibility for Ruby 1.9.3 users
on Debian systems where Ruby 1.9.3 still uses Syck.
-rwxr-xr-xbin/dtas-console1
-rwxr-xr-xbin/dtas-ctl3
-rwxr-xr-xbin/dtas-cueedit11
-rwxr-xr-xbin/dtas-enq1
-rwxr-xr-xbin/dtas-msinkctl1
-rwxr-xr-xbin/dtas-player1
-rwxr-xr-xbin/dtas-sinkedit1
-rwxr-xr-xbin/dtas-sourceedit1
-rwxr-xr-xbin/dtas-xdelay1
-rw-r--r--dtas-mpris.gemspec1
-rw-r--r--lib/dtas.rb1
-rw-r--r--lib/dtas/buffer.rb1
-rw-r--r--lib/dtas/buffer/read_write.rb1
-rw-r--r--lib/dtas/buffer/splice.rb1
-rw-r--r--lib/dtas/command.rb1
-rw-r--r--lib/dtas/compat_onenine.rb1
-rw-r--r--lib/dtas/disclaimer.rb1
-rw-r--r--lib/dtas/edit_client.rb1
-rw-r--r--lib/dtas/format.rb6
-rw-r--r--lib/dtas/pipe.rb1
-rw-r--r--lib/dtas/player.rb5
-rw-r--r--lib/dtas/player/client_handler.rb5
-rw-r--r--lib/dtas/process.rb10
-rw-r--r--lib/dtas/replaygain.rb1
-rw-r--r--lib/dtas/rg_state.rb1
-rw-r--r--lib/dtas/serialize.rb1
-rw-r--r--lib/dtas/sigevent.rb1
-rw-r--r--lib/dtas/sigevent/efd.rb1
-rw-r--r--lib/dtas/sigevent/pipe.rb1
-rw-r--r--lib/dtas/sink.rb1
-rw-r--r--lib/dtas/source.rb1
-rw-r--r--lib/dtas/source/av.rb1
-rw-r--r--lib/dtas/source/av_ff_common.rb19
-rw-r--r--lib/dtas/source/cmd.rb1
-rw-r--r--lib/dtas/source/common.rb1
-rw-r--r--lib/dtas/source/ff.rb1
-rw-r--r--lib/dtas/source/file.rb1
-rw-r--r--lib/dtas/source/mp3gain.rb3
-rw-r--r--lib/dtas/source/sox.rb11
-rw-r--r--lib/dtas/state_file.rb1
-rw-r--r--lib/dtas/unix_accepted.rb1
-rw-r--r--lib/dtas/unix_client.rb8
-rw-r--r--lib/dtas/unix_server.rb1
-rw-r--r--lib/dtas/util.rb1
-rw-r--r--lib/dtas/writable_iter.rb1
-rw-r--r--lib/dtas/xs.rb14
-rw-r--r--setup.rb1
-rw-r--r--test/covshow.rb1
-rw-r--r--test/helper.rb1
-rw-r--r--test/player_integration.rb1
-rw-r--r--test/test_buffer.rb1
-rw-r--r--test/test_format.rb1
-rw-r--r--test/test_format_change.rb1
-rw-r--r--test/test_player.rb1
-rw-r--r--test/test_player_client_handler.rb1
-rw-r--r--test/test_player_integration.rb1
-rw-r--r--test/test_process.rb8
-rw-r--r--test/test_rg_integration.rb1
-rw-r--r--test/test_rg_state.rb1
-rw-r--r--test/test_sink.rb1
-rw-r--r--test/test_sink_pipe_size.rb1
-rw-r--r--test/test_sink_tee_integration.rb1
-rw-r--r--test/test_source_av.rb1
-rw-r--r--test/test_source_sox.rb1
-rw-r--r--test/test_unixserver.rb1
-rw-r--r--test/test_util.rb1
66 files changed, 60 insertions, 97 deletions
diff --git a/bin/dtas-console b/bin/dtas-console
index 3b246bd..6d5672b 100755
--- a/bin/dtas-console
+++ b/bin/dtas-console
@@ -1,5 +1,4 @@
 #!/usr/bin/env ruby
-# -*- encoding: binary -*-
 # Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
 #
diff --git a/bin/dtas-ctl b/bin/dtas-ctl
index 1c0a242..267a873 100755
--- a/bin/dtas-ctl
+++ b/bin/dtas-ctl
@@ -1,10 +1,7 @@
 #!/usr/bin/env ruby
-# -*- encoding: binary -*-
 # Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
 require 'dtas/unix_client'
 
-# Unix paths are encoding agnostic
-ARGV.map! { |arg| arg.b }
 c = DTAS::UNIXClient.new
 puts c.req(ARGV)
diff --git a/bin/dtas-cueedit b/bin/dtas-cueedit
index ece4af1..8396cd5 100755
--- a/bin/dtas-cueedit
+++ b/bin/dtas-cueedit
@@ -1,16 +1,15 @@
 #!/usr/bin/env ruby
-# -*- encoding: binary -*-
 # Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
 require 'tempfile'
-require 'shellwords'
+require 'dtas/xs'
 usage = "Usage: #$0 FILENAME"
 editor = ENV["VISUAL"] || ENV["EDITOR"] || "vi"
 ARGV.size > 0 or abort usage
+include DTAS::XS
 
 def err_msg(cmd, status)
-  err_cmd = cmd.map { |f| Shellwords.escape(f) }.join(' ')
-  "E: #{err_cmd} failed: #{status.inspect}"
+  "E: #{xs(cmd)} failed: #{status.inspect}"
 end
 
 def x!(*cmd)
@@ -52,7 +51,7 @@ ARGV.each do |file|
     # avoid an expensive update if the user didn't change anything
     current = File.binread(tmp.path)
     if current == original
-      $stderr.puts "tags for #{Shellwords.escape(file)} unchanged" if $DEBUG
+      $stderr.puts "tags for #{xs(Array(file))} unchanged" if $DEBUG
       next
     end
 
@@ -68,7 +67,7 @@ ARGV.each do |file|
       warn err_msg(cmd, $?)
       warn "E: restoring original from backup"
       x!(*%W(metaflac --import-cuesheet-from=#{backup.path} #{file}))
-      warn "E: backup cuesheet restored, #{Shellwords.escape(file)} unchanged"
+      warn "E: backup cuesheet restored, #{xs(Array(file))} unchanged"
       exit(false)
     end
   ensure
diff --git a/bin/dtas-enq b/bin/dtas-enq
index 287c3f7..78829a4 100755
--- a/bin/dtas-enq
+++ b/bin/dtas-enq
@@ -1,5 +1,4 @@
 #!/usr/bin/env ruby
-# -*- encoding: binary -*-
 # Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
 require 'dtas/unix_client'
diff --git a/bin/dtas-msinkctl b/bin/dtas-msinkctl
index 00d8540..b417d0f 100755
--- a/bin/dtas-msinkctl
+++ b/bin/dtas-msinkctl
@@ -1,5 +1,4 @@
 #!/usr/bin/env ruby
-# -*- encoding: binary -*-
 # Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
 require 'yaml'
diff --git a/bin/dtas-player b/bin/dtas-player
index 75ec6a6..640d31c 100755
--- a/bin/dtas-player
+++ b/bin/dtas-player
@@ -1,5 +1,4 @@
 #!/usr/bin/env ruby
-# -*- encoding: binary -*-
 # Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
 Thread.abort_on_exception = $stderr.sync = $stdout.sync = true
diff --git a/bin/dtas-sinkedit b/bin/dtas-sinkedit
index 3e12415..93a4fe9 100755
--- a/bin/dtas-sinkedit
+++ b/bin/dtas-sinkedit
@@ -1,5 +1,4 @@
 #!/usr/bin/env ruby
-# -*- encoding: binary -*-
 # Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
 require 'dtas/edit_client'
diff --git a/bin/dtas-sourceedit b/bin/dtas-sourceedit
index 3de1c11..a511793 100755
--- a/bin/dtas-sourceedit
+++ b/bin/dtas-sourceedit
@@ -1,5 +1,4 @@
 #!/usr/bin/env ruby
-# -*- encoding: binary -*-
 # Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
 require 'dtas/edit_client'
diff --git a/bin/dtas-xdelay b/bin/dtas-xdelay
index 5ac63ae..3b57f44 100755
--- a/bin/dtas-xdelay
+++ b/bin/dtas-xdelay
@@ -1,5 +1,4 @@
 #!/usr/bin/env ruby
-# -*- encoding: binary -*-
 # Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
 USAGE = "Usage: #$0 [-x FREQ] [-l] /dev/fd/LO /dev/fd/HI DELAY [DELAY ...]"
diff --git a/dtas-mpris.gemspec b/dtas-mpris.gemspec
index c6dd808..48d0a28 100644
--- a/dtas-mpris.gemspec
+++ b/dtas-mpris.gemspec
@@ -1,4 +1,3 @@
-# -*- encoding: binary -*-
 # Copyright 2013, Eric Wong <normalperson@yhbt.net> and all contributors.
 # License: GPLv2 or later <http://www.gnu.org/licenses/gpl-2.0.txt>
 # This is GPLv2+ instead of GPLv3+ because ruby-dbus is LGPLv2.1 (only)
diff --git a/lib/dtas.rb b/lib/dtas.rb
index d51e8bd..02c9d16 100644
--- a/lib/dtas.rb
+++ b/lib/dtas.rb
@@ -1,4 +1,3 @@
-# -*- encoding: binary -*-
 # Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
 module DTAS # :nodoc:
diff --git a/lib/dtas/buffer.rb b/lib/dtas/buffer.rb
index 6ae3cfc..c9f096c 100644
--- a/lib/dtas/buffer.rb
+++ b/lib/dtas/buffer.rb
@@ -1,4 +1,3 @@
-# -*- encoding: binary -*-
 # Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
 require_relative '../dtas'
diff --git a/lib/dtas/buffer/read_write.rb b/lib/dtas/buffer/read_write.rb
index 5e816b2..1f1e4a7 100644
--- a/lib/dtas/buffer/read_write.rb
+++ b/lib/dtas/buffer/read_write.rb
@@ -1,4 +1,3 @@
-# -*- encoding: binary -*-
 # Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
 require 'io/wait'
diff --git a/lib/dtas/buffer/splice.rb b/lib/dtas/buffer/splice.rb
index 2cbd16d..18dfd82 100644
--- a/lib/dtas/buffer/splice.rb
+++ b/lib/dtas/buffer/splice.rb
@@ -1,4 +1,3 @@
-# -*- encoding: binary -*-
 # Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
 require 'io/wait'
diff --git a/lib/dtas/command.rb b/lib/dtas/command.rb
index b1b52ce..91b3c6f 100644
--- a/lib/dtas/command.rb
+++ b/lib/dtas/command.rb
@@ -1,4 +1,3 @@
-# -*- encoding: binary -*-
 # Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
 # common code for wrapping SoX/ecasound/... commands
diff --git a/lib/dtas/compat_onenine.rb b/lib/dtas/compat_onenine.rb
index f8040a5..d031252 100644
--- a/lib/dtas/compat_onenine.rb
+++ b/lib/dtas/compat_onenine.rb
@@ -1,4 +1,3 @@
-# -*- encoding: binary -*-
 # Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
 
diff --git a/lib/dtas/disclaimer.rb b/lib/dtas/disclaimer.rb
index 9a02a28..558bb19 100644
--- a/lib/dtas/disclaimer.rb
+++ b/lib/dtas/disclaimer.rb
@@ -1,4 +1,3 @@
-# -*- encoding: binary -*-
 # :enddoc:
 # Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
diff --git a/lib/dtas/edit_client.rb b/lib/dtas/edit_client.rb
index 50c8444..45300c1 100644
--- a/lib/dtas/edit_client.rb
+++ b/lib/dtas/edit_client.rb
@@ -1,4 +1,3 @@
-# -*- encoding: binary -*-
 # Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
 require 'tempfile'
diff --git a/lib/dtas/format.rb b/lib/dtas/format.rb
index 35682a7..690a21f 100644
--- a/lib/dtas/format.rb
+++ b/lib/dtas/format.rb
@@ -1,4 +1,3 @@
-# -*- encoding: binary -*-
 # Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
 # class represents an audio format (type/bits/channels/sample rate/...)
@@ -9,6 +8,7 @@ require_relative 'serialize'
 class DTAS::Format # :nodoc:
   include DTAS::Process
   include DTAS::Serialize
+
   NATIVE_ENDIAN = [1].pack("l") == [1].pack("l>") ? "big" : "little"
 
   attr_accessor :type # s32, f32, f64 ... any point in others?
@@ -63,10 +63,6 @@ class DTAS::Format # :nodoc:
     %W(-f #{@type}_#{endian2},#@channels,#@rate)
   end
 
-  def inspect
-    "<#{self.class}(#{Shellwords.join(to_sox_arg)})>"
-  end
-
   def to_hsh
     to_hash.delete_if { |k,v| v == FORMAT_DEFAULTS[k] }
   end
diff --git a/lib/dtas/pipe.rb b/lib/dtas/pipe.rb
index c3cebca..cd3ac46 100644
--- a/lib/dtas/pipe.rb
+++ b/lib/dtas/pipe.rb
@@ -1,4 +1,3 @@
-# -*- encoding: binary -*-
 # Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
 begin
diff --git a/lib/dtas/player.rb b/lib/dtas/player.rb
index 73342bb..ba42490 100644
--- a/lib/dtas/player.rb
+++ b/lib/dtas/player.rb
@@ -1,9 +1,9 @@
-# -*- encoding: binary -*-
 # Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
 require 'yaml'
 require 'shellwords'
 require_relative '../dtas'
+require_relative 'xs'
 require_relative 'source'
 require_relative 'source/sox'
 require_relative 'source/av'
@@ -18,6 +18,7 @@ require_relative 'state_file'
 
 class DTAS::Player # :nodoc:
   require_relative 'player/client_handler'
+  include DTAS::XS
   include DTAS::Player::ClientHandler
   attr_accessor :state_file
   attr_accessor :socket
@@ -52,7 +53,7 @@ class DTAS::Player # :nodoc:
   end
 
   def echo(msg)
-    msg = Shellwords.join(msg) if Array === msg
+    msg = xs(Array(msg))
     @watchers.delete_if do |io, _|
       if io.closed?
         true
diff --git a/lib/dtas/player/client_handler.rb b/lib/dtas/player/client_handler.rb
index f29db36..f601d46 100644
--- a/lib/dtas/player/client_handler.rb
+++ b/lib/dtas/player/client_handler.rb
@@ -1,7 +1,8 @@
-# -*- encoding: binary -*-
 # Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
+require_relative '../xs'
 module DTAS::Player::ClientHandler # :nodoc:
+  include DTAS::XS
 
   # returns true on success, wait_ctl arg on error
   def set_bool(io, kv, v)
@@ -116,7 +117,7 @@ module DTAS::Player::ClientHandler # :nodoc:
     name = msg[1]
     case msg[0]
     when "ls"
-      io.emit(Shellwords.join(@sinks.keys.sort))
+      io.emit(xs(@sinks.keys.sort))
     when "rm"
       sink = @sinks.delete(name) or return io.emit("ERR #{name} not found")
       drop_sink(sink)
diff --git a/lib/dtas/process.rb b/lib/dtas/process.rb
index 5b11f14..b90b318 100644
--- a/lib/dtas/process.rb
+++ b/lib/dtas/process.rb
@@ -1,11 +1,12 @@
-# -*- encoding: binary -*-
 # Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
-require 'shellwords'
 require 'io/wait'
 require_relative '../dtas'
+require_relative 'xs'
+
 module DTAS::Process # :nodoc:
   PIDS = {}
+  include DTAS::XS
 
   def self.reaper
     begin
@@ -60,7 +61,7 @@ module DTAS::Process # :nodoc:
     w.close
     if err_str
       we.close
-      res = ""
+      res = "".b
       want = { r => res, re => err_str }
       begin
         readable = IO.select(want.keys) or next
@@ -82,7 +83,6 @@ module DTAS::Process # :nodoc:
     _, status = Process.waitpid2(pid)
     return res if status.success?
     return status if no_raise
-    raise RuntimeError,
-          "`#{Shellwords.join(Array(cmd))}' failed: #{status.inspect}"
+    raise RuntimeError, "`#{xs(Array(cmd))}' failed: #{status.inspect}"
   end
 end
diff --git a/lib/dtas/replaygain.rb b/lib/dtas/replaygain.rb
index 8845b90..d3fa8ad 100644
--- a/lib/dtas/replaygain.rb
+++ b/lib/dtas/replaygain.rb
@@ -1,4 +1,3 @@
-# -*- encoding: binary -*-
 # Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
 #
diff --git a/lib/dtas/rg_state.rb b/lib/dtas/rg_state.rb
index bf6f972..a6c56f5 100644
--- a/lib/dtas/rg_state.rb
+++ b/lib/dtas/rg_state.rb
@@ -1,4 +1,3 @@
-# -*- encoding: binary -*-
 # Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
 #
diff --git a/lib/dtas/serialize.rb b/lib/dtas/serialize.rb
index 449c8d3..ceba005 100644
--- a/lib/dtas/serialize.rb
+++ b/lib/dtas/serialize.rb
@@ -1,4 +1,3 @@
-# -*- encoding: binary -*-
 # Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
 module DTAS::Serialize # :nodoc:
diff --git a/lib/dtas/sigevent.rb b/lib/dtas/sigevent.rb
index 282dad9..3800f4b 100644
--- a/lib/dtas/sigevent.rb
+++ b/lib/dtas/sigevent.rb
@@ -1,4 +1,3 @@
-# -*- encoding: binary -*-
 # Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
 begin
diff --git a/lib/dtas/sigevent/efd.rb b/lib/dtas/sigevent/efd.rb
index 1fef013..b108b89 100644
--- a/lib/dtas/sigevent/efd.rb
+++ b/lib/dtas/sigevent/efd.rb
@@ -1,4 +1,3 @@
-# -*- encoding: binary -*-
 # Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
 class DTAS::Sigevent < SleepyPenguin::EventFD # :nodoc:
diff --git a/lib/dtas/sigevent/pipe.rb b/lib/dtas/sigevent/pipe.rb
index d85a81b..bf2ba00 100644
--- a/lib/dtas/sigevent/pipe.rb
+++ b/lib/dtas/sigevent/pipe.rb
@@ -1,4 +1,3 @@
-# -*- encoding: binary -*-
 # Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
 class DTAS::Sigevent # :nodoc:
diff --git a/lib/dtas/sink.rb b/lib/dtas/sink.rb
index 0ce6237..9ccd8ea 100644
--- a/lib/dtas/sink.rb
+++ b/lib/dtas/sink.rb
@@ -1,4 +1,3 @@
-# -*- encoding: binary -*-
 # Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
 require 'yaml'
diff --git a/lib/dtas/source.rb b/lib/dtas/source.rb
index 4608150..d8f0170 100644
--- a/lib/dtas/source.rb
+++ b/lib/dtas/source.rb
@@ -1,4 +1,3 @@
-# -*- encoding: binary -*-
 # Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
 require_relative '../dtas'
diff --git a/lib/dtas/source/av.rb b/lib/dtas/source/av.rb
index 6005344..d44b1a9 100644
--- a/lib/dtas/source/av.rb
+++ b/lib/dtas/source/av.rb
@@ -1,4 +1,3 @@
-# -*- encoding: binary -*-
 # Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
 require_relative '../../dtas'
diff --git a/lib/dtas/source/av_ff_common.rb b/lib/dtas/source/av_ff_common.rb
index 666adbd..bcb8a0a 100644
--- a/lib/dtas/source/av_ff_common.rb
+++ b/lib/dtas/source/av_ff_common.rb
@@ -1,9 +1,9 @@
-# -*- encoding: binary -*-
 # Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
 require_relative '../../dtas'
 require_relative '../source'
 require_relative '../replaygain'
+require_relative '../xs'
 require_relative 'file'
 
 # Common code for libav (avconv/avprobe) and ffmpeg (and ffprobe)
@@ -12,6 +12,7 @@ require_relative 'file'
 # support JSON, so we have an ugly parser...
 module DTAS::Source::AvFfCommon # :nodoc:
   include DTAS::Source::File
+  include DTAS::XS
   AStream = Struct.new(:duration, :channels, :rate)
   AV_FF_TRYORDER = 1
 
@@ -35,16 +36,16 @@ module DTAS::Source::AvFfCommon # :nodoc:
     s = qx(@env, cmd, err_str: err, no_raise: true)
     return false if Process::Status === s
     return false if err =~ /Unable to find a suitable output format for/
-    s.scan(%r{^\[STREAM\]\n(.*?)\n\[/STREAM\]\n}m) do |_|
+    s.scan(%r{^\[STREAM\]\n(.*?)\n\[/STREAM\]\n}mn) do |_|
       stream = $1
       if stream =~ /^codec_type=audio$/
         as = AStream.new
         index = nil
-        stream =~ /^index=(\d+)\s*$/m and index = $1.to_i
-        stream =~ /^duration=([\d\.]+)\s*$/m and as.duration = $1.to_f
-        stream =~ /^channels=(\d)\s*$/m and as.channels = $1.to_i
-        stream =~ /^sample_rate=([\d\.]+)\s*$/m and as.rate = $1.to_i
-        index or raise "BUG: no audio index from #{Shellwords.join(cmd)}"
+        stream =~ /^index=(\d+)\s*$/nm and index = $1.to_i
+        stream =~ /^duration=([\d\.]+)\s*$/nm and as.duration = $1.to_f
+        stream =~ /^channels=(\d)\s*$/nm and as.channels = $1.to_i
+        stream =~ /^sample_rate=([\d\.]+)\s*$/nm and as.rate = $1.to_i
+        index or raise "BUG: no audio index from #{xs(cmd)}"
 
         # some streams have zero channels
         @astreams[index] = as if as.channels > 0 && as.rate > 0
@@ -52,9 +53,9 @@ module DTAS::Source::AvFfCommon # :nodoc:
     end
     s.scan(%r{^\[FORMAT\]\n(.*?)\n\[/FORMAT\]\n}m) do |_|
       f = $1
-      f =~ /^duration=([\d\.]+)\s*$/m and @duration = $1.to_f
+      f =~ /^duration=([\d\.]+)\s*$/nm and @duration = $1.to_f
       # TODO: multi-line/multi-value/repeated tags
-      f.gsub!(/^TAG:([^=]+)=(.*)$/i) { |_| @comments[$1.upcase] = $2 }
+      f.gsub!(/^TAG:([^=]+)=(.*)$/ni) { |_| @comments[$1.upcase] = $2 }
     end
     ! @astreams.empty?
   end
diff --git a/lib/dtas/source/cmd.rb b/lib/dtas/source/cmd.rb
index 3ea2049..3c409e9 100644
--- a/lib/dtas/source/cmd.rb
+++ b/lib/dtas/source/cmd.rb
@@ -1,4 +1,3 @@
-# -*- encoding: binary -*-
 # Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
 require_relative '../../dtas'
diff --git a/lib/dtas/source/common.rb b/lib/dtas/source/common.rb
index 7cc5f7c..03d1562 100644
--- a/lib/dtas/source/common.rb
+++ b/lib/dtas/source/common.rb
@@ -1,4 +1,3 @@
-# -*- encoding: binary -*-
 # Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
 module DTAS::Source::Common # :nodoc:
diff --git a/lib/dtas/source/ff.rb b/lib/dtas/source/ff.rb
index b8e6f6b..fa4bbf7 100644
--- a/lib/dtas/source/ff.rb
+++ b/lib/dtas/source/ff.rb
@@ -1,4 +1,3 @@
-# -*- encoding: binary -*-
 # Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
 require_relative '../../dtas'
diff --git a/lib/dtas/source/file.rb b/lib/dtas/source/file.rb
index d79dd88..3dadc67 100644
--- a/lib/dtas/source/file.rb
+++ b/lib/dtas/source/file.rb
@@ -1,4 +1,3 @@
-# -*- encoding: binary -*-
 # Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
 require_relative '../../dtas'
diff --git a/lib/dtas/source/mp3gain.rb b/lib/dtas/source/mp3gain.rb
index fe0b642..b48c759 100644
--- a/lib/dtas/source/mp3gain.rb
+++ b/lib/dtas/source/mp3gain.rb
@@ -1,4 +1,3 @@
-# -*- encoding: binary -*-
 # Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
 require_relative '../process'
@@ -15,7 +14,7 @@ module DTAS::Source::Mp3gain # :nodoc:
     tmp = {}
     case @infile
     when String
-      @infile =~ /\.mp[g23]\z/i or return
+      @infile =~ /\.mp[g23]\z/in or return
       qx(%W(mp3gain -s c #@infile)).split(/\n/).each do |line|
         case line
         when /^Recommended "(Track|Album)" dB change:\s*(\S+)/
diff --git a/lib/dtas/source/sox.rb b/lib/dtas/source/sox.rb
index d030628..0001689 100644
--- a/lib/dtas/source/sox.rb
+++ b/lib/dtas/source/sox.rb
@@ -1,15 +1,16 @@
-# -*- encoding: binary -*-
 # Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
 require_relative '../../dtas'
 require_relative '../source'
 require_relative '../replaygain'
+require_relative '../xs'
 
 # this is usually one input file
 class DTAS::Source::Sox # :nodoc:
   require_relative 'file'
 
   include DTAS::Source::File
+  include DTAS::XS
 
   SOX_DEFAULTS = COMMAND_DEFAULTS.merge(
     "command" => 'exec sox "$INFILE" $SOXFMT - $TRIMFX $RGFX',
@@ -27,7 +28,7 @@ class DTAS::Source::Sox # :nodoc:
     if msg
       return if @last_failed == infile
       @last_failed = infile
-      return warn("`#{Shellwords.join(cmd)}' #{msg}")
+      return warn("`#{xs(cmd)}' #{msg}")
     end
     true
   end
@@ -49,7 +50,7 @@ class DTAS::Source::Sox # :nodoc:
     qx(@env, %W(soxi -p #@infile), err: "/dev/null").to_i # sox.git f4562efd0aa3
   rescue # fallback to parsing the whole output
     s = qx(@env, %W(soxi #@infile), err: "/dev/null")
-    s =~ /Precision\s+:\s*(\d+)-bit/
+    s =~ /Precision\s+:\s*(\d+)-bit/n
     v = $1.to_i
     return v if v > 0
     raise TypeError, "could not determine precision for #@infile"
@@ -81,8 +82,8 @@ class DTAS::Source::Sox # :nodoc:
     tmp = {}
     case @infile
     when String
-      qx(@env, %W(soxi -a #@infile)).split(/\n/).each do |line|
-        key, value = line.split(/=/, 2)
+      qx(@env, %W(soxi -a #@infile)).split(/\n/n).each do |line|
+        key, value = line.split(/=/n, 2)
         key && value or next
         # TODO: multi-line/multi-value/repeated tags
         tmp[key.upcase] = value
diff --git a/lib/dtas/state_file.rb b/lib/dtas/state_file.rb
index 05015ae..c009797 100644
--- a/lib/dtas/state_file.rb
+++ b/lib/dtas/state_file.rb
@@ -1,4 +1,3 @@
-# -*- encoding: binary -*-
 # Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
 require 'yaml'
diff --git a/lib/dtas/unix_accepted.rb b/lib/dtas/unix_accepted.rb
index c995364..be344c7 100644
--- a/lib/dtas/unix_accepted.rb
+++ b/lib/dtas/unix_accepted.rb
@@ -1,4 +1,3 @@
-# -*- encoding: binary -*-
 # Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
 require 'socket'
diff --git a/lib/dtas/unix_client.rb b/lib/dtas/unix_client.rb
index 1a0de90..fa94bbf 100644
--- a/lib/dtas/unix_client.rb
+++ b/lib/dtas/unix_client.rb
@@ -1,7 +1,7 @@
-# -*- encoding: binary -*-
 # Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
-require 'dtas'
+require_relative '../dtas'
+require_relative 'xs'
 require 'socket'
 require 'io/wait'
 require 'shellwords'
@@ -9,6 +9,8 @@ require 'shellwords'
 class DTAS::UNIXClient # :nodoc:
   attr_reader :to_io
 
+  include DTAS::XS
+
   def self.default_path
     (ENV["DTAS_PLAYER_SOCK"] || File.expand_path("~/.dtas/player.sock")).b
   end
@@ -19,7 +21,7 @@ class DTAS::UNIXClient # :nodoc:
   end
 
   def req_start(args)
-    args = Shellwords.join(args) if Array === args
+    args = xs(args) if Array === args
     @to_io.send(args, Socket::MSG_EOR)
   end
 
diff --git a/lib/dtas/unix_server.rb b/lib/dtas/unix_server.rb
index 07e16b4..bccfad5 100644
--- a/lib/dtas/unix_server.rb
+++ b/lib/dtas/unix_server.rb
@@ -1,4 +1,3 @@
-# -*- encoding: binary -*-
 # Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
 require 'socket'
diff --git a/lib/dtas/util.rb b/lib/dtas/util.rb
index f785b37..b235b0e 100644
--- a/lib/dtas/util.rb
+++ b/lib/dtas/util.rb
@@ -1,4 +1,3 @@
-# -*- encoding: binary -*-
 # Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
 require_relative '../dtas'
diff --git a/lib/dtas/writable_iter.rb b/lib/dtas/writable_iter.rb
index 0694085..1fd65eb 100644
--- a/lib/dtas/writable_iter.rb
+++ b/lib/dtas/writable_iter.rb
@@ -1,4 +1,3 @@
-# -*- encoding: binary -*-
 # Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
 require_relative '../dtas'
diff --git a/lib/dtas/xs.rb b/lib/dtas/xs.rb
new file mode 100644
index 0000000..968865d
--- /dev/null
+++ b/lib/dtas/xs.rb
@@ -0,0 +1,14 @@
+# Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
+# License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
+require_relative '../dtas'
+require 'shellwords'
+
+# We always escape binary strings because paths on POSIX filesystems are
+# encoding agnostic.  Shellwords.split does give UTF-8 strings, but nothing
+# cares at that point if the encoding isn't valid (and it's right to not care,
+# again, filesystems can use any byte value in names except '\0'.
+module DTAS::XS # :nodoc:
+  def xs(ary)
+    Shellwords.join(ary.map { |s| s.b })
+  end
+end
diff --git a/setup.rb b/setup.rb
index 5eb5006..9f0c826 100644
--- a/setup.rb
+++ b/setup.rb
@@ -1,4 +1,3 @@
-# -*- encoding: binary -*-
 #
 # setup.rb
 #
diff --git a/test/covshow.rb b/test/covshow.rb
index bc9a3e5..2fd48c6 100644
--- a/test/covshow.rb
+++ b/test/covshow.rb
@@ -1,4 +1,3 @@
-# -*- encoding: binary -*-
 # Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
 #
diff --git a/test/helper.rb b/test/helper.rb
index f5cb68d..e993463 100644
--- a/test/helper.rb
+++ b/test/helper.rb
@@ -1,4 +1,3 @@
-# -*- encoding: binary -*-
 # Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
 $stdout.sync = $stderr.sync = Thread.abort_on_exception = true
diff --git a/test/player_integration.rb b/test/player_integration.rb
index 79d4304..8ff1be2 100644
--- a/test/player_integration.rb
+++ b/test/player_integration.rb
@@ -1,4 +1,3 @@
-# -*- encoding: binary -*-
 # Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
 require './test/helper'
diff --git a/test/test_buffer.rb b/test/test_buffer.rb
index 249321f..259cd4f 100644
--- a/test/test_buffer.rb
+++ b/test/test_buffer.rb
@@ -1,4 +1,3 @@
-# -*- encoding: binary -*-
 # Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
 require './test/helper'
diff --git a/test/test_format.rb b/test/test_format.rb
index bbf64bf..0c0b292 100644
--- a/test/test_format.rb
+++ b/test/test_format.rb
@@ -1,4 +1,3 @@
-# -*- encoding: binary -*-
 # Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
 require './test/helper'
diff --git a/test/test_format_change.rb b/test/test_format_change.rb
index 0dcfb79..99c694a 100644
--- a/test/test_format_change.rb
+++ b/test/test_format_change.rb
@@ -1,4 +1,3 @@
-# -*- encoding: binary -*-
 # Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
 require './test/player_integration'
diff --git a/test/test_player.rb b/test/test_player.rb
index 5eff8ff..0fc776a 100644
--- a/test/test_player.rb
+++ b/test/test_player.rb
@@ -1,4 +1,3 @@
-# -*- encoding: binary -*-
 # Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
 require './test/helper'
diff --git a/test/test_player_client_handler.rb b/test/test_player_client_handler.rb
index 6f59d59..21d8489 100644
--- a/test/test_player_client_handler.rb
+++ b/test/test_player_client_handler.rb
@@ -1,4 +1,3 @@
-# -*- encoding: binary -*-
 # Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
 require './test/helper'
diff --git a/test/test_player_integration.rb b/test/test_player_integration.rb
index d1cbfb3..b60ed36 100644
--- a/test/test_player_integration.rb
+++ b/test/test_player_integration.rb
@@ -1,4 +1,3 @@
-# -*- encoding: binary -*-
 # Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
 require './test/player_integration'
diff --git a/test/test_process.rb b/test/test_process.rb
index ad2b641..7f7b014 100644
--- a/test/test_process.rb
+++ b/test/test_process.rb
@@ -1,4 +1,3 @@
-# -*- encoding: binary -*-
 # Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
 require './test/helper'
@@ -6,6 +5,13 @@ require 'dtas/process'
 class TestProcess < Minitest::Unit::TestCase
   include DTAS::Process
 
+  def test_encoding
+    assert_equal Encoding::BINARY, qx('echo HIHIH').encoding
+    s = ""
+    a = qx('echo HIHIHI; echo >&2 BYEBYE', err_str: s)
+    assert_equal Encoding::BINARY, a.encoding
+  end
+
   def test_qx_env
     assert_equal "WORLD\n", qx({"HELLO" => "WORLD"}, 'echo $HELLO')
   end
diff --git a/test/test_rg_integration.rb b/test/test_rg_integration.rb
index a3f15b7..23fd5d6 100644
--- a/test/test_rg_integration.rb
+++ b/test/test_rg_integration.rb
@@ -1,4 +1,3 @@
-# -*- encoding: binary -*-
 # Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
 require './test/player_integration'
diff --git a/test/test_rg_state.rb b/test/test_rg_state.rb
index 72ff45f..c79e716 100644
--- a/test/test_rg_state.rb
+++ b/test/test_rg_state.rb
@@ -1,4 +1,3 @@
-# -*- encoding: binary -*-
 # Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
 require './test/helper'
diff --git a/test/test_sink.rb b/test/test_sink.rb
index 4d9e159..2f39d1c 100644
--- a/test/test_sink.rb
+++ b/test/test_sink.rb
@@ -1,4 +1,3 @@
-# -*- encoding: binary -*-
 # Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
 require './test/helper'
diff --git a/test/test_sink_pipe_size.rb b/test/test_sink_pipe_size.rb
index 6b8eccd..18328df 100644
--- a/test/test_sink_pipe_size.rb
+++ b/test/test_sink_pipe_size.rb
@@ -1,4 +1,3 @@
-# -*- encoding: binary -*-
 # Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
 begin
diff --git a/test/test_sink_tee_integration.rb b/test/test_sink_tee_integration.rb
index bd01529..1fd6b0f 100644
--- a/test/test_sink_tee_integration.rb
+++ b/test/test_sink_tee_integration.rb
@@ -1,4 +1,3 @@
-# -*- encoding: binary -*-
 # Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
 require './test/player_integration'
diff --git a/test/test_source_av.rb b/test/test_source_av.rb
index 072e2aa..c5344a5 100644
--- a/test/test_source_av.rb
+++ b/test/test_source_av.rb
@@ -1,4 +1,3 @@
-# -*- encoding: binary -*-
 # Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
 require './test/helper'
diff --git a/test/test_source_sox.rb b/test/test_source_sox.rb
index 4ba9ba3..ce7227b 100644
--- a/test/test_source_sox.rb
+++ b/test/test_source_sox.rb
@@ -1,4 +1,3 @@
-# -*- encoding: binary -*-
 # Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
 require './test/helper'
diff --git a/test/test_unixserver.rb b/test/test_unixserver.rb
index bc63305..68fd16b 100644
--- a/test/test_unixserver.rb
+++ b/test/test_unixserver.rb
@@ -1,4 +1,3 @@
-# -*- encoding: binary -*-
 # Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
 require './test/helper'
diff --git a/test/test_util.rb b/test/test_util.rb
index 19e47ab..e768050 100644
--- a/test/test_util.rb
+++ b/test/test_util.rb
@@ -1,4 +1,3 @@
-# -*- encoding: binary -*-
 # Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
 # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
 require './test/helper'