ruby-mpd-client 0.2.0 → 1.0.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.
- checksums.yaml +5 -5
- data/.travis.yml +10 -0
- data/README.md +13 -5
- data/lib/mpd/commands.rb +61 -0
- data/lib/mpd/commands/abstract.rb +61 -0
- data/lib/mpd/commands/all_files.rb +17 -0
- data/lib/mpd/commands/change_volume.rb +14 -0
- data/lib/mpd/commands/current_playlist_add.rb +19 -0
- data/lib/mpd/commands/current_playlist_info.rb +18 -0
- data/lib/mpd/commands/current_playlist_remove.rb +20 -0
- data/lib/mpd/commands/current_song.rb +14 -0
- data/lib/mpd/commands/ping.rb +23 -0
- data/lib/mpd/commands/play.rb +23 -0
- data/lib/mpd/commands/set_volume.rb +14 -0
- data/lib/mpd/commands/status.rb +14 -0
- data/lib/mpd/connection.rb +41 -0
- data/lib/mpd/server_response.rb +50 -0
- data/lib/mpd/version.rb +1 -1
- data/lib/ruby-mpd-client.rb +1 -1
- data/ruby-mpd-client.gemspec +1 -0
- metadata +32 -10
- data/lib/mpd/client.rb +0 -51
- data/lib/mpd/client/commands.rb +0 -10
- data/lib/mpd/client/commands/current_playlist.rb +0 -17
- data/lib/mpd/client/commands/playback_control.rb +0 -36
- data/lib/mpd/client/commands/playback_options.rb +0 -36
- data/lib/mpd/client/connection.rb +0 -39
- data/lib/mpd/client/server_response.rb +0 -52
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 8ca78849c735d15541f0f0e04e83ac1af66d71c3c3202739a0718f7cfc7860e4
|
4
|
+
data.tar.gz: db532da5093220f87880cd0d47137866b089be98ba8d03a7aa89334869b6da9d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0d23063c2519c020bcf16009a1f6f1874b2d4f53ad41879fc023b5b460e9a531f13a5a665574399cef5836bd9fadbfd4213d2a64f8cef966fa2b8c2dd79194e4
|
7
|
+
data.tar.gz: 0423b775979eb61f9eff55fcfd05d29e6375a17df5e1caf2bb6b9828d7b2d3c32e84e10c792ade9ab004f0462a91292d225e0851f9164a417c6f55c1b698504d
|
data/.travis.yml
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
language: ruby
|
2
|
+
rvm:
|
3
|
+
- 2.3.0
|
4
|
+
script: rake spec
|
5
|
+
deploy:
|
6
|
+
provider: rubygems
|
7
|
+
api_key:
|
8
|
+
secure: CCtmgUnWoiG4tKRalp9kfEcaeDUfipES0mcWPV4K0D/K651nxZ0kHe+VV+3rpvV1KDs4i5W+TosVvpH5lDL7+oALLFTsYgo3iam+kzMLfoskkZUuizUDxYjXrWI0T+SM0gL3Ax1J9oJ0cd7j1sUGi5TZ/IHXrKknm1yqFIx83mgKCFxYKJUAwQuwpo924ukqyQ0IsJtYX7AJ31hQwFBZSscJbriaxsz3dN+ptmvYVt9/+oIowHrvZCFnlgejel/eZ9iKCMR8buxx1RF3Q3y7LZkpMb20UBfjMwUkz/XBXGFCFVUaCLEcdFnAuoRePJ8a+q3Qkd0wZp+5g2offguVycTWsPTGgSjSAXcPUK0fOnE6bsBZ9XnkAiwkPtxO3MeG7iBcGBX2XY/Tzl+8EW2FgGeIICBh5sg+UqmrGAuqzmtgrJJwOaBeyLEbAKemAdPRfN7M0Hq1DgbOHchttmiCAY1Ja/RBiYwbEkZsPn9VI2tH3CUvdqc0B4jPV05OKU1sv06hHKJTWoCjsmvd52Tr0Kbr5ofBvLMj+uHnyCx78SwfReVCPEb2PzK5GUBG6+Ufu8UOTFdlS8gDmSO09R/qd/kSILvxCLntNVQAn/aUlnZ0aBJURxhoTQkKRSBGcGrOUXhMKnj3jnwZw1othJ5xxiSXy6fM/8JrsxyPH7TalT8=
|
9
|
+
on:
|
10
|
+
branch: master
|
data/README.md
CHANGED
@@ -18,13 +18,21 @@ It does not do much
|
|
18
18
|
```ruby
|
19
19
|
require 'ruby-mpd-client'
|
20
20
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
#
|
21
|
+
MPD::Commands::SetVolume.new(host: 'localhost') # :host can be ommited
|
22
|
+
.execute(75)
|
23
|
+
MPD::Commands::Next.new.execute
|
24
|
+
|
25
|
+
#
|
26
|
+
# to use one connection
|
27
|
+
#
|
28
|
+
conn = MPD::Connection.new(host: 'localhost', port: 6600)
|
29
|
+
conn.connect
|
30
|
+
MPD::Commands::Next.new(connection: conn).execute
|
31
|
+
MPD::Commands::Pause.new(connection: conn).execute
|
26
32
|
```
|
27
33
|
|
34
|
+
For available commands see [lib/mpd/commands](lib/mpd/commands).
|
35
|
+
|
28
36
|
## Contributing
|
29
37
|
|
30
38
|
Bug reports and pull requests are welcome on GitHub at https://github.com/Nondv/ruby-mpd-client.
|
data/lib/mpd/commands.rb
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
Dir[File.join(__dir__, 'commands', '*.rb')].each { |f| require f }
|
2
|
+
|
3
|
+
module MPD
|
4
|
+
#
|
5
|
+
# Contains classes representing MPD commands
|
6
|
+
#
|
7
|
+
module Commands
|
8
|
+
#
|
9
|
+
# To decrease code amount
|
10
|
+
#
|
11
|
+
def self.define_trivial_command(class_name, command)
|
12
|
+
klass = Class.new(::MPD::Commands::Abstract) do
|
13
|
+
define_method :execute do
|
14
|
+
super(command)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
const_set(class_name, klass)
|
19
|
+
end
|
20
|
+
|
21
|
+
#
|
22
|
+
# To define commands like 'save "whatever this is"'
|
23
|
+
#
|
24
|
+
def self.define_text_argument_command(class_name, command)
|
25
|
+
klass = Class.new(::MPD::Commands::Abstract) do
|
26
|
+
define_method :execute do |arg|
|
27
|
+
super("#{command} \"#{arg}\"")
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
const_set(class_name, klass)
|
32
|
+
end
|
33
|
+
|
34
|
+
#
|
35
|
+
# To define commands like "random <1/0>"
|
36
|
+
#
|
37
|
+
def self.define_option_command(class_name, command)
|
38
|
+
klass = Class.new(::MPD::Commands::Abstract) do
|
39
|
+
define_method :execute do |state|
|
40
|
+
super(command + state ? ' 1' : ' 0')
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
const_set(class_name, klass)
|
45
|
+
end
|
46
|
+
|
47
|
+
define_trivial_command(:Pause, 'pause 1')
|
48
|
+
define_trivial_command(:Stop, 'stop')
|
49
|
+
define_trivial_command(:Previous, 'previous')
|
50
|
+
define_trivial_command(:Next, 'next')
|
51
|
+
define_trivial_command(:CurrentPlaylistClear, 'clear')
|
52
|
+
|
53
|
+
define_text_argument_command :PlaylistDelete, :rm
|
54
|
+
define_text_argument_command :PlaylistSave, :save
|
55
|
+
define_text_argument_command :PlaylistLoad, :load
|
56
|
+
|
57
|
+
%w[Consume Crossfade Random Repeat Single].each do |class_name|
|
58
|
+
define_option_command(class_name, class_name.downcase)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'mpd/connection'
|
2
|
+
require 'mpd/server_response'
|
3
|
+
require 'mpd/playlist'
|
4
|
+
|
5
|
+
module MPD
|
6
|
+
module Commands
|
7
|
+
#
|
8
|
+
# Base class for MPD commands.
|
9
|
+
#
|
10
|
+
class Abstract
|
11
|
+
attr_reader :connection
|
12
|
+
|
13
|
+
#
|
14
|
+
# You can provide you own connection. It should have same
|
15
|
+
#
|
16
|
+
def initialize(connection: nil, host: 'localhost', port: 6600)
|
17
|
+
@connection = connection || Connection.new(host: host, port: port).tap(&:connect).tap(&:gets)
|
18
|
+
end
|
19
|
+
|
20
|
+
#
|
21
|
+
# This method should be overriden.
|
22
|
+
# Example:
|
23
|
+
#
|
24
|
+
# def execute
|
25
|
+
# super('ping')
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
def execute(command)
|
29
|
+
exec_command(command)
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def exec_command(command)
|
35
|
+
connection.puts(command)
|
36
|
+
response = ServerResponse.from_connection(connection)
|
37
|
+
raise(MpdError, response.status) if response.error?
|
38
|
+
response
|
39
|
+
end
|
40
|
+
|
41
|
+
def exec_command_list(commands)
|
42
|
+
connection.puts('command_list_begin')
|
43
|
+
commands.each { |c| connection.puts(c) }
|
44
|
+
connection.puts('command_list_end')
|
45
|
+
|
46
|
+
response = ServerResponse.from_connection(connection)
|
47
|
+
raise(MpdError, response.status) if response.error?
|
48
|
+
response
|
49
|
+
end
|
50
|
+
|
51
|
+
def resolve_range(arg)
|
52
|
+
if arg.is_a?(Range)
|
53
|
+
last = arg.exclude_end? ? arg.end : arg.end + 1
|
54
|
+
"#{arg.begin}:#{last}"
|
55
|
+
else
|
56
|
+
arg
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'mpd/commands/abstract'
|
2
|
+
|
3
|
+
module MPD
|
4
|
+
module Commands
|
5
|
+
#
|
6
|
+
# Uses "listall" command to get
|
7
|
+
# all files (directories are filtered out) from db.
|
8
|
+
#
|
9
|
+
class AllFiles < Abstract
|
10
|
+
def execute
|
11
|
+
super('listall').key_value_pairs
|
12
|
+
.select { |e| e[0] == 'file' }
|
13
|
+
.map(&:last)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'mpd/commands/abstract'
|
2
|
+
|
3
|
+
module MPD
|
4
|
+
module Commands
|
5
|
+
#
|
6
|
+
# Adds song(s) to current playlist
|
7
|
+
# `songs` is an array of URIs.
|
8
|
+
#
|
9
|
+
class CurrentPlaylistAdd < Abstract
|
10
|
+
#
|
11
|
+
# `songs` is position (as int) or range
|
12
|
+
#
|
13
|
+
def execute(songs)
|
14
|
+
return exec_command("add \"#{songs}\"") unless songs.is_a?(Array)
|
15
|
+
exec_command_list(songs.map { |s| "add \"#{s}\"" })
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'mpd/commands/abstract'
|
2
|
+
|
3
|
+
module MPD
|
4
|
+
module Commands
|
5
|
+
#
|
6
|
+
# Info about songs in current playlist
|
7
|
+
#
|
8
|
+
class CurrentPlaylistInfo < Abstract
|
9
|
+
# `songs` can be range
|
10
|
+
# or integer (to show info about one song)
|
11
|
+
# or completely ommited (to show info about all songs)
|
12
|
+
def execute(songs = nil)
|
13
|
+
response = super("playlistinfo #{resolve_range(songs)}")
|
14
|
+
Playlist.from_response(response)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'mpd/commands/abstract'
|
2
|
+
|
3
|
+
module MPD
|
4
|
+
module Commands
|
5
|
+
#
|
6
|
+
# Removes songs from current playlist
|
7
|
+
# by id or position/range
|
8
|
+
#
|
9
|
+
class CurrentPlaylistRemove < Abstract
|
10
|
+
#
|
11
|
+
# `position` is int or range
|
12
|
+
# `id` is int song id
|
13
|
+
#
|
14
|
+
def execute(position: nil, id: nil)
|
15
|
+
raise(ArgumentError) if position && id || !position && !id
|
16
|
+
exec_command(id ? "deleteid #{id}" : "delete #{resolve_range(position)}")
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'mpd/commands/abstract'
|
2
|
+
|
3
|
+
module MPD
|
4
|
+
module Commands
|
5
|
+
#
|
6
|
+
# Tries to execute "ping" command.
|
7
|
+
# Returns `true` if succedeed,
|
8
|
+
# raises error if `MpdError` occurred,
|
9
|
+
# `false` otherwise
|
10
|
+
#
|
11
|
+
class Ping < Abstract
|
12
|
+
# rubocop:disable Lint/RescueWithoutErrorClass
|
13
|
+
def execute
|
14
|
+
super('ping')
|
15
|
+
true
|
16
|
+
rescue => e
|
17
|
+
raise e if e.is_a?(MpdError)
|
18
|
+
false
|
19
|
+
end
|
20
|
+
# rubocop:enable Lint/RescueWithoutErrorClass
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'mpd/commands/abstract'
|
2
|
+
|
3
|
+
module MPD
|
4
|
+
module Commands
|
5
|
+
#
|
6
|
+
# Play specific song (by id or cur. playlist position).
|
7
|
+
#
|
8
|
+
#
|
9
|
+
class Play < Abstract
|
10
|
+
def execute(position: nil, id: nil)
|
11
|
+
raise(ArgumentError, 'too many arguments') if position && id
|
12
|
+
|
13
|
+
if position
|
14
|
+
super("play #{position}")
|
15
|
+
elsif id
|
16
|
+
super("playid #{id}")
|
17
|
+
else
|
18
|
+
super('play')
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'socket'
|
2
|
+
|
3
|
+
module MPD
|
4
|
+
#
|
5
|
+
# Simple wrapper over Socket
|
6
|
+
#
|
7
|
+
class Connection
|
8
|
+
def initialize(host:, port:)
|
9
|
+
@host = host
|
10
|
+
@port = port
|
11
|
+
end
|
12
|
+
|
13
|
+
def connect
|
14
|
+
disconnect if socket
|
15
|
+
@socket = TCPSocket.open(host, port)
|
16
|
+
end
|
17
|
+
|
18
|
+
def disconnect
|
19
|
+
socket && socket.close
|
20
|
+
@socket = nil
|
21
|
+
end
|
22
|
+
|
23
|
+
def puts(text)
|
24
|
+
raise ConnectionError unless socket
|
25
|
+
socket.puts(text)
|
26
|
+
rescue Errno::ECONNRESET
|
27
|
+
raise ConnectionError
|
28
|
+
end
|
29
|
+
|
30
|
+
def gets
|
31
|
+
raise ConnectionError unless socket
|
32
|
+
socket.gets || raise(ConnectionError)
|
33
|
+
rescue Errno::ECONNRESET
|
34
|
+
raise ConnectionError
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
attr_reader :socket, :host, :port
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module MPD
|
2
|
+
#
|
3
|
+
# Just a frozen string with some useful methods
|
4
|
+
#
|
5
|
+
class ServerResponse < String
|
6
|
+
def self.from_connection(conn)
|
7
|
+
line = ''
|
8
|
+
buffer = ''
|
9
|
+
while line != "OK\n" && !line.start_with?('ACK')
|
10
|
+
line = conn.gets
|
11
|
+
raise(ConnectionError) if line.nil?
|
12
|
+
buffer << line
|
13
|
+
end
|
14
|
+
|
15
|
+
new(buffer.force_encoding('UTF-8'))
|
16
|
+
end
|
17
|
+
|
18
|
+
def initialize(response_text)
|
19
|
+
super
|
20
|
+
freeze
|
21
|
+
end
|
22
|
+
|
23
|
+
def to_h
|
24
|
+
key_value_pairs.to_h
|
25
|
+
end
|
26
|
+
|
27
|
+
def key_value_pairs
|
28
|
+
content.split("\n").map do |line|
|
29
|
+
index = line.index(':')
|
30
|
+
raise "can't create key-value pair" unless index
|
31
|
+
key = line[0...index]
|
32
|
+
value = line[(index + 1)..-1].strip
|
33
|
+
[key, value]
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# text without status
|
38
|
+
def content
|
39
|
+
lines[0..-2].join
|
40
|
+
end
|
41
|
+
|
42
|
+
def status
|
43
|
+
lines.last.chomp
|
44
|
+
end
|
45
|
+
|
46
|
+
def error?
|
47
|
+
status.start_with?('ACK')
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
data/lib/mpd/version.rb
CHANGED
data/lib/ruby-mpd-client.rb
CHANGED
data/ruby-mpd-client.gemspec
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby-mpd-client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dmitriy Non
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-12-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -38,6 +38,20 @@ dependencies:
|
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec-its
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
41
55
|
description:
|
42
56
|
email:
|
43
57
|
- non.dmitriy@gmail.com
|
@@ -46,21 +60,29 @@ extensions: []
|
|
46
60
|
extra_rdoc_files: []
|
47
61
|
files:
|
48
62
|
- ".gitignore"
|
63
|
+
- ".travis.yml"
|
49
64
|
- Gemfile
|
50
65
|
- LICENSE.txt
|
51
66
|
- README.md
|
52
67
|
- Rakefile
|
53
68
|
- bin/console
|
54
69
|
- bin/setup
|
55
|
-
- lib/mpd/
|
56
|
-
- lib/mpd/
|
57
|
-
- lib/mpd/
|
58
|
-
- lib/mpd/
|
59
|
-
- lib/mpd/
|
60
|
-
- lib/mpd/
|
61
|
-
- lib/mpd/
|
70
|
+
- lib/mpd/commands.rb
|
71
|
+
- lib/mpd/commands/abstract.rb
|
72
|
+
- lib/mpd/commands/all_files.rb
|
73
|
+
- lib/mpd/commands/change_volume.rb
|
74
|
+
- lib/mpd/commands/current_playlist_add.rb
|
75
|
+
- lib/mpd/commands/current_playlist_info.rb
|
76
|
+
- lib/mpd/commands/current_playlist_remove.rb
|
77
|
+
- lib/mpd/commands/current_song.rb
|
78
|
+
- lib/mpd/commands/ping.rb
|
79
|
+
- lib/mpd/commands/play.rb
|
80
|
+
- lib/mpd/commands/set_volume.rb
|
81
|
+
- lib/mpd/commands/status.rb
|
82
|
+
- lib/mpd/connection.rb
|
62
83
|
- lib/mpd/errors.rb
|
63
84
|
- lib/mpd/playlist.rb
|
85
|
+
- lib/mpd/server_response.rb
|
64
86
|
- lib/mpd/song.rb
|
65
87
|
- lib/mpd/version.rb
|
66
88
|
- lib/ruby-mpd-client.rb
|
@@ -85,7 +107,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
85
107
|
version: '0'
|
86
108
|
requirements: []
|
87
109
|
rubyforge_project:
|
88
|
-
rubygems_version: 2.
|
110
|
+
rubygems_version: 2.7.3
|
89
111
|
signing_key:
|
90
112
|
specification_version: 4
|
91
113
|
summary: yet another MPD client on Ruby
|
data/lib/mpd/client.rb
DELETED
@@ -1,51 +0,0 @@
|
|
1
|
-
require 'mpd/client/connection'
|
2
|
-
require 'mpd/client/server_response'
|
3
|
-
require 'mpd/client/commands'
|
4
|
-
|
5
|
-
module MPD
|
6
|
-
class Client
|
7
|
-
def self.connect(host: 'localhost', port: 6600)
|
8
|
-
new(host: host, port: port).tap(&:connect)
|
9
|
-
end
|
10
|
-
|
11
|
-
def initialize(host: 'localhost', port: 6600)
|
12
|
-
@connection = Connection.new(host: host, port: port)
|
13
|
-
end
|
14
|
-
|
15
|
-
def current_song
|
16
|
-
execute('currentsong').to_h
|
17
|
-
end
|
18
|
-
|
19
|
-
def status
|
20
|
-
response = execute('status')
|
21
|
-
response.to_h
|
22
|
-
end
|
23
|
-
|
24
|
-
def execute(command)
|
25
|
-
connection.puts(command)
|
26
|
-
response = ServerResponse.from_connection(connection)
|
27
|
-
raise(MpdError, response.status) if response.error?
|
28
|
-
response
|
29
|
-
end
|
30
|
-
|
31
|
-
def connected?
|
32
|
-
execute('ping')
|
33
|
-
rescue => e
|
34
|
-
raise e if e.is_a?(MpdError)
|
35
|
-
false
|
36
|
-
end
|
37
|
-
|
38
|
-
def connect
|
39
|
-
connection.connect
|
40
|
-
raise(ConnectionError) unless connection.gets =~ /^OK/
|
41
|
-
end
|
42
|
-
|
43
|
-
def disconnect
|
44
|
-
connection.disconnect
|
45
|
-
end
|
46
|
-
|
47
|
-
private
|
48
|
-
|
49
|
-
attr_reader :connection
|
50
|
-
end
|
51
|
-
end
|
data/lib/mpd/client/commands.rb
DELETED
@@ -1,17 +0,0 @@
|
|
1
|
-
require 'mpd/playlist'
|
2
|
-
|
3
|
-
module MPD
|
4
|
-
class Client
|
5
|
-
module Commands
|
6
|
-
# https://www.musicpd.org/doc/protocol/queue.html
|
7
|
-
module CurrentPlaylist
|
8
|
-
# songs - integer or range
|
9
|
-
def playlist_info(songs = nil)
|
10
|
-
argument = songs.is_a?(Range) ? "#{songs.begin}:#{songs.end}" : songs
|
11
|
-
response = execute "playlistinfo #{argument}"
|
12
|
-
Playlist.from_response(response)
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
@@ -1,36 +0,0 @@
|
|
1
|
-
module MPD
|
2
|
-
class Client
|
3
|
-
module Commands
|
4
|
-
# https://www.musicpd.org/doc/protocol/playback_commands.html
|
5
|
-
module PlaybackControl
|
6
|
-
def play(position: nil, id: nil)
|
7
|
-
raise(ArgumentError, 'too many arguments') if position && id
|
8
|
-
|
9
|
-
if position
|
10
|
-
execute "play #{position}"
|
11
|
-
elsif id
|
12
|
-
execute "playid #{id}"
|
13
|
-
else
|
14
|
-
execute 'pause 0'
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
def pause
|
19
|
-
execute 'pause 1'
|
20
|
-
end
|
21
|
-
|
22
|
-
def stop
|
23
|
-
execute 'stop'
|
24
|
-
end
|
25
|
-
|
26
|
-
def previous
|
27
|
-
execute 'previous'
|
28
|
-
end
|
29
|
-
|
30
|
-
def next
|
31
|
-
execute 'next'
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
@@ -1,36 +0,0 @@
|
|
1
|
-
module MPD
|
2
|
-
class Client
|
3
|
-
module Commands
|
4
|
-
# https://www.musicpd.org/doc/protocol/playback_option_commands.html
|
5
|
-
module PlaybackOptions
|
6
|
-
def consume(state)
|
7
|
-
execute "consume #{state ? 1 : 0}"
|
8
|
-
end
|
9
|
-
|
10
|
-
def crossfade(state)
|
11
|
-
execute "crossfade #{state ? 1 : 0}"
|
12
|
-
end
|
13
|
-
|
14
|
-
def random(state)
|
15
|
-
execute "random #{state ? 1 : 0}"
|
16
|
-
end
|
17
|
-
|
18
|
-
def repeat(state)
|
19
|
-
execute "repeat #{state ? 1 : 0}"
|
20
|
-
end
|
21
|
-
|
22
|
-
def single(state)
|
23
|
-
execute "single #{state ? 1 : 0}"
|
24
|
-
end
|
25
|
-
|
26
|
-
def volume(val)
|
27
|
-
execute "setvol #{val}"
|
28
|
-
end
|
29
|
-
|
30
|
-
def change_volume_by(val)
|
31
|
-
execute("volume #{val}")
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
@@ -1,39 +0,0 @@
|
|
1
|
-
require 'socket'
|
2
|
-
|
3
|
-
module MPD
|
4
|
-
class Client
|
5
|
-
#
|
6
|
-
# It's `Client`'s internal class. Don't use it outside `Client`
|
7
|
-
#
|
8
|
-
class Connection
|
9
|
-
def initialize(host:, port:)
|
10
|
-
@host = host
|
11
|
-
@port = port
|
12
|
-
end
|
13
|
-
|
14
|
-
def connect
|
15
|
-
disconnect if socket
|
16
|
-
@socket = TCPSocket.open(host, port)
|
17
|
-
end
|
18
|
-
|
19
|
-
def disconnect
|
20
|
-
socket && socket.close
|
21
|
-
@socket = nil
|
22
|
-
end
|
23
|
-
|
24
|
-
def puts(text)
|
25
|
-
raise ConnectionError unless socket
|
26
|
-
socket.puts(text)
|
27
|
-
end
|
28
|
-
|
29
|
-
def gets
|
30
|
-
raise ConnectionError unless socket
|
31
|
-
socket.gets
|
32
|
-
end
|
33
|
-
|
34
|
-
private
|
35
|
-
|
36
|
-
attr_reader :socket, :host, :port
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
@@ -1,52 +0,0 @@
|
|
1
|
-
module MPD
|
2
|
-
class Client
|
3
|
-
#
|
4
|
-
# Just a frozen string with some useful methods
|
5
|
-
#
|
6
|
-
class ServerResponse < String
|
7
|
-
def self.from_connection(conn)
|
8
|
-
line = ''
|
9
|
-
buffer = ''
|
10
|
-
while line != "OK\n" && !line.start_with?('ACK')
|
11
|
-
line = conn.gets
|
12
|
-
raise(ConnectionError) if line.nil?
|
13
|
-
buffer << line
|
14
|
-
end
|
15
|
-
|
16
|
-
new(buffer.force_encoding('UTF-8'))
|
17
|
-
end
|
18
|
-
|
19
|
-
def initialize(response_text)
|
20
|
-
super
|
21
|
-
freeze
|
22
|
-
end
|
23
|
-
|
24
|
-
def to_h
|
25
|
-
key_value_pairs.to_h
|
26
|
-
end
|
27
|
-
|
28
|
-
def key_value_pairs
|
29
|
-
content.split("\n").map do |line|
|
30
|
-
index = line.index(':')
|
31
|
-
raise "can't create key-value pair" unless index
|
32
|
-
key = line[0...index]
|
33
|
-
value = line[(index + 1)..-1].strip
|
34
|
-
[key, value]
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
# text without status
|
39
|
-
def content
|
40
|
-
lines[0..-2].join
|
41
|
-
end
|
42
|
-
|
43
|
-
def status
|
44
|
-
lines.last.chomp
|
45
|
-
end
|
46
|
-
|
47
|
-
def error?
|
48
|
-
status.start_with?('ACK')
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|