awesomewm/lib/mpd.lua
2009-10-24 16:50:19 +00:00

151 lines
3.8 KiB
Lua

-- Small interface to MusicPD
-- use luasocket, with a persistant connection to the MPD server.
--
-- Author: Alexandre "kAworu" Perrin <kaworu at kaworu dot ch>
--
-- based on a netcat version from Steve Jothen <sjothen at gmail dot com>
-- (see http://github.com/otkrove/ion3-config/tree/master/mpd.lua)
require("socket")
-- Grab env
local socket = socket
local string = string
local tonumber = tonumber
local setmetatable = setmetatable
local os = os
-- Music Player Daemon Lua library.
module("mpd")
MPD = {
} MPD_mt = { __index = MPD }
-- create and return a new mpd client.
-- the settings argument is a table with theses keys:
-- hostname: the MPD's host (default localhost)
-- port: MPD's port to connect to (default 6600)
-- desc: server's description (default hostname)
-- password: the server's password (default nil, no password)
-- timeout: time in sec to wait for connect() and receive() (default 1)
-- retry: time in sec to wait before reconnect if error (default 60)
function new(settings)
local client = {}
if settings == nil then settings = {} end
client.hostname = settings.hostname or "localhost"
client.port = settings.port or 6600
client.desc = settings.desc or client.hostname
client.password = settings.password
client.timeout = settings.timeout or 1
client.retry = settings.retry or 60
setmetatable(client, MPD_mt)
return client
end
-- calls the action and returns the server's response.
-- Example: if the server's response to "status" action is:
-- volume: 20
-- repeat: 0
-- random: 0
-- playlist: 599
-- ...
-- then the returned table is:
-- { volume = 20, repeat = 0, random = 0, playlist = 599, ... }
function MPD:send(action)
local command = string.format("%s\n", action)
local values = {}
-- connect to MPD server if not already done.
if not self.connected then
if not self.last_try or (os.time() - self.last_try) > self.retry then
self.socket = socket.tcp()
self.socket:settimeout(self.timeout, 't')
self.last_try = os.time()
self.connected = self.socket:connect(self.hostname, self.port)
if self.connected and self.password then
self:send(string.format("password %s", self.password))
end
end
end
if not self.connected then
return {}
end
self.socket:send(command)
local line = ""
while not line:match("^OK$") do
line = self.socket:receive("*l")
if not line then -- closed,timeout (mpd killed?)
self.connected = false
return self:send(action)
end
if line:match(string.format("^ACK", action)) then
return { errormsg = line }
end
local _, _, key, value = string.find(line, "([^:]+):%s(.+)")
if key then
values[string.lower(key)] = value
end
end
return values
end
function MPD:next()
self:send("next")
end
function MPD:previous()
self:send("previous")
end
function MPD:stop()
self:send("stop")
end
-- no need to check the new value, mpd will set the volume in [0,100]
function MPD:volume_up(delta)
local stats = self:send("status")
local new_volume = tonumber(stats.volume) + delta
self:send(string.format("setvol %d", new_volume))
end
function MPD:volume_down(delta)
self:volume_up(-delta)
end
function MPD:toggle_random()
local stats = self:send("status")
if tonumber(stats.random) == 0 then
self:send("random 1")
else
self:send("random 0")
end
end
function MPD:toggle_repeat()
local stats = self:send("status")
if tonumber(stats["repeat"]) == 0 then
self:send("repeat 1")
else
self:send("repeat 0")
end
end
function MPD:toggle_play()
if self:send("status").state == "stop" then
self:send("play")
else
self:send("pause")
end
end
-- vim:filetype=lua:tabstop=8:shiftwidth=2:fdm=marker: