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
--
⑨