From ae5c0cd3ecb8e53b04edb75d92a52b7eca9d3c15 Mon Sep 17 00:00:00 2001 From: Lauchmelder Date: Sun, 17 Apr 2022 18:31:19 +0200 Subject: [PATCH] added commandline parsing --- src/main.c | 76 ++++++++++++++++++++++++++++++++++++++++++++------- src/message.c | 9 ++++++ src/message.h | 3 +- 3 files changed, 76 insertions(+), 12 deletions(-) diff --git a/src/main.c b/src/main.c index e7096b9..52e3995 100644 --- a/src/main.c +++ b/src/main.c @@ -1,33 +1,34 @@ -#include #include -#include #include -#include -#include #include #include +#include #include #include #include "midi_interface.h" #include "midi_parser.h" +typedef struct +{ + const char* midi_file; + const char* mapping_file; +} CommandArguments; + MidiInterface* interface; static int _Atomic playing = ATOMIC_VAR_INIT(0); static uint32_t _Atomic time_per_quarter = ATOMIC_VAR_INIT(1); static uint32_t _Atomic current_tick = ATOMIC_VAR_INIT(0); +CommandArguments parse_command_args(int argc, char** argv); + void* play_track(void* data); void* advance_counter(void* data); int main(int argc, char** argv) { - if(argc != 2) - { - fprintf(stderr, "Usage: musicalpi "); - exit(-1); - } + CommandArguments args = parse_command_args(argc, argv); printf("Loading MIDI file...\n"); MidiParser* parser; @@ -106,7 +107,12 @@ void* play_track(void* data) { time_per_quarter = ((uint32_t*)(event.infos))[0]; } - else if(event.type == MidiNotePressed || event.type == MidiNoteReleased || event.type == MidiControllerValueChanged) + else if( + event.type == MidiNotePressed || + event.type == MidiNoteReleased || + event.type == MidiControllerValueChanged || + event.type == MidiProgramChanged + ) { message->channel = (((uint8_t*)(event.infos))[0] & 0xF); message->data = event.infos + 1; @@ -124,6 +130,13 @@ void* play_track(void* data) case MidiControllerValueChanged: message->type = CONTROLLER_CHANGE; break; + + case MidiProgramChanged: + message->type = PROGRAM_CHANGE; + break; + + default: + break; } // printf("Sending %d %d\n", message->data[0], message->data[1]); int result = write_midi_device(interface, message); @@ -134,4 +147,47 @@ void* play_track(void* data) current_event++; tick_of_last_event += event.timeToAppear; } + + return NULL; +} + +CommandArguments parse_command_args(int argc, char** argv) +{ + CommandArguments parsed_args; + parsed_args.midi_file = NULL; + parsed_args.mapping_file = NULL; + + int opt; + + while ((opt = getopt(argc, argv, "hm:")) != -1) + { + switch(opt) + { + case 'm': + { + size_t len = strlen(optarg); + parsed_args.mapping_file = (const char*)malloc(len); + memcpy((void*)parsed_args.mapping_file, (void*)optarg, len); + } break; + + case 'h': + fprintf(stderr, "Usage: %s [-m mapping_file] midi_file\n", argv[0]); + exit(EXIT_SUCCESS); + } + } + + if(optind < argc) + { + size_t len = strlen(argv[optind]); + parsed_args.midi_file = (const char*)malloc(len); + memcpy((void*)parsed_args.midi_file, (void*)argv[optind], len); + } + + if(parsed_args.midi_file == NULL) + { + fprintf(stderr, "A MIDI file is required\n"); + exit(EXIT_FAILURE); + } + + return parsed_args; } \ No newline at end of file diff --git a/src/message.c b/src/message.c index 4398e4b..e91e0ac 100644 --- a/src/message.c +++ b/src/message.c @@ -23,6 +23,7 @@ int data_length(MessageType type) case NOTE_ON: return 2; case NOTE_OFF: return 2; case CONTROLLER_CHANGE: return 2; + case PROGRAM_CHANGE: return 1; case SYSTEM_EXCLUSIVE: return 0; } @@ -48,6 +49,10 @@ int decode_status_byte(Message* message, uint8_t status) message->type = CONTROLLER_CHANGE; break; + case 0xC0: + message->type = PROGRAM_CHANGE; + break; + case 0xF0: message->type = SYSTEM_EXCLUSIVE; break; @@ -78,6 +83,10 @@ int encode_status_byte(const Message* message, uint8_t* status) *status |= 0xB0; break; + case PROGRAM_CHANGE: + *status |= 0xC0; + break; + case SYSTEM_EXCLUSIVE: *status |= 0xF0; break; diff --git a/src/message.h b/src/message.h index da9112e..db53fd5 100644 --- a/src/message.h +++ b/src/message.h @@ -5,8 +5,7 @@ typedef enum MessageType { - NOTE_OFF, NOTE_ON, CONTROLLER_CHANGE, - SYSTEM_EXCLUSIVE + NOTE_OFF, NOTE_ON, CONTROLLER_CHANGE, PROGRAM_CHANGE, SYSTEM_EXCLUSIVE } MessageType; typedef struct Message