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 pull request #439 from gregflynn/201908_gf_customize_pulsebar_notification_char...
[etc/awesome.git] / widget / alsabar.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     = math
14 local string   = string
15 local type     = type
16 local tonumber = tonumber
17
18 -- ALSA volume bar
19 -- lain.widget.alsabar
20
21 local function factory(args)
22     local alsabar = {
23         colors = {
24             background = "#000000",
25             mute       = "#EB8F8F",
26             unmute     = "#A4CE8A"
27         },
28
29         _current_level = 0,
30         _playback      = "off"
31     }
32
33     local args       = args or {}
34     local timeout    = args.timeout or 5
35     local settings   = args.settings or function() end
36     local width      = args.width or 63
37     local height     = args.height or 1
38     local margins    = args.margins or 1
39     local paddings   = args.paddings or 1
40     local ticks      = args.ticks or false
41     local ticks_size = args.ticks_size or 7
42
43     alsabar.cmd                 = args.cmd or "amixer"
44     alsabar.channel             = args.channel or "Master"
45     alsabar.togglechannel       = args.togglechannel
46     alsabar.colors              = args.colors or alsabar.colors
47     alsabar.followtag           = args.followtag or false
48     alsabar.notification_preset = args.notification_preset
49
50     if not alsabar.notification_preset then
51         alsabar.notification_preset = { font = "Monospace 10" }
52     end
53
54     local format_cmd = string.format("%s get %s", alsabar.cmd, alsabar.channel)
55
56     if alsabar.togglechannel then
57         format_cmd = { awful.util.shell, "-c", string.format("%s get %s; %s get %s",
58         alsabar.cmd, alsabar.channel, alsabar.cmd, alsabar.togglechannel) }
59     end
60
61     alsabar.bar = wibox.widget {
62         color            = alsabar.colors.unmute,
63         background_color = alsabar.colors.background,
64         forced_height    = height,
65         forced_width     = width,
66         margins          = margins,
67         paddings         = margins,
68         ticks            = ticks,
69         ticks_size       = ticks_size,
70         widget           = wibox.widget.progressbar
71     }
72
73     alsabar.tooltip = awful.tooltip({ objects = { alsabar.bar } })
74
75     function alsabar.update(callback)
76         helpers.async(format_cmd, function(mixer)
77             local vol, playback = string.match(mixer, "([%d]+)%%.*%[([%l]*)")
78
79             if not vol or not playback then return end
80
81             if vol ~= alsabar._current_level or playback ~= alsabar._playback then
82                 alsabar._current_level = tonumber(vol)
83                 alsabar.bar:set_value(alsabar._current_level / 100)
84                 if alsabar._current_level == 0 or playback == "off" then
85                     alsabar._playback = playback
86                     alsabar.tooltip:set_text("[Muted]")
87                     alsabar.bar.color = alsabar.colors.mute
88                 else
89                     alsabar._playback = "on"
90                     alsabar.tooltip:set_text(string.format("%s: %s", alsabar.channel, vol))
91                     alsabar.bar.color = alsabar.colors.unmute
92                 end
93
94                 volume_now = {
95                     level  = alsabar._current_level,
96                     status = alsabar._playback
97                 }
98
99                 settings()
100
101                 if type(callback) == "function" then callback() end
102             end
103         end)
104     end
105
106     function alsabar.notify()
107         alsabar.update(function()
108             local preset = alsabar.notification_preset
109
110             preset.title = string.format("%s - %s%%", alsabar.channel, alsabar._current_level)
111
112             if alsabar._playback == "off" then
113                 preset.title = preset.title .. " Muted"
114             end
115
116             -- tot is the maximum number of ticks to display in the notification
117             local tot = alsabar.notification_preset.max_ticks
118
119             if not tot then
120                 local wib = awful.screen.focused().mywibox
121                 -- if we can grab mywibox, tot is defined as its height if
122                 -- horizontal, or width otherwise
123                 if wib then
124                     if wib.position == "left" or wib.position == "right" then
125                         tot = wib.width
126                     else
127                         tot = wib.height
128                     end
129                 -- fallback: default horizontal wibox height
130                 else
131                     tot = 20
132                 end
133             end
134
135             int = math.modf((alsabar._current_level / 100) * tot)
136             preset.text = string.format("[%s%s]", string.rep("|", int),
137                           string.rep(" ", tot - int))
138
139             if alsabar.followtag then preset.screen = awful.screen.focused() end
140
141             if not alsabar.notification then
142                 alsabar.notification = naughty.notify {
143                     preset  = preset,
144                     destroy = function() alsabar.notification = nil end
145                 }
146             else
147                 naughty.replace_text(alsabar.notification, preset.title, preset.text)
148             end
149         end)
150     end
151
152     helpers.newtimer(string.format("alsabar-%s-%s", alsabar.cmd, alsabar.channel), timeout, alsabar.update)
153
154     return alsabar
155 end
156
157 return factory