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:

API change: lain.widget.contrib.tpbat has been rewritten and renamed to lain.widget...
[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      = {}
52         alsabar.notification_preset.font = "Monospace 10"
53     end
54
55     local format_cmd = string.format("%s get %s", alsabar.cmd, alsabar.channel)
56
57     if alsabar.togglechannel then
58         format_cmd = { awful.util.shell, "-c", string.format("%s get %s; %s get %s",
59         alsabar.cmd, alsabar.channel, alsabar.cmd, alsabar.togglechannel) }
60     end
61
62     alsabar.bar = wibox.widget {
63         color            = alsabar.colors.unmute,
64         background_color = alsabar.colors.background,
65         forced_height    = height,
66         forced_width     = width,
67         margins          = margins,
68         paddings         = margins,
69         ticks            = ticks,
70         ticks_size       = ticks_size,
71         widget           = wibox.widget.progressbar
72     }
73
74     alsabar.tooltip = awful.tooltip({ objects = { alsabar.bar } })
75
76     function alsabar.update(callback)
77         helpers.async(format_cmd, function(mixer)
78             local vol, playback = string.match(mixer, "([%d]+)%%.*%[([%l]*)")
79
80             if not vol or not playback then return end
81
82             if vol ~= alsabar._current_level or playback ~= alsabar._playback then
83                 alsabar._current_level = tonumber(vol)
84                 alsabar.bar:set_value(alsabar._current_level / 100)
85                 if alsabar._current_level == 0 or playback == "off" then
86                     alsabar._playback = playback
87                     alsabar.tooltip:set_text("[Muted]")
88                     alsabar.bar.color = alsabar.colors.mute
89                 else
90                     alsabar._playback = "on"
91                     alsabar.tooltip:set_text(string.format("%s: %s", alsabar.channel, vol))
92                     alsabar.bar.color = alsabar.colors.unmute
93                 end
94
95                 volume_now = {
96                     level  = alsabar._current_level,
97                     status = alsabar._playback
98                 }
99
100                 settings()
101
102                 if type(callback) == "function" then callback() end
103             end
104         end)
105     end
106
107     function alsabar.notify()
108         alsabar.update(function()
109             local preset = alsabar.notification_preset
110
111             preset.title = string.format("%s - %s%%", alsabar.channel, alsabar._current_level)
112
113             if alsabar._playback == "off" then
114                 preset.title = preset.title .. " Muted"
115             end
116
117             -- tot is the maximum number of ticks to display in the notification
118             -- fallback: default horizontal wibox height
119             local wib, tot = awful.screen.focused().mywibox, 20
120
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             end
130
131             int = math.modf((alsabar._current_level / 100) * tot)
132             preset.text = string.format("[%s%s]", string.rep("|", int),
133                           string.rep(" ", tot - int))
134
135             if alsabar.followtag then preset.screen = awful.screen.focused() end
136
137             if not alsabar.notification then
138                 alsabar.notification = naughty.notify {
139                     preset  = preset,
140                     destroy = function() alsabar.notification = nil end
141                 }
142             else
143                 naughty.replace_text(alsabar.notification, preset.title, preset.text)
144             end
145         end)
146     end
147
148     helpers.newtimer(string.format("alsabar-%s-%s", alsabar.cmd, alsabar.channel), timeout, alsabar.update)
149
150     return alsabar
151 end
152
153 return factory