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

5453b1f1b7ed203636ecfe72f20a27399c0a437d
[etc/awesome.git] / widgets / pulsebar.lua
1
2 --[[
3                                                   
4      Licensed under GNU General Public License v2 
5       * (c) 2013, Luke Bonham                     
6       * (c) 2013, Rman                            
7                                                   
8 --]]
9
10 local helpers      = require("lain.helpers")
11 local awful        = require("awful")
12 local naughty      = require("naughty")
13 local wibox        = require("wibox")
14 local math         = { modf   = math.modf }
15 local string       = { format = string.format,
16                        gmatch = string.gmatch,
17                        match  = string.match,
18                        rep    = string.rep }
19 local type         = type
20 local tonumber     = tonumber
21 local setmetatable = setmetatable
22
23 -- Pulseaudio volume bar
24 -- lain.widgets.pulsebar
25 local pulsebar = {
26     colors = {
27         background = "#000000",
28         mute       = "#EB8F8F",
29         unmute     = "#A4CE8A"
30     },
31
32     _current_level = 0,
33     _muted         = false
34 }
35
36 local function worker(args)
37     local args       = args or {}
38     local timeout    = args.timeout or 5
39     local settings   = args.settings or function() end
40     local width      = args.width or 63
41     local height     = args.heigth or 1
42     local ticks      = args.ticks or false
43     local ticks_size = args.ticks_size or 7
44     local vertical   = args.vertical or false
45     local scallback  = args.scallback
46
47     pulsebar.cmd           = args.cmd or "pacmd list-sinks | sed -n -e '0,/*/d' -e '/base volume/d' -e '/volume:/p' -e '/muted:/p' -e '/device\\.string/p'"
48     pulsebar.sink          = args.sink or 0
49     pulsebar.colors        = args.colors or pulsebar.colors
50     pulsebar.followtag     = args.followtag or false
51     pulsebar.notifications = args.notification_preset
52
53     if not pulsebar.notification_preset then
54         pulsebar.notification_preset      = {}
55         pulsebar.notification_preset.font = "Monospace 10"
56     end
57
58     pulsebar.bar = wibox.widget {
59         forced_height    = height,
60         forced_width     = width,
61         color            = pulsebar.colors.unmute,
62         background_color = pulsebar.colors.background,
63         margins          = 1,
64         paddings         = 1,
65         ticks            = ticks,
66         ticks_size       = ticks_size,
67         widget           = wibox.widget.progressbar,
68         layout           = vertical and wibox.container.rotate
69     }
70
71     pulsebar.tooltip = awful.tooltip({ objects = { pulsebar.bar } })
72
73     function pulsebar.update(callback)
74         if scallback then pulseaudio.cmd = scallback() end
75
76         helpers.async({ awful.util.shell, "-c", pulsebar.cmd }, function(s)
77             volume_now = {
78                 index = string.match(s, "index: (%S+)") or "N/A",
79                 sink  = string.match(s, "device.string = \"(%S+)\"") or "N/A",
80                 muted = string.match(s, "muted: (%S+)") or "N/A"
81             }
82
83             local ch = 1
84             volume_now.channel = {}
85             for v in string.gmatch(s, ":.-(%d+)%%") do
86               volume_now.channel[ch] = v
87               ch = ch + 1
88             end
89
90             volume_now.left  = volume_now.channel[1] or "N/A"
91             volume_now.right = volume_now.channel[2] or "N/A"
92
93             local volu = volume_now.left
94             local mute = volume_now.muted
95
96             if (volu and volu ~= pulsebar._current_level) or (mute and mute ~= pulsebar._muted) then
97                 pulsebar._current_level = volu
98                 pulsebar.bar:set_value(pulsebar._current_level / 100)
99                 if (not mute and volu == 0) or mute == "yes" then
100                     pulsebar._muted = true
101                     pulsebar.tooltip:set_text ("[Muted]")
102                     pulsebar.bar.color = pulsebar.colors.mute
103                 else
104                     pulsebar._muted = false
105                     pulsebar.tooltip:set_text(string.format("%s: %s", pulsebar.sink, 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             if pulsebar._muted then
121                 preset.title = string.format("Sink %s - Muted", pulsebar.sink)
122             else
123                 preset.title = string.format("%s - %s%%", pulsebar.sink, pulsebar._current_level)
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                 naughty.reset_timeout(pulsebar.notification, preset.timeout)
140             end
141         end)
142     end
143
144     helpers.newtimer(string.format("pulsebar-%s", pulsebar.sink), timeout, pulsebar.update)
145
146     return pulsebar
147 end
148
149 return setmetatable(pulsebar, { __call = function(_, ...) return worker(...) end })