diff --git a/awesome-wm-widgets/.gitignore b/awesome-wm-widgets/.gitignore new file mode 100644 index 0000000..d0cf895 --- /dev/null +++ b/awesome-wm-widgets/.gitignore @@ -0,0 +1,43 @@ +# Compiled Lua sources +luac.out + +# luarocks build files +*.src.rock +*.zip +*.tar.gz + +# Object files +*.o +*.os +*.ko +*.obj +*.elf + +# Precompiled Headers +*.gch +*.pch + +# Libraries +*.lib +*.a +*.la +*.lo +*.def +*.exp + +# Shared objects (inc. Windows DLLs) +*.dll +*.so +*.so.* +*.dylib + +# Executables +*.exe +*.out +*.app +*.i*86 +*.x86_64 +*.hex + +# IDEA files +.idea \ No newline at end of file diff --git a/awesome-wm-widgets/LICENSE b/awesome-wm-widgets/LICENSE new file mode 100644 index 0000000..1f89e49 --- /dev/null +++ b/awesome-wm-widgets/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2017 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/awesome-wm-widgets/README.md b/awesome-wm-widgets/README.md new file mode 100644 index 0000000..f7f8b97 --- /dev/null +++ b/awesome-wm-widgets/README.md @@ -0,0 +1,80 @@ +# Awesome WM widgets + +Set of super simple widgets compatible with Awesome Window Manager v.4+. + +![screenshot](./screenshot.png) + +or with separators + +![screenshot](./screenshot_with_sprtrs.png) + +Some more screenshots in this reddit [post](https://www.reddit.com/r/unixporn/comments/8qijmx/awesomewm_dark_theme/) + +From left to right: + +- [spotify-widget](https://github.com/streetturtle/AwesomeWM/tree/master/spotify-widget) / [rhythmbox-widget](https://github.com/streetturtle/AwesomeWM/tree/master/rhythmbox-widget) +- [cpu-widget](https://github.com/streetturtle/AwesomeWM/tree/master/cpu-widget) +- [weather-widget](https://github.com/streetturtle/AwesomeWM/tree/master/weather-widget) +- [email-widget](https://github.com/streetturtle/AwesomeWM/tree/master/email-widget) +- [brightness-widget](https://github.com/streetturtle/AwesomeWM/tree/master/brightness-widget) +- [volume-widget](https://github.com/streetturtle/AwesomeWM/tree/master/volume-widget) +- [volumebar-widget](https://github.com/streetturtle/AwesomeWM/tree/master/volumebar-widget) +- [volumearc-widget](https://github.com/streetturtle/AwesomeWM/tree/master/volumearc-widget) +- [batteryarc-widget](https://github.com/streetturtle/AwesomeWM/tree/master/batteryarc-widget) +- [battery-widget](https://github.com/streetturtle/AwesomeWM/tree/master/battery-widget) +- [ram-widget](https://github.com/streetturtle/AwesomeWM/tree/master/ram-widget) +- [translate-widget](https://github.com/streetturtle/AwesomeWM/tree/master/translate-widget) (not on the screenshot) +- [spotify-shell](https://github.com/streetturtle/AwesomeWM/tree/master/spotify-shell) + +Some of these widgets use [Arc icon theme](https://github.com/horst3180/arc-icon-theme) by default but it could be easily +changed to any other icon theme or custom icons. If you want to have separators between widgets like on the screenshot create text widget with ` : ` and place it between widgets: + +```lua +... +sprtr = wibox.widget.textbox() +sprtr:set_text(" : ") +... +sprtr, +volume_icon, +sprtr, +battery_widget, +sprtr, +... +``` + +# Installation + +Clone the repo under **~/.config/awesome/**, then in **rc.lua** add the import of the widget you'd like to use in "require" section on the top of the file: + +```lua +local battery_widget = require("awesome-wm-widgets.battery-widget.battery") +``` + +and then add widget to the wibox (you can search for **mytextclock** and add widget before): + +```lua + -- Add widgets to the wibox + s.mywibox:setup { + layout = wibox.layout.align.horizontal, + { -- Left widgets + ... + }, + s.mytasklist, -- Middle widget + { -- Right widgets + ... + battery_widget, + mytextclock + ... + } +``` + +You will also need to install [Arc icon theme](https://github.com/horst3180/arc-icon-theme) if widget uses icons. By default it should be installed under **/usr/share/icons/Arc**. If you prefer different installation folder then you'll have to change path to the icons in the source code of the widget you want to use. + +# Icons + +If you don't want to install Arc icon theme you can just download the icons which are used from the [Arc repository](https://github.com/horst3180/arc-theme). +Or create your own icons with the same name. + +In case of any questions/suggestions don't hesitate to contact me, I would be happy to help :) + +PRs/issues and st★rs are welcome! diff --git a/awesome-wm-widgets/battery-widget/README.md b/awesome-wm-widgets/battery-widget/README.md new file mode 100644 index 0000000..57f7c3f --- /dev/null +++ b/awesome-wm-widgets/battery-widget/README.md @@ -0,0 +1,29 @@ +# Battery widget + +Simple and easy-to-install widget for Awesome Window Manager. + +This widget consists of: + + - an icon which shows the battery level: + ![Battery Widget](./bat-wid-1.png) + - a pop-up window, which shows up when you hover over an icon: + ![Battery Widget](./bat-wid-2.png) + Alternatively you can use a tooltip (check the code): + ![Battery Widget](./bat-wid-22.png) + - a pop-up warning message which appears on bottom right corner when battery level is less that 15% (you can get the image [here](https://vk.com/images/stickers/1933/512.png)): + ![Battery Widget](./bat-wid-3.png) + +Note that widget uses the Arc icon theme, so it should be [installed](https://github.com/horst3180/arc-icon-theme#installation) first under **/usr/share/icons/Arc/** folder. + +## Installation + +This widget reads the output of acpi tool. +- install `acpi` and check the output: + +```bash +$ sudo apt-get install acpi +$ acpi +Battery 0: Discharging, 66%, 02:34:06 remaining +``` + +Then refer to the [installation](https://github.com/streetturtle/awesome-wm-widgets#installation) section of the repo. diff --git a/awesome-wm-widgets/battery-widget/bat-wid-1.png b/awesome-wm-widgets/battery-widget/bat-wid-1.png new file mode 100644 index 0000000..00e1618 Binary files /dev/null and b/awesome-wm-widgets/battery-widget/bat-wid-1.png differ diff --git a/awesome-wm-widgets/battery-widget/bat-wid-2.png b/awesome-wm-widgets/battery-widget/bat-wid-2.png new file mode 100644 index 0000000..ae20af2 Binary files /dev/null and b/awesome-wm-widgets/battery-widget/bat-wid-2.png differ diff --git a/awesome-wm-widgets/battery-widget/bat-wid-22.png b/awesome-wm-widgets/battery-widget/bat-wid-22.png new file mode 100644 index 0000000..38761f7 Binary files /dev/null and b/awesome-wm-widgets/battery-widget/bat-wid-22.png differ diff --git a/awesome-wm-widgets/battery-widget/bat-wid-3.png b/awesome-wm-widgets/battery-widget/bat-wid-3.png new file mode 100644 index 0000000..352b496 Binary files /dev/null and b/awesome-wm-widgets/battery-widget/bat-wid-3.png differ diff --git a/awesome-wm-widgets/battery-widget/battery.lua b/awesome-wm-widgets/battery-widget/battery.lua new file mode 100644 index 0000000..a472bbf --- /dev/null +++ b/awesome-wm-widgets/battery-widget/battery.lua @@ -0,0 +1,135 @@ +------------------------------------------------- +-- Battery Widget for Awesome Window Manager +-- Shows the battery status using the ACPI tool +-- More details could be found here: +-- https://github.com/streetturtle/awesome-wm-widgets/tree/master/battery-widget + +-- @author Pavel Makhov +-- @copyright 2017 Pavel Makhov +------------------------------------------------- + +local awful = require("awful") +local naughty = require("naughty") +local watch = require("awful.widget.watch") +local wibox = require("wibox") + +-- acpi sample outputs +-- Battery 0: Discharging, 75%, 01:51:38 remaining +-- Battery 0: Charging, 53%, 00:57:43 until charged + +local PATH_TO_ICONS = "/usr/share/icons/Arc/status/symbolic/" +local HOME = os.getenv("HOME") + +local battery_widget = wibox.widget { + { + id = "icon", + widget = wibox.widget.imagebox, + resize = false + }, + layout = wibox.container.margin(_, 0, 0, 3) +} + +-- Popup with battery info +-- One way of creating a pop-up notification - naughty.notify +local notification +local function show_battery_status() + awful.spawn.easy_async([[bash -c 'acpi']], + function(stdout, _, _, _) + notification = naughty.notify{ + text = stdout, + title = "Battery status", + timeout = 5, hover_timeout = 0.5, + width = 200, + } + end + ) +end + +-- Alternative to naughty.notify - tooltip. You can compare both and choose the preferred one +--battery_popup = awful.tooltip({objects = {battery_widget}}) + +-- To use colors from beautiful theme put +-- following lines in rc.lua before require("battery"): +-- beautiful.tooltip_fg = beautiful.fg_normal +-- beautiful.tooltip_bg = beautiful.bg_normal + +local function show_battery_warning() + naughty.notify{ + icon = HOME .. "/.config/awesome/nichosi.png", + icon_size=100, + text = "Huston, we have a problem", + title = "Battery is dying", + timeout = 5, hover_timeout = 0.5, + position = "bottom_right", + bg = "#F06060", + fg = "#EEE9EF", + width = 300, + } +end + +local last_battery_check = os.time() + +watch("acpi -i", 10, + function(widget, stdout, stderr, exitreason, exitcode) + local batteryType + + local battery_info = {} + local capacities = {} + for s in stdout:gmatch("[^\r\n]+") do + local status, charge_str, time = string.match(s, '.+: (%a+), (%d?%d?%d)%%,?.*') + if status ~= nil then + table.insert(battery_info, {status = status, charge = tonumber(charge_str)}) + else + local cap_str = string.match(s, '.+:.+last full capacity (%d+)') + table.insert(capacities, tonumber(cap_str)) + end + end + + local capacity = 0 + for i, cap in ipairs(capacities) do + capacity = capacity + cap + end + + local charge = 0 + local status + for i, batt in ipairs(battery_info) do + if batt.charge >= charge then + status = batt.status -- use most charged battery status + -- this is arbitrary, and maybe another metric should be used + end + + charge = charge + batt.charge * capacities[i] + end + charge = charge / capacity + + if (charge >= 0 and charge < 15) then + batteryType = "battery-empty%s-symbolic" + if status ~= 'Charging' and os.difftime(os.time(), last_battery_check) > 300 then + -- if 5 minutes have elapsed since the last warning + last_battery_check = time() + + show_battery_warning() + end + elseif (charge >= 15 and charge < 40) then batteryType = "battery-caution%s-symbolic" + elseif (charge >= 40 and charge < 60) then batteryType = "battery-low%s-symbolic" + elseif (charge >= 60 and charge < 80) then batteryType = "battery-good%s-symbolic" + elseif (charge >= 80 and charge <= 100) then batteryType = "battery-full%s-symbolic" + end + + if status == 'Charging' then + batteryType = string.format(batteryType, '-charging') + else + batteryType = string.format(batteryType, '') + end + + widget.icon:set_image(PATH_TO_ICONS .. batteryType .. ".svg") + + -- Update popup text + -- battery_popup.text = string.gsub(stdout, "\n$", "") + end, + battery_widget) + +battery_widget:connect_signal("mouse::enter", function() show_battery_status() end) +battery_widget:connect_signal("mouse::leave", function() naughty.destroy(notification) end) + +return battery_widget diff --git a/awesome-wm-widgets/batteryarc-widget/10_c.png b/awesome-wm-widgets/batteryarc-widget/10_c.png new file mode 100644 index 0000000..3faf753 Binary files /dev/null and b/awesome-wm-widgets/batteryarc-widget/10_c.png differ diff --git a/awesome-wm-widgets/batteryarc-widget/10_d.png b/awesome-wm-widgets/batteryarc-widget/10_d.png new file mode 100644 index 0000000..c9aa8d3 Binary files /dev/null and b/awesome-wm-widgets/batteryarc-widget/10_d.png differ diff --git a/awesome-wm-widgets/batteryarc-widget/20_c.png b/awesome-wm-widgets/batteryarc-widget/20_c.png new file mode 100644 index 0000000..f0a191d Binary files /dev/null and b/awesome-wm-widgets/batteryarc-widget/20_c.png differ diff --git a/awesome-wm-widgets/batteryarc-widget/20_d.png b/awesome-wm-widgets/batteryarc-widget/20_d.png new file mode 100644 index 0000000..15fabed Binary files /dev/null and b/awesome-wm-widgets/batteryarc-widget/20_d.png differ diff --git a/awesome-wm-widgets/batteryarc-widget/80_c.png b/awesome-wm-widgets/batteryarc-widget/80_c.png new file mode 100644 index 0000000..e6dae75 Binary files /dev/null and b/awesome-wm-widgets/batteryarc-widget/80_c.png differ diff --git a/awesome-wm-widgets/batteryarc-widget/80_d.png b/awesome-wm-widgets/batteryarc-widget/80_d.png new file mode 100644 index 0000000..220c8e3 Binary files /dev/null and b/awesome-wm-widgets/batteryarc-widget/80_d.png differ diff --git a/awesome-wm-widgets/batteryarc-widget/README.md b/awesome-wm-widgets/batteryarc-widget/README.md new file mode 100644 index 0000000..cb73e09 --- /dev/null +++ b/awesome-wm-widgets/batteryarc-widget/README.md @@ -0,0 +1,45 @@ +# Batteryarc widget + +This widget is more informative version of [battery widget](https://github.com/streetturtle/awesome-wm-widgets/tree/master/battery-widget). + +Depending of the battery status it could look following ways: + + - ![10_d](./10_d.png) - less than 15 percent + - ![10_c](./10_c.png) - less than 15 percent, charging + - ![20_d](./20_d.png) - between 15 and 40 percent + - ![20_c](./20_c.png) - between 15 and 40 percent, charging + - ![80_d](./80_d.png) - more than 40 percent + - ![80_c](./80_c.png) - more than 40 percent, charging + +Widget uses following beautiful variables with values: + +```lua +theme.widget_main_color = "#74aeab" +theme.widget_red = "#e53935" +theme.widget_yellow = "#c0ca33" +theme.widget_green = "#43a047" +theme.widget_black = "#000000" +theme.widget_transparent = "#00000000" +``` + +which means that you need to copy the code above and paste it in your **theme.lua**. Otherwise you can change colors directly in the widget. + +## Installation + +Clone repo, include widget and use it in **rc.lua**: + +```lua +local batteryarc_widget = require("awesome-wm-widgets.batteryarc-widget.batteryarc") +... +s.mytasklist, -- Middle widget + { -- Right widgets + layout = wibox.layout.fixed.horizontal, + ... + batteryarc_widget, + ... +``` +You can get the icon for warning popup [here](https://vk.com/images/stickers/1933/512.png) + +## Troubleshooting + +In case of any doubts or questions don't hesitate to raise an [issue](https://github.com/streetturtle/awesome-wm-widgets/issues/new). diff --git a/awesome-wm-widgets/batteryarc-widget/batteryarc.lua b/awesome-wm-widgets/batteryarc-widget/batteryarc.lua new file mode 100644 index 0000000..6b28c46 --- /dev/null +++ b/awesome-wm-widgets/batteryarc-widget/batteryarc.lua @@ -0,0 +1,147 @@ +local awful = require("awful") +local beautiful = require("beautiful") +local naughty = require("naughty") +local wibox = require("wibox") +local watch = require("awful.widget.watch") + +local HOME = os.getenv("HOME") + +-- only text +local text = wibox.widget { + id = "txt", + font = "Play 5", + widget = wibox.widget.textbox +} + +-- mirror the text, because the whole widget will be mirrored after +local mirrored_text = wibox.container.mirror(text, { horizontal = true }) + +-- mirrored text with background +local mirrored_text_with_background = wibox.container.background(mirrored_text) + +local batteryarc = wibox.widget { + mirrored_text_with_background, + max_value = 1, + rounded_edge = true, + thickness = 2, + start_angle = 4.71238898, -- 2pi*3/4 + forced_height = 17, + forced_width = 17, + bg = "#ffffff11", + paddings = 2, + widget = wibox.container.arcchart, + set_value = function(self, value) + self.value = value + end, +} + +-- mirror the widget, so that chart value increases clockwise +local batteryarc_widget = wibox.container.mirror(batteryarc, { horizontal = true }) + +local last_battery_check = os.time() + +watch("acpi -i", 10, + function(widget, stdout, stderr, exitreason, exitcode) + local batteryType + + local battery_info = {} + local capacities = {} + for s in stdout:gmatch("[^\r\n]+") do + local status, charge_str, time = string.match(s, '.+: (%a+), (%d?%d?%d)%%,?.*') + if status ~= nil then + table.insert(battery_info, {status = status, charge = tonumber(charge_str)}) + else + local cap_str = string.match(s, '.+:.+last full capacity (%d+)') + table.insert(capacities, tonumber(cap_str)) + end + end + + local capacity = 0 + for i, cap in ipairs(capacities) do + capacity = capacity + cap + end + + local charge = 0 + local status + for i, batt in ipairs(battery_info) do + if batt.charge >= charge then + status = batt.status -- use most charged battery status + -- this is arbitrary, and maybe another metric should be used + end + + charge = charge + batt.charge * capacities[i] + end + charge = charge / capacity + + widget.value = charge / 100 + if status == 'Charging' then + mirrored_text_with_background.bg = beautiful.widget_green + mirrored_text_with_background.fg = beautiful.widget_black + else + mirrored_text_with_background.bg = beautiful.widget_transparent + mirrored_text_with_background.fg = beautiful.widget_main_color + end + + text.text = charge + + if charge < 15 then + batteryarc.colors = { beautiful.widget_red } + if status ~= 'Charging' and os.difftime(os.time(), last_battery_check) > 300 then + -- if 5 minutes have elapsed since the last warning + last_battery_check = time() + + show_battery_warning() + end + elseif charge > 15 and charge < 40 then + batteryarc.colors = { beautiful.widget_yellow } + else + batteryarc.colors = { beautiful.widget_main_color } + end + end, + batteryarc) + +-- Popup with battery info +-- One way of creating a pop-up notification - naughty.notify +local notification +function show_battery_status() + awful.spawn.easy_async([[bash -c 'acpi']], + function(stdout, _, _, _) + notification = naughty.notify { + text = stdout, + title = "Battery status", + timeout = 5, + hover_timeout = 0.5, + width = 200, + } + end) +end + +batteryarc:connect_signal("mouse::enter", function() show_battery_status() end) +batteryarc:connect_signal("mouse::leave", function() naughty.destroy(notification) end) + +-- Alternative to naughty.notify - tooltip. You can compare both and choose the preferred one + +--battery_popup = awful.tooltip({objects = {battery_widget}}) + +-- To use colors from beautiful theme put +-- following lines in rc.lua before require("battery"): +-- beautiful.tooltip_fg = beautiful.fg_normal +-- beautiful.tooltip_bg = beautiful.bg_normal + +--[[ Show warning notification ]] +function show_battery_warning() + naughty.notify { + icon = HOME .. "/.config/awesome/nichosi.png", + icon_size = 100, + text = "Huston, we have a problem", + title = "Battery is dying", + timeout = 5, + hover_timeout = 0.5, + position = "bottom_right", + bg = "#F06060", + fg = "#EEE9EF", + width = 300, + } +end + +return batteryarc_widget diff --git a/awesome-wm-widgets/brightness-widget/README.md b/awesome-wm-widgets/brightness-widget/README.md new file mode 100644 index 0000000..fa123c1 --- /dev/null +++ b/awesome-wm-widgets/brightness-widget/README.md @@ -0,0 +1,56 @@ +# Brightness widget + +![Brightness widget](./br-wid-1.png) + +This widget represents current brightness level. + +## Installation + +Firstly you need to get the current brightness level. There are two options: + + - using `xbacklight` command (depending on your video card (I guess) it may or may not work) + + To check if it works install xbackligth and check if it works: + + ```bash + sudo apt-get install xbacklight + xbacklight -get + ``` + + If there is no output it means that it doesn't work, but there is a second option: + + - using `light` command + + Install it from this git repo: [github.com/haikarainen/light](https://github.com/haikarainen/light) and check if it works but running + + ```bash + git clone https://github.com/haikarainen/light.git && \ + cd ./light && \ + sudo make && sudo make install \ + light -G + 49.18 + ``` +Depending on the chosen option change `GET_BRIGHTNESS_CMD` variable in **brightness.lua**. + +Then in **rc.lua** add the import on top of the file and then add widget to the wibox: + +```lua +require("awesome-wm-widgets.brightness-widget.brightness") +... +-- Add widgets to the wibox +s.mywibox:setup { +... +{ -- Right widgets +... +brightness_widget +``` + +## Controls + +In order to change brightness by shortcuts you can add them to the `globalkeys` table in the **rc.lua**: + +```lua +awful.key({ modkey }, ";", function () awful.spawn("light -A 5") end, {description = "increase brightness", group = "custom"}), +awful.key({ modkey, "Shift"}, ";", function () awful.spawn("light -U 5") end, {description = "decrease brightness", group = "custom"}), +``` +On laptop you can use `XF86MonBrightnessUp` and `XF86MonBrightnessDown` keys. diff --git a/awesome-wm-widgets/brightness-widget/br-wid-1.png b/awesome-wm-widgets/brightness-widget/br-wid-1.png new file mode 100644 index 0000000..f9200eb Binary files /dev/null and b/awesome-wm-widgets/brightness-widget/br-wid-1.png differ diff --git a/awesome-wm-widgets/brightness-widget/brightness.lua b/awesome-wm-widgets/brightness-widget/brightness.lua new file mode 100644 index 0000000..1b2e8a6 --- /dev/null +++ b/awesome-wm-widgets/brightness-widget/brightness.lua @@ -0,0 +1,56 @@ +------------------------------------------------- +-- Brightness Widget for Awesome Window Manager +-- Shows the brightness level of the laptop display +-- More details could be found here: +-- https://github.com/streetturtle/awesome-wm-widgets/tree/master/brightness-widget + +-- @author Pavel Makhov +-- @copyright 2017 Pavel Makhov +------------------------------------------------- + +local wibox = require("wibox") +local watch = require("awful.widget.watch") +local spawn = require("awful.spawn") + +local PATH_TO_ICON = "/usr/share/icons/Arc/status/symbolic/display-brightness-symbolic.svg" +local GET_BRIGHTNESS_CMD = "light -G" -- "xbacklight -get" +local INC_BRIGHTNESS_CMD = "light -A 1" -- "xbacklight -inc 5" +local DEC_BRIGHTNESS_CMD = "light -U 1" -- "xbacklight -dec 5" + +local brightness_text = wibox.widget.textbox() +brightness_text:set_font('Play 9') + +local brightness_icon = wibox.widget { + { + image = PATH_TO_ICON, + resize = false, + widget = wibox.widget.imagebox, + }, + top = 3, + widget = wibox.container.margin +} + +local brightness_widget = wibox.widget { + brightness_icon, + brightness_text, + layout = wibox.layout.fixed.horizontal, +} + +local update_widget = function(widget, stdout, stderr, exitreason, exitcode) + local brightness_level = tonumber(string.format("%.0f", stdout)) + widget:set_text(" " .. brightness_level .. "%") +end, + +brightness_widget:connect_signal("button::press", function(_,_,_,button) + if (button == 4) then spawn(INC_BRIGHTNESS_CMD, false) + elseif (button == 5) then spawn(DEC_BRIGHTNESS_CMD, false) + end + + spawn.easy_async(GET_BRIGHTNESS_CMD, function(stdout, stderr, exitreason, exitcode) + update_widget(brightness_widget, stdout, stderr, exitreason, exitcode) + end) +end) + +watch(GET_BRIGHTNESS_CMD, 1, update_widget, brightness_text) + +return brightness_widget diff --git a/awesome-wm-widgets/cpu-widget/README.md b/awesome-wm-widgets/cpu-widget/README.md new file mode 100644 index 0000000..5321aa0 --- /dev/null +++ b/awesome-wm-widgets/cpu-widget/README.md @@ -0,0 +1,34 @@ +# CPU widget + +This widget shows the average CPU load among all cores of the machine: + +![screenshot](out.gif) + +When the load is more than 80% the graph becomes red. You can easily customize the widget by changing colors, step width, step spacing, width and interval. + +## How it works + +To measure the load I took Paul Colby's bash [script](http://colby.id.au/calculating-cpu-usage-from-proc-stat/) and rewrote it in Lua, which was quite simple. +So awesome simply reads the first line of /proc/stat: + +```bash +$ cat /proc/stat | grep '^cpu ' +cpu 197294 718 50102 2002182 3844 0 2724 0 0 0 +``` + +and calculates the percentage. + +## Installation + +Clone/download repo and use widget in **rc.lua**: + +```lua +require("awesome-wm-widgets.cpu-widget.cpu-widget") +... +s.mytasklist, -- Middle widget + { -- Right widgets + layout = wibox.layout.fixed.horizontal, + ... + cpu_widget, + ... +``` diff --git a/awesome-wm-widgets/cpu-widget/cpu-widget.lua b/awesome-wm-widgets/cpu-widget/cpu-widget.lua new file mode 100644 index 0000000..455ff58 --- /dev/null +++ b/awesome-wm-widgets/cpu-widget/cpu-widget.lua @@ -0,0 +1,52 @@ +------------------------------------------------- +-- CPU Widget for Awesome Window Manager +-- Shows the current CPU utilization +-- More details could be found here: +-- https://github.com/streetturtle/awesome-wm-widgets/tree/master/cpu-widget + +-- @author Pavel Makhov +-- @copyright 2017 Pavel Makhov +------------------------------------------------- + +local watch = require("awful.widget.watch") +local wibox = require("wibox") +local beautiful = require("beautiful") + +local cpugraph_widget = wibox.widget { + max_value = 100, + background_color = "#00000000", + forced_width = 50, + step_width = 2, + step_spacing = 1, + widget = wibox.widget.graph +} + +--- By default graph widget goes from left to right, so we mirror it and push up a bit +local cpu_widget = wibox.container.margin(wibox.container.mirror(cpugraph_widget, { horizontal = true }), 0, 0, 0, 2) + +local total_prev = 0 +local idle_prev = 0 + +watch([[bash -c "cat /proc/stat | grep '^cpu '"]], 1, + function(widget, stdout, stderr, exitreason, exitcode) + local user, nice, system, idle, iowait, irq, softirq, steal, guest, guest_nice = + stdout:match('(%d+)%s(%d+)%s(%d+)%s(%d+)%s(%d+)%s(%d+)%s(%d+)%s(%d+)%s(%d+)%s(%d+)%s') + + local total = user + nice + system + idle + iowait + irq + softirq + steal + + local diff_idle = idle - idle_prev + local diff_total = total - total_prev + local diff_usage = (1000 * (diff_total - diff_idle) / diff_total + 5) / 10 + + widget:set_color(diff_usage > 80 and beautiful.widget_red + or beautiful.widget_main_color) + + widget:add_value(diff_usage) + + total_prev = total + idle_prev = idle + end, + cpugraph_widget +) + +return cpu_widget diff --git a/awesome-wm-widgets/cpu-widget/out.gif b/awesome-wm-widgets/cpu-widget/out.gif new file mode 100644 index 0000000..ac7542d Binary files /dev/null and b/awesome-wm-widgets/cpu-widget/out.gif differ diff --git a/awesome-wm-widgets/email-widget/README.md b/awesome-wm-widgets/email-widget/README.md new file mode 100644 index 0000000..c0777db --- /dev/null +++ b/awesome-wm-widgets/email-widget/README.md @@ -0,0 +1,35 @@ +# Email widget + +This widget consists of an icon with counter which shows number of unread emails: ![email icon](./em-wid-1.png) +and a popup message which appears when mouse hovers over an icon: ![email popup](./em-wid-2.png) + +Note that widget uses the Arc icon theme, so it should be [installed](https://github.com/horst3180/arc-icon-theme#installation) first under **/usr/share/icons/Arc/** folder. + +## Installation + +To install it put **email.lua** and **email-widget** folder under **~/.config/awesome**. Then + + - in **email.lua** cahnge path to python scripts; + - in python scripts add your credentials (note that password should be encrypted using pgp for example); + - add widget to awesome: + +```lua +require("email") +... +s.mytasklist, -- Middle widget + { -- Right widgets + layout = wibox.layout.fixed.horizontal, + ... + email_icon, + email_widget, + ... +``` + +## How it works + +This widget uses the output of two python scripts, first is called every 20 seconds - it returns number of unread emails and second is called when mouse hovers over an icon and displays content of those emails. For both of them you'll need to provide your credentials and imap server. For testing they can simply be called from console: + +``` bash +python ~/.config/awesome/email/count_unread_emails.py +python ~/.config/awesome/email/read_emails.py +``` \ No newline at end of file diff --git a/awesome-wm-widgets/email-widget/count_unread_emails.py b/awesome-wm-widgets/email-widget/count_unread_emails.py new file mode 100644 index 0000000..f4d2b86 --- /dev/null +++ b/awesome-wm-widgets/email-widget/count_unread_emails.py @@ -0,0 +1,16 @@ +#!/usr/bin/python + +import imaplib +import email + +M=imaplib.IMAP4_SSL("mail.teenagemutantninjaturtles.com", 993) +M.login("mickey@tmnt.com","cowabunga") + +status, counts = M.status("INBOX","(MESSAGES UNSEEN)") + +if status == "OK": + unread = counts[0].split()[4][:-1] +else: + unread = "N/A" + +print(unread) \ No newline at end of file diff --git a/awesome-wm-widgets/email-widget/em-wid-1.png b/awesome-wm-widgets/email-widget/em-wid-1.png new file mode 100644 index 0000000..5290ea8 Binary files /dev/null and b/awesome-wm-widgets/email-widget/em-wid-1.png differ diff --git a/awesome-wm-widgets/email-widget/em-wid-2.png b/awesome-wm-widgets/email-widget/em-wid-2.png new file mode 100644 index 0000000..0a0fd3a Binary files /dev/null and b/awesome-wm-widgets/email-widget/em-wid-2.png differ diff --git a/awesome-wm-widgets/email-widget/email.lua b/awesome-wm-widgets/email-widget/email.lua new file mode 100644 index 0000000..d6619f9 --- /dev/null +++ b/awesome-wm-widgets/email-widget/email.lua @@ -0,0 +1,42 @@ +local wibox = require("wibox") +local awful = require("awful") +local naughty = require("naughty") +local watch = require("awful.widget.watch") + +local path_to_icons = "/usr/share/icons/Arc/actions/22/" + +email_widget = wibox.widget.textbox() +email_widget:set_font('Play 9') + +email_icon = wibox.widget.imagebox() +email_icon:set_image(path_to_icons .. "/mail-mark-new.png") + +watch( + "python /home//.config/awesome/email-widget/count_unread_emails.py", 20, + function(widget, stdout, stderr, exitreason, exitcode) + local unread_emails_num = tonumber(stdout) or 0 + if (unread_emails_num > 0) then + email_icon:set_image(path_to_icons .. "/mail-mark-unread.png") + email_widget:set_text(stdout) + elseif (unread_emails_num == 0) then + email_icon:set_image(path_to_icons .. "/mail-message-new.png") + email_widget:set_text("") + end + end +) + + +function show_emails() + awful.spawn.easy_async([[bash -c 'python /home//.config/awesome/email-widget/read_unread_emails.py']], + function(stdout, stderr, reason, exit_code) + naughty.notify{ + text = stdout, + title = "Unread Emails", + timeout = 5, hover_timeout = 0.5, + width = 400, + } + end + ) +end + +email_icon:connect_signal("mouse::enter", function() show_emails() end) diff --git a/awesome-wm-widgets/email-widget/read_unread_emails.py b/awesome-wm-widgets/email-widget/read_unread_emails.py new file mode 100644 index 0000000..343fe66 --- /dev/null +++ b/awesome-wm-widgets/email-widget/read_unread_emails.py @@ -0,0 +1,42 @@ +#!/usr/bin/python + +import imaplib +import email +import datetime + +def process_mailbox(M): + rv, data = M.search(None, "(UNSEEN)") + if rv != 'OK': + print "No messages found!" + return + + for num in data[0].split(): + rv, data = M.fetch(num, '(BODY.PEEK[])') + if rv != 'OK': + print "ERROR getting message", num + return + + msg = email.message_from_string(data[0][1]) + print 'From:', msg['From'] + print 'Subject: %s' % (msg['Subject']) + date_tuple = email.utils.parsedate_tz(msg['Date']) + if date_tuple: + local_date = datetime.datetime.fromtimestamp(email.utils.mktime_tz(date_tuple)) + print "Local Date:", local_date.strftime("%a, %d %b %Y %H:%M:%S") + # with code below you can process text of email + # if msg.is_multipart(): + # for payload in msg.get_payload(): + # if payload.get_content_maintype() == 'text': + # print payload.get_payload() + # else: + # print msg.get_payload() + + +M=imaplib.IMAP4_SSL("mail.teenagemutantninjaturtles.com", 993) +M.login("mickey@tmnt.com","cowabunga") + +rv, data = M.select("INBOX") +if rv == 'OK': + process_mailbox(M) +M.close() +M.logout() \ No newline at end of file diff --git a/awesome-wm-widgets/mpdarc-widget/README.md b/awesome-wm-widgets/mpdarc-widget/README.md new file mode 100644 index 0000000..2192410 --- /dev/null +++ b/awesome-wm-widgets/mpdarc-widget/README.md @@ -0,0 +1,26 @@ +# MPD Widget + +Music Player Daemon widget by @raphaelfournier. + +# Prerequisite + +Install `mpd` (Music Player Daemon itself) and `mpc` (Music Player Client - program for controlling mpd), both should be available in repo, e.g for Ubuntu: + +```bash +sudo apt-get install mpd mpc +``` + +## Installation + +To use this widget clone repo under **~/.config/awesome/** and then add it in **rc.lua**: + +```lua +local mpdarc_widget = require("awesome-wm-widgets.mpdarc-widget.mpdarc") +... +s.mytasklist, -- Middle widget + { -- Right widgets + layout = wibox.layout.fixed.horizontal, + ... + mpdarc_widget, + ... +``` diff --git a/awesome-wm-widgets/mpdarc-widget/mpdarc.lua b/awesome-wm-widgets/mpdarc-widget/mpdarc.lua new file mode 100644 index 0000000..ca0f411 --- /dev/null +++ b/awesome-wm-widgets/mpdarc-widget/mpdarc.lua @@ -0,0 +1,119 @@ +------------------------------------------------- +-- mpd Arc Widget for Awesome Window Manager +-- Modelled after Pavel Makhov's work + +-- @author Raphaël Fournier-S'niehotta +-- @copyright 2018 Raphaël Fournier-S'niehotta +------------------------------------------------- + +local awful = require("awful") +local beautiful = require("beautiful") +local spawn = require("awful.spawn") +local watch = require("awful.widget.watch") +local wibox = require("wibox") +local naughty = require("naughty") + +local GET_MPD_CMD = "mpc status" +local TOGGLE_MPD_CMD = "mpc toggle" +local PAUSE_MPD_CMD = "mpc pause" +local STOP_MPD_CMD = "mpc stop" +local NEXT_MPD_CMD = "mpc next" +local PREV_MPD_CMD = "mpc prev" + +local PATH_TO_ICONS = "/usr/share/icons/Arc" +local PAUSE_ICON_NAME = PATH_TO_ICONS .. "/actions/24/player_pause.png" +local PLAY_ICON_NAME = PATH_TO_ICONS .. "/actions/24/player_play.png" +local STOP_ICON_NAME = PATH_TO_ICONS .. "/actions/24/player_stop.png" + +local icon = wibox.widget { + id = "icon", + widget = wibox.widget.imagebox, + image = PLAY_ICON_NAME + } +local mirrored_icon = wibox.container.mirror(icon, { horizontal = true }) + +local mpdarc = wibox.widget { + mirrored_icon, + max_value = 1, + value = 0.75, + thickness = 2, + start_angle = 4.71238898, -- 2pi*3/4 + forced_height = 32, + forced_width = 32, + rounded_edge = true, + bg = "#ffffff11", + paddings = 0, + widget = wibox.container.arcchart +} + +local mpdarc_icon_widget = wibox.container.mirror(mpdarc, { horizontal = true }) +local mpdarc_current_song_widget = wibox.widget { + id = 'current_song', + widget = wibox.widget.textbox, + font = 'Play 9' +} + +local update_graphic = function(widget, stdout, _, _, _) + local current_song = string.gmatch(stdout, "[^\r\n]+")() + stdout = string.gsub(stdout, "\n", "") + local mpdpercent = string.match(stdout, "(%d%d)%%") + local mpdstatus = string.match(stdout, "%[(%a+)%]") + if mpdstatus == "playing" then + icon.image = PLAY_ICON_NAME + widget.colors = { beautiful.widget_main_color } + widget.value = tonumber((100-mpdpercent)/100) + mpdarc_current_song_widget.markup = current_song + elseif mpdstatus == "paused" then + icon.image = PAUSE_ICON_NAME + widget.colors = { beautiful.widget_main_color } + widget.value = tonumber(mpdpercent/100) + mpdarc_current_song_widget.markup = current_song + else + icon.image = STOP_ICON_NAME + if string.len(stdout) == 0 then -- MPD is not running + mpdarc_current_song_widget.markup = "MPD is not running" + else + widget.colors = { beautiful.widget_red } + mpdarc_current_song_widget.markup = "" + end + end +end + +mpdarc:connect_signal("button::press", function(_, _, _, button) + if (button == 1) then awful.spawn(TOGGLE_MPD_CMD, false) -- left click + elseif (button == 2) then awful.spawn(STOP_MPD_CMD, false) + elseif (button == 3) then awful.spawn(PAUSE_MPD_CMD, false) + elseif (button == 4) then awful.spawn(NEXT_MPD_CMD, false) -- scroll up + elseif (button == 5) then awful.spawn(PREV_MPD_CMD, false) -- scroll down + end + + spawn.easy_async(GET_MPD_CMD, function(stdout, stderr, exitreason, exitcode) + update_graphic(mpdarc, stdout, stderr, exitreason, exitcode) + end) +end) + +local notification +function show_MPD_status() + spawn.easy_async(GET_MPD_CMD, + function(stdout, _, _, _) + notification = naughty.notify { + text = stdout, + title = "MPD", + timeout = 5, + hover_timeout = 0.5, + width = 600, + } + end) +end + +mpdarc:connect_signal("mouse::enter", function() show_MPD_status() end) +mpdarc:connect_signal("mouse::leave", function() naughty.destroy(notification) end) + +watch(GET_MPD_CMD, 1, update_graphic, mpdarc) + +local mpdarc_widget = { + mpdarc_icon_widget, + mpdarc_current_song_widget, + layout = wibox.layout.align.horizontal, + } +return mpdarc_widget diff --git a/awesome-wm-widgets/pomodoroarc-widget/README.md b/awesome-wm-widgets/pomodoroarc-widget/README.md new file mode 100644 index 0000000..49b1b2c --- /dev/null +++ b/awesome-wm-widgets/pomodoroarc-widget/README.md @@ -0,0 +1,16 @@ +# Pomodoro Widget + +:construction: This widget is under construction :construction_worker: + +## Installation + +This widget is based on [@jsspencer](https://github.com/jsspencer)' [pomo](https://github.com/jsspencer/pomo) - a simple pomodoro timer. +So first install/clone it anywhere you like, then either + - in widget's code provide path to the pomo.sh, or + - add pomo.sh to the PATH, or + - make a soft link in /usr/local/bin/ to it: + ```bash + sudo ln -sf /opt/pomodoro/pomo.sh /usr/local/bin/pomo + ``` + +Note that by default widget's code expects third way and calls script by `pomo`. \ No newline at end of file diff --git a/awesome-wm-widgets/pomodoroarc-widget/pomodoroarc.lua b/awesome-wm-widgets/pomodoroarc-widget/pomodoroarc.lua new file mode 100644 index 0000000..dab8c3a --- /dev/null +++ b/awesome-wm-widgets/pomodoroarc-widget/pomodoroarc.lua @@ -0,0 +1,135 @@ +------------------------------------------------- +-- Pomodoro Arc Widget for Awesome Window Manager +-- Modelled after Pavel Makhov's work + +-- @author Raphaël Fournier-S'niehotta +-- @copyright 2018 Raphaël Fournier-S'niehotta +------------------------------------------------- + +local awful = require("awful") +local beautiful = require("beautiful") +local spawn = require("awful.spawn") +local watch = require("awful.widget.watch") +local wibox = require("wibox") +local naughty = require("naughty") + +local GET_pomodoro_CMD = "pomo clock" +local PAUSE_pomodoro_CMD = "pomo pause" +local START_pomodoro_CMD = "pomo start" +local STOP_pomodoro_CMD = "pomo stop" + +local text = wibox.widget { + id = "txt", + --font = "Play 12", +font = "Inconsolata Medium 13", + widget = wibox.widget.textbox +} +-- mirror the text, because the whole widget will be mirrored after +local mirrored_text = wibox.container.margin(wibox.container.mirror(text, { horizontal = true })) +mirrored_text.right = 5 -- pour centrer le texte dans le rond +-- +--local mirrored_text = wibox.container.mirror(text, { horizontal = true }) + +-- mirrored text with background +local mirrored_text_with_background = wibox.container.background(mirrored_text) + +local pomodoroarc = wibox.widget { + mirrored_text_with_background, + max_value = 1, + thickness = 2, + start_angle = 4.71238898, -- 2pi*3/4 + forced_height = 32, + forced_width = 32, + rounded_edge = true, + bg = "#ffffff11", + paddings = 0, + widget = wibox.container.arcchart +} + +local pomodoroarc_widget = wibox.container.mirror(pomodoroarc, { horizontal = true }) + +local update_graphic = function(widget, stdout, _, _, _) + local pomostatus = string.match(stdout, " (%D?%D?):%D?%D?") + if pomostatus == "--" then +text.font = "Inconsolata Medium 13" + widget.colors = { beautiful.widget_main_color } + text.text = "25" + widget.value = 1 + else +text.font = "Inconsolata Medium 13" + local pomomin = string.match(stdout, "[ P]?[BW](%d?%d?):%d?%d?") + local pomosec = string.match(stdout, "[ P]?[BW]%d?%d?:(%d?%d?)") + local pomodoro = pomomin * 60 + pomosec + + local status = string.match(stdout, "([ P]?)[BW]%d?%d?:%d?%d?") + local workbreak = string.match(stdout, "[ P]?([BW])%d?%d?:%d?%d?") + text.text = pomomin + +-- Helps debugging + --naughty.notify { + --text = pomomin, + --title = "pomodoro debug", + --timeout = 5, + --hover_timeout = 0.5, + --width = 200, + --} + + if status == " " then -- clock ticking + if workbreak == "W" then + widget.value = tonumber(pomodoro/(25*60)) + if tonumber(pomomin) < 5 then -- last 5 min of pomo + widget.colors = { beautiful.widget_red } + else + widget.colors = { beautiful.widget_blue } + end + elseif workbreak == "B" then -- color during pause + widget.colors = { beautiful.widget_green } + widget.value = tonumber(pomodoro/(5*60)) + end + elseif status == "P" then -- paused + if workbreak == "W" then + widget.colors = { beautiful.widget_yellow } + widget.value = tonumber(pomodoro/(25*60)) +text.font = "Inconsolata Medium 13" + text.text = "PW" + elseif workbreak == "B" then + widget.colors = { beautiful.widget_yellow } + widget.value = tonumber(pomodoro/(5*60)) +text.font = "Inconsolata Medium 13" + text.text = "PB" + end + end + end +end + +pomodoroarc:connect_signal("button::press", function(_, _, _, button) + if (button == 2) then awful.spawn(PAUSE_pomodoro_CMD, false) + elseif (button == 1) then awful.spawn(START_pomodoro_CMD, false) + elseif (button == 3) then awful.spawn(STOP_pomodoro_CMD, false) + end + + spawn.easy_async(GET_pomodoro_CMD, function(stdout, stderr, exitreason, exitcode) + update_graphic(pomodoroarc, stdout, stderr, exitreason, exitcode) + end) +end) + +local notification +function show_pomodoro_status() + spawn.easy_async(GET_pomodoro_CMD, + function(stdout, _, _, _) + notification = naughty.notify { + text = stdout, + title = "pomodoro status", + timeout = 5, + hover_timeout = 0.5, + width = 200, + } + end) +end + +pomodoroarc:connect_signal("mouse::enter", function() show_pomodoro_status() end) +pomodoroarc:connect_signal("mouse::leave", function() naughty.destroy(notification) end) + +watch(GET_pomodoro_CMD, 1, update_graphic, pomodoroarc) + +return pomodoroarc_widget diff --git a/awesome-wm-widgets/ram-widget/README.md b/awesome-wm-widgets/ram-widget/README.md new file mode 100644 index 0000000..461aa99 --- /dev/null +++ b/awesome-wm-widgets/ram-widget/README.md @@ -0,0 +1,9 @@ +# Ram widget + +This widget shows the RAM usage. When clicked another widget appears with more detailed information: + +![screenshot](./out.gif) + +## Installation + +Please refer to the [installation](https://github.com/streetturtle/awesome-wm-widgets#installation) section of the repo. \ No newline at end of file diff --git a/awesome-wm-widgets/ram-widget/out.gif b/awesome-wm-widgets/ram-widget/out.gif new file mode 100644 index 0000000..736f894 Binary files /dev/null and b/awesome-wm-widgets/ram-widget/out.gif differ diff --git a/awesome-wm-widgets/ram-widget/ram-widget.lua b/awesome-wm-widgets/ram-widget/ram-widget.lua new file mode 100644 index 0000000..3072068 --- /dev/null +++ b/awesome-wm-widgets/ram-widget/ram-widget.lua @@ -0,0 +1,78 @@ +local awful = require("awful") +local watch = require("awful.widget.watch") +local wibox = require("wibox") + +--- Main ram widget shown on wibar +local ramgraph_widget = wibox.widget { + border_width = 0, + colors = { + '#74aeab', '#26403f' + }, + display_labels = false, + forced_width = 25, + widget = wibox.widget.piechart +} + +--- Widget which is shown when user clicks on the ram widget +local w = wibox { + height = 200, + width = 400, + ontop = true, + expand = true, + bg = '#1e252c', + max_widget_size = 500 +} + +w:setup { + border_width = 0, + colors = { + '#5ea19d', + '#55918e', + '#4b817e', + }, + display_labels = false, + forced_width = 25, + id = 'pie', + widget = wibox.widget.piechart +} + +local total, used, free, shared, buff_cache, available, total_swap, used_swap, free_swap + +local function getPercentage(value) + return math.floor(value / (total+total_swap) * 100 + 0.5) .. '%' +end + +watch('bash -c "free | grep -z Mem.*Swap.*"', 1, + function(widget, stdout, stderr, exitreason, exitcode) + total, used, free, shared, buff_cache, available, total_swap, used_swap, free_swap = + stdout:match('(%d+)%s*(%d+)%s*(%d+)%s*(%d+)%s*(%d+)%s*(%d+)%s*Swap:%s*(%d+)%s*(%d+)%s*(%d+)') + + widget.data = { used, total-used } widget.data = { used, total-used } + + if w.visible then + w.pie.data_list = { + {'used ' .. getPercentage(used + used_swap), used + used_swap}, + {'free ' .. getPercentage(free + free_swap), free + free_swap}, + {'buff_cache ' .. getPercentage(buff_cache), buff_cache} + } + end + end, + ramgraph_widget +) + +ramgraph_widget:buttons( + awful.util.table.join( + awful.button({}, 1, function() + awful.placement.top_right(w, { margins = {top = 25, right = 10}, parent = awful.screen.focused() }) + w.pie.data_list = { + {'used ' .. getPercentage(used + used_swap), used + used_swap}, + {'free ' .. getPercentage(free + free_swap), free + free_swap}, + {'buff_cache ' .. getPercentage(buff_cache), buff_cache} + } + w.pie.display_labels = true + w.visible = not w.visible + end) + ) +) + +return ramgraph_widget diff --git a/awesome-wm-widgets/rhythmbox-widget/rhythmbox.lua b/awesome-wm-widgets/rhythmbox-widget/rhythmbox.lua new file mode 100644 index 0000000..1287587 --- /dev/null +++ b/awesome-wm-widgets/rhythmbox-widget/rhythmbox.lua @@ -0,0 +1,16 @@ +local wibox = require("wibox") +local awful = require("awful") +local watch = require("awful.widget.watch") + +rhythmbox_widget = wibox.widget.textbox() +rhythmbox_widget:set_font('Play 9') + +rhythmbox_icon = wibox.widget.imagebox() +rhythmbox_icon:set_image("/usr/share/icons/Arc/devices/22/audio-speakers.png") + +watch( + "rhythmbox-client --no-start --print-playing", 1, + function(widget, stdout, stderr, exitreason, exitcode) + rhythmbox_widget:set_text(stdout) + end +) \ No newline at end of file diff --git a/awesome-wm-widgets/run-shell/run-shell.lua b/awesome-wm-widgets/run-shell/run-shell.lua new file mode 100644 index 0000000..e46d5a9 --- /dev/null +++ b/awesome-wm-widgets/run-shell/run-shell.lua @@ -0,0 +1,91 @@ +------------------------------------------------- +-- Run Shell for Awesome Window Manager +-- More details could be found here: +-- https://github.com/streetturtle/awesome-wm-widgets/tree/master/run-shell + +-- @author Pavel Makhov +-- @copyright 2018 Pavel Makhov +------------------------------------------------- + +local awful = require("awful") +local gfs = require("gears.filesystem") +local wibox = require("wibox") +local gears = require("gears") +local naughty = require("naughty") +local completion = require("awful.completion") + +local run_shell = awful.widget.prompt() + +local w = wibox { + visible = false, + ontop = true, + height = 1060, + width = 1920 +} + +w:setup { + { + { + { + { + text = '', + font = 'Play 18', + widget = wibox.widget.textbox, + }, + id = 'icon', + top = 9, + left = 10, + layout = wibox.container.margin + }, + { + run_shell, + left = 10, + layout = wibox.container.margin, + }, + id = 'left', + layout = wibox.layout.fixed.horizontal + }, + widget = wibox.container.background, + bg = '#333333', + shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, 3) + end, + shape_border_color = '#74aeab', + shape_border_width = 1, + forced_width = 200, + forced_height = 50 + }, + layout = wibox.container.place +} + +local function launch(s) + awful.spawn.with_line_callback(os.getenv("HOME") .. "/.config/awesome/awesome-wm-widgets/run-shell/scratch_6.sh " .. tostring(awful.screen.focused().geometry.x), { + stdout = function(line) + w.visible = true + w.bgimage = '/tmp/i3lock-' .. line .. '.png' + awful.placement.top(w, { margins = { top = 20 }, parent = awful.screen.focused() }) + awful.prompt.run { + prompt = "Run: ", + bg_cursor = '#74aeab', + textbox = run_shell.widget, + completion_callback = completion.shell, + exe_callback = function(...) + run_shell:spawn_and_handle_error(...) + end, + history_path = gfs.get_cache_dir() .. "/history", + done_callback = function() + -- w.bgimage='' + w.visible = false + awful.spawn([[bash -c 'rm -f /tmp/i3lock*']]) + end + } + end, + stderr = function(line) + naughty.notify { text = "ERR:" .. line } + end, + }) +end + +return { + launch = launch +} diff --git a/awesome-wm-widgets/run-shell/scratch_6.sh b/awesome-wm-widgets/run-shell/scratch_6.sh new file mode 100755 index 0000000..1504a60 --- /dev/null +++ b/awesome-wm-widgets/run-shell/scratch_6.sh @@ -0,0 +1,40 @@ +#!/usr/bin/env bash + +#IMAGE=/tmp/i3lock.png +#SCREENSHOT="scrot -u $IMAGE" # 0.46s +# +## Alternate screenshot method with imagemagick. NOTE: it is much slower +## SCREENSHOT="import -window root $IMAGE" # 1.35s +# +## Here are some imagemagick blur types +## Uncomment one to use, if you have multiple, the last one will be used +# +## All options are here: http://www.imagemagick.org/Usage/blur/#blur_args +##BLURTYPE="0x5" # 7.52s +##BLURTYPE="0x2" # 4.39s +##BLURTYPE="5x2" # 3.80s +#BLURTYPE="2x8" # 2.90s +##BLURTYPE="2x3" # 2.92s +# +## Get the screenshot, add the blur and lock the screen with it +#$SCREENSHOT +#convert $IMAGE -blur $BLURTYPE $IMAGE +#echo 'done' + + +# -------------------------- + +#RES=$(xrandr --current | grep '*' | uniq | awk '{print $1}') +RNDM=$(uuidgen) +IMAGE="/tmp/i3lock-$RNDM.png" + + +#ffmpeg -loglevel panic -f x11grab -video_size 1920x1060 -y -i :0.0+0,20 -filter_complex "boxblur=9" -vframes 1 $IMAGE +#ffmpeg -loglevel panic -f x11grab -video_size 1920x1060 -y -i :0.0+0,20 -vf frei0r=pixeliz0r -vframes 1 $IMAGE +ffmpeg -loglevel panic -f x11grab -video_size 1920x1060 -y -i :0.0+$1,20 -vf frei0r=pixeliz0r -vframes 1 $IMAGE +#ffmpeg -loglevel panic -f x11grab -video_size 1920x1060 -y -i :0.0+0,20 -filter_complex "boxblur=9" -vframes 1 "/tmp/i3lock$(uuidgen).png" + +echo $RNDM + +#lock screen +#ffmpeg -loglevel panic -f x11grab -video_size $(xdpyinfo | grep dimensions | sed -r 's/^[^0-9]*([0-9]+x[0-9]+).*$/\1/') -y -i :0.0+$1,20 -vf frei0r=pixeliz0r -vframes 1 /tmp/test.png ; i3lock -i /tmp/test.png diff --git a/awesome-wm-widgets/screenshot.png b/awesome-wm-widgets/screenshot.png new file mode 100644 index 0000000..9406ebf Binary files /dev/null and b/awesome-wm-widgets/screenshot.png differ diff --git a/awesome-wm-widgets/screenshot_with_sprtrs.png b/awesome-wm-widgets/screenshot_with_sprtrs.png new file mode 100644 index 0000000..361d5a2 Binary files /dev/null and b/awesome-wm-widgets/screenshot_with_sprtrs.png differ diff --git a/awesome-wm-widgets/secrets.lua b/awesome-wm-widgets/secrets.lua new file mode 100644 index 0000000..8ce0cb0 --- /dev/null +++ b/awesome-wm-widgets/secrets.lua @@ -0,0 +1,15 @@ +------------------------------------------------- +-- Allows to store API keys in one place +-- +-- @author Pavel Makhov +-- @copyright 2018 Pavel Makhov +-------------------------------------------- + +local secrets = { + -- Yandex.Translate API key - https://tech.yandex.com/translate/ + translate_widget_api_key = '', + -- OpenWeatherMap API key - https://openweathermap.org/appid + weather_widget_api_key = '' +} + +return secrets diff --git a/awesome-wm-widgets/spotify-shell/README.md b/awesome-wm-widgets/spotify-shell/README.md new file mode 100644 index 0000000..4bc9af7 --- /dev/null +++ b/awesome-wm-widgets/spotify-shell/README.md @@ -0,0 +1,73 @@ +# Spotify Shell + + +![demo](./demo.gif) + +## Features + +1. Supports following commands (same as `sp` client): + - `play`/`pause`/`next`; + - any other string will start a search and play the first result for a given search query; + - feh - shows the current artwork with `feh`; + +1. Stores history and allows navigate through it; + +1. Highly customizable + +## Controls + +Keyboard navigation (copied from [`awful.prompt`](https://awesomewm.org/doc/api/libraries/awful.prompt.html) API documentation page): + +| Name | Usage | +|---|---| +| CTRL+A | beginning-of-line | +| CTRL+B | backward-char | +| CTRL+C | cancel | +| CTRL+D | delete-char | +| CTRL+E | end-of-line | +| CTRL+J | accept-line | +| CTRL+M | accept-line | +| CTRL+F | move-cursor-right | +| CTRL+H | backward-delete-char | +| CTRL+K | kill-line | +| CTRL+U | unix-line-discard | +| CTRL+W | unix-word-rubout | +| CTRL+BACKSPAC | unix-word-rubout | +| SHIFT+INSERT | paste | +| HOME | beginning-of-line | +| END | end-of-line | +| CTRL+R | reverse history search, matches any history entry containing search term. | +| CTRL+S | forward history search, matches any history entry containing search term. | +| CTRL+UP | ZSH up line or search, matches any history entry starting with search term. | +| CTRL+DOWN | ZSH down line or search, matches any history entry starting with search term. | +| CTRL+DELETE | delete the currently visible history entry from history file. This does not delete new commands or history entries under user editing. | + + +## Installation + +1. Install [sp](https://gist.github.com/streetturtle/fa6258f3ff7b17747ee3) - CLI client for [Spotify for Linux](https://www.spotify.com/ca-en/download/linux/): + + ```bash + $ sudo git clone https://gist.github.com/fa6258f3ff7b17747ee3.git ~/dev/ + $ sudo ln -s ~/dev/sp /usr/local/bin/ + ``` + + Check if it works by running `sp help`. + +1. Get an 'id' and 'secret' from [developer.spotify.com](https://beta.developer.spotify.com/documentation/general/guides/app-settings/) and paste it in the header of the `sp` (`SP_ID` and `SP_SECRET`) - this enables search feature. + +1. Clone this repo under **~/.config/awesome/** + +1. Require spotify-shell at the beginning of **rc.lua**: + + ```lua + local spotify_shell = require("awesome-wm-widgets.spotify-shell.spotify-shell") + ``` + +1. Add a shortcut which will show Spotify Shell widget: + + ```lua + awful.key({ modkey, }, "d", function () spotify_shell.launch() end, {description = "spotify shell", group = "music"}), + ``` + +1. It uses icon from [Papirus Icon Theme](https://github.com/PapirusDevelopmentTeam/papirus-icon-theme). So you should either install this icon theme, or download an icon you want to use and provide path to it in **spotify-shell.lua**. diff --git a/awesome-wm-widgets/spotify-shell/demo.gif b/awesome-wm-widgets/spotify-shell/demo.gif new file mode 100644 index 0000000..6696b3a Binary files /dev/null and b/awesome-wm-widgets/spotify-shell/demo.gif differ diff --git a/awesome-wm-widgets/spotify-shell/spotify-shell.lua b/awesome-wm-widgets/spotify-shell/spotify-shell.lua new file mode 100644 index 0000000..0611e66 --- /dev/null +++ b/awesome-wm-widgets/spotify-shell/spotify-shell.lua @@ -0,0 +1,75 @@ +------------------------------------------------- +-- Spotify Shell for Awesome Window Manager +-- Simplifies interaction with Spotify for Linux +-- More details could be found here: +-- https://github.com/streetturtle/awesome-wm-widgets/tree/master/spotify-shell + +-- @author Pavel Makhov +-- @copyright 2018 Pavel Makhov +------------------------------------------------- + +local awful = require("awful") +local gfs = require("gears.filesystem") +local wibox = require("wibox") +local gears = require("gears") + +local ICON = '/usr/share/icons/Papirus-Light/32x32/apps/spotify-linux-48x48.svg' + +local spotify_shell = awful.widget.prompt() + +local w = wibox { + bg = '#1e252c', + border_width = 1, + border_color = '#84bd00', + max_widget_size = 500, + ontop = true, + height = 50, + width = 250, + shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, 3) + end +} + +w:setup { + { + { + image = ICON, + widget = wibox.widget.imagebox, + resize = false + }, + id = 'icon', + top = 9, + left = 10, + layout = wibox.container.margin + }, + { + layout = wibox.container.margin, + left = 10, + spotify_shell, + }, + id = 'left', + layout = wibox.layout.fixed.horizontal +} + +local function launch() + w.visible = true + + awful.placement.top(w, { margins = {top = 40}, parent = awful.screen.focused()}) + awful.prompt.run{ + prompt = "Spotify Shell: ", + bg_cursor = '#84bd00', + textbox = spotify_shell.widget, + history_path = gfs.get_dir('cache') .. '/spotify_history', + exe_callback = function(input_text) + if not input_text or #input_text == 0 then return end + awful.spawn("sp " .. input_text) + end, + done_callback = function() + w.visible = false + end + } +end + +return { + launch = launch +} diff --git a/awesome-wm-widgets/spotify-widget/README.md b/awesome-wm-widgets/spotify-widget/README.md new file mode 100644 index 0000000..eff3027 --- /dev/null +++ b/awesome-wm-widgets/spotify-widget/README.md @@ -0,0 +1,33 @@ +# Spotify widget + +This widget displays currently playing song on [Spotify for Linux](https://www.spotify.com/download/linux/) client: ![screenshot](./spo-wid-1.png) and consists of two parts: + + - status icon which shows if music is currently playing + - artist and name of the current song playing + +## Controls + + - left click - play/pause + - scroll up - play next song + - scroll down - play previous song + +## Dependencies + +Note that widget uses the Arc icon theme, so it should be [installed](https://github.com/horst3180/arc-icon-theme#installation) first under **/usr/share/icons/Arc/** folder. + +## Installation + +First you need to have spotify CLI installed. Here is how you can do it (except widget part): [pavelmakhov.com/2016/02/awesome-wm-spotify](http://pavelmakhov.com/2016/02/awesome-wm-spotify) + +To use this widget clone repo under **~/.config/awesome/** and then add it in **rc.lua**: + +```lua +local spotify_widget = require("awesome-wm-widgets.spotify-widget.spotify") +... +s.mytasklist, -- Middle widget + { -- Right widgets + layout = wibox.layout.fixed.horizontal, + ... + spotify_widget, + ... +``` diff --git a/awesome-wm-widgets/spotify-widget/spo-wid-1.png b/awesome-wm-widgets/spotify-widget/spo-wid-1.png new file mode 100644 index 0000000..296c2f6 Binary files /dev/null and b/awesome-wm-widgets/spotify-widget/spo-wid-1.png differ diff --git a/awesome-wm-widgets/spotify-widget/spotify.lua b/awesome-wm-widgets/spotify-widget/spotify.lua new file mode 100644 index 0000000..c6f2188 --- /dev/null +++ b/awesome-wm-widgets/spotify-widget/spotify.lua @@ -0,0 +1,72 @@ +------------------------------------------------- +-- Spotify Widget for Awesome Window Manager +-- Shows currently playing song on Spotify for Linux client +-- More details could be found here: +-- https://github.com/streetturtle/awesome-wm-widgets/tree/master/spotify-widget + +-- @author Pavel Makhov +-- @copyright 2018 Pavel Makhov +------------------------------------------------- + +local awful = require("awful") +local wibox = require("wibox") +local watch = require("awful.widget.watch") + +local GET_SPOTIFY_STATUS_CMD = 'sp status' +local GET_CURRENT_SONG_CMD = 'sp current-oneline' +local PATH_TO_ICONS = "/usr/share/icons/Arc" + +local spotify_widget = wibox.widget { + { + id = "icon", + widget = wibox.widget.imagebox, + }, + { + id = 'current_song', + widget = wibox.widget.textbox, + font = 'Play 9' + }, + layout = wibox.layout.align.horizontal, + set_status = function(self, is_playing) + self.icon.image = PATH_TO_ICONS .. + (is_playing and "/actions/24/player_play.png" + or "/actions/24/player_pause.png") + end, + set_text = function(self, path) + self.current_song.markup = path + end, +} + +local update_widget_icon = function(widget, stdout, _, _, _) + stdout = string.gsub(stdout, "\n", "") + widget:set_status(stdout == 'Playing' and true or false) +end + +local update_widget_text = function(widget, stdout, _, _, _) + if string.find(stdout, 'Error: Spotify is not running.') ~= nil then + widget:set_text('') + widget:set_visible(false) + else + widget:set_text(stdout) + widget:set_visible(true) + end +end + +watch(GET_SPOTIFY_STATUS_CMD, 1, update_widget_icon, spotify_widget) +watch(GET_CURRENT_SONG_CMD, 1, update_widget_text, spotify_widget) + +--- Adds mouse controls to the widget: +-- - left click - play/pause +-- - scroll up - play next song +-- - scroll down - play previous song +spotify_widget:connect_signal("button::press", function(_, _, _, button) + if (button == 1) then awful.spawn("sp play", false) -- left click + elseif (button == 4) then awful.spawn("sp next", false) -- scroll up + elseif (button == 5) then awful.spawn("sp prev", false) -- scroll down + end + awful.spawn.easy_async(GET_SPOTIFY_STATUS_CMD, function(stdout, stderr, exitreason, exitcode) + update_widget_icon(spotify_widget, stdout, stderr, exitreason, exitcode) + end) +end) + +return spotify_widget diff --git a/awesome-wm-widgets/translate-widget/README.MD b/awesome-wm-widgets/translate-widget/README.MD new file mode 100644 index 0000000..dcc603f --- /dev/null +++ b/awesome-wm-widgets/translate-widget/README.MD @@ -0,0 +1,28 @@ +# Translate Widget + +This widget allows quickly translate words or phrases without opening a browser - just using Awesome. To provide direction of the translation add the 2 letters code of the source and target languages at the end of the phrase, for example _hello enfr_ will translate _hello_ from English to French. This widget is based on [Yandex.Translate API](https://tech.yandex.com/translate/). + +![demo](./demo.gif) + +## Controls + + - Mod4 + c - opens a translate prompt; + - left click on the popup widget - copies the translation to the clipboard and closes widget; + - right click on the popup widget - copies text to translate to the clipboard and closes widget. + +## Installation + +1. Clone repo under **~/.config/awesome/** +1. Get an [API key](https://translate.yandex.com/developers/keys) and paste it in **translate.lua** as value of the `API_KEY` variable +1. Require widget in **rc.lua**: + + ```lua + local translate = require("awesome-wm-widgets.translate-widget.translate") + ``` + +1. Add a shortcut to run translate prompt: + + ```lua + awful.key({ modkey }, "c", function() translate.show_translate_prompt() end, { description = "run translate prompt", group = "launcher" }), + ``` + diff --git a/awesome-wm-widgets/translate-widget/demo.gif b/awesome-wm-widgets/translate-widget/demo.gif new file mode 100644 index 0000000..3645d47 Binary files /dev/null and b/awesome-wm-widgets/translate-widget/demo.gif differ diff --git a/awesome-wm-widgets/translate-widget/demo1.gif b/awesome-wm-widgets/translate-widget/demo1.gif new file mode 100644 index 0000000..62cc9f4 Binary files /dev/null and b/awesome-wm-widgets/translate-widget/demo1.gif differ diff --git a/awesome-wm-widgets/translate-widget/translate.lua b/awesome-wm-widgets/translate-widget/translate.lua new file mode 100644 index 0000000..fe242b4 --- /dev/null +++ b/awesome-wm-widgets/translate-widget/translate.lua @@ -0,0 +1,196 @@ +------------------------------------------------- +-- Translate Widget based on the Yandex.Translate API +-- https://tech.yandex.com/translate/ + +-- @author Pavel Makhov +-- @copyright 2018 Pavel Makhov +------------------------------------------------- + +local awful = require("awful") +local capi = {keygrabber = keygrabber } +local https = require("ssl.https") +local json = require("json") +local naughty = require("naughty") +local wibox = require("wibox") +local gears = require("gears") +local gfs = require("gears.filesystem") + +local API_KEY = '' +local BASE_URL = 'https://translate.yandex.net/api/v1.5/tr.json/translate' +local ICON = '/usr/share/icons/Papirus-Dark/48x48/apps/gnome-translate.svg' + +--- Returns two values - string to translate and direction: +-- 'dog enfr' -> 'dog', 'en-fr' +-- @param input_string user's input which consists of +-- text to translate and direction, 'dog enfr' +local function extract(input_string) + local word, lang = input_string:match('^(.+)%s(%a%a%a%a)$') + + if word ~= nill and lang ~= nill then + lang = lang:sub(1, 2) .. '-' .. lang:sub(3) + end + return word, lang +end + +--- Simple url encoder - replaces spaces with '+' sign +-- @param url to encode +local function urlencode(url) + if (url) then + url = string.gsub(url, " ", "+") + end + return url +end + +local w = wibox { + width = 300, + border_width = 1, + border_color = '#66ccff', + ontop = true, + expand = true, + bg = '#1e252c', + max_widget_size = 500, + shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, 3) + end + +} + +w:setup { + { + { + image = ICON, + widget = wibox.widget.imagebox, + resize = false + }, + id = 'img', + layout = wibox.container.margin(_, 0, 0, 10) + }, + { + { + id = 'header', + widget = wibox.widget.textbox + }, + { + id = 'src', + widget = wibox.widget.textbox + }, + { + id = 'res', + widget = wibox.widget.textbox + }, + id = 'text', + layout = wibox.layout.fixed.vertical, + }, + id = 'left', + layout = wibox.layout.fixed.horizontal +} + +--- Main function - takes the user input and shows the widget with translation +-- @param request_string - user input (dog enfr) +local function translate(to_translate, lang) + local urll = BASE_URL .. '?lang=' .. lang .. '&text=' .. urlencode(to_translate) .. '&key=' .. API_KEY + + local resp_json, code = https.request(urll) + if (code == 200 and resp_json ~= nil) then + local resp = json.decode(resp_json).text[1] + + w.left.text.header:set_markup('' .. lang .. '') + w.left.text.src:set_markup('' .. lang:sub(1,2) .. ': ' .. to_translate .. '') + w.left.text.res:set_markup('' .. lang:sub(4) .. ': ' .. resp .. '') + + awful.placement.top(w, { margins = {top = 40}}) + + local h1 = w.left.text.header:get_height_for_width(w.width, w.screen) + local h2 = w.left.text.src:get_height_for_width(w.width, w.screen) + local h3 = w.left.text.res:get_height_for_width(w.width, w.screen) + + -- calculate height of the widget + w.height = h1 + h2 + h3 + 20 + -- try to vetrtically align the icon + w.left.img:set_top((h1 + h2 + h3 + 20 - 48)/2) + + w.visible = true + w:buttons( + awful.util.table.join( + awful.button({}, 1, function() + awful.spawn.with_shell("echo '" .. resp .. "' | xclip -selection clipboard") + w.visible = false + end), + awful.button({}, 3, function() + awful.spawn.with_shell("echo '" .. to_translate .."' | xclip -selection clipboard") + w.visible = false + end) + ) + ) + + capi.keygrabber.run(function(_, key, event) + if event == "release" then return end + if key then + capi.keygrabber.stop() + w.visible = false + end + end) + else + naughty.notify({ + preset = naughty.config.presets.critical, + title = 'Translate Widget Error', + text = resp_json, + }) + end +end + +local input_widget = wibox { + width = 300, + ontop = true, + screen = mouse.screen, + expand = true, + bg = '#1e252c', + max_widget_size = 500, + border_width = 1; + border_width = 1, + border_color = '#66ccff', + shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, 3) + end +} + +local prompt = awful.widget.prompt() + +input_widget:setup { + layout = wibox.container.margin, + prompt, + left = 10 +} + +local function show_translate_prompt() + awful.placement.top(input_widget, { margins = {top = 40}, parent = awful.screen.focused()}) + input_widget.height = 40 + input_widget.visible = true + + awful.prompt.run { + prompt = "Translate: ", + textbox = prompt.widget, + history_path = gfs.get_dir('cache') .. '/translate_history', + bg_cursor = '#66ccff', + exe_callback = function(text) + if not text or #text == 0 then return end + local to_translate, lang = extract(text) + if not to_translate or #to_translate==0 or not lang or #lang == 0 then + naughty.notify({ + preset = naughty.config.presets.critical, + title = 'Translate Widget Error', + text = 'Language is not provided', + }) + return + end + translate(to_translate, lang) + end, + done_callback = function() + input_widget.visible = false + end + } +end + +return { + show_translate_prompt = show_translate_prompt +} diff --git a/awesome-wm-widgets/volume-widget/README.md b/awesome-wm-widgets/volume-widget/README.md new file mode 100644 index 0000000..118abc6 --- /dev/null +++ b/awesome-wm-widgets/volume-widget/README.md @@ -0,0 +1,44 @@ +# Volume widget + +Simple and easy-to-install widget for Awesome Window Manager which represents the sound level: ![Volume Widget]( +./vol-widget-1.png) + +Note that widget uses the Arc icon theme, so it should be [installed](https://github.com/horst3180/arc-icon-theme#installation) first under **/usr/share/icons/Arc/** folder. + +## Installation + +- clone/copy **volume.lua** file; + +- include `volume.lua` and add volume widget to your wibox in rc.lua: + +```lua +require("volume") +... +s.mytasklist, -- Middle widget + { -- Right widgets + layout = wibox.layout.fixed.horizontal, + ... + volume_widget, + ... +``` + +- _Optional step._ In Arc icon theme the muted audio level icon (![Volume-widget](./audio-volume-muted-symbolic.png)) looks like 0 level icon, which could be a bit misleading. + So I decided to use original muted icon for low audio level, and the same icon, but colored in red for muted audio level. Fortunately icons are in svg format, so you can easily recolor them with `sed`, so it would look like this (![Volume Widget](./audio-volume-muted-symbolic_red.png)): + + ```bash + cd /usr/share/icons/Arc/status/symbolic && + sudo cp audio-volume-muted-symbolic.svg audio-volume-muted-symbolic_red.svg && + sudo sed -i 's/bebebe/ed4737/g' ./audio-volume-muted-symbolic_red.svg + ``` + +## Control volume + +To mute/unmute click on the widget. To increase/decrease volume scroll up or down when mouse cursor is over the widget. + +If you want to control volume level by keyboard shortcuts add following lines in shortcut section of the **rc.lua** (the commands could be slightly different depending on your PC configuration): + +```lua +awful.key({ modkey}, "[", function () awful.spawn("amixer -D pulse sset Master 5%+") end, {description = "increase volume", group = "custom"}), +awful.key({ modkey}, "]", function () awful.spawn("amixer -D pulse sset Master 5%-") end, {description = "decrease volume", group = "custom"}), +awful.key({ modkey}, "\", function () awful.spawn("amixer -D pulse set Master +1 toggle") end, {description = "mute volume", group = "custom"}), +``` diff --git a/awesome-wm-widgets/volume-widget/audio-volume-muted-symbolic.png b/awesome-wm-widgets/volume-widget/audio-volume-muted-symbolic.png new file mode 100644 index 0000000..b9dffd6 Binary files /dev/null and b/awesome-wm-widgets/volume-widget/audio-volume-muted-symbolic.png differ diff --git a/awesome-wm-widgets/volume-widget/audio-volume-muted-symbolic.svg b/awesome-wm-widgets/volume-widget/audio-volume-muted-symbolic.svg new file mode 100644 index 0000000..e577d05 --- /dev/null +++ b/awesome-wm-widgets/volume-widget/audio-volume-muted-symbolic.svg @@ -0,0 +1,88 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + diff --git a/awesome-wm-widgets/volume-widget/audio-volume-muted-symbolic_new.svg b/awesome-wm-widgets/volume-widget/audio-volume-muted-symbolic_new.svg new file mode 100644 index 0000000..504c146 --- /dev/null +++ b/awesome-wm-widgets/volume-widget/audio-volume-muted-symbolic_new.svg @@ -0,0 +1,81 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + diff --git a/awesome-wm-widgets/volume-widget/audio-volume-muted-symbolic_red.png b/awesome-wm-widgets/volume-widget/audio-volume-muted-symbolic_red.png new file mode 100644 index 0000000..f47807d Binary files /dev/null and b/awesome-wm-widgets/volume-widget/audio-volume-muted-symbolic_red.png differ diff --git a/awesome-wm-widgets/volume-widget/audio-volume-muted-symbolic_red.svg b/awesome-wm-widgets/volume-widget/audio-volume-muted-symbolic_red.svg new file mode 100644 index 0000000..d42c2ba --- /dev/null +++ b/awesome-wm-widgets/volume-widget/audio-volume-muted-symbolic_red.svg @@ -0,0 +1,88 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + diff --git a/awesome-wm-widgets/volume-widget/vol-widget-1.png b/awesome-wm-widgets/volume-widget/vol-widget-1.png new file mode 100644 index 0000000..6f09cce Binary files /dev/null and b/awesome-wm-widgets/volume-widget/vol-widget-1.png differ diff --git a/awesome-wm-widgets/volume-widget/volume.lua b/awesome-wm-widgets/volume-widget/volume.lua new file mode 100644 index 0000000..8124bcf --- /dev/null +++ b/awesome-wm-widgets/volume-widget/volume.lua @@ -0,0 +1,67 @@ +------------------------------------------------- +-- Volume Widget for Awesome Window Manager +-- Shows the current volume level +-- More details could be found here: +-- https://github.com/streetturtle/awesome-wm-widgets/tree/master/volume-widget + +-- @author Pavel Makhov +-- @copyright 2018 Pavel Makhov +------------------------------------------------- + +local awful = require("awful") +local wibox = require("wibox") +local watch = require("awful.widget.watch") +local spawn = require("awful.spawn") + +local path_to_icons = "/usr/share/icons/Arc/status/symbolic/" + +local GET_VOLUME_CMD = 'amixer -D pulse sget Master' +local INC_VOLUME_CMD = 'amixer -D pulse sset Master 5%+' +local DEC_VOLUME_CMD = 'amixer -D pulse sset Master 5%-' +local TOG_VOLUME_CMD = 'amixer -D pulse sset Master toggle' + +local volume_widget = wibox.widget { + { + id = "icon", + image = path_to_icons .. "audio-volume-muted-symbolic.svg", + resize = false, + widget = wibox.widget.imagebox, + }, + layout = wibox.container.margin(_, _, _, 3), + set_image = function(self, path) + self.icon.image = path + end +} + +local update_graphic = function(widget, stdout, _, _, _) + local mute = string.match(stdout, "%[(o%D%D?)%]") + local volume = string.match(stdout, "(%d?%d?%d)%%") + volume = tonumber(string.format("% 3d", volume)) + local volume_icon_name + if mute == "off" then volume_icon_name="audio-volume-muted-symbolic_red" + elseif (volume >= 0 and volume < 25) then volume_icon_name="audio-volume-muted-symbolic" + elseif (volume < 50) then volume_icon_name="audio-volume-low-symbolic" + elseif (volume < 75) then volume_icon_name="audio-volume-medium-symbolic" + elseif (volume <= 100) then volume_icon_name="audio-volume-high-symbolic" + end + widget.image = path_to_icons .. volume_icon_name .. ".svg" +end + +--[[ allows control volume level by: +- clicking on the widget to mute/unmute +- scrolling when cursor is over the widget +]] +volume_widget:connect_signal("button::press", function(_,_,_,button) + if (button == 4) then awful.spawn(INC_VOLUME_CMD, false) + elseif (button == 5) then awful.spawn(DEC_VOLUME_CMD, false) + elseif (button == 1) then awful.spawn(TOG_VOLUME_CMD, false) + end + + spawn.easy_async(GET_VOLUME_CMD, function(stdout, stderr, exitreason, exitcode) + update_graphic(volume_widget, stdout, stderr, exitreason, exitcode) + end) +end) + +watch(GET_VOLUME_CMD, 1, update_graphic, volume_widget) + +return volume_widget \ No newline at end of file diff --git a/awesome-wm-widgets/volumearc-widget/README.md b/awesome-wm-widgets/volumearc-widget/README.md new file mode 100644 index 0000000..702b486 --- /dev/null +++ b/awesome-wm-widgets/volumearc-widget/README.md @@ -0,0 +1,25 @@ +# Volumearc widget + +Almost the same as [volumebar widget](https://github.com/streetturtle/awesome-wm-widgets/tree/master/volumebar-widget), but using arcchart: + +![screenshot](out.gif) + +Supports: + - scroll up - increase volume, + - scroll down - decrease volume, + - left click - mute/unmute. + +## Installation + +Clone repo, include widget and use it in **rc.lua**: + +```lua +require("volumearc") +... +s.mytasklist, -- Middle widget + { -- Right widgets + layout = wibox.layout.fixed.horizontal, + ... + volumearc_widget, + ... +``` diff --git a/awesome-wm-widgets/volumearc-widget/out.gif b/awesome-wm-widgets/volumearc-widget/out.gif new file mode 100644 index 0000000..61fa486 Binary files /dev/null and b/awesome-wm-widgets/volumearc-widget/out.gif differ diff --git a/awesome-wm-widgets/volumearc-widget/volumearc.lua b/awesome-wm-widgets/volumearc-widget/volumearc.lua new file mode 100644 index 0000000..9cd7865 --- /dev/null +++ b/awesome-wm-widgets/volumearc-widget/volumearc.lua @@ -0,0 +1,59 @@ +------------------------------------------------- +-- Volume Arc Widget for Awesome Window Manager +-- Shows the current volume level +-- More details could be found here: +-- https://github.com/streetturtle/awesome-wm-widgets/tree/master/volumearc-widget + +-- @author Pavel Makhov +-- @copyright 2018 Pavel Makhov +------------------------------------------------- + +local awful = require("awful") +local beautiful = require("beautiful") +local spawn = require("awful.spawn") +local watch = require("awful.widget.watch") +local wibox = require("wibox") + +local GET_VOLUME_CMD = 'amixer -D pulse sget Master' +local INC_VOLUME_CMD = 'amixer -D pulse sset Master 5%+' +local DEC_VOLUME_CMD = 'amixer -D pulse sset Master 5%-' +local TOG_VOLUME_CMD = 'amixer -D pulse sset Master toggle' + +local volumearc = wibox.widget { + max_value = 1, + thickness = 2, + start_angle = 4.71238898, -- 2pi*3/4 + forced_height = 17, + forced_width = 17, + bg = "#ffffff11", + paddings = 2, + widget = wibox.container.arcchart +} + +local volumearc_widget = wibox.container.mirror(volumearc, { horizontal = true }) + +local update_graphic = function(widget, stdout, _, _, _) + local mute = string.match(stdout, "%[(o%D%D?)%]") + local volume = string.match(stdout, "(%d?%d?%d)%%") + volume = tonumber(string.format("% 3d", volume)) + + widget.value = volume / 100; + widget.colors = mute == 'off' and { beautiful.widget_red } + or { beautiful.widget_main_color } + +end + +volumearc:connect_signal("button::press", function(_, _, _, button) + if (button == 4) then awful.spawn(INC_VOLUME_CMD, false) + elseif (button == 5) then awful.spawn(DEC_VOLUME_CMD, false) + elseif (button == 1) then awful.spawn(TOG_VOLUME_CMD, false) + end + + spawn.easy_async(GET_VOLUME_CMD, function(stdout, stderr, exitreason, exitcode) + update_graphic(volumearc, stdout, stderr, exitreason, exitcode) + end) +end) + +watch(GET_VOLUME_CMD, 1, update_graphic, volumearc) + +return volumearc_widget \ No newline at end of file diff --git a/awesome-wm-widgets/volumebar-widget/README.md b/awesome-wm-widgets/volumebar-widget/README.md new file mode 100644 index 0000000..2198f6d --- /dev/null +++ b/awesome-wm-widgets/volumebar-widget/README.md @@ -0,0 +1,29 @@ +# Volumebar widget + +Almost the same as volume widget, but more minimalistic: + +![screenshot](out.gif) + +Supports + - scroll up - increase volume, + - scroll down - decrease volume, + - left click - mute/unmute. + + ## Installation + + Clone repo, include widget and use it in **rc.lua**: + + ```lua + require("volumebar") +... +s.mytasklist, -- Middle widget + { -- Right widgets + layout = wibox.layout.fixed.horizontal, + ... + volumebar_widget, + ... + ``` + +## Troubleshooting + +If the bar is not showing up, try to decrease top or bottom margin - widget uses hardcoded margins for vertical alignment, so if your wibox is too small then bar is simply hidden by the margins. diff --git a/awesome-wm-widgets/volumebar-widget/out.gif b/awesome-wm-widgets/volumebar-widget/out.gif new file mode 100644 index 0000000..16653c8 Binary files /dev/null and b/awesome-wm-widgets/volumebar-widget/out.gif differ diff --git a/awesome-wm-widgets/volumebar-widget/volumebar.lua b/awesome-wm-widgets/volumebar-widget/volumebar.lua new file mode 100644 index 0000000..9685ce7 --- /dev/null +++ b/awesome-wm-widgets/volumebar-widget/volumebar.lua @@ -0,0 +1,66 @@ +------------------------------------------------- +-- Volume Bar Widget for Awesome Window Manager +-- Shows the current volume level +-- More details could be found here: +-- https://github.com/streetturtle/awesome-wm-widgets/tree/master/volumebar-widget + +-- @author Pavel Makhov +-- @copyright 2018 Pavel Makhov +------------------------------------------------- + +local awful = require("awful") +local gears = require("gears") +local spawn = require("awful.spawn") +local watch = require("awful.widget.watch") +local wibox = require("wibox") + +local GET_VOLUME_CMD = 'amixer sget Master' +local INC_VOLUME_CMD = 'amixer sset Master 5%+' +local DEC_VOLUME_CMD = 'amixer sset Master 5%-' +local TOG_VOLUME_CMD = 'amixer sset Master toggle' + +local bar_color = "#74aeab" +local mute_color = "#ff0000" +local background_color = "#3a3a3a" + +local volumebar_widget = wibox.widget { + max_value = 1, + forced_width = 50, + paddings = 0, + border_width = 0.5, + color = bar_color, + background_color = background_color, + shape = gears.shape.bar, + clip = true, + margins = { + top = 8, + bottom = 8, + }, + widget = wibox.widget.progressbar +} + +local update_graphic = function(widget, stdout, _, _, _) + local mute = string.match(stdout, "%[(o%D%D?)%]") + local volume = string.match(stdout, "(%d?%d?%d)%%") + volume = tonumber(string.format("% 3d", volume)) + + widget.value = volume / 100; + widget.color = mute == "off" and mute_color + or bar_color + +end + +volumebar_widget:connect_signal("button::press", function(_,_,_,button) + if (button == 4) then awful.spawn(INC_VOLUME_CMD) + elseif (button == 5) then awful.spawn(DEC_VOLUME_CMD) + elseif (button == 1) then awful.spawn(TOG_VOLUME_CMD) + end + + spawn.easy_async(GET_VOLUME_CMD, function(stdout, stderr, exitreason, exitcode) + update_graphic(volumebar_widget, stdout, stderr, exitreason, exitcode) + end) +end) + +watch(GET_VOLUME_CMD, 1, update_graphic, volumebar_widget) + +return volumebar_widget diff --git a/awesome-wm-widgets/weather-widget/README.md b/awesome-wm-widgets/weather-widget/README.md new file mode 100644 index 0000000..7573cff --- /dev/null +++ b/awesome-wm-widgets/weather-widget/README.md @@ -0,0 +1,17 @@ +# Weather widget + +![Weather Widget](./weather-widget.png) + +Note that widget uses the Arc icon theme, so it should be [installed](https://github.com/horst3180/arc-icon-theme#installation) first under **/usr/share/icons/Arc/** folder. + +## Installation + + - install lua socket +```bash +$ sudo apt-get install lua-socket +``` + + - download json parser for lua: https://github.com/rxi/json.lua + - get Open Weather Map app id here: https://openweathermap.org/appid + +You can read how it works in more details [here](http://pavelmakhov.com/2017/02/weather-widget-for-awesome-wm) diff --git a/awesome-wm-widgets/weather-widget/weather-widget.png b/awesome-wm-widgets/weather-widget/weather-widget.png new file mode 100644 index 0000000..177b350 Binary files /dev/null and b/awesome-wm-widgets/weather-widget/weather-widget.png differ diff --git a/awesome-wm-widgets/weather-widget/weather.lua b/awesome-wm-widgets/weather-widget/weather.lua new file mode 100644 index 0000000..88d3658 --- /dev/null +++ b/awesome-wm-widgets/weather-widget/weather.lua @@ -0,0 +1,132 @@ +------------------------------------------------- +-- Weather Widget based on the OpenWeatherMap +-- https://openweathermap.org/ +-- +-- @author Pavel Makhov +-- @copyright 2018 Pavel Makhov +------------------------------------------------- + +local http = require("socket.http") +local json = require("json") +local naughty = require("naughty") +local wibox = require("wibox") + +local city = os.getenv("AWW_WEATHER_CITY") or "Montreal,ca" +local open_map_key = os.getenv("AWW_WEATHER_API_KEY") or 'c3d7320b359da4e48c2d682a04076576' +local path_to_icons = "/usr/share/icons/Arc/status/symbolic/" + +local icon_widget = wibox.widget { + { + id = "icon", + resize = false, + widget = wibox.widget.imagebox, + }, + layout = wibox.container.margin(_ , 0, 0, 3), + set_image = function(self, path) + self.icon.image = path + end, +} + +local temp_widget = wibox.widget{ + font = "Play 9", + widget = wibox.widget.textbox, +} + +local weather_widget = wibox.widget { + icon_widget, + temp_widget, + layout = wibox.layout.fixed.horizontal, +} + +--- Maps openWeatherMap icons to Arc icons +local icon_map = { + ["01d"] = "weather-clear-symbolic.svg", + ["02d"] = "weather-few-clouds-symbolic.svg", + ["03d"] = "weather-clouds-symbolic.svg", + ["04d"] = "weather-overcast-symbolic.svg", + ["09d"] = "weather-showers-scattered-symbolic.svg", + ["10d"] = "weather-showers-symbolic.svg", + ["11d"] = "weather-storm-symbolic.svg", + ["13d"] = "weather-snow-symbolic.svg", + ["50d"] = "weather-fog-symbolic.svg", + ["01n"] = "weather-clear-night-symbolic.svg", + ["02n"] = "weather-few-clouds-night-symbolic.svg", + ["03n"] = "weather-clouds-night-symbolic.svg", + ["04n"] = "weather-overcast-symbolic.svg", + ["09n"] = "weather-showers-scattered-symbolic.svg", + ["10n"] = "weather-showers-symbolic.svg", + ["11n"] = "weather-storm-symbolic.svg", + ["13n"] = "weather-snow-symbolic.svg", + ["50n"] = "weather-fog-symbolic.svg" +} + +--- handy function to convert temperature from Kelvin to Celcius +function to_celcius(kelvin) + return math.floor(tonumber(kelvin) - 273.15) +end + +--- Return wind direction as a string. +function to_direction(degrees) + -- Ref: https://www.campbellsci.eu/blog/convert-wind-directions + if degrees == nil then + return "Unknown dir" + end + local directions = { + "N", + "NNE", + "NE", + "ENE", + "E", + "ESE", + "SE", + "SSE", + "S", + "SSW", + "SW", + "WSW", + "W", + "WNW", + "NW", + "NNW", + "N", + } + return directions[math.floor((degrees % 360) / 22.5) + 1] +end + +local weather_timer = timer({ timeout = 60 }) +local resp + +weather_timer:connect_signal("timeout", function () + local resp_json = http.request("https://api.openweathermap.org/data/2.5/weather?q=" .. city .."&appid=" .. open_map_key) + if (resp_json ~= nil) then + resp = json.decode(resp_json) + icon_widget.image = path_to_icons .. icon_map[resp.weather[1].icon] + temp_widget:set_text(to_celcius(resp.main.temp) .. "°C") + end +end) +weather_timer:start() +weather_timer:emit_signal("timeout") + +--- Notification with weather information. Popups when mouse hovers over the icon +local notification +weather_widget:connect_signal("mouse::enter", function() + notification = naughty.notify{ + icon = path_to_icons .. icon_map[resp.weather[1].icon], + icon_size=20, + text = + '' .. resp.weather[1].main .. ' (' .. resp.weather[1].description .. ')
' .. + 'Humidity: ' .. resp.main.humidity .. '%
' .. + 'Temperature: ' .. to_celcius(resp.main.temp) .. '
' .. + 'Pressure: ' .. resp.main.pressure .. 'hPa
' .. + 'Clouds: ' .. resp.clouds.all .. '%
' .. + 'Wind: ' .. resp.wind.speed .. 'm/s (' .. to_direction(resp.wind.deg) .. ')', + timeout = 5, hover_timeout = 10, + width = 200 + } +end) + +weather_widget:connect_signal("mouse::leave", function() + naughty.destroy(notification) +end) + +return weather_widget diff --git a/rc.lua b/rc.lua index 2a7ae86..a9a7056 100644 --- a/rc.lua +++ b/rc.lua @@ -13,6 +13,11 @@ local beautiful = require("beautiful") local naughty = require("naughty") local menubar = require("menubar") local hotkeys_popup = require("awful.hotkeys_popup").widget +local volume_widget = require("awesome-wm-widgets.volume-widget.volume") +local volume_bar_widget = require("awesome-wm-widgets.volumebar-widget.volumebar") +local cpu_widget = require("awesome-wm-widgets.cpu-widget.cpu-widget") +local battery_widget = require("awesome-wm-widgets.battery-widget.battery") +local ram_widget = require("awesome-wm-widgets.ram-widget.ram-widget") -- Custom imports local options = require("options") @@ -201,13 +206,12 @@ local tasklist_buttons = awful.util.table.join( awful.client.focus.byidx(-1) end)) -local battery = require('battery') -local volume = require('volume') local calendar = require('calendar') local launchbar = require('launchbar') local music = require('music') -- local background = require('background_widget') local delimiter = wibox.widget.textbox(" | ") +local delimiter2 = wibox.widget.textbox(" ") local function set_wallpaper(s) -- Wallpaper @@ -268,7 +272,13 @@ awful.screen.connect_for_each_screen(function(s) music.icon_widget, music.text_widget, delimiter, + ram_widget, + delimiter2, + cpu_widget, + delimiter, volume_widget, + delimiter2, + volume_bar_widget, delimiter, battery_widget, delimiter, @@ -398,17 +408,14 @@ globalkeys = awful.util.table.join( -- Custom shortcuts awful.key({ }, "XF86AudioRaiseVolume", function() awful.util.spawn("amixer set Master 3%+", false) - update_volume() end, {description = "increase the volume by 3%", group="custom"}), awful.key({ }, "XF86AudioLowerVolume", function() awful.util.spawn("amixer set Master 3%-", false) - update_volume() end, {description = "decrease the volume by 3%", group="custom"}), awful.key({ }, "XF86AudioMute", function() awful.util.spawn("amixer set Master toggle", false) - update_volume() end, {description = "mute sound", group="custom"}), awful.key({ }, "XF86MonBrightnessDown", function ()