Gerrit Niezen

Maker of open-source software and hardware.

Feature image

I'm working out of a co-working space in town today, and walked into a bookshop during my lunch break. Yes, a physical bookshop. You know they still exist, right?

Unfortunately there is only one independent bookshop left in Swansea and that one is in the lovely seaside village of Mumbles, not in the town centre. I was walking around in Waterstones, one of the larger bookstore chains in the UK. The one in Swansea is inside the old Carlton Cinema, a historic building with a beautiful glass facade.

They do have a pretty extensive collection of books, and I noticed the following ones which piqued my interest:

Let me know in the comments if you can guess the thread that ties these authors together! 😜

#Reading

Feature image

One spindle on the staircase in our new house is broken. How do you go about finding out a new one? I started googling and found out there is a mind-boggling array of spindle designs. I found one website that said they made copies of spindles of your existing staircase and you just need to send them a picture. I sent off all the required info and got back an e-mail very quickly saying that there's a minimum order quantity of 35. Yes, it would've have been great if they posted that detail on their website.

Ten websites and hundred of designs later, I discover that it's actually a very simple design called an Edwardian spindle, and there is a specific design that's from the “Richard Burbidge Trademark Range” that's very popular. I'm not 100% sure if ours is from that range, but at least I've now identified the design. This would be a great use case for Amazon's new Part Finder tool.

Feature image

Man, moving house can be tiring, especially if you're trying to do it yourself. We've had great help from friends with the whole process, but there's still a lot of work to do.

A move is always an eye-opener to see exactly how much stuff you have. Why do we have so much stuff? Some of it is necessary, but I'm sure all of us have some things that we hold on to just in case. I hope I can get rid of some of the “just in case” stuff soon, as I just don't have the energy right now to try and decide what I want to keep and what I want to throw or give away.

One thing that I'm kind of excited about is that I want to re-read some of the books on my book case. I mean, I know I'm keeping them because I like them, so I should re-read them to at least see if that is still the case.

Feature image

It's pretty early on Saturday morning, but I just realised that I probably won't have time later today to write a blog post. We're in the process of packing to move to the new house.

I rented a van yesterday. I've never driven one before, so that was an interesting experience. It was weird not being able to look behind you, as there is no rear view mirror. Apart from that, it didn't feel that different from driving a car.

I usually enjoy the part of packing where you can get rid of things, but it feels like I'm just stuffing things into boxes at the moment. Hopefully I will be able to properly go through things when I unpack and then be able to throw some things away. Well, let's get started!

Feature image

OK, this is the last of my “favourite X of the first half of 2018” posts, this time covering some TV series I've enjoyed watching. Lately I mostly just watch Netflix, and prefer reading to watching TV, so I definitely don't consider myself to know what's good on TV.

  • Altered Carbon - I read the book a while ago, and obviously the TV series doesn't match up to the book. Still, it's entertaining viewing, if you don't mind your sci-fi being a bit violent.
  • Black Mirror Season 4 - The best kind of sci-fi is the kind that you think about long after you've first watched it.
  • Star Trek: Discovery - It may be a different than the other Star Trek series, but still very enjoyable.
  • Safe - Hearing Michael C. Hall speaking with a British accent takes some getting used to, but it's definitely worth the watch (even if you're not a fan of Dexter).

Currently I'm watching The Staircase, but I'm not yet sure whether to recommend it as I'm just over halfway in the season.

Feature image

Wow, I didn't think I'd be able to keep this blog going for two months without skipping a day, but here we are. As I'm not using any analytics on this blog, I have no idea how many people are actually reading this. Which is probably a good thing, as my focus is on just putting something out there every day and not necessarily trying to build an audience.

I hope someone finds some of the things I write here useful. Maybe I should at least enable a comment section to give anyone reading this the opportunity to provide feedback. You know what? I'm going to add it right now.

Feature image

Today I started on wrapping the libmtp C library in a Node.js module. So far, I've managed to load the list of files on the device and successfully retrieve a file.

Let's start with the bindings.gyp file:

{
  "targets": [{
      "target_name": "module",
      "sources": [ "./src/module.c" ],
      "libraries": [
          "<!@(pkg-config --libs libmtp)"
      ],
      "cflags": [
          "<!@(pkg-config --cflags libmtp)"
      ]
  }],
}

Here I'm specifying that the file containing the C code is in module.c, and that we're using the libmtp shared library. On macOS, use brew install libmtp. On Linux, use sudo apt-get install libmtp-dev. Oh, you'll also need pkg-config if it's not installed on your system yet[1].

Here is the NAPI function to run the code in the C library and return the result to JS:

napi_value getFile(napi_env env, napi_callback_info info) {
  napi_status status;

  size_t argc = 2;
  napi_value argv[2];
  status = napi_get_cb_info(env, info, &argc;, argv, NULL, NULL);
  if (status != napi_ok) {
      napi_throw_error(env, NULL, "Failed to parse arguments");
  }

  int id = 0;
  char path[20];
  napi_get_value_int32(env, argv[0], &id;);
  napi_get_value_string_utf8(env, argv[1], path, 20, NULL);

  int ret = LIBMTP_Get_File_To_File(device, id, path, NULL, NULL);

  napi_value retVal;
  status = napi_create_int32(env, ret, &retVal;);
  if (status != napi_ok) {
      napi_throw_error(env, NULL, "Unable to create return value");
  }

  return retVal;
}

For details on how we get the arguments converted from JS to C, and the return value back to JS, see this tutorial. The line to focus on here is the one with LIBMTP_Get_File_To_File, where we pass the file ID to get from the device, and a path to save that file to.

As we need to connect to the device before we read the file, I added the following code to the NAPI Init function:

napi_value Init(napi_env env, napi_value exports) {
  napi_status status;
  napi_value fn;

  LIBMTP_Init();

  fprintf(stdout, "libmtp version: " LIBMTP_VERSION_STRING "\n\n");

  device = LIBMTP_Get_First_Device();
  if (device == NULL) {
    printf("No devices.\n");
    return 0;
  }

  status = napi_create_function(env, NULL, 0, getFile, NULL, &fn;);
  if (status != napi_ok) {
      napi_throw_error(env, NULL, "Unable to wrap native function");
  }

  status = napi_set_named_property(env, exports, "get_file_to_file", fn);
  if (status != napi_ok) {
      napi_throw_error(env, NULL, "Unable to populate exports");
  }

  return exports;
}

NAPI_MODULE(NODE_GYP_MODULE_NAME, Init)

The line with napi_set_named_property specifies what the function name is called in JS, while napi_create_function creates a JS function from the C function called getFile.

Now it's as easy as just calling the function from JS:

const binding = require('node-gyp-build')(__dirname);
    
console.log(`Status:`, binding.get_file_to_file(1693, 'test.jpg'));

We pass the file ID (1693 in this example) and the path to save file into (test.jpg in the same folder). And that's it, we can read files from an Android phone over MTP on macOS! I'll be posting all the code on GitHub soon once I've cleaned it up a bit.


  1. brew install pkg-config on macOS. ↩︎

#nodemtp

Feature image

Following up from yesterday, I started using libmtp to see if I can connect to an Android phone and read a file from it. Once the library is successfully compiled, you can run some of the example programs in the examples/ folder. To list all the files on your device, run ./mtp-files. Then, to retrieve a file, you can run

./mtp-connect --getfile <FILE_NUMBER> <DESTINATION>

It seems to work just fine, so the next step is to wrap it as a Node.js library. There's a great article by Mathias Buus on the past and present of handling native (C/C++) modules in Node.js. Basically, N-API is the way to go. It's already stable in Node v10, and works in Node v8 as well.

I followed this tutorial to build a basic native module with N-API, and it works great. The best part was building it and running it in Node v10, and then running the same code in Node v8 without any issues. Nice!

#nodemtp

Feature image

Media Transfer Protocol (MTP) has replaced USB Mass Storage as the dominant protocol for transferring digital media between an Android phone and a computer. USB Mass Storage allows devices to be mounted as drives on the host computer, and while MTP also allows drives to be mounted, it happens at a level where it's easier to restrict which files are made available to the host system. If that sounds to you like something Microsoft would design, you'd be right.

MTP works great on Windows machines of course, and surprisingly well on Linux. However, while there's apparently some basic MTP support on macOS, it doesn't even allow you to mount a device without external software, like Android File Transfer.

I spent some time today looking at options for connecting to an Android phone on macOS with MTP using Node.js. Here are some possible options:

  1. Use FUSE (Filesystem in Userspace) with Node bindings. This will requires installation of FUSE for macOS first, which I think also involves installing a kernel extension. So it's basically a no-go for macOS High Sierra and above.
  2. Write a wrapper for libmtp, using this unmaintained repo as a base.
  3. Port parts of this application over to Node.js, as its only dependency seems to be libusb. This means essentially writing your own MTP implementation on top of node-usb.

Since MTP has been standardised as part of the USB Device Class specifications, writing an MTP implementation on node-usb does make sense, but will probably be a lot of work. I think I will opt for (2) first as it's easier, with (3) as a fallback.

#nodemtp

Feature image

If you have an e-reader/Kindle, and you haven't yet had a look at Standard Ebooks, do yourself a favour and go there now.

Depending on where you are in the world, copyright only expires 50 to 100 years after the creator's death – crazy if you really think about it. In any case, that means hat you won't find any recently written books on Standard Ebooks, but you will find some great classics. Here are some that I still want to read, in no alphabetical order by author:

#Reading

Enter your email to subscribe to updates.