shithub: m8c

Download patch

ref: 163ee603b7133ba61fc5e989189c58b163feb87f
parent: 6e40acac61543546ff0bab95dc7389fcf5b2f3b1
author: Jonne Kokkonen <jonne.kokkonen@gmail.com>
date: Mon Mar 17 14:30:33 EDT 2025

add a message queue system

--- a/Makefile
+++ b/Makefile
@@ -1,8 +1,8 @@
 #Set all your object files (the object files of all the .c files in your project, e.g. main.o my_sub_functions.o )
-OBJ = src/main.o src/serial.o src/slip.o src/command.o src/render.o src/ini.o src/config.o src/input.o src/gamecontrollers.o src/fx_cube.o src/usb.o src/audio.o src/usb_audio.o src/ringbuffer.o src/inprint2.o src/midi.o
+OBJ = src/main.o src/serial.o src/slip.o src/command.o src/render.o src/ini.o src/config.o src/input.o src/gamecontrollers.o src/fx_cube.o src/usb.o src/audio.o src/usb_audio.o src/ringbuffer.o src/inprint2.o src/midi.o src/queue.o
 
 #Set any dependant header files so that if they are edited they cause a complete re-compile (e.g. main.h some_subfunctions.h some_definitions_file.h ), or leave blank
-DEPS = src/serial.h src/slip.h src/command.h src/render.h src/ini.h src/config.h src/input.h src/gamecontrollers.h src/fx_cube.h src/audio.h src/ringbuffer.h src/inline_font.h src/midi.h
+DEPS = src/serial.h src/slip.h src/command.h src/render.h src/ini.h src/config.h src/input.h src/gamecontrollers.h src/fx_cube.h src/audio.h src/ringbuffer.h src/inline_font.h src/midi.h src/queue.h
 
 #Any special libraries you are using in your project (e.g. -lbcm2835 -lrt `pkg-config --libs gtk+-3.0` ), or leave blank
 INCLUDES = $(shell pkg-config --libs sdl3 libserialport | sed 's/-mwindows//')
--- a/src/command.c
+++ b/src/command.c
@@ -1,7 +1,7 @@
 // Copyright 2021 Jonne Kokkonen
 // Released under the MIT licence, https://opensource.org/licenses/MIT
 
-#include <SDL3/SDL_log.h>
+#include <SDL3/SDL.h>
 
 #include "command.h"
 #include "render.h"
--- a/src/midi.c
+++ b/src/midi.c
@@ -5,6 +5,7 @@
 #include "midi.h"
 #include "command.h"
 #include "config.h"
+#include "queue.h"
 #include <SDL3/SDL.h>
 #include <rtmidi_c.h>
 #include <stdbool.h>
@@ -13,6 +14,7 @@
 
 RtMidiInPtr midi_in;
 RtMidiOutPtr midi_out;
+message_queue_s queue;
 
 const unsigned char m8_sysex_header[4] = {0xF0, 0x00, 0x02, 0x61};
 const unsigned int m8_sysex_header_size = sizeof(m8_sysex_header);
@@ -38,7 +40,7 @@
   size_t pos = m8_sysex_header_size + 1;
 
   // Calculate expected output size (ignoring EOT if present)
-  size_t expected_output_size =
+  const size_t expected_output_size =
       (length - m8_sysex_header_size) - ((length - m8_sysex_header_size) / 8);
   if (encoded_data[length - 1] == sysex_message_end) {
     length--; // Ignore the EOT byte
@@ -84,7 +86,7 @@
   if (message_size < 5 || !message_is_m8_sysex(message))
     return;
 
-  uint8_t *decoded_data;
+  unsigned char *decoded_data;
   size_t decoded_length;
   midi_decode(message, message_size, &decoded_data, &decoded_length);
 
@@ -99,7 +101,7 @@
       // printf("%02X ", decoded_data[i]);
     }
     // printf("\n");
-    process_command(decoded_data, decoded_length);
+    push_message(&queue, decoded_data, decoded_length);
     SDL_free(decoded_data);
   } else {
     printf("Decoding failed.\n");
@@ -116,8 +118,10 @@
   return 1;
 }
 
-int init_serial(int verbose, const char *preferred_device) {
+int init_serial(const int verbose, const char *preferred_device) {
 
+  init_queue(&queue);
+
   int midi_in_initialized = 0;
   int midi_out_initialized = 0;
 
@@ -125,7 +129,7 @@
   if (midi_in == NULL || midi_out == NULL) {
     initialize_rtmidi();
   };
-  unsigned int ports_total_in = rtmidi_get_port_count(midi_in);
+  const unsigned int ports_total_in = rtmidi_get_port_count(midi_in);
   if (verbose)
     SDL_Log("Number of MIDI in ports: %d", ports_total_in);
   for (unsigned int port_number = 0; port_number < ports_total_in; port_number++) {
@@ -138,7 +142,6 @@
     if (strncmp("M8", port_name, 2) == 0) {
       if (verbose)
         SDL_Log("Found M8 Input in MIDI port %d", port_number);
-
       rtmidi_in_ignore_types(midi_in, false, true, true);
       rtmidi_open_port(midi_in, port_number, "M8");
       midi_in_initialized = 1;
@@ -157,7 +160,7 @@
 int reset_display(void) {
   SDL_Log("Reset display\n");
   const unsigned char reset_sysex[8] = {0xF0, 0x00, 0x02, 0x61, 0x00, 0x00, 'R', 0xF7};
-  int result = rtmidi_out_send_message(midi_out, &reset_sysex[0], sizeof(reset_sysex));
+  const int result = rtmidi_out_send_message(midi_out, &reset_sysex[0], sizeof(reset_sysex));
   if (result != 0) {
     SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "Error resetting M8 display, code %d", result);
     return 0;
@@ -166,7 +169,7 @@
 }
 
 int enable_and_reset_display(void) {
-  //rtmidi_in_set_callback(midi_in, midi_callback, NULL);
+  rtmidi_in_set_callback(midi_in, midi_callback, NULL);
   const unsigned char enable_sysex[8] = {0xF0, 0x00, 0x02, 0x61, 0x00, 0x00, 'E', 0xF7};
   int result = rtmidi_out_send_message(midi_out, &enable_sysex[0], sizeof(enable_sysex));
   if (result != 0) {
@@ -179,7 +182,8 @@
 
 int disconnect(void) {
   const unsigned char disconnect_sysex[8] = {0xF0, 0x00, 0x02, 0x61, 0x00, 0x00, 'D', 0xF7};
-  int result = rtmidi_out_send_message(midi_out, &disconnect_sysex[0], sizeof(disconnect_sysex));
+  const int result =
+      rtmidi_out_send_message(midi_out, &disconnect_sysex[0], sizeof(disconnect_sysex));
   if (result != 0) {
     SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "Failed to send disconnect");
   }
@@ -191,7 +195,7 @@
 
 int send_msg_controller(const unsigned char input) {
   const unsigned char input_sysex[9] = {0xF0, 0x00, 0x02, 0x61, 0x00, 0x00, 'C', input, 0xF7};
-  int result = rtmidi_out_send_message(midi_out, &input_sysex[0], sizeof(input_sysex));
+  const int result = rtmidi_out_send_message(midi_out, &input_sysex[0], sizeof(input_sysex));
   if (result != 0) {
     SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "Failed to send key input message");
     return 0;
@@ -205,7 +209,7 @@
   }
   const unsigned char keyjazz_sysex[10] = {0xF0, 0x00, 0x02, 0x61,     0x00,
                                            0x00, 'K',  note, velocity, 0xF7};
-  int result = rtmidi_out_send_message(midi_out, &keyjazz_sysex[0], sizeof(keyjazz_sysex));
+  const int result = rtmidi_out_send_message(midi_out, &keyjazz_sysex[0], sizeof(keyjazz_sysex));
   if (result != 0) {
     SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "Failed to send keyjazz input message");
     return 0;
@@ -214,36 +218,21 @@
 }
 
 int process_serial(config_params_s conf) {
-  unsigned char midi_message[1024];
-  size_t midi_message_size = 1024;
-  while (rtmidi_in_get_message(midi_in,midi_message,&midi_message_size)) {
-    if (midi_message_size < 5 || !message_is_m8_sysex(midi_message))
-      return 1;
-
-    uint8_t *decoded_data;
-    size_t decoded_length;
-    midi_decode(midi_message, midi_message_size, &decoded_data, &decoded_length);
-
-    // printf("Original data: ");
-    for (size_t i = 0; i < midi_message_size; i++) {
-      // printf("%02X ", message[i]);
-    }
-
-    if (decoded_data) {
-      // printf("\nDecoded MIDI Data: ");
-      for (size_t i = 0; i < decoded_length; i++) {
-        // printf("%02X ", decoded_data[i]);
-      }
-      // printf("\n");
-      process_command(decoded_data, decoded_length);
-      SDL_free(decoded_data);
-    }
-    printf("Decoding failed.\n");
-    return 0;
+  unsigned char *command;
+  size_t length = 0;
+  while ((command = pop_message(&queue, &length)) != NULL) {
+    process_command(command, length);
   }
   return 1;
 }
 
-int destroy_serial() { return disconnect(); }
+int destroy_serial() {
+  if (queue.mutex != NULL) {
+    SDL_LogDebug(SDL_LOG_CATEGORY_SYSTEM, "Destroying command queue");
+    SDL_DestroyMutex(queue.mutex);
+    SDL_DestroyCondition(queue.cond);
+  }
+  return disconnect();
+}
 
 #endif
\ No newline at end of file
--- /dev/null
+++ b/src/queue.c
@@ -1,0 +1,55 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <SDL3/SDL.h>
+#include "queue.h"
+
+// Initialize the message queue
+void init_queue(message_queue_s *queue) {
+    queue->front = 0;
+    queue->rear = 0;
+    queue->mutex = SDL_CreateMutex();
+    queue->cond = SDL_CreateCondition();
+}
+
+void destroy_queue(message_queue_s *queue) {
+  SDL_DestroyMutex(queue->mutex);
+  SDL_DestroyCondition(queue->cond);
+}
+
+// Push a message to the queue
+void push_message(message_queue_s *queue, const unsigned char *message, size_t length) {
+    SDL_LockMutex(queue->mutex);
+
+    if ((queue->rear + 1) % MAX_QUEUE_SIZE == queue->front) {
+        SDL_LogError(SDL_LOG_CATEGORY_SYSTEM,"Queue is full, cannot add message.");
+    } else {
+        // Allocate space for the message and store it
+        queue->messages[queue->rear] = SDL_malloc(length);
+        memcpy(queue->messages[queue->rear], message, length);
+        queue->lengths[queue->rear] = length;
+        queue->rear = (queue->rear + 1) % MAX_QUEUE_SIZE;
+        SDL_SignalCondition(queue->cond);  // Signal consumer thread
+    }
+
+    SDL_UnlockMutex(queue->mutex);
+}
+
+// Pop a message from the queue
+unsigned char *pop_message(message_queue_s *queue, size_t *length) {
+  SDL_LockMutex(queue->mutex);
+
+  // Check if the queue is empty
+  if (queue->front == queue->rear) {
+    SDL_UnlockMutex(queue->mutex);
+    return NULL;  // Return NULL if there are no messages
+  }
+
+  // Otherwise, retrieve the message and its length
+  *length = queue->lengths[queue->front];
+  unsigned char *message = queue->messages[queue->front];
+  queue->front = (queue->front + 1) % MAX_QUEUE_SIZE;
+
+  SDL_UnlockMutex(queue->mutex);
+  return message;
+}
\ No newline at end of file
--- /dev/null
+++ b/src/queue.h
@@ -1,0 +1,26 @@
+//
+// Created by jonne on 3/17/25.
+//
+
+#ifndef QUEUE_H
+#define QUEUE_H
+
+#include <SDL3/SDL.h>
+
+#define MAX_QUEUE_SIZE 4096
+
+typedef struct {
+  unsigned char *messages[MAX_QUEUE_SIZE];
+  size_t lengths[MAX_QUEUE_SIZE]; // Store lengths of each message
+  int front;
+  int rear;
+  SDL_Mutex *mutex;
+  SDL_Condition *cond;
+} message_queue_s;
+
+// Initialize the message queue
+void init_queue(message_queue_s *queue);
+unsigned char *pop_message(message_queue_s *queue, size_t *length);
+void push_message(message_queue_s *queue, const unsigned char *message, size_t length);
+
+#endif // QUEUE_H
--