shithub: m8c

ref: d750ca7c0c55188ea4afb8103c9708ab11345002
dir: /src/input.c/

View raw version
#include "input.h"
#include "backends/rtmidi.h"
#include "backends/serialport.h"
#include "config.h"
#include "gamecontrollers.h"
#include "render.h"
#include "audio.h"
#include <SDL3/SDL.h>

uint8_t keyjazz_enabled = 0;
uint8_t keyjazz_base_octave = 2;
uint8_t keyjazz_velocity = 0x64;

static uint8_t keycode = 0; // value of the pressed key

static input_msg_s key = {normal, 0, 0, 0};

int input_process(config_params_s conf, enum app_state *app_state) {
  static uint8_t prev_input = 0;
  static uint8_t prev_note = 0;

  // get current inputs
  const input_msg_s input = input_get_msg(&conf);

  switch (input.type) {
  case normal:
    if (input.value != prev_input) {
      prev_input = input.value;
      send_msg_controller(input.value);
    }
    break;
  case keyjazz:
    if (input.value != 0) {
      if (input.eventType == SDL_EVENT_KEY_DOWN && input.value != prev_input) {
        send_msg_keyjazz(input.value, input.value2);
        prev_note = input.value;
      } else if (input.eventType == SDL_EVENT_KEY_UP && input.value == prev_note) {
        send_msg_keyjazz(0xFF, 0);
      }
    }
    prev_input = input.value;
    break;
  case special:
    if (input.value != prev_input) {
      prev_input = input.value;
      switch (input.value) {
      case msg_quit:
        SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "Received msg_quit from input device.");
        *app_state = 0;
        break;
      case msg_reset_display:
        reset_display();
        break;
      case msg_toggle_audio:
        conf.audio_enabled = !conf.audio_enabled;
        audio_toggle(conf.audio_device_name, conf.audio_buffer_size);
        break;
      default:
        break;
      }
      break;
    }
  }
  return 1;
}

uint8_t toggle_input_keyjazz() {
  keyjazz_enabled = !keyjazz_enabled;
  SDL_LogDebug(SDL_LOG_CATEGORY_SYSTEM, keyjazz_enabled ? "Keyjazz enabled" : "Keyjazz disabled");
  return keyjazz_enabled;
}

static input_msg_s handle_keyjazz(SDL_Event *event, uint8_t keyvalue, config_params_s *conf) {
  input_msg_s key = {keyjazz, keyvalue, keyjazz_velocity, event->type};
  switch (event->key.scancode) {
  case SDL_SCANCODE_Z:
    key.value = keyjazz_base_octave * 12;
    break;
  case SDL_SCANCODE_S:
    key.value = 1 + keyjazz_base_octave * 12;
    break;
  case SDL_SCANCODE_X:
    key.value = 2 + keyjazz_base_octave * 12;
    break;
  case SDL_SCANCODE_D:
    key.value = 3 + keyjazz_base_octave * 12;
    break;
  case SDL_SCANCODE_C:
    key.value = 4 + keyjazz_base_octave * 12;
    break;
  case SDL_SCANCODE_V:
    key.value = 5 + keyjazz_base_octave * 12;
    break;
  case SDL_SCANCODE_G:
    key.value = 6 + keyjazz_base_octave * 12;
    break;
  case SDL_SCANCODE_B:
    key.value = 7 + keyjazz_base_octave * 12;
    break;
  case SDL_SCANCODE_H:
    key.value = 8 + keyjazz_base_octave * 12;
    break;
  case SDL_SCANCODE_N:
    key.value = 9 + keyjazz_base_octave * 12;
    break;
  case SDL_SCANCODE_J:
    key.value = 10 + keyjazz_base_octave * 12;
    break;
  case SDL_SCANCODE_M:
    key.value = 11 + keyjazz_base_octave * 12;
    break;
  case SDL_SCANCODE_Q:
    key.value = 12 + keyjazz_base_octave * 12;
    break;
  case SDL_SCANCODE_2:
    key.value = 13 + keyjazz_base_octave * 12;
    break;
  case SDL_SCANCODE_W:
    key.value = 14 + keyjazz_base_octave * 12;
    break;
  case SDL_SCANCODE_3:
    key.value = 15 + keyjazz_base_octave * 12;
    break;
  case SDL_SCANCODE_E:
    key.value = 16 + keyjazz_base_octave * 12;
    break;
  case SDL_SCANCODE_R:
    key.value = 17 + keyjazz_base_octave * 12;
    break;
  case SDL_SCANCODE_5:
    key.value = 18 + keyjazz_base_octave * 12;
    break;
  case SDL_SCANCODE_T:
    key.value = 19 + keyjazz_base_octave * 12;
    break;
  case SDL_SCANCODE_6:
    key.value = 20 + keyjazz_base_octave * 12;
    break;
  case SDL_SCANCODE_Y:
    key.value = 21 + keyjazz_base_octave * 12;
    break;
  case SDL_SCANCODE_7:
    key.value = 22 + keyjazz_base_octave * 12;
    break;
  case SDL_SCANCODE_U:
    key.value = 23 + keyjazz_base_octave * 12;
    break;
  case SDL_SCANCODE_I:
    key.value = 24 + keyjazz_base_octave * 12;
    break;
  case SDL_SCANCODE_9:
    key.value = 25 + keyjazz_base_octave * 12;
    break;
  case SDL_SCANCODE_O:
    key.value = 26 + keyjazz_base_octave * 12;
    break;
  case SDL_SCANCODE_0:
    key.value = 27 + keyjazz_base_octave * 12;
    break;
  case SDL_SCANCODE_P:
    key.value = 28 + keyjazz_base_octave * 12;
    break;
  default:
    key.type = normal;
    if (event->key.repeat > 0 || event->key.type == SDL_EVENT_KEY_UP) {
      break;
    }
    if (event->key.scancode == conf->key_jazz_dec_octave) {
      if (keyjazz_base_octave > 0) {
        keyjazz_base_octave--;
        display_keyjazz_overlay(1, keyjazz_base_octave, keyjazz_velocity);
      }
    } else if (event->key.scancode == conf->key_jazz_inc_octave) {
      if (keyjazz_base_octave < 8) {
        keyjazz_base_octave++;
        display_keyjazz_overlay(1, keyjazz_base_octave, keyjazz_velocity);
      }
    } else if (event->key.scancode == conf->key_jazz_dec_velocity) {
      if ((event->key.mod & SDL_KMOD_ALT) > 0) {
        if (keyjazz_velocity > 1)
          keyjazz_velocity -= 1;
      } else {
        if (keyjazz_velocity > 0x10)
          keyjazz_velocity -= 0x10;
      }
      display_keyjazz_overlay(1, keyjazz_base_octave, keyjazz_velocity);
    } else if (event->key.scancode == conf->key_jazz_inc_velocity) {
      if ((event->key.mod & SDL_KMOD_ALT) > 0) {
        if (keyjazz_velocity < 0x7F)
          keyjazz_velocity += 1;
      } else {
        if (keyjazz_velocity < 0x6F)
          keyjazz_velocity += 0x10;
      }
      display_keyjazz_overlay(1, keyjazz_base_octave, keyjazz_velocity);
    }
    break;
  }

  return key;
}

static input_msg_s handle_normal_keys(const SDL_Event *event, const config_params_s *conf) {
  input_msg_s key = {normal, 0, 0, 0};

  if (event->key.scancode == conf->key_up) {
    key.value = key_up;
  } else if (event->key.scancode == conf->key_left) {
    key.value = key_left;
  } else if (event->key.scancode == conf->key_down) {
    key.value = key_down;
  } else if (event->key.scancode == conf->key_right) {
    key.value = key_right;
  } else if (event->key.scancode == conf->key_select ||
             event->key.scancode == conf->key_select_alt) {
    key.value = key_select;
  } else if (event->key.scancode == conf->key_start ||
             event->key.scancode == conf->key_start_alt) {
    key.value = key_start;
  } else if (event->key.scancode == conf->key_opt ||
             event->key.scancode == conf->key_opt_alt) {
    key.value = key_opt;
  } else if (event->key.scancode == conf->key_edit ||
             event->key.scancode == conf->key_edit_alt) {
    key.value = key_edit;
  } else if (event->key.scancode == conf->key_delete) {
    key.value = key_opt | key_edit;
  } else if (event->key.scancode == conf->key_reset) {
    key = (input_msg_s){special, msg_reset_display, 0, 0};
  } else if (event->key.scancode == conf->key_toggle_audio) {
    key = (input_msg_s){special, msg_toggle_audio, 0, 0};
  } else {
    key.value = 0;
  }
  return key;
}

// Handles SDL input events
void handle_sdl_events(config_params_s *conf) {

  static int prev_key_analog = 0;
  static unsigned int ticks_window_resized = 0;

  SDL_Event event;

  // Read joysticks
  const int key_analog = gamecontrollers_handle_buttons(conf);
  if (prev_key_analog != key_analog) {
    keycode = key_analog;
    prev_key_analog = key_analog;
  }

  const input_msg_s gamepad_msg = gamecontrollers_handle_special_messages(conf);
  if (gamepad_msg.type == special) {
    key = gamepad_msg;
  }

  while (SDL_PollEvent(&event)) {

    switch (event.type) {

    // Reinitialize game controllers on controller add/remove/remap
    case SDL_EVENT_GAMEPAD_ADDED:
    case SDL_EVENT_GAMEPAD_REMOVED:
      gamecontrollers_initialize();
      break;

    // Handle SDL quit events (for example, window close)
    case SDL_EVENT_QUIT:
      key = (input_msg_s){special, msg_quit, 0, 0};
      break;

    case SDL_EVENT_WINDOW_RESIZED:
        if (SDL_GetTicks() - ticks_window_resized > 500) {
          SDL_Log("Resizing window...");
          key = (input_msg_s){special, msg_reset_display, 0, 0};
          ticks_window_resized = SDL_GetTicks();
        }
      break;

    case SDL_EVENT_KEY_DOWN:

      if (event.key.repeat > 0) {
        break;
      }

      // ALT+ENTER toggles fullscreen
      if (event.key.key == SDLK_RETURN && (event.key.mod & SDL_KMOD_ALT) > 0) {
        toggle_fullscreen();
        break;
      }

      // ALT+F4 quits program
      if (event.key.key == SDLK_F4 && (event.key.mod & SDL_KMOD_ALT) > 0) {
        key = (input_msg_s){special, msg_quit, 0, 0};
        break;
      }

      // ESC = toggle keyjazz
      if (event.key.key == SDLK_ESCAPE) {
        display_keyjazz_overlay(toggle_input_keyjazz(), keyjazz_base_octave, keyjazz_velocity);
        break;
      }

    // Intentional fallthrough
    case SDL_EVENT_KEY_UP:

      // Normal keyboard inputs
      key = handle_normal_keys(&event, conf);

      if (keyjazz_enabled) {
        key = handle_keyjazz(&event, key.value, conf);
      }
      break;

    default:
      break;
    }

    switch (key.type) {
    case normal:
      if (event.type == SDL_EVENT_KEY_DOWN) {
        keycode |= key.value;
      } else if (event.type == SDL_EVENT_KEY_UP) {
        keycode &= ~key.value;
      }
      break;
    case keyjazz:
      // Do not allow pressing multiple keys with keyjazz
    case special:
      if (event.type == SDL_EVENT_KEY_DOWN) {
        keycode = key.value;
      } else if (event.type == SDL_EVENT_KEY_UP) {
        keycode = 0;
      }
      break;
    default:
      break;
    }
  }
}

// Returns the currently pressed keys to main
input_msg_s input_get_msg(config_params_s *conf) {

  key = (input_msg_s){normal, 0, 0, 0};

  // Query for SDL events
  handle_sdl_events(conf);

  if (!keyjazz_enabled && keycode == (key_start | key_select | key_opt | key_edit)) {
    key = (input_msg_s){special, msg_reset_display, 0, 0};
  }

  if (key.type == normal) {
    /* Normal input keys go through some event-based manipulation in
       handle_sdl_events(), the value is stored in keycode variable */
    const input_msg_s input = (input_msg_s){key.type, keycode, 0, 0};
    return input;
  }
  // Special event keys already have the correct keycode baked in
  return key;
}