Sunday, 5 November 2023

Excluding devices from pipewire control

In my previous blog post I described how I used pipewire to add a bluetooth dongle to the audio outputs of my computer.

Unfortunately activating pipewire had the result of it taking control of all the sound interfaces on my computer. This caused a problem with a line-in port which I use for recording audio at scheduled times. It turns out that now and then pipewire will reset the port for maximum gain, wrecking the recording.

I searched for how to exclude this port from pipewire's influence and this was the best answer. I discovered the PCI bus id of the sound card (actually onboard sound device) in question and wrote an override script just like the one described with my card's id. Unfortunately the whole device has to be disabled, not just the line-in port, but that's ok for me. I still have an HDMI port which I can connect to my amplifier instead of using the analog line-out port. So thanks to the author of that ZenLinux blog for the insight. It's a pity such a simple task has to be so complicated, maybe future wireplumber developments will make this simpler.

Monday, 11 September 2023

Getting a bluetooth capable amplifier working with a bluetooth USB dongle on Linux

A while back I bought one of those $10 tiny class D amplifiers that can drive my bookshelf speakers with up to 30W (depending on power supply voltage, between 12V and 24V). An old laptop supply supplies this. It can be fed from a 3.5 audio socket or from bluetooth. Works like a charm. May not be audiophile but good enough for me.

I've been feeding it from an older mobile phone that mounts a SMB share from my workhorse computer. But as I would like to automate it so that I can use music to wake me up, I bought a bluetooth USB dongle from one of many AliExpress sellers. It contains a Realtek chipset that I checked is supported in Linux and supports BT 5.3 profile.

How to set the dongle up? Plugging it in elicited messages in the syslog, as dmesg showed. I used the KDE desktop widget (probably bluedevil) to connect to it and command it to pair and connect to amplifier. A prerequisite is that bluetoothd should be running. I discoved that the configuration can also be done from the CLI using bluez-tools. But once discovered and paired, nothing more needs to be done on this front as the setup is static.

How to send audio to it? I thought there might be a PCM device under /dev like for sound cards. But no. It seems that you need a service like pulseaudio to drive it. So I got stuck into pulseaudio documentation. Along the way I discovered that my distro prefers pipewire. So I installed the pipewire packages and this also obsoleted the corresponding pulseaudio packages. One of the packages pipewire-pulseaudio supplies compatible functionality.

Pipewire is a process that should keep running to handle all this. How to fire it off? It turns out that it's preferable to run it with user permissions, using the user instance of systemd, e.g.

systemctl --user start pipewire.service

How to make sure it runs when the user logs in? You activate the systemd units like this:

systemctl --user enable pipewire.service pipewire.socket

Then start both the service and the socket the first time.

How to send audio to pipewire? I struggled with this under pulseaudio, it wouldn't show up in players like vlc or amarok. But once I switched to pipewire, the bluetooth audio sink was just there and I could control the volume and make it the default audio playback.

How to specify this device to mplayer so that I can play from a cron job? I just had to specify it to the -ao option.

mplayer -ao pulse audio.mp3

Notice that mplayer sees pipewire the same as pulseaudio. I can put this in a profile in .mplayer/config named after the amplifier ID:

[xinyi]
ao=pulse

then I can specify:

mplayer -profile xinyi audio.mp3

The advantage is that I can specify other settings in the profile.

Wednesday, 6 September 2023

Pay attention to the size of ipsets for nftables

I was preparing an ipset for blocking access by geographical region using firewalld. Firewalld can work with either the traditional iptables or the newer nftables.

I created the ipset file using this Makefile stanza:

%.load: ipset_%.txt
        -firewall-cmd --permanent --delete-ipset=$(@:.load=)
        firewall-cmd --permanent --new-ipset=$(@:.load=) --type=hash:net
        firewall-cmd --permanent --ipset=$(@:.load=) --add-entries-from-file=$<
        systemctl reload firewalld

Here % is replaced by the two letter country code for the region I want to allow.

In the public zone I have a rich rule which inverts the test. This is the result of the firewall-cmd I issued:

  <rule family="ipv4">
    <source ipset="ok" invert="True"/>
    <service name="theservice"/>
    <log/>
    <drop/>
  </rule>

Later I discovered that that the countries not in ok weren't blocked. Troubleshooting found these symptoms:

  • firewall-cmd --state returned failed, despite systemctl stating that the service had started
  • There was a message about python-nftables failing in systemd logs
  • nft list showed nothing in the chains or rulesets

Searching on these symptoms got hits but none of the solutions worked. The only thing I learnt is that firewalld calls the python3-nftables routines to manipulate the nftables. I thought it might be the top line in the Python script which read #!/usr/bin/python which invokes python2 on my system, but adding 3 made no difference presumably because firewalld calls it with /usr/bin/python3 <name of script>. Someone suggested this python3 module was broken in a particular distro release because it didn't include a needed flag so he went back to iptables as the backend. I didn't want to do this. Also the report was for a previous distro release so over a year old.

Playing around with ipset which deals directly with the kernel to create the sets manually revealed that the default maxelem of 65336 was not sufficient for my set. After some experimentation I figured that I had to increase this parameter at creation. This boiled down to including this final option on the firewall-cmd line:

firewall-cmd --permanent --new-ipset=$(@:.load=) --type=hash:net --option=maxelem=262144

Now restarting firewalld took a bit longer due to having to digest lots of entries, and there was no more failure of python-nftables. Inspecting the ruleset using nft worked and showed that the nftables rule was in place.

It would have been easier if I had understood the relationship of all the components of this setup better, but things are obvious in hindsight.

Wednesday, 12 July 2023

Prefer IPv4 for zypper updates

I had been battling server timeouts from a local mirror of OpenSUSE repositories when I noticed that if I telneted to the troublesome server it attempted to contact it via its IPv6 address. My Internet retailer doesn't support IPv6 connections, although my Linux distro and modem are capable. At the moment there's no need as there is no shortage of IPv4 addresses in this country.

A little search found that it's due to the curl library trying IPv6 addresses first. There is a little known environment variable in libzypp to control this. I put

ZYPP_MEDIA_CURL_IPRESOLVE=4

in my environment settings and I no longer had server timeouts.

If you are using sudo to run zypper, look into the env_keep option  in the sudoers file, and check that the env_reset option is enabled (the default), for example:

Defaults env_keep += "ZYPP_MEDIA_CURL_IPRESOLVE"



 

Sunday, 2 April 2023

Displaying problematic characters for Windows like the colon in Samba shares

I have a Samba share which contains music files which I want to play on my tablet (but could also be a Windows desktop). The colon is perfectly valid in Linux filenames and is used a lot in MP3 filenames. On the client side it falls back to DOS mapping because the colon is not legal in Windows filenames. So it's impossible to see what the song is. Here is how you can make the displayed names more readable.

Add these lines to smb.conf, either in the global or a share section:

vfs objects = catia 

catia:mappings = 0x22:0xa8,0x2a:0xa4,0x2f:0xf8,0x3a:0xf7,0x3c:0xab,0x3e:
0xbb,0x3f:0xbf,0x5c:0xff,0x7c:0xa6

And for good measure:

mangled names = no

Those changes map problematic characters to extended characters. For example colon : is now displayed as the division sign ÷ It's not ideal but at least you can read the filenames now.

Credit to:  https://unix.stackexchange.com/questions/299130/samba-how-to-display-files-with-colon-in-their-names/381639#381639