// ----
// ---- file   : MIDIPipeDevice.cpp
// ---- author : Bastian Spiegel <bs@tkscript.de>
// ---- legal  : (c) 2014-2019 by Bastian Spiegel. 
// ----          Distributed under terms of the GNU LESSER GENERAL PUBLIC LICENSE (LGPL). See 
// ----          http://www.gnu.org/licenses/licenses.html#LGPL or COPYING for further information.
// ----
// ---- info   : This is part of the "syntracker" sequencer.
// ----
// ---- changed: 01Sep2014, 11Sep2015, 14Sep2015, 17Jul2016, 09Sep2016, 03Dec2016
// ----          03Mar2017, 27May2017, 18Aug2017, 22Jan2019
// ----
// ----
// ----

#include "tkmidipipe.h"


MIDIPipeDevice::MIDIPipeDevice(void) {
   dev_idx = 0;
   cmd_buffer = NULL;
   note_buffer = NULL;

   memset(channels, 0xFF, sizeof(midipipe_device_ch_t) * 16);
   memset(shadow_channels, 0xFF, sizeof(midipipe_device_ch_t) * 16);

   sUI chIdx;
   for(chIdx=0; chIdx<16; chIdx++)
   {
      channels[chIdx].num_notes = 0;
      shadow_channels[chIdx].num_notes = 0;
      param_mode[chIdx] = 0; // MSBLSB
   }

   // memset(channel_resets, 0xFF, sizeof(midipipe_device_ch_t) * 16);
   b_midicache = YAC_TRUE;

   b_note_off = YAC_TRUE;
   // b_note_off = YAC_FALSE;

   b_global = YAC_FALSE;
}

MIDIPipeDevice::~MIDIPipeDevice(void) {
}

void MIDIPipeDevice::setDevIdx(sUI _devIdx) {
   dev_idx = _devIdx;
}

void MIDIPipeDevice::setBuffers(YAC_Buffer *_cmdBuffer, YAC_Buffer *_noteBuffer) {
   cmd_buffer = _cmdBuffer;
   note_buffer = _noteBuffer;
}

void MIDIPipeDevice::clearMIDICache(void) {
   // (note) do not reset note data to prevent hanging notes
   // // memset(channels, 0xFF, sizeof(midipipe_device_ch_t) * 16);
   // yac_host->printf("xxx MIDIPipeDevice::clearMIDICache: dev_idx=%u\n", dev_idx);

   for(sUI chIdx = 0; chIdx < 16u; chIdx++)
   {
      midipipe_device_ch_t *ch = &channels[chIdx];

      ch->prg         = -1;
      ch->ch_pressure = -1;
      ch->pitchbend   = -1;
      
      memset(ch->cc_states, 0xFF, sizeof(midipipe_ctl_state_t) * 128);
      memset(ch->rpn_states, 0xFF, sizeof(midipipe_ctl_state_t) * 16384);
      memset(ch->nrpn_states, 0xFF, sizeof(midipipe_ctl_state_t) * 16384);
   }
}

void MIDIPipeDevice::setEnableMIDICache(sBool _bEnable) {
   b_midicache = _bEnable;
}

sBool MIDIPipeDevice::getEnableMIDICache(void) {
   return b_midicache;
}

void MIDIPipeDevice::setEnableNoteOffMsg(sBool _bEnable) {
   b_note_off = _bEnable;
}

sBool MIDIPipeDevice::getEnableNoteOffMsg(void) {
   return b_note_off;
}

void MIDIPipeDevice::setEnableGlobal(sBool _bEnable) {
   b_global = _bEnable;
}

sBool MIDIPipeDevice::getEnableGlobal(void) {
   return b_global;
}

sSI MIDIPipeDevice::getPrg(sUI _ch) {
   if(_ch < 16)
   {
      return shadow_channels[_ch].prg;
   }
   return -1;
}

sSI MIDIPipeDevice::getChPressure(sUI _ch) {
   if(_ch < 16)
   {
      return shadow_channels[_ch].ch_pressure;
   }
   return -1;
}

sSI MIDIPipeDevice::getPitchbend(sUI _ch) {
   if(_ch < 16)
   {
      return shadow_channels[_ch].pitchbend;
   }
   return -1;
}

sSI MIDIPipeDevice::getCCState(sUI _ch, sUI _cc) {
   if( (_ch < 16) && (_cc < 128) )
   {
      return shadow_channels[_ch].cc_states[_cc].value;
   }
   return -1;
}

sSI MIDIPipeDevice::getRPNState(sUI _ch, sUI _rpn) {
   if( (_ch < 16) && (_rpn < 16384) )
   {
      return shadow_channels[_ch].rpn_states[_rpn].value;
   }
   return -1;
}

sSI MIDIPipeDevice::getNRPNState(sUI _ch, sUI _nrpn) {
   if( (_ch < 16) && (_nrpn < 16384) )
   {
      return shadow_channels[_ch].nrpn_states[_nrpn].value;
   }
   return -1;
}

sSI MIDIPipeDevice::getPolyPressure(sUI _ch, sUI _note) {
   if( (_ch < 16) && (_note < 128) )
   {
      return shadow_channels[_ch].note_states[_note].poly_pressure;
   }
   return -1;
}

void MIDIPipeDevice::setParamMode(sUI _ch, sSI _mode) {
   param_mode[_ch & 15] = _mode;
}

sSI  MIDIPipeDevice::getParamMode(sUI _ch) {
   return sSI(param_mode[_ch & 15]);
}
