ruby-mpd 0.1.4
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/.gitignore +22 -0
- data/AUTHORS +1 -0
- data/COPYING +340 -0
- data/DOC.rdoc +78 -0
- data/README.rdoc +174 -0
- data/data/database.yaml +347 -0
- data/examples/rmpc.rb +67 -0
- data/examples/tailmpc.rb +115 -0
- data/lib/mpdserver.rb +1206 -0
- data/lib/ruby-mpd.rb +310 -0
- data/lib/ruby-mpd/parser.rb +151 -0
- data/lib/ruby-mpd/playlist.rb +77 -0
- data/lib/ruby-mpd/plugins/channels.rb +58 -0
- data/lib/ruby-mpd/plugins/controls.rb +72 -0
- data/lib/ruby-mpd/plugins/database.rb +79 -0
- data/lib/ruby-mpd/plugins/information.rb +146 -0
- data/lib/ruby-mpd/plugins/outputs.rb +26 -0
- data/lib/ruby-mpd/plugins/playback_options.rb +88 -0
- data/lib/ruby-mpd/plugins/playlists.rb +17 -0
- data/lib/ruby-mpd/plugins/queue.rb +125 -0
- data/lib/ruby-mpd/plugins/reflection.rb +46 -0
- data/lib/ruby-mpd/plugins/stickers.rb +52 -0
- data/lib/ruby-mpd/song.rb +31 -0
- data/ruby-mpd.gemspec +17 -0
- data/tests/libtests.rb +1145 -0
- data/tests/servertests.rb +3405 -0
- metadata +73 -0
@@ -0,0 +1,77 @@
|
|
1
|
+
class MPD
|
2
|
+
# An object representing an .m3u playlist stored by MPD.
|
3
|
+
#
|
4
|
+
# Playlists are stored inside the configured playlist directory. They are
|
5
|
+
# addressed with their file name (without the directory and without the
|
6
|
+
# .m3u suffix).
|
7
|
+
#
|
8
|
+
# Some of the commands described in this section can be used to run playlist
|
9
|
+
# plugins instead of the hard-coded simple m3u parser. They can access
|
10
|
+
# playlists in the music directory (relative path including the suffix) or
|
11
|
+
# remote playlists (absolute URI with a supported scheme).
|
12
|
+
#
|
13
|
+
# Changes: rm -> destroy. listplaylistinfo -> songs. Playlist prefixes
|
14
|
+
# dropped also of course. Listplaylist not used, kinda inferior to listplaylistinfo
|
15
|
+
class Playlist
|
16
|
+
|
17
|
+
attr_accessor :name
|
18
|
+
|
19
|
+
def initialize(mpd, options)
|
20
|
+
@name = options[:playlist]
|
21
|
+
@mpd = mpd
|
22
|
+
#@last_modified = options[:'last-modified']
|
23
|
+
end
|
24
|
+
|
25
|
+
# Lists the songs in the playlist. Playlist plugins are supported.
|
26
|
+
# @return [Array<MPD::Song>] songs in the playlist.
|
27
|
+
def songs
|
28
|
+
mpd.build_songs_list @mpd.send_command(:listplaylistinfo, @name)
|
29
|
+
end
|
30
|
+
|
31
|
+
# Loads the playlist into the current queue. Playlist plugins are supported.
|
32
|
+
#
|
33
|
+
# Since 0.17, a range can be passed to load, to load only a part of the playlist.
|
34
|
+
# @macro returnraise
|
35
|
+
def load(range=nil)
|
36
|
+
@mpd.send_command :load, @name, range
|
37
|
+
end
|
38
|
+
|
39
|
+
# Adds URI to the playlist.
|
40
|
+
# @macro returnraise
|
41
|
+
def add(uri)
|
42
|
+
@mpd.send_command :playlistadd, @name, uri
|
43
|
+
end
|
44
|
+
|
45
|
+
# Clears the playlist.
|
46
|
+
# @macro returnraise
|
47
|
+
def clear
|
48
|
+
@mpd.send_command :playlistclear, @name
|
49
|
+
end
|
50
|
+
|
51
|
+
# Deletes song at position POS from the playlist.
|
52
|
+
# @macro returnraise
|
53
|
+
def delete(pos)
|
54
|
+
@mpd.send_command :playlistdelete, @name, pos
|
55
|
+
end
|
56
|
+
|
57
|
+
# Moves song with SONGID in the playlist to the position SONGPOS.
|
58
|
+
# @macro returnraise
|
59
|
+
def move(songid, songpos)
|
60
|
+
@mpd.send_command :playlistmove, @name
|
61
|
+
end
|
62
|
+
|
63
|
+
# Renames the playlist to +new_name+.
|
64
|
+
# @macro returnraise
|
65
|
+
def rename(new_name)
|
66
|
+
@mpd.send_command :rename, @name, new_name
|
67
|
+
@name = new_name
|
68
|
+
end
|
69
|
+
|
70
|
+
# Deletes the playlist from the disk.
|
71
|
+
# @macro returnraise
|
72
|
+
def destroy
|
73
|
+
@mpd.send_command :rm, @name
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
class MPD
|
2
|
+
module Plugins
|
3
|
+
# = Client to client commands
|
4
|
+
#
|
5
|
+
# Clients can communicate with each others over "channels". A channel
|
6
|
+
# is created by a client subscribing to it. More than one client can be
|
7
|
+
# subscribed to a channel at a time; all of them will receive the messages
|
8
|
+
# which get sent to it.
|
9
|
+
#
|
10
|
+
# Each time a client subscribes or unsubscribes, the global idle event
|
11
|
+
# subscription is generated. In conjunction with the channels command, this
|
12
|
+
# may be used to auto-detect clients providing additional services.
|
13
|
+
#
|
14
|
+
# New messages are indicated by the message idle event.
|
15
|
+
module Channels
|
16
|
+
|
17
|
+
# Subscribe to a channel. The channel is created if it does not exist already.
|
18
|
+
# The name may consist of alphanumeric ASCII characters plus underscore, dash, dot and colon.
|
19
|
+
# @param [Symbol, String] channel The channel to subscribe to.
|
20
|
+
# @macro returnraise
|
21
|
+
def subscribe(channel)
|
22
|
+
send_command :subscribe, channel
|
23
|
+
end
|
24
|
+
|
25
|
+
# Unsubscribe from a channel.
|
26
|
+
# @param [Symbol, String] channel The channel to unsibscribe from.
|
27
|
+
# @macro returnraise
|
28
|
+
def unsubscribe(channel)
|
29
|
+
send_command :unsubscribe, channel
|
30
|
+
end
|
31
|
+
|
32
|
+
# Obtain a list of all channels.
|
33
|
+
# @return [Array<String>]
|
34
|
+
# @return [String] if only one channel exists.
|
35
|
+
# @return [true] if no channels exist.
|
36
|
+
def channels
|
37
|
+
send_command :channels
|
38
|
+
end
|
39
|
+
|
40
|
+
# Reads messages for this client. The response is an array of
|
41
|
+
# hashes with +:channel+ and +:message+ keys or true if no messages.
|
42
|
+
# @return [Array<Hash>] Messages recieved.
|
43
|
+
# @return [Hash] if only one message recieved
|
44
|
+
# @return [true] if no messages.
|
45
|
+
def readmessages
|
46
|
+
send_command :readmessages
|
47
|
+
end
|
48
|
+
|
49
|
+
# Send a message to the specified channel.
|
50
|
+
# @param [Symbol, String] channel The channel to send to.
|
51
|
+
# @param [String] message The message to send.
|
52
|
+
# @macro returnraise
|
53
|
+
def sendmessage(channel, message)
|
54
|
+
send_command :sendmessage, channel, message
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
class MPD
|
2
|
+
module Plugins
|
3
|
+
# Commands for controlling playback. Changes have been made to {#seek},
|
4
|
+
# command maps to +seekcur+ from MPD and the original seek command is
|
5
|
+
# {#seekpos} here.
|
6
|
+
module Controls
|
7
|
+
# Plays the next song in the playlist.
|
8
|
+
# @macro returnraise
|
9
|
+
def next
|
10
|
+
send_command :next
|
11
|
+
end
|
12
|
+
|
13
|
+
# Resume/pause playback.
|
14
|
+
# @note The use of pause without an argument is deprecated in MPD.
|
15
|
+
# @macro returnraise
|
16
|
+
def pause=(toggle)
|
17
|
+
send_command :pause, toggle
|
18
|
+
end
|
19
|
+
|
20
|
+
# Begin playing the playist.
|
21
|
+
# @param [Integer] pos Position in the playlist to start playing.
|
22
|
+
# @macro returnraise
|
23
|
+
def play(pos = nil)
|
24
|
+
send_command :play, pos
|
25
|
+
end
|
26
|
+
|
27
|
+
# Begin playing the playlist.
|
28
|
+
# @param [Integer] songid ID of the song where to start playing.
|
29
|
+
# @macro returnraise
|
30
|
+
def playid(songid = nil)
|
31
|
+
send_command :playid, songid
|
32
|
+
end
|
33
|
+
|
34
|
+
# Plays the previous song in the playlist.
|
35
|
+
# @macro returnraise
|
36
|
+
def previous
|
37
|
+
send_command :previous
|
38
|
+
end
|
39
|
+
|
40
|
+
# Seeks to the position in seconds within the current song.
|
41
|
+
# If prefixed by '+' or '-', then the time is relative to the current
|
42
|
+
# playing position.
|
43
|
+
#
|
44
|
+
# @since MPD 0.17
|
45
|
+
# @param [Integer, String] time Position within the current song.
|
46
|
+
# Returns true if successful,
|
47
|
+
def seek(time)
|
48
|
+
send_command :seekcur, time
|
49
|
+
end
|
50
|
+
|
51
|
+
# Seeks to the position +time+ (in seconds) of the
|
52
|
+
# song at +pos+ in the playlist.
|
53
|
+
# @macro returnraise
|
54
|
+
def seekpos(pos, time)
|
55
|
+
send_command :seek, pos, time
|
56
|
+
end
|
57
|
+
|
58
|
+
# Seeks to the position +time+ (in seconds) of the song with
|
59
|
+
# the id of +songid+.
|
60
|
+
# @macro returnraise
|
61
|
+
def seekid(songid, time)
|
62
|
+
send_command :seekid, songid, time
|
63
|
+
end
|
64
|
+
|
65
|
+
# Stop playing.
|
66
|
+
# @macro returnraise
|
67
|
+
def stop
|
68
|
+
send_command :stop
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
class MPD
|
2
|
+
module Plugins
|
3
|
+
# Commands for interacting with the music database.
|
4
|
+
#
|
5
|
+
# Changes: listallinfo -> songs
|
6
|
+
module Database
|
7
|
+
|
8
|
+
# Counts the number of songs and their total playtime
|
9
|
+
# in the db matching, matching the searched tag exactly.
|
10
|
+
# @return [Hash] a hash with +songs+ and +playtime+ keys.
|
11
|
+
def count(type, what)
|
12
|
+
send_command :count, type, what
|
13
|
+
end
|
14
|
+
|
15
|
+
# Finds songs in the database that are *EXACTLY* matched by the what
|
16
|
+
# argument.
|
17
|
+
#
|
18
|
+
# @param [Symbol] type Can be any tag supported by MPD, or one of the two special
|
19
|
+
# parameters: +:file+ to search by full path (relative to database root),
|
20
|
+
# and +:any+ to match against all available tags.
|
21
|
+
# @return [Array<MPD::Song>] Songs that matched.
|
22
|
+
def find(type, what)
|
23
|
+
build_songs_list send_command(:find, type, what)
|
24
|
+
end
|
25
|
+
|
26
|
+
# findadd
|
27
|
+
|
28
|
+
# List all tags of the specified type.
|
29
|
+
# Type can be any tag supported by MPD or +:file+.
|
30
|
+
# If type is 'album' then arg can be a specific artist to list the albums for
|
31
|
+
#
|
32
|
+
# @return [Array<String>]
|
33
|
+
def list(type, arg = nil)
|
34
|
+
send_command :list, type, arg
|
35
|
+
end
|
36
|
+
|
37
|
+
# listall
|
38
|
+
|
39
|
+
# List all of the songs in the database starting at path.
|
40
|
+
# If path isn't specified, the root of the database is used
|
41
|
+
#
|
42
|
+
# @return [Array<MPD::Song>]
|
43
|
+
def songs(path = nil)
|
44
|
+
build_songs_list send_command(:listallinfo, path)
|
45
|
+
end
|
46
|
+
|
47
|
+
# lsinfo
|
48
|
+
|
49
|
+
# Searches for any song that contains +what+ in the +type+ field.
|
50
|
+
# Searches are *NOT* case sensitive.
|
51
|
+
#
|
52
|
+
# @param (see #find)
|
53
|
+
# @return [Array<MPD::Song>] Songs that matched.
|
54
|
+
def search(type, what)
|
55
|
+
build_songs_list(send_command(:search, type, what))
|
56
|
+
end
|
57
|
+
|
58
|
+
# searchadd
|
59
|
+
|
60
|
+
# searchaddpl
|
61
|
+
|
62
|
+
# Tell the server to update the database. Optionally,
|
63
|
+
# specify the path to update.
|
64
|
+
#
|
65
|
+
# @return [Integer] Update job ID
|
66
|
+
def update(path = nil)
|
67
|
+
send_command :update, path
|
68
|
+
end
|
69
|
+
|
70
|
+
# Same as {#update}, but also rescans unmodified files.
|
71
|
+
#
|
72
|
+
# @return [Integer] Update job ID
|
73
|
+
def rescan(path = nil)
|
74
|
+
send_command :rescan, path
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,146 @@
|
|
1
|
+
class MPD
|
2
|
+
module Plugins
|
3
|
+
# Informational commands regarding MPD's current status.
|
4
|
+
module Information
|
5
|
+
|
6
|
+
# Clears the current error message reported in status
|
7
|
+
# (also accomplished by any command that starts playback).
|
8
|
+
#
|
9
|
+
# @macro returnraise
|
10
|
+
def clearerror
|
11
|
+
send_command :clearerror
|
12
|
+
end
|
13
|
+
|
14
|
+
# Get the currently playing song
|
15
|
+
#
|
16
|
+
# @return [MPD::Song]
|
17
|
+
def current_song
|
18
|
+
Song.new send_command :currentsong
|
19
|
+
end
|
20
|
+
|
21
|
+
# Waits until there is a noteworthy change in one or more of MPD's subsystems.
|
22
|
+
# As soon as there is one, it lists all changed systems in a line in the format
|
23
|
+
# 'changed: SUBSYSTEM', where SUBSYSTEM is one of the following:
|
24
|
+
#
|
25
|
+
# * *database*: the song database has been modified after update.
|
26
|
+
# * *update*: a database update has started or finished. If the database was modified
|
27
|
+
# during the update, the database event is also emitted.
|
28
|
+
# * *stored_playlist*: a stored playlist has been modified, renamed, created or deleted
|
29
|
+
# * *playlist*: the current playlist has been modified
|
30
|
+
# * *player*: the player has been started, stopped or seeked
|
31
|
+
# * *mixer*: the volume has been changed
|
32
|
+
# * *output*: an audio output has been enabled or disabled
|
33
|
+
# * *options*: options like repeat, random, crossfade, replay gain
|
34
|
+
# * *sticker*: the sticker database has been modified.
|
35
|
+
# * *subscription*: a client has subscribed or unsubscribed to a channel
|
36
|
+
# * *message*: a message was received on a channel this client is subscribed to; this
|
37
|
+
# event is only emitted when the queue is empty
|
38
|
+
#
|
39
|
+
# If the optional +masks+ argument is used, MPD will only send notifications
|
40
|
+
# when something changed in one of the specified subsytems.
|
41
|
+
#
|
42
|
+
# @since MPD 0.14
|
43
|
+
# @param [Symbol] masks A list of subsystems we want to be notified on.
|
44
|
+
def idle(*masks)
|
45
|
+
send_command(:idle, *masks)
|
46
|
+
end
|
47
|
+
|
48
|
+
# MPD status: volume, time, modes...
|
49
|
+
# * *volume*: 0-100
|
50
|
+
# * *repeat*: true or false
|
51
|
+
# * *random*: true or false
|
52
|
+
# * *single*: true or false
|
53
|
+
# * *consume*: true or false
|
54
|
+
# * *playlist*: 31-bit unsigned integer, the playlist version number
|
55
|
+
# * *playlistlength*: integer, the length of the playlist
|
56
|
+
# * *state*: :play, :stop, or :pause
|
57
|
+
# * *song*: playlist song number of the current song stopped on or playing
|
58
|
+
# * *songid*: playlist songid of the current song stopped on or playing
|
59
|
+
# * *nextsong*: playlist song number of the next song to be played
|
60
|
+
# * *nextsongid*: playlist songid of the next song to be played
|
61
|
+
# * *time*: total time elapsed (of current playing/paused song)
|
62
|
+
# * *elapsed*: Total time elapsed within the current song, but with higher resolution.
|
63
|
+
# * *bitrate*: instantaneous bitrate in kbps
|
64
|
+
# * *xfade*: crossfade in seconds
|
65
|
+
# * *mixrampdb*: mixramp threshold in dB
|
66
|
+
# * *mixrampdelay*: mixrampdelay in seconds
|
67
|
+
# * *audio*: [sampleRate, bits, channels]
|
68
|
+
# * *updating_db*: job id
|
69
|
+
# * *error*: if there is an error, returns message here
|
70
|
+
#
|
71
|
+
# @return [Hash] Current MPD status.
|
72
|
+
def status
|
73
|
+
send_command :status
|
74
|
+
end
|
75
|
+
|
76
|
+
# Statistics.
|
77
|
+
#
|
78
|
+
# * *artists*: number of artists
|
79
|
+
# * *songs*: number of albums
|
80
|
+
# * *uptime*: daemon uptime in seconds
|
81
|
+
# * *db_playtime*: sum of all song times in the db
|
82
|
+
# * *db_update*: last db update in a Time object
|
83
|
+
# * *playtime*: time length of music played
|
84
|
+
#
|
85
|
+
# @return [Hash] MPD statistics.
|
86
|
+
def stats
|
87
|
+
send_command :stats
|
88
|
+
end
|
89
|
+
|
90
|
+
# Unofficial additions below
|
91
|
+
|
92
|
+
# Is MPD paused?
|
93
|
+
# @return [Boolean]
|
94
|
+
def paused?
|
95
|
+
return status[:state] == :pause
|
96
|
+
end
|
97
|
+
|
98
|
+
# Is MPD playing?
|
99
|
+
# @return [Boolean]
|
100
|
+
def playing?
|
101
|
+
return status[:state] == :play
|
102
|
+
end
|
103
|
+
|
104
|
+
# @return [Boolean] Is MPD stopped?
|
105
|
+
def stopped?
|
106
|
+
return status[:state] == :stop
|
107
|
+
end
|
108
|
+
|
109
|
+
# Gets the volume level.
|
110
|
+
# @return [Integer]
|
111
|
+
def volume
|
112
|
+
return status[:volume]
|
113
|
+
end
|
114
|
+
|
115
|
+
# @return [Integer] Crossfade in seconds.
|
116
|
+
def crossfade
|
117
|
+
return status[:xfade]
|
118
|
+
end
|
119
|
+
|
120
|
+
# @return [Integer] Current playlist version number.
|
121
|
+
def playlist_version
|
122
|
+
return status[:playlist]
|
123
|
+
end
|
124
|
+
|
125
|
+
# Returns true if consume is enabled.
|
126
|
+
def consume?
|
127
|
+
return status[:consume]
|
128
|
+
end
|
129
|
+
|
130
|
+
# Returns true if single is enabled.
|
131
|
+
def single?
|
132
|
+
return status[:single]
|
133
|
+
end
|
134
|
+
|
135
|
+
# Returns true if random playback is currently enabled,
|
136
|
+
def random?
|
137
|
+
return status[:random]
|
138
|
+
end
|
139
|
+
|
140
|
+
# Returns true if repeat is enabled,
|
141
|
+
def repeat?
|
142
|
+
return status[:repeat]
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
class MPD
|
2
|
+
module Plugins
|
3
|
+
# Commands related to audio output devices.
|
4
|
+
module Outputs
|
5
|
+
# Gives a list of all outputs
|
6
|
+
# @return [Array<Hash>] An array of outputs.
|
7
|
+
def outputs
|
8
|
+
send_command :outputs
|
9
|
+
end
|
10
|
+
|
11
|
+
# Enables specified output.
|
12
|
+
# @param [Integer] num Number of the output to enable.
|
13
|
+
# @macro returnraise
|
14
|
+
def enableoutput(num)
|
15
|
+
send_command :enableoutput, num
|
16
|
+
end
|
17
|
+
|
18
|
+
# Disables specified output.
|
19
|
+
# @param [Integer] num Number of the output to disable.
|
20
|
+
# @macro returnraise
|
21
|
+
def disableoutput(num)
|
22
|
+
send_command :disableoutput, num
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|