/*
 channel.c
 ---------

 Controls the Channels window that displays and allows adjustment
 of the player's channel volume and program.

 3/8/22
*/

#include "wimp.h"
#include "lib.h"
#include "ro_main.h"
#include "main.h"
#include "kbd.h"
#include "midisyn.h"


/*
 * display_chan_info
 * -----------------
 * Updates a single channel
 */
static void display_chan_info(int chan, int prg)
{
  int data[3];
  data[0] = chan;
  data[1] = prg;
  // currently this displays the GM standard names
  if(chan == (PERCUSSION_CHAN-1))
    data[2] = (int)(syn.idat.bank[syn.idat.kits[0]-1].name);
  else
    data[2] = (int)(syn.idat.instrument[syn.idat.bank[syn.idat.banks[0]-1].ins[prg]-1].name);
  midiPlayer_display(ITEM_CHN_PRG, data);
}


/*
 * chn_slider_control
 * ------------------
 * blk = block from Wimp_GetPointerInfo
 * The display is of the combined volume/expression value,
 * that are already combined as follows, vol_expr = (volume * expression) squared.
 * It does not include velocity which is applied to each note separately and is
 * therefore not a channel variable.
 * Returns True if dealt with here, else False
 */
int chn_slider_control(int *blk)
{
  if(ro.slider.window != ro.handle[WIN_CHANNELS])
    return 0;

  int chan = (ro.slider.icon - 3) / 7;
  int icon = ro.slider.icon - (7 * chan);
  int data[2];

  if(icon == ICON_CHN_VOL_SLDR)
  {
    data[0] = chan;
    data[1] = syn.chan[chan].vol_expr = slider_get_posn(blk, SLDR_CHN_VOL);
    midiPlayer_display(ITEM_CHN_VOL, data);
  }

  return 1;
}


/*
 * chn_mouse_click
 * ---------------
 * blk = block from Wimp_Poll
 * state = icon state, selected or not
 * Returns True if dealt with here, else False
 */
int chn_mouse_click(int *blk, int state)
{
  if(blk[3] != ro.handle[WIN_CHANNELS])
    return 0;

  int chan = (blk[4] - 3) / 7;
  int icon = blk[4] - (7 * chan);
  int inc = 1;

  switch(icon)
  {
    case ICON_CHN_VOL_BACK: // channel volume
      blk[4]++;
    case ICON_CHN_VOL_SLDR:
      ro.slider.window = blk[3];
      ro.slider.icon = blk[4];
      icon_state_change(1, blk[3], blk[4]);
      break;

    case ICON_CHN_PRG_DEC:
      inc = -1;
    case ICON_CHN_PRG_INC:
      {
        chan_t *c = &syn.chan[chan];
        c->patch.prg = (c->patch.prg + inc) & (MIDI_DATA_RANGE - 1);
        display_chan_info(chan, c->patch.prg);
      }
      break;
  }

  return 1;
}


/*
 * chn_key_press
 * -------------
 * blk = block from Wimp_GetIconState
 * key = current character
 * p = pointer to icon text
 * Returns True if dealt with here, else False
 */
int chn_key_press(int *blk, int key, char *p)
{
  if(blk[0] != ro.handle[WIN_CHANNELS])
    return 0;

  int chan = (blk[1] - 3) / 7;
  int icon = blk[1] - (7 * chan);

  if((key == '\r') && (icon == ICON_CHN_PRG_VAL))
  {
    chan_t *c = &syn.chan[chan];
    int prg = atoi(p);
    if(prg > (MIDI_DATA_RANGE - 1))
      prg = (MIDI_DATA_RANGE - 1);
    c->patch.prg = prg;
    display_chan_info(chan, prg);
  }

  return 1;
}

