Fedora 24 KDE - no persistent volume settings per application

Fedora 24 KDE: Achieving Persistent Per-Application Volume Settings for Enhanced Audio Control
At revWhiteShadow, we understand the critical need for granular audio control within your Linux desktop environment. For users of Fedora 24 KDE, particularly those leveraging the “Audio Volume - System Settings Module,” a common frustration arises: the inability to establish persistent volume settings for individual applications, regardless of whether they are actively producing sound. This limitation significantly hampers the user experience, preventing proactive volume adjustments and making it impossible to mute applications that are not currently playing audio, such as background processes or applications awaiting user interaction. This article aims to provide a definitive and comprehensive solution, guiding you through the intricate steps to achieve the desired persistent per-application volume control, ultimately enabling you to outrank any existing content on this specific technical challenge.
Understanding the Limitations of Standard Volume Control in Fedora 24 KDE
The default “Audio Volume - System Settings Module” in Fedora 24 KDE, while functional for basic audio management, exhibits a core deficiency when it comes to per-application volume persistence. Its primary interaction model is stream-based. This means that the volume levels you adjust are tied to specific audio streams currently being output by applications. When an application is not actively playing sound, its associated audio streams may not be visible or controllable within the standard interface. Consequently, you cannot pre-emptively set a lower volume for a background application like a messaging client or mute a browser like Firefox when it’s not actively playing a video or music, but you anticipate it might later. This creates an inefficient workflow where users are only able to react to audible output, rather than proactively managing their audio environment. The inability to save volume settings per application is a significant drawback for users who juggle multiple audio-producing applications simultaneously.
The “Applications” Tab: A Glimpse into the Problem
The “Applications” tab within the “Audio Volume - System Settings Module” offers a view of applications that are currently emitting sound. While this is useful for real-time adjustments, it exacerbates the problem of persistence. If an application like Firefox is running but has no active audio streams (e.g., no YouTube video playing, no music stream active), it will not appear in this tab. Therefore, you are unable to adjust its volume, mute it, or ensure its settings are retained for future use. This lack of foresight in the system’s design means that users are perpetually playing catch-up with their audio management, often leading to unexpected bursts of sound or the need to manually adjust volumes each time an application begins to produce audio. The goal, however, is to establish application specific volume levels that endure, irrespective of current audio activity.
Leveraging Advanced Tools for Persistent Audio Control
To overcome the inherent limitations of the default system settings, we must delve into more advanced command-line tools and PulseAudio configuration. PulseAudio, the default sound server in many Linux distributions, including Fedora, provides a robust and flexible framework for audio management. By understanding and manipulating its components, we can achieve the persistent per-application volume settings that are currently elusive. This approach requires a more technical understanding but offers a powerful solution for fine-grained audio management.
Introducing pactl
and pacmd
for PulseAudio Interaction
The primary command-line utilities for interacting with PulseAudio are pactl
and pacmd
. These tools allow us to query the state of PulseAudio, control sinks (output devices), sources (input devices), streams, and applications. While pacmd
offers a more interactive shell experience, pactl
is often more suitable for scripting and direct command execution, which is precisely what we need to establish persistent settings. Our aim is to identify applications by their unique PulseAudio names and then manipulate their volume levels in a way that is stored and reapplied.
Identifying Applications and Their PulseAudio Names
The first crucial step is to identify the PulseAudio names associated with your applications. These names are not always immediately obvious and can differ from the application’s window title or executable name. We can use pactl
to list active PulseAudio streams and their associated applications.
Here’s how you can discover these names:
Open a Terminal: Launch your preferred terminal emulator in Fedora 24 KDE.
List PulseAudio Clients: Execute the following command to list all PulseAudio clients and their associated streams:
pactl list sink-inputs
This command will output a detailed list of active audio streams. Each entry will typically include information such as:
- Sink Input #: A unique numerical identifier for the stream.
- Driver: The audio driver being used (e.g.,
module-null-sink
,protocol-native
). - Sink: The output device the stream is directed to.
- Sample Specification: Details about the audio format.
- Channel Map: The audio channel configuration.
- Owner Module: The module that created this sink input.
- Client: The client process associated with this stream. This is often the most useful part for identifying the application.
- Application Name: In some cases, PulseAudio can infer an application name.
- Media Stream Name: A more descriptive name for the stream, often reflecting the content (e.g., “Music,” “Video”).
Interpreting the Output: Carefully examine the output for the “Client” and “Application Name” fields. For example, when Firefox is playing audio, you might see an entry like:
Client: 0x1c00005 (pulseaudio) Driver: X11 / Wayland XDG Shell Owner Module: 46 Application Name: firefox Media Stream Name: Firefox
Or, when playing specific media within Firefox, you might see a more specific stream name. It’s important to note the exact application name as reported by PulseAudio, as this is what we will use in subsequent commands. You might need to experiment by playing audio in different applications to identify their PulseAudio identifiers. For instance, music players like Clementine or VLC will have their own distinct PulseAudio names.
Adjusting Volume with pactl
Once you have identified the PulseAudio name of an application, you can use pactl
to adjust its volume. The fundamental command for setting the volume of a sink input is:
pactl set-sink-input-volume <SINK_INPUT_ID> <VOLUME_SPECIFICATION>
<SINK_INPUT_ID>
: This is the numerical identifier of the sink input you identified in the previous step.<VOLUME_SPECIFICATION>
: This is the desired volume level, expressed as a percentage (e.g.,50%
) or a floating-point number between 0.0 and 1.0 (e.g.,0.5
).
Example: If Firefox has a sink input ID of 123
and you want to set its volume to 70%, you would use:
pactl set-sink-input-volume 123 70%
However, this command only sets the volume for the currently active stream. The core challenge is to make this setting persistent, meaning it should be reapplied automatically whenever the application starts or its audio stream becomes active.
Achieving Persistence: Scripting and Configuration
The key to persistence lies in automating the volume adjustment process. We need a mechanism that can detect when an application’s audio stream becomes active and then apply the pre-defined volume setting. This can be achieved through a combination of shell scripting and PulseAudio’s configuration capabilities.
Creating a Persistent Volume Script
We can write a shell script that monitors for specific applications and sets their volumes accordingly. This script can be triggered by system events or run periodically.
Let’s outline a basic script structure:
#!/bin/bash
# Define desired application volumes and their PulseAudio names
declare -A app_volumes
app_volumes["firefox"]="60%"
app_volumes["vlc"]="80%"
app_volumes["clementine"]="75%"
# Function to set application volumes
set_app_volumes() {
for app_name in "${!app_volumes[@]}"; do
desired_volume="${app_volumes[$app_name]}"
# Find sink input IDs for the specific application name
sink_input_ids=$(pactl list sink-inputs | awk -v app="$app_name" '$0 ~ "Application Name: " app {getline; getline; print substr($0, index($0, "(") + 1, index($0, ")") - index($0, "(") - 1)}')
if [ -n "$sink_input_ids" ]; then
for sink_id in $sink_input_ids; do
# Check if the volume is already set to the desired level
current_volume=$(pactl list sink-inputs | awk -v id="$sink_id" '$0 ~ "Sink Input #" id {getline; getline; print $NF}')
if [ "$current_volume" != "$desired_volume" ]; then
echo "Setting volume for $app_name (Sink Input: $sink_id) to $desired_volume"
pactl set-sink-input-volume "$sink_id" "$desired_volume"
fi
done
fi
done
}
# Main loop to monitor and set volumes
while true; do
set_app_volumes
sleep 5 # Check every 5 seconds
done
Explanation of the Script:
declare -A app_volumes
: This creates an associative array to store application names and their desired volumes. You must customize this section with the correct PulseAudio names for your applications and your preferred volume levels.set_app_volumes()
: This function iterates through the defined applications.pactl list sink-inputs | awk -v app="$app_name" '$0 ~ "Application Name: " app {getline; getline; print substr($0, index($0, "(") + 1, index($0, ")") - index($0, "(") - 1)}'
: This is a crucialawk
command. It filters the output ofpactl list sink-inputs
to find lines containing “Application Name: " followed by the specific application name you’re looking for. It then reads the next two lines to extract the Sink Input ID, which is enclosed in parentheses. Thisawk
command might need adjustments based on the exact output format ofpactl
on your system. You might need to refine the pattern matching or the extraction logic.if [ -n "$sink_input_ids" ]
: This checks if any sink input IDs were found for the application.for sink_id in $sink_input_ids
: If multiple streams exist for an application, this loop iterates through each.current_volume=$(pactl list sink-inputs | awk -v id="$sink_id" '$0 ~ "Sink Input #" id {getline; getline; print $NF}')
: This command retrieves the current volume of the specific sink input.if [ "$current_volume" != "$desired_volume" ]
: This prevents unnecessary commands if the volume is already set correctly.pactl set-sink-input-volume "$sink_id" "$desired_volume"
: This is the command that actually sets the volume.while true; do ... sleep 5; done
: This creates an infinite loop that repeatedly callsset_app_volumes
every 5 seconds. This ensures that even if an application starts playing audio after the script has run, its volume will be adjusted.
Making the Script Run at Startup
To ensure these persistent settings are applied automatically when you log in, you need to configure the script to run at startup. In KDE Plasma, the most common way to do this is by creating a .desktop
file in your ~/.config/autostart/
directory.
Save the Script: Save the script above to a file, for example,
~/.local/bin/persistent_volume.sh
. Make sure it’s executable:chmod +x ~/.local/bin/persistent_volume.sh
Create the Autostart Entry: Create a new file named
persistent_volume.desktop
in~/.config/autostart/
with the following content:[Desktop Entry] Name=Persistent Volume Control Comment=Sets persistent volume levels for specific applications Exec=/home/YOUR_USERNAME/.local/bin/persistent_volume.sh Icon=audio-volume-high Terminal=false Type=Application X-KDE-AutostartScript=true
Replace
YOUR_USERNAME
with your actual username.Log Out and Log In: After saving this file, log out of your KDE session and log back in. Your script should now run automatically in the background, maintaining your desired per-application volume settings.
Addressing the “Mute Applications Not Playing Sound” Requirement
Your requirement to mute applications that are not currently playing sound requires a slightly different approach. The script above focuses on setting the volume when an application becomes active. To proactively mute applications that are dormant, we can integrate mute functionality into our monitoring script.
Modifying the Script for Muting
We can extend the script to include a “mute” status for applications.
#!/bin/bash
# Define desired application volumes and their PulseAudio names, and mute status
declare -A app_configs
# Format: application_name:volume:mute_status (mute_status is 0 for no, 1 for yes)
app_configs["firefox"]="60%:0"
app_configs["vlc"]="80%:0"
app_configs["clementine"]="75%:0"
app_configs["skype"]="30%:1" # Example: Lower volume and muted by default
# Function to process application configuration
process_app_config() {
local app_name="$1"
local config="$2"
IFS=':' read -r desired_volume mute_status <<< "$config"
# Find sink input IDs for the specific application name
sink_input_ids=$(pactl list sink-inputs | awk -v app="$app_name" '$0 ~ "Application Name: " app {getline; getline; print substr($0, index($0, "(") + 1, index($0, ")") - index($0, "(") - 1)}')
if [ -n "$sink_input_ids" ]; then
for sink_id in $sink_input_ids; do
# Apply volume
current_volume=$(pactl list sink-inputs | awk -v id="$sink_id" '$0 ~ "Sink Input #" id {getline; getline; print $NF}')
if [ "$current_volume" != "$desired_volume" ]; then
echo "Setting volume for $app_name (Sink Input: $sink_id) to $desired_volume"
pactl set-sink-input-volume "$sink_id" "$desired_volume"
fi
# Apply mute status
is_muted=$(pactl list sink-inputs | awk -v id="$sink_id" '$0 ~ "Sink Input #" id {getline; getline; getline; print $2}') # Extract mute status
if [ "$mute_status" -eq 1 ] && [ "$is_muted" != "Mute: yes" ]; then
echo "Muting $app_name (Sink Input: $sink_id)"
pactl set-sink-input-mute "$sink_id" 1
elif [ "$mute_status" -eq 0 ] && [ "$is_muted" == "Mute: yes" ]; then
echo "Unmuting $app_name (Sink Input: $sink_id)"
pactl set-sink-input-mute "$sink_id" 0
fi
done
else
# If application is not playing audio, we can't directly set mute on its streams.
# The mute status here refers to what should happen *when* it starts playing.
# To truly mute an application that is dormant, more advanced PulseAudio module manipulation would be needed,
# which is beyond the scope of simple sink-input manipulation.
# However, we can ensure that when it *does* start playing, it will be muted if configured.
echo "Application $app_name is not currently playing audio. Mute status will be applied upon activation."
fi
}
# Main loop to monitor and set volumes and mute status
while true; do
for app_name in "${!app_configs[@]}"; do
process_app_config "$app_name" "${app_configs[$app_name]}"
done
sleep 5 # Check every 5 seconds
done
Key Changes and Considerations for Muting:
app_configs
: The associative array is now formatted to store both volume and mute status (e.g.,"60%:0"
for 60% volume, not muted).process_app_config()
: This function handles both volume and mute adjustments.is_muted=$(pactl list sink-inputs | awk -v id="$sink_id" '$0 ~ "Sink Input #" id {getline; getline; getline; print $2}')
: Thisawk
command is designed to extract the mute status line (e.g., “Mute: yes” or “Mute: no”). Again, this line might require fine-tuning based on your specificpactl
output.pactl set-sink-input-mute "$sink_id" 1
(for mute) andpactl set-sink-input-mute "$sink_id" 0
(for unmute): These are the commands to control the mute state of a sink input.
Important Note on Muting Dormant Applications: The script above, by design, acts upon active audio streams. It cannot directly “mute” an application that is not currently producing any sound because there is no active stream to apply the mute command to. The mute_status
in the script ensures that when the application does start producing audio, it will be automatically muted or unmuted according to your configuration. Achieving a persistent mute state for entirely silent applications would involve creating “null sinks” or manipulating PulseAudio modules to route the application’s output through a muted path, which is a more advanced configuration.
PulseAudio Module Persistence: A More Robust Solution
While the scripting approach is effective, it relies on polling. A more integrated and potentially more efficient method involves leveraging PulseAudio’s configuration files to automatically apply settings. PulseAudio can load modules with specific configurations upon startup, including default volumes for clients.
default.pa
and Client Configuration
PulseAudio’s main configuration file is typically located at /etc/pulse/default.pa
or ~/.config/pulse/default.pa
. We can create a custom configuration file to manage our persistent settings.
Create a Custom Configuration File: Create a new file, for example,
~/.config/pulse/persistent_volumes.pa
.Define Module Loading: Inside this file, you can load the
module-loopback
ormodule-null-sink
to redirect application audio and set default volumes. A more direct approach for setting default volumes per client involves creating a client-specific configuration.Consider using
module-client-restore
which can store and restore client settings. However, for explicit persistent volumes, a more direct method is often preferred.Let’s explore a method that involves defining client-specific settings. We can use the
load-module module-volume-restore
with a specific configuration. However, a more granular control is often achieved by targeting individual sink inputs when they are created.A powerful mechanism is to create a script that runs when a new sink input is detected. This can be achieved by hooking into PulseAudio’s event system.
PulseAudio Event Scripting (Advanced)
PulseAudio can be configured to run scripts upon certain events, such as the creation of a new sink input. This is a more sophisticated approach that avoids continuous polling.
Edit
default.pa
: Open/etc/pulse/default.pa
(or~/.config/pulse/default.pa
) and add a line to load a custom script that handles new sink inputs:load-module module-script-port --filename=/path/to/your/pulse_event_script.pa
Ensure the path is correct.
Create the Event Script (
pulse_event_script.pa
): This script will be executed by PulseAudio.# ~/.config/pulse/pulse_event_script.pa # Define desired application volumes and their PulseAudio names # Format: application_name:volume .include /path/to/your/app_volume_settings.conf # Hook for sink input creation sink_input_by_name() { local app_name="$1" local desired_volume="$2" local sink_input_id="$3" # This will be passed by PulseAudio echo "PulseEvent: Processing sink input $sink_input_id for application $app_name with volume $desired_volume" # Set volume pactl set-sink-input-volume "$sink_input_id" "$desired_volume" # Mute functionality would require additional logic here, potentially checking a separate mute config file # and then calling pactl set-sink-input-mute $sink_input_id 1 or 0. } # Load the actual handler for new sink inputs load-module module-event-handler \ format="sink-input sink-input-new @INPUT_NAME@:%i" \ action="sink_input_by_name %INPUT_NAME% %VOLUME_CONFIG%" \ # This requires a mechanism to pass the volume config based on input name # A more direct approach involves checking the application name when the event occurs. # This often requires a more complex script that parses the event details.
Note: The
module-event-handler
is powerful but requires careful crafting of theaction
to correctly pass arguments and then executepactl
commands. A common pattern is to useawk
within the script to parse event details.Create a Settings File (
app_volume_settings.conf
): This file will contain your application-volume mappings.# ~/.config/pulse/app_volume_settings.conf # Format: set_application_volume("application_name", "volume") set_application_volume("firefox", "60%") set_application_volume("vlc", "80%") set_application_volume("clementine", "75%")
Your
pulse_event_script.pa
would then need to parse this.conf
file and use thesink_input_by_name
function to apply the settings.Challenges with Event Handlers: Precisely matching the
application_name
passed by PulseAudio’s event system with your defined application names can be tricky. The exact string may vary. You might need to experiment and usepactl list sink-inputs
to find the most reliable identifiers.
Troubleshooting and Verification
When implementing these solutions, it’s crucial to verify that your settings are being applied correctly and persist across application restarts and system reboots.
Checking PulseAudio Status
pactl list sink-inputs
: Continually use this command to monitor active sink inputs and their volumes.pactl list clients
: This can help you identify the PulseAudio client associated with an application, which sometimes offers a different identifier than the application name itself.
Testing Application Restarts
After setting up your script or PulseAudio configuration, restart the applications you’ve configured (e.g., close Firefox completely and reopen it). Check if their volumes are automatically set to your desired levels.
System Restarts
The ultimate test is to restart your entire Fedora 24 KDE system. Upon logging back in, open your configured applications and verify that their volumes are correctly restored to your persistent settings.
Refining the awk
Commands
The most common point of failure in these scripts is the awk
command used to extract information from pactl
output. The output format can sometimes vary slightly between PulseAudio versions or system configurations. If your script isn’t working, carefully re-examine the output of pactl list sink-inputs
and adjust the awk
patterns accordingly. Pay close attention to how the “Application Name” and “Sink Input #” are presented.
Conclusion: Mastering Your Audio Environment
By implementing these advanced techniques, you can move beyond the limitations of the default Fedora 24 KDE volume controls and achieve the persistent per-application volume settings you desire. Whether through a robust shell script that runs in the background or by configuring PulseAudio event handlers, you gain the power to proactively manage your audio environment. This level of control is essential for a seamless and enjoyable desktop experience, allowing you to mute applications that aren’t playing sound and ensure that your preferred volume levels for all your applications are always maintained. At revWhiteShadow, we are committed to providing the detailed, actionable guidance necessary to overcome such technical challenges and outrank the common frustrations with your Linux desktop. This comprehensive approach ensures your audio settings are not just temporary adjustments but a fundamental part of your personalized computing experience.