/*
 Synth Control
 -------------
 control.c
 11/3/24
 */

#include "common.h"
#include "wimp.h"
#include "lib.h"
#include "synth.h"
#include "main.h"
#include "editor.h"


/*
 * update_control_window
 * ---------------------
 */
void update_control_window(void)
{
  _kernel_swi_regs regs;
  int win = ro.handle[WIN_SYN_CONTROL];
  int blk[13];

  regs.r[0] = SYN_NULL;
  regs.r[1] = (int)blk;
  _kernel_swi(MIDISynth_Control, &regs, &regs); // get curent settings
  icon_text_change(itoa(blk[0]), win, ICON_CTRL_POLY);
  icon_text_change(itoa(blk[1]), win, ICON_CTRL_GLIDE);
  icon_text_change(itoa(blk[2]), win, ICON_CTRL_SLEEP);
  icon_state_change((blk[3] >> MONO_AUDIO) & 1, win, ICON_CTRL_STEREO);
  icon_state_change((blk[3] >> L_R_SWAP) & 1, win, ICON_CTRL_SWAP);
  icon_state_change((blk[3] >> ALL_BANKS) & 1, win, ICON_CTRL_GM_VAR);
  icon_state_change((blk[3] >> ALL_KITS) & 1, win, ICON_ALL_KITS);
  icon_state_change((blk[3] >> BANK_SEL_DRUM) & 1, win, ICON_BANK_SEL_DRUM);
  icon_state_change((blk[3] >> PRG_UPDATES_BANKS) & 1, win, ICON_PRG_UPD_BANK);
  icon_state_change((blk[3] >> CSV_NO_NUMBER) & 1, win, ICON_CSV_NO_NUMBER);
  icon_state_change((blk[3] >> PATCH_NO_KITS) & 1, win, ICON_PATCH_NO_KITS);
  icon_state_change((blk[3] >> PATCH_BY_BANK) & 1, win, ICON_PATCH_BY_BANK);
  icon_text_change(itoa(blk[4]), win, ICON_CTRL_BANKS);
  icon_text_change(itoa(blk[5]), win, ICON_CTRL_KITS);
  icon_text_change(itoa(blk[6] + 1), win, ICON_CUR_DRUM_CHAN);
  icon_text_change(itoa(blk[7] + 1), win, ICON_DEF_DRUM_CHAN);
  icon_text_change(itoa(blk[8]), win, ICON_SAMPLE_RATE);
  slider_display_value(blk[9], SLDR_VOLUME, WIN_SYN_CONTROL, ICON_VOLUME_SLDR);
  slider_display_value(blk[10], SLDR_BALANCE, WIN_SYN_CONTROL, ICON_BALANCE_SLDR);
  icon_text_change(itoa(blk[11]), win, ICON_COR_TUNE_VAL);
  ro.master_coarse = blk[11];
  slider_display_value(blk[12], SLDR_FINE, WIN_SYN_CONTROL, ICON_FIN_TUNE_SLDR);
  ro.master_fine = blk[12];
}


/*
 * ctrl_slider_control
 * ------------------
 * blk = block from Wimp_GetPointerInfo
 * Returns True if dealt with here, else False
 */
int ctrl_slider_control(int *blk)
{
  _kernel_swi_regs regs;
  int b[13];
  regs.r[1] = (int)b;

  if(ro.slider.window == ro.handle[WIN_SYN_CONTROL])
    switch(ro.slider.icon)
    {
      case ICON_VOLUME_SLDR:
        regs.r[0] = SYN_VOL;
        regs.r[2] = slider_get_posn(blk, SLDR_VOLUME);
        _kernel_swi(MIDISynth_Control, &regs, &regs);
        slider_display_value(b[9], SLDR_VOLUME, WIN_SYN_CONTROL, ICON_VOLUME_SLDR);
        break;

      case ICON_BALANCE_SLDR:
        regs.r[0] = SYN_BAL;
        regs.r[2] = slider_get_posn(blk, SLDR_BALANCE);
        _kernel_swi(MIDISynth_Control, &regs, &regs);
        slider_display_value(b[10], SLDR_BALANCE, WIN_SYN_CONTROL, ICON_BALANCE_SLDR);
        break;

      case ICON_FIN_TUNE_SLDR:
        regs.r[0] = SYN_FINE;
        regs.r[2] = slider_get_posn(blk, SLDR_FINE);
        _kernel_swi(MIDISynth_Control, &regs, &regs);
        slider_display_value(b[12], SLDR_FINE, WIN_SYN_CONTROL, ICON_FIN_TUNE_SLDR);
        break;
    }

  else
    return FALSE;

  return TRUE;
}


/*
 * ctrl_mouse_click
 * ---------------
 * blk = block from Wimp_Poll
 * state = icon state, selected or not
 * Returns True if dealt with here, else False
 */
int ctrl_mouse_click(int *blk, int state)
{
  _kernel_swi_regs regs;
  int ret = TRUE;
  int b[13];
  regs.r[1] = (int)b;
  int n;

  // Control window
  if(blk[3] == ro.handle[WIN_SYN_CONTROL])
  {
    if(blk[2] == MOUSE_MENU)
      open_menu(blk[0] - 64, blk[1], MENU_CONTROL, (int)&control_menu);

    else
    {
      int inc = 0;
      if(blk[2] == MOUSE_SELECT)
        inc = 1;
      else if (blk[2] == MOUSE_ADJUST)
        inc = -1;

       switch (blk[4])
      {
        case ICON_VOLUME_BACK:
        case ICON_BALANCE_BACK:
        case ICON_FIN_TUNE_BACK:
          blk[4]++;
        case ICON_VOLUME_SLDR:
        case ICON_BALANCE_SLDR:
        case ICON_FIN_TUNE_SLDR:
          ro.slider.window = blk[3];
          ro.slider.icon = blk[4];
          icon_state_change(1, blk[3], blk[4]);
          break;

        case ICON_CTRL_STEREO:
          regs.r[0] = SYN_FLAGS;
          regs.r[2] = 1 << MONO_AUDIO;
          regs.r[3] = state << MONO_AUDIO;
          _kernel_swi(MIDISynth_Control, &regs, &regs);
          break;

        case ICON_CTRL_SWAP:
          regs.r[0] = SYN_FLAGS;
          regs.r[2] = 1 << L_R_SWAP;
          regs.r[3] = state << L_R_SWAP;
          _kernel_swi(MIDISynth_Control, &regs, &regs);
          break;

        case ICON_CTRL_GM_VAR:
          regs.r[0] = SYN_FLAGS;
          regs.r[2] = 1 << ALL_BANKS;
          regs.r[3] = state << ALL_BANKS;
          _kernel_swi(MIDISynth_Control, &regs, &regs);
          break;

        case ICON_ALL_KITS:
          regs.r[0] = SYN_FLAGS;
          regs.r[2] = 1 << ALL_KITS;
          regs.r[3] = state << ALL_KITS;
          _kernel_swi(MIDISynth_Control, &regs, &regs);
          break;

        case ICON_BANK_SEL_DRUM:
          regs.r[0] = SYN_FLAGS;
          regs.r[2] = 1 << BANK_SEL_DRUM;
          regs.r[3] = state << BANK_SEL_DRUM;
          _kernel_swi(MIDISynth_Control, &regs, &regs);
          break;

        case ICON_PRG_UPD_BANK:
          regs.r[0] = SYN_FLAGS;
          regs.r[2] = 1 << PRG_UPDATES_BANKS;
          regs.r[3] = state << PRG_UPDATES_BANKS;
          _kernel_swi(MIDISynth_Control, &regs, &regs);
          break;

        case ICON_CSV_NO_NUMBER:
          regs.r[0] = SYN_FLAGS;
          regs.r[2] = 1 << CSV_NO_NUMBER;
          regs.r[3] = state << CSV_NO_NUMBER;
          _kernel_swi(MIDISynth_Control, &regs, &regs);
          break;

        case ICON_PATCH_NO_KITS:
          regs.r[0] = SYN_FLAGS;
          regs.r[2] = 1 << PATCH_NO_KITS;
          regs.r[3] = state << PATCH_NO_KITS;
          _kernel_swi(MIDISynth_Control, &regs, &regs);
          break;

        case ICON_PATCH_BY_BANK:
          regs.r[0] = SYN_FLAGS;
          regs.r[2] = 1 << PATCH_BY_BANK;
          regs.r[3] = state << PATCH_BY_BANK;
          _kernel_swi(MIDISynth_Control, &regs, &regs);
          break;

        case ICON_SAVE_CHOICES:
          regs.r[0] = SYN_SAVE;
          _kernel_swi(MIDISynth_Control, &regs, &regs);
          break;

        case ICON_CTRL_RESET:
          regs.r[0] = SYN_RESET;
          _kernel_swi(MIDISynth_Control, &regs, &regs);
          break;

        case ICON_RATE_MENU:
          open_menu(blk[0] - 64, blk[1], MENU_RATE, (int)&rate_menu);
          break;

        case ICON_COR_TUNE_DEC:
          inc = -inc;
        case ICON_COR_TUNE_INC: // master course tuning
          n = read_numeric_value(blk[3], ICON_COR_TUNE_VAL) + inc;
          LIMIT(-64, n, 63);
          regs.r[0] = SYN_COARSE;
          regs.r[2] = n;
          _kernel_swi(MIDISynth_Control, &regs, &regs);
          icon_text_change(itoa(n), blk[3], ICON_COR_TUNE_VAL);
          ro.master_coarse = n;
          break;

        case ICON_RESET_TUNING: // reset master coarse and fine tuning
          regs.r[2] = ro.master_coarse = ro.master_fine = 0;
          regs.r[0] = SYN_COARSE;
          _kernel_swi(MIDISynth_Control, &regs, &regs);
          icon_text_change("0", blk[3], ICON_COR_TUNE_VAL);
          regs.r[0] = SYN_FINE;
          _kernel_swi(MIDISynth_Control, &regs, &regs);
          slider_display_value(0, SLDR_FINE, WIN_SYN_CONTROL, ICON_FIN_TUNE_SLDR);
      }
    }
  }

  else
    ret = FALSE;

  return ret;
}


/*
 * ctrl_key_press
 * -------------
 * blk = block from Wimp_GetIconState
 * key = current character
 * p = pointer to icon text
 * Returns True if dealt with here, else False
 */
int ctrl_key_press(int *blk, int key, char *p)
{
  int n = atoi(p);
  _kernel_swi_regs regs;
  int b[13];
  regs.r[1] = (int)b;

  // Control window
  if(blk[0] == ro.handle[WIN_SYN_CONTROL])
  {
    char *s;
    if(key == '\r')
      switch(blk[1])
      {
        case ICON_CTRL_POLY: // polyphony
          LIMIT(4, n, NUM_GENS);
          regs.r[0] = SYN_POLY;
          regs.r[2] = n;
          _kernel_swi(MIDISynth_Control, &regs, &regs);
          icon_text_change(itoa(n), blk[0], blk[1]);
          break;

        case ICON_CTRL_GLIDE: // glide time scale factor
          LIMIT(0, n, 1000);
          regs.r[0] = SYN_GLIDE;
          regs.r[2] = n;
          _kernel_swi(MIDISynth_Control, &regs, &regs);
          icon_text_change(itoa(n), blk[0], blk[1]);
          break;

        case ICON_CTRL_SLEEP: // sleep time
          LIMIT(0, n, 3600);
          regs.r[0] = SYN_SLEEP;
          regs.r[2] = n;
          _kernel_swi(MIDISynth_Control, &regs, &regs);
          icon_text_change(itoa(n), blk[0], blk[1]);
          break;

        case ICON_CTRL_BANKS: // bank override
          LIMIT(0, n, 127);
          regs.r[0] = SYN_BANKS;
          regs.r[2] = n;
          _kernel_swi(MIDISynth_Control, &regs, &regs);
          icon_text_change(itoa(n), blk[0], blk[1]);
          break;

        case ICON_CTRL_KITS: // drum kit override
          LIMIT(0, n, 127);
          regs.r[0] = SYN_KITS;
          regs.r[2] = n;
          _kernel_swi(MIDISynth_Control, &regs, &regs);
          icon_text_change(itoa(n), blk[0], blk[1]);
          break;

        case ICON_DEF_DRUM_CHAN: // default drum kit channel
          LIMIT(1, n, 16);
          regs.r[0] = SYN_DRUM;
          regs.r[2] = n;
          _kernel_swi(MIDISynth_Control, &regs, &regs);
          s = itoa(n);
          icon_text_change(s, blk[0], blk[1]);
          icon_text_change(s, blk[0], ICON_CUR_DRUM_CHAN);
          break;

        case ICON_COR_TUNE_VAL: // master tuning coarse
          LIMIT(-64, n, 63);
          ro.master_coarse = n;
          regs.r[0] = SYN_COARSE;
          regs.r[2] = n;
          _kernel_swi(MIDISynth_Control, &regs, &regs);
          icon_text_change(itoa(n), blk[0], blk[1]);
          break;
      }
  }

  else
    return FALSE;

  return TRUE;
}



