diff --git a/bin/init.lua b/bin/init.lua index 67f2b3a..a69bd63 100755 --- a/bin/init.lua +++ b/bin/init.lua @@ -39,15 +39,5 @@ return { --awful.spawn("flameshot gui -p \"" .. conf.screenshot_dir .. "\"", false) awful.spawn("flameshot gui", false) end - }, - - mpc = { - watch = function(command, timeout, callback, widget) - awful.widget.watch("mpc --host " .. conf.mpd_host .. " " .. command, timeout, callback, widget) - end, - - command = function(command, callback) - awful.spawn.easy_async("mpc --host " .. conf.mpd_host .. " " .. command, callback) - end } } diff --git a/classes/init.lua b/classes/init.lua index 0886da5..6f87be5 100644 --- a/classes/init.lua +++ b/classes/init.lua @@ -2,4 +2,5 @@ return { Backlight = require("classes/backlight"), Volume = require("classes/volume"), Battery = require("classes/battery"), + MPC = require("classes/mpc") } diff --git a/classes/mpc/init.lua b/classes/mpc/init.lua new file mode 100644 index 0000000..b37e8bb --- /dev/null +++ b/classes/mpc/init.lua @@ -0,0 +1,7 @@ +local P = require("classes/mpc/mpc") + +local F = function(args) + return P:new(args) +end + +return F diff --git a/classes/mpc/mpc.lua b/classes/mpc/mpc.lua new file mode 100644 index 0000000..36d787a --- /dev/null +++ b/classes/mpc/mpc.lua @@ -0,0 +1,170 @@ +local widget_types = { + basic = require("classes/mpc/widget"), +} + +local P = { + name = "mpc" +} + +--- +-- Internal methods +--- +function P:_cmd(command) + -- Build complete pamixer arguments, combining sink and options. + -- Must have a leading space. + return "mpc --host " .. self.mpd_host .. " " .. command +end + +function P:_get_status() + -- Update mute status and volume. + -- Values in this table are updated. + awful.spawn.easy_async( + self:_cmd("current --format \"title=%title% artist=%artist%\""), + function(stdout, stderr, exitreason, exitcode) + + if (stdout == "") then + return + end + + self.current_title = string.match(stdout, "title=(.*)artist=") + self.current_artist = string.match(stdout, "artist=(.*)") + self:_update_widget() + end + ) + + awful.spawn.easy_async( + self:_cmd("status"), + function(stdout, stderr, exitreason, exitcode) + + self.is_playing = string.match(stdout, "(%[playing)") or false + self.is_paused = string.match(stdout, "(%[paused)") or false + self.is_stopped = not (self.is_playing or self.is_paused) + + self.volume = string.match(stdout, "volume: ?(%d?%d?%d)%%") + self:_update_widget() + end + ) + + -- This is used inside a timer, so return true to keep it running. + return true +end + + + +function P:_update_widget() + self.widget:update{ + title = self.current_title, + artist = self.current_artist, + play = self.is_playing, + pause = self.is_paused, + stop = self.is_stopped, + volume = self.volume or 0 + } +end + +--- +-- Simple actions +--- +function P:volume_up() + awful.spawn(self:_cmd("volume +5"), false) + self:_get_status() +end + +function P:volume_down() + awful.spawn(self:_cmd("volume -5"), false) + self:_get_status() +end + +function P:toggle() + awful.spawn(self:_cmd("toggle"), false) + self:_get_status() +end + +function P:next() + awful.spawn(self:_cmd("next"), false) + self:_get_status() +end + +function P:prev() + awful.spawn(self:_cmd("prev"), false) + self:_get_status() +end + + +--- +-- Create new volume_interface +--- +function P:new(args) + -- Arguments + local m = { + update_interval = args.update_interal or 1, + widget_type = args.widget_type or "basic", + mpd_host = args.mpd_host or "localhost", + } + setmetatable(m, self) + self.__index = self + + -- Create widget for this volume interface + m.widget = widget_types[m.widget_type]:new() + + m.widget.widget:connect_signal("button::press", + function(_, _, _, button, mods) + if (button == 3) or (button == 1)then + m:toggle() + end + end + ) + + m.widget.right:connect_signal("button::press", + function(_, _, _, button, mods) + if (button == 4) then -- Scroll up + m:prev() + elseif (button == 5) then -- Scroll down + m:next() + end + end + ) + + + m.widget.left:connect_signal("button::press", + function(_, _, _, button, mods) + if (button == 4) then -- Scroll up + m:volume_up() + elseif (button == 5) then -- Scroll down + m:volume_down() + end + end + ) + + -- Polling timer + m.timer_poll = gears.timer { + timeout = m.update_interval, + call_now = true, + autostart = true, + callback = function() + m:_get_status() + end + } + + --[[ + -- Timer waiting for changes + -- DO NOT USE, WILL DOS MPD + m.timer_wait = gears.timer { + timeout = 0.1, + call_now = true, + autostart = true, + callback = function() + awful.spawn.easy_async( + m:_cmd("current --wait"), + function(stdout, stderr, exitreason, exitcode) + m:_get_status() + end + ) + end + } + --]] + + return m +end + +return P diff --git a/classes/mpc/widget.lua b/classes/mpc/widget.lua new file mode 100644 index 0000000..c1bdc82 --- /dev/null +++ b/classes/mpc/widget.lua @@ -0,0 +1,128 @@ +local P = {} + +function P:update(args) + if (args.error ~= nil) then + self.title.markup = "MPD is not" + self.artist.markup = "connected" + self.volume.markup = "??" + else + self.title.markup = args.title or "No track" + self.artist.markup = args.artist or "loaded" + + if (args.play) then + self.icon.image = beautiful.icons.music.blue.playing + elseif (args.pause) then + self.icon.image = beautiful.icons.music.blue.paused + elseif (args.stop) then + self.icon.image = beautiful.icons.music.blue.stopped + end + + if (args.volume) then + self.volume.markup = args.volume .. "%" + else + self.volume.markup = "" + end + end +end + +function P:new() + local widget = {} + setmetatable(widget, self) + self.__index = self + + widget.title = wibox.widget.textbox("MPD is not") + widget.title.valign = "center" + widget.title.align = "left" + widget.title.font = "Hack NF 12" + widget.title.ellipsize = "end" + widget.title.forced_width = beautiful.dpi(conf.mpc_width) + + widget.artist = wibox.widget.textbox("connected") + widget.artist.valign = "center" + widget.artist.align = "left" + widget.artist.font = "Hack NF 12" + widget.artist.ellipsize = "end" + widget.artist.forced_width = beautiful.dpi(conf.mpc_width) + + widget.volume = wibox.widget.textbox("??") + widget.volume.valign = "center" + widget.volume.align = "left" + widget.volume.font = "Hack NF 10" + widget.volume.ellipsize = "end" + widget.volume.forced_width = beautiful.dpi(10) + + + widget.icon = wibox.widget { + resize = true, + image = beautiful.icons.music.blue.playing, + widget = wibox.widget.imagebox + } + + widget.left = wibox.widget { + wibox.widget { + { + widget.icon, + top = beautiful.dpi(2), + bottom = beautiful.dpi(2), + left = 0, right = 0, + layout = wibox.container.margin, + }, + widget.volume, + + forced_num_cols = 1, + forced_num_rows = 2, + homogeneous = true, + expand = true, + layout = wibox.layout.grid + }, + layout = wibox.container.background + } + + widget.right = wibox.widget { + wibox.widget { + widget.title, + widget.artist, + + forced_num_cols = 1, + forced_num_rows = 2, + homogeneous = true, + expand = true, + layout = wibox.layout.grid + }, + layout = wibox.container.background, + } + + widget.widget = wibox.widget { + { + { -- Right spacer + widget = wibox.widget.separator, + color = beautiful.color.transparent, + forced_width = beautiful.dpi(3) + }, + + widget.left, + widget.right, + + { -- Left spacer + widget = wibox.widget.separator, + color = beautiful.color.transparent, + forced_width = beautiful.dpi(3) + }, + layout = wibox.layout.align.horizontal, + }, + layout = wibox.container.background, + } + + + widget.widget:connect_signal("mouse::enter", function(result) + widget.widget.bg = beautiful.color.bar.hover_bg + end) + + widget.widget:connect_signal("mouse::leave", function(result) + widget.widget.bg = beautiful.color.transparent + end) + + return widget +end + +return P diff --git a/desktop/init.lua b/desktop/init.lua index 75e6a91..2dc0ca3 100755 --- a/desktop/init.lua +++ b/desktop/init.lua @@ -46,11 +46,6 @@ local desktop = { } } -if conf.mpc_enabled then - desktop.widgets.mpc = require("desktop.widgets.mpc") -end - - -- If timed wallpaper is enabled, load timed manager if (type(beautiful.wallpaper) == "table") then @@ -162,7 +157,7 @@ awful.screen.connect_for_each_screen( if (conf.mpc_enabled) then rightside = gears.table.join(rightside, { - desktop.widgets.mpc, + mpc.widget.widget, desktop.widgets.space(5), desktop.widgets.separator(2, 5, 3), desktop.widgets.space(15), diff --git a/desktop/widgets/mpc.lua b/desktop/widgets/mpc.lua deleted file mode 100644 index 4704ee1..0000000 --- a/desktop/widgets/mpc.lua +++ /dev/null @@ -1,193 +0,0 @@ -local mpc_widget = {} - -mpc_widget.title = wibox.widget.textbox("MPD is not") -mpc_widget.title.valign = "center" -mpc_widget.title.align = "left" -mpc_widget.title.font = "Hack NF 12" -mpc_widget.title.ellipsize = "end" -mpc_widget.title.forced_width = beautiful.dpi(conf.mpc_width) - -mpc_widget.artist = wibox.widget.textbox("connected") -mpc_widget.artist.valign = "center" -mpc_widget.artist.align = "left" -mpc_widget.artist.font = "Hack NF 12" -mpc_widget.artist.ellipsize = "end" -mpc_widget.artist.forced_width = beautiful.dpi(conf.mpc_width) - -mpc_widget.volume = wibox.widget.textbox("??") -mpc_widget.volume.valign = "center" -mpc_widget.volume.align = "left" -mpc_widget.volume.font = "Hack NF 10" -mpc_widget.volume.ellipsize = "end" -mpc_widget.volume.forced_width = beautiful.dpi(10) - - -mpc_widget.icon_play = wibox.widget { - resize = true, - image = beautiful.icons.music.blue.playing, - widget = wibox.widget.imagebox -} - - - -mpc_widget.left = wibox.widget { - wibox.widget { - { - mpc_widget.icon_play, - top = beautiful.dpi(2), - bottom = beautiful.dpi(2), - left = 0, right = 0, - layout = wibox.container.margin, - }, - mpc_widget.volume, - - forced_num_cols = 1, - forced_num_rows = 2, - homogeneous = true, - expand = true, - layout = wibox.layout.grid - }, - layout = wibox.container.background -} - -mpc_widget.right = wibox.widget { - wibox.widget { - mpc_widget.title, - mpc_widget.artist, - - forced_num_cols = 1, - forced_num_rows = 2, - homogeneous = true, - expand = true, - layout = wibox.layout.grid - }, - layout = wibox.container.background, -} - - -mpc_widget.widget = wibox.widget { - { - { -- Right spacer - widget = wibox.widget.separator, - color = beautiful.color.transparent, - forced_width = beautiful.dpi(3) - }, - - mpc_widget.left, - mpc_widget.right, - - { -- Left spacer - widget = wibox.widget.separator, - color = beautiful.color.transparent, - forced_width = beautiful.dpi(3) - }, - layout = wibox.layout.align.horizontal, - }, - layout = wibox.container.background, -} - - -mpc_widget.widget:connect_signal("mouse::enter", function(result) - mpc_widget.widget.bg = beautiful.color.bar.hover_bg -end) - -mpc_widget.widget:connect_signal("mouse::leave", function(result) - mpc_widget.widget.bg = beautiful.color.transparent -end) - - -mpc_widget.widget:connect_signal("button::press", - function(_, _, _, button, mods) - if (button == 3) or (button == 1)then - bin.mpc.command("toggle") - end - mpc_widget.readupdate() - end -) - - -mpc_widget.right:connect_signal("button::press", - function(_, _, _, button, mods) - if (button == 4) then -- Scroll up - bin.mpc.command("prev") - elseif (button == 5) then -- Scroll down - bin.mpc.command("next") - end - - mpc_widget.readupdate() - end -) - - -mpc_widget.left:connect_signal("button::press", - function(_, _, _, button, mods) - if (button == 4) then -- Scroll up - bin.mpc.command("volume +5") - elseif (button == 5) then -- Scroll down - bin.mpc.command("volume -5") - end - mpc_widget.readupdate() - end -) - - -mpc_widget.update = function(stdout) - if (stdout == "") then - return - end - - mpc_widget.title.markup = string.match(stdout, "title=(.*)artist=") - mpc_widget.artist.markup = string.match(stdout, "artist=(.*)") - - -end - - -mpc_widget.update_status = function(stdout) - play = string.match(stdout, "(%[playing)") or false - pause = string.match(stdout, "(%[paused)") or false - stop = not (play or pause) - - if (play) then - mpc_widget.icon_play.image = beautiful.icons.music.blue.playing - elseif (pause) then - mpc_widget.icon_play.image = beautiful.icons.music.blue.paused - elseif (stop) then - mpc_widget.icon_play.image = beautiful.icons.music.blue.stopped - end - - volume = string.match(stdout, "volume: (%d?%d?%d)%%") - if (volume) then - mpc_widget.volume.markup = volume .. "%" - else - mpc_widget.volume.markup = "" - end -end - -mpc_widget.readupdate = function() - bin.mpc.command("current --format \"title=%title% artist=%artist%\"", - function(stdout, stderr, exitreason, exitcode) - mpc_widget.update(stdout) - end - ) - - bin.mpc.command("status", - function(stdout, stderr, exitreason, exitcode) - mpc_widget.update_status(stdout) - end - ) -end - - --- The time here is super short because the --wait option is used in mpc. --- It will not return a response until changes are seen. -bin.mpc.watch("current --wait", 0.01, function(_, stdout) mpc_widget.readupdate() end, mpc_widget.widget) -bin.mpc.watch("current", 1, function(_, stdout) mpc_widget.readupdate() end, mpc_widget.widget) - - --- Make sure you do an initial read, though, otherwise the widget will --- not update until a change occurs. -mpc_widget.readupdate() - - -return mpc_widget.widget diff --git a/rc.lua b/rc.lua index cc78f5d..94db145 100755 --- a/rc.lua +++ b/rc.lua @@ -41,6 +41,7 @@ classes = require("classes") vol = classes.Volume{pa_sink = conf.pamixer_sink} bck = classes.Backlight{} batt = classes.Battery{} +mpc = classes.MPC{mpd_host = conf.mpd_host} desktop = require("desktop")