shithub: m8c

Download patch

ref: 77d211a56fd2689b5927e1aaa9f316d2d7848f4c
parent: ade0037a6fcb50567e156bf59cdbfb28543de39f
author: Jonne Kokkonen <jonne.kokkonen@gmail.com>
date: Mon Mar 17 08:19:50 EDT 2025

refactor serial stuff outside main

--- a/.github/workflows/build-ubuntu.yml
+++ b/.github/workflows/build-ubuntu.yml
@@ -30,7 +30,7 @@
         id: cache-x86_64-sdl3-files
         uses: actions/cache@v4
         with:
-          path: 'SDL3-${{ env.SDL_VERSION }}'
+          path: 'SDL3-3.2.8'
           key: linux-x86_64-sdl3-files
 
       - name: 'Download SDL3 sources'
--- a/.github/workflows/build-windows.yml
+++ b/.github/workflows/build-windows.yml
@@ -43,7 +43,7 @@
       id: cache-sdl3-files
       uses: actions/cache@v4
       with:
-        path: 'SDL3-3.2.4'
+        path: 'SDL3-3.2.8'
         key: win-sdl3-files-${{ matrix.sys }}
 
     - name: 'Download SDL3 sources'
--- a/Makefile
+++ b/Makefile
@@ -8,7 +8,9 @@
 INCLUDES = $(shell pkg-config --libs sdl3 libserialport | sed 's/-mwindows//')
 
 #Set any compiler flags you want to use (e.g. -I/usr/include/somefolder `pkg-config --cflags gtk+-3.0` ), or leave blank
-local_CFLAGS = $(CFLAGS) $(shell pkg-config --cflags sdl3 libserialport) -Wall -Wextra -O2 -pipe -I.
+local_CFLAGS = $(CFLAGS) $(shell pkg-config --cflags sdl3 libserialport) -DUSE_LIBSERIALPORT -Wall -Wextra -O2 -pipe -I.
+# local_CFLAGS = $(CFLAGS) $(shell pkg-config --cflags sdl3 libserialport) -DUSE_RTMIDI -Wall -Wextra -O2 -pipe -I.
+
 
 #Set the compiler you are using ( gcc for C or g++ for C++ )
 CC = gcc
--- a/src/main.c
+++ b/src/main.c
@@ -24,10 +24,57 @@
 uint8_t need_display_reset = 0;
 
 // Handles CTRL+C / SIGINT
-void intHandler() { run = QUIT; }
+void signal_handler() { run = QUIT; }
 
-void close_serial_port() { disconnect(); }
+int process_inputs(config_params_s conf) {
+  static uint8_t prev_input = 0;
+  static uint8_t prev_note = 0;
 
+  // get current inputs
+  const input_msg_s input = get_input_msg(&conf);
+
+  switch (input.type) {
+  case normal:
+    if (input.value != prev_input) {
+      prev_input = input.value;
+      send_msg_controller(input.value);
+    }
+    break;
+  case keyjazz:
+    if (input.value != 0) {
+      if (input.eventType == SDL_EVENT_KEY_DOWN && input.value != prev_input) {
+        send_msg_keyjazz(input.value, input.value2);
+        prev_note = input.value;
+      } else if (input.eventType == SDL_EVENT_KEY_UP && input.value == prev_note) {
+        send_msg_keyjazz(0xFF, 0);
+      }
+    }
+    prev_input = input.value;
+    break;
+  case special:
+    if (input.value != prev_input) {
+      prev_input = input.value;
+      switch (input.value) {
+      case msg_quit:
+        SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "Received msg_quit from input device.");
+        run = 0;
+        break;
+      case msg_reset_display:
+        reset_display();
+        break;
+      case msg_toggle_audio:
+        conf.audio_enabled = !conf.audio_enabled;
+        toggle_audio(conf.audio_device_name, conf.audio_buffer_size);
+        break;
+      default:
+        break;
+      }
+      break;
+    }
+  }
+  return 1;
+}
+
 int main(const int argc, char *argv[]) {
 
   if (argc == 2 && SDL_strcmp(argv[1], "--list") == 0) {
@@ -35,10 +82,12 @@
   }
 
   char *preferred_device = NULL;
+#ifdef USE_LIBSERIALPORT // Device selection should be only available with libserialport
   if (argc == 3 && SDL_strcmp(argv[1], "--dev") == 0) {
     preferred_device = argv[2];
     SDL_Log("Using preferred device %s.\n", preferred_device);
   }
+#endif
 
   char *config_filename = NULL;
   if (argc == 3 && SDL_strcmp(argv[1], "--config") == 0) {
@@ -51,33 +100,13 @@
   config_params_s conf = init_config(config_filename);
   read_config(&conf);
 
-  // allocate memory for serial buffer
-  uint8_t *serial_buf = SDL_malloc(serial_read_size);
-
-  static uint8_t slip_buffer[serial_read_size]; // SLIP command buffer
-  SDL_zero(slip_buffer);
-
-  // settings for the slip packet handler
-  static const slip_descriptor_s slip_descriptor = {
-      .buf = slip_buffer,
-      .buf_size = sizeof(slip_buffer),
-      .recv_message = process_command, // the function where complete slip
-                                       // packets are processed further
-  };
-
-  static slip_handler_s slip;
-
-  uint8_t prev_input = 0;
-  uint8_t prev_note = 0;
-  uint16_t zerobyte_packets = 0; // used to detect device disconnection
   uint8_t port_inited = 0;
 
-  signal(SIGINT, intHandler);
-  signal(SIGTERM, intHandler);
+  signal(SIGINT, signal_handler);
+  signal(SIGTERM, signal_handler);
 #ifdef SIGQUIT
-  signal(SIGQUIT, intHandler);
+  signal(SIGQUIT, signal_handler);
 #endif
-  slip_init(&slip, &slip_descriptor);
 
   // First device detection to avoid SDL init if it isn't necessary. To be run
   // only if we shouldn't wait for M8 to be connected.
@@ -84,7 +113,6 @@
   if (conf.wait_for_device == 0) {
     port_inited = init_serial(1, preferred_device);
     if (port_inited == 0) {
-      SDL_free(serial_buf);
       return 1;
     }
   }
@@ -91,7 +119,6 @@
 
   // initialize all SDL systems
   if (initialize_sdl(conf.init_fullscreen) == false) {
-    SDL_free(serial_buf);
     SDL_Quit();
     return 1;
   }
@@ -139,7 +166,7 @@
         // get current input
         const input_msg_s input = get_input_msg(&conf);
         if (input.type == special && input.value == msg_quit) {
-          SDL_LogCritical(SDL_LOG_CATEGORY_ERROR, "Input message QUIT.");
+          SDL_LogDebug(SDL_LOG_CATEGORY_SYSTEM, "Input message QUIT.");
           run = QUIT;
         }
 
@@ -185,7 +212,6 @@
         gamecontrollers_close();
         close_renderer();
         kill_inline_font();
-        SDL_free(serial_buf);
         SDL_Quit();
         return -1;
       }
@@ -193,99 +219,16 @@
 
     // main loop
     while (run == RUN) {
+      process_inputs(conf);
 
-      // get current inputs
-      const input_msg_s input = get_input_msg(&conf);
-
-      switch (input.type) {
-      case normal:
-        if (input.value != prev_input) {
-          prev_input = input.value;
-          send_msg_controller(input.value);
-        }
-        break;
-      case keyjazz:
-        if (input.value != 0) {
-          if (input.eventType == SDL_EVENT_KEY_DOWN && input.value != prev_input) {
-            send_msg_keyjazz(input.value, input.value2);
-            prev_note = input.value;
-          } else if (input.eventType == SDL_EVENT_KEY_UP && input.value == prev_note) {
-            send_msg_keyjazz(0xFF, 0);
-          }
-        }
-        prev_input = input.value;
-        break;
-      case special:
-        if (input.value != prev_input) {
-          prev_input = input.value;
-          switch (input.value) {
-          case msg_quit:
-            SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "Received msg_quit from input device.");
-            run = 0;
-            break;
-          case msg_reset_display:
-            reset_display();
-            break;
-          case msg_toggle_audio:
-            conf.audio_enabled = !conf.audio_enabled;
-            toggle_audio(conf.audio_device_name,conf.audio_buffer_size);
-            break;
-          default:
-            break;
-          }
-          break;
-        }
+      const int result = process_serial(conf);
+      if (result == 0) {
+        port_inited = 0;
+        run = WAIT_FOR_DEVICE;
+        audio_destroy();
+      } else if (result == -1) {
+        run = QUIT;
       }
-
-      while (1) {
-        // read serial port
-        const int bytes_read = serial_read(serial_buf, serial_read_size);
-        if (bytes_read < 0) {
-          SDL_LogCritical(SDL_LOG_CATEGORY_ERROR, "Error %d reading serial.", bytes_read);
-          run = QUIT;
-          break;
-        }
-        if (bytes_read > 0) {
-          // input from device: reset the zero byte counter and create a
-          // pointer to the serial buffer
-          zerobyte_packets = 0;
-          const uint8_t *cur = serial_buf;
-          const uint8_t *end = serial_buf + bytes_read;
-          while (cur < end) {
-            // process the incoming bytes into commands and draw them
-            const int n = slip_read_byte(&slip, *cur++);
-            if (n != SLIP_NO_ERROR) {
-              if (n == SLIP_ERROR_INVALID_PACKET) {
-                reset_display();
-              } else {
-                SDL_LogError(SDL_LOG_CATEGORY_ERROR, "SLIP error %d\n", n);
-              }
-            }
-          }
-        } else {
-          // zero byte packet, increment counter
-          zerobyte_packets++;
-          if (zerobyte_packets > conf.wait_packets) {
-            zerobyte_packets = 0;
-
-            // try opening the serial port to check if it's alive
-            if (check_serial_port()) {
-              // the device is still there, carry on
-              break;
-            }
-            port_inited = 0;
-            run = WAIT_FOR_DEVICE;
-            close_serial_port();
-            if (conf.audio_enabled == 1) {
-              audio_destroy();
-            }
-            /* we'll make one more loop to see if the device is still there
-             * but just sending zero bytes. if it doesn't get detected when
-             * resetting the port, it will disconnect */
-          }
-          break;
-        }
-      }
       render_screen();
       SDL_Delay(conf.idle_ms);
     }
@@ -294,14 +237,11 @@
 
   // exit, clean up
   SDL_Log("Shutting down");
-  if (conf.audio_enabled == 1) {
-    audio_destroy();
-  }
+  audio_destroy();
   gamecontrollers_close();
   close_renderer();
   if (port_inited == 1)
-    close_serial_port();
-  SDL_free(serial_buf);
+    destroy_serial();
   SDL_Quit();
   return 0;
 }
--- a/src/serial.c
+++ b/src/serial.c
@@ -4,7 +4,7 @@
 // Contains portions of code from libserialport's examples released to the
 // public domain
 
-#ifndef USE_LIBUSB
+#ifdef USE_LIBSERIALPORT
 #include <SDL3/SDL.h>
 #include <libserialport.h>
 #include <stdio.h>
@@ -12,9 +12,17 @@
 #include <string.h>
 #include <unistd.h>
 
+#include "command.h"
 #include "serial.h"
+#include "slip.h"
+#include "config.h"
 
 struct sp_port *m8_port = NULL;
+// allocate memory for serial buffers
+static uint8_t serial_buffer[serial_read_size] = {0};
+static uint8_t slip_buffer[serial_read_size] = {0};
+static slip_handler_s slip;
+static uint16_t zero_byte_packets = 0; // used to detect device disconnection
 
 // Helper function for error handling
 static int check(enum sp_return result);
@@ -94,6 +102,17 @@
     // Port is already initialized
     return 1;
   }
+
+  // settings for the slip packet handler
+  static const slip_descriptor_s slip_descriptor = {
+      .buf = slip_buffer,
+      .buf_size = sizeof(slip_buffer),
+      .recv_message = process_command, // the function where complete slip
+                                       // packets are processed further
+  };
+
+  slip_init(&slip, &slip_descriptor);
+
   /* A pointer to a null-terminated array of pointers to
    * struct sp_port, which will contain the ports found.*/
   struct sp_port **port_list;
@@ -264,5 +283,56 @@
   }
 
   return 1;
+}
+
+int process_serial(config_params_s conf) {
+  while (1) {
+    // read serial port
+    const int bytes_read = serial_read(serial_buffer, serial_read_size);
+    if (bytes_read < 0) {
+      SDL_LogCritical(SDL_LOG_CATEGORY_ERROR, "Error %d reading serial.", bytes_read);
+      disconnect();
+      return -1;
+      break;
+    }
+    if (bytes_read > 0) {
+      // input from device: reset the zero byte counter and create a
+      // pointer to the serial buffer
+      zero_byte_packets = 0;
+      const uint8_t *cur = serial_buffer;
+      const uint8_t *end = serial_buffer + bytes_read;
+      while (cur < end) {
+        // process the incoming bytes into commands and draw them
+        const int n = slip_read_byte(&slip, *cur++);
+        if (n != SLIP_NO_ERROR) {
+          if (n == SLIP_ERROR_INVALID_PACKET) {
+            reset_display();
+          } else {
+            SDL_LogError(SDL_LOG_CATEGORY_ERROR, "SLIP error %d\n", n);
+          }
+        }
+      }
+    } else {
+      // zero byte packet, increment counter
+      zero_byte_packets++;
+      if (zero_byte_packets > conf.wait_packets) {
+        zero_byte_packets = 0;
+
+        // try opening the serial port to check if it's alive
+        if (check_serial_port()) {
+          // the device is still there, carry on
+          break;
+        }
+        disconnect();
+        return 0;
+      }
+      break;
+    }
+  }
+  return 1;
+}
+
+int destroy_serial() {
+  return disconnect();
 }
 #endif
--- a/src/serial.h
+++ b/src/serial.h
@@ -3,18 +3,16 @@
 
 #ifndef _SERIAL_H_
 #define _SERIAL_H_
+#ifdef USE_LIBSERIALPORT
+
 #include <stdint.h>
+#include "config.h"
 
-#ifdef USE_LIBUSB
-// Max packet length of the USB endpoint
-#define serial_read_size 1024
-int init_serial_with_file_descriptor(int file_descriptor);
-#else
 // maximum amount of bytes to read from the serial in one read()
 #define serial_read_size 1024
-#endif
 
 int init_serial(int verbose, const char *preferred_device);
+int destroy_serial();
 int list_devices();
 int check_serial_port();
 int reset_display();
@@ -23,5 +21,7 @@
 int serial_read(uint8_t *serial_buf, int count);
 int send_msg_controller(uint8_t input);
 int send_msg_keyjazz(uint8_t note, uint8_t velocity);
+int process_serial(config_params_s conf);
 
+#endif
 #endif
--- a/src/usb.h
+++ b/src/usb.h
@@ -4,6 +4,6 @@
 
 #include <libusb.h>
 extern libusb_device_handle *devh;
-
+int init_serial_with_file_descriptor(int file_descriptor);
 #endif // USE_LIBUSB
 #endif // M8C_USB_H_
--