An OpenResty/Luasocket MPD client library


Example Usage

    local mpd = require'lib.resty.mpd'
    local client =
    -- loop until we've read 5 events
    local events = 5
    while events > 0 do
      local res, err = client:idle()
      if err then
          if err == 'timeout' then
              -- cancel current idle for next loop
              local noidle_ok, noidle_err = client:noidle()
              if noidle_err then
                  print('Error: ' .. noidle_err)
              print('Error: ' .. err)
          for _,event in pairs(res) do
              print('Event: ' .. event)
              events = events - 1
              -- do something based on the event

Instantiating a client

client =

Returns a new MPD client object. Opts is an (optional) table of parameters for the client. Accepted parameters:

  • timeout_continue - boolean. If true, reading operations will continue attempting to read even during a timeout. If you have a client that loops around calls to idle you may want to consider enabling this.

ok, err = client:connect(url)

Connects to MPD, supports tcp and unix socket connections.

The URL should be in one of two formats:

  • tcp://host:port

  • unix:/path/to/socket

  • host:port

  • host (implied port 6600)

  • tcp://host (implied port 6600)

  • path/to/socket (does not have to be absolute)

ok, err = client:close()


Version 2.1.0

New feature: new takes an optional table, see documentation.

Version 2.0.2

Fixes potential race condition in noidle.

Uses correct socket timeout scale (seconds with luasocket, milliseconds in nginx).

Version 2.0.1

Fixes timed out operations.

Version 2.0.0

Breaking Changes

idle change

In previous versions, calling idle would return a string, with a special string ("interrupted") in the case of the idle being canceled with noidle. In MPD, a call to idle can return multiple events.

idle now returns an array of events, with an empty array used to represent idle being canceled.

commands and notcommands change

Previous versions returned a table with each command being a key set to true.

commands and notcommands now returns an array of commands.

Non-Breaking Changes

Previous versions required the URL to match the formats:

  • tcp://host:port

  • unix:/path/to/socket

The URL can additionally use the formats:

  • host:port

  • host (implied port 6600)

  • tcp://host (implied port 6600)

  • path/to/socket (does not have to be absolute)

I still recommend the tcp:// or unix: prefixes to be explicit

Implemented Protocol Functions

For details on each of these functions, see the MPD proto docs:

ok, err = client:clearerror()

Clears any current error message

res, err = client:currentsong()

Returns a table about the current song. In the case of an error, returns nil and an object describing the error.

events, err = client:idle(...)

Waits until MPD emits a noteworthy change. You can specify a list of events you're interested in, or leave blank for all events. Returns an array of events.

May return zero events, in the case of canceling an idle via client:noidle()

The events:

  • database

  • update

  • stored_playlist

  • playlist

  • player

  • mixer

  • output

  • options

  • sticker

  • subscription

  • message

res, err = client:status()

res, err = client:stats()

boolean, err = client:consume(boolean)

duration, err = client:crossfade(duration)

db, err = client:mixrampdb(db)

duration, err = client:mixrampdelay(duration)

boolean, err = client:random(boolean)

boolean, err = client:_repeat(boolean)

volume, err = client:setvol(volume)

boolean, err = client:single(boolean)

mode, err = client:replay_gain_mode(mode)

status, err = client:replay_gain_status()

ok, err = client:_next()

boolean, err = client:pause(boolean)

ok, err = client:play([pos])

ok, err = client:playid([id])

ok, err = client:previous()

ok, err = client:seek(songpos, time)

ok, err = client:seekid(songid, time)

ok, err = client:seekcur(time)

ok, err = client:stop()

ok, err = client:add(uri)

ok, err = client:addid(uri,position)

ok, err = client:clear()

ok, err = client:_delete(pos, [end])

ok, err = client:deleteid(songid)

ok, err = client:move(start, end | to, [to])

ok, err = client:moveid(from, to)

res, err = client:playlistfind(tag, needle)

res, err = client:playlistid(id)

res, err = client:playlistinfo([pos],[end])

res, err = client:playlistsearch(tag, needle)

res, err = client:plchanges(version, [start], [end])

ok, err = client:prio(priority, [start], [end], ...)

ok, err = client:prioid(priority, id, ... id+)

ok, err = client:rangeid(id, [start], [end])

ok, err = client:shuffle([start], [end])

ok, err = client:swap(song1, song2)

ok, err = client:swapid(song1, song2)

ok, err = client:addtagid(id, tag, value)

ok, err = client:cleartagid(id, [tag])

res, err = client:listplaylist(name)

res, err = client:listplaylistinfo(name)

res, err = client:listplaylists()

ok, err = client:load(name, [start], [end])

ok, err = client:playlistadd(name, uri)

ok, err = client:playlistclear(name)

ok, err = client:playlistdelete(name, pos)

ok, err = client:playlistmove(name, from, to)

ok, err = client:rename(name, newname)

ok, err = client:rm(name)

ok, err = client:save(name)

ok, err = client:password(password)

ok, err = client:ping()

ok, err = client:kill()

res, err = client:count(...)

res, err = client:find(...)

res, err = client:findadd(...)

res, err = client:list(type,...)

res, err = client:listfiles([uri])

res, err = client:lsinfo([uri])

res, err = client:readcomments([uri])

res, err = client:search(...)

res, err = client:searchadd(...)

res, err = client:searchaddpl(playlist, ...)

res, err = client:update([uri])

res, err = client:rescan([uri])

res, err = client:sticker(...)

id, err = client:disableoutput(id)

id, err = client:enableoutput(id)

id, err = client:toggleoutput(id)

res, err = client:outputs()

res, err = client:config()

res, err = client:commands()

res, err = client:notcommands()

res, err = client:tagtypes()

res, err = client:urlhandlers()

res, err = client:decoders()

ok, err = client:mount(path,uri)

ok, err = client:unmount(path)

res, err = client:listmounts()

res, err = client:listneighbors()

ok, err = client:subscribe(name)

ok, err = client:unsubscribe(name)

res, err = client:channels()

res, err = client:readmessages()

ok, err = client:sendmessage(name, message)


MIT license (see LICENSE)


John Regan