Colon Files: rsync-tr

I was copying over some music to my phone (via jmtpfs and rsync), and I noticed that some of the files failed with “Input/output error”:

After a while it dawned on me what all these files had in common was that there’s a colon in the file names. And presumably the MicroSD card in the phone uses a VFAT file system, and those file systems don’t like colons in the file names at all.

So I thought: Surely there’s a simple switch I can give to rsync to translate file name characters. I mean, this problem can’t be that obscure: We’ve been copying media files to devices that use VFAT file systems for decades now.

But after reading the man page and Googling for hours: rsync doesn’t support this. I mean, I can somewhat understand why. Whatever you’re doing is going to be pretty hackish. You could get file name collisions or inconsistent rsyncs, perhaps. On the other hand, these devices are the end point for these files: We don’t really care much about the names…

It turns out that Matt McCutchen wrote a patch in 2007 that was never accepted. It adds a simple –tr :/- syntax that does exactly what I need.

The patch no longer applies cleanly, but it’s surprising how little work was needed to shoehorn it into the current rsync source code. They’ve obviously retained the basic structure of the files and the repo, for which I am thankful.

I put the resulting git fork up on Microsoft Github.

And there’s a few other gotchas when rsyncing to VFAT: It doesn’t support all the Linux file system flags or renaming in the way rsync does by default, so for reference, here’s the complete command line I ended up with that will (sort of) reliably copy over new files to my phone:

~/src/rsync/rsync -atvL \
  --tr ':?"/-!' --inplace \
  --ignore-existing \
  /music/picks/ /mnt/sony/SD\ card/Android/music/

Your mileage will vary.


Hidden tracks on CDs used to be a pretty common thing. Not “real” hidden tracks: You could play tricks with the directory structure and put a track before the first one, so you have to skip back from 1 to get to 0.

No, the common way to do this is to pad the final track with, say, ten minutes of silence, and then the “hidden” song starts.

While the concept of hidden tracks is fun, in practice it’s really annoying, because it means that you’re sitting there listening to silence for ten minutes.

So once upon a time I wrote a little C program that would look for silences in the last track of all the CDs I have ripped, and if it finds (long) silences, then splitting happens.

As CDs are getting less popular as a means of distribution (to put it mildly), the hidden track thing has all but disappeared, too, but this week I got
the new Deathcrush album, and it employs this tactic.

I started looking around for the scripts to split the file, and then I discovered that it was in an obscure region of my home directory, not touched for ten years, and not put on Microsoft Github.

But now it is.

It’s probably a couple of decades too late to be useful to anybody, but there you go. It compiles and everything on the current Debian, which just amazes me. I mean, I wrote it in… like… 2003?

Go Linux.

Fun with DPMS; or, An Emacs-Based Screensaver

I’ve got a bunch of monitors, large and small, that (in general) are always on. Because I’m too lazy to switch stuff off and or.

They display some useful information, but are largely decorative (i.e, some of them display temperature data, and some use xscreensaver to show what albums are playing).

But I’ve got the rest of the lights and stuff in the apt to switch off when I push the “I’m going to bed” button on the wall. I thought it might be nice to have all the monitors also switch off at the same time? And then I could link the “I’m awake now” button on the wall to switching all the monitors on again.

So cyber.

I thought this was going to be really easy, but… you know… computers.

First of all: Switching a screen off is easy:

$ xset dpms force off

And then it’s off.

$ xset dpms force on; xset -dpms

to switch it on again and disable power management again (to avoid the monitors switching themselves off again on their own volition).

So far so good!

However, there’s like a dozen things that feel free to wake monitors up.


Easiest first: I’ve got a little monitor that plays Youtube 24/7 (and displays weather data).

It would switch itself on immediately, because it uses mpv to display the youtube vids. To switch that off, just say –no-stop-screensaver.

Stereo Computer

The screen on the computer I use to control the stereo would switch it self on whenever the song changed, and after a bit of trial and error and more code reading, I found this:

(set-mouse-pixel-position (selected-frame) 2000 0)

It’s code designed to just move the mouse pointer off the screen. And it turns out that that makes X wake the monitor up!

I guess that… makes sense? I mean, moving the mouse is supposed to wake the screen up, so…

I added the following guard:

(defun jukebox-monitor-on-p ()
    (call-process "xset" nil t nil "q")
    (goto-char (point-min))
    (search-forward "Monitor is On" nil t)))


Many of the larger screens use xscreensaver to display the sleeve of whatever album is playing, and xscreensaver wakes the monitor up after just a few seconds. Isn’t that ironic!

Don’t you think?

It’s like a screensaver that switches on a screen that’s already saved, it’s like

Oh, where was I…

xscreensaver has a bunch of DPMS-related options:

dpmsEnabled:	False
dpmsQuickOff:	False
dpmsStandby:	24:00:00
dpmsSuspend:	24:00:00
dpmsOff:	24:00:00

But none of them seem to help with this problem. xscreensaver stubbornly wakes shit up. What’s up with that, jwz?


The only solution for this problem is to write an Emacs-based screensaver.


It uses the xelb library to query the idleness (to schedule when to start saving the screen) and to query/restore focus after closing the screensaver window.

Man. It’d be great if somebody could write a manual for xelb. Working with it is kinda frustrating because you just have to poke around, looking at examples, until you suddenly get something that works. I spent, like, seven thousand hours (approx.) trying to get the idleness out of it until I guessed (by looking at what exwm did with randr extensions) that you had to say

(xcb:get-extension-data x 'xcb:screensaver)

before trying to call the xcb:screensaver:QueryInfo function.

[Edit: Emacs give me almost all events that’s given to the frame (mouse and keystrokes), but not when the user presses shift, etc. Is there a way to get something like xcb_wait_for_event out of the xelb library?]


Isn’t it weird how these trivial projects tend to spiral out of control?

Especially for certain people?

Don’t you think?

For Flacs Sake

Yesterday, I bought this Black Cab EP off of Bandcamp, but when I played it today, all I got was silence.

A new form of Extreme Australian Minimalism or a bug?

My music interface is Emacs, and it uses flac123 to play FLAC files. It’s not a very er supported program, but I find it convenient since it uses the same command format as mpg123/321.

I have encountered FLAC files before that it couldn’t play, but I’ve never taken the time to try to debug the problem.

$ file /music/repository/Black\ Cab/Empire\ States\ EP/01-Empire\ States.flac 
/music/repository/Black Cab/Empire States EP/01-Empire States.flac: FLAC audio bitstream data, 24 bit, stereo, 44.1 kHz, 29760127 samples

Huh… so it’s 24 bits, while the rest of the FLAC files I’ve got are 16 bits?

Hm! Spot the problem!

Yes, if the format is anything other than 8 or 16 bits, then no samples are copied over from the FLAC decompression library to the libao player function, resulting in very hi-fi silent silence.

So this should be easy to fix, I thought: Just copy over, like, more bytes in the 24 bits per sample case, right?


But… the libao documentation is er uhm what’s the word oh yeah fucked up. It doesn’t really say whether ao_play expects three bytes per sample in the 24 bit case or four bytes. I tried all kinds of weird and awkward byte order manipulation, and got various forms of quite interesting noises squeaking out of the stereo, but nothing really musical.

So I wondered whether libao just doesn’t support 24 bits “natively”, and I added some “if 24 bits, then open as 32 bits” logic and presto!

Beautiful music! With so many bits!

I’ve pushed the resulting code to my fork on Microsoft Github.

The four people out there in the world playing 24 bit FLAC files on Linux from the command line or in Emacs: You’re welcome.

Useful Consumer Review

I needed a new scanner, and I wanted one that was significantly faster than the one I’ve been using until now. After some Googling, I landed on the Epson DS-50000, which is an A3+ scanner with a promise of being able to scan an A3 300DPI page in four seconds.

The web site I bought it from said that it’s a 4PPM scanner.


So I was excited when I finally got it, two months after I ordered it. Was it going to be 4PPM or 4SPP?

The latter! From hitting “enter” on my USB-connected laptop to having the scanned page up in my Emacs, it takes 3.5 seconds. Very impressive, I think. It’s only USB2, and I thought that might be a bottleneck, perhaps, but apparently not. It also feels very sturdy and it doesn’t have a fan, so it’s quite silent. It’s very nice. And it makes good-quality scans, too.


Yes, I connected it to a Linux laptop and you all knows what comes next: A tale of woe.

$ scanimage -d epsonds:libusb:001:019 --resolution 300dpi > /tmp/file

Worked perfectly the first time I tried it, so I thought I was in luck for once. But then I tried it again:

$ scanimage -d epsonds:libusb:001:019 --resolution 300dpi > /tmp/file
scanimage: open of device epsonds:libusb:001:019 failed: Error during device I/O

Gah! Basically, nothing helped. And it’s not just when scanning: Any command that talks to the scanner works the first time:

$ scanimage -L
device `epsonds:libusb:001:019' is a Epson DS-50000 ESC/I-2

But the second time:

$ scanimage -L

No scanners were identified. If you were expecting something different,
check that the scanner is plugged in, turned on and detected by the
sane-find-scanner tool (if appropriate). Please read the documentation
which came with this software (README, FAQ, manpages).

If I unplug it and replug it, then it works again.

After googling a bit, it seems that somebody had the same issue some years back with a different scanner, and the way to fix it was to build scanimage and friends from the current source tree, but that didn’t help.

So after some head scratching, I thought of a different approach: Obviously, something scanimage is doing is leaving the scanner in a bad state. What if I just reset the USB interface? Is that something that’s even possible?


I added a Makefile and put it on Microsoft Github for your convenience. All the code does is basically:

ioctl(fd, USBDEVFS_RESET, 0);

And this resets just the single USB port, so nothing else wonky happens to the USB sub-subsystem. And the command is extremely fast, so it adds no delay to the scanning process.

You do get a lot of these messages in your kern.log, though:

Oct 28 21:03:06 corrigan kernel: [972003.683893] usb 1-2: reset high-speed USB device number 19 using xhci_hcd

But who cares.

It’s truly the year of Linux on the Laptop.