#ifndef _MIDICONTROLLER_H
#define _MIDICONTROLLER_H

#ifdef __cplusplus
extern "C" {
#endif

#include "midievent.h"

enum midi_controller_t {
  // MSB
  MIDICTRL_BANK_SELECT=0,
  MIDICTRL_MODULATION_WHEEL,
  MIDICTRL_BREATH_CONTROLLER,
  MIDICTRL_FOOT_CONTROLLER=4,
  MIDICTRL_PORTAMENTO_TIME,
  MIDICTRL_DATA_ENTRY,
  MIDICTRL_CHANNEL_VOLUME,
  MIDICTRL_BALANCE,
  MIDICTRL_PAN=0x0a,
  MIDICTRL_EXPRESSION_CONTROLLER,
  MIDICTRL_EFFECT_CONTROL_1,
  MIDICTRL_EFFECT_CONTROL_2,
  MIDICTRL_GEN_PURPOSE_CONTROLLER_1=0x10,
  MIDICTRL_GEN_PURPOSE_CONTROLLER_2,
  MIDICTRL_GEN_PURPOSE_CONTROLLER_3,
  MIDICTRL_GEN_PURPOSE_CONTROLLER_4,

  // LSB is +0x20
  MIDICTRL__LSB=0x20,

  // on/off only (127..64 on, 63..0 off)
  MIDICTRL_SUSTAIN=0x40,
  MIDICTRL_PORTAMENTO,
  MIDICTRL_SOSTENUTO,
  MIDICTRL_SOFT_PEDAL,
  MIDICTRL_LEGATO,
  MIDICTRL_HOLD_2,

#if 0
  // other continuous
  SOUND_CONTROLLER_1,  // (TG: Sound Variation;  FX: Exciter On/Off)
  SOUND_CONTROLLER_2,  // (TG: Harmonic Content; FX: Compressor On/Off)
  SOUND_CONTROLLER_3,  // (TG: Release Time;     FX: Distortion On/Off)
  SOUND_CONTROLLER_4,  // (TG: Attack Time;   FX: EQ On/Off)
  SOUND_CONTROLLER_5,  // (TG: Brightness;   FX: Expander On/Off)
  SOUND_CONTROLLER_6,  // (TG: Undefined;   FX: Reverb OnOff)
  SOUND_CONTROLLER_7,  // (TG: Undefined;   FX: Delay OnOff)
  SOUND_CONTROLLER_8,  // (TG: Undefined;   FX: Pitch Transpose OnOff)
  SOUND_CONTROLLER_9,  // (TG: Undefined;   FX: Flange/Chorus OnOff)
  SOUND_CONTROLLER_10, // (TG: Undefined;   FX: Special Effects OnOff)

  GENERAL_PURPOSE_CONTROLLER_5,
  GENERAL_PURPOSE_CONTROLLER_6,
  GENERAL_PURPOSE_CONTROLLER_7,
  GENERAL_PURPOSE_CONTROLLER_8,
  PORTAMENTO_CONTROL,  // (0vvvvvvv is the source Note number)   (Detail)
  EFFECTS_1,    // (Ext. Effects Depth)
  EFFECTS_2,    // (Tremelo Depth)
  EFFECTS_3,    // (Chorus Depth)
  EFFECTS_4,    // (Celeste Depth)
  EFFECTS_5,    // (Phaser Depth)
  DATA_INCREMENT,
  DATA_DECREMENT,
  NON_REGISTERED_PARAMETER_NUMBER_LSB,
  NON_REGISTERED_PARAMETER_NUMBER_MSB,
  REGISTERED_PARAMETER_NUMBER_LSB,
  REGISTERED_PARAMETER_NUMBER_MSB,
#endif

  // channel mode,  except otherwise stated: value=0
  MIDICTRL_ALL_SOUND_OFF=0x78,
  MIDICTRL_RESET_ALL_CONTROLLERS,
  MIDICTRL_LOCAL_CONTROL, // value: off/on
  MIDICTRL_ALL_NOTES_OFF, 
  MIDICTRL_OMNI_MODE_OFF, // (does ANO)
  MIDICTRL_OMNI_MODE_ON,  // (does ANO)
  MIDICTRL_MONO_MODE_ON,  // (does ANO)  [value: 0/1..16: channel]
  MIDICTRL_POLY_MODE_ON
};

static inline void midictrl_event_set(midi_event_t *ret,char channel,char number,char value) {
  // assert(ret); assert( (channel>=0)&&(channel<16) );
  ret->time=0;
  ret->type=EV_CONTROLLER;
  ret->channel=channel;
  ret->controller.number=number;
  ret->controller.value=value;
}

#define midictrl_event_init(chan,num,val) \
  { .time = 0, .type = EV_CONTROLLER, .channel = chan, \
    { .controller = { .number = num, .value = val } } }

#ifdef __cplusplus
}
#endif

#endif
