Gerrit Niezen

Maker of open-source software and hardware.

I have a Next Thing Co. CHIP single board computer (unfortunately discontinued) that I use to run homebridge, in order to connect HomeKit to my Hive home setup. So that I can control my thermostat and lights using Siri on my phone you see!

What is a little bit annoying is that the flashing lights on the CHIP makes my study look like a disco at night. I want a little case that covers the lights – Thingiverse to the rescue! There are quite a few designs for CHIP cases, so I decided to settle on the one that has been made the most.

It's currently printing on my Prusa i3 MK3 and should take around 30 minutes. Just before printing the printer let me know that there's a new firmware version available, probably because I upgraded the slicer software. Having a really long USB type B cable makes updating the firmware super easy, as I can connect the computer to the printer without having to move things around.

#Making

Comment on this post

Oops, I skipped a day yesterday. Mainly it was because I was visiting Cellnovo at the Sony UK Technology Centre in Pencoed, and I only got back late in the afternoon. Sony Pencoed is where the Raspberry Pi is made, but I wasn't there for the Pi. I was there to learn more about Cellnovo's insulin pump.

I'll post more details in the future, but let's just say for now that it was pretty impressive to see what goes into making a high-accuracy insulin delivery device. Cellnovo started out here in Swansea in 2002, and moved to Pencoed just outside of Bridgend in 2016. It's great to know that there's a state-of-the-art insulin pump being manufactured less than an hour's drive from where I live.

Comment on this post

Feature image

I struggled for two days straight to get my LZO Node module working on Windows. It kept on complaining about “A dynamic link library (DLL) initialization routine failed.” when trying to use it in Electron on Windows. It turns out that this is due to a bug in Electron and Node. The funny thing is that there is a workaround implemented in the prebuildify dependency I'm using, but I was just not using the latest version. Always check your dependency versions kids!

There was one more twist: It still wouldn't work on 32-bit Windows, resulting in a “Module not found” error when it's clearly in the right directory. It seems to have something to do with the avutil-56.dll I built, as using a prebuilt .dll works fine. I do need to build my own, as prebuilt ones are usually not LGPL licensed. So now I'm rebuilding FFmpeg for the umpteenth time, this time round using the ffmpeg-windows-build-helpers script to build LGPL-licensed 32-bit and 64-bit cross-compiled shared libraries:

./cross_compile_ffmpeg.sh --enable-gpl=n --build-ffmpeg-shared=y --compiler-flavors=multi

#Node.js

Comment on this post

Feature image

I don't think I have ever had pumpkin pie before. To my understanding it is mainly eaten during Thanksgiving in the US. When we recently went to pick some pumpkins on a nearby farm for Halloween decorations, we made sure to get enough to make some soup and pie as well.

Today I cleaned and cubed one of the remain pumpkins we had, and attempted baking a pumpkin pie for the first time. I bought the shortcrust pastry, so that I just had to roll it out, but the rest was made from scratch. It's a nice feeling knowing that the pumpkin you picked from a field yourself is going into a pie you're baking yourself.

The pie came out of the oven looking reasonably edible, if not as pretty as the picture in the recipe I used. It's now in the fridge chilling for a while, and I'm looking forward to having a slice with a cup of coffee in a minute.

Comment on this post

Feature image

I enjoy using GNOME Boxes for virtual machines so much! I've already written about how horrible the experience of trying to use Virtualbox or VMWare on Linux is, and that everything just works in Boxes.

Having used it for a couple of months now, it is still working without any issues and has some delightful features:

  • There is a “Send file..” option, where you can send a file to the guest VM without even having to install any plugins.
  • The “Share Clipboard” option means you can copy & paste between the host and the guest VM.
  • If you do install the SPICE plugins on the guest VM, you can start sharing folders without even having to reboot the VM

And while writing this post I just discovered that I can connect remotely over VNC to my Windows test laptops using Boxes as well!

Comment on this post

Feature image

I found the reason why I didn't get av_lzo1x_decode compiled into the avutil library when cross-compiling to Windows from Linux the first time (as described in yesterday's blog post). Basically I needed to do sudo apt-get install mingw-w64-tools first, which adds a tool that ensures the necessary library functions get compiled in. Who knew?

Because the flag to use run-time references is enabled by default, you need to recreate the import library from the .dll file using the .def file:

lib /machine:x64 /def:avutil-56.def /out:avutil.lib

Note that if you're using a avutil-56.def file, your executable will be looking for a avutil-56.dll, not avutil.dll as expected. I had to use Dependency Walker to figure this out. And then I discovered that I only built the 32-bit DLL. To build for 64-bit, use:

./configure --enable-shared --arch=x86_64 --target-os=mingw32 --cross-prefix=x86_64-w64-mingw32-

By the way, if you want to check if a DLL file is 32-bit or 64-bit, you can use

dumpbin /headers avutil-56.dll | findstr machine

To use the right DLL with the right architecture, I used the following snippet based on headless-gl's binding.gyp:

'copies': [
  {
    'destination': '$(SolutionDir)$(ConfigurationName)',
    'files': [
      '<(module_root_dir)/lib/<(target_arch)/avutil-56.dll'
    ]
  }
]

This will copy the DLL from either lib/x64 or lib/x86 and put it in the same folder as module.node. Nice!

#Node.js

Comment on this post

Feature image

I've been away at a Tidepool offsite, which explains the lack of updates to the blog. Hopefully we'll be back to regularly daily updates from now onward.

I've been struggling to successfully link to the avutil shared library on Windows. I thought it was because of a problem with the settings in my binding.gyp file, but it turns out I somehow didn't build the required routine into the DLL file. I just discovered that there's a command on Windows that you can use to inspect DLL files.

dumpbin /exports avutil.dll

This lists all the symbol entries. I expected av_lzo1x_decode to be in there, and surprisingly it wasn't. Note that to use this command you need to have Visual Studio installed and then open a Developer Command Prompt or add it to your path.

Comment on this post

Feature image

As promised, here is the C code for wrapping libavutil's LZO algorithm into a Node.js module:

#include <node_api.h>
#include <napi-macros.h>
#include <stdio.h>
#include <stdlib.h>
#include "lzo.h"

#define BUFFER_SIZE 200

NAPI_METHOD(decompress) {
  NAPI_ARGV(2)
  NAPI_ARGV_BUFFER(in, 0)
  NAPI_ARGV_INT32(length, 1)

  int outlen = BUFFER_SIZE;
  unsigned char *out = malloc(outlen);
  napi_value result;

  int ret = av_lzo1x_decode(out, &outlen, in, &length);
  int size = BUFFER_SIZE - outlen;

  if (ret != 0) {
    napi_throw_error(env, NULL, "Failed to decompress");
  }

  NAPI_STATUS_THROWS(napi_create_buffer_copy(env, size, out, NULL, &result));

  free(out);

  return result;
}

NAPI_INIT() {
  NAPI_EXPORT_FUNCTION(decompress)
}

It makes use of the napi-macros package to keep things simple and readable. Basically we're just reading in two arguments – the encoded data and its length. We then send that to the decode algorithm by calling av_lzo1x_decode, and then copy the result in a Node.js Buffer object that we return. Simple.

Let me know if you see any mistakes – this code hasn't been peer reviewed yet.

#Node.js

Comment on this post

Feature image

Yesterday I started wrapping the LZO algorithm inside libavutil into a Node.js library. I'm still working on the C code, but let's have a look at how to test if it's actually working. I needed to generate some LZO-compressed date, so I installed the lzop tool using sudo apt install lzop. Then I generated a compressed file using:

echo "The quick quick quick brown fox" | lzop > y.lzo

I opened the resulting file in a hex editor and found the compressed bit, which looked like this: The quick q)�brown fox. Based on this, I figured that if I skip the first 50 bytes of the file, I get to the actual compressed data. So I wrote the following JS code to test if the decompression algorithm works:

const binding = require('node-gyp-build')(__dirname);
const fs = require('fs');

fs.readFile('y.lzo', (err, data) => {
  if (err) throw err;
  const skip = 50;
  const ret = binding.decompress(data.slice(skip), data.length - skip);
  console.log(ret.toString());
});

module.exports = binding;

So far I can see that the data decompresses successfully, but I'm still having a bit of trouble passing back the data into a Node.js Buffer object.

#Node.js

Comment on this post

Feature image

Now that I have built FFmpeg's libavutil as a shared library, I need to wrap the C code into a Node.js module. I've done this previously for libmtp, and will be following a similar approach.

First, we need to define our bindings.gyp file:

{
    "targets": [{
        "target_name": "module",
        "sources": [ "./src/module.c" ],
        "library_dirs": [
          "../lib",
        ],
        "libraries": [
            "-lavutil"
        ],
        "include_dirs": [
          "<!(node -e \"require('napi-macros')\")"
        ]
    }],
}

We have one C source file called module.c stored in ./src, while our shared libraries are stored in ./lib. For some reason, the relative path to define the library directories need to go up one directory in order to work. We also need to define the name of the library we're using, avutil, otherwise we'll get a symbol lookup error.

Note that I'm using the napi-macros set of utility macros that makes using N-API a bit more fun, as well as prebuildify. All that you need in your index.js is the following:

const binding = require('node-gyp-build')(__dirname);
    
module.exports = binding;

I'm still working on the C code, so look out for that tomorrow.

#Node.js

Comment on this post

Enter your email to subscribe to updates.