KIN is a portable lightweight tray utility which sends realtime data from your system to USB HID devices, with the goal of making them more intelligent
KIN is a portable lightweight tray utility which sends realtime data from your system to USB HID devices, with the goal of making them more intelligent
🔥 cskartikey marked your project as well cooked! As a prize for your nicely cooked project, look out for a bonus prize in the mail :)
I built a tray utility which send system info to configured HID devices. I am really happy with the current version of the software, since my own HID devices work really well with it. The hardest part was definitely removing as much CGO as possible in order to make compiling easier on most platforms.
I want to work on it more, maybe by allowing devices to be plugged in at runtime or a configuration UI but for now everything is complete. I also want to improve Linux compatibility since it isn’t very good right now, as it relies on certain CLI software to be present.
I sorted out all the extra stuff you need to do whenever launching a project. This means I now have a completed README to describe the project, a LICENSES directory which links all the third party libraries/software I used along with their licenses, and an automatic release system which will build the software for all supported platforms whenever I push a version tag.
The only major thing which I would like to have is automatic building for x86-64 on macOS, but since fyne-io/systray requires CGO for macOS and GitHub doesn’t have a free runner for x86 macOS it’ll have to be left out for now.
Here’s a screenshot of what the tray looks like on all platforms
Log in to leave a comment
I added 2 features to the tray which make the user experience better. The first is device status which will tell you whether or not the device is connected to the application. The second is a shortcut to open the config directory, since opening it manually is ever so slightly annoying. I also added icons to all the tray actions to make it look a bit better.
Log in to leave a comment
The actual code is now complete! Well there is still the tray features I want to add but that’s about it. Since there is a lot I did this time around I’ll split this into parts based on what changes I made.
Refactoring Code
This time around I refactored literally the entire codebase. Nearly every function has been changed in some way, whether it be small changes like variable names or parameters, or big changes like merging entire files. There are hardly any comments since I wanted the code itself to be clear enough to anyone trying to understand the code. The main exception to this rule is in purego code, where I have comments explaining which headers constants or data structures come from.
HID Updates
I swapped from “github.com/sstallion/go-hid” to “rafaelmartins.com/p/usbhid” since the former is written in CGO, while the latter is written in purego. Functionality is the exact same, the only differences are in the function definitions and data types. Only one minor change was made which is adding a magic hex header to all data which is sent, which allows a HID device identify whether data is being sent from KIN or some other source.
Tray Icon
I finally updated the tray icon to something more appropriate. I made 3 versions of the icon using Aseprite. The first is the primary version used on Windows and Linux in most situations. The second is a low resolution version which is used only on windows in Low-DPI situations. The third is a monochrome icon which MacOS uses as a NSImage template image. The new icon looks pretty decent on all platforms imo.
The demo attached uses my hackpad to demonstrate data being transmitted from device to my hackpad over HID, which is then logged through QMK.
Log in to leave a comment
I’ve swapped the info fetchers on MacOS and Windows to use purego instead of CGO. This also means that I’m no longer using a CLI tool like osascript on macs, which is cool I suppose. However to get cross compilation working, I will need to swap the hid library which is being used as the current one uses CGO and that’s no good.
I also plan on doing another cleanup of the codebase, while also documenting pretty much every function and variable because things are a bit messy in my opinion. Along with that I want to rename active_window to activeapp because that’s what it actually does, it tells you literally nothing about the window and only about the active application name. No idea what I was thinking when initially naming the folder. Finally I need to add features to the tray item since it’s a bit useless right now besides letting you know the application is running
Log in to leave a comment
So I got windows working properly, though I think I’m going to change the architecture for most of the application. Before I talk about that, I removed MIQT since I decided against a proper UI, and a tray item can be accomplished by using a fyne package which doesn’t require CGO. I also moved all of the info fetchers into a folder called info, simply for convenience sake.
Currently I’m using a combination of CGO and windows syscalls in order to fetch the information we need. However I don’t really like using CGO since it makes building a huge pain on windows since you need a proper mingw setup. This also applies to other platforms, since one of the big benefits of Go is how easy it is to cross compile simply by setting GOOS. In theory this comes at a performance cost, since the only proper alternative to CGO us purego from what I have found. But since purego uses a lot of the same code as CGO for interacting with C, and the fact that the program is already extremely light weight, I think it’s acceptable.
Log in to leave a comment
Linux works now! It is not done in the best way though. Right now I’m simply calling a CLI executable and filtering the output for what I want. On MacOS I still consider this acceptable since osascript is on literally every Mac. On Linux however so many configurations are possible that I would rather use CGO to support more platforms (specifically more wayland compositors). This means I will be rewriting in the future, but for now It’s perfectly fine while I work on Windows support.
Log in to leave a comment
We now have a working config file! I decided on TOML since it’s arguably the most readable since it is practically an extended .ini file. I’ve not gotten configuration from UI working, but I’m not particularly attached to having a UI beyond a tray item so it’ll depend on whether I feel like it or not.
There was of course more refactoring as I moved stuff between folders in order to keep the codebase relatively clean and easy to read. I also made sure exiting is done properly through a dedicated shutdown function, since I don’t think anyone would appreciate a memory leak in the application.
There is not too much left which I want to do. I want to make something like an ARCHITECTURE.md file where I describe the application architecture for the sake of clarity. I’m also going to need to actually flesh out the README.md. Finally there’s cross-platform compatibility, which should be extremely simple in theory.
Log in to leave a comment
So this is going to be a smaller project because I don’t have too many goals for the software.
I want it to be configurable so you can actually pick which device you want to send info to. I also want to be able to configure what data is sent, and what is not. It’s obviously going to work on the 3 main operating systems (MacOS, Windows, Linux Wayland/X11) since I personally use all 3 depending on the situation.
To that extent I’ve already got 2 of the main pieces of information I want to send, which is volume and the active application setup. I’ve also got sending the data over HID to a keyboard set at build time, but I haven’t gotten to the point where it’s configurable.
Not sure what picture to upload for this one, so I’ll go with the (most likely temporary) tray icon for the application (I set up a tray with MIQT)