mpd 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +3 -0
- data/bin/mpc.rb +8 -0
- data/lib/mpd.rb +12 -0
- data/lib/mpd/controller.rb +206 -0
- data/lib/mpd/controller/audio.rb +78 -0
- data/lib/mpd/controller/channels.rb +117 -0
- data/lib/mpd/controller/commands.rb +57 -0
- data/lib/mpd/controller/config.rb +35 -0
- data/lib/mpd/controller/current_playlist.rb +110 -0
- data/lib/mpd/controller/database.rb +235 -0
- data/lib/mpd/controller/decoders.rb +54 -0
- data/lib/mpd/controller/do.rb +42 -0
- data/lib/mpd/controller/player.rb +109 -0
- data/lib/mpd/controller/playlists.rb +113 -0
- data/lib/mpd/controller/stats.rb +31 -0
- data/lib/mpd/controller/status.rb +69 -0
- data/lib/mpd/controller/stickers.rb +87 -0
- data/lib/mpd/controller/supported_protocols.rb +36 -0
- data/lib/mpd/controller/supported_tags.rb +36 -0
- data/lib/mpd/controller/toggle.rb +72 -0
- data/lib/mpd/protocol.rb +15 -0
- data/lib/mpd/protocol/command.rb +50 -0
- data/lib/mpd/protocol/command_list.rb +48 -0
- data/lib/mpd/protocol/response.rb +181 -0
- data/lib/mpd/version.rb +15 -0
- data/mpd.gemspec +16 -0
- metadata +71 -0
@@ -0,0 +1,36 @@
|
|
1
|
+
#--
|
2
|
+
# DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
3
|
+
# Version 2, December 2004
|
4
|
+
#
|
5
|
+
# DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
6
|
+
# TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
7
|
+
#
|
8
|
+
# 0. You just DO WHAT THE FUCK YOU WANT TO.
|
9
|
+
#++
|
10
|
+
|
11
|
+
module MPD; class Controller
|
12
|
+
|
13
|
+
class SupportedTags
|
14
|
+
include Enumerable
|
15
|
+
|
16
|
+
attr_reader :controller
|
17
|
+
|
18
|
+
def initialize (controller)
|
19
|
+
@controller = controller
|
20
|
+
@supported = []
|
21
|
+
|
22
|
+
controller.do_and_raise_if_needed(:tagtypes).each {|_, name|
|
23
|
+
@supported << name.to_sym
|
24
|
+
}
|
25
|
+
end
|
26
|
+
|
27
|
+
def each (&block)
|
28
|
+
return to_enum unless block_given?
|
29
|
+
|
30
|
+
@supported.each(&block)
|
31
|
+
|
32
|
+
self
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
end; end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
#--
|
2
|
+
# DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
3
|
+
# Version 2, December 2004
|
4
|
+
#
|
5
|
+
# DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
6
|
+
# TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
7
|
+
#
|
8
|
+
# 0. You just DO WHAT THE FUCK YOU WANT TO.
|
9
|
+
#++
|
10
|
+
|
11
|
+
module MPD; class Controller
|
12
|
+
|
13
|
+
class Toggle
|
14
|
+
attr_reader :controller
|
15
|
+
|
16
|
+
def initialize (controller)
|
17
|
+
@controller = controller
|
18
|
+
end
|
19
|
+
|
20
|
+
def toggle (name)
|
21
|
+
controller.do_and_raise_if_needed name, !on?(name)
|
22
|
+
end
|
23
|
+
|
24
|
+
def on (name)
|
25
|
+
unless on? name
|
26
|
+
controller.do_and_raise_if_needed name, true
|
27
|
+
end
|
28
|
+
|
29
|
+
self
|
30
|
+
end
|
31
|
+
|
32
|
+
def off (name)
|
33
|
+
if on? name
|
34
|
+
controller.do_and_raise_if_needed name, false
|
35
|
+
end
|
36
|
+
|
37
|
+
self
|
38
|
+
end
|
39
|
+
|
40
|
+
def on? (name)
|
41
|
+
controller.status.__send__ "#{name}?"
|
42
|
+
end
|
43
|
+
|
44
|
+
%w[pause random consume repeat single].each {|name|
|
45
|
+
define_method name do
|
46
|
+
toggle name
|
47
|
+
end
|
48
|
+
|
49
|
+
define_method "#{name}!" do
|
50
|
+
on name
|
51
|
+
end
|
52
|
+
|
53
|
+
define_method "no_#{name}!" do
|
54
|
+
off name
|
55
|
+
end
|
56
|
+
|
57
|
+
define_method "#{name}?" do
|
58
|
+
on? name
|
59
|
+
end
|
60
|
+
}
|
61
|
+
|
62
|
+
def pause?
|
63
|
+
controller.status == :pause
|
64
|
+
end
|
65
|
+
|
66
|
+
alias shuffle random
|
67
|
+
alias shuffle! random!
|
68
|
+
alias no_shuffle! no_random!
|
69
|
+
alias shuffle? random?
|
70
|
+
end
|
71
|
+
|
72
|
+
end; end
|
data/lib/mpd/protocol.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
#--
|
2
|
+
# DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
3
|
+
# Version 2, December 2004
|
4
|
+
#
|
5
|
+
# DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
6
|
+
# TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
7
|
+
#
|
8
|
+
# 0. You just DO WHAT THE FUCK YOU WANT TO.
|
9
|
+
#++
|
10
|
+
|
11
|
+
require 'stringio'
|
12
|
+
|
13
|
+
require 'mpd/protocol/response'
|
14
|
+
require 'mpd/protocol/command'
|
15
|
+
require 'mpd/protocol/command_list'
|
@@ -0,0 +1,50 @@
|
|
1
|
+
#--
|
2
|
+
# DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
3
|
+
# Version 2, December 2004
|
4
|
+
#
|
5
|
+
# DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
6
|
+
# TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
7
|
+
#
|
8
|
+
# 0. You just DO WHAT THE FUCK YOU WANT TO.
|
9
|
+
#++
|
10
|
+
|
11
|
+
module MPD; module Protocol
|
12
|
+
|
13
|
+
class Command
|
14
|
+
attr_reader :name, :arguments
|
15
|
+
|
16
|
+
def initialize (name, *arguments)
|
17
|
+
@name = name.to_sym
|
18
|
+
@arguments = arguments.flatten.compact
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_s
|
22
|
+
result = name.to_s
|
23
|
+
|
24
|
+
unless arguments.empty?
|
25
|
+
result << ' ' << arguments.map {|argument|
|
26
|
+
if argument.is_a? Range
|
27
|
+
if argument.end == -1
|
28
|
+
"#{argument.begin}:"
|
29
|
+
else
|
30
|
+
"#{argument.begin}:#{argument.end + (argument.exclude_end? ? 0 : 1)}"
|
31
|
+
end
|
32
|
+
elsif argument == true || argument == false
|
33
|
+
argument ? '1' : '0'
|
34
|
+
else
|
35
|
+
argument = argument.to_s
|
36
|
+
|
37
|
+
if argument.include?(' ') || argument.include?('"')
|
38
|
+
%{"#{argument.gsub '"', '\"'}"}
|
39
|
+
else
|
40
|
+
argument
|
41
|
+
end
|
42
|
+
end
|
43
|
+
}.join(' ')
|
44
|
+
end
|
45
|
+
|
46
|
+
result
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
end; end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
#--
|
2
|
+
# DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
3
|
+
# Version 2, December 2004
|
4
|
+
#
|
5
|
+
# DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
6
|
+
# TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
7
|
+
#
|
8
|
+
# 0. You just DO WHAT THE FUCK YOU WANT TO.
|
9
|
+
#++
|
10
|
+
|
11
|
+
module MPD; module Protocol
|
12
|
+
|
13
|
+
class CommandList
|
14
|
+
def initialize (*commands)
|
15
|
+
@commands = commands.flatten.compact
|
16
|
+
end
|
17
|
+
|
18
|
+
def respond_to_missing? (id, include_private = false)
|
19
|
+
@commands.respond_to?(id)
|
20
|
+
end
|
21
|
+
|
22
|
+
def method_missing (id, *args, &block)
|
23
|
+
if @commands.respond_to? id
|
24
|
+
return @commands.__send__ id, *args, &block
|
25
|
+
end
|
26
|
+
|
27
|
+
super
|
28
|
+
end
|
29
|
+
|
30
|
+
def to_s
|
31
|
+
result = StringIO.new
|
32
|
+
|
33
|
+
result.puts 'command_list_ok_begin'
|
34
|
+
@commands.each {|command|
|
35
|
+
result.puts command.to_s
|
36
|
+
}
|
37
|
+
result.print 'command_list_end'
|
38
|
+
|
39
|
+
result.seek 0
|
40
|
+
result.read
|
41
|
+
end
|
42
|
+
|
43
|
+
def to_a
|
44
|
+
@commands
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
end; end
|
@@ -0,0 +1,181 @@
|
|
1
|
+
#--
|
2
|
+
# DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
3
|
+
# Version 2, December 2004
|
4
|
+
#
|
5
|
+
# DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
6
|
+
# TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
7
|
+
#
|
8
|
+
# 0. You just DO WHAT THE FUCK YOU WANT TO.
|
9
|
+
#++
|
10
|
+
|
11
|
+
require 'date'
|
12
|
+
|
13
|
+
module MPD; module Protocol
|
14
|
+
|
15
|
+
class Response
|
16
|
+
class Data
|
17
|
+
attr_reader :name, :value
|
18
|
+
|
19
|
+
def initialize (name, value)
|
20
|
+
@name = name
|
21
|
+
@value = case name
|
22
|
+
when :song, :artists, :albums, :songs, :uptime, :playtime, :db_playtime, :volume,
|
23
|
+
:playlistlength, :xfade, :Time, :Pos, :Id, :Date, :Track, :Disc, :MUSICBRAINZ_TRACKID,
|
24
|
+
:MUSICBRAINZ_ARTISTID, :MUSICBRAINZ_ALBUMID, :MUSICBRAINZ_ALBUMARTISTID, :outputid
|
25
|
+
value.to_i
|
26
|
+
|
27
|
+
when :mixrampdb, :mixrampdelay
|
28
|
+
value == 'nan' ? Float::NAN : value.to_f
|
29
|
+
|
30
|
+
when :repeat, :random, :single, :consume, :outputenabled
|
31
|
+
value != '0'
|
32
|
+
|
33
|
+
when :db_update
|
34
|
+
Time.at(value.to_i)
|
35
|
+
|
36
|
+
when :command, :state, :changed, :replay_gain_mode
|
37
|
+
value.to_sym
|
38
|
+
|
39
|
+
when :"Last-Modified"
|
40
|
+
DateTime.iso8601(value)
|
41
|
+
|
42
|
+
else value.force_encoding('UTF-8')
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.read (io, command)
|
48
|
+
result = []
|
49
|
+
|
50
|
+
while (line = io.readline) && !line.match(/^(list_)?OK(\s|$)/) && !line.start_with?('ACK ')
|
51
|
+
name, value = line.split ': ', 2
|
52
|
+
name = name.to_sym
|
53
|
+
value = value.chomp
|
54
|
+
|
55
|
+
result << Data.new(name, value)
|
56
|
+
end
|
57
|
+
|
58
|
+
type, message = line.split ' ', 2
|
59
|
+
|
60
|
+
if type == 'OK' || type == 'list_OK'
|
61
|
+
Ok.new(command, result, message)
|
62
|
+
else
|
63
|
+
Error.new(command, result, *Error.parse(message))
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def self.parse (text)
|
68
|
+
read(StringIO.new(text))
|
69
|
+
end
|
70
|
+
|
71
|
+
include Enumerable
|
72
|
+
|
73
|
+
attr_reader :command
|
74
|
+
|
75
|
+
def initialize (command, data)
|
76
|
+
@command = command
|
77
|
+
@internal = data.freeze
|
78
|
+
end
|
79
|
+
|
80
|
+
def each
|
81
|
+
return to_enum unless block_given?
|
82
|
+
|
83
|
+
@internal.each {|data|
|
84
|
+
yield [data.name, data.value]
|
85
|
+
}
|
86
|
+
|
87
|
+
self
|
88
|
+
end
|
89
|
+
|
90
|
+
def empty?
|
91
|
+
to_a.empty?
|
92
|
+
end
|
93
|
+
|
94
|
+
def to_a
|
95
|
+
@internal
|
96
|
+
end
|
97
|
+
|
98
|
+
def to_hash
|
99
|
+
return @hash if @hash
|
100
|
+
|
101
|
+
result = {}
|
102
|
+
|
103
|
+
each {|name, value|
|
104
|
+
if result[name]
|
105
|
+
if result[name].is_a? Array
|
106
|
+
result[name] << value
|
107
|
+
else
|
108
|
+
result[name] = [result[name], value]
|
109
|
+
end
|
110
|
+
else
|
111
|
+
result[name] = value
|
112
|
+
end
|
113
|
+
}
|
114
|
+
|
115
|
+
@hash = result.freeze
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
class Ok < Response
|
120
|
+
attr_reader :message
|
121
|
+
|
122
|
+
def initialize (command, data, message)
|
123
|
+
super(command, data)
|
124
|
+
|
125
|
+
@message = message
|
126
|
+
end
|
127
|
+
|
128
|
+
def success?; true; end
|
129
|
+
end
|
130
|
+
|
131
|
+
class Error < Response
|
132
|
+
Codes = {
|
133
|
+
NOT_LIST: 1,
|
134
|
+
ARG: 2,
|
135
|
+
PASSWORD: 3,
|
136
|
+
PERMISSION: 4,
|
137
|
+
UNKNOWN: 5,
|
138
|
+
|
139
|
+
NO_EXIST: 50,
|
140
|
+
PLAYLIST_MAX: 51,
|
141
|
+
SYSTEM: 52,
|
142
|
+
PLAYLIST_LOAD: 53,
|
143
|
+
UPDATE_ALREADY: 54,
|
144
|
+
PLAYER_SYNC: 55,
|
145
|
+
EXIST: 56
|
146
|
+
}
|
147
|
+
|
148
|
+
def self.parse (text)
|
149
|
+
text.match(/^\[(\d+)@(\d+)\] {([^}]*)} (.*?)$/).to_a[1 .. -1]
|
150
|
+
end
|
151
|
+
|
152
|
+
attr_reader :offset, :message
|
153
|
+
|
154
|
+
def initialize (command, data, code, offset, command_name, message)
|
155
|
+
if !command_name.empty? && command.name != command_name.to_sym
|
156
|
+
raise ArgumentError, 'the passed command object and the response command name do not match'
|
157
|
+
end
|
158
|
+
|
159
|
+
super(command, data)
|
160
|
+
|
161
|
+
@code = (code.is_a?(Integer) || Integer(code) rescue false) ? Codes.key(code.to_i) : code.to_sym.upcase
|
162
|
+
@offset = offset.to_i
|
163
|
+
@message = message
|
164
|
+
|
165
|
+
unless Codes[to_sym]
|
166
|
+
raise ArgumentError, 'the Error code does not exist'
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
def success?; false; end
|
171
|
+
|
172
|
+
def to_sym
|
173
|
+
@code
|
174
|
+
end
|
175
|
+
|
176
|
+
def to_i
|
177
|
+
Codes[to_sym]
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
end; end
|
data/lib/mpd/version.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
#--
|
2
|
+
# DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
3
|
+
# Version 2, December 2004
|
4
|
+
#
|
5
|
+
# DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
6
|
+
# TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
7
|
+
#
|
8
|
+
# 0. You just DO WHAT THE FUCK YOU WANT TO.
|
9
|
+
#++
|
10
|
+
|
11
|
+
module MPD
|
12
|
+
def self.version
|
13
|
+
'0.17.0'
|
14
|
+
end
|
15
|
+
end
|
data/mpd.gemspec
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
Kernel.load 'lib/mpd/version.rb'
|
2
|
+
|
3
|
+
Gem::Specification.new {|s|
|
4
|
+
s.name = 'mpd'
|
5
|
+
s.version = MPD.version
|
6
|
+
s.author = 'meh.'
|
7
|
+
s.email = 'meh@paranoici.org'
|
8
|
+
s.homepage = 'http://github.com/meh/ruby-mpd'
|
9
|
+
s.platform = Gem::Platform::RUBY
|
10
|
+
s.summary = 'MPD controller library.'
|
11
|
+
|
12
|
+
s.files = `git ls-files`.split("\n")
|
13
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
|
14
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
15
|
+
s.require_paths = ['lib']
|
16
|
+
}
|
metadata
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: mpd
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.17.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- meh.
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-07-07 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description:
|
15
|
+
email: meh@paranoici.org
|
16
|
+
executables:
|
17
|
+
- mpc.rb
|
18
|
+
extensions: []
|
19
|
+
extra_rdoc_files: []
|
20
|
+
files:
|
21
|
+
- README.md
|
22
|
+
- bin/mpc.rb
|
23
|
+
- lib/mpd.rb
|
24
|
+
- lib/mpd/controller.rb
|
25
|
+
- lib/mpd/controller/audio.rb
|
26
|
+
- lib/mpd/controller/channels.rb
|
27
|
+
- lib/mpd/controller/commands.rb
|
28
|
+
- lib/mpd/controller/config.rb
|
29
|
+
- lib/mpd/controller/current_playlist.rb
|
30
|
+
- lib/mpd/controller/database.rb
|
31
|
+
- lib/mpd/controller/decoders.rb
|
32
|
+
- lib/mpd/controller/do.rb
|
33
|
+
- lib/mpd/controller/player.rb
|
34
|
+
- lib/mpd/controller/playlists.rb
|
35
|
+
- lib/mpd/controller/stats.rb
|
36
|
+
- lib/mpd/controller/status.rb
|
37
|
+
- lib/mpd/controller/stickers.rb
|
38
|
+
- lib/mpd/controller/supported_protocols.rb
|
39
|
+
- lib/mpd/controller/supported_tags.rb
|
40
|
+
- lib/mpd/controller/toggle.rb
|
41
|
+
- lib/mpd/protocol.rb
|
42
|
+
- lib/mpd/protocol/command.rb
|
43
|
+
- lib/mpd/protocol/command_list.rb
|
44
|
+
- lib/mpd/protocol/response.rb
|
45
|
+
- lib/mpd/version.rb
|
46
|
+
- mpd.gemspec
|
47
|
+
homepage: http://github.com/meh/ruby-mpd
|
48
|
+
licenses: []
|
49
|
+
post_install_message:
|
50
|
+
rdoc_options: []
|
51
|
+
require_paths:
|
52
|
+
- lib
|
53
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
54
|
+
none: false
|
55
|
+
requirements:
|
56
|
+
- - ! '>='
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
version: '0'
|
59
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
60
|
+
none: false
|
61
|
+
requirements:
|
62
|
+
- - ! '>='
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: '0'
|
65
|
+
requirements: []
|
66
|
+
rubyforge_project:
|
67
|
+
rubygems_version: 1.8.24
|
68
|
+
signing_key:
|
69
|
+
specification_version: 3
|
70
|
+
summary: MPD controller library.
|
71
|
+
test_files: []
|