]> 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:

30fbb40c4557ee547e189c31268528bd6069be9b
[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             local wib = awful.screen.focused().mywibox
127
128             local tot = wib.height
129             if wib.position == "left" or wib.position == "right" then
130                 tot = wib.width
131             end
132
133             int = math.modf((pulsebar._current_level / 100) * tot)
134             preset.text = string.format("[%s%s]", string.rep("|", int),
135                           string.rep(" ", tot - int))
136
137             if pulsebar.followtag then preset.screen = awful.screen.focused() end
138
139             if not pulsebar.notification then
140                 pulsebar.notification = naughty.notify {
141                     preset  = preset,
142                     destroy = function() pulsebar.notification = nil end
143                 }
144             else
145                 naughty.replace_text(pulsebar.notification, preset.title, preset.text)
146             end
147         end)
148     end
149
150     helpers.newtimer(string.format("pulsebar-%s", pulsebar.sink), timeout, pulsebar.update)
151
152     return pulsebar
153 end
154
155 return factory