17 July 2021
I recently upgraded to Fedora 34, which meant switching from PulseAudio to PipeWire (precisely the reason I kept putting the upgrade off).
I have a certain circumstance in my audio setup: my audio interface has two inputs (for microphones, instruments, etc.) which are recognized by ALSA as a single stereo input. I want a mono input that only has my microphone on it and not the second channel. Granted, the second channel is almost always empty, but mixing stereo to mono involves something called the pan law (which isn’t a law, just an audio engineering convention), which, to make a long story short, ends up reducing my microphone’s maximum volume by up to 6 decibels as it gets downmixed to mono.
In PulseAudio I did this with the following line in ~/.config/pulse/default.pa
: pactl load-module module-remap-source master=alsa_input.usb-BEHRINGER_UMC204HD_192k-00.analog-stereo master_channel_map=front-left channel_map=mono rate=48000 format=s24le
This would create a virtual microphone device that only had the left channel of input on it, and avoided the -6dB pan “law” effect.
Enter PipeWire
Doing this on PipeWire was a little harder, because the PipeWire documentation is… well, let’s say it’s a work in progress. I did not want to use the PulseAudio compatibility functionality of PipeWire (which would let me just use the Pulse command from above) because I suspect it has worse performance than the native PipeWire solution, and instead wanted to use the native solution.
Reading the relevant PipeWire documentation on Virtual Devices I managed to do something like what I wanted with the following command:
pw-loopback --capture-props='audio.position=[FL, FL]' --playback-props='media.class=Audio/Source node.name=testsource audio.position=[mono]'
However, this had two issues: (1) it did not persist through restarts, and (2) if I selected the virtual interface as my default input, PipeWire would try to be smart and re-link it to itself, causing it to stop working. This is to my understanding not a bug but a feature, as the documentation page says:
Streams are normally automatically linked to devices by the session manager. This means that coupled streams don’t need any manual intervention to get linked and can also be moved around with tools like pavucontrol or pw-metadata.
I wanted a solution that persisted through restarts, and one that I could just set as my system-wide default microphone input and forget about.
The solution
First, copy a default PipeWire session manager config file to your ~/.config
(or under /etc/pipewire/
if you want it to be system-wide):
cp /usr/share/pipewire/media-session.d/media-session.conf ~/.config/pipewire/media-session.d
Then, open up that config file and insert the following at the bottom of the context.modules
section. Mind your braces and square brackets; humans are second-class citizens in the PipeWire config format.
{ name = libpipewire-module-loopback
args = {
capture.props = {
audio.position = [FL, FL]
node.target = alsa_input.usb-BEHRINGER_UMC204HD_192k-00.analog-stereo
}
playback.props = {
media.class = Audio/Source
node.name = mono-microphone
node.description = "Behringer Left"
audio.position = [mono]
}
}
}
This must go in the session manager config (something that took me a long time to figure out), and PipeWire is very fussy about the parameters; specifying media.class
for the capture.props
section will break everything, as does node.name
and what have you.
The configuration here works for me, and I hope it works for the future me who came back here to remind himself of how to configure this, and I hope it works for you. If it doesn’t, god help you (or me).
13 February 2021
Like most people, I have a mouse with thumb buttons on it. Mouse designers of the late 90s and early
00s decided to call these buttons “Back” and “Forward” and make them navigate backwards and forwards
in web browsers and such. Not a feature I use very much.
What I do use a lot is VoIP communications software, where I use push-to-talk bound to one of these
thumb buttons. Therein lies the problem: whenever I press push-to-talk with my web browser active,
it takes me off the page I was on and onto the previous page I was on. I don’t want that to happen.
Browser designers clearly don’t relate to this issue, so there’s no easy, universal way to disable
this backwards-forwards functionality of the thumb buttons. And even if I did disable it in Firefox,
my file browser would still use them for navigation, and if I disabled it there, there’d still be
some app out there that insists on using these buttons for this purpose. It’s a battle I can’t win.
Some years ago I discovered a great solution for this. My Logitech mouse allows rebinding the mouse
buttons to arbitrary keyboard buttons, so why don’t I just change it to some keyboard button I almost
never use like the Pause button? Even better, the F-keys that normally run from F1 to F12 actually
run all the way up to F24. Modern keyboards obviously never go that high, but due to legacy reasons
operating systems still support these “high F” keys.
So I opened the Logitech Control Panel on Windows, entered the key binding interface and… wait,
I can’t actually input F13 in here. How do I do it? I’ll spare you the suspense and say that I did
it with a simple AutoHotKey script that sent the F13 keystroke which the Logitech software happily
accepted. I don’t have that script anymore because I don’t use Windows, but it was a oneliner so
you’ll figure it out. I’m counting on you.
But then I switched to Linux, and the Logitech Control Panel doesn’t work on Linux and unfortunately,
the forwards/backwards buttons do. What now?
The actual solution
Enter libratbag, a community-maintained effort to enable
features in modern mice (and a small handful of other peripherals) that would normally be accessed
through the driver software, which is unfortunately typically exclusive to Windows.
It’s supposed to be a library/dbus daemon type thing to enable GUI frontends to access these devices,
and it has a GUI frontend called Piper. Unfortunately, Piper
doesn’t want to accept the F13 key.
Thankfully libratbag also comes with a command line utility called ratbagctl
.
$ ratbagctl
singing-gundi: Logitech MX518 Gaming Mouse
When invoked, it shows us a list of supported devices along with a human-readable ID.
In this case there’s only one supported device, “singing-gundi” the Logitech MX518 Gaming Mouse.
We read man ratbagctl
like a good boy and piece together the following commands:
$ ratbagctl singing-gundi button 3 get
Button: 4 is mapped to 'button 4'
Button 3 is the first thumb button, the one closer to the user. We can see it’s currently bound to
‘button 4’, which is the default and not at all confusing (ratbag indexes the buttons from 0 while
X11 – or whatever is handling the input – indexes from 1). We want to rebind it to F13.
The manpage specifies the command button N action set button B
, but this is for setting it to
mouse buttons, not keyboard keys, so we can’t rebind it to F13 this way. Instead we need to use
ratbagctl singing-gundi button 3 action set macro KEY_F13
The shell should be silent in response, which means the command succeeded. We can check that it
worked with
$ ratbagctl singing-gundi button 3 get
Button: 3 is mapped to macro '↕F13'
And that’s it! The first thumb button is now going to be sending the F13 keystroke, which X11 calls
XF86Tools by the way. This should be recognized in pretty much any app or game as a keybinding,
but browsers won’t go backwards when pressing it.
If you want to go back to the default, simply use
ratbagctl singing-gundi button 3 action set button 4
09 July 2020
I’ve used Fedora for many years now on my laptop, and the default font rendering has served me well there…
but only because the laptop has a HiDPI screen which doesn’t need subpixel hinting as much as regular screens.
Subpixel hinting, as it turns out, is patented by Microsoft (accursed software patents) so most Linux distributions
don’t ship with it enabled, and its absence is painfully obvious on ye olde low-DPI screens especially when viewing
light text on dark backgrounds.
Anyway, there’s a helpful COPR repository that fixes all of this. https://github.com/silenc3r/fedora-better-fonts (or more directly, https://copr.fedorainfracloud.org/coprs/dawid/better_fonts/).
Enable this repository and install the packages it offers and you’ll get prettier fonts, plus it installs
replacements for a bunch of common Microsoft fonts, making web pages appear closer to what they do on Windows
(if this is something you don’t want, I suppose you can just not install the fontconfig-font-replacements
package.)
Installation instructions (as per the COPR repo page):
-
Enable COPR repository with packages from this repo: dnf copr enable dawid/better_fonts
-
Install packages: dnf install fontconfig-enhanced-defaults fontconfig-font-replacements
-
Log out and log in again or restart computer to see the effect
05 July 2020
I have a now fairly old BenQ XL2420Z gaming monitor. It is a 144Hz refresh rate model
and has strobing backlight functionality for motion blur reduction. However, I run
it at 120Hz using some custom timings, because this reduces visual artifacting with the strobing backlight and makes the display brighter when the strobing is enabled. BlurBusters calls this the “1350 Vertical Total trick”, or something along those lines. The why and how of
it is beyond me.
I had some issues setting this custom resolution up under Linux using Xorg and the
proprietary Nvidia drivers. Someone at the BlurBusters forums created a
guide which was helpful, but
was missing some key details that were necessary to get this to work on my machine.
The configuration
Here’s the configuration for the impatient. If you have the exact same display I do,
this may work for you. However, you may want to read on to see how this configuration
came to be.
Save this into /etc/X11/xorg.conf.d/
with some descriptive filename. If you are unfamiliar with conf.d style configs, these loose files are read after the main Xorg.conf (which on modern systems often doesn’t even exist anymore) and any changes in them are applied in alphabetical order. In my case, this file is /etc/X11/xorg.conf.d/20-xl2420z-customres.conf
.
Section "Monitor"
Identifier "xl2420z" #This identifier can be anything; it's just the name of this config block.
#The next line defines the custom resolution.
#The exact meaning of the magic numbers here is beyond the scope of this blog post.
ModeLine "1920x1080_120_vt1350" 336.96 1920 1968 2000 2080 1080 1083 1088 1350 +hsync -vsync
EndSection
Section "Screen"
Identifier "Screen0"
#The next line disables some safety checks imposed by the Nvidia driver
#It uses the display's EDID so that they are only disabled for the XL2420Z and
#not any other displays.
#Without this line the custom resolution will be rejected as unsafe.
Option "ModeValidation" "DPY-EDID-edbe03be-f4a0-3a94-b9e8-00884a48f8f4: AllowNonEdidModes,NoMaxPClkCheck,NoEdidMaxPClkCheck,NoHorizSyncCheck"
Monitor "xl2420z" #This is important so that the monitor block above is actually used!
EndSection
Applying the configuration
Once you’ve saved the config to a valid path, reboot your computer (or restart X, but it’s safer and easier to reboot).
After the reboot, use the nvidia-settings
GUI to enable the custom resolution. Select “X Server Display Configuration” from the list on the left, then select your monitor, switch to Advanced mode on the bottom right, and then set the correct resolution. It will unhelpfully be categorized by the refresh rate, so you might be in a situation where the right resolution is 1920x1080 120 Hz (1) or something. Just select the correct dimensions, and then scroll through the refresh rate selection until you see the correct Mode Name; that’s the resolution you want.
Once you’ve got the right resolution, click on Apply and then exit out of the GUI.
The resolution should now be applied, and the drivers will load it automatically every
boot, and you should be done! If not, read the debugging section below.
I’ve also seen the custom resolution defined in the config file directly using the MetaModes option, but I couldn’t get that to work either. Your mileage may vary.
How the configuration came to be
There are two key bits in this config that you may have to customize for your setup.
The first is the ModeLine, which is the set of magic numbers that defines our
custom resolution. The ModeLine here is from the BlurBusters forum guide linked above
and matches the timings I successfully used on Windows for many years on this monitor.
If you have to create your own ModeLine, this calculator may come in handy to calculate the various timings.
I’m woefully clueless about the meaning of these values, but the calculator should help
you if you’re just trying to recreate the settings given in some Windows-oriented guide.
Note that Windows-oriented guides often omit the Back Porch values. This is because
those values can be inferred from the other values, and Windows tools like the Nvidia
Control Panel and ToastyX Custom Resolution Utility do so. The back porch values are
simply what’s left over after you subtract all the other values from the Horizontal or
Vertical Total values. For instance for a Vertical Total of 1350, subtract the
Resolution (1080), Front Porch (3) and Sync Pulse (5) values and you’re left with 262;
that is the Back Porch value.
The second is the EDID used in the ModeValidation option. This is a unique ID for a specific monitor model (or maybe even a specific monitor; I don’t know). There are more generic identifiers available, but using this one ensures that the option is never applied to the wrong monitor.
The Nvidia drivers come with a tool called nvidia-settings
which you can use to discover these identifiers. Use nvidia-settings -q dpys
to list all the display devices on your system, and then look for the right monitor:
$ nvidia-settings -q dpys
9 Display Devices on kotenbu:0
[...]
[7] kotenbu:0[dpy:7] (DP-4) (connected, enabled)
Has the following names:
DFP
DFP-6
DPY-EDID-edbe03be-f4a0-3a94-b9e8-00884a48f8f4
DPY-7
DP-4
Connector-2
[...]
If you have a lot of monitors and aren’t quite sure which one is which, you can use either xrandr
or the nvidia-settings
GUI (just run nvidia-settings
with no parameters) to find the short identifier of the display, which you can then match to the long EDID identifier in the output above:
Once you have the EDID, you can use that in the config.
Debugging
This can get frustrating if (or when) things go wrong. I had trouble getting Xorg to
actually load the config and the custom mode.
Increasing the Xorg logging verbosity can help here; this is done using the parameter -logverbose 6
. 6 is the minimum level to display information on ModeLines and why they may or may not be loaded.
In my case the entire Monitor section was being ignored. The key to overcoming this was adding the Monitor "xl2420z"
line into the Screen section. Another possible option is to use this feature, which should enable the Monitor section for only a specific device, but I couldn’t get this to work personally (quoting from man xorg.conf
):
Option “Monitor-outputname” “monitorsection”
(for example, Option “Monitor-VGA” “VGA monitor” for a VGA output)
In the absence of specific association of monitor sections to outputs, if a monitor section is present the server
will associate it with an output to preserve compatibility for previous single-head configurations.
Specifying video modes is optional because the server will use the DDC or other information provided by the monitor
to automatically configure the list of modes available. When modes are specified explicitly in the Monitor section
(with the Mode, ModeLine, or UseModes keywords), built-in modes with the same names are not included. Built-in
modes with different names are, however, still implicitly included, when they meet the requirements of the monitor.
Good luck.
19 May 2020
I use PuTTY to run Weechat (an IRC client) over SSH. Over the years I’ve noticed that
the alt+numberkey combination suddenly stops working for no apparent reason, which is a bummer because
that’s how you change channel windows in Weechat.
After figuring out the reason this happens, forgetting all about it, then figuring it
out again, then forgetting it again, and then figuring it out once more, I figured that
I should just write it down here.
It’s Photoshop. Yeah. I don’t know why or how, but Photoshop sometimes does this.
It doesn’t always do it, but occasionally it does. And when it does, closing it
immediately solves the issue (which, I guess, only makes sense). Anyway, go figure.
That’s all.