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

layout: fixed useless_gap retrieval
[etc/awesome.git] / widgets / alsabar.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 newtimer     = require("lain.helpers").newtimer
11 local read_pipe    = require("lain.helpers").read_pipe
12
13 local awful        = require("awful")
14 local beautiful    = require("beautiful")
15 local naughty      = require("naughty")
16 local wibox        = require("wibox")
17
18 local math         = { modf   = math.modf }
19 local string       = { format = string.format,
20                        match  = string.match,
21                        rep    = string.rep }
22 local tonumber     = tonumber
23
24 local setmetatable = setmetatable
25
26 -- ALSA volume bar
27 -- lain.widgets.alsabar
28 local alsabar = {
29     channel = "Master",
30     step    = "1%",
31
32     colors = {
33         background = beautiful.bg_normal,
34         mute       = "#EB8F8F",
35         unmute     = "#A4CE8A"
36     },
37
38     terminal = terminal or "xterm",
39     mixer    = string.format("%s -e alsamixer", terminal),
40
41     notifications = {
42         font      = beautiful.font:sub(beautiful.font:find(""), beautiful.font:find(" ")),
43         font_size = "11",
44         color     = beautiful.fg_normal,
45         screen    = 1
46     },
47
48     _current_level = 0,
49     _muted         = false
50 }
51
52 function alsabar.notify()
53     alsabar.update()
54
55     local preset = {
56         title   = "",
57         text    = "",
58         timeout = 5,
59         screen  = alsabar.notifications.screen,
60         font    = string.format("%s %s", alsabar.notifications.font,
61                   alsabar.notifications.font_size),
62         fg      = alsabar.notifications.color
63     }
64
65     if alsabar._muted
66     then
67         preset.title = string.format("%s - Muted", alsabar.channel)
68     else
69         preset.title = string.format("%s - %s%%", alsabar.channel, alsabar._current_level)
70     end
71
72     int = math.modf((alsabar._current_level / 100) * awful.screen.focused().mywibox.height)
73     preset.text = string.format("[%s%s]", string.rep("|", int),
74                   string.rep(" ", awful.screen.focused().mywibox.height - int))
75
76     if alsabar.followtag then
77         preset.screen = awful.screen.focused()
78     end
79
80     if alsabar._notify ~= nil then
81         alsabar._notify = naughty.notify ({
82             replaces_id = alsabar._notify.id,
83             preset      = preset,
84         })
85     else
86         alsabar._notify = naughty.notify ({
87             preset = preset,
88         })
89     end
90 end
91
92 local function worker(args)
93     local args         = args or {}
94     local timeout      = args.timeout or 5
95     local settings     = args.settings or function() end
96     local width        = args.width or 63
97     local height       = args.heigth or 1
98     local ticks        = args.ticks or false
99     local ticks_size   = args.ticks_size or 7
100     local vertical     = args.vertical or false
101
102     alsabar.cmd           = args.cmd or "amixer"
103     alsabar.channel       = args.channel or alsabar.channel
104     alsabar.togglechannel = args.togglechannel
105     alsabar.step          = args.step or alsabar.step
106     alsabar.colors        = args.colors or alsabar.colors
107     alsabar.notifications = args.notifications or alsabar.notifications
108     alsabar.followtag     = args.followtag or false
109
110     alsabar.bar = wibox.widget {
111         forced_height    = height,
112         forced_width     = width,
113         color            = alsabar.colors.unmute,
114         background_color = alsabar.colors.background,
115         margins          = 1,
116         paddings         = 1,
117         ticks            = ticks,
118         ticks_size       = ticks_size,
119         widget           = wibox.widget.progressbar,
120         layout           = vertical and wibox.container.rotate
121     }
122
123     alsabar.tooltip = awful.tooltip({ objects = { alsabar.bar } })
124
125     function alsabar.update()
126         -- Get mixer control contents
127         local mixer = read_pipe(string.format("%s get %s", alsabar.cmd, alsabar.channel))
128
129         -- Capture mixer control state:          [5%] ... ... [on]
130         local volu, mute = string.match(mixer, "([%d]+)%%.*%[([%l]*)")
131
132         -- HDMIs can have a channel different from Master for toggling mute
133         if alsabar.togglechannel then
134             mute = string.match(read_pipe(string.format("%s get %s", alsabar.cmd, alsabar.togglechannel)), "%[(%a+)%]")
135         end
136
137         if (volu and tonumber(volu) ~= alsabar._current_level) or (mute and string.match(mute, "on") ~= alsabar._muted)
138         then
139             alsabar._current_level = tonumber(volu) or alsabar._current_level
140             alsabar.bar:set_value(alsabar._current_level / 100)
141             if (not mute and tonumber(volu) == 0) or mute == "off"
142             then
143                 alsabar._muted = true
144                 alsabar.tooltip:set_text ("[Muted]")
145                 alsabar.bar.color = alsabar.colors.mute
146             else
147                 alsabar._muted = false
148                 alsabar.tooltip:set_text(string.format("%s: %s", alsabar.channel, volu))
149                 alsabar.bar.color = alsabar.colors.unmute
150             end
151
152             volume_now = {}
153             volume_now.level = tonumber(volu)
154             volume_now.status = mute
155
156             settings()
157         end
158     end
159
160     alsabar.bar:buttons(awful.util.table.join (
161           awful.button({}, 1, function()
162             awful.util.spawn(alsabar.mixer)
163           end),
164           awful.button({}, 2, function()
165                                                 awful.util.spawn(string.format("%s set %s 100%%", alsabar.cmd, alsabar.channel))
166             alsabar.update()
167           end),
168           awful.button({}, 3, function()
169             awful.util.spawn(string.format("%s set %s toggle", alsabar.cmd, alsabar.togglechannel or alsabar.channel))
170             alsabar.update()
171           end),
172           awful.button({}, 4, function()
173             awful.util.spawn(string.format("%s set %s %s+", alsabar.cmd, alsabar.channel, alsabar.step))
174             alsabar.update()
175           end),
176           awful.button({}, 5, function()
177             awful.util.spawn(string.format("%s set %s %s-", alsabar.cmd, alsabar.channel, alsabar.step))
178             alsabar.update()
179           end)
180     ))
181
182     timer_id = string.format("alsabar-%s-%s", alsabar.cmd, alsabar.channel)
183
184     newtimer(timer_id, timeout, alsabar.update)
185
186     return alsabar
187 end
188
189 return setmetatable(alsabar, { __call = function(_, ...) return worker(...) end })