Software problem: DKIM

I managed to waste my time on another thing. I foolishly thought that I should finally add DKIM to my mail server. Configuring it in the mail server was relatively easy. But once I started to check whether it actually works, I’ve fallen into trouble.

I started with the elliptic curve algorithm (ed25519). OpenDKIM on Debian stable failed to verify the signature due to an unknown algorithm. So I tried sending an e-mail to Gmail and it reported its DKIM check as failed too. Not very encouraging, but Google is generally incompetent as for e-mail handling1, so I suspected it could be their fault and tried further. The best explanation I could dig out from Gmail was “no key”, which could indicate Gmail also doesn’t understand ed25519 algorithm. Indeed, when I copied the failed message from Gmail to a newer version of OpenDKIM, it passed. OK, apparently dealing with software problem of category 2, an e-mail provider unable to handle modern standards despite it encourages e-mail senders to use DKIM.

Since this experience had indicated ed25519 is still too new, I tried to configure an additional, RSA, key. But my registrar, Hover, doesn’t accept long enough TXT DNS records. This would be OK if they accepted split DNS records. I managed to create a split record in Hover, apparently bypassing some checks by chance because my further similar attempts were rejected in the web UI. But the record didn’t work and the corresponding address couldn’t be resolved. After many attempts I’ve given up, Hover apparently doesn’t support split DNS records, which is a software problem of category 2 again, registrar DNS deficiency.

So I have DKIM set up and up-to-date SMTP servers can enjoy it. For the rest, nothing has changed, they think DKIM signatures are still missing in my e-mails. I can’t see any reason to waste more time on it.

Footnotes:

1

Just from my personal experience: Crippling incoming e-mails by deduplication, a horrible filter system and a spam filtering that’s best to disable because of nonsense false positives.

Czech programming keyboard is back!

I’ve recently reinstalled my computer and switched to a different Linux distribution there. Because of the change, I got new (or different) versions of many desktop components. And when configuring my keyboard, I can see Czech programming keyboard is available in X again. What a relief!

Software problems (and rsync failed to set permissions)

I regret that I have little opportunity to work on free software outside my job these days. One of the reasons is that I have been struggling all the time with things that don’t work, a significant part of them being software problems.

Software problems can be categorized into three groups:

  1. User stupidity problems
  2. Software stup deficiencies
  3. Bugs

In the current complex environments it’s often not clear in which of the categories a given problem falls. Nevertheless a problem is a problem and it (sometimes) must be solved or at least a workaround must be found regardless of the cause and all the unknowns.

I’m starting a series of posts about some of the software problems I experience. I have the following reasons to do that:

  • It’s a therapy. Clearly seeing what I waste time on helps me recognize I’m objectively prevented from doing useful things and perhaps find ways how to avoid dealing with less or more useless things.
  • Defining and describing a problem often helps solving it.
  • Some of the problems may be experienced by other users too and the solutions may help them.
  • It’s sort of my documentation of the problems.

Let’s start with something simple today. My backups to external media were breaking due to the following error:

rsync: [generator] failed to set permissions on “…”: Operation not supported (95)

The problem was apparently that symbolic links have normally 777 permissions, but on OpenAFS they have 755. A remedy is to add --no-perms after -a in rsync command line options. That means rsync won’t preserve permissions at all but it is not a big problem for me with that kind of backups and it’s clearly better than failing backups. I’d say this problem falls into category 2.

Emacs workspaces

I use Emacs for everything that can be done with it reasonably. I often run in a single Emacs session Gnus, Org agendas, command line actions, IRC, several development projects, etc. The question is how to switch between all those activities efficiently.

During the years, I tried several workspace, perspective or screen (whatever they are called) Emacs add-on packages. But I have never been completely satisfied with any of them. There have always been bugs, limitations and/or discomfort.

Then I applied the principle of simplicity: Use the simplest thing that may work. And the thing is Emacs frames. As simple as that, I’ve been using my workspaces based on Emacs frames for almost two years now and it has been working to my satisfaction so far.

The frames provide two crucial facilities:

  • Separate dynamic window configurations and switching between them easily. Frames provide that by definition. The only problem is that your window manager must be able to manage a lot of Emacs frames reasonably. But any civilized window manager should be able to do that and e.g. KDE is.
  • Switching to workspace specific buffers. Frames do that by default — at least with Ido, recently used buffers in the given frame are offered first when switching buffers. Unlike in some other workspace solutions, the buffers offered are not limited just to the given workspace, which is a killer feature. It’s much easier not to care about assignments of buffers to workspaces and to simply rely on the recent buffers approach.

Of course, C-x 5 key bindings are not enough to work with workspaces efficiently. I implemented my own workspace management mechanism, based on my wrappers around the previous solutions I used and described below.

First, it’s useful to track the last frame because returning to the last workspace is a very common action:

(defvar my-last-frame nil)

Let’s track last workspaces too:

(defvar my-last-workspaces '())

Frame switching may not work smoothly in some window environments, so let’s make a custom function to select a frame and to store the workspace to the variables defined above:

(defun my-select-frame (frame)
  (unless (eq frame (selected-frame))
    (setq my-last-frame (selected-frame)))
  (raise-frame frame)
  (x-focus-frame frame)
  (select-frame frame)
  (setq my-last-workspaces (cons frame (remove frame my-last-workspaces))))

I give my workspaces names, stored and displayed in frame titles. Let’s define functions retrieving workspace names:

(defun my-workspace-name (&optional frame)
  (let ((frame (or frame (selected-frame))))
    (or (frame-parameter frame 'title)
        (frame-parameter frame 'name))))

(defun my-all-workspace-names ()
  (setq my-last-workspaces (cl-delete-if-not #'frame-live-p my-last-workspaces))
  (mapcar 'my-workspace-name
          (delete-dups (append my-last-workspaces (frame-list)))))

Now we can switch among workspaces:

(defun my-workspace-switch (name)
  (interactive "sWorkspace: ")
  (let ((frame-list (frame-list))
        (frame nil)
        (new nil))
    (while (and (not frame) frame-list)
      (if (string= (my-workspace-name (car frame-list)) name)
          (setq frame (car frame-list))
        (setq frame-list (cdr frame-list))))
    (unless frame
      (setq frame (make-frame `((title . ,name))))
      (setq new t))
    (my-select-frame frame)
    new))

(defun my-last-workspace ()
  (interactive)
  (if (and my-last-frame (frame-live-p my-last-frame))
      (my-select-frame my-last-frame)
    (my-workspace-switch (read-string "Switch to workspace: "))))

As you can see, it’s possible to switch to an already present workspace or to a new workspace, using the same command. But typing the workspace name each time is cumbersome, let’s make it easier:

(defun my-switch-to-workspace (&optional key)
  (interactive)
  (unless key
    (setq key (logand last-command-event 255)))
  (let* ((prefix (char-to-string key))
         (current-name (my-workspace-name))
         ;; This will be explained later:
         (predefined (cl-assoc prefix my-workspaces :test #'string-prefix-p)))
    (if predefined
        (cl-destructuring-bind (name new-fn refresh-fn) predefined
          (if (equal current-name name)
              (when refresh-fn
                (funcall refresh-fn))
            (when (and (my-workspace-switch name)
                       new-fn)
              (funcall new-fn))))
      (let* ((candidates
              (remove current-name
                      (cl-remove-if-not
                       #'(lambda (n) (string-prefix-p prefix n))
                       (my-all-workspace-names))))
             (n (length candidates)))
        (cond
         ((= n 0)
          (my-workspace-switch
           (read-from-minibuffer "Switch to workspace: ")))
         ((= n 1)
          (my-workspace-switch
           (car candidates)))
         (t
          (my-workspace-switch
           (completing-read "Switch to workspace: " candidates nil t prefix))))))))

(global-set-key (kbd "<s-return>") 'my-last-workspace)
(dotimes (i 26)
  (global-set-key (kbd (format "s-%c" (+ ?a i))) 'my-switch-to-workspace))

This implements a single key workspace switching and assigns it to key bindings. I use a–z letters, as seen above, together with Super modifier to switch between workspaces. I name my workspaces in such a way that the name of each of them preferably starts with a different letter, making this mechanism work very well. I also define C-c z binding to be able to switch among workspaces when Super key happens not working:

(defun my-switch-to-workspace-key (key)
  (interactive "c")
  (my-switch-to-workspace key))  
(global-set-key (kbd "C-c z") 'my-switch-to-workspace-key)

As there are Emacs applications I run often, in their own workspaces, it’s useful to have predefined workspaces:

(defvar my-workspaces
  ;; name
  ;; new-fn
  ;; refresh-fn
  '(("emacs"
     nil
     (lambda ()
       (require 'bookmark)
       (unless bookmark-alist
         (bookmark-maybe-load-default-file))
       (bookmark-jump "init.d"))) 
    ("gnus"
     gnus
     (lambda ()
       (let ((group-buffer (get-buffer "*Group*")))
         (if group-buffer
             (switch-to-buffer group-buffer)
           (gnus)
           (cd "~")))))
    ("irc"
     my-erc-connect
     nil)
    ("org"
     my-org-agenda
     my-org-agenda)
    ("roam"
     org-roam-find-file
     org-roam-find-file)
    ("system"
     my-run-eshell
     (lambda ()
       (call-interactively
        (lambda ()
          (interactive)
          (ido-buffer-internal ido-default-buffer-method nil nil nil "eshell:")))))))

Each entry in this list defines a workspace name, the function to run when the workspace is created and the function to run when switching to the workspace I’m already in (a “refresh” function), which is especially useful to reset the workspace to its default state. The corresponding part in my-switch-to-workspace above takes care of the predefined workspaces.

One last bit is handling workspaces containing development projects. It’s natural to name them after their source directories but that could quickly lead to initial letter collisions with other workspaces. I dedicated a special x: prefix to those workspaces. I use Projectile to manage my source directories and integrate it with my workspaces:

(defconst my-projectile-workspace-prefix "x:")

(defun my-projectile-switch-project-action ()
  (when (my-workspace-switch (concat my-projectile-workspace-prefix
                                     projectile-project-name))
    (projectile-vc)
    (delete-other-windows)))
(setq projectile-switch-project-action 'my-projectile-switch-project-action)  

When I open a development project using Projectile, it automatically switches to its workspace, names it accordingly and opens Magit for it. Then I can switch to the project using s-x key. If I work on multiple development projects simultaneously, my-switch-to-workspace offers the last one used by default to avoid using completion all the time.

As you can see, utilizing Emacs frames as workspaces is easy and powerful. I don’t need to use or make special add-ons to have workspaces, Emacs frames are good enough and they can be customized as needed relatively easily.

speechd-el 2.11 released

speechd-el 2.11 release introduces index marking feature, i.e. moving the cursor as the text of a buffer is read. This feature has been planned for more than 10 years but due to various circumstances, its implementation, although not that difficult, has been delayed. Now it is finally implemented although it may need further improvements in future if performance problems are experienced in practice. Sending long texts to Speech Dispatcher in chunks may be one of useful improvements.

speechd-el was designed as a project requiring low maintenance that needn’t be updated with each new Emacs version. Time has proved it is indeed so and speechd-el rarely requires updates of its code base. However, speechd-el has been here long enough to experience some conceptual changes in Emacs. During the time, Emacs has deprecated cl library in favor of cl-lib, improved the function advising mechanism and introduced a true lexical let. 2.11 version adjusts to those changes and, together with some other fixes, removed all compilation warnings.

So speechd-el is now in a clean state and the last long-planned feature has been implemented. I currently don’t plan any further changes to speechd-el unless there are bug reports, feature requests or patches from its users.

Playing with high-resolution audio

Some time ago, I’ve found out that under special circumstances I can hear differences between 320 kbps mp3 and CD audio. Now, I’m curious whether I can hear any difference between CD and high-resolution audio.

There is a lot of discussions whether high-resolution audio is a gimmick or a useful thing. Maybe the answer is simple: some people can hear the difference against CD audio, some can’t and some think they can while they can’t. Either of that is fine, one enjoys the music the way he likes it.

However it’s not that easy to find relevant arguments about high-resolution audio. One of the most pro-arguments is that it’s better because it has a higher sampling frequency and a higher bit depth. Yes, it has both, but an explanation whether it actually matters and why is usually missing. On the other hand, there are cons-arguments about „Nyquist theorem“ and „dynamic range“. But they also usually miss meaningful explanations. Yes, according to the Nyquist theorem, CD audio is good enough to capture frequencies up to 22 kHz, i.e. covering the frequency limits of human hearing. But music is not only about frequency but also about volume and tone curve shapes. Imagine what happens e.g. to a sine or another 10 kHz or 11.025 kHz sound curve when it’s sampled on 44.1 kHz. Yes, you get exactly the same tone frequency, but possibly with a lower volume and sounding like a different instrument. And regarding dynamic range, it’s about resolution in the quiet parts. While 16-bit whole-range resolution covers the whole audible specter, less than 10-value range remains to represent quiet but still audible sounds, which looks a bit coarse.

So purely numerically, high resolution audio adds information within nominal human listening range. Whether we can recognize the added information is a different question as well as whether we can percieve inaudible frequencies some way. I guess my tentative answer above holds, but let’s return to the original problem, whether I can hear the difference. The best way to find out is to try it, which is not completely trivial.

The first step is finding true high-resolution audio. Some popular hi-res sites sell overpriced recordings, which I’m not going to buy. Another option is utilizing streaming services offering hi-res audio but I’m not their subscriber. Fortunately, there is a selection of Czech music of various genres in hi-res, not much more expensive than their CD quality versions. I bought five albums of different kinds there that I’d probably buy anyway sooner or later (three contemporary recordings, two older recordings from analog tapes; one classical orchestral work, two single-instrument classical works and two popular music albums with a lot of vocals; one 192 kHz, two 96 kHz, one 88.2 kHz, one 48 kHz and all 24-bit). For a total additional price of about one pizza I could obtain their hi-res versions. This is worth the fun, isn’t it?

The second step is how to play hi-res audio. Besides the obvious need of having an audio system capable of playing hi-res audio, there are also software issues. The PulseAudio thing clearly tries to solve different problems than playing hi-res audio (well, I wonder again which ones — my recent experiences include heavily distorted sound on normal play and inability to switch to a different sound input for a running application) and it’s best to avoid it. Fortunately, there is a way to prevent PulseAudio from touching a USB DAC. Then it’s possible to use the DAC safely with a player that can send sound data to the DAC directly, without any sound processing and conversions. I used VLC with ALSA output. Another option is to use Volumio on a dedicated device (such as Raspberry Pi), which does the right thing out of the box.

The third step is to get something to compare the hi-res version to. The mp3’s bundled with the hi-res recordings are lossy and I can’t be sure they weren’t processed differently. I used sox utility to convert the audio to a CD like quality, i.e. 16 bit depth and 48 or 44.1 kHz frequency (depending on the original hi-res frequency):

sox FILE.flac -r 48000 -b 16 FILE-cd.flac

The fourth step is finding a calm moment when it’s possible to listen to the music carefully, without disruptions and background noise. This is the most tricky thing!

Finally, the fifth step is actually listening to the music.

And the result? I couldn’t hear any difference.

Back to Vanilla Music

I have found out that I was mistaken, Odyssey Android music player cannot always play the tracks in the right order. Additionally, it has sometimes problems (as many Android music players have) with non-ASCII characters in file tags. So I’m returning back to using Vanilla Music. I abandoned it when it was incapable to play newly added albums whatever I tried to do. This seems to be fixed now. And there are also no problems with non-ASCII characters so far.

Another good news about my phone is that the occasional very short (and very annoying) interruptions of music play (regardless of the music player used) are, hopefully, also no longer present.

It’s sooo nice when one can play music on a mobile phone.

Switching from Firefox to Brave

The new Firefox ESR release has hit my desktop this week. Debian stable is stable; except for Firefox. Firefox ESR releases last only for about one year. Debian release cycle is typically about two years so in order to keep up with security fixes, Debian stable has to switch to a new major Firefox version once a year. That means replacing old bugs with new ones in Firefox more often than in the rest of the system.

This time, color management has stopped working for me after the update. The only way I’ve found to avoid green faces and/or completely false colors at some places was to disable color management completely. (Yes, using those cryptic undocumented numeric values in about:config.) I don’t know what’s wrong, the rest of my system hasn’t changed and all the other color management capable applications work normally. There are reports about color management bugs in Firefox 77 and later (the ESR version is 78). It’s not a critical problem, I can use a different browser when I need to see accurate colors, but it’s still annoying. But what is worse, such a kind of regression indicates that there is something wrong with Firefox development.

Firefox is dying and IMHO one of the reasons is that it stops offering attractive features to its users. Which of the new Firefox features introduced in the last years do you use? I can’t recall any. Which of the old Firefox features removed in the last years do you miss? I can recall several.

Firefox has still some significant advantages over most other web browsers: It can still browse the web, it’s free software and it doesn’t track its users (this may be a bit arguable but there is a clear difference against the most popular web browser). But I’m afraid Firefox won’t survive and we will be able to use only proprietary web browsers in the future, returning to what we had a quarter century ago. There is at least hope we won’t remain just with The Only Mighty Web Browser on GNU/Linux.

Enough is enough and I think it’s time to start looking around. Firefox has already set my web browser UI expectations so low during the time that there is little barrier to start preparing for the future by switching to a different browser. So I’m switching to Brave. Well, who knows how long that web browser survives. But it’s free software, based on a popular code base, led by Brendan Eich, and with an interesting approach to privacy, advertisements and content creators. And yes, color management works in Brave.

The Brave concept is definitely worth to try. Replacing spying advertisements with micropayments should have already been here long time ago and I’m happy we have finally something that starts pushing the very needed change seriously. It’s currently only a half-step IMO because of the use of cryptocurrencies (the concept of money based on wasting electricity is flawed) and requiring me either to accept privacy-respecting advertisements (no, thank you, I’m not interested in advertisements) or to upload my identity card to an internet service (I don’t know why Binance needs it for small exchanges; there is no such need when using real money). So I’m taking also only a half-step now and just switching to Brave and not joining its Rewards program. Hopefully the service will evolve and will allow me to use real money sooner or later to reward content creators.

Natalika

Who remembers the old times when most music albums were not available on streaming services and couldn’t be bought online as downloadable archives? In the pre-online music era, there was a lot of amazing recordings by non-mainstream artists that are no longer available nowadays.

I was lucky a couple of times and discovered great old CDs in some “forgotten” e-shops or in second-hand stores. A few of those old recordings were released again. But most of them are unfortunately inaccessible, maybe forever.

One of the recordings that I’ve missed were albums by Natalika. That amazing world music band was quite popular for a few years around 2000 (in the sense that it even appeared on TV several times). And then the band disappeared for long time. IIRC their CDs were never available in normal distribution so I’ve never seen them in CD shops. And I think their online presence was irregular during the time. From time to time, I recalled the band but couldn’t find their CDs anywhere at the moment.

I’ve recently recalled the band again and found out that they have a working web site and their 20 years old CDs are still available. What a discovery! I ordered the CDs and now I can enjoy listening to those great pieces of music, which were previously missing in my music archive. AFAIK those CDs are the last unsold pieces, which won’t be available anymore in any form once they are sold out. If you like that kind of music, grab them while you can, they are worth it.