Friday, January 14, 2022

gmusicbrowser on Debian bullseye

gmusicbrowser is not longer available as a package to install to Debian Linux. It was removed in 2019, due to lack of maintenance and Debian bug 912882. The root cause was that gmusicbrowser depended on libgtk2-perl, which was being dropped.

gmusicbrowser issue 57 tracks progress to migrate to gtk3 since 2013. The 1.1.99.1 release is the first based on gtk3 but there has been a year of development since then, as yet unreleased.

Fortunately, it is easy to install the gtk3 based gmusicbrowser on Debian bullseye with xfce4 desktop. It is probably as easy to install with any other desktops, but I haven't tried any of them.

$ git clone https://github.com/squentin/gmusicbrowser.git
$ cd gmusicbrowser
$ sudo make install

I didn't have to install any packages beyond what were already installed.

I haven't tested it extensively, but I haven't had any problems. If you too like gmusicbrowser, you can install it to current Debian system easily this way, and probably many other systems.

Saturday, January 1, 2022

Preparing to configure Windows

 I bought a new laptop - a dynabook tecra. It came pre-installed with Windows 10. Completing the Windows 10 setup was easy but for the next few days, every time I reboot it installs more updates.

This time, it has been displaying 'Preparing to configure Windows' for over 20 minutes with no indication of progress or when it might finish. 

The Windows Club has a page on this. They recommend waiting for 2 hours before giving up and trying anything other than waiting.

TWO HOURS! For an update. Not even a full install.

I can complete an update of Linux in about 2 minutes, typically.

What is Microsoft thinking, to make such an obtuse update process? It's not like they are beginners, without experience. They have been doing this for years.

It is because of nonsense like this that I prefer Linux. I never have such problems with Linux.

I would just abort the Windows update but, being conservative, I want to backup the Windows partitions before I wipe them and install Linux and I don't want the backups corrupted by an incomplete update. I am having to reboot a few times to confirm I have all the Linux issues sorted (modules and firmware for all the essential hardware). It is extremely annoying having to deal with Windows again.

Eventually it had completed its update and now I am unable to access the BIOS setup or boot menu. It boots straight to Windows every time, restart or shutdown and boot. Fucking Windows update - it was working normally until the fucking update.


Saturday, December 11, 2021

srf - spaced repetition flashcards

I have been using srf to study Mandarin for about 6 months now, with a selection of decks imported from anki, and cards I have created myself. 

My study time is better regulated and I am making better progress than when I was studying with anki

The difference is the scheduling algorithm. The scheduler in srf regulates new cards automatically, to maintain a target study time per day and sorts due cards differently, allowing good progress even with a large backlog of due cards (e.g. after not studying for a few days).

Initial development of srf is now complete. Rate of change is slowed. The user interface, particularly for editing content, remains a bit crude but adequate. Lately, I spend most of my time studying and very little developing the program.

I was reluctant to develop a new program. It took a lot of time away from study. But the limitations of the anki scheduler were too frustrating and it is now clear that a better scheduler makes a big difference to progress. From a technical perspective, the differences are subtle and simple but practically they make a big difference.

The essential differences are:

  • present cards with shorter interval before cards with longer interval
  • automatically regulate new cards based on past and future workload

Presenting cards with shorter intervals first makes a big difference when working through a backlog. Anki presents cards in the order they were due, regardless of interval. The difference is subtle but important.

With a large backlog in Anki, the backlog effectively blocks review of cards with shorter intervals. Unfamiliar / difficult cards are not seen as soon as they should be, defeating learning. With a large enough backlog, it is practically impossible to learn: one churns through a large number of cards without making progress because it is too long between reviews.

The problem is exacerbated by anki introducing more new cards every day, despite the backlog. It is possible to change the number of new cards per day manually but paying attention to this takes attention away from studying.

The scheduler in srf prioritizes the cards you are learning (with shorter intervals) over the backlogged cards. Thus, one can learn despite the backlog and that learning is the way to clear the backlog. And while there is an excessive backlog, srf does not introduce new cards, so gradually, reliably, the backlog is cleared. When it is cleared, new cards are introduced again.

With these changes, study time per day is more consistent: varying closely around configured target study time per day. And progress is better when one is not overloaded.

libinput - touchpad acceleration - piecewise linear profile

I have implemented a piecewise linear acceleration profile for touchpad in a fork of libinput.

The mapping function is defined by an array of points: (speed, factor), which must be sorted in order of increasing speed. Between the points, factor is determined by linear interpolation.

A single point gives a fixed acceleration factor, like the libinput flat profile.

Two points give a single, linear slope, clipped at the upper and lower input speeds. But the clipping is irrelevant if the speeds of the two points are sufficiently low (e.g. 0) and high respectively, in which case all inputs will be at speeds between the points.

Factor
^
|                   _________
|                 /
|                /
|               /
|-----------/
|
+-----------------------------------------------> Speed

More complex curves can be approximated by more points. With enough points, any of the profiles in the old X.org server can be approximated.

At the moment, configuration parameters are hard coded, because I haven't figured out how to add configuration parameters and because using new parameters would require changing code outside libinput (e.g. the X or Wayland libinput drivers).

One of the limitations of libinput is that the only means of configuration is via the API. As a result, to add new configuration parameters requires modification of both the libinput library and whatever software (e.g. Wayland compositor, xf86-input-libinput, etc.) calls it. I may add configuration via environment variable to work around this limitation but in the meantime, as you will have to compile and install this version anyway, it is almost as easy to edit the source as a separate configuration file or environment variable.

See the touchpad-pl branch of this fork of libinput.

To try this profile for your touchpad:

$ git clone https://github.com/ig3/libinput.git
$ cd libinput
$ git checkout touchpad-pl
$ meson --prefix=/usr builddir/
$ ninja -C builddir/
$ sudu ninja -C builddir/ install

This is working for me on Debian 11 with xfce desktop. I haven't tried a system running Wayland.

To change the profile, edit src/filter-touchpad-pl.c. The parameters are in function touchpad_accel_profile().

To test:

$ sudu libinput debug-events

Monday, November 29, 2021

Brabantia BBEK1114 Break Maker

The manual for this bread maker is not very good and the functionality is limited. If I were buying another, I would look for something that lets me start at any point in the programs instead of only being able to start at the beginning.

I mostly used the Sweet Bread and French Bread programs. Timing isn't in the manual, which makes it difficult to add nuts, etc. as the bell is not very loud: unless you are right by the machine and listening for it, it is easy to miss.

The timer counts down. If you add time (up to 15 hours total) the additional time is added at the beginning, doing nothing. The program itself is not changed otherwise. This is a problem because all the ingredients are in the machine and the yeast can start fermenting. It would be better to do an initial mix and beat down the dough periodically, instead of leaving it to sit un-mixed. But there is no such option. Best one can do is leave it in a cool place so the dough doesn't rise too much and overflow. 

There is no indication in the manual of the baking temperature. I haven't tried to measure it.

I generally use only a teaspoon or less of dry yeast and about half the indicated sugar in the 750g recipe and it rises to fill the machine, sometimes rising to press against the top. I haven't tried a 1kg recipe but expect it would overflow if I didn't do anything to limit its rising.

I have only made a few of the recipes. The results are surprisingly good and it is very easy, but more like cake than bread. Quite short and crumby. Adding some gluten to the 11.5% protein flour helps a bit.

Sweet Bread

  • 3:45 - Start / Mix
  • 3:41 - Knead
  • 3:38 - Rest
  • 3:30 - Knead
  • 3:20 - Rest
  • 3:10 - Knead
  • 2:55 - Rest
  • 2:40 - Knead
  • 2:35 - Add / Knead
  • 2:25 - Ferment
  • 1:35 - Beat down
  • 1:34 - Ferment
  • 0:50 - Bake
  • 0:00 - Keep warm

French Bread

  • 4:00 - Start / Mix
  • 3:56 - Knead
  • 3:50 - Rest
  • 3:40 - Kenad
  • 3:35 - Rest
  • 3:30 - Knead
  • 3:10 - Rest
  • 2:55 - Knead
  • 2:50 - Add / Knead
  • 2:40 - Ferment
  • 1:40 - Beat down
  • 1:39 - Ferment
  • 0:50 - Bake
  • 0:00 - Keep warm

Monday, November 15, 2021

Libinput: using libinput as a library

The libinput documentation includes a section on using libinput as a library, but with no prior experience with libinput, I found it inadequate to get me oriented. So, here are some additional notes.

Background

libinput is a library to handle input devices in Wayland compositors and to provide a generic X.Org input driver. It provides device detection, device handling, input device event processing and abstraction so minimize the amount of custom input code compositors need to provide the common set of functionality that users expect. Essentially, it is an interface to the input devices.

libinput is not used directly by Wayland applications, it is an input stack used by the compositor.

libinput is not used directly by X applications but rather through the custom xf86-input-libinput driver.  

Libinput may be used by programs other than these display servers. For example, the libinput distribution provides several tools for testing and interacting with libinput. Any program that accesses the input devices supported by libinput may use libinput to access them, as an alternative to accessing them directly.

libinput is designed to handle all input devices available on a system but it is possible to limit which devices libinput has access to. For example, the use of xf86-input-libinput depends on xorg.conf snippets for specific devices. But libinput works best if it handles all input devices as this allows for smarter handling of features that affect multiple devices.

libinput handles all common devices used to interact with a desktop system. This includes mice, keyboards, touchscreens, touchpads and graphics tablets. libinput does not expose the device type to the caller, it solely provides capabilities and the attached features (see this blog post).

libinput does not handle some devices. The primary reason is that these device have no clear interaction with a desktop environment.

See Building against libinput for guidance on configuration and linking the libinput library. 

Libinput does not have many configuration options. This is deliberate.

Initializing a context

The first step in using libinput is initializing a context. The context is manifest as a data structure. Most calls to libinput functions require this context as an argument.

The libinput API documentation has a section on Initialization and manipulation of libinput contexts.

Saturday, November 13, 2021

Libinput sample

The libinput API documentation has a sample program on the main page but it doesn't compile as given.

This revision of it does compile and run:

#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <libinput.h>
#include <libudev.h>
#include <stdio.h>

#define ANSI_HIGHLIGHT    "\x1B[0;1;39m"
#define ANSI_RED    "\x1B[0;31m"
#define ANSI_GREEN    "\x1B[0;32m"
#define ANSI_YELLOW   "\x1B[0;33m"
#define ANSI_BLUE   "\x1B[0;34m"
#define ANSI_MAGENTA    "\x1B[0;35m"
#define ANSI_CYAN   "\x1B[0;36m"
#define ANSI_BRIGHT_RED   "\x1B[0;31;1m"
#define ANSI_BRIGHT_GREEN "\x1B[0;32;1m"
#define ANSI_BRIGHT_YELLOW  "\x1B[0;33;1m"
#define ANSI_BRIGHT_BLUE  "\x1B[0;34;1m"
#define ANSI_BRIGHT_MAGENTA "\x1B[0;35;1m"
#define ANSI_BRIGHT_CYAN  "\x1B[0;36;1m"
#define ANSI_NORMAL   "\x1B[0m"


static int open_restricted(const char *path, int flags, void *user_data)
{
        int fd = open(path, flags);
        return fd < 0 ? -errno : fd;
}
 
static void close_restricted(int fd, void *user_data)
{
        close(fd);
}
 
const static struct libinput_interface interface = {
        .open_restricted = open_restricted,
        .close_restricted = close_restricted,
};

static void
log_handler(struct libinput *li,
    enum libinput_log_priority priority,
    const char *format,
    va_list args)
{
  static int is_tty = -1;

  if (is_tty == -1)
    is_tty = isatty(STDOUT_FILENO);

  if (is_tty) {
    if (priority >= LIBINPUT_LOG_PRIORITY_ERROR)
      printf(ANSI_RED);
    else if (priority >= LIBINPUT_LOG_PRIORITY_INFO)
      printf(ANSI_HIGHLIGHT);
  }

  vprintf(format, args);

  if (is_tty && priority >= LIBINPUT_LOG_PRIORITY_INFO)
    printf(ANSI_NORMAL);
}
 
 
int main(void) {
  fprintf(stderr, "start main\n");
        struct libinput *li;
        struct libinput_event *event;

        struct udev *udev = udev_new();

        if (!udev) {
          fprintf(stderr, "Failed to initialize udev\n");
          return -1;
        }
 
        fprintf(stderr, "create libinput context for udev\n");
        li = libinput_udev_create_context(&interface, NULL, udev);
        if (!li) {
          fprintf(stderr, "Failed to create libinput context\n");
          return -1;
        }

        libinput_log_set_handler(li, log_handler);
        libinput_log_set_priority(li, LIBINPUT_LOG_PRIORITY_DEBUG);

        if (libinput_udev_assign_seat(li, "seat0")) {
          fprintf(stderr, "Failed to assign seat\n");
          libinput_unref(li);
          li = NULL;
          udev_unref(udev);
          return -1;
        }

        libinput_dispatch(li);
 
        while ((event = libinput_get_event(li)) != NULL) {
 
                // handle the event here
                fprintf(stderr, "in the event loop\n");
 
                libinput_event_destroy(event);
                libinput_dispatch(li);
        }
 
        fprintf(stderr, "unreference libinput context\n");
        libinput_unref(li);
 
        return 0;
}

 

This can be compiled with:

$  gcc -o sample sample.c `pkg-config --cflags --libs libinput` -ludev

 

Labels