]> git.madduck.net Git - etc/awesome.git/blobdiff - widgets/mpd.lua

madduck's git repository

Every one of the projects in this repository is available at the canonical URL git://git.madduck.net/madduck/pub/<projectpath> — see each project's metadata for the exact URL.

All patches and comments are welcome. Please squash your changes to logical commits before using git-format-patch and git-send-email to patches@git.madduck.net. If you'd read over the Git project's submission guidelines and adhered to them, I'd be especially grateful.

SSH access, as well as push access can be individually arranged.

If you use my repositories frequently, consider adding the following snippet to ~/.gitconfig and using the third clone URL listed for each project:

[url "git://git.madduck.net/madduck/"]
  insteadOf = madduck:

Merge branch 'master' of github.com:copycat-killer/lain
[etc/awesome.git] / widgets / mpd.lua
index dcb7101da5c47c59ee5e75378a2c218e6f90d12a..1d2c61737895c27c9c2d7550f3f3ad1636e6215a 100644 (file)
                                                   
 --]]
 
-local markup       = require("lain.util.markup")
 local helpers      = require("lain.helpers")
+local async        = require("lain.asyncshell")
 
-local awful        = require("awful")
-local beautiful    = require("beautiful")
+local escape_f     = require("awful.util").escape
 local naughty      = require("naughty")
 local wibox        = require("wibox")
 
-local io           = io
 local os           = { execute  = os.execute,
                        getenv   = os.getenv }
-local string       = { gmatch   = string.gmatch }
+local math         = { floor    = math.floor }
+local mouse        = mouse
+local string       = { format   = string.format,
+                       match    = string.match,
+                       gmatch   = string.gmatch }
 
 local setmetatable = setmetatable
 
 -- MPD infos
 -- lain.widgets.mpd
-local mpd = { id = nil }
-
-function worker(args)
-    local args = args or {}
-    local password = args.password or ""
-    local host = args.host or "127.0.0.1"
-    local port = args.port or "6600"
-    local music_dir = args.music_dir or os.getenv("HOME") .. "/Music"
-    local refresh_timeout = args.refresh_timeout or 1
-    local notify_timeout = args.notify_timeout or 5
-    local color_artist = args.color_artist or beautiful.fg_normal or "#FFFFFF"
-    local color_song = args.color_song or beautiful.fg_focus or "#FFFFFF"
-    local spr = args.spr or ""
-    local musicplr = args.musicplr or "ncmpcpp"
-    local shadow = args.shadow or false
+local mpd = {}
+
+local function worker(args)
+    local args        = args or {}
+    local timeout     = args.timeout or 1
+    local password    = args.password or ""
+    local host        = args.host or "127.0.0.1"
+    local port        = args.port or "6600"
+    local music_dir   = args.music_dir or os.getenv("HOME") .. "/Music"
+    local cover_size  = args.cover_size or 100
+    local default_art = args.default_art or ""
+    local followmouse = args.followmouse or false
+    local echo_cmd    = args.echo_cmd or "echo"
+    local settings    = args.settings or function() end
 
     local mpdcover = helpers.scripts_dir .. "mpdcover"
-    local mpdh = "telnet://"..host..":"..port
-    local echo = "echo 'password "..password.."\nstatus\ncurrentsong\nclose'"
-
-    local mympd = wibox.widget.textbox()
+    local mpdh = "telnet://" .. host .. ":" .. port
+    local echo = echo_cmd .. " 'password " .. password .. "\nstatus\ncurrentsong\nclose'"
+
+    mpd.widget = wibox.widget.textbox('')
+
+    mpd_notification_preset = {
+        title   = "Now playing",
+        timeout = 5
+    }
+
+    helpers.set_map("current mpd track", "")
+    helpers.set_map("current mpd file", "")
+
+    function mpd.update()
+        async.request(echo .. " | curl --connect-timeout 1 -fsm 3 " .. mpdh, function (f)
+            mpd_now = {
+                state   = "N/A",
+                file    = "N/A",
+                artist  = "N/A",
+                title   = "N/A",
+                album   = "N/A",
+                date    = "N/A",
+                time    = "N/A",
+                elapsed = "N/A"
+            }
+
+            for line in string.gmatch(f, "[^\n]+") do
+                for k, v in string.gmatch(line, "([%w]+):[%s](.*)$") do
+                    if     k == "state"   then mpd_now.state   = v
+                    elseif k == "file"    then mpd_now.file    = v
+                    elseif k == "Name"    then mpd_now.name    = escape_f(v)
+                    elseif k == "Artist"  then mpd_now.artist  = escape_f(v)
+                    elseif k == "Title"   then mpd_now.title   = escape_f(v)
+                    elseif k == "Album"   then mpd_now.album   = escape_f(v)
+                    elseif k == "Date"    then mpd_now.date    = escape_f(v)
+                    elseif k == "Time"    then mpd_now.time    = v
+                    elseif k == "elapsed" then mpd_now.elapsed = string.match(v, "%d+")
+                    end
+                end
+            end
 
-    helpers.set_map("current mpd track", nil)
+            mpd_notification_preset.text = string.format("%s (%s) - %s\n%s", mpd_now.artist,
+                                           mpd_now.album, mpd_now.date, mpd_now.title)
 
-    local mympdupdate = function()
-        local function set_nompd()
-            if shadow
+            if mpd_now.file ~= helpers.get_map("current mpd file")
             then
-                mympd:set_text('')
-            else
-                mympd:set_markup(markup(color_artist, " mpd "), markup(color_song , "off "))
-            end
-        end
-
-        local mpd_state  = {
-            ["{state}"]  = "N/A",
-            ["{file}"]   = "N/A",
-            ["{Artist}"] = "N/A",
-            ["{Title}"]  = "N/A",
-            ["{Album}"]  = "N/A",
-            ["{Date}"]   = "N/A"
-        }
-
-        -- Get data from MPD server
-        local f = io.popen(echo .. " | curl --connect-timeout 1 -fsm 3 " .. mpdh)
-
-        for line in f:lines() do
-            for k, v in string.gmatch(line, "([%w]+):[%s](.*)$") do
-                if     k == "state"  then mpd_state["{"..k.."}"] = v
-                elseif k == "file"   then mpd_state["{"..k.."}"] = v
-                elseif k == "Artist" then mpd_state["{"..k.."}"] = awful.util.escape(v)
-                elseif k == "Title"  then mpd_state["{"..k.."}"] = awful.util.escape(v)
-                elseif k == "Album"  then mpd_state["{"..k.."}"] = awful.util.escape(v)
-                elseif k == "Date"   then mpd_state["{"..k.."}"] = awful.util.escape(v)
-                end
+                widget = mpd.widget
+                settings()
+                helpers.set_map("current mpd file", mpd_now.file)
             end
-        end
 
-        f:close()
-
-        if mpd_state["{state}"] == "play"
-        then
-            if mpd_state["{Title}"] ~= helpers.get_map("current mpd track")
+            if mpd_now.state == "play"
+            then
+                if mpd_now.title ~= helpers.get_map("current mpd track")
+                then
+                    helpers.set_map("current mpd track", mpd_now.title)
+
+                    if string.match(mpd_now.file, "http.*://") == nil
+                    then -- local file
+                        os.execute(string.format("%s %q %q %d %q", mpdcover, music_dir,
+                                   mpd_now.file, cover_size, default_art))
+                        current_icon = "/tmp/mpdcover.png"
+                    else -- http stream
+                        current_icon = default_art
+                    end
+
+                    if followmouse then
+                        mpd_notification_preset.screen = mouse.screen
+                    end
+
+                    mpd.id = naughty.notify({
+                        preset = mpd_notification_preset,
+                        icon = current_icon,
+                        replaces_id = mpd.id,
+                    }).id
+                end
+            elseif mpd_now.state ~= "pause"
             then
-                helpers.set_map("current mpd track", mpd_state["{Title}"])
-                os.execute(mpdcover .. " '" .. music_dir .. "' '"
-                           .. mpd_state["{file}"] .. "'")
-                mpd.id = naughty.notify({
-                    title = "Now playing",
-                    text = mpd_state["{Artist}"] .. " ("   ..
-                           mpd_state["{Album}"]  .. ") - " ..
-                           mpd_state["{Date}"]   .. "\n"   ..
-                           mpd_state["{Title}"],
-                    icon = "/tmp/mpdcover.png",
-                    fg = beautiful.fg_focus or "#FFFFFF",
-                    bg = beautiful.bg_normal or "#000000" ,
-                    timeout = notify_timeout,
-                    replaces_id = mpd.id
-                }).id
+                helpers.set_map("current mpd track", nil)
             end
-            mympd:set_markup(markup(color_artist, " " .. mpd_state["{Artist}"])
-                             .. spr ..
-                             markup(color_song, " " .. mpd_state["{Title}"] .. " "))
-        elseif mpd_state["{state}"] == "pause"
-        then
-            mympd:set_markup(markup(color_artist, " mpd")
-                             .. spr ..
-                             markup(color_song, " paused "))
-        else
-            helpers.set_map("current mpd track", nil)
-                       set_nompd()
-             end
+        end)
     end
 
-    local mympdtimer = timer({ timeout = refresh_timeout })
-    mympdtimer:connect_signal("timeout", mympdupdate)
-    mympdtimer:start()
-    mympdtimer:emit_signal("timeout")
-
-    mympd:buttons(awful.util.table.join(
-        awful.button({}, 0,
-            function()
-                helpers.run_in_terminal(musicplr)
-            end)
-    ))
-
-    local mpd_out = { widget = mympd, notify = mympdupdate }
+    helpers.newtimer("mpd", timeout, mpd.update)
 
-    return setmetatable(mpd_out, { __index = mpd_out.widget })
+    return setmetatable(mpd, { __index = mpd.widget })
 end
 
 return setmetatable(mpd, { __call = function(_, ...) return worker(...) end })