static void beatstep_send_sysex(int request, int function, int control, int value) { unsigned char sndr[] = { SYSEX, 0x00, 0x20, 0x6B, /* Arturia sysex ID */ 0x7f, 0x42, /* Dev.ID, Beatstep ? */ request ? 0x01 : 0x02, 0x00, function, control, request ? EOX : value, EOX }; midi_send_sysex(CTRLR_PORT, sndr, sizeof(sndr) - request); /* Don't really like this at all, but apparently some form of delay is * needed to avoid message overruns. Since the underlying * snd_seq_event_output_direct() call copies the event and data to a local * structure before its write() call to the sequencer device, there shouldn't * be any overruns on the top level. Question is if the delay is needed * for the Beatstep or if has something to do with the MIDI (and/or USB) * stack in Linux. In the latter case, one would think that there would be * some form of functionality to check that it was ok to send more data, * but I haven't found any such functin. * Empirically, 100us seems to be enough, but we put in a larger delay to * be on the safe side. */ usleep(1000); }
void configure_midi() { int note_channel = 0; config_lookup_int(&app_config, CFG_DEVICES_MIDI_CONTROLLER_CHANNEL, &controller_channel); config_lookup_int(&app_config, CFG_DEVICES_MIDI_NOTE_CHANNEL, ¬e_channel); synth_model_set_midi_channel(&synth_model, note_channel); config_setting_t *setting_devices_midi_input = config_lookup(&app_config, CFG_DEVICES_MIDI_INPUT); if (setting_devices_midi_input == NULL) { LOG_ERROR("Missing midi input devices in config"); exit(EXIT_FAILURE); } const char* midi_device_names[MAX_MIDI_DEVICES]; int midi_device_count = config_setting_length(setting_devices_midi_input); if (midi_device_count < 0 || midi_device_count > MAX_MIDI_DEVICES) { LOG_ERROR("Invalid number of midi devices %d - should be between 1 and %d", midi_device_count, MAX_MIDI_DEVICES); exit(EXIT_FAILURE); } for (int i = 0; i < midi_device_count; i++) { midi_device_names[i] = config_setting_get_string_elem(setting_devices_midi_input, i); } if (midi_initialise(midi_device_count, midi_device_names) < 0) { exit(EXIT_FAILURE); } if (!synth_controllers_initialise(controller_channel, config_lookup(&app_config, CFG_CONTROLLERS))) { exit(EXIT_FAILURE); } if (mod_matrix_controller_initialise(config_lookup(&app_config, CFG_MOD_MATRIX_CONTROLLER), config_lookup(&patch_config, CFG_MOD_MATRIX_CONTROLLER)) != RESULT_OK) { exit(EXIT_FAILURE); } synth_controllers_load(SETTINGS_FILE, &synth_model); config_setting_t *setting_sysex_init_message = config_lookup(&app_config, CFG_SYSEX_INIT); if (setting_sysex_init_message != NULL) { int message_len = config_setting_length(setting_sysex_init_message); char *message_bytes = alloca(message_len); for (int i = 0; i < message_len; i++) { message_bytes[i] = config_setting_get_int_elem(setting_sysex_init_message, i); } midi_send_sysex(message_bytes, message_len); } }