rmpd 1.1.15 → 1.1.16
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/console.rb +1 -1
- data/lib/rmpd.rb +2 -0
- data/lib/rmpd/command.rb +70 -44
- data/lib/rmpd/commands/admin.rb +1 -1
- data/lib/rmpd/commands/miscellaneous.rb +7 -2
- data/lib/rmpd/connection.rb +49 -66
- data/lib/rmpd/version.rb +1 -1
- data/spec/models/commands_spec.rb +21 -10
- data/spec/models/connection_spec.rb +3 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7ed7a0812069ac86c9233bca9760bcceb0acc079
|
4
|
+
data.tar.gz: 48355f71e90c5cdadd1130d5dab71ec705274783
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 368aabafe5d5d3aa6c115ea01594ebcac6e3e17580379aa6cd2c0f09f5a76725d438483f2f17d13dd40049722e11b7bf113d839fbd16e7d197b7df2d9591fb6d
|
7
|
+
data.tar.gz: f31ddb04deb6543737e1d4681fbb698f34ceb1f9b7ee5bfbe31cbdaffb64dfd02f630e3091c14a95893192a22f284ad2e1dd1feb385f2407f8c80ef9f181e371
|
data/.gitignore
CHANGED
data/console.rb
CHANGED
data/lib/rmpd.rb
CHANGED
@@ -17,6 +17,8 @@ module Rmpd
|
|
17
17
|
|
18
18
|
class MpdConnRefusedError < MpdError ; end
|
19
19
|
|
20
|
+
class MpdDisconnectedError < MpdError; end
|
21
|
+
|
20
22
|
class MpdAckError < MpdError
|
21
23
|
def initialize(regex_match)
|
22
24
|
@error, @command_list_num, @current_command, @message = regex_match.values_at(1..-1)
|
data/lib/rmpd/command.rb
CHANGED
@@ -41,31 +41,26 @@ module Rmpd
|
|
41
41
|
module IdleStrategy
|
42
42
|
|
43
43
|
def execute(connection, *args, &block)
|
44
|
-
connection.
|
45
|
-
|
46
|
-
|
47
|
-
|
44
|
+
connection.synchronize do
|
45
|
+
connection.send_command(@name, *args)
|
46
|
+
if block_given?
|
47
|
+
yield connection.socket rescue nil
|
48
|
+
connection.send_command("noidle")
|
49
|
+
end
|
50
|
+
Response.factory(@name).parse(connection.read_response)
|
48
51
|
end
|
49
|
-
Response.factory(@name).parse(connection.read_response)
|
50
|
-
rescue EOFError
|
51
|
-
puts "IdleStrategy EOFError received, retrying" if $DEBUG
|
52
|
-
connection.close
|
53
|
-
retry
|
54
52
|
end
|
55
|
-
|
56
53
|
end
|
57
54
|
|
58
55
|
module NoidleStrategy
|
59
56
|
|
60
57
|
def execute(connection, *args)
|
61
|
-
connection.
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
connection.close
|
68
|
-
retry
|
58
|
+
connection.synchronize do
|
59
|
+
connection.send_command(@name, *args)
|
60
|
+
# The MPD server will never respond to a noidle command.
|
61
|
+
# http://www.mail-archive.com/musicpd-dev-team@lists.sourceforge.net/msg02246.html
|
62
|
+
nil
|
63
|
+
end
|
69
64
|
end
|
70
65
|
|
71
66
|
end
|
@@ -73,52 +68,83 @@ module Rmpd
|
|
73
68
|
module CommandStrategy
|
74
69
|
|
75
70
|
def execute(connection, *args)
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
71
|
+
tries = 0
|
72
|
+
begin
|
73
|
+
connection.synchronize do
|
74
|
+
connection.send_command(@name, *args)
|
75
|
+
Response.factory(@name).parse(connection.read_response)
|
76
|
+
end
|
77
|
+
rescue MpdDisconnectedError => e
|
78
|
+
tries += 1
|
79
|
+
if tries < 5
|
80
|
+
puts "CommandStrategy MpdDisconnectedError received, retrying" if $DEBUG
|
81
|
+
connection.connect
|
82
|
+
retry
|
83
|
+
else
|
84
|
+
puts "CommandStrategy retries exceeded" if $DEBUG
|
85
|
+
raise e
|
86
|
+
end
|
87
|
+
end
|
82
88
|
end
|
83
|
-
|
84
89
|
end
|
85
90
|
|
86
91
|
module CommandListStrategy
|
87
92
|
|
88
93
|
def execute(connection, *args, &block)
|
94
|
+
tries = 0
|
89
95
|
list = List.new
|
90
96
|
yield list
|
91
97
|
|
92
|
-
|
93
|
-
|
94
|
-
|
98
|
+
begin
|
99
|
+
connection.synchronize do
|
100
|
+
connection.send_command("command_list_begin")
|
101
|
+
list.map do |command_w_args|
|
102
|
+
connection.send_command(*command_w_args)
|
103
|
+
end
|
104
|
+
connection.send_command("command_list_end")
|
105
|
+
Response.factory(@name).parse(connection.read_response)
|
106
|
+
end
|
107
|
+
rescue MpdDisconnectedError => e
|
108
|
+
tries += 1
|
109
|
+
if tries < 5
|
110
|
+
puts "CommandListStrategy MpdDisconnectedError received, retrying" if $DEBUG
|
111
|
+
connect
|
112
|
+
retry
|
113
|
+
else
|
114
|
+
puts "CommandListStrategy retries exceeded" if $DEBUG
|
115
|
+
raise e
|
116
|
+
end
|
95
117
|
end
|
96
|
-
connection.send_command("command_list_end")
|
97
|
-
Response.factory(@name).parse(connection.read_response)
|
98
|
-
rescue EOFError
|
99
|
-
puts "CommandListStrategy EOFError received, retrying" if $DEBUG
|
100
|
-
connection.close
|
101
|
-
retry
|
102
118
|
end
|
103
|
-
|
104
119
|
end
|
105
120
|
|
106
121
|
module CommandListOkStrategy
|
107
122
|
|
108
123
|
def execute(connection, *args, &block)
|
124
|
+
tries = 0
|
109
125
|
@list = List.new
|
110
126
|
yield @list
|
111
127
|
|
112
|
-
|
113
|
-
|
114
|
-
|
128
|
+
begin
|
129
|
+
connection.synchronize do
|
130
|
+
connection.send_command("command_list_ok_begin")
|
131
|
+
@list.map do |command_w_args|
|
132
|
+
connection.send_command(*command_w_args)
|
133
|
+
end
|
134
|
+
connection.send_command("command_list_end")
|
135
|
+
handle_command_list_ok_response(connection.read_response)
|
136
|
+
end
|
137
|
+
rescue MpdDisconnectedError => e
|
138
|
+
tries += 1
|
139
|
+
if tries < 5
|
140
|
+
puts "CommandListOkStrategy MpdDisconnectedError received, retrying" if $DEBUG
|
141
|
+
connect
|
142
|
+
retry
|
143
|
+
else
|
144
|
+
puts "CommandListOkStrategy retries exceeded" if $DEBUG
|
145
|
+
raise e
|
146
|
+
end
|
115
147
|
end
|
116
|
-
connection.send_command("command_list_end")
|
117
|
-
handle_command_list_ok_response(connection.read_response)
|
118
|
-
rescue EOFError
|
119
|
-
puts "CommandListOkStrategy EOFError received, retrying" if $DEBUG
|
120
|
-
connection.close
|
121
|
-
retry
|
122
148
|
end
|
123
149
|
|
124
150
|
|
data/lib/rmpd/commands/admin.rb
CHANGED
@@ -13,8 +13,13 @@ module Rmpd
|
|
13
13
|
simple_command :status
|
14
14
|
|
15
15
|
def close
|
16
|
-
|
17
|
-
|
16
|
+
@socket_mu.lock
|
17
|
+
begin
|
18
|
+
send_command("close")
|
19
|
+
@socket.close
|
20
|
+
ensure
|
21
|
+
@socket_mu.unlock
|
22
|
+
end
|
18
23
|
end
|
19
24
|
|
20
25
|
simple_command :command_list
|
data/lib/rmpd/connection.rb
CHANGED
@@ -20,44 +20,71 @@ module Rmpd
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def close
|
23
|
-
@socket_mu.
|
24
|
-
|
25
|
-
|
23
|
+
@socket_mu.synchronize {@socket.close}
|
24
|
+
end
|
25
|
+
|
26
|
+
def synchronize(&block)
|
27
|
+
@socket_mu.synchronize(&block)
|
26
28
|
end
|
27
29
|
|
28
30
|
def connect
|
29
31
|
@socket_mu.lock
|
30
|
-
|
32
|
+
begin
|
33
|
+
return unless @socket.nil? || @socket.closed?
|
34
|
+
|
35
|
+
if %r{^/} === @config.hostname
|
36
|
+
connect_unix_socket
|
37
|
+
else
|
38
|
+
connect_inet_socket
|
39
|
+
end
|
40
|
+
|
41
|
+
read_response # protocol version, ignore for now
|
42
|
+
if @config.password
|
43
|
+
send_command("password", @config.password)
|
44
|
+
Response.factory("password").parse(read_response)
|
45
|
+
end
|
46
|
+
ensure
|
31
47
|
@socket_mu.unlock
|
32
|
-
return
|
33
48
|
end
|
34
|
-
|
49
|
+
end
|
35
50
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
51
|
+
def read_response
|
52
|
+
response = []
|
53
|
+
|
54
|
+
while (line = @socket.readline.force_encoding("UTF-8"))
|
55
|
+
response << line.strip
|
56
|
+
break if END_RE === line
|
40
57
|
end
|
41
58
|
|
42
|
-
|
43
|
-
password(@config.password) if @config.password
|
59
|
+
response
|
44
60
|
end
|
45
61
|
|
62
|
+
def send_command(command, *args)
|
63
|
+
@socket.puts("#{command} #{quote(args).join(" ")}".strip)
|
64
|
+
rescue Errno::EPIPE, EOFError => e
|
65
|
+
@socket.close
|
66
|
+
raise MpdDisconnectedError.new(e)
|
67
|
+
end
|
68
|
+
|
69
|
+
|
70
|
+
protected
|
71
|
+
|
72
|
+
def mpd
|
73
|
+
self
|
74
|
+
end
|
75
|
+
|
76
|
+
|
77
|
+
private
|
78
|
+
|
46
79
|
def connect_unix_socket
|
47
|
-
@
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
@socket = nil
|
52
|
-
raise MpdConnRefusedError.new(error)
|
53
|
-
ensure
|
54
|
-
@socket_mu.unlock
|
55
|
-
end
|
80
|
+
@socket = UNIXSocket.new(@config.hostname)
|
81
|
+
rescue StandardError => error
|
82
|
+
@socket = nil
|
83
|
+
raise MpdConnRefusedError.new(error)
|
56
84
|
end
|
57
85
|
|
58
86
|
def connect_inet_socket
|
59
87
|
Socket::getaddrinfo(@config.hostname, @config.port, nil, SOCK_STREAM).each do |info|
|
60
|
-
@socket_mu.lock
|
61
88
|
begin
|
62
89
|
sockaddr = Socket.pack_sockaddr_in(info[1], info[3])
|
63
90
|
@socket = Socket.new(info[4], info[5], 0)
|
@@ -67,52 +94,8 @@ module Rmpd
|
|
67
94
|
raise MpdConnRefusedError.new(error)
|
68
95
|
else
|
69
96
|
break
|
70
|
-
ensure
|
71
|
-
@socket_mu.unlock
|
72
|
-
end
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
def send_command(command, *args)
|
77
|
-
tries = 0
|
78
|
-
|
79
|
-
begin
|
80
|
-
connect
|
81
|
-
send_command_without_reconnect(command, *args)
|
82
|
-
rescue Errno::EPIPE, EOFError
|
83
|
-
if (tries += 1) < MAX_RETRIES
|
84
|
-
retry
|
85
|
-
else
|
86
|
-
raise MpdError.new("Retry count exceeded")
|
87
|
-
end
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
|
-
def send_command_without_reconnect(command, *args)
|
92
|
-
@socket_mu.lock
|
93
|
-
@socket.puts("#{command} #{quote(args).join(" ")}".strip)
|
94
|
-
rescue => e
|
95
|
-
@socket.close
|
96
|
-
raise e
|
97
|
-
ensure
|
98
|
-
@socket_mu.unlock
|
99
|
-
end
|
100
|
-
|
101
|
-
def read_response
|
102
|
-
response = []
|
103
|
-
|
104
|
-
@socket_mu.synchronize do
|
105
|
-
while (line = @socket.readline.force_encoding("UTF-8"))
|
106
|
-
response << line.strip
|
107
|
-
break if END_RE === line
|
108
97
|
end
|
109
98
|
end
|
110
|
-
|
111
|
-
response
|
112
|
-
end
|
113
|
-
|
114
|
-
def mpd
|
115
|
-
self
|
116
99
|
end
|
117
100
|
|
118
101
|
def quote(args)
|
data/lib/rmpd/version.rb
CHANGED
@@ -30,23 +30,28 @@ describe Rmpd::Commands do
|
|
30
30
|
@socket.stub!(:readline).and_return(*(connect_response + ok))
|
31
31
|
@socket.should_receive(:close).exactly(5).times
|
32
32
|
lambda do
|
33
|
+
@conn.connect
|
33
34
|
@conn.ping
|
34
|
-
end.should raise_error(Rmpd::
|
35
|
+
end.should raise_error(Rmpd::MpdDisconnectedError)
|
35
36
|
end
|
36
37
|
|
37
38
|
it "should abort after a limited number of tries against a closed connection" do
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
39
|
+
pending do
|
40
|
+
@socket.stub!(:puts).and_raise(EOFError)
|
41
|
+
@socket.stub!(:readline).and_return(*(connect_response + ok))
|
42
|
+
@socket.should_receive(:close).exactly(5).times
|
43
|
+
lambda do
|
44
|
+
@conn.connect
|
45
|
+
@conn.ping
|
46
|
+
end.should raise_error(MpdError, "Retry count exceeded")
|
47
|
+
end
|
44
48
|
end
|
45
49
|
|
46
50
|
describe "close" do
|
47
51
|
it "should close the socket" do
|
48
52
|
@socket.stub!(:readline).and_return(*connect_response)
|
49
53
|
@socket.should_receive(:close).once
|
54
|
+
@conn.connect
|
50
55
|
@conn.ping
|
51
56
|
@conn.close
|
52
57
|
end
|
@@ -57,6 +62,7 @@ describe Rmpd::Commands do
|
|
57
62
|
set_password
|
58
63
|
@socket.stub!(:readline).and_return(*connect_and_auth_responses)
|
59
64
|
$stderr.should_receive(:puts).with(/deprecated/i)
|
65
|
+
@conn.connect
|
60
66
|
@conn.volume(0)
|
61
67
|
end
|
62
68
|
end
|
@@ -78,7 +84,7 @@ describe Rmpd::Commands do
|
|
78
84
|
@song_id = 1
|
79
85
|
@cmd = "playlistinfo \"#{@song_id}\""
|
80
86
|
@responses = connect_and_auth_responses + ["file: blah\n", "boobies: yay!\n"] + ok
|
81
|
-
@command = Proc.new {@conn.playlistinfo(@song_id)}
|
87
|
+
@command = Proc.new {@conn.connect; @conn.playlistinfo(@song_id)}
|
82
88
|
end
|
83
89
|
|
84
90
|
it_should_behave_like "a command with a song pos"
|
@@ -90,7 +96,7 @@ describe Rmpd::Commands do
|
|
90
96
|
@song_id = 12
|
91
97
|
@cmd = "play \"#{@song_id}\""
|
92
98
|
@responses = connect_and_auth_responses + ok
|
93
|
-
@command = Proc.new {@conn.play(@song_id)}
|
99
|
+
@command = Proc.new {@conn.connect; @conn.play(@song_id)}
|
94
100
|
end
|
95
101
|
|
96
102
|
it_should_behave_like "a command with a song pos"
|
@@ -102,7 +108,7 @@ describe Rmpd::Commands do
|
|
102
108
|
@song_id = 23
|
103
109
|
@cmd = "delete \"#{@song_id}\""
|
104
110
|
@responses = connect_and_auth_responses + ok
|
105
|
-
@command = Proc.new {@conn.delete(@song_id)}
|
111
|
+
@command = Proc.new {@conn.connect; @conn.delete(@song_id)}
|
106
112
|
end
|
107
113
|
|
108
114
|
it_should_behave_like "a command with a song pos"
|
@@ -115,6 +121,7 @@ describe Rmpd::Commands do
|
|
115
121
|
@socket.stub!(:puts).and_return(@socket.puts)
|
116
122
|
@socket.stub!(:eof?).and_return(false)
|
117
123
|
|
124
|
+
@conn.connect
|
118
125
|
@conn.command_list do |c|
|
119
126
|
c.status
|
120
127
|
c.stats
|
@@ -127,6 +134,7 @@ describe Rmpd::Commands do
|
|
127
134
|
@socket.stub!(:puts).and_return(@socket.puts)
|
128
135
|
@socket.stub!(:eof?).and_return(false)
|
129
136
|
|
137
|
+
@conn.connect
|
130
138
|
@conn.command_list do |c|
|
131
139
|
c.addid("foo")
|
132
140
|
end
|
@@ -139,6 +147,7 @@ describe Rmpd::Commands do
|
|
139
147
|
@responses = connect_response
|
140
148
|
@socket.stub!(:readline).and_return(*@responses)
|
141
149
|
|
150
|
+
@conn.connect
|
142
151
|
@conn.noidle.should be_nil
|
143
152
|
end
|
144
153
|
|
@@ -146,6 +155,7 @@ describe Rmpd::Commands do
|
|
146
155
|
@responses = connect_response + status_response + ok
|
147
156
|
@socket.stub!(:readline).and_return(*@responses)
|
148
157
|
|
158
|
+
@conn.connect
|
149
159
|
response = @conn.status
|
150
160
|
|
151
161
|
response.should have(2).items, response.pretty_inspect
|
@@ -161,6 +171,7 @@ describe Rmpd::Commands do
|
|
161
171
|
@socket.stub!(:puts).and_return(@socket.puts)
|
162
172
|
@socket.stub!(:eof?).and_return(false)
|
163
173
|
|
174
|
+
@conn.connect
|
164
175
|
results = @conn.command_list_ok do |c|
|
165
176
|
c.list("album")
|
166
177
|
c.list("artist")
|
@@ -18,6 +18,7 @@ describe Connection do
|
|
18
18
|
it "should connect successfully" do
|
19
19
|
responses = connect_response + ok
|
20
20
|
@socket.should_receive(:readline).and_return(*responses)
|
21
|
+
@conn.connect
|
21
22
|
@conn.ping
|
22
23
|
end
|
23
24
|
|
@@ -25,6 +26,7 @@ describe Connection do
|
|
25
26
|
responses = connect_and_auth_responses + ok
|
26
27
|
set_password
|
27
28
|
@socket.should_receive(:readline).and_return(*responses)
|
29
|
+
@conn.connect
|
28
30
|
@conn.ping
|
29
31
|
end
|
30
32
|
|
@@ -40,6 +42,7 @@ describe Connection do
|
|
40
42
|
it "should handle connection failures gracefully" do
|
41
43
|
@socket.stub!(:connect).and_raise(Errno::ECONNREFUSED.new("test"))
|
42
44
|
lambda do
|
45
|
+
@conn.connect
|
43
46
|
@conn.ping
|
44
47
|
end.should raise_error(Rmpd::MpdError)
|
45
48
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rmpd
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.
|
4
|
+
version: 1.1.16
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Eric Wollesen
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-09-
|
11
|
+
date: 2016-09-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|