diff options
-rw-r--r-- | Documentation/dtas-player_protocol.txt | 8 | ||||
-rw-r--r-- | lib/dtas/player.rb | 2 | ||||
-rw-r--r-- | lib/dtas/player/client_handler.rb | 21 | ||||
-rw-r--r-- | lib/dtas/state_file.rb | 2 | ||||
-rw-r--r-- | test/test_player_integration.rb | 18 |
5 files changed, 51 insertions, 0 deletions
diff --git a/Documentation/dtas-player_protocol.txt b/Documentation/dtas-player_protocol.txt index efbd065..b431180 100644 --- a/Documentation/dtas-player_protocol.txt +++ b/Documentation/dtas-player_protocol.txt @@ -203,6 +203,14 @@ Commands here should be alphabetized according to `LC_ALL=C sort' 1. input type (flac/opus/mp3/etc) 2. transport protocol (local FS/http/ftp/sftp/etc) +* state dump [FILENAME] + Immediately dump the state of the player. If a FILENAME is specified, + the state is written to that file. Otherwise, the default state file + (configured via DTAS_PLAYER_STATE environment variable, defaulting + to ~/.dtas/player_state.yml) is written to. This does not use fsync(2), + users requiring fsync should open(2) that file and fsync(2) it + themselves if necessary. + * watch - adds the client to the passive watch list for notifications. It is recommended clients issue no further commands and open another client socket to issue non-watch commands. diff --git a/lib/dtas/player.rb b/lib/dtas/player.rb index ba42490..3571a7f 100644 --- a/lib/dtas/player.rb +++ b/lib/dtas/player.rb @@ -212,6 +212,8 @@ class DTAS::Player # :nodoc: io.emit("OK") when "source" source_handler(io, msg) + when "state" + state_file_handler(io, msg) when "cd" chdir_handler(io, msg) when "pwd" diff --git a/lib/dtas/player/client_handler.rb b/lib/dtas/player/client_handler.rb index f601d46..bbdc1c5 100644 --- a/lib/dtas/player/client_handler.rb +++ b/lib/dtas/player/client_handler.rb @@ -479,5 +479,26 @@ module DTAS::Player::ClientHandler # :nodoc: # echo(%W(cd msg[0])) # should we broadcast this? io.emit("OK") end + + def state_file_handler(io, msg) + case msg.shift + when "dump" + dest = msg.shift + if dest + sf = DTAS::StateFile.new(dest, false) + elsif @state_file + sf = @state_file + dest = sf.path + else + return io.emit("ERR no state file configured") + end + begin + sf.dump(self) + rescue => e + return io.emit("ERR dumping to #{xs(Array(dest))} #{e.message}") + end + end + io.emit("OK") + end end # :startdoc: diff --git a/lib/dtas/state_file.rb b/lib/dtas/state_file.rb index c009797..0ba876f 100644 --- a/lib/dtas/state_file.rb +++ b/lib/dtas/state_file.rb @@ -3,6 +3,8 @@ require 'yaml' require 'tempfile' class DTAS::StateFile # :nodoc: + attr_reader :path + def initialize(path, do_fsync = false) @path = path @do_fsync = do_fsync diff --git a/test/test_player_integration.rb b/test/test_player_integration.rb index b60ed36..e7f7306 100644 --- a/test/test_player_integration.rb +++ b/test/test_player_integration.rb @@ -188,6 +188,24 @@ class TestPlayerIntegration < Minitest::Unit::TestCase assert_equal "/", s.req("pwd") end + def test_state_file + state = Tempfile.new(%w(state .yml)) + state_path = state.path + state.close! + s = client_socket + s.req_ok(%W(state dump #{state_path})) + hash = YAML.load(IO.binread(state_path)) + assert_equal @sock_path, hash["socket"] + assert_equal "default", hash["sinks"][0]["name"] + + assert_equal "", IO.binread(@state_tmp.path) + s.req_ok(%W(state dump)) + orig = YAML.load(IO.binread(@state_tmp.path)) + assert_equal orig, hash + ensure + File.unlink(state_path) + end + def test_source_ed s = client_socket assert_equal "sox av ff", s.req("source ls") |