diff options
Diffstat (limited to 'mpris-widget')
| -rw-r--r-- | mpris-widget/README.md | 26 | ||||
| -rw-r--r-- | mpris-widget/init.lua | 267 | 
2 files changed, 293 insertions, 0 deletions
| diff --git a/mpris-widget/README.md b/mpris-widget/README.md new file mode 100644 index 0000000..1978914 --- /dev/null +++ b/mpris-widget/README.md @@ -0,0 +1,26 @@ +# MPRIS Widget (In progress) + +Music Player Info widget cy @mgabs + +# Prerequisite + +Install `playerctl` (mpris implementation), should be available in repo, e.g for Ubuntu: + +```bash +sudo apt-get install playerctl +``` + +## Installation + +To use this widget clone repo under **~/.config/awesome/** and then add it in **rc.lua**: + +```lua +local mpris_widget = require("awesome-wm-widgets.mpris-widget") +... +s.mytasklist, -- Middle widget +	{ -- Right widgets +    layout = wibox.layout.fixed.horizontal, +		... +    mpris_widget, +		... +``` diff --git a/mpris-widget/init.lua b/mpris-widget/init.lua new file mode 100644 index 0000000..1b6dcfc --- /dev/null +++ b/mpris-widget/init.lua @@ -0,0 +1,267 @@ +------------------------------------------------- +-- mpris based Arc Widget for Awesome Window Manager +-- Modelled after Pavel Makhov's work +-- @author Mohammed Gaber +-- requires - playerctl +-- @copyright 2020 +------------------------------------------------- +local awful = require("awful") +local beautiful = require("beautiful") +local spawn = require("awful.spawn") +local watch = require("awful.widget.watch") +local wibox = require("wibox") +local naughty = require("naughty") +local gears = require("gears") + +local GET_MPD_CMD = "playerctl -p %s -f '{{status}};{{xesam:artist}};{{xesam:title}};{{mpris:artUrl}}' metadata" + +local TOGGLE_MPD_CMD = "playerctl play-pause" +local PAUSE_MPD_CMD = "playerctl pause" +local STOP_MPD_CMD = "playerctl stop" +local NEXT_MPD_CMD = "playerctl next" +local PREV_MPD_CMD = "playerctl previous" +local LIST_PLAYERS_CMD = "playerctl -l" + +local PATH_TO_ICONS = "/usr/share/icons/Arc" +local PAUSE_ICON_NAME = PATH_TO_ICONS .. "/actions/24/player_pause.png" +local PLAY_ICON_NAME = PATH_TO_ICONS .. "/actions/24/player_play.png" +local STOP_ICON_NAME = PATH_TO_ICONS .. "/actions/24/player_stop.png" +local LIBRARY_ICON_NAME = PATH_TO_ICONS .. "/actions/24/music-library.png" + +local default_player = '' + +local mpris_widget = wibox.widget{ +    { +        id = 'artist', +        widget = wibox.widget.textbox +    }, +    { +        max_value = 1, +        value = 0, +        thickness = 2, +        start_angle = 4.71238898, -- 2pi*3/4 +        forced_height = 24, +        forced_width = 24, +        rounded_edge = true, +        bg = "#ffffff11", +        paddings = 0, +        widget = wibox.container.arcchart +    }, +    { +        id = 'title', +        widget = wibox.widget.textbox +    }, +    layout = wibox.layout.fixed.horizontal, +    set_text = function(self, artis, title) +        self:get_children_by_id('artist')[1]:set_text(artis) +        self:get_children_by_id('title')[1]:set_text(title) +    end +} + +local rows  = { layout = wibox.layout.fixed.vertical } + +local popup = awful.popup{ +    bg = beautiful.bg_normal, +    ontop = true, +    visible = false, +    shape = gears.shape.rounded_rect, +    border_width = 1, +    border_color = beautiful.bg_focus, +    maximum_width = 400, +    offset = { y = 5 }, +    widget = {} +} + +local function rebuild_popup() +    awful.spawn.easy_async(LIST_PLAYERS_CMD, function(stdout, _, _, _) +        for player_name in stdout:gmatch("[^\r\n]+") do +            if player_name ~='' or player_name ~=nil then +                for i = 0, #rows do rows[i]=nil end + +                local checkbox = wibox.widget{ +                    { +                        checked       = player_name == default_player, +                        color         = beautiful.bg_normal, +                        paddings      = 2, +                        shape         = gears.shape.circle, +                        forced_width = 20, +                        forced_height = 20, +                        check_color = beautiful.fg_urgent, +                        widget        = wibox.widget.checkbox +                    }, +                    valign = 'center', +                    layout = wibox.container.place, +                } + +                checkbox:connect_signal("button::press", function(c) +                    default_player = player_name +                    rebuild_popup() +                end) + +                table.insert(rows, wibox.widget { +                    { +                        { +                            checkbox, +                            { +                                { +                                    text = player_name, +                                    align = 'left', +                                    widget = wibox.widget.textbox +                                }, +                                left = 10, +                                layout = wibox.container.margin +                            }, +                            spacing = 8, +                            layout = wibox.layout.align.horizontal +                        }, +                        margins = 4, +                        layout = wibox.container.margin +                    }, +                    bg = beautiful.bg_normal, +                    widget = wibox.container.background +                }) +            end +        end +    end) + +    popup:setup(rows) +end + +local function worker() + +    -- retriving song info +    local current_song, artist, mpdstatus, art, artUrl + +    local icon = wibox.widget { +        id = "icon", +        widget = wibox.widget.imagebox, +        image = PLAY_ICON_NAME +    } +    local mirrored_icon = wibox.container.mirror(icon, {horizontal = true}) + +    local mpdarc = wibox.widget { +        mirrored_icon, +        -- max_value = 1, +        -- value = 0, +        thickness = 2, +        start_angle = 4.71238898, -- 2pi*3/4 +        forced_height = 24, +        forced_width = 24, +        rounded_edge = true, +        bg = "#ffffff11", +        paddings = 0, +        widget = wibox.container.arcchart +    } + +    local mpdarc_icon_widget = wibox.container.mirror(mpdarc, {horizontal = true}) +    local mpdarc_current_song_widget = wibox.widget { +        id = 'current_song', +        widget = wibox.widget.textbox, +        font = 'Play 10' +    } + +    local update_graphic = function(widget, stdout, _, _, _) +        -- mpdstatus, artist, current_song = stdout:match("(%w+)%;+(.-)%;(.*)") +        local words = {} +        for w in stdout:gmatch("([^;]*)") do table.insert(words, w) end + +        mpdstatus = words[1] +        artist = words[2] +        current_song = words[3] +        art = words[4] +        if current_song ~= nil then +            if string.len(current_song) > 18 then +                current_song = string.sub(current_song, 0, 9) .. ".." +            end +        end + +        if art ~= nil then artUrl = string.sub(art, 8, -1) end + +        if mpdstatus == "Playing" then +            mpdarc_icon_widget.visible = true +            icon.image = PLAY_ICON_NAME +            widget.colors = {beautiful.widget_main_color} +            mpdarc_current_song_widget.markup = current_song +            widget:set_text(artist, current_song) +        elseif mpdstatus == "Paused" then +            mpdarc_icon_widget.visible = true +            icon.image = PAUSE_ICON_NAME +            widget.colors = {beautiful.widget_main_color} +            mpdarc_current_song_widget.markup = current_song +            widget.set_text(artist, current_song) +        elseif mpdstatus == "Stopped" then +            mpdarc_icon_widget.visible = true +            icon.image = STOP_ICON_NAME +            mpdarc_current_song_widget.markup = "" +        else -- no player is running +            icon.image = LIBRARY_ICON_NAME +            mpdarc_icon_widget.visible = false +            mpdarc_current_song_widget.markup = "" +            widget.colors = {beautiful.widget_red} +        end +    end + +    mpdarc:connect_signal("button::press", function(_, _, _, button) +        if (button == 1) then +            awful.spawn(TOGGLE_MPD_CMD, false) -- left click +        elseif (button == 2) then +            awful.spawn(STOP_MPD_CMD, false) +        elseif (button == 3) then +            awful.spawn(PAUSE_MPD_CMD, false) +        elseif (button == 4) then +            awful.spawn(NEXT_MPD_CMD, false) -- scroll up +        elseif (button == 5) then +            awful.spawn(PREV_MPD_CMD, false) -- scroll down +        end + +        -- spawn.easy_async(string.format(GET_MPD_CMD, "'" .. default_player .. "'"), function(stdout, stderr, exitreason, exitcode) +        --     update_graphic(mpdarc, stdout, stderr, exitreason, exitcode) +        -- end) +    end) + +    mpris_widget:buttons( +            awful.util.table.join( +                    awful.button({}, 3, function() +                        if popup.visible then +                            popup.visible = not popup.visible +                        else +                            rebuild_popup() +                            popup:move_next_to(mouse.current_widget_geometry) +                        end +                    end), +                    awful.button({}, 4, function() awful.spawn(NEXT_MPD_CMD, false) end), +                    awful.button({}, 5, function() awful.spawn(PREV_MPD_CMD, false) end), +                    awful.button({}, 1, function() awful.spawn(TOGGLE_MPD_CMD, false) end) +            ) +    ) + + + +    local notification +    local function show_MPD_status() +        spawn.easy_async(GET_MPD_CMD, function() +            notification = naughty.notification { +                margin = 10, +                timeout = 5, +                hover_timeout = 0.5, +                width = 240, +                height = 90, +                title = "<b>" .. mpdstatus .. "</b>", +                text = current_song .. " <b>by</b> " .. artist, +                image = artUrl +            } +        end) +    end + +    mpdarc:connect_signal("mouse::enter", function() +        if current_song ~= nil and artist ~= nil then show_MPD_status() end +    end) +    mpdarc:connect_signal("mouse::leave", function() naughty.destroy(notification) end) + +    watch(string.format(GET_MPD_CMD, "'" .. default_player .. "'"), 1, update_graphic, mpris_widget) + +    return mpris_widget + +end + +return setmetatable(mpris_widget, {__call = function(_, ...) return worker(...) end}) | 
