class MPD::Client

The `MPD::Client` is used for interactions with a MPD server.

Example:

“`ruby require 'mpd_client' require 'logger'

client = MPD::Client.new client.log = Logger.new($stderr) client.connect('/var/run/mpd/socket') “`

Constants

VERSION

Attributes

log[RW]

Default logger for all `MPD::Client“ instances

“`ruby MPD::Client.log = Logger.new($stderr) “`

log[W]

Sets the logger used by this instance of MPD::Client

mpd_version[R]

Public Class Methods

add_command(name, retval) click to toggle source
# File lib/mpd_client.rb, line 161
def add_command(name, retval)
  escaped_name = name.tr(' ', '_')
  define_method escaped_name.to_sym do |*args|
    ensure_connected

    execute(name, *args, retval)
  end
end
connect(host = 'localhost', port = 6600) click to toggle source
# File lib/mpd_client.rb, line 154
def connect(host = 'localhost', port = 6600)
  client = MPD::Client.new
  client.connect(host, port)

  client
end
new() click to toggle source
# File lib/mpd_client.rb, line 176
def initialize
  @mutex = Mutex.new
  reset
end
remove_command(name) click to toggle source
# File lib/mpd_client.rb, line 170
def remove_command(name)
  raise "Can't remove not existent '#{name}' command" unless method_defined? name.to_sym
  remove_method name.to_sym
end

Public Instance Methods

command_list_end() click to toggle source
# File lib/mpd_client.rb, line 226
def command_list_end
  raise 'Not in command list' if @command_list.nil?
  write_command('command_list_end')

  fetch_command_list
end
command_list_ok_begin() click to toggle source

www.musicpd.org/doc/protocol/ch01s04.html

# File lib/mpd_client.rb, line 220
def command_list_ok_begin
  raise 'Already in command list' unless @command_list.nil?
  write_command('command_list_ok_begin')
  @command_list = []
end
connect(host = 'localhost', port = 6600) click to toggle source
# File lib/mpd_client.rb, line 181
def connect(host = 'localhost', port = 6600)
  @host = host
  @port = port

  reconnect
end
connected?() click to toggle source
# File lib/mpd_client.rb, line 215
def connected?
  @connected
end
disconnect() click to toggle source
# File lib/mpd_client.rb, line 201
def disconnect
  log&.info('MPD disconnect')
  @socket.close
  reset
end
log() click to toggle source

The current logger. If no logger has been set MPD::Client.log is used

# File lib/mpd_client.rb, line 234
def log
  @log || MPD::Client.log
end
reconnect() click to toggle source
# File lib/mpd_client.rb, line 188
def reconnect
  log&.info("MPD (re)connect #{@host}, #{@port}")

  @socket = if @host.start_with?('/')
              UNIXSocket.new(@host)
            else
              TCPSocket.new(@host, @port)
            end

  hello
  @connected = true
end
reset() click to toggle source
# File lib/mpd_client.rb, line 207
def reset
  @mpd_version = nil
  @command_list = nil
  @socket = nil
  @log = nil
  @connected = false
end

Private Instance Methods

ensure_connected() click to toggle source
# File lib/mpd_client.rb, line 243
def ensure_connected
  raise 'Please connect to MPD server' unless connected?
end
escape(text) click to toggle source
# File lib/mpd_client.rb, line 458
def escape(text)
  text.to_s.gsub('\\', '\\\\').gsub('"', '\\"')
end
execute(command, *args, retval) click to toggle source
# File lib/mpd_client.rb, line 247
def execute(command, *args, retval)
  @mutex.synchronize do
    write_command(command, *args)

    if !@command_list.nil?
      @command_list << retval
    else
      eval retval
    end
  end
end
fetch_changes() click to toggle source
# File lib/mpd_client.rb, line 377
def fetch_changes
  fetch_objects(['cpos'])
end
fetch_command_list() click to toggle source
# File lib/mpd_client.rb, line 437
def fetch_command_list
  result = []
  begin
    @command_list.each do |retval|
      result << (eval retval)
    end
  ensure
    @command_list = nil
  end

  result
end
fetch_database() click to toggle source
# File lib/mpd_client.rb, line 405
def fetch_database
  fetch_objects(%w[file directory playlist])
end
fetch_item() click to toggle source
# File lib/mpd_client.rb, line 324
def fetch_item
  pairs = read_pairs
  return nil if pairs.size != 1

  pairs[0][1]
end
fetch_list() click to toggle source
# File lib/mpd_client.rb, line 336
def fetch_list
  result = []
  seen = nil

  read_pairs.each do |key, value|
    if key != seen
      raise "Expected key '#{seen}', got '#{key}'" unless seen.nil?
      seen = key
    end

    result << value
  end

  result
end
fetch_messages() click to toggle source
# File lib/mpd_client.rb, line 393
def fetch_messages
  fetch_objects('channel')
end
fetch_mounts() click to toggle source
# File lib/mpd_client.rb, line 385
def fetch_mounts
  fetch_objects(['mount'])
end
fetch_neighbors() click to toggle source
# File lib/mpd_client.rb, line 389
def fetch_neighbors
  fetch_objects(['neighbor'])
end
fetch_nothing() click to toggle source
# File lib/mpd_client.rb, line 331
def fetch_nothing
  line = read_line
  raise "Got unexpected value: #{line}" unless line.nil?
end
fetch_object() click to toggle source
# File lib/mpd_client.rb, line 371
def fetch_object
  objs = fetch_objects

  objs ? objs[0] : {}
end
fetch_objects(delimeters = []) click to toggle source
# File lib/mpd_client.rb, line 352
def fetch_objects(delimeters = [])
  result = []
  obj = {}
  read_pairs.each do |key, value|
    key = key.downcase
    if delimeters.include?(key)
      result << obj unless obj.empty?
      obj = {}
    elsif obj.include?(key)
      obj[key] << value
    end
    obj[key] = value
  end

  result << obj unless obj.empty?

  result
end
fetch_outputs() click to toggle source
# File lib/mpd_client.rb, line 397
def fetch_outputs
  fetch_objects(['outputid'])
end
fetch_playlist() click to toggle source
# File lib/mpd_client.rb, line 413
def fetch_playlist
  result = []
  read_pairs(':').each do |_key, value|
    result << value
  end

  result
end
fetch_playlists() click to toggle source
# File lib/mpd_client.rb, line 409
def fetch_playlists
  fetch_objects(['playlist'])
end
fetch_plugins() click to toggle source
# File lib/mpd_client.rb, line 401
def fetch_plugins
  fetch_objects(['plugin'])
end
fetch_songs() click to toggle source
# File lib/mpd_client.rb, line 381
def fetch_songs
  fetch_objects(['file'])
end
fetch_sticker() click to toggle source
# File lib/mpd_client.rb, line 433
def fetch_sticker
  fetch_stickers[0]
end
fetch_stickers() click to toggle source
# File lib/mpd_client.rb, line 422
def fetch_stickers
  result = []
  read_pairs.each do |_key, sticker|
    value = sticker.split('=', 2)
    raise "Could now parse sticker: #{sticker}" if value.size < 2
    result << Hash[*value]
  end

  result
end
hello() click to toggle source
# File lib/mpd_client.rb, line 450
def hello
  line = @socket.gets
  raise 'Connection lost while reading MPD hello' unless line.end_with?("\n")
  line.chomp!
  raise "Got invalid MPD hello: #{line}" unless line.start_with?(HELLO_PREFIX)
  @mpd_version = line[/#{HELLO_PREFIX}(.*)/, 1]
end
read_line() click to toggle source
# File lib/mpd_client.rb, line 285
def read_line
  line = @socket.gets.force_encoding('utf-8')
  raise 'Connection lost while reading line' unless line.end_with?("\n")
  line.chomp!
  if line.start_with?(ERROR_PREFIX)
    error = line[/#{ERROR_PREFIX}(.*)/, 1].strip
    raise error
  end

  if !@command_list.nil?
    return if line == NEXT
    raise "Got unexpected '#{SUCCESS}'" if line == SUCCESS
  elsif line == SUCCESS
    return
  end

  line
end
read_pair(separator) click to toggle source
# File lib/mpd_client.rb, line 304
def read_pair(separator)
  line = read_line
  return if line.nil?
  pair = line.split(separator, 2)
  raise "Could now parse pair: '#{line}'" if pair.size < 2

  pair # Array
end
read_pairs(separator = ': ') click to toggle source
# File lib/mpd_client.rb, line 313
def read_pairs(separator = ': ')
  result = []
  pair = read_pair(separator)
  while pair
    result << pair
    pair = read_pair(separator)
  end

  result
end
write_command(command, *args) click to toggle source
# File lib/mpd_client.rb, line 269
def write_command(command, *args)
  parts = [command]
  args.each do |arg|
    line = if arg.is_a?(Array)
             arg.size == 1 ? "\"#{arg[0].to_i}:\"" : "\"#{arg[0].to_i}:#{arg[1].to_i}\""
           else
             "\"#{escape(arg)}\""
           end

    parts << line
  end
  # log.debug("Calling MPD: #{command}#{args}") if log
  log&.debug("Calling MPD: #{parts.join(' ')}")
  write_line(parts.join(' '))
end
write_line(line) click to toggle source
# File lib/mpd_client.rb, line 259
def write_line(line)
  begin
    @socket.puts line
  rescue Errno::EPIPE
    reconnect
    @socket.puts line
  end
  @socket.flush
end