massive update, probably broken
[dotfiles/.git] / .config / awesome / lain / 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