Saturday, January 31, 2015

[solved] more on Arch sound (fix for chipmunk sound)

No reasonable person likes PulseAudio currently. It's also a mystery why it was ever developed instead of, say, simply enhancing OSS (so we would only have one sound daemon). But, since OSS and ALSA were left behind, it goes without saying that, over time, a Linux distribution is near-certain to become infected with PulseAudio -- it will automatically be installed as a dependency by one application or another. Eventually, PulseAudio is almost certain to interfere with something, for example to make Audacious play MP3's at a chipmunk's pitch. As I write in early 2015, the strategy that works for me is,

crippling Pulse-Audio without removal

You can try a straight-up # pacman -Rs pulseaudio, but dependencies tend not to allow this. So cripple it.
Note: the PulseAudio daemon respawns if not properly neutered.
  • obviously start with $ pulseaudio --kill
  • directory /usr/share/alsa/alsa.conf.d hides a PulseAudio file (50-pulseaudio.conf) which ALSA executes during ALSA startup. This file surreptitiously activates /bin/pulseaudio. Rename it so it's no longer executed, eg "cp 50-pulseaudio.conf 50-pulseaudio_conf.bak", OR change /bin/pulseaudio to /bin/true in the file.
  • stop PulseAudio autospawning by gutting /etc/pulse/client.conf and replacing its lines with
    # custom version
    autospawn = no
    # "/bin/true" doesn't do anything, but no errors
    daemon-binary = /bin/true
  • Check inside /etc/X11/xinit/xinitrc.d to be sure X11 isn't infected. Eliminate any PulseAudio files in that directory.
  • $ systemctl list-units |grep pulse to verify no systemctl pulseaudio targets are present

/usr/share/alsa/alsa.conf vs. /etc/asound.conf

These initializing files use the same commands and formats, as well as one other config file, ~/.asoundrc. Since all 3 files are ALSA initializing files, only one is necessary, delete the other two to avoid interference. I typically keep /usr/share/alsa/alsa.conf because it's the most complete out-of-the-box, and because so many applications (eg. Audacious) load it. Save a copy of the working version for future installs. Not sure how to activate the file under systemd, so I just logout and log-in to be sure the file is read. Next, the alsa.conf configuration.

/usr/share/alsa/alsa.conf ("USAA" here)

USAA has a few problems itself.
  • backup the default USAA, eg # cp /usr/share/alsa/alsa.conf /usr/share/alsa/alsa_conf.bak. Backup any other files that are modified as well.
  • USAA's first subroutine is to load /etc/alsa.conf and /home/foo/.asoundrc. These can have PulseAudio hooks that wrongly set playback frequency. Carefully delete this subroutine, from
    [
    {
    func load
    files [
    {
    @func concat
    strings [
    { @func datadir }
    "/alsa.conf.d/"
    ]
    }
    "/etc/asound.conf"
    "~/.asoundrc"
    ]

    errors false
    }
    ]
    ...to....
    @hooks [
    {
    func load
    files [
    {
    @func concat
    strings [
    { @func datadir }
    "/alsa.conf.d/"
    ]
    }
    ]

    errors false
    }
    ]
    and save.
  • backup and then eliminate any of these which exist
    1. /etc/asound.conf
    2. ~/.asoundrc
    3. ~/.config/asound.conf

NB: There is *one* situation where I occasionally want ~/.asoundrc, albeit customized. If I have an external USB mic and some application won't simply accept its direct information, eg "plughw:1,0", I can turn it into a second soundcard that's providing content. Of course, there is no playback via the mic. Audacity, for example, likes this arrangement.

verify

Logout, log back in, and then try an Audacious or command line play, etc... $ aplay somefile.mp3

Thursday, January 29, 2015

[solved] Linux alarm clock

I left my phone at work today, and I often use it as a morning alarm. What to do? This site came to the rescue.
sleep 5h 30m && vlc somemusic.mp3

Friday, January 2, 2015

[solved] xsane fails to find WLAN Brother scanner

Over the holiday I visited a buddy who put me on his home WLAN, which included a Brother MFC-8840D printer. This printer also has scanning capacity. I added the printer via CUPS, and it printed. I hadn't network scanned previously, so I tried Xsane, hoping for the best. Xsane failed to detect the MFC-8840D. I was skeptical about going straight to port 6566, since forwarding runs the risk of compromising the firewall or causing other security problems, which are easy to do, apparently. So, what to do? Below, I'll describe my solution, and then some of the troubleshooting (6+ hours) that preceded it.

1. overview

Budget a half-hour to forty minutes to accomplish the connection if you already know the steps. Some of my learning steps: 1) SANE and CUPS are entirely different pathways; SANE does not require CUPS to be operating or enabled during scanning, at least on a Brother, 2) determine the correct backend software for your scanner and download (if necessary), 3) if using brscan-skey for special buttons (see below) start the necessary daemons with systemctl. I didn't need brscan-skey however, had I needed it, this step is important, 4) manually install the config file (after backend).

2. scanner backend

This took getting used to. USB scanners typically don't require drivers in Linux so for this WLAN scanner, I was thinking all the scanner would need was a network connection. Over a network, a driver is also needed. Brother has a site for LAN backends. Go there to determine which version you need for your Brother model. There two files:
  • backend - for the older printer my buddy had it was "brscan". In the AUR, it says it's for USB scanners, but that's a misleading typo. Just download and install.
  • scan key - pointless unless you want to use automated physical keys on the scanner such as "scan to fax", "scan to email", etc. Secondly, if you obtained "brscan" in step 1 above from the AUR, then scan-key is included and you don't need this step anyway.
Note: For those who want brscan-skey, documentation shows it's good to omit the "user" and "group" fields, and install the service file to /usr/lib/systemd/user/brscan-skey.service instead of /usr/lib/systemd/system/brscan-skey.service. That's so users can start (or enable) the brscan-skeydaemon as a regular user without sudo, eg:
$ systemctl --user start brscan-skey
If you don't do all those permission changes, you apparently will need the standard:
# systemctl start brscan-skey.service
As noted above, I didn't need brscan-skey, so I disabled it (I also stopped CUPS).

3. install the config file

The following application is supposed to do the installation:
# /usr/share/brother/sane/setupSaneScan -i
This didn't work for me. In other words, after this step, I looked for the scanner and was greeted with the following:
$ scanimage -L
bugchk_free(ptr=(nil))@brother_modelinf.c(467)
Aborted (core dumped)

Strace indicated scanimage failed when looking for "Brother.ini" at /usr/local/Brother/sane/Brsane.ini. The file does exist however, at /usr/share/brother/sane/Brsane.ini, so I created the directory in /usr/local , and copied the file to where it was looking.
# cp /usr/share/brother/sane/Brsane.ini /usr/local/Brother/sane/Brsane.ini
At this point, the program ran through but, as user, could not create a socket connection due to permissions (go figure).
$ scanimage -L
[bjnp] create_broadcast_socket: bind socket to local address failed - Cannot assign requested address
What's apparently happened here is setupSaneScan doesn't work very well. It might even be unnecessary to run. In my case, it certainly failed to write the file /usr/share/brother/sane/brsanenetdevice.cfg, or to install the scanner. This site has the few lines needed to nano into /usr/share/brother/sane/brsanenetdevice.cfg. For example:
# nano /usr/share/brother/sane/brsanenetdevice.cfg
DEVICE=MFC8840D , "MFC-8840D" , 0x4f9:0x160 , IP-ADDRESS=192.168.1.4

In summary:
  • copy /usr/share/brother/sane/Brsane.ini to /usr/local/Brother/sane/Brsane.ini
  • create and enter lines into /usr/share/brother/sane/brsanenetdevice.cfg

4. install the scanner driver

Following the hand-entries in /usr/share/brother/sane/brsanenetdevice.cfg, the printer/scanner still must be installed.
  • unless desired, turn off CUPS and brscan-skey with systemctl
    # systemctl stop org.cups.cupsd.service
    # systemctl stop brscan-skey.service
  • obtain the IP of the printer, you'll recognize it by its operating system
    # nmap -O 192.168.1.1/24 -oG
  • obtain the exact model name for the printer from /usr/share/brother/sane/Brsane.ini
  • let's say the printer IP was 192.168.1.4, and the model name was "MFC-8840D". Using these values, or the ones for your printer, enter /usr/share/brother/sane/brsaneconfig -a name="common name" model="model from INI" ip=xxx.xxx.xx.xx", eg,
    # /usr/share/brother/sane/brsaneconfig -a name=MFC8840D model=MFC-8840D ip=192.168.1.4
  • verify this went through with "brsaneconfig -q", and "scanimage -L"
# /usr/share/brother/sane/brsaneconfig -q
Devices on network 0 MFC8840D MFC-8840D I:192.168.1.4
$ scanimage -L
device `brother:net1;dev0' is a Brother MFC-8840D MFC8840D
So, with scanimage -L showing detection, xsane can be initiated for scanning.

investigation leading to solution (6+ hrs)

This is not necessary to read; it's just crib notes (to save time in the future) of troubleshooting which eventually led to a solution.

To start with, I left the CUPS daemon on. I wasn't sure what might be necessary to detect the scanner. Further down here, I realize CUPS actually gets in the way of installation. Secondly, I read that scanner drivers expect "nobody" should be included in the "scanner" group. You can do this with, eg...
# usermod -a -G scanner nobody
... but I like to directly (not recommended) type into the /etc/group and /etc/passwd files: I added nobody to the scanner group in /etc/group. None of these changes had any effect, but YMMV. I then checked for scanners.
$ scanimage -L
[bjnp] create_broadcast_socket: bind socket to local address failed - Cannot assign requested address
Since BJNP is the Canon-specific CUPS back-end, and since my attempt to connect was to a Brother, the unsolicited appearance of BJNP, and causing scanimage to repeatedly fail, was... annoying.

A more powerful attempt to locate the fail...
# strace scanimage -L 2>&1 |tee bigfile.txt
# chown 500:500 bigfile.txt
$ grep socket bigfile.txt >bigfile2.txt
And here's the portion with the fail...
socket(PF_INET6, SOCK_DGRAM, IPPROTO_IP) = 132 setsockopt(132, SOL_SOCKET, SO_BROADCAST, [1], 4) = 0 setsockopt(132, SOL_IPV6, IPV6_V6ONLY, [1], 4) = 0 bind(132, {sa_family=AF_INET6, sin6_port=htons(8612), inet_pton(AF_INET6, "fe80::b277:2173:31a6:e71", &sin6_addr), sin6_flowinfo=0, sin6_scope_id=if_nametoindex("enp4s0")}, 28) = -1 EADDRNOTAVAIL (Cannot assign requested address) fstat(2, {st_mode=S_IFIFO|0600, st_size=0, ...}) = 0 write(2, "[bjnp] ", 7[bjnp] ) = 7 write(2, "create_broadcast_socket: bind so"..., 95create_broadcast_socket: bind socket to local address failed - Cannot assign requested address ) = 95 close(132)
Subroutine 132 is failing. The real fail was scanimage was demanding an IPV6 addresses, which of course is a too rigid restriction to place onto an older IPV4 scanner. Additionally, scanimage was soliciting via "enp4s0", the ethernet LAN NIC. This was a further problem because the LAN NIC was not connected, I was only connecting via my WiFi card. If scanimage demanded these to be present, nothing was going to work on the older Brother on a WAN.

To be sure I wasn't crazy, I nmap-ped the LAN ("nmap -O 192.168.1.1/24 -oG somefile.txt") , found the printer by the Brother OS, and made sure I was able to ping it successfully, using only the WiFi NIC, and leaving the LAN NIC disconnected. This was a success. But I never was able to eliminate the BJNP, IPV6, or LAN NIC failures with the CUPS daemon "on".

/etc/sane.d/saned.conf

Digging through some pages, it appeared the first effort should be to modify /etc/sane.d/saned.conf When I opened the file, all lines were commented, so I added two uncommented lines
localhost 192.168.1.0/24

/etc/saned.d/net.conf

According to http://wiki.archlinux.org/index.php/sane, the file /etc/sane.d/net.conf must be similarly modified.
localhost 192.168.1.0/24

to xinetd or not xinetd?

Xinetd is for allowing anyone on a LAN to use a hardwired (eg. by USB) scanner. My friend's Brother was sitting on a WLAN, independent of any system, so it should have been simpler. Still, after I installed xinetd (pacman), some tweaks were required. For example, in /etc/sane.d/saned.conf,these lines are at the bottom:
# NOTE: /etc/inetd.conf (or /etc/xinetd.conf) and # /etc/services must also be properly configured to start...
Well now. /etc/services is a listing of applications for each port, and sane-port was there at line 6566 for both UDP and TCP. This appeared OK. Next stop was /etc/xinetd.d/sane.
# cat /etc/xinetd.d/sane service sane-port { port = 6566 socket_type = stream wait = no user = nobody group = scanner server = /usr/bin/saned # disabled by default! disable = yes }
So there's nothing allowing LAN access. Using the site above, and this Slackware page, I changed the file by adding "tcp" capability (because WLAN):
# cat /etc/xinetd.d/sane service sane-port { port = 6566 socket_type = stream protocol = tcp wait = no user = nobody group = scanner server = /usr/bin/saned # disabled by default! disable = no }

check loopback

If you went the nuclear route and brought down your firewall during this, a good check to be sure it's re-established is to telnet into it. The connection should be refused.
telnet localhost [service port]
For example, xsane uses port 6566 so...
telnet localhost 6566
Try telnetting as both root and user; if groups are properly set-up, users should be able to telnet the port.