ref: 1632907c2adec85c3fbf552b1666cb1a77763cbd
parent: 2deb15b1fc32a56de320d35d8c55cbb572376502
author: laamaa <jonne.kokkonen@gmail.com>
date: Sat Sep 20 12:39:13 EDT 2025
add settings toggle keybinding (F1) and integrate with configuration system, update README.md
--- a/README.md
+++ b/README.md
@@ -2,34 +2,29 @@
## Introduction
-*m8c* is a client for Dirtywave M8 tracker's headless mode. The application should be cross-platform ready and can be
-built in Linux, Windows (with MSYS2/MINGW64) and macOS.
+*m8c* is a remote display client for the Dirtywave M8 Tracker. It mirrors the M8’s display, enables
+keyboard/gamepad control, and can route audio to your computer—useful for recording, streaming, larger screens,
+or alternative input methods. The application is cross‑platform and can be built on Linux, Windows (MSYS2/MINGW64), and
+macOS.
-The [Dirtywave M8 Tracker](https://dirtywave.com/products/m8-tracker) is a portable sequencer and synthesizer, featuring
-8 tracks of assignable instruments such as FM, waveform synthesis, virtual analog, sample playback, and MIDI output. It
-is powered by a [Teensy](https://www.pjrc.com/teensy/) micro-controller and inspired by the Gameboy
-tracker [Little Sound DJ](https://www.littlesounddj.com/lsd/index.php).
+The [Dirtywave M8 Tracker](https://dirtywave.com/products/m8-tracker) is a portable sequencer and synthesizer featuring
+8 tracks of assignable instruments (using engines like FM, waveform synthesis, virtual analog, sample playback, and MIDI output).
+It is inspired by the Game Boy tracker [Little Sound DJ](https://www.littlesounddj.com/lsd/index.php).
-While Dirtywave makes new batches of units available on a regular basis, M8 is sometimes sold out due to the high demand of the unit. To fill this gap and to allow users to freely test this wonderful
-tracker, [Timothy Lamb](https://github.com/trash80) was kind enough to make
-the [M8 Headless](https://github.com/Dirtywave/M8HeadlessFirmware) available to everyone.
+m8c works with the official M8 hardware over USB. It also supports the [M8 Headless](https://github.com/Dirtywave/M8HeadlessFirmware)
+firmware running on a [Teensy](https://www.pjrc.com/teensy/) microcontroller. If you enjoy the M8 and its
+tracker workflow, please support [Dirtywave](https://dirtywave.com/) by purchasing the hardware. You can check
+availability [here](https://dirtywave.com/products/m8-tracker-model-02). You can also
+support the creator, [Trash80](https://github.com/trash80) via [Patreon](https://www.patreon.com/trash80).
-If you like the M8 and you gel with the tracker workflow, please support [Dirtywave](https://dirtywave.com/) by
-purchasing the actual unit. You can check its availability [here](https://dirtywave.com/products/m8-tracker-model-02).
-Meanwhile, you can also subscribe to Timothy Lamb's [Patreon](https://www.patreon.com/trash80).
-
Many thanks to:
-* Trash80: For the great M8 hardware and the original fonts that were converted to a bitmap for use in the
- program.
-* driedfruit: For a wonderful little routine to blit inline bitmap
- fonts, [SDL_inprint](https://github.com/driedfruit/SDL_inprint/)
+* Trash80: For the great M8 hardware and the original fonts that were converted to a bitmap for use in the program.
+* driedfruit: For a wonderful little routine to blit inline bitmap fonts, [SDL_inprint](https://github.com/driedfruit/SDL_inprint/)
* marcinbor85: For the slip handling routine, https://github.com/marcinbor85/slip
* turbolent: For the great Golang-based g0m8 application, which I used as reference on how the M8 serial protocol works.
* *Everyone who's contributed to m8c!*
-Disclaimer: I'm not a coder and hardly understand C, use at your own risk :)
-
-------
## Installation
@@ -44,11 +39,13 @@
There are prebuilt binaries available in the [releases section](https://github.com/laamaa/m8c/releases/) for Windows.
-When running the program for the first time on Windows, Windows Defender may show a warning about an unrecognized app. Click "More info" and then "Run anyway" to proceed.
+When running the program for the first time on Windows, Windows Defender may show a warning about an unrecognized app.
+Click "More info" and then "Run anyway" to proceed.
### macOS
-There are prebuilt binaries available in the [releases section](https://github.com/laamaa/m8c/releases/) for recent versions of macOS.
+There are prebuilt binaries available in the [releases section](https://github.com/laamaa/m8c/releases/) for recent
+versions of macOS.
When running the program for the first time on macOS, it may not open as it is from an Unidentified Developer. You need
to open it from the Applications Folder via Control+Click > Open then select Open from the popup menu.
@@ -148,6 +145,7 @@
```
Example output:
+
```
2024-02-25 18:39:27.806 m8c[99838:4295527] INFO: Found M8 device: /dev/cu.usbmodem124709801
2024-02-25 18:39:27.807 m8c[99838:4295527] INFO: Found M8 device: /dev/cu.usbmodem121136001
@@ -237,14 +235,15 @@
You can change the most common options without editing `config.ini` using the in-app settings overlay.
- **How to open:**
- - Keyboard: press F1.
- - Gamepad: hold the Back/Select button for about 2 seconds.
+ - Keyboard: press F1.
+ - Gamepad: hold the Back/Select button for about 2 seconds.
- **How to navigate:**
- - Move: Up/Down arrows or D‑pad.
- - Activate/enter: Enter/Space or South/A.
- - Adjust values (sliders/integers): Left/Right arrows or D‑pad left/right.
- - Back/close: Esc or F1; on gamepad use East/B or Back.
- - While remapping inputs, the menu will prompt you; press the desired key/button or move an axis. Use Esc/B/Back to cancel a capture.
+ - Move: Up/Down arrows or D‑pad.
+ - Activate/enter: Enter/Space or South/A.
+ - Adjust values (sliders/integers): Left/Right arrows or D‑pad left/right.
+ - Back/close: Esc or F1; on gamepad use East/B or Back.
+ - While remapping inputs, the menu will prompt you; press the desired key/button or move an axis. Use Esc/B/Back to
+ cancel a capture.
Changes take effect immediately; use Save if you want them persisted to disk.
@@ -320,14 +319,14 @@
### Device Not Found
* The program starts but shows "No M8 device found":
- - Ensure your M8 or Teensy is connected via USB
- - Check that the headless firmware is properly installed
- - Try running with `--list` to see detected devices
- - On Linux, verify USB permissions (see permission issues above)
+ - Ensure your M8 or Teensy is connected via USB
+ - If using a Teensy, check that the headless firmware is properly installed
+ - Try running with `--list` to see detected devices
+ - On Linux, verify USB permissions (see permission issues above)
### Audio Issues
* No audio output:
- - Check that audio routing is enabled (F12)
- - Verify audio device selection in config
- - On macOS, ensure microphone permission is granted
+ - Check that audio routing is enabled (F12)
+ - Verify audio device selection in config
+ - On macOS, ensure microphone permission is granted
--- a/src/config.c
+++ b/src/config.c
@@ -54,6 +54,7 @@
c.key_jazz_inc_velocity = SDL_SCANCODE_KP_PLUS;
c.key_jazz_dec_velocity = SDL_SCANCODE_KP_MINUS;
c.key_toggle_audio = SDL_SCANCODE_F12;
+ c.key_toggle_settings = SDL_SCANCODE_F1;
c.key_toggle_log = SDL_SCANCODE_F2;
c.gamepad_up = SDL_GAMEPAD_BUTTON_DPAD_UP;
@@ -89,7 +90,7 @@
SDL_Log("Writing config file to %s", config_path);-#define INI_LINE_COUNT 49
+#define INI_LINE_COUNT 50
#define INI_LINE_LENGTH 50
// Entries for the config file
@@ -135,6 +136,7 @@
conf->key_jazz_dec_velocity);
snprintf(ini_values[initPointer++], INI_LINE_LENGTH, "key_toggle_audio=%d\n",
conf->key_toggle_audio);
+ snprintf(ini_values[initPointer++], INI_LINE_LENGTH, "key_toggle_settings=%d\n", conf->key_toggle_settings);
snprintf(ini_values[initPointer++], INI_LINE_LENGTH, "key_toggle_log=%d\n", conf->key_toggle_log);
snprintf(ini_values[initPointer++], INI_LINE_LENGTH, "[gamepad]\n");
snprintf(ini_values[initPointer++], INI_LINE_LENGTH, "gamepad_up=%d\n", conf->gamepad_up);
@@ -273,6 +275,7 @@
const char *key_jazz_inc_velocity = ini_get(ini, "keyboard", "key_jazz_inc_velocity");
const char *key_jazz_dec_velocity = ini_get(ini, "keyboard", "key_jazz_dec_velocity");
const char *key_toggle_audio = ini_get(ini, "keyboard", "key_toggle_audio");
+ const char *key_toggle_settings = ini_get(ini, "keyboard", "key_toggle_settings");
const char *key_toggle_log = ini_get(ini, "keyboard", "key_toggle_log");
if (key_up)
@@ -313,6 +316,8 @@
conf->key_jazz_dec_velocity = SDL_atoi(key_jazz_dec_velocity);
if (key_toggle_audio)
conf->key_toggle_audio = SDL_atoi(key_toggle_audio);
+ if (key_toggle_settings)
+ conf->key_toggle_log = SDL_atoi(key_toggle_settings);
if (key_toggle_log)
conf->key_toggle_log = SDL_atoi(key_toggle_log);
}
--- a/src/config.h
+++ b/src/config.h
@@ -34,6 +34,7 @@
unsigned int key_jazz_inc_velocity;
unsigned int key_jazz_dec_velocity;
unsigned int key_toggle_audio;
+ unsigned int key_toggle_settings;
unsigned int key_toggle_log;
int gamepad_up;
--- a/src/events.c
+++ b/src/events.c
@@ -61,7 +61,7 @@
case SDL_EVENT_KEY_DOWN:
// Toggle settings with F1
- if (event->key.key == SDLK_F1 && event->key.repeat == 0) {+ if (event->key.scancode == ctx->conf.key_toggle_settings && event->key.repeat == 0) {settings_toggle_open();
return ret_val;
}
--- a/src/settings.c
+++ b/src/settings.c
@@ -107,26 +107,27 @@
break;
case VIEW_KEYS:
add_item(items, count, "Keyboard bindings", ITEM_HEADER, NULL, 0, 0, 0);
- add_item(items, count, "Up ", ITEM_BIND_KEY, (void *)&conf->key_up, 0, 0, 0);
- add_item(items, count, "Left ", ITEM_BIND_KEY, (void *)&conf->key_left, 0, 0, 0);
- add_item(items, count, "Down ", ITEM_BIND_KEY, (void *)&conf->key_down, 0, 0, 0);
- add_item(items, count, "Right ", ITEM_BIND_KEY, (void *)&conf->key_right, 0, 0, 0);
- add_item(items, count, "Select ", ITEM_BIND_KEY, (void *)&conf->key_select, 0, 0, 0);
- add_item(items, count, "Select (Alt)", ITEM_BIND_KEY, (void *)&conf->key_select_alt, 0, 0, 0);
- add_item(items, count, "Start ", ITEM_BIND_KEY, (void *)&conf->key_start, 0, 0, 0);
- add_item(items, count, "Start (Alt) ", ITEM_BIND_KEY, (void *)&conf->key_start_alt, 0, 0, 0);
- add_item(items, count, "Opt ", ITEM_BIND_KEY, (void *)&conf->key_opt, 0, 0, 0);
- add_item(items, count, "Opt (Alt) ", ITEM_BIND_KEY, (void *)&conf->key_opt_alt, 0, 0, 0);
- add_item(items, count, "Edit ", ITEM_BIND_KEY, (void *)&conf->key_edit, 0, 0, 0);
- add_item(items, count, "Edit (Alt) ", ITEM_BIND_KEY, (void *)&conf->key_edit_alt, 0, 0, 0);
- add_item(items, count, "Delete ", ITEM_BIND_KEY, (void *)&conf->key_delete, 0, 0, 0);
- add_item(items, count, "Reset ", ITEM_BIND_KEY, (void *)&conf->key_reset, 0, 0, 0);
- add_item(items, count, "Jazz +Oct ", ITEM_BIND_KEY, (void *)&conf->key_jazz_inc_octave, 0, 0, 0);
- add_item(items, count, "Jazz -Oct ", ITEM_BIND_KEY, (void *)&conf->key_jazz_dec_octave, 0, 0, 0);
- add_item(items, count, "Jazz +Vel ", ITEM_BIND_KEY, (void *)&conf->key_jazz_inc_velocity, 0, 0, 0);
- add_item(items, count, "Jazz -Vel ", ITEM_BIND_KEY, (void *)&conf->key_jazz_dec_velocity, 0, 0, 0);
- add_item(items, count, "Toggle audio", ITEM_BIND_KEY, (void *)&conf->key_toggle_audio, 0, 0, 0);
- add_item(items, count, "Toggle log ", ITEM_BIND_KEY, (void *)&conf->key_toggle_log, 0, 0, 0);
+ add_item(items, count, "Up ", ITEM_BIND_KEY, (void *)&conf->key_up, 0, 0, 0);
+ add_item(items, count, "Left ", ITEM_BIND_KEY, (void *)&conf->key_left, 0, 0, 0);
+ add_item(items, count, "Down ", ITEM_BIND_KEY, (void *)&conf->key_down, 0, 0, 0);
+ add_item(items, count, "Right ", ITEM_BIND_KEY, (void *)&conf->key_right, 0, 0, 0);
+ add_item(items, count, "Select ", ITEM_BIND_KEY, (void *)&conf->key_select, 0, 0, 0);
+ add_item(items, count, "Select (Alt) ", ITEM_BIND_KEY, (void *)&conf->key_select_alt, 0, 0, 0);
+ add_item(items, count, "Start ", ITEM_BIND_KEY, (void *)&conf->key_start, 0, 0, 0);
+ add_item(items, count, "Start (Alt) ", ITEM_BIND_KEY, (void *)&conf->key_start_alt, 0, 0, 0);
+ add_item(items, count, "Opt ", ITEM_BIND_KEY, (void *)&conf->key_opt, 0, 0, 0);
+ add_item(items, count, "Opt (Alt) ", ITEM_BIND_KEY, (void *)&conf->key_opt_alt, 0, 0, 0);
+ add_item(items, count, "Edit ", ITEM_BIND_KEY, (void *)&conf->key_edit, 0, 0, 0);
+ add_item(items, count, "Edit (Alt) ", ITEM_BIND_KEY, (void *)&conf->key_edit_alt, 0, 0, 0);
+ add_item(items, count, "Delete ", ITEM_BIND_KEY, (void *)&conf->key_delete, 0, 0, 0);
+ add_item(items, count, "Reset ", ITEM_BIND_KEY, (void *)&conf->key_reset, 0, 0, 0);
+ add_item(items, count, "Jazz +Oct ", ITEM_BIND_KEY, (void *)&conf->key_jazz_inc_octave, 0, 0, 0);
+ add_item(items, count, "Jazz -Oct ", ITEM_BIND_KEY, (void *)&conf->key_jazz_dec_octave, 0, 0, 0);
+ add_item(items, count, "Jazz +Vel ", ITEM_BIND_KEY, (void *)&conf->key_jazz_inc_velocity, 0, 0, 0);
+ add_item(items, count, "Jazz -Vel ", ITEM_BIND_KEY, (void *)&conf->key_jazz_dec_velocity, 0, 0, 0);
+ add_item(items, count, "Toggle audio ", ITEM_BIND_KEY, (void *)&conf->key_toggle_audio, 0, 0, 0);
+ add_item(items, count, "Toggle settings", ITEM_BIND_KEY, (void *)&conf->key_toggle_settings, 0, 0, 0);
+ add_item(items, count, "Toggle log ", ITEM_BIND_KEY, (void *)&conf->key_toggle_log, 0, 0, 0);
add_item(items, count, "", ITEM_HEADER, NULL, 0, 0, 0);
add_item(items, count, "Back", ITEM_CLOSE, NULL, 0, 0, 0);
break;
--
⑨