summaryrefslogtreecommitdiff
path: root/volume-widget
diff options
context:
space:
mode:
authorstreetturtle <streetturtle@gmail.com>2021-03-19 20:49:00 -0400
committerstreetturtle <streetturtle@gmail.com>2021-03-19 20:49:00 -0400
commit25d9eecfc68df3251dc96008aaa4cd7c81900da6 (patch)
tree7f0b6a6c125ea622e099e5b569115b80dcad3753 /volume-widget
parenta37e0a673ee3e6655f3d4be2c5a2f6c832476456 (diff)
[volume] BREAKING CHANGE - new widget instead of old ones
Having three widgets for volume led to a problem of code duplication - same logic was duplicated three times. However when an issue was discovered and fixed, it was fixed in only one of three widgets. So I decided to create a volume widget from scratch, adding new features, such as selecting input/output, better responsiveness, easily customizable widget ui (bar, text, icon, icon and text, arc). Should close #199, #198, #185, #182, #47, #122, #183.
Diffstat (limited to 'volume-widget')
-rw-r--r--volume-widget/README.md159
-rw-r--r--volume-widget/audio-volume-muted-symbolic.pngbin435 -> 0 bytes
-rw-r--r--volume-widget/audio-volume-muted-symbolic_red.pngbin450 -> 0 bytes
-rw-r--r--volume-widget/icons/audio-volume-high-symbolic.svg88
-rw-r--r--volume-widget/icons/audio-volume-low-symbolic.svg (renamed from volume-widget/audio-volume-muted-symbolic_red.svg)18
-rw-r--r--volume-widget/icons/audio-volume-medium-symbolic.svg (renamed from volume-widget/audio-volume-muted-symbolic_new.svg)37
-rw-r--r--volume-widget/icons/audio-volume-muted-symbolic.svg (renamed from volume-widget/audio-volume-muted-symbolic.svg)0
-rw-r--r--volume-widget/screenshots/variations.pngbin0 -> 9153 bytes
-rw-r--r--volume-widget/screenshots/volume-sink-sources.pngbin0 -> 74043 bytes
-rw-r--r--volume-widget/utils.lua105
-rw-r--r--volume-widget/vol-widget-1.pngbin824 -> 0 bytes
-rw-r--r--volume-widget/volume-2.svg1
-rw-r--r--volume-widget/volume.lua329
-rw-r--r--volume-widget/widgets/arc-widget.lua46
-rw-r--r--volume-widget/widgets/horizontal-bar-widget.lua58
-rw-r--r--volume-widget/widgets/icon-and-text-widget.lua59
-rw-r--r--volume-widget/widgets/icon-widget.lua46
-rw-r--r--volume-widget/widgets/vertical-bar-widget.lua64
18 files changed, 761 insertions, 249 deletions
diff --git a/volume-widget/README.md b/volume-widget/README.md
index aebcf98..d08b795 100644
--- a/volume-widget/README.md
+++ b/volume-widget/README.md
@@ -1,109 +1,112 @@
# Volume widget
-Simple and easy-to-install widget for Awesome Window Manager which shows the sound level: ![Volume Widget](./vol-widget-1.png)
+Volume widget based on [amixer](https://linux.die.net/man/1/amixer) (is used for controlling the audio volume) and [pacmd](https://linux.die.net/man/1/pacmd) (is used for selecting a sink/source). Also, the widget provides an easy way to customize how it looks, following types are supported out-of-the-box:
-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.
+![types](screenshots/variations.png)
-## Customization
+From left to right: `horizontal_bar`, `vertical_bar`, `icon`, `icon_and_text`, `arc`
-It is possible to customize widget by providing a table with all or some of the following config parameters:
+A right-click on the widget opens a popup where you can choose a sink/source:
+![sink-sources](screenshots/volume-sink-sources.png)
-| Name | Default | Description |
-|---|---|---|
-| `volume_audio_controller`| `pulse` | audio device |
-| `display_notification` | `false` | Display a notification on mouseover and keypress |
-| `notification_position` | `top_right`| The notification position |
-| `delta` | 5 | The volume +/- percentage |
+### Features
-## Installation
+ - switch between sinks/sources by right clicking on the widget;
+ - more responsive than previous versions of volume widget, which were refreshed once a second;
+ - 5 predefined customizable looks;
-- clone/copy **volume.lua** file;
+## Installation
-- include `volume.lua` and add volume widget to your wibox in rc.lua:
+Clone the repo under **~/.config/awesome/** and add widget in **rc.lua**:
```lua
-local volume_widget = require("awesome-wm-widgets.volume-widget.volume")
-local volume_widget_widget = volume_widget({display_notification = true})
+local volume_widget = require('awesome-wm-widgets.volume-widget.volume')
...
- s.mytasklist, -- Middle widget
- { -- Right widgets
- ...
- volume_widget_widget,
- ...
-
+s.mytasklist, -- Middle widget
+ { -- Right widgets
+ layout = wibox.layout.fixed.horizontal,
+ ...
+ -- default
+ volume_widget(),
+ -- customized
+ volume_widget{
+ type = 'arc'
+ },
```
-### Control volume
-To mute/unmute click on the widget. To increase/decrease volume scroll up or down when mouse cursor is over the widget.
+### Shortcuts
-If you want to control volume level by keyboard shortcuts add following lines in shortcut section of the **rc.lua**:
-IF you have notification activated, a notification will pop-up on key press
+To improve responsiveness of the widget when volume level is changed by a shortcut use corresponding methods of the widget:
```lua
--- Key bindings
-globalkeys = gears.table.join(
- awful.key(
- {},
- 'XF86AudioRaiseVolume',
- volume_widget.raise,
- {description = 'volume up', group = 'hotkeys'}
- ),
- awful.key(
- {},
- 'XF86AudioLowerVolume',
- volume_widget.lower,
- {description = 'volume down', group = 'hotkeys'}
- ),
- awful.key(
- {},
- 'XF86AudioMute',
- volume_widget.toggle,
- {description = 'toggle mute', group = 'hotkeys'}
- ),
+awful.key({ modkey }, "]", function() volume_widget:inc() end),
+awful.key({ modkey }, "[", function() volume_widget:dec() end),
+awful.key({ modkey }, "\\", function() volume_widget:toggle() end),
```
-### Icons
+## Customization
-- _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)):
+It is possible to customize the widget by providing a table with all or some of the following config parameters:
- ```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
- ```
+### Generic parameter
-### Pulse or ALSA only
+| Name | Default | Description |
+|---|---|---|
+| `type`| `icon_and_text`| Widget type, one of `horizontal_bar`, `vertical_bar`, `icon`, `icon_and_text`, `arc` |
-Try running this command:
+Depending on the chosen widget type add parameters from the corresponding section below:
-```bash
-amixer -D pulse sget Master
-```
+#### `icon` parameters
-If that prints something like this, then the default setting of 'pulse' is probably fine:
+| Name | Default | Description |
+|---|---|---|
+| `icon_dir`| `./icons`| Path to the folder with icons |
-```
-Simple mixer control 'Master',0
- Capabilities: pvolume pvolume-joined pswitch pswitch-joined
- Playback channels: Mono
- Limits: Playback 0 - 64
- Mono: Playback 64 [100%] [0.00dB] [on]
+_Note:_ if you are changing icons, the folder should contain following .svg images:
+ - audio-volume-high-symbolic
+ - audio-volume-medium-symbolic
+ - audio-volume-low-symbolic
+ - audio-volume-muted-symbolic
-```
+#### `icon_and_text` parameters
-If it prints something like this:
+| Name | Default | Description |
+|---|---|---|
+| `icon_dir`| `./icons`| Path to the folder with icons |
+| `font` | `beautiful.font` | Font name and size, like `Play 12` |
-```bash
-$ amixer -D pulse sget Master
-ALSA lib pulse.c:243:(pulse_connect) PulseAudio: Unable to connect: Connection refused
+#### `arc` parameters
-amixer: Mixer attach pulse error: Connection refused
-```
-then set `volume_audio_controller` to `alsa_only` in widget constructor:
+| Name | Default | Description |
+|---|---|---|
+| `thickness` | 2 | Thickness of the arc |
+| `main_color` | `beautiful.fg_color` | Color of the arc |
+| `bg_color` | `#ffffff11` | Color of the arc's background |
+| `mute_color` | `beautiful.fg_urgent` | Color of the arc when mute |
+| `size` | 18 | Size of the widget |
-```lua
-volume_widget({
- volume_audio_controller = 'alsa_only'
-})
-```
+#### `horizontal_bar` parameters
+
+| Name | Default | Description |
+|---|---|---|
+| `main_color` | `beautiful.fg_normal` | Color of the bar |
+| `mute_color` | `beautiful.fg_urgent` | Color of the bar when mute |
+| `bg_color` | `'#ffffff11'` | Color of the bar's background |
+| `width` | `50` | The bar width |
+| `margins` | `10` | Top and bottom margins (if your wibar is 22 px high, bar will be 2 px = 22 - 2*10) |
+| `shape` | `'bar'` | [gears.shape](https://awesomewm.org/doc/api/libraries/gears.shape.html), could be `octogon`, `hexagon`, `powerline`, etc |
+| `with_icon` | `true` | Show volume icon|
+
+_Note:_ I didn't figure out how does the `forced_height` property of progressbar widget work (maybe it doesn't work at all), thus there is a workaround with margins.
+
+#### `vertical_bar` parameters
+
+| Name | Default | Description |
+|---|---|---|
+| `main_color` | `beautiful.fg_normal` | Color of the bar |
+| `mute_color` | `beautiful.fg_urgent` | Color of the bar when mute |
+| `bg_color` | `'#ffffff11'` | Color of the bar's background |
+| `width` | `10` | The bar width |
+| `margins` | `20` | Top and bottom margins (if your wibar is 22 px high, bar will be 2 px = 22 - 2*10) |
+| `shape` | `'bar'` | [gears.shape](https://awesomewm.org/doc/api/libraries/gears.shape.html), could be `octogon`, `hexagon`, `powerline`, etc |
+| `with_icon` | `true` | Show volume icon|
diff --git a/volume-widget/audio-volume-muted-symbolic.png b/volume-widget/audio-volume-muted-symbolic.png
deleted file mode 100644
index b9dffd6..0000000
--- a/volume-widget/audio-volume-muted-symbolic.png
+++ /dev/null
Binary files differ
diff --git a/volume-widget/audio-volume-muted-symbolic_red.png b/volume-widget/audio-volume-muted-symbolic_red.png
deleted file mode 100644
index f47807d..0000000
--- a/volume-widget/audio-volume-muted-symbolic_red.png
+++ /dev/null
Binary files differ
diff --git a/volume-widget/icons/audio-volume-high-symbolic.svg b/volume-widget/icons/audio-volume-high-symbolic.svg
new file mode 100644
index 0000000..985c107
--- /dev/null
+++ b/volume-widget/icons/audio-volume-high-symbolic.svg
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="16"
+ viewBox="0 0 16 16"
+ height="16"
+ id="svg2"
+ version="1.1"
+ inkscape:version="0.91 r"
+ sodipodi:docname="audio-volume-high-symbolic.svg">
+ <metadata
+ id="metadata30">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1215"
+ inkscape:window-height="776"
+ id="namedview28"
+ showgrid="true"
+ inkscape:zoom="38.125"
+ inkscape:cx="8"
+ inkscape:cy="8"
+ inkscape:window-x="65"
+ inkscape:window-y="24"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg2"
+ showguides="true"
+ inkscape:snap-intersection-paths="false"
+ inkscape:object-paths="false">
+ <inkscape:grid
+ type="xygrid"
+ id="grid4158" />
+ </sodipodi:namedview>
+ <defs
+ id="defs4" />
+ <path
+ d="M 6,2 2,6 2,10 6,14 6,9 7,8 6,7 Z"
+ id="path18"
+ inkscape:connector-curvature="0"
+ style="fill:#bebebe"
+ sodipodi:nodetypes="cccccccc" />
+ <path
+ d="M 1.300003,5 C 0.216589,5 0,6.163269 0,7.4 L 0,8.6 C 0,9.836747 0.24312,11 1.300003,11 L 3,11 3,5 Z"
+ id="path20"
+ inkscape:connector-curvature="0"
+ style="fill:#bebebe"
+ sodipodi:nodetypes="ssssccs" />
+ <path
+ style="opacity:1;fill:#bebebe;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 13.140638,1 11.726417,2.413582 C 12.808349,3.4955144 13.990412,5.4467621 14,8 c 0,2.551493 -1.192916,4.505751 -2.273583,5.586418 L 13.140638,15 C 14.595711,13.544927 16.019176,11 16,8 16.035061,5 14.595117,2.4544787 13.140638,1 Z"
+ id="path4508"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccc" />
+ <path
+ style="opacity:1;fill:#bebebe;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 11,3.1156678 9.5897193,4.5261118 C 10.372347,5.3087395 11,6.5690611 11,8 11,9.4309388 10.372767,10.690952 9.5897193,11.474 L 11,12.884 C 12.275645,11.608355 13,9.854095 13,8 13,6.1543677 12.273068,4.3887355 11,3.1156678 Z"
+ id="path4529"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccc" />
+ <path
+ style="opacity:1;fill:#bebebe;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 8.629,5 7.2094668,6.4096296 C 8,7.05621 8,7.805653 8,8 8,8.1932576 7.982199,8.9408674 7.209,9.59 L 8.6289063,11 C 9.8466375,9.952694 10,8.5984701 10,8 10,7.400497 9.854476,6.062891 8.629,5 Z"
+ id="path4569"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccscccc" />
+</svg>
diff --git a/volume-widget/audio-volume-muted-symbolic_red.svg b/volume-widget/icons/audio-volume-low-symbolic.svg
index d42c2ba..7eb4531 100644
--- a/volume-widget/audio-volume-muted-symbolic_red.svg
+++ b/volume-widget/icons/audio-volume-low-symbolic.svg
@@ -12,8 +12,8 @@
height="16"
id="svg2"
version="1.1"
- inkscape:version="0.91 r13725"
- sodipodi:docname="audio-volume-muted-symbolic.svg">
+ inkscape:version="0.91 r"
+ sodipodi:docname="audio-volume-low-symbolic.svg">
<metadata
id="metadata30">
<rdf:RDF>
@@ -40,8 +40,8 @@
id="namedview28"
showgrid="true"
inkscape:zoom="38.125"
- inkscape:cx="3.4229508"
- inkscape:cy="7.947541"
+ inkscape:cx="8"
+ inkscape:cy="8"
inkscape:window-x="65"
inkscape:window-y="24"
inkscape:window-maximized="1"
@@ -59,28 +59,28 @@
d="M 6,2 2,6 2,10 6,14 6,9 7,8 6,7 Z"
id="path18"
inkscape:connector-curvature="0"
- style="fill:#ed4737"
+ style="fill:#bebebe"
sodipodi:nodetypes="cccccccc" />
<path
d="M 1.300003,5 C 0.216589,5 0,6.163269 0,7.4 L 0,8.6 C 0,9.836747 0.24312,11 1.300003,11 L 3,11 3,5 Z"
id="path20"
inkscape:connector-curvature="0"
- style="fill:#ed4737"
+ style="fill:#bebebe"
sodipodi:nodetypes="ssssccs" />
<path
- style="opacity:0.3;fill:#ed4737;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ style="opacity:0.3;fill:#bebebe;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 13.140638,1 11.726417,2.413582 C 12.808349,3.4955144 13.990412,5.4467621 14,8 c 0,2.551493 -1.192916,4.505751 -2.273583,5.586418 L 13.140638,15 C 14.595711,13.544927 16.019176,11 16,8 16.035061,5 14.595117,2.4544787 13.140638,1 Z"
id="path4508"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccc" />
<path
- style="opacity:0.3;fill:#ed4737;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ style="opacity:0.3;fill:#bebebe;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 11,3.1156678 9.5897193,4.5261118 C 10.372347,5.3087395 11,6.5690611 11,8 11,9.4309388 10.372767,10.690952 9.5897193,11.474 L 11,12.884 C 12.275645,11.608355 13,9.854095 13,8 13,6.1543677 12.273068,4.3887355 11,3.1156678 Z"
id="path4529"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccc" />
<path
- style="opacity:0.3;fill:#ed4737;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ style="opacity:1;fill:#bebebe;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 8.629,5 7.2094668,6.4096296 C 8,7.05621 8,7.805653 8,8 8,8.1932576 7.982199,8.9408674 7.209,9.59 L 8.6289063,11 C 9.8466375,9.952694 10,8.5984701 10,8 10,7.400497 9.854476,6.062891 8.629,5 Z"
id="path4569"
inkscape:connector-curvature="0"
diff --git a/volume-widget/audio-volume-muted-symbolic_new.svg b/volume-widget/icons/audio-volume-medium-symbolic.svg
index 504c146..11e44fe 100644
--- a/volume-widget/audio-volume-muted-symbolic_new.svg
+++ b/volume-widget/icons/audio-volume-medium-symbolic.svg
@@ -12,8 +12,8 @@
height="16"
id="svg2"
version="1.1"
- inkscape:version="0.92.2 2405546, 2018-03-11"
- sodipodi:docname="audio-volume-muted-symbolic-shan.svg">
+ inkscape:version="0.91 r"
+ sodipodi:docname="audio-volume-medium-symbolic.svg">
<metadata
id="metadata30">
<rdf:RDF>
@@ -35,15 +35,15 @@
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
- inkscape:window-width="1438"
- inkscape:window-height="858"
+ inkscape:window-width="1215"
+ inkscape:window-height="776"
id="namedview28"
showgrid="true"
inkscape:zoom="38.125"
- inkscape:cx="3.4229508"
- inkscape:cy="7.947541"
- inkscape:window-x="0"
- inkscape:window-y="20"
+ inkscape:cx="8"
+ inkscape:cy="8"
+ inkscape:window-x="65"
+ inkscape:window-y="24"
inkscape:window-maximized="1"
inkscape:current-layer="svg2"
showguides="true"
@@ -56,26 +56,33 @@
<defs
id="defs4" />
<path
+ d="M 6,2 2,6 2,10 6,14 6,9 7,8 6,7 Z"
+ id="path18"
+ inkscape:connector-curvature="0"
+ style="fill:#bebebe"
+ sodipodi:nodetypes="cccccccc" />
+ <path
+ d="M 1.300003,5 C 0.216589,5 0,6.163269 0,7.4 L 0,8.6 C 0,9.836747 0.24312,11 1.300003,11 L 3,11 3,5 Z"
+ id="path20"
+ inkscape:connector-curvature="0"
+ style="fill:#bebebe"
+ sodipodi:nodetypes="ssssccs" />
+ <path
style="opacity:0.3;fill:#bebebe;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 13.140638,1 11.726417,2.413582 C 12.808349,3.4955144 13.990412,5.4467621 14,8 c 0,2.551493 -1.192916,4.505751 -2.273583,5.586418 L 13.140638,15 C 14.595711,13.544927 16.019176,11 16,8 16.035061,5 14.595117,2.4544787 13.140638,1 Z"
id="path4508"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccc" />
<path
- style="opacity:0.3;fill:#bebebe;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ style="opacity:1;fill:#bebebe;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 11,3.1156678 9.5897193,4.5261118 C 10.372347,5.3087395 11,6.5690611 11,8 11,9.4309388 10.372767,10.690952 9.5897193,11.474 L 11,12.884 C 12.275645,11.608355 13,9.854095 13,8 13,6.1543677 12.273068,4.3887355 11,3.1156678 Z"
id="path4529"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccc" />
<path
- style="opacity:0.3;fill:#bebebe;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ style="opacity:1;fill:#bebebe;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 8.629,5 7.2094668,6.4096296 C 8,7.05621 8,7.805653 8,8 8,8.1932576 7.982199,8.9408674 7.209,9.59 L 8.6289063,11 C 9.8466375,9.952694 10,8.5984701 10,8 10,7.400497 9.854476,6.062891 8.629,5 Z"
id="path4569"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccscccc" />
- <path
- style="opacity:0.3;fill:#bebebe;fill-opacity:1;stroke-width:0.02622951"
- d="M 4.5036936,12.482983 3.0218135,11.000927 2.1430379,11.000775 C 1.6597113,11.000691 1.1955581,10.989371 1.1115864,10.975618 0.56198086,10.885606 0.24352693,10.462909 0.07812436,9.603862 0.03708101,9.390696 0.03147539,9.196108 0.03147539,7.984533 c 0,-1.217172 0.0054766,-1.405527 0.04717053,-1.622335 0.132109,-0.686963 0.3489491,-1.058742 0.7259726,-1.244702 L 0.97448297,5.033716 1.9849464,5.026316 2.9954098,5.018916 4.4970492,3.518184 5.9986885,2.0174522 V 4.5094289 7.001406 l 0.4983672,0.497849 0.498367,0.497849 -0.4982329,0.498725 -0.498233,0.498725 -0.00669,2.485223 -0.00669,2.485223 z"
- id="path819"
- inkscape:connector-curvature="0" />
</svg>
diff --git a/volume-widget/audio-volume-muted-symbolic.svg b/volume-widget/icons/audio-volume-muted-symbolic.svg
index e577d05..e577d05 100644
--- a/volume-widget/audio-volume-muted-symbolic.svg
+++ b/volume-widget/icons/audio-volume-muted-symbolic.svg
diff --git a/volume-widget/screenshots/variations.png b/volume-widget/screenshots/variations.png
new file mode 100644
index 0000000..21d7ead
--- /dev/null
+++ b/volume-widget/screenshots/variations.png
Binary files differ
diff --git a/volume-widget/screenshots/volume-sink-sources.png b/volume-widget/screenshots/volume-sink-sources.png
new file mode 100644
index 0000000..7d010bc
--- /dev/null
+++ b/volume-widget/screenshots/volume-sink-sources.png
Binary files differ
diff --git a/volume-widget/utils.lua b/volume-widget/utils.lua
new file mode 100644
index 0000000..417a666
--- /dev/null
+++ b/volume-widget/utils.lua
@@ -0,0 +1,105 @@
+
+
+local utils = {}
+
+local function split(string_to_split, separator)
+ if separator == nil then separator = "%s" end
+ local t = {}
+
+ for str in string.gmatch(string_to_split, "([^".. separator .."]+)") do
+ table.insert(t, str)
+ end
+
+ return t
+end
+
+function utils.extract_sinks_and_sources(pacmd_output)
+ local sinks = {}
+ local sources = {}
+ local device
+ local properties
+ local ports
+ local in_sink = false
+ local in_source = false
+ local in_device = false
+ local in_properties = false
+ local in_ports = false
+ for line in pacmd_output:gmatch("[^\r\n]+") do
+ if string.match(line, 'source%(s%) available.') then
+ in_sink = false
+ in_source = true
+ end
+ if string.match(line, 'sink%(s%) available.') then
+ in_sink = true
+ in_source = false
+ end
+
+ if string.match(line, 'index:') then
+ in_device = true
+ in_properties = false
+ device = {
+ id = line:match(': (%d+)'),
+ is_default = string.match(line, '*') ~= nil
+ }
+ if in_sink then
+ table.insert(sinks, device)
+ elseif in_source then
+ table.insert(sources, device)
+ end
+ end
+
+ if string.match(line, '^\tproperties:') then
+ in_device = false
+ in_properties = true
+ properties = {}
+ device['properties'] = properties
+ end
+
+ if string.match(line, 'ports:') then
+ in_device = false
+ in_properties = false
+ in_ports = true
+ ports = {}
+ device['ports'] = ports
+ end
+
+ if string.match(line, 'active port:') then
+ in_device = false
+ in_properties = false
+ in_ports = false
+ device['active_port'] = line:match(': (.+)'):gsub('<',''):gsub('>','')
+ end
+
+ if in_device then
+ local t = split(line, ': ')
+ local key = t[1]:gsub('\t+', ''):lower()
+ local value = t[2]:gsub('^<', ''):gsub('>$', '')
+ device[key] = value
+ end
+
+ if in_properties then
+ local t = split(line, '=')
+ local key = t[1]:gsub('\t+', ''):gsub('%.', '_'):gsub('-', '_'):gsub(':', ''):gsub("%s+$", "")
+ local value
+ if t[2] == nil then
+ value = t[2]
+ else
+ value = t[2]:gsub('"', ''):gsub("^%s+", ""):gsub(' Analog Stereo', '')
+ end
+ properties[key] = value
+ end
+
+ if in_ports then
+ local t = split(line, ': ')
+ local key = t[1]
+ if key ~= nil then
+ key = key:gsub('\t+', '')
+ end
+ ports[key] = t[2]
+ end
+ end
+
+ return sinks, sources
+end
+
+return utils \ No newline at end of file
diff --git a/volume-widget/vol-widget-1.png b/volume-widget/vol-widget-1.png
deleted file mode 100644
index 6f09cce..0000000
--- a/volume-widget/vol-widget-1.png
+++ /dev/null
Binary files differ
diff --git a/volume-widget/volume-2.svg b/volume-widget/volume-2.svg
new file mode 100644
index 0000000..10f1c67
--- /dev/null
+++ b/volume-widget/volume-2.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#ffffff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-volume-2"><polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5"></polygon><path d="M19.07 4.93a10 10 0 0 1 0 14.14M15.54 8.46a5 5 0 0 1 0 7.07"></path></svg> \ No newline at end of file
diff --git a/volume-widget/volume.lua b/volume-widget/volume.lua
index cb8c21d..59f0a7a 100644
--- a/volume-widget/volume.lua
+++ b/volume-widget/volume.lua
@@ -1,181 +1,216 @@
-------------------------------------------------
--- Volume Widget for Awesome Window Manager
--- Shows the current volume level
+-- The Ultimate Volume Widget for Awesome Window Manager
-- More details could be found here:
-- https://github.com/streetturtle/awesome-wm-widgets/tree/master/volume-widget
--- @author Pavel Makhov, Aurélien Lajoie
--- @copyright 2018 Pavel Makhov
+-- @author Pavel Makhov
+-- @copyright 2020 Pavel Makhov
-------------------------------------------------
+local awful = require("awful")
local wibox = require("wibox")
local spawn = require("awful.spawn")
-local naughty = require("naughty")
-local gfs = require("gears.filesystem")
-local dpi = require('beautiful').xresources.apply_dpi
-
-local PATH_TO_ICONS = "/usr/share/icons/Arc/status/symbolic/"
-local volume_icon_name="audio-volume-high-symbolic"
-local GET_VOLUME_CMD = 'amixer sget Master'
-
-local volume = {
- device = '',
- display_notification = false,
- display_notification_onClick = true,
- notification = nil,
- delta = 5
-}
+local gears = require("gears")
+local beautiful = require("beautiful")
+local watch = require("awful.widget.watch")
+local utils = require("awesome-wm-widgets.volume-widget.utils")
-function volume:toggle()
- volume:_cmd('amixer ' .. volume.device .. ' sset Master toggle')
-end
-function volume:raise()
- volume:_cmd('amixer ' .. volume.device .. ' sset Master ' .. tostring(volume.delta) .. '%+')
-end
-function volume:lower()
- volume:_cmd('amixer ' .. volume.device .. ' sset Master ' .. tostring(volume.delta) .. '%-')
-end
+local LIST_DEVICES_CMD = [[sh -c "pacmd list-sinks; pacmd list-sources"]]
+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'
---{{{ Icon and notification update
-
---------------------------------------------------
--- Set the icon and return the message to display
--- base on sound level and mute
---------------------------------------------------
-local function parse_output(stdout)
- local level = string.match(stdout, "(%d?%d?%d)%%")
- if stdout:find("%[off%]") then
- volume_icon_name="audio-volume-muted-symbolic_red"
- return level.."% <span color=\"red\"><b>Mute</b></span>"
- end
- level = tonumber(string.format("% 3d", level))
-
- if (level >= 0 and level < 25) then
- volume_icon_name="audio-volume-muted-symbolic"
- elseif (level < 50) then
- volume_icon_name="audio-volume-low-symbolic"
- elseif (level < 75) then
- volume_icon_name="audio-volume-medium-symbolic"
+
+local widget_types = {
+ icon_and_text = require("awesome-wm-widgets.volume-widget.widgets.icon-and-text-widget"),
+ icon = require("awesome-wm-widgets.volume-widget.widgets.icon-widget"),
+ arc = require("awesome-wm-widgets.volume-widget.widgets.arc-widget"),
+ horizontal_bar = require("awesome-wm-widgets.volume-widget.widgets.horizontal-bar-widget"),
+ vertical_bar = require("awesome-wm-widgets.volume-widget.widgets.vertical-bar-widget")
+}
+local volume = {}
+
+local rows = { layout = wibox.layout.fixed.vertical }
+
+local popup = awful.popup{
+ bg = beautiful.bg_normal,
+ ontop = true,
+ visible = false,
+ shape = gears.shape.rounded_rect,
+ border_width = 1,
+ border_color = beautiful.bg_focus,
+ maximum_width = 400,
+ offset = { y = 5 },
+ widget = {}
+}
+
+local function build_main_line(device)
+ if device.active_port ~= nil and device.ports[device.active_port] ~= nil then
+ return device.properties.device_description .. ' · ' .. device.ports[device.active_port]
else
- volume_icon_name="audio-volume-high-symbolic"
+ return device.properties.device_description
end
- return level.."%"
end
---------------------------------------------------------
---Update the icon and the notification if needed
---------------------------------------------------------
-local function update_graphic(widget, stdout, _, _, _)
- local txt = parse_output(stdout)
- widget.image = PATH_TO_ICONS .. volume_icon_name .. ".svg"
- if (volume.display_notification or volume.display_notification_onClick) then
- volume.notification.iconbox.image = PATH_TO_ICONS .. volume_icon_name .. ".svg"
- naughty.replace_text(volume.notification, "Volume", txt)
- end
-end
+local function build_rows(devices, on_checkbox_click, device_type)
+ local device_rows = { layout = wibox.layout.fixed.vertical }
+ for _, device in pairs(devices) do
+
+ local checkbox = wibox.widget {
+ checked = device.is_default,
+ color = beautiful.bg_normal,
+ paddings = 2,
+ shape = gears.shape.circle,
+ forced_width = 20,
+ forced_height = 20,
+ check_color = beautiful.fg_urgent,
+ widget = wibox.widget.checkbox
+ }
+
+ checkbox:connect_signal("button::press", function()
+ spawn.easy_async(string.format([[sh -c 'pacmd set-default-%s "%s"']], device_type, device.name), function()
+ on_checkbox_click()
+ end)
+ end)
-local function notif(msg, keep)
- if (volume.display_notification or (keep and volume.display_notification_onClick)) then
- naughty.destroy(volume.notification)
- volume.notification= naughty.notify{
- text = msg,
- icon=PATH_TO_ICONS .. volume_icon_name .. ".svg",
- icon_size = dpi(16),
- title = "Volume",
- position = volume.position,
- timeout = keep and 0 or 2, hover_timeout = 0.5,
- width = 200,
- screen = mouse.screen
+ local row = wibox.widget {
+ {
+ {
+ {
+ checkbox,
+ valign = 'center',
+ layout = wibox.container.place,
+ },
+ {
+ {
+ text = build_main_line(device),
+ align = 'left',
+ widget = wibox.widget.textbox
+ },
+ left = 10,
+ layout = wibox.container.margin
+ },
+ spacing = 8,
+ layout = wibox.layout.align.horizontal
+ },
+ margins = 4,
+ layout = wibox.container.margin
+ },
+ bg = beautiful.bg_normal,
+ widget = wibox.container.background
}
+
+ row:connect_signal("mouse::enter", function(c) c:set_bg(beautiful.bg_focus) end)
+ row:connect_signal("mouse::leave", function(c) c:set_bg(beautiful.bg_normal) end)
+
+ local old_cursor, old_wibox
+ row:connect_signal("mouse::enter", function()
+ local wb = mouse.current_wibox
+ old_cursor, old_wibox = wb.cursor, wb
+ wb.cursor = "hand1"
+ end)
+ row:connect_signal("mouse::leave", function()
+ if old_wibox then
+ old_wibox.cursor = old_cursor
+ old_wibox = nil
+ end
+ end)
+
+ row:connect_signal("button::press", function()
+ spawn.easy_async(string.format([[sh -c 'pacmd set-default-%s "%s"']], device_type, device.name), function()
+ on_checkbox_click()
+ end)
+ end)
+
+ table.insert(device_rows, row)
end
+
+ return device_rows
+end
+
+local function build_header_row(text)
+ return wibox.widget{
+ {
+ markup = "<b>" .. text .. "</b>",
+ align = 'center',
+ widget = wibox.widget.textbox
+ },
+ bg = beautiful.bg_normal,
+ widget = wibox.container.background
+ }
+end
+
+local function rebuild_popup()
+ spawn.easy_async(LIST_DEVICES_CMD, function(stdout)
+
+ local sinks, sources = utils.extract_sinks_and_sources(stdout)
+
+ for i = 0, #rows do rows[i]=nil end
+
+ table.insert(rows, build_header_row("SINKS"))
+ table.insert(rows, build_rows(sinks, function() rebuild_popup() end, "sink"))
+ table.insert(rows, build_header_row("SOURCES"))
+ table.insert(rows, build_rows(sources, function() rebuild_popup() end, "source"))
+
+ popup:setup(rows)
+ end)
end
---}}}
local function worker(user_args)
---{{{ Args
+
local args = user_args or {}
- local volume_audio_controller = args.volume_audio_controller or 'pulse'
- volume.display_notification = args.display_notification or false
- volume.display_notification_onClick = args.display_notification_onClick or true
- volume.position = args.notification_position or "top_right"
- if volume_audio_controller == 'pulse' then
- volume.device = '-D pulse'
- end
- volume.delta = args.delta or 5
- GET_VOLUME_CMD = 'amixer ' .. volume.device.. ' sget Master'
---}}}
---{{{ Check for icon path
- if not gfs.dir_readable(PATH_TO_ICONS) then
- naughty.notify{
- title = "Volume Widget",
- text = "Folder with icons doesn't exist: " .. PATH_TO_ICONS,
- preset = naughty.config.presets.critical
- }
- return
+ local widget_type = args.widget_type
+ local refresh_rate = args.refresh_rate or 1
+
+ if widget_types[widget_type] == nil then
+ volume.widget = widget_types['icon_and_text'].get_widget(user_args.icon_and_text_args)
+ else
+ volume.widget = widget_types[widget_type].get_widget(args)
end
---}}}
---{{{ Widget creation
- volume.widget = wibox.widget {
- {
- id = "icon",
- image = PATH_TO_ICONS .. "audio-volume-muted-symbolic.svg",
- resize = false,
- widget = wibox.widget.imagebox,
- },
- margins = 3,
- layout = wibox.container.margin,
- set_image = function(self, path)
- self.icon.image = path
+
+ local function update_graphic(widget, stdout)
+ local mute = string.match(stdout, "%[(o%D%D?)%]") -- \[(o\D\D?)\] - [on] or [off]
+ if mute == 'off' then widget:mute()
+ elseif mute == 'on' then widget:unmute()
end
- }
---}}}
---{{{ Spawn functions
- function volume:_cmd(cmd)
- notif("")
- spawn.easy_async(cmd, function(stdout, stderr, exitreason, exitcode)
- update_graphic(volume.widget, stdout, stderr, exitreason, exitcode)
- end)
+ local volume_level = string.match(stdout, "(%d?%d?%d)%%") -- (\d?\d?\d)\%)
+ volume_level = string.format("% 3d", volume_level)
+ widget:set_volume_level(volume_level)
end
- local function show()
- spawn.easy_async(GET_VOLUME_CMD, function(stdout, _, _, _)
- local txt = parse_output(stdout)
- notif(txt, true)
- end
- )
+ function volume:inc()
+ spawn.easy_async(INC_VOLUME_CMD, function(stdout) update_graphic(volume.widget, stdout) end)
end
---}}}
---{{{ Mouse event
- --[[ 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 volume.raise()
- elseif (button == 5) then volume.lower()
- elseif (button == 1) then volume.toggle()
- end
- end)
- if volume.display_notification then
- volume.widget:connect_signal("mouse::enter", function() show() end)
- volume.widget:connect_signal("mouse::leave", function() naughty.destroy(volume.notification) end)
- elseif volume.display_notification_onClick then
- volume.widget:connect_signal("button::press", function(_,_,_,button)
- if (button == 3) then show() end
- end)
- volume.widget:connect_signal("mouse::leave", function() naughty.destroy(volume.notification) end)
+
+ function volume:dec()
+ spawn.easy_async(DEC_VOLUME_CMD, function(stdout) update_graphic(volume.widget, stdout) end)
end
---}}}
---{{{ Set initial icon
- spawn.easy_async(GET_VOLUME_CMD, function(stdout)
- parse_output(stdout)
- volume.widget.image = PATH_TO_ICONS .. volume_icon_name .. ".svg"
- end)
---}}}
+ function volume:toggle()
+ spawn.easy_async(TOG_VOLUME_CMD, function(stdout) update_graphic(volume.widget, stdout) end)
+ end
+
+ volume.widget:buttons(
+ awful.util.table.join(
+ awful.button({}, 3, function()
+ if popup.visible then
+ popup.visible = not popup.visible
+ else
+ rebuild_popup()
+ popup:move_next_to(mouse.current_widget_geometry)
+ end
+ end),
+ awful.button({}, 4, function() volume:inc() end),
+ awful.button({}, 5, function() volume:dec() end),
+ awful.button({}, 1, function() volume:toggle() end)
+ )
+ )
+
+ watch(GET_VOLUME_CMD, refresh_rate, update_graphic, volume.widget)
return volume.widget
end
diff --git a/volume-widget/widgets/arc-widget.lua b/volume-widget/widgets/arc-widget.lua
new file mode 100644
index 0000000..b512f12
--- /dev/null
+++ b/volume-widget/widgets/arc-widget.lua
@@ -0,0 +1,46 @@
+local wibox = require("wibox")
+local beautiful = require('beautiful')
+
+local ICON_DIR = os.getenv("HOME") .. '/.config/awesome/awesome-wm-widgets/volume-widget/icons/'
+
+local widget = {}
+
+function widget.get_widget(widgets_args)
+ local args = widgets_args or {}
+
+ local thickness = args.thickness or 2
+ local main_color = args.main_color or beautiful.fg_color
+ local bg_color = args.bg_color or '#ffffff11'
+ local mute_color = args.mute_color or beautiful.fg_urgent
+ local size = args.size or 18
+
+ return wibox.widget {
+ {
+ id = "icon",
+ image = ICON_DIR .. 'audio-volume-high-symbolic.svg',
+ resize = true,
+ widget = wibox.widget.imagebox,
+ },
+ max_value = 100,
+ thickness = thickness,
+ start_angle = 4.71238898, -- 2pi*3/4
+ forced_height = size,
+ forced_width = size,
+ bg = bg_color,
+ paddings = 2,
+ widget = wibox.container.arcchart,
+ set_volume_level = function(self, new_value)
+ self.value = new_value
+ end,
+ mute = function(self)
+ self.colors = { mute_color }
+ end,
+ unmute = function(self)
+ self.colors = { main_color }
+ end
+ }
+
+end
+
+
+return widget \ No newline at end of file
diff --git a/volume-widget/widgets/horizontal-bar-widget.lua b/volume-widget/widgets/horizontal-bar-widget.lua
new file mode 100644
index 0000000..be1f38d
--- /dev/null
+++ b/volume-widget/widgets/horizontal-bar-widget.lua
@@ -0,0 +1,58 @@
+local wibox = require("wibox")
+local beautiful = require('beautiful')
+local gears = require("gears")
+
+local ICON_DIR = os.getenv("HOME") .. '/.config/awesome/awesome-wm-widgets/volume-widget/icons/'
+
+local widget = {}
+
+function widget.get_widget(widgets_args)
+ local args = widgets_args or {}
+
+ local main_color = args.main_color or beautiful.fg_normal
+ local mute_color = args.mute_color or beautiful.fg_urgent
+ local bg_color = args.bg_color or '#ffffff11'
+ local width = args.width or 50
+ local margins = args.margins or 10
+ local shape = args.shape or 'bar'
+ local with_icon = args.with_icon == true and true or false
+
+ local bar = wibox.widget {
+ {
+ {
+ id = "icon",
+ image = ICON_DIR .. 'audio-volume-high-symbolic.svg',
+ resize = false,
+ widget = wibox.widget.imagebox,
+ },
+ valign = 'center',
+ visible = with_icon,
+ layout = wibox.container.place,
+ },
+ {
+ id = 'bar',
+ max_value = 100,
+ forced_width = width,
+ color = main_color,
+ margins = { top = margins, bottom = margins },
+ background_color = bg_color,
+ shape = gears.shape[shape],
+ widget = wibox.widget.progressbar,
+ },
+ spacing = 4,
+ layout = wibox.layout.fixed.horizontal,
+ set_volume_level = function(self, new_value)
+ self:get_children_by_id('bar')[1]:set_value(tonumber(new_value))
+ end,
+ mute = function(self)
+ self:get_children_by_id('bar')[1]:set_color(mute_color)
+ end,
+ unmute = function(self)
+ self:get_children_by_id('bar')[1]:set_color(main_color)
+ end
+ }
+
+ return bar
+end
+
+return widget
diff --git a/volume-widget/widgets/icon-and-text-widget.lua b/volume-widget/widgets/icon-and-text-widget.lua
new file mode 100644
index 0000000..b1a2793
--- /dev/null
+++ b/volume-widget/widgets/icon-and-text-widget.lua
@@ -0,0 +1,59 @@
+local wibox = require("wibox")
+local beautiful = require('beautiful')
+
+local widget = {}
+
+local ICON_DIR = os.getenv("HOME") .. '/.config/awesome/awesome-wm-widgets/volume-widget/icons/'
+
+function widget.get_widget(widgets_args)
+ local args = widgets_args or {}
+
+ local font = args.font or beautiful.font
+ local icon_dir = args.icon_dir or ICON_DIR
+
+ return wibox.widget {
+ {
+ {
+ id = "icon",
+ resize = false,
+ widget = wibox.widget.imagebox,
+ },
+ valign = 'center',
+ layout = wibox.container.place
+ },
+ {
+ id = 'txt',
+ font = font,
+ widget = wibox.widget.textbox
+ },
+ layout = wibox.layout.fixed.horizontal,
+ set_volume_level = function(self, new_value)
+ self:get_children_by_id('txt')[1]:set_text(new_value)
+ local volume_icon_name
+ if self.is_muted then
+ volume_icon_name = 'audio-volume-muted-symbolic'
+ else
+ local new_value_num = tonumber(new_value)
+ if (new_value_num >= 0 and new_value_num < 33) then
+ volume_icon_name="audio-volume-low-symbolic"
+ elseif (new_value_num < 66) then
+ volume_icon_name="audio-volume-medium-symbolic"
+ else
+ volume_icon_name="audio-volume-high-symbolic"
+ end
+ end
+ self:get_children_by_id('icon')[1]:set_image(icon_dir .. volume_icon_name .. '.svg')
+ end,
+ mute = function(self)
+ self.is_muted = true
+ self:get_children_by_id('icon')[1]:set_image(icon_dir .. 'audio-volume-muted-symbolic.svg')
+ end,
+ unmute = function(self)
+ self.is_muted = false
+ end
+ }
+
+end
+
+
+return widget \ No newline at end of file
diff --git a/volume-widget/widgets/icon-widget.lua b/volume-widget/widgets/icon-widget.lua
new file mode 100644
index 0000000..cc39a3d
--- /dev/null
+++ b/volume-widget/widgets/icon-widget.lua
@@ -0,0 +1,46 @@
+local wibox = require("wibox")
+
+local widget = {}
+
+local ICON_DIR = os.getenv("HOME") .. '/.config/awesome/awesome-wm-widgets/volume-widget/icons/'
+
+function widget.get_widget(widgets_args)
+ local args = widgets_args or {}
+
+ local icon_dir = args.icon_dir or ICON_DIR
+
+ return wibox.widget {
+ {
+ id = "icon",
+ resize = false,
+ widget = wibox.widget.imagebox,
+ },
+ valign = 'center',
+ layout = wibox.container.place,
+ set_volume_level = function(self, new_value)
+ local volume_icon_name
+ if self.is_muted then
+ volume_icon_name = 'audio-volume-muted-symbolic'
+ else
+ local new_value_num = tonumber(new_value)
+ if (new_value_num >= 0 and new_value_num < 33) then
+ volume_icon_name="audio-volume-low-symbolic"
+ elseif (new_value_num < 66) then
+ volume_icon_name="audio-volume-medium-symbolic"
+ else
+ volume_icon_name="audio-volume-high-symbolic"
+ end
+ end
+ self:get_children_by_id('icon')[1]:set_image(icon_dir .. volume_icon_name .. '.svg')
+ end,
+ mute = function(self)
+ self.is_muted = true
+ self:get_children_by_id('icon')[1]:set_image(icon_dir .. 'audio-volume-muted-symbolic.svg')
+ end,
+ unmute = function(self)
+ self.is_muted = false
+ end
+ }
+end
+
+return widget \ No newline at end of file
diff --git a/volume-widget/widgets/vertical-bar-widget.lua b/volume-widget/widgets/vertical-bar-widget.lua
new file mode 100644
index 0000000..6f32b50
--- /dev/null
+++ b/volume-widget/widgets/vertical-bar-widget.lua
@@ -0,0 +1,64 @@
+local wibox = require("wibox")
+local beautiful = require('beautiful')
+local gears = require("gears")
+
+local ICON_DIR = os.getenv("HOME") .. '/.config/awesome/awesome-wm-widgets/volume-widget/icons/'
+
+local widget = {}
+
+function widget.get_widget(widgets_args)
+ local args = widgets_args or {}
+
+ local main_color = args.main_color or beautiful.fg_normal
+ local mute_color = args.mute_color or beautiful.fg_urgent
+ local bg_color = args.bg_color or '#ffffff11'
+ local width = args.width or 10
+ local margins = args.height or 2
+ local shape = args.shape or 'bar'
+ local with_icon = args.with_icon == true and true or false
+
+ local bar = wibox.widget {
+ {
+ {
+ id = "icon",
+ image = ICON_DIR .. 'audio-volume-high-symbolic.svg',
+ resize = false,
+ widget = wibox.widget.imagebox,
+ },
+ valign = 'center',
+ visible = with_icon,
+ layout = wibox.container.place,
+ },
+ {
+ {
+ id = 'bar',
+ max_value = 100,
+ forced_width = width,
+ forced_height = 5,
+ margins = { top = margins, bottom = margins },
+ color = main_color,
+ background_color = bg_color,
+ shape = gears.shape[shape],
+ widget = wibox.widget.progressbar,
+ },
+ forced_width = width,
+ direction = 'east',
+ layout = wibox.container.rotate,
+ },
+ spacing = 4,
+ layout = wibox.layout.fixed.horizontal,
+ set_volume_level = function(self, new_value)
+ self:get_children_by_id('bar')[1]:set_value(tonumber(new_value))
+ end,
+ mute = function(self)
+ self:get_children_by_id('bar')[1]:set_color(mute_color)
+ end,
+ unmute = function(self)
+ self:get_children_by_id('bar')[1]:set_color(main_color)
+ end
+ }
+
+ return bar
+end
+
+return widget