X-Git-Url: https://git.rmz.io/dotfiles.git/blobdiff_plain/9f1e7dfd8aca63ee47257cb2b797a48ac4aeaeff..03e18ae17a72f3db72ee65eb290d35fb13d66237:/awesome/widgets/mpc.lua?ds=inline diff --git a/awesome/widgets/mpc.lua b/awesome/widgets/mpc.lua index a3c5b87..ae4f658 100644 --- a/awesome/widgets/mpc.lua +++ b/awesome/widgets/mpc.lua @@ -4,6 +4,8 @@ local lgi = require "lgi" local GLib = lgi.GLib local Gio = lgi.Gio +local trace_mpc = false + local mpc = {} local function parse_password(host) @@ -28,22 +30,25 @@ function mpc.new(host, port, password, error_handler, ...) _error_handler = error_handler or function() end, _connected = false, _try_reconnect = false, - _idle_commands = { ... } + _idle_subsystems = { ... } }, { __index = mpc }) - self:_connect() + 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) - self._try_reconnect = not self._try_reconnect - if self._try_reconnect then - self:_connect() - end end -function mpc:_connect() +function mpc:connect() if self._connected then return end -- Reset all of our state self._reply_handlers = {} @@ -94,80 +99,78 @@ function mpc:_connect() if type(err) ~= "number" then self._output, self._input = nil, nil self:_error(err) - else - line = tostring(line) - if line == "OK" or line:match("^ACK ") then - local success = line == "OK" - local arg - if success then - arg = self._pending_reply - else - arg = { line } - end - local handler = self._reply_handlers[1] - table.remove(self._reply_handlers, 1) - self._pending_reply = {} - handler(success, arg) + return + end + + line = tostring(line) + if line == "OK" or line:match("^ACK ") then + local success = line == "OK" + local arg + if success then + arg = self._pending_reply else - local _, _, key, value = string.find(line, "([^:]+):%s(.+)") - if key then - if key == "binary" then - value = tonumber(value) - local data = {} - while value > 0 do - local b = assert(obj:read_bytes(value)) - table.insert(data, b.data) - 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) - else - self._pending_reply[string.lower(key)] = value + arg = { line } + end + local handler = self._reply_handlers[1] + 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 + local k = string.lower(key) + if k == "binary" then + value = tonumber(value) + local data = {} + while value > 0 do + local b = assert(obj:read_bytes(value)) + table.insert(data, b.data) + value = value - #b + end + local w = obj:read_bytes(1) -- read newline at end of binary + 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[k] = value end end - do_read() end + do_read() 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 @@ -175,9 +178,9 @@ end 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 @@ -185,24 +188,22 @@ function mpc:_send(command, callback) 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 function mpc:send(...) - self:_connect() + self:connect() 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()