]> git.madduck.net Git - etc/awesome.git/blob - widget/pulsebar.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:

78b7d49e385ea5f150b581846f82e0c1b265326a
[etc/awesome.git] / widget / pulsebar.lua
1 --[[
2
3      Licensed under GNU General Public License v2
4       * (c) 2013, Luca CPZ
5       * (c) 2013, Rman
6
7 --]]
8
9 local helpers        = require("lain.helpers")
10 local awful          = require("awful")
11 local naughty        = require("naughty")
12 local wibox          = require("wibox")
13 local math           = { modf   = math.modf }
14 local string         = { format = string.format,
15                          match  = string.match,
16                          gmatch = string.gmatch,
17                          rep    = string.rep }
18 local type, tonumber = type, tonumber
19
20 -- PulseAudio volume bar
21 -- lain.widget.pulsebar
22
23 local function factory(args)
24     local pulsebar = {
25         colors = {
26             background = "#000000",
27             mute       = "#EB8F8F",
28             unmute     = "#A4CE8A"
29         },
30
31         _current_level = 0,
32         _mute          = "no",
33         device         = "N/A"
34     }
35
36     local args       = args or {}
37     local timeout    = args.timeout or 5
38     local settings   = args.settings or function() end
39     local width      = args.width or 63
40     local height     = args.heigth or 1
41     local ticks      = args.ticks or false
42     local ticks_size = args.ticks_size or 7
43
44     pulsebar.colors              = args.colors or pulsebar.colors
45     pulsebar.followtag           = args.followtag or false
46     pulsebar.notification_preset = args.notification_preset
47     pulsebar.devicetype          = args.devicetype or "sink"
48     pulsebar.cmd                 = args.cmd or "pacmd list-" .. pulsebar.devicetype .. "s | sed -n -e '/*/,$!d' -e '/index/p' -e '/base volume/d' -e '/volume:/p' -e '/muted:/p' -e '/device\\.string/p'"
49
50     if not pulsebar.notification_preset then
51         pulsebar.notification_preset = {
52             font = "Monospace 10"
53         }
54     end
55
56     pulsebar.bar = wibox.widget {
57         forced_height    = height,
58         forced_width     = width,
59         color            = pulsebar.colors.unmute,
60         background_color = pulsebar.colors.background,
61         margins          = 1,
62         paddings         = 1,
63         ticks            = ticks,
64         ticks_size       = ticks_size,
65         widget           = wibox.widget.progressbar,
66     }
67
68     pulsebar.tooltip = awful.tooltip({ objects = { pulsebar.bar } })
69
70     function pulsebar.update(callback)
71         helpers.async({ awful.util.shell, "-c", type(pulsebar.cmd) == "string" and pulsebar.cmd or pulsebar.cmd() },
72         function(s)
73             volume_now = {
74                 index  = string.match(s, "index: (%S+)") or "N/A",
75                 device = string.match(s, "device.string = \"(%S+)\"") or "N/A",
76                 muted  = string.match(s, "muted: (%S+)") or "N/A"
77             }
78
79             pulsebar.device = volume_now.index
80
81             local ch = 1
82             volume_now.channel = {}
83             for v in string.gmatch(s, ":.-(%d+)%%") do
84               volume_now.channel[ch] = v
85               ch = ch + 1
86             end
87
88             volume_now.left  = volume_now.channel[1] or "N/A"
89             volume_now.right = volume_now.channel[2] or "N/A"
90
91             local volu = volume_now.left
92             local mute = volume_now.muted
93
94             if volu:match("N/A") or mute:match("N/A") then return end
95
96             if volu ~= pulsebar._current_level or mute ~= pulsebar._mute then
97                 pulsebar._current_level = tonumber(volu)
98                 pulsebar.bar:set_value(pulsebar._current_level / 100)
99                 if pulsebar._current_level == 0 or mute == "yes" then
100                     pulsebar._mute = mute
101                     pulsebar.tooltip:set_text ("[muted]")
102                     pulsebar.bar.color = pulsebar.colors.mute
103                 else
104                     pulsebar._mute = "no"
105                     pulsebar.tooltip:set_text(string.format("%s %s: %s", pulsebar.devicetype, pulsebar.device, volu))
106                     pulsebar.bar.color = pulsebar.colors.unmute
107                 end
108
109                 settings()
110
111                 if type(callback) == "function" then callback() end
112             end
113         end)
114     end
115
116     function pulsebar.notify()
117         pulsebar.update(function()
118             local preset = pulsebar.notification_preset
119
120             preset.title = string.format("%s %s - %s%%", pulsebar.devicetype, pulsebar.device, pulsebar._current_level)
121
122             if pulsebar._mute == "yes" then
123                 preset.title = preset.title .. " muted"
124             end
125
126             int = math.modf((pulsebar._current_level / 100) * awful.screen.focused().mywibox.height)
127             preset.text = string.format("[%s%s]", string.rep("|", int),
128                           string.rep(" ", awful.screen.focused().mywibox.height - int))
129
130             if pulsebar.followtag then preset.screen = awful.screen.focused() end
131
132             if not pulsebar.notification then
133                 pulsebar.notification = naughty.notify {
134                     preset  = preset,
135                     destroy = function() pulsebar.notification = nil end
136                 }
137             else
138                 naughty.replace_text(pulsebar.notification, preset.title, preset.text)
139             end
140         end)
141     end
142
143     helpers.newtimer(string.format("pulsebar-%s", pulsebar.sink), timeout, pulsebar.update)
144
145     return pulsebar
146 end
147
148 return factory