local GLib = lgi.GLib
local Gio = lgi.Gio
+local trace_mpc = false
+
local mpc = {}
local function parse_password(host)
_error_handler = error_handler or function() end,
_connected = false,
_try_reconnect = false,
- _idle_commands = { ... }
+ _idle_subsystems = { ... }
}, { __index = mpc })
self:_connect()
return self
end
+function mpc:_write(command)
+ if trace_mpc then
+ print("write: " .. command)
+ end
+ self._output:write(command .. "\n")
+end
+
function mpc:_error(err)
self._connected = false
self._error_handler(err)
table.remove(self._reply_handlers, 1)
self._pending_reply = {}
handler(success, arg)
+
+ if next(self._reply_handlers) == nil then
+ self:_start_idle()
+ end
else
local _, _, key, value = string.find(line, "([^:]+):%s(.+)")
if key then
- if key == "binary" then
+ local k = string.lower(key)
+ if k == "binary" then
value = tonumber(value)
local data = {}
while value > 0 do
value = value - #b
end
local w = obj:read_bytes(1) -- read newline at end of binary
- self._pending_reply[string.lower(key)] = table.concat(data)
+ self._pending_reply[k] = table.concat(data)
+ elseif k == "changed" then
+ if not self._pending_reply[k] then
+ self._pending_reply[k] = {}
+ end
+
+ self._pending_reply[k][value] = true
else
- self._pending_reply[string.lower(key)] = value
+ self._pending_reply[k] = value
end
end
end
end
do_read()
- -- To synchronize the state on startup, send the idle commands now. As a
- -- side effect, this will enable idle state.
- self:_send_idle_commands(true)
-
- return self
-end
-
-function mpc:_send_idle_commands(skip_stop_idle)
- -- We use a ping to unset this to make sure we never get into a busy
- -- loop sending idle / unidle commands. Next call to
- -- _send_idle_commands() might be ignored!
- if self._idle_commands_pending then
- return
- end
- if not skip_stop_idle then
- self:_stop_idle()
+ -- To synchronize the state on startup, send the idle commands now.
+ for i = 1, #self._idle_subsystems, 2 do
+ self._idle_subsystems[i+1](self)
end
- self._idle_commands_pending = true
- for i = 1, #self._idle_commands, 2 do
- self:_send(self._idle_commands[i], self._idle_commands[i+1])
- end
- self:_send("ping", function()
- self._idle_commands_pending = false
- end)
- self:_start_idle()
+ return self
end
function mpc:_start_idle()
if self._idle then
- error("Still idle?!")
+ error("start_idle but already idle")
end
self:_send("idle", function(success, reply)
+ self._idle = false
if reply.changed then
-- idle mode was disabled by mpd
- self:_send_idle_commands()
+ for i = 1, #self._idle_subsystems, 2 do
+ local subsys = self._idle_subsystems[i]
+ if reply.changed[subsys] then
+ self._idle_subsystems[i+1](self)
+ end
+ end
end
end)
self._idle = true
function mpc:_stop_idle()
if not self._idle then
- error("Not idle?!")
+ error("stop_idle but not idle")
end
- self._output:write("noidle\n")
+ self:_write("noidle")
self._idle = false
end
if self._idle then
error("Still idle in send()?!")
end
- self._output:write(command .. "\n")
+ self:_write(command)
table.insert(self._reply_handlers, callback or function() end)
end
if not self._connected then
return
end
- local args = { ... }
- if not self._idle then
- error("Something is messed up, we should be idle here...")
+ if self._idle then
+ self:_stop_idle()
end
- self:_stop_idle()
+ local args = { ... }
for i = 1, #args, 2 do
self:_send(args[i], args[i+1])
end
- self:_start_idle()
end
function mpc:toggle_play()