Giter Site home page Giter Site logo

marioortizmanero / polybar-pulseaudio-control Goto Github PK

View Code? Open in Web Editor NEW
456.0 5.0 48.0 194 KB

A feature-full Polybar module to control PulseAudio

License: MIT License

Shell 99.53% Dockerfile 0.47%
polybar control pavolume pavucontrol switch-sinks audio manager pulseaudio hacktoberfest

polybar-pulseaudio-control's Introduction

PulseAudio Control

A feature-full volume control module for PulseAudio. Also known as Pavolume. Main features:

  • Increase/Decrease and Mute the default audio node (can be sink or source).
  • Switch between nodes easily. You can also blacklist useless devices.
  • Optionally enable notifications and OSD messages.
  • Works as a shortcut to pavucontrol or your favorite audio manager tool.
  • Highly customizable: check the Usage section for details.

example

Installation

Arch

Install pulseaudio-control from the AUR with your preferred method, for example:

$ yay -S pulseaudio-control

Other Linux

Download the bash script from this repository, or extract it from the latest release, and put it somewhere in your $PATH.

Dependencies

pulseaudio with pactl in your $PATH. You might want to have pavucontrol installed to easily control pulseaudio with a GUI. The script can send notifications if enabled, for which you'll need a notification daemon like dunst.

This script works with PipeWire as well, as long as your system has something like pipewire-pulse.

To be able to switch the default sinks from this script you might need to disable stream target device restore by editing the corresponding line in /etc/pulse/default.pa to:

load-module module-stream-restore restore_device=false

At a minimum, bash version 4 is required to run the script. You can check your bash version by running bash --version.

Usage

pulseaudio-control is expected to be invoked from a polybar module:

[module/pulseaudio-control]
type = custom/script
exec = pulseaudio-control [option...] <action>

where action, and (optionally) options are as specified in pulseaudio-control help:

Usage: ./pulseaudio-control.bash [OPTION...] ACTION

Terminology: A node represents either a sink (output) or source (input).

Options:
  --autosync | --no-autosync
        Whether to maintain same volume for all programs.
        Default: "no"
  --color-muted <rrggbb>
        Color in which to format when muted.
        Pass empty string to disable.
        Default: "6b6b6b"
  --notifications | --no-notifications
        Whether to show notifications when changing nodes.
        Default: "no"
  --osd | --no-osd
        Whether to display KDE's OSD message.
        Default: "no"
  --icon-muted <icon>
        Icon to use when muted.
        Default: none
  --icon-node <icon>
        Icon to use for node.
        Default: none
  --format <string>
        Use a format string to control the output.
        Remember to pass this argument wrapped in single quotes (`'`) instead
        of double quotes (`"`) to avoid your shell from evaluating the
        variables early.
        Available variables:
        * $VOL_ICON
        * $VOL_LEVEL
        * $ICON_NODE
        * $NODE_NICKNAME
        * $IS_MUTED (yes/no)
        Default: '$VOL_ICON ${VOL_LEVEL}%  $ICON_NODE $NODE_NICKNAME'
  --icons-volume <icon>[,<icon>...]
        Icons for volume, from lower to higher.
        Default: none
  --node-type <node_type>
        Whether to consider PulseAudio sinks (output) or sources (input).
        All the operations of pulseaudio-control will apply to one of the two.
        Pass `input` for the sources, e.g. a microphone.
        Pass `output` for the sinks, e.g. speakers, headphones.
        Default: "output"
  --volume-max <int>
        Maximum volume to which to allow increasing.
        Default: "130"
  --volume-step <int>
        Step size when inc/decrementing volume.
        Default: "2"
  --node-blacklist <name>[,<name>...]
        Nodes to ignore when switching. You can use globs. Don't forget to
        quote the string when using globs, to avoid unwanted shell glob
        extension.
        Default: none
  --node-nicknames-from <prop>
        pactl property to use for node names, unless overridden by
        --node-nickname. Its possible values are listed under the 'Properties'
        key in the output of `pactl list sinks` and `pactl list sources`.
        Default: none
  --node-nickname <name>:<nick>
        Nickname to assign to given node name, taking priority over
        --node-nicknames-from. May be given multiple times, and 'name' is
        exactly as listed in the output of `pactl list sinks short | cut -f2`
        and `pactl list sources short | cut -f2`.
        Note that you can also specify a port name for the node with
        `<name>/<port>`.
        It is also possible to use glob matching to match node and port names.
        Exact matches are prioritized. Don't forget to quote the string when
        using globs, to avoid unwanted shell glob extension.
        Default: none
  --listen-timeout-secs
        The listen command updates the output as soon as it receives an event
        from PulseAudio. However, events are often accompanied by many other
        useless ones, which may result in unnecessary consecutive output
        updates. This script buffers the following events until a timeout is
        reached to avoid this scenario, which lessens the CPU load on events.
        However, this may result in noticeable latency when performing many
        actions quickly (e.g., updating the volume with the mouse wheel). You
        can specify what timeout to use to control the responsiveness, in
        seconds.
        Default: "0.05"

Actions:
  help              display this message and exit
  output            print the PulseAudio status once
  listen            listen for changes in PulseAudio to automatically update
                    this script's output
  up, down          increase or decrease the default node's volume
  mute, unmute      mute or unmute the default node's audio
  togmute           switch between muted and unmuted
  next-node         switch to the next available node
  sync              synchronize all the output streams volume to be the same as
                    the current node's volume

Author:
    Mario Ortiz Manero
More info on GitHub:
    https://github.com/marioortizmanero/polybar-pulseaudio-control

See the Module section for an example, or the Useful icons section for some packs of icons.

Module

The example from the screenshot can:

  • Increase and decrease the volume on mousewheel scroll
  • Mute the audio on left click
  • Switch between devices on mousewheel click
  • Open pavucontrol on right click
[module/pulseaudio-control-output]
type = custom/script
tail = true
format-underline = ${colors.cyan}
label-padding = 2
label-foreground = ${colors.foreground}

# Icons mixed from Font Awesome 5 and Material Icons
# You can copy-paste your options for each possible action, which is more
# trouble-free but repetitive, or apply only the relevant ones (for example
# --node-blacklist is only needed for next-node).
exec = pulseaudio-control --icons-volume " , " --icon-muted "" --node-nicknames-from "device.description" --node-nickname "alsa_output.pci-0000_00_1b.0.analog-stereo:  Speakers" --node-nickname "alsa_output.usb-Kingston_HyperX_Virtual_Surround_Sound_00000000-00.analog-stereo:  Headphones" listen
click-right = exec pavucontrol &
click-left = pulseaudio-control togmute
click-middle = pulseaudio-control --node-blacklist "alsa_output.pci-0000_01_00.1.hdmi-stereo-extra2" next-node
scroll-up = pulseaudio-control --volume-max 130 up
scroll-down = pulseaudio-control --volume-max 130 down

[module/pulseaudio-control-input]
type = custom/script
tail = true
format-underline = ${colors.cyan}
label-padding = 2
label-foreground = ${colors.foreground}

# Use --node-blacklist to remove the unwanted PulseAudio .monitor that are child of sinks
exec = pulseaudio-control  --node-type input --icons-volume "" --icon-muted "" --node-nickname "alsa_output.pci-0000_0c_00.3.analog-stereo:  Webcam" --node-nickname "alsa_output.usb-Kingston_HyperX_Virtual_Surround_Sound_00000000-00.analog-stereo:  Headphones" --node-blacklist "*.monitor" listen
click-right = exec pavucontrol &
click-left = pulseaudio-control --node-type input togmute
click-middle = pulseaudio-control --node-type input next-node
scroll-up = pulseaudio-control --node-type input --volume-max 130 up
scroll-down = pulseaudio-control --node-type input --volume-max 130 down

Useful icons

Here's a list with some icons from different fonts you can copy-paste. Most have a space afterwards so that the module has a bit of spacing. They may appear bugged on your browser if the font isn't available there. Please add yours if they aren't in the list.

Font name Volumes Muted Output icons Input icons
FontAwesome " , , " " " or " " " " or " " or ", "
Material " , , " " " or "󰍭 " " " or " " or " " "󰍬, 󰍮"
Emoji "🔈 ,🔉 ,🔊 " "🔇 " "🔈 " or "🎧 " "🎙️ "
Emoji v2 "🕨 ,🕩 ,🕪 " "🔇 " "🕨 " or "🎧 " "🎤 "

Most of these can be used after downloading a Nerd Font and including it in your Polybar config. For example:

font-X = Font Awesome 5 Free: style=Solid: pixelsize=11
font-Y = Font Awesome 5 Brands: pixelsize=11
font-Z = Material Icons: style=Regular: pixelsize=13; 2

FAQ

Can I use this with a status bar other than Polybar?

The only part of this script that's tied to Polybar is the color formatting. When muted, the dimmed color will probably not work. Please let us know in this issue if you want support for a new status bar. I'd strongly recommend you to open a PR yourself, as it should be relatively easy!

Does this work with PipeWire?

Yes! You only need to install the pulseaudio client on your machine. On Arch Linux, that's pipewire-pulse, for example.

It won't work with other audio servers like JACK, though.

This script uses too much CPU

We use the pactl subscribe command to get notified of new events that may occur in order to refresh the output. However, the command often outputs a lot of events for a simple action, like increasing the volume. Instead of refreshing for every single line it prints, we:

  1. Wait for one event
  2. Update the output first
  3. Continue to listen for events until a timeout ends, or until we reach a large enough number of them
  4. Update the output again
  5. Go back to step 1

This way, the first event will update quickly, and the following ones, which are most likely unnecessary, will be ignored until some time passes. This reduces the CPU usage, but it's not really perfect, as everyone percieves latency differently, and it depends on the use-case.

The timer can be configured with --listen-timeout-secs, which has a default value of 0.05 (50 ms). If you want less CPU usage, i.e., ignore more duplicate events, you can bump it to, for example, 0.1 (100 ms). Or for faster refreshes when performing multiple actions quickly, e.g., updating the volume with your mousewheel, you can even use a smaller value.

This script feels laggy when performing multiple actions quickly

Please refer to the previous question, as you can fix this by setting a smaller refresh delay with --listen-timeout-secs.

Sources

Part of the script and of this README's info was taken from customlinux.blogspot.com, the creator. It was later adapted to fit polybar. It is also mixed with the ArcoLinux version, which implemented the listen action to use less resources.

Development

Any PRs and issues are welcome! The tests can be ran with bats tests.bats, preferably with the Dockerfile in this repository.

polybar-pulseaudio-control's People

Contributors

0jdxt avatar aerion avatar andrhua avatar chuahou avatar fabian-thomas avatar foben avatar kronn avatar m-gregoire avatar marioortizmanero avatar mntzrr avatar ojford avatar samyak-jain avatar sleepybag avatar spfabgerman avatar wgorecki avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

polybar-pulseaudio-control's Issues

Formatting the output with a fully configurable string

It'd be pretty neat to be able to fully configure the script's output with something like:

FORMAT='$VOL_ICON ${VOL_LEVEL}%  $SINK_ICON $SINK_NICKNAME'

It would of course have to use single quotes so that it's evaluated with eval "$FORMAT" later in the script when printing the output. This would get rid of SINK_ICON as a side effect. It would also have to be thoroughly documented.

This is related to #25, as it would also allow to configure whether to show the microphones, or the sinks.

Make `next-sink` also iterate the sink ports

For example, my speakers are on alsa_output.pci-0000_2f_00.4.iec958-stereo whereas my headphones are alsa_output.pci-0000_2f_00.4.analog-stereo. Running pulseuadio-control next-sink doesn't identify the alternate port and stays on whichever I'm on.

I'm currently using indicator-sound-switcher which seems to identify both ports, so there may be an idea there but I've yet to dig around.

Thanks!

External sink change causes bad array subscript error

If the sink changes externally to pulseaudio-control, for example, an active bluetooth device disconnects, the output of listen changes to line 61: SINK_NICKNAMES["$sinkName"]="$nickname": bad array subscript.

It fixes on sink change if you rotate back through to the same one, but of course that's only a workaround, and also requires that more than one sink is still present. (If you're hitting this issue and have only one sink left, the other option is restarting the polybar.)

endColor shouldn't be a global

Pretty pointless considering it's only used in output. I should research what color codes other status bars use (apart from polybar). Because if they're all the same, it's unnecessary. Otherwise, I should add documentation for support on other status bars.

Not working with different locale

The script wasn't working for me and I realized the problems was the locale.

For example, pactl info was returning the messages in spanish, so greps weren't working.

Easy solution, prefix each pulseaudio-control:

LC_ALL=c pulseaudio-control

Support more status bars

The repo is called polybar-pulseaudio-control but that's just because I use Polybar and I created the script for my own. But I'd like to rename it to just pulseaudio-control. The core of the script can be perfectly re-used for other status bars. I would introduce a --status-bar flag that sets the "compatibility mode" for that. If anyone wants to give it a try, leave a comment here!

--sink-nickname works for <name> but not for <nick>

Steps to reproduce:

  1. copy paste default configuration for exec found inside README (here tweaked, it makes no difference)
exec = pulseaudio-control --icons-volume " , , " --icon-muted "" --sink-nicknames-from "device.description" 
--sink-nickname "alsa_output.pci-0000_00_1b.0.analog-stereo: speaker" 
--sink-nickname "alsa_output.usb-Kingston_HyperX_Virtual_Surround_Sound_00000000-00.analog-stereo" listen
  1. reload i3 with Mod + Shift + R

Expected behavior:

  • shows icon and text as supposed to (see --sink-nickname <name>:<nick> in pavu-control --help

What does NOT happen is the module displaying the nickname and icon I gave for the sink
image

[module/pulseaudio-control]
type = custom/script
tail = true
format-underline = #0000FF
label-foreground = ${colors.foreground}
;label-maxlen = 30

# Icons mixed from Font Awesome 5 and Material Icons
# You can copy-paste your options for each possible action, which is more
# trouble-free but repetitive, or apply only the relevant ones (for example
# --sink-blacklist is only needed for next-sink).
exec = pulseaudio-control --icons-volume " , , " --icon-muted "" --sink-nicknames-from "device.description" 
--sink-nickname "alsa_output.pci-0000_00_1b.0.analog-stereo: speaker" 
--sink-nickname "alsa_output.usb-Kingston_HyperX_Virtual_Surround_Sound_00000000-00.analog-stereo" listen
click-right = pulseaudio-control --sink-blacklist "alsa_output.pci-0000_01_00.1.hdmi-stereo-extra2" next-sink

Am I doing something wrong?
using arch linux
i3 as wm
picom as compositor

Code cleanup

There are many parts of the code that could do with a bit of cleaning up. I would very much appreciate any help on this, I can help out by reviewing any changes:

  • The script includes multiple ways of reading properties:

    1. With a while read in getNicknameFromProp
    2. With a good ol' grep pipe everywhere else

    The first actually seems more robust, but the second is more "bash"-y. I don't really care, anyway. The point is that they should be consistent.

  • getNickname is quite messy. The if statements could surely be simplified in some way. Or it should be commented internally, at least.

  • Overall, many commands are incredibly large and complicated. We could:

    • Split each pipe into a different line with \ so that it's more readable
    • Try to simplify them
  • Put all the simple getter functions at the beginning of the file

If anyone else thinks of other improvements, please leave them as a comment here!

Error flash on volume level change

Changing the volume causes the module to flash with the error message

./pulseaudio-control.sh: line 189: [: too many arguments

Similar result can be achieved by simply running the script from the command line;

δ ./pulseaudio-control.sh --listen
./pulseaudio-control.sh: line 189: [: too many arguments
# 75%   # 2                                                    

/sbin/pulseaudio-control: line 313: [: : Expected an integer expression

When i run the command:

$ pulseaudio-control --icons-volume " , " --icon-muted " " --sink-nicknames-from "device.description" --sink-nickname "alsa_output.pci-0000_00_1f.3.analog-stereo: Volume" listen

I get 2 errors:
/sbin/pulseaudio-control: line 313: [: : Expected integer expression
/sbin/pulseaudio-control: line 313: [: : Expected integer expression

The output of pactl list sinks short | cut -f2 is: alsa_output.pci-0000_00_1f.3.analog-stereo

inspecting the line 313 of the script it looks like it compares 2 different volumes

High idle CPU usage from Pipewire process

Been confused as to why pipewire has been idling at around 30% CPU usage for a while and I finally figured out it was being caused by pulseaudio-control when I was making changes to my config.

Here's my config:

[module/pulseaudio-control]
type = custom/script
tail = true
format-underline = ${colors.cyan}
label-foreground = ${colors.foreground}

exec = pulseaudio-control --format '$ICON_NODE $NODE_NICKNAME' --node-blacklist "*.monitor" --node-nickname 'alsa_output.pci-0000_0b*.analog-stereo:Desk' --node-nickname 'alsa_output.pci-0000_09*.hdmi-stereo-extra3:TV' output

click-left = pulseaudio-control next-node
click-right = exec pavucontrol &

And am running the latest version of pulseaudio-control:

pacman -Q pulseaudio-control          
pulseaudio-control 3.1.1-1

I noticed when when pulseaudio-control is enabled in Polybar, running pactl subscribe returns a ton of these messages:

...
Event 'remove' on client #75672
Event 'remove' on client #75671
Event 'new' on client #75673
Event 'new' on client #75674
Event 'remove' on client #75673
Event 'remove' on client #75674
Event 'new' on client #75675
Event 'new' on client #75676
Event 'remove' on client #75675
Event 'remove' on client #75676
Event 'new' on client #75677
Event 'new' on client #75678
Event 'remove' on client #75677
Event 'remove' on client #75678
Event 'new' on client #75679
Event 'new' on client #75680
Event 'remove' on client #75679
Event 'remove' on client #75680
Event 'new' on client #75681
Event 'new' on client #75682
Event 'remove' on client #75681
Event 'remove' on client #75682
Event 'new' on client #75683
Event 'new' on client #75684
Event 'remove' on client #75683
Event 'remove' on client #75684
Event 'new' on client #75685
Event 'new' on client #75686
Event 'remove' on client #75685
Event 'remove' on client #75686
Event 'new' on client #75687
Event 'remove' on client #75687
Event 'new' on client #75688
Event 'remove' on client #75688
Event 'new' on client #75689
Event 'remove' on client #75689
Event 'new' on client #75690
Event 'remove' on client #75690
Event 'new' on client #75691
Event 'remove' on client #75691
Event 'new' on client #75692
Event 'remove' on client #75692
Event 'remove' on client #72539
Event 'remove' on client #72538
Event 'new' on client #75693
Event 'new' on client #75694
...

And that's with no desktop applications at all running on the machine.

I think this may be related to #68 but I don't know how to verify that.

Any help would be appreciated! This module is an incredibly useful addition to Polybar.

Packaging for distros

This is an issue to discuss packaging for distros or just any Operating System that may work with pulseaudio-control. Currently:

If you want to add this module to your distro or have any concerns regarding the already existing packages, create a new comment here.

Add a test script

It doesn't have to be too detailed, but it'd be nice to have a test script to make sure the most basic functions always work as intended.

  • Test for volUp
  • Test for volDown
  • Test for changeDevice
  • Test for volSync
  • Test for volMute (all three cases)
  • listen behaviour (#9 and #20 should be finished first)
  • More specific edge cases

Specify a minimum bash version

The script currently uses maps, which I think is a relatively new feature on bash. It'd be a good idea to mention the minimum version required in the README dependencies section.

Documentation for port names

The port names feature merged in #43 should be documented before creating a new release. The thing is that the left column for commands and such is getting too big to add new things to the commands, leaving almost no space for the command's description. So perhaps it'd be be best to trim the options and add the format to the descriptions, or not use columns at all.

specify multiple blacklist devices only reads first entry

Issue: when specifying multiple sinks to blacklist using the --sink-blacklist flag only the first entry is read.

Can you please tell me if this is a formatting issue on my side?

--sink-blacklist <name>[,<name>...] Sinks to ignore when switching. Default: none

click-middle = /usr/bin/pulseaudio-control.bash --sink-blacklist "alsa_output.usb-SteelSeries_Arctis_Pro_Wireless-00.mono-chat, alsa_output.usb-SENUCN_Digital_Hifi_Audio-00.iec958-stereo" next-sink

pactl list sinks short [15:30:38] 0 alsa_output.usb-SteelSeries_Arctis_Pro_Wireless-00.mono-chat module-alsa-card.c s16le 1ch 44100Hz SUSPENDED 1 alsa_output.usb-SteelSeries_Arctis_Pro_Wireless-00.stereo-game module-alsa-card.c s16le 2ch 44100Hz RUNNING 2 alsa_output.usb-SENUCN_Digital_Hifi_Audio-00.iec958-stereo module-alsa-card.c s16le 2ch 44100Hz SUSPENDED 4 alsa_output.pci-0000_01_00.1.hdmi-stereo module-alsa-card.c s16le 2ch 44100Hz SUSPENDED

Many unnecessary updates

I've noticed that when using the script, getCurSink is called twice, and other unnecessary updates are done. I'll document it to do more research and fix it once I have more time:

Only running the script:

❯ bash pulseaudio-control-debug.sh 
getCurSink called
getCurSink called
getCurlVol called
getVolMuteStatus called
 18%    1

Volume up -> volume down -> single sink switch -> mute (output is called too many times?)

❯ bash pulseaudio-control-debug.sh --listen
getCurSink called
getCurSink called
getCurlVol called
getVolMuteStatus called
 18%    1
getCurSink called
getCurlVol called
getVolMuteStatus called
 20%    1
getCurSink called
getCurlVol called
getVolMuteStatus called
 18%    1
getCurSink called
getCurlVol called
getVolMuteStatus called
 58%    2
getCurSink called
getCurlVol called
getVolMuteStatus called
 58%    2
getCurSink called
getCurlVol called
getVolMuteStatus called
 58%    2
getCurSink called
getCurlVol called
getVolMuteStatus called
 58%    2
getCurSink called
getCurlVol called
getVolMuteStatus called
 58%    2
getCurSink called
getCurlVol called
getVolMuteStatus called
%{F#6b6b6b} 58%    2%{F-}

Random update when seemingly nothing changed:

❯ bash pulseaudio-control-debug.sh --listen
getCurSink called
getCurSink called
getCurlVol called
getVolMuteStatus called
 18%    1
getCurSink called
getCurlVol called
getVolMuteStatus called
 18%    1

Update when a new song starts (unnecessary):

❯ bash pulseaudio-control-debug.sh --listen
getCurSink called
getCurlVol called
getVolMuteStatus called
 18%    1
getCurSink called
getCurlVol called
getVolMuteStatus called
 18%    1
getCurSink called
getCurlVol called
getVolMuteStatus called
 18%    1
getCurSink called
getCurlVol called
getVolMuteStatus called
 18%    1

Update when the song is paused (unnecessary):

❯ bash pulseaudio-control-debug.sh --listen
getCurSink called
getCurlVol called
getVolMuteStatus called
 18%    1
getCurSink called
getCurlVol called
getVolMuteStatus called
 18%    1

Increasing & decreasing the volume (curiously, getCurVol is only called once for the latter)::

❯ bash pulseaudio-control-debug.sh --up    
getCurSink called
volUp called
getCurlVol called
getCurlVol called

❯ bash pulseaudio-control-debug.sh --down
getCurSink called
volDown called
getCurlVol called

Other calls:

❯ bash pulseaudio-control-debug.sh --sync
getCurSink called
volSync called
getSinkInputs called
getCurlVol called

❯ bash pulseaudio-control-debug.sh --change
getCurSink called
changeDevice called

Customize or label auto_null

When I am connected via VNC - the output displays "Dummy Output". It would be able to detect this and modify / blacklist or label

pulseaudio-control sees it as auto_null

pactul list sinks output:
Sink #395
State: IDLE
Name: auto_null
Description: Dummy Output
Driver: PipeWire
Sample Specification: float32le 2ch 48000Hz
Channel Map: front-left,front-right
Owner Module: 4294967295
Mute: no
Volume: front-left: 65536 / 100% / 0.00 dB, front-right: 65536 / 100% / 0.00 dB
balance 0.00
Base Volume: 65536 / 100% / 0.00 dB
Monitor Source: auto_null.monitor
Latency: 0 usec, configured 0 usec
Flags: DECIBEL_VOLUME LATENCY
Properties:
node.name = "auto_null"
device.description = "Dummy Output"
audio.rate = "48000"
audio.channels = "2"
audio.position = "FL,FR"
media.class = "Audio/Sink"
factory.name = "support.null-audio-sink"
node.virtual = "true"
monitor.channel-volumes = "true"
factory.id = "18"
clock.quantum-limit = "8192"
client.id = "31"
node.driver = "true"
factory.mode = "merge"
audio.adapt.follower = ""
library.name = "audioconvert/libspa-audioconvert"
object.id = "54"
object.serial = "395"
Formats:
pcm

OSD doesn't work

It doesn't like my OSD on Plasma 5.22.5 (Arch Linux).
Cannot find '.showVolume' in object /modules/kosd at org.kde.kded

Consider using arguments to configure the module, rather than constants inside the script

It might be a good idea to use arguments rather than constants at the top of the script. For example SINK_BLACKLIST=(a b c) would become --sink-blacklist a --sink-blacklist b --sink-blacklist c or --sink-blacklist a,b,c.

There are of course downsides and upsides to this:

Pros

  • Using arguments would make it possible to have multiple Polybar modules with a single script. This doesn't really make sense with the current behavior, but if #25 is implemented it would be less troublesome to configure it for both sinks and microphones.

  • Using arguments is more user friendly and manageable than modifying the script, I'd say. It's also easier to update the script because you can just replace it.

Cons

  • Using parameters would imply repetition, as the script would need to be configured whenever it's called. The polybar module would be harder to manage and configure. It would mean long and repetitive commands for each keybinding.

AUR packaging

I'll make a PKGBUILD soon so that it can be uploaded.

Duplicate & useless events from `pactl subscribe`

This is a single 2% volume increase:

❯ pactl subscribe
Event 'new' on client #217
Event 'remove' on client #217
Event 'new' on client #218
Event 'remove' on client #218
Event 'new' on client #219
Event 'change' on client #219
Event 'change' on sink #0
Event 'remove' on client #219
Event 'new' on client #220
Event 'remove' on client #220
Event 'new' on client #221
Event 'remove' on client #221
Event 'new' on client #222
Event 'remove' on client #222

It also creates events for currently useless things, like new songs playing and such. Here's the output when a new song starts on Spotify:

❯ pactl subscribe
Event 'change' on sink-input #0
Event 'change' on sink #0
Event 'change' on sink #0
Event 'change' on sink-input #0
Event 'new' on client #224
Event 'remove' on client #224
Event 'new' on client #225
Event 'remove' on client #225
Event 'new' on client #226
Event 'remove' on client #226
Event 'new' on client #227
Event 'remove' on client #227
Event 'new' on client #228
Event 'remove' on client #228
Event 'new' on client #229
Event 'remove' on client #229
Event 'new' on client #230
Event 'remove' on client #230
Event 'new' on client #231
Event 'remove' on client #231
Event 'new' on client #232
Event 'remove' on client #232
Event 'new' on client #233
Event 'remove' on client #233
Event 'new' on client #234
Event 'remove' on client #234
Event 'new' on client #235
Event 'remove' on client #235

Not sure if there's anything I can do here, but I should investigate regardless.

Next to % of volume says Sink #0

Hi, i have been using your script for volume control and everything works fine, but next to % of volume it says Sink #0. I have tried to remove it with some flags ( for example --autosync) but it didn`t work. It is small thing and i am sure that it is only for me but it is a bit annoying.

If you could help it would be much appreciated!

volumecontrolscript
ps

Error when pulseaudio is loading

image

This only happens when pulseaudio starts running (sometimes). It does go away, but it still should be fixed. At this line:

# Fixed volume icons over max volume
local iconsLen=${#VOLUME_ICONS[@]}
if [ "$iconsLen" -ne 0 ]; then
    local volSplit=$((MAX_VOL / iconsLen))
    for i in $(seq 1 "$iconsLen"); do
        if [ $((i * volSplit)) -ge $curVol ]; then  # <-- Here
            volIcon="${VOLUME_ICONS[$((i-1))]}"
            break
        fi
    done
else
    volIcon=""
fi

It happens in the ouput function, which does check if pulseaudio is running, but as it's still loading some obtained variable is probably incorrect (curVol?). The bug should be fixed by checking for errors when getCurSink, getCurVol and getCurMuteStatus are called. This could also implement a better solution to check if pulseaudio is running, rather than this:

if [ -z "$(pgrep pulseaudio)" ]; then echo "Pulseaudio not running"; return 1; fi

The design choice here is whether the return value of these functions should be checked, or maybe they handle the errors by themselves and exit the script.

pulseaudio-control does not quit correctly on shutdown, resulting in 90 second shutdown and reboot times


As you can see from this screenshot above, on shutting down or rebooting my system, a long 1m30s wait happens because of pulseaudio-control.

You can see from the line Nov 04 22:16:46 Kappa wireplumber[704]: to Nov 04 22:18:15 Kappa systemd[1]: session-1.scope: Stopping timed out. Killing. there is a 1m30s wait. This is the default timeout for systemd for hanging processes on reboot. I know this because editing the file /etc/systemd/system.conf and setting

DefaultTimeoutStartSec=10s
DefaultTimeoutStopSec=10s

will make the timeout 10 seconds.

I know it's pulseaudio-control because it is the only program running on my system, as my user, that uses pactl and bash. The rest of my scripts are set to use dash. It also shows polybar as still running, which is probably still running because it's trying to close pulseaudio-control.

This is a pretty serious issue considering it increases my shutdown and reboot times by 90 seconds. Let me know if you need any more info and I'll be happy to provide it for you.

Thanks for the amazing work on the script otherwise!
Fazzi

No updates in `listen` when switching between microphones

The PR #64 introduced the on client pattern to the command in grep. However, that ends up consuming lots of CPU power even when the script isn't being used. For instance, I get on client events when playing music, which shouldn't update.

The easy fix would be to just remove on client from the patterns. However, we added that because without it, the microphone listen function didn't work in some specific cases. I'm still not sure which cases these are, though.

This was reported by Viterzgir at https://aur.archlinux.org/packages/pulseaudio-control.

/cc @Aerion

"Pluseaudio not started" error produces high CPU load for polybar

Occasionally upon system startup pulseaudio-control returns "Pulseaudio not started" in polybar. If I run the commands manually from the terminal I do get the expected volume percentages. I have to restart polybar one or two times to get this to resolve.

When this occurs, my system CPU increases to 30%+ and top reports polybar's CPU utilization is something like 7-8% instead of it's normal 0.6-0.7%. Once I restart polybar and correct the "Pulseaudio not started" error, CPU utilization returns to normal.

This only seems to happen intermittently when I start up my system or when I wake from sleep. My assumption is that there is some race condition.

Seems to be two things happening here though:

  1. pulseaudio-control listen is losing communication with pulseaudio, even though pulseaudio is running
  2. Polybar or pulseaudio is going haywire when it is in this state.

Let me know what other information I can provide to help to identify what the issue is.

This is my setup

[module/pulseaudio-control-input]
type = custom/script
tail = true
double-click-left = exec pavucontrol &
exec = pulseaudio-control --node-nicknames-from "device.description" --node-nickname "alsa_input.pci*: " --node-type input --icon-muted  --icons-volume "" --format '$VOL_ICON ${VOL_LEVEL}% $ICON_NODE $NODE_NICKNAME'  listen

[module/pulseaudio-control-output]
type = custom/script
tail = true
double-click-left = exec pavucontrol &
exec = pulseaudio-control --node-nicknames-from "device.description" --node-nickname "alsa_output.pci*:󰓃" --node-type output --icon-muted  --icons-volume " " --format '$VOL_ICON ${VOL_LEVEL}% $ICON_NODE $NODE_NICKNAME'  listen

CLI flag followed by value removes the value

Hello,

When the last CLI flag is one that doesn't expect any argument (e.g. --osd), the last CLI argument is not taken into accound.

To reproduce, in its simplest form

# Expected results: displays the output
$ pulseaudio-control --osd output
Unrecognised action:
# Expected results: throws an error as this_argument_is_ignored is invalid
$ pulseaudio-control --osd this_argument_is_ignored output
64% Sink #69

There is a workaround: to either follow it with a random arg that will get discarded, or ensure that the following argument is a one starting with --.

Best,

Help message rather than showing the status by default

Currently, there is no --help parameter. This would come in handy for new users, and should also point to this repository.

This would mean that whenever an argument isn't found, rather than calling output, the help message would be shown. Current behaviour:

case "$1" in
    --up)
        volUp
        ;;

    # Other arguments

    *)
        # By default print output for bar.
        output
        ;;
esac

More flexible / more general portnames?

Hello,

I've been using this script for quite some time now (probably over 2 years), thank you so much for all the work you put in it.

Recently I bought a new laptop, and on this machine, with Ubuntu 22.04.2, pactl list sinks reports ports as e.g. [Out] Speaker or [Out] Headphones. Unfortunately, the script only matches on [Out], which makes it impossible to use --node-nickname to distinguish between headphones and laptop speakers (by displaying different icons) .

One possible fix is to change awk '/Active Port: / {print $3}' with awk '/Active Port: / {print $3$4}' in getNodeName() (so that I can match on [Out]Speaker).

That simple fix works for my use case, and does not seem to cause issues when the port description does not contain spaces, but I don't know how generalizable you would want the solution to be here. What if there are more than two fields? Do you want to account for that? Maybe use something else than awk and simply return everything that follows Active Port:?

Allow variable substitution in --color-muted

I use wal to theme my system, and for most modules I could use something like
format-muted = ${colors.disabled} to make the module highlight red when muted, or use
--color-muted ${colors.disabled} in my call to the pulseaudio-control bash script, but I get /bin/bash line 1: bad substitution when I do that.
Is there an undocumented way to change the color of the module when muted, or some way to correctly escape the color such that it can be read?

No longer updates every time volume changes

When changing my volume, a visual update is painfully slow and (as I have a keyboard with a volume wheel, and thus have it set up so that volume goes up by only one each time), it makes it really difficult to set a precise volume now without going really slowly to wait for it to update. Below is running the same command through the terminal, and you can see that it is skipping a bunch, where as pre 3.0.0 updated at every change.
image
Is this intended behaviour? I really hope not, or I'll have to stick to the outdated version.

Better OSD support

The current OSD feature only works for KDE. It'd be nice to have it on Gnome, too (for example).

There isn't a standard way to show OSD messages (unlike for notifications), so the current Desktop Environment would have to be checked. This would be done at startup, and saved into a variable later checked when the OSD is displayed. I'm not sure about all the available DEs with OSD support, nor have the time to test them all, so I'd appreciate help on this one.

Error flash on volume change - line 231

Hi,

Changing the volume causes the following error message to display:
/pulseaudio-control.sh: line 231: [: : integer expression expected
If I run the script from the command line I get the following awk errors as well:

./pulseaudio-control.sh --listen
awk: line 1: regular expression compile failed (missing operand)
* index:
awk: line 1: regular expression compile failed (missing operand)
* index:
./pulseaudio-control.sh: line 231: [: : integer expression expected
# 24%   # 

From what I understand the error is related to the custom sink icons - I didn't set any (didn't event modify the script) but I don't really care about them.

Small issue and easyeffects

Hi!
I have a small issue where, I run pactl I receive this:
ppc
(I checked to see if there was a difference when I had headphones plugged in and the result was the same. i.e pactl list sinks | grep Name from issue #61 the listed sinks remain the same output)
I have tried changing the --sink-name to either one to see if it change anything but nothings working at this point and I have 0 experience with pulse/pipewire/easyeffects any sound related thing.
ppc2

system:
endeavouros
i3wm
any help is appreciated thanks!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.