Permalink
Browse files

Reconsolidate the Client model. #16

  • Loading branch information...
1 parent e17a367 commit fb644a8edb1358d00d9a1bc8fbf82c7b46458964 @smashwilson committed Mar 4, 2012
Showing with 38 additions and 168 deletions.
  1. +38 −5 app/models/client.rb
  2. +0 −105 app/models/development_client.rb
  3. +0 −54 app/models/production_client.rb
  4. +0 −4 app/models/test_client.rb
View
@@ -1,4 +1,5 @@
require 'mpg123player/common'
+require 'active_support/json'
# Non-ActiveRecord model. Manage status and communications with the mpg123 player process.
class Client
@@ -11,21 +12,53 @@ def initialize
configure
end
- # Issue a command to the server, synchronously if appropriate.
+ # Issue a command to the server and wait for the remote process to handle it, within the currently configured
+ # +command_timeout+.
def command string, parameter = nil
- raise '#command not implemented'
+ cmd = PlayerCommand.create!(:action => string, :parameter => parameter)
+
+ Rails.logger.silence(WARN) do
+ wait_time = 0
+ until wait_time >= @command_timeout
+ wait_time += sleep(@command_poll)
+ return true unless PlayerCommand.exist?(cmd.id)
+ end
+ end
+
+ # Timed out waiting for command acceptance
+ false
end
# Status
- # Return false and set +error+ if the player is in a bad state.
+ # Query the current player status, setting +error+ and returning false if something is wrong.
def ok?
+ unless File.readable?(@pid_path)
+ @error = "Can't read the pid file at #{@pid_path}!"
+ return false
+ end
+ pid = File.open(@pid_path) { |f| f.gets(nil) }.to_i
+ Process.kill(0, pid)
+ rescue Errno::ESRCH => e
+ @error = "The server died!"
+ false
+ rescue Errno::EPERM => e
+ @error = "Someone else is running the server!"
+ false
+ else
true
end
- # Return a Status object representing the current state of the player, ready for JSON rendering.
+ # Populate the Status object by reading the JSON written to disk by the server process, amending it with our local
+ # +error+ if one is present.
def status
- Status.stopped
+ @status ||= if File.readable?(@status_path)
+ Status.from(JSON(File.read(@status_path)))
+ else
+ Status.stopped
+ end
+ @status.error = @error
+ @status
end
def playing?
@@ -1,105 +0,0 @@
-# This client is for interactive development mode (even on the same system that the real websinger-player is running
-# on.) It simulates the "playing" of music and advancement through tracks in real-time with a background thread, but
-# doesn't actually produce any audio.
-class DevelopmentClient < Client
-
- def status
- self.class.status
- end
-
- class << self
- @status ||= Mpg123Player::Status.stopped
- @shutting_down ||= false
-
- def status ; @status ; end
-
- Thread.new { main_loop }
-
- def main_loop
- advance
- until @shutting_down
- play_track
- process_command_queue
- end
- end
-
- def advance
- e = EnqueuedTrack.top
- while e.nil? && !@shutting_down
- sleep 0.5
- e = EnqueuedTrack.top
- process_command_queue
- end
- load_track(e.track) unless @shutting_down
- end
-
- def load_track t, state = :playing
- @status.on_track t
- @status.playback_state = state
- end
-
- # Advance the playing of the current track by a single second.
- def play_track
- return if @status.playback_state = :paused
- sleep 1
- @status.seconds += 1
- if @status.seconds >= @status.length
- @status.playback_state = :stopped
- advance
- end
- end
-
- # Consume commands from the command queue.
- def process_command_queue
- Rails.logger.silence(WARN) do
- PlayerCommand.flush_queue.each { |c| process_command c }
- end
- end
-
- # Handle a specific command.
- def process_command command
- handler = method("#{command.action}_action")
- case handler.arity
- when 0 ; handler.call
- when 1 ; handler.call(command.parameter)
- else ; raise "Action method #{command.action}_action has arity of #{handler.arity}"
- end
- end
-
- # Fake commands that just manipulate the status directly.
-
- def play_action
- @status.playback_state = :playing
- end
-
- def pause_action
- @status.playback_state = :paused
- end
-
- def jump_action seconds
- @status.seconds = seconds.to_f
- end
-
- def volume_action percent
- @status.volume = percent.to_f
- end
-
- def restart_action
- @status.seconds = 0
- end
-
- def skip_action
- e = EnqueuedTrack.top
- if e.nil?
- @status.playback_state = :stopped
- else
- load_track e.track, @status.playback_state
- end
- end
-
- def shutdown_action
- @shutting_down = true
- end
-
- end
-end
@@ -1,54 +0,0 @@
-require 'active_support/json'
-
-# Client implementation for use in production. This Client actually communicates with a remote Mpg123player::Server
-# process, lauched with `rake websinger:player`, and results in actual music playing over the speakers.
-class ProductionClient < Client
-
- # Issue a command to the server and wait for the remote process to handle it, within the currently configured
- # +command_timeout+.
- def command string, parameter = nil
- cmd = PlayerCommand.create!(:action => string, :parameter => parameter)
-
- Rails.logger.silence(WARN) do
- wait_time = 0
- until wait_time >= @command_timeout
- wait_time += sleep(@command_poll)
- return true unless PlayerCommand.exist?(cmd.id)
- end
- end
-
- # Timed out waiting for command acceptance
- false
- end
-
- # Query the current player status, setting +error+ and returning false if something is wrong.
- def ok?
- unless File.readable?(@pid_path)
- @error = "Can't read the pid file at #{@pid_path}!"
- return false
- end
- pid = File.open(@pid_path) { |f| f.gets(nil) }.to_i
- Process.kill(0, pid)
- rescue Errno::ESRCH => e
- @error = "The server died!"
- false
- rescue Errno::EPERM => e
- @error = "Someone else is running the server!"
- false
- else
- true
- end
-
- # Populate the Status object by reading the JSON written to disk by the server process, amending it with our local
- # +error+ if one is present.
- def status
- @status ||= if File.readable?(@status_path)
- Status.from(JSON(File.read(@status_path)))
- else
- Status.stopped
- end
- @status.error = @error
- @status
- end
-
-end
@@ -1,4 +0,0 @@
-# A Client implementation for use in test cases. Requires explicit methods to drive its lifecycle (advancing through
-# tracks and so on).
-class TestClient < Client
-end

0 comments on commit fb644a8

Please sign in to comment.