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:

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