about summary refs log tree commit homepage
path: root/lib/dtas/player.rb
diff options
context:
space:
mode:
authorEric Wong <normalperson@yhbt.net>2013-09-09 04:12:29 +0000
committerEric Wong <normalperson@yhbt.net>2013-09-09 04:13:16 +0000
commit59ca3ba986e1f872d851b9b6ce588e20d8020243 (patch)
tree36b26be54ce81055471c48b5f4e1a80152e5f9d6 /lib/dtas/player.rb
parent4b29f098adfaa900dc7c293163eb914f6725d800 (diff)
downloaddtas-59ca3ba986e1f872d851b9b6ce588e20d8020243.tar.gz
This should allow us to repeat through a list of tracks with relative
ease.  There is a rudimentary dtas-tl client implemented.  This
may be removed in the future.
Diffstat (limited to 'lib/dtas/player.rb')
-rw-r--r--lib/dtas/player.rb28
1 files changed, 25 insertions, 3 deletions
diff --git a/lib/dtas/player.rb b/lib/dtas/player.rb
index 2bf2716..eddaf70 100644
--- a/lib/dtas/player.rb
+++ b/lib/dtas/player.rb
@@ -15,6 +15,7 @@ require_relative 'buffer'
 require_relative 'sigevent'
 require_relative 'rg_state'
 require_relative 'state_file'
+require_relative 'tracklist'
 
 class DTAS::Player # :nodoc:
   require_relative 'player/client_handler'
@@ -25,6 +26,7 @@ class DTAS::Player # :nodoc:
   attr_reader :sinks
 
   def initialize
+    @tl = DTAS::Tracklist.new
     @state_file = nil
     @socket = nil
     @srv = nil
@@ -87,6 +89,8 @@ class DTAS::Player # :nodoc:
       rv[k] = instance_variable_get("@#{k}").to_hsh
     end
 
+    rv["tracklist"] = @tl.to_hsh
+
     # no empty hashes or arrays
     rv.delete_if do |k,v|
       case v
@@ -111,6 +115,9 @@ class DTAS::Player # :nodoc:
   def self.load(hash)
     rv = new
     rv.instance_eval do
+      if v = hash["tracklist"]
+        @tl = DTAS::Tracklist.load(v)
+      end
       @rg = DTAS::RGState.load(hash["rg"])
       if v = hash["sink_buf"]
         v = v["buffer_size"]
@@ -218,6 +225,8 @@ class DTAS::Player # :nodoc:
       chdir_handler(io, msg)
     when "pwd"
       io.emit(Dir.pwd)
+    when "tl"
+      tl_handler(io, msg)
     end
   end
 
@@ -242,7 +251,7 @@ class DTAS::Player # :nodoc:
       obj.on_death(status) if obj.respond_to?(:on_death)
       case obj
       when @current
-        next_source(@paused ? nil : @queue.shift)
+        next_source(@paused ? nil : _next)
       when DTAS::Sink # on unexpected sink death
         sink_death(obj, status)
       end
@@ -250,6 +259,10 @@ class DTAS::Player # :nodoc:
     :wait_readable
   end
 
+  def _next
+    @queue.shift || @tl.next_track
+  end
+
   def sink_death(sink, status)
     deleted = []
     @targets.delete_if do |t|
@@ -272,7 +285,7 @@ class DTAS::Player # :nodoc:
     if (@current || @queue[0]) && !@paused
       # we get here if source/sinks are all killed in restart_pipeline
       __sink_activate(sink)
-      next_source(@queue.shift) unless @current
+      next_source(_next) unless @current
     end
   end
 
@@ -337,6 +350,15 @@ class DTAS::Player # :nodoc:
         rv = src.try(*source_spec) and return rv
       end
     end
+
+    # don't get stuck in an infinite loop if @tl.repeat==true and we can't
+    # decode anything (FS errors, sox uninstalled, etc...)
+    while path = @tl.next_track(false)
+      @sources.each do |src|
+        rv = src.try(path) and return rv
+      end
+    end
+
     echo "idle"
     nil
   end
@@ -410,7 +432,7 @@ class DTAS::Player # :nodoc:
     @srv.wait_ctl(sev, :wait_readable)
     old_chld = trap(:CHLD) { sev.signal }
     create_default_sink
-    next_source(@paused ? nil : @queue.shift)
+    next_source(@paused ? nil : (@queue.shift || @tl.cur_track))
     begin
       event_loop_iter
     rescue => e # just in case...