ref: dc9503f082e21098218c2657a3a15c32c2d39b76
parent: a701f7c3847a0226d30623a5c54033f58715bae1
author: Jonne Kokkonen <jonne.kokkonen@gmail.com>
date: Sun Mar 23 12:33:35 EDT 2025
Refactor MIDI initialization and add queue size handling. Extract MIDI device detection to a dedicated function, improve device disconnection handling, and centralize MIDI port cleanup logic. Extend the queue API with a function to retrieve its size and document all queue functions.
--- a/src/backends/m8_rtmidi.c
+++ b/src/backends/m8_rtmidi.c
@@ -127,15 +127,8 @@
return 1;
}
-int m8_initialize(const int verbose, const char *preferred_device) {-
- int midi_in_initialized = 0;
- int midi_out_initialized = 0;
-
- SDL_LogDebug(SDL_LOG_CATEGORY_SYSTEM, "init_serial called");
- if (midi_in == NULL || midi_out == NULL) {- initialize_rtmidi();
- };
+int detect_m8_midi_device(const int verbose, const char *preferred_device) {+ int m8_midi_port_number = -1;
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);@@ -146,16 +139,10 @@
rtmidi_get_port_name(midi_in, port_number, &port_name[0], &port_name_length_in);
if (verbose)
SDL_LogDebug(SDL_LOG_CATEGORY_SYSTEM, "MIDI IN port %d, name: %s", port_number, port_name);
-
if (SDL_strncmp("M8", port_name, 2) == 0) {+ m8_midi_port_number = port_number;
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;
- rtmidi_open_port(midi_out, port_number, "M8");
- midi_out_initialized = 1;
- init_queue(&queue);
if (preferred_device != NULL && SDL_strcmp(preferred_device, port_name) == 0) { SDL_Log("Found preferred device, breaking");break;
@@ -162,11 +149,25 @@
}
}
}
- return midi_in_initialized && midi_out_initialized;
+ return m8_midi_port_number;
}
-int check_serial_port(void) {- SDL_LogDebug(SDL_LOG_CATEGORY_SYSTEM, "check_serial_port called");
+int m8_initialize(const int verbose, const char *preferred_device) {+
+ int m8_midi_port_number = 0;
+
+ SDL_LogDebug(SDL_LOG_CATEGORY_SYSTEM, "Initialize M8 via RTMIDI called");
+ if (midi_in == NULL || midi_out == NULL) {+ initialize_rtmidi();
+ };
+ m8_midi_port_number = detect_m8_midi_device(verbose, preferred_device);
+ if (m8_midi_port_number >= 0) {+ rtmidi_in_ignore_types(midi_in, false, true, true); // Allow sysex
+ rtmidi_open_port(midi_in, m8_midi_port_number, "M8");
+ rtmidi_open_port(midi_out, m8_midi_port_number, "M8");
+ init_queue(&queue);
+ return 1;
+ }
return 0;
}
@@ -175,7 +176,7 @@
const unsigned char reset_sysex[8] = {0xF0, 0x00, 0x02, 0x61, 0x00, 0x00, 'R', 0xF7};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);
+ SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "Error resetting M8 display, error %s", midi_out->msg);
return 0;
}
return 1;
@@ -193,6 +194,16 @@
return result;
}
+void close_and_free_midi_ports(void) {+ SDL_LogDebug(SDL_LOG_CATEGORY_SYSTEM, "Freeing MIDI ports");
+ rtmidi_close_port(midi_in);
+ rtmidi_close_port(midi_out);
+ rtmidi_in_free(midi_in);
+ rtmidi_out_free(midi_out);
+ midi_in = NULL;
+ midi_out = NULL;
+}
+
int disconnect(void) { const unsigned char disconnect_sysex[8] = {0xF0, 0x00, 0x02, 0x61, 0x00, 0x00, 'D', 0xF7};const int result =
@@ -200,9 +211,7 @@
if (result != 0) {SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "Failed to send disconnect");
}
- SDL_LogDebug(SDL_LOG_CATEGORY_SYSTEM, "Freeing MIDI ports");
- rtmidi_in_free(midi_in);
- rtmidi_out_free(midi_out);
+ close_and_free_midi_ports();
return !result;
}
@@ -231,12 +240,26 @@
}
int m8_process_data(config_params_s conf) {+
(void)conf; // unused parameter
- unsigned char *command;
- size_t length = 0;
- while ((command = pop_message(&queue, &length)) != NULL) {- process_command(command, length);
+ static unsigned int empty_cycles = 0;
+
+ if (queue_size(&queue) > 0) {+ unsigned char *command;
+ empty_cycles = 0;
+ size_t length = 0;
+ while ((command = pop_message(&queue, &length)) != NULL) {+ process_command(command, length);
+ SDL_free(command);
+ }
+ } else {+ empty_cycles++;
+ if (empty_cycles >= conf.wait_packets) {+ SDL_Log("No messages received for %d cycles, assuming device disconnected", empty_cycles);+ close_and_free_midi_ports();
+ return 0;
+ }
}
return 1;
}
@@ -263,8 +286,7 @@
rtmidi_get_port_name(midi_in, port_number, &port_name[0], &port_name_length_in);
SDL_Log("MIDI IN port %d, name: %s", port_number, port_name);}
- rtmidi_in_free(midi_in);
- rtmidi_out_free(midi_out);
+ close_and_free_midi_ports();
return 1;
}
--- a/src/backends/queue.c
+++ b/src/backends/queue.c
@@ -12,7 +12,16 @@
queue->cond = SDL_CreateCondition();
}
+// Free allocated memory and destroy mutex
void destroy_queue(message_queue_s *queue) {+ SDL_LockMutex(queue->mutex);
+
+ while (queue->front != queue->rear) {+ SDL_free(queue->messages[queue->front]);
+ queue->front = (queue->front + 1) % MAX_QUEUE_SIZE;
+ }
+
+ SDL_UnlockMutex(queue->mutex);
SDL_DestroyMutex(queue->mutex);
SDL_DestroyCondition(queue->cond);
}
@@ -52,4 +61,11 @@
SDL_UnlockMutex(queue->mutex);
return message;
+}
+
+unsigned int queue_size(const message_queue_s *queue) {+ SDL_LockMutex(queue->mutex);
+ const unsigned int size = (queue->rear - queue->front + MAX_QUEUE_SIZE) % MAX_QUEUE_SIZE;
+ SDL_UnlockMutex(queue->mutex);
+ return size;
}
\ No newline at end of file
--- a/src/backends/queue.h
+++ b/src/backends/queue.h
@@ -18,9 +18,39 @@
SDL_Condition *cond;
} message_queue_s;
-// Initialize the message queue
+/**
+ * Initializes the message queue structure.
+ *
+ * @param queue A pointer to the message queue structure to be initialized.
+ */
void init_queue(message_queue_s *queue);
+
+/**
+ * Retrieves and removes a message from the front of the message queue.
+ * If the queue is empty, the function returns NULL.
+ *
+ * @param queue A pointer to the message queue structure from which the message is to be retrieved.
+ * @param length A pointer to a variable where the length of the retrieved message will be stored.
+ * @return A pointer to the retrieved message, or NULL if the queue is empty.
+ */
unsigned char *pop_message(message_queue_s *queue, size_t *length);
+
+/**
+ * Adds a new message to the message queue.
+ * If the queue is full, the message will not be added.
+ *
+ * @param queue A pointer to the message queue structure where the message is to be stored.
+ * @param message A pointer to the message data to be added to the queue.
+ * @param length The length of the message in bytes.
+ */
void push_message(message_queue_s *queue, const unsigned char *message, size_t length);
+
+/**
+ * Calculates the current size of the message queue.
+ *
+ * @param queue A pointer to the message queue structure whose size is to be determined.
+ * @return The number of messages currently in the queue.
+ */
+unsigned int queue_size(const message_queue_s *queue);
#endif // QUEUE_H
--- a/src/main.c
+++ b/src/main.c
@@ -165,7 +165,7 @@
renderer_close();
inline_font_close();
SDL_Quit();
- return -1;
+ return 1;
}
}
--
⑨