// generated by Fast Light User Interface Designer (fluid) version 1.0308

#include "OscilGenUI.h"
// OscilgenUI.cc
// Original ZynAddSubFX author Nasca Octavian Paul
// Copyright (C) 2002-2005 Nasca Octavian Paul
// Copyright 2009-2010, Alan Calvert
// Copyright 2016-2022 Will Godfrey and others.

// This file is part of yoshimi, which is free software: you can redistribute
// it and/or modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.

// yoshimi is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE.   See the GNU General Public License (version 2 or
// later) for more details.

// You should have received a copy of the GNU General Public License along with
// yoshimi; if not, write to the Free Software Foundation, Inc., 51 Franklin
// Street, Fifth Floor, Boston, MA  02110-1301, USA.

// This file is a derivative of the ZynAddSubFX original.


#include <cmath>
#include "MasterUI.h"
#include "Misc/NumericFuncs.h"
    using func::decibel;
    using func::asDecibel;
using std::to_string;

OscilSpectrum::OscilSpectrum(int x,int y, int w, int h, const char *label):Fl_Box(x,y,w,h,label) {
  oscilSmp=NULL;
}

void OscilSpectrum::init(OscilGen *oscilSmp_,int oscbase_, SynthEngine *_synth) {
  //
      synth = _synth;
      oscilSmp = oscilSmp_;
      oscbase = oscbase_;
}

void OscilSpectrum::draw() {
  //
      int ox = x();
      int oy = y();
      int lx = w();
      int ly = h();
      const int maxdb = 60; // must be multiple of 10
      int GX = 2;
      int n = lx / GX - 1;
      if (n > synth->halfoscilsize)
          n = synth->halfoscilsize;
      float x;
      float* spc = new float[n];
      for (int i = 0; i < n; ++i)
          spc[i] = 0.0;
  
      if (oscbase == 0)
          oscilSmp->getOscilSpectrumIntensities(n, spc);
      else
          oscilSmp->getBasefuncSpectrumIntensities(n, spc);
  
      // normalize
      float max = 0;
      for (int i = 0; i < n; ++i)
      {
          x = fabsf(spc[i]);
          if (max < x)
              max = x;
      }
      if (max < 0.000001)
          max = 1.0;
      max = max * 1.05;
  
      // draw
      if (this->active_r())
          fl_color(this->parent()->selection_color());
      else
          fl_color(this->parent()->color());
  
      for (int i = 1; i < maxdb / 10; ++i)
      {
          int ky = int((float)i * ly * 10.0 / maxdb) / 2;
          ky *= 2;
          fl_line(ox, oy + ky - 1, ox + lx - 2, oy + ky - 1);
      }
  
      for (int i = 2; i < n; ++i)
      {
          int tmp = i * GX - 2;
          fl_line(ox + tmp, oy + 2, ox + tmp, oy + ly - 2);
      }
      if (this->active_r())
          fl_color(this->parent()->labelcolor());
      else
          fl_color(this->parent()->color());
  
      // draws the spectrum
      for (int i = 0; i < n; ++i)
      {
          int tmp = i * GX + 2;
          x = spc[i] / max;
  
          if (x > decibel(-maxdb))
              x = asDecibel(x) / maxdb + 1;
          else
              x = 0;
  
          int val = int((ly - 2) * x);
          if (val > 0)
              fl_line(ox + tmp, oy + ly - 2 - val, ox + tmp, oy + ly - 2);
      }
      delete [] spc;
}

PSlider::PSlider(int x,int y, int w, int h, const char *label):mwheel_slider(x,y,w,h,label) {
  ;
}

void PSlider::update_selection_color(int new_value) {
  const int default_val = 0; // Turn into member variable if needed
      selection_color(new_value == default_val ? 0 : 222);
}

double PSlider::value() {
  return mwheel_slider::value();
}

int PSlider::value(double val) {
  update_selection_color((int) val);
      return mwheel_slider::value(val);
}

int PSlider::handle(int event) {
  int X=x(),Y=y(),W=w(),H=h();
  
      int rval = 0;
  
      if ((!Fl::event_buttons())|| (event==0)||(Fl::event_shift()==0))
          rval = mwheel_slider::handle(event);
  
      else if (!Fl::event_inside(X,Y,W,H))
      {
          if (event==FL_DRAG)
          {
              mwheel_slider::handle(FL_RELEASE);
              mwheel_slider::handle(FL_LEAVE);
              deactivate();
              activate();
              rval = 1;
          }
          else
          {
              rval = mwheel_slider::handle(event);
          }
      }
      else
      {
         rval = mwheel_slider::handle(FL_PUSH);
      }
  
      update_selection_color((int) value());
      return rval;
}

Oscilloscope::Oscilloscope(int x,int y, int w, int h, int frame_, const char *label):Fl_Box(x,y,w,h,label) {
  //
      oscilSmp=NULL;
      phase=64;
      oscbase=0;
      frame = frame_;
}

void Oscilloscope::init(OscilGen *oscilSmp_, SynthEngine *_synth) {
  //
      synth = _synth;
      oscilSmp=oscilSmp_;
}

void Oscilloscope::init(OscilGen *oscilSmp_,int oscbase_, SynthEngine *_synth) {
  //
      synth = _synth;
      oscilSmp=oscilSmp_;
      oscbase=oscbase_;
}

void Oscilloscope::init(OscilGen *oscilSmp_,int oscbase_,int phase_, SynthEngine *_synth) {
  //
      synth = _synth;
      oscilSmp=oscilSmp_;
      oscbase=oscbase_;
      phase=phase_;
}

void Oscilloscope::draw() {
  //
      int ox = x();
      int oy = y();
      int lx = w();
      int ly = h() - 1;
      fl_line_style(0, int(1 * ly / float(frame)));
      fft::Waveform smps(synth->oscilsize);
      if (oscbase == 0)
          oscilSmp->displayWaveformForGui(smps);
      else
          oscilSmp->displayBasefuncForGui(smps);
  
      if (damage() != 1)
      {
          fl_color(0, 0, 0);
          fl_rectf(ox, oy, lx, ly);
      }
  
      // normalize
      float max = 0;
      for (int o = 0; o < synth->oscilsize; ++o)
      {
          if (max < fabsf(smps[o]))
              max = fabsf(smps[o]);
      }
      if (max < 0.00001)
          max = 1.0;
      max = -max * 1.05;
  
      // draw
      if (frame > 20)
      {
          if (this->active_r())
              fl_color(this->parent()->labelcolor());
          else
              fl_color(this->parent()->color());
          int GX = 16;
          if (lx < GX * 3)
              GX = -1;
          for (int i = 1; i < GX; i++)
          {
              int tmp = int(lx / (float)GX * i);
              fl_line(ox + tmp, oy + 2, ox + tmp, oy + ly - 2);
          }
          int GY = 8;
          if (ly < GY * 3)
              GY = -1;
          for (int i = 1; i < GY; i++)
          {
              int tmp = int(ly / (float)GY * i);
              fl_line(ox + 2, oy + tmp, ox + lx - 2, oy + tmp);
          }
      }
      fl_line_style(0, int(2 * ly / float(frame)));
      // draw the function
      fl_line(ox + 2, oy + ly / 2, ox + lx - 2, oy + ly / 2);
      if (this->active_r())
          fl_color(this->parent()->selection_color());
      else
          fl_color(this->parent()->labelcolor());
      int ph = int((phase - 64.0) / 128.0 * synth->oscilsize_f + synth->oscilsize_f);
      int lastx, lasty, nextx, nexty;
      for (int i = 1; i < lx; ++i)
      {
          int k = int(synth->oscilsize_f * (i - 1) / lx) + ph;
          float y = smps[k % synth->oscilsize] / max;
          nextx = i + ox;
          nexty = int(y * ly / 2.0) + oy + ly / 2;
          if (i == 1)
              fl_line(nextx - 1, int(y * ly / 2.0) + oy + ly / 2, nextx, nexty);
          else
              fl_line(lastx, lasty, nextx, nexty);
          lastx = nextx;
          lasty = nexty;
      }
      fl_line_style(0, 1);
}

void Oscilharmonic::cb_mag_i(PSlider* o, void*) {
  //
        int x = 64;
        if (Fl::event_button3())
        {
            if (n == 0)
                x = 127;
            o->value(64 - x);
        }
        else
            x = 64 - (int)o->value();

        send_data(TOPLEVEL::action::forceUpdate, TOPLEVEL::insert::harmonicAmplitude, n, x, TOPLEVEL::type::Integer);
}
void Oscilharmonic::cb_mag(PSlider* o, void* v) {
  ((Oscilharmonic*)(o->parent()->user_data()))->cb_mag_i(o,v);
}

void Oscilharmonic::cb_phase_i(PSlider* o, void*) {
  //
        int x = 64;
        if (Fl::event_button3())
            o->value(0);
        else
            x = 64 - (int)o->value();

        send_data(TOPLEVEL::action::forceUpdate, TOPLEVEL::insert::harmonicPhase, n, x, TOPLEVEL::type::Integer);
}
void Oscilharmonic::cb_phase(PSlider* o, void* v) {
  ((Oscilharmonic*)(o->parent()->user_data()))->cb_phase_i(o,v);
}

Fl_Group* Oscilharmonic::make_window() {
  { harmonic = new Fl_Group(0, 0, 25, 225);
    harmonic->box(FL_NO_BOX);
    harmonic->color(FL_BACKGROUND_COLOR);
    harmonic->selection_color(FL_BACKGROUND_COLOR);
    harmonic->labeltype(FL_NO_LABEL);
    harmonic->labelfont(0);
    harmonic->labelsize(10);
    harmonic->labelcolor(FL_FOREGROUND_COLOR);
    harmonic->user_data((void*)(this));
    harmonic->align(Fl_Align(FL_ALIGN_TOP));
    harmonic->when(FL_WHEN_RELEASE);
    { PSlider* o = mag = new PSlider(0, 1, 15, 122);
      mag->type(4);
      mag->box(FL_FLAT_BOX);
      mag->color(FL_BACKGROUND_COLOR);
      mag->selection_color(FL_BACKGROUND_COLOR);
      mag->labeltype(FL_NORMAL_LABEL);
      mag->labelfont(0);
      mag->labelsize(14);
      mag->labelcolor(FL_FOREGROUND_COLOR);
      mag->minimum(-63);
      mag->maximum(64);
      mag->step(1);
      mag->callback((Fl_Callback*)cb_mag);
      mag->align(Fl_Align(FL_ALIGN_BOTTOM));
      mag->when(FL_WHEN_CHANGED);
      o->value(64 - oscil->Phmag[n]);
      o->setValueType(VC_WaveHarmonicMagnitude); o->useCustomTip(true);
    } // PSlider* mag
    { PSlider* o = phase = new PSlider(0, 140, 15, 82);
      phase->type(4);
      phase->box(FL_FLAT_BOX);
      phase->color(FL_BACKGROUND_COLOR);
      phase->selection_color(FL_BACKGROUND_COLOR);
      phase->labeltype(FL_NORMAL_LABEL);
      phase->labelfont(0);
      phase->labelsize(14);
      phase->labelcolor(FL_FOREGROUND_COLOR);
      phase->minimum(64);
      phase->maximum(-63);
      phase->step(1);
      phase->callback((Fl_Callback*)cb_phase);
      phase->align(Fl_Align(FL_ALIGN_BOTTOM));
      phase->when(FL_WHEN_CHANGED);
      o->value(64 - oscil->Phphase[n]);
      o->setValueType(VC_PhaseOffset); o->useCustomTip(true);
    } // PSlider* phase
    { magblock = new Fl_Box(15, 60, 5, 5);
      magblock->box(FL_FLAT_BOX);
      magblock->color(FL_DARK3);
    } // Fl_Box* magblock
    { phaseblock = new Fl_Box(15, 178, 5, 5);
      phaseblock->box(FL_FLAT_BOX);
      phaseblock->color(FL_DARK3);
    } // Fl_Box* phaseblock
    { Fl_Box* o = number = new Fl_Box(-4, 124, 36, 15);
      number->labelfont(1);
      number->labelsize(12);
      number->align(Fl_Align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE));
      if (n < 99 || (n & 1) == 0) {char tmp[12]; snprintf(tmp, 12, "%d", n + 1); o->label(strdup(tmp));}
    } // Fl_Box* number
    harmonic->end();
  } // Fl_Group* harmonic
  return harmonic;
}

Oscilharmonic::Oscilharmonic(int x,int y, int w, int h, const char *label):Fl_Group(x,y,w,h,label) {
  //
      n=0;
      oscil=NULL;
      display=NULL;
      applybutton=NULL;
      cbwidget=NULL;
}

void Oscilharmonic::send_data(int action, int insert, int control, float value, int type) {
  //
          type |= TOPLEVEL::type::Write;
          collect_data(synth, value, action, type, control, npart, kititem, engine, insert);
}

void Oscilharmonic::init(OscilParameters *oscil_,int n_,Fl_Group *display_,Fl_Widget *oldosc_,Fl_Widget *cbwidget_,Fl_Widget *applybutton_, SynthEngine *_synth, int npart_, int kititem_, int engine_) {
  //
      synth = _synth;
      oscil=oscil_;
      n=n_;
      npart = npart_;
      kititem = kititem_;
      engine = engine_;
      display=display_;
      oldosc=oldosc_;
      cbwidget=cbwidget_;
      applybutton=applybutton_;
      make_window();
      end();
      harmonic->show();
}

void Oscilharmonic::refresh() {
  //
      mag->value(64 - oscil->Phmag[n]);
      phase->value(64 - oscil->Phphase[n]);
}

Oscilharmonic::~Oscilharmonic() {
  //
      harmonic->hide();
}

void OscilEditor::cb_osceditUI_i(Fl_Double_Window* o, void*) {
  saveWin(synth, osceditUI->w(), osceditUI->h(), osceditUI->x(), osceditUI->y(), false, "Waveform " + to_string(waveType));
OSCseen = false;
o->hide();
}
void OscilEditor::cb_osceditUI(Fl_Double_Window* o, void* v) {
  ((OscilEditor*)(o->user_data()))->cb_osceditUI_i(o,v);
}

void OscilEditor::cb_applybutton_i(Fl_Button*, void*) {
  //
        send_data(TOPLEVEL::action::forceUpdate, PADSYNTH::control::applyChanges, 1, TOPLEVEL::type::Integer);
}
void OscilEditor::cb_applybutton(Fl_Button* o, void* v) {
  ((OscilEditor*)(o->parent()->user_data()))->cb_applybutton_i(o,v);
}

void OscilEditor::cb_hrndtype_i(Fl_Choice* o, void*) {
  //
            send_data(TOPLEVEL::action::forceUpdate, OSCILLATOR::control::harmonicRandomnessType, o->value(), TOPLEVEL::type::Integer);
}
void OscilEditor::cb_hrndtype(Fl_Choice* o, void* v) {
  ((OscilEditor*)(o->parent()->parent()->parent()->user_data()))->cb_hrndtype_i(o,v);
}

void OscilEditor::cb_hrnddial_i(WidgetPDial* o, void*) {
  //
            send_data(0, OSCILLATOR::control::harmonicAmplitudeRandomness, o->value(), TOPLEVEL::type::Integer);
}
void OscilEditor::cb_hrnddial(WidgetPDial* o, void* v) {
  ((OscilEditor*)(o->parent()->parent()->parent()->user_data()))->cb_hrnddial_i(o,v);
}

void OscilEditor::cb_rndslider_i(mwheel_val_slider_rev* o, void*) {
  //
          if (Fl::event_button() == 3)
              o->value(0);

          send_data(0, OSCILLATOR::control::phaseRandomness, o->value(), TOPLEVEL::type::Integer);
}
void OscilEditor::cb_rndslider(mwheel_val_slider_rev* o, void* v) {
  ((OscilEditor*)(o->parent()->user_data()))->cb_rndslider_i(o,v);
}

void OscilEditor::cb_bfslider_i(WidgetPDial* o, void*) {
  //
          send_data(TOPLEVEL::action::forceUpdate, OSCILLATOR::control::baseFunctionParameter, o->value(), TOPLEVEL::type::Integer);
}
void OscilEditor::cb_bfslider(WidgetPDial* o, void* v) {
  ((OscilEditor*)(o->parent()->parent()->user_data()))->cb_bfslider_i(o,v);
}

void OscilEditor::cb_bftype_i(Fl_Choice* o, void*) {
  //
          send_data(TOPLEVEL::action::forceUpdate, OSCILLATOR::control::baseFunctionType, o->value(), TOPLEVEL::type::Integer);
}
void OscilEditor::cb_bftype(Fl_Choice* o, void* v) {
  ((OscilEditor*)(o->parent()->parent()->user_data()))->cb_bftype_i(o,v);
}

void OscilEditor::cb_bfmodpar1_i(WidgetPDial* o, void*) {
  //
            send_data(TOPLEVEL::action::forceUpdate, OSCILLATOR::control::baseModulationParameter1, o->value(), TOPLEVEL::type::Integer);
}
void OscilEditor::cb_bfmodpar1(WidgetPDial* o, void* v) {
  ((OscilEditor*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_bfmodpar1_i(o,v);
}

void OscilEditor::cb_bfmodpar2_i(WidgetPDial* o, void*) {
  //
            send_data(TOPLEVEL::action::forceUpdate, OSCILLATOR::control::baseModulationParameter2, o->value(), TOPLEVEL::type::Integer);
}
void OscilEditor::cb_bfmodpar2(WidgetPDial* o, void* v) {
  ((OscilEditor*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_bfmodpar2_i(o,v);
}

void OscilEditor::cb_bfmodpar3_i(WidgetPDial* o, void*) {
  //
            send_data(TOPLEVEL::action::forceUpdate, OSCILLATOR::control::baseModulationParameter3, o->value(), TOPLEVEL::type::Integer);
}
void OscilEditor::cb_bfmodpar3(WidgetPDial* o, void* v) {
  ((OscilEditor*)(o->parent()->parent()->parent()->parent()->user_data()))->cb_bfmodpar3_i(o,v);
}

void OscilEditor::cb_bfmodtype_i(Fl_Choice* o, void*) {
  //
            send_data(TOPLEVEL::action::forceUpdate, OSCILLATOR::control::baseModulationType, o->value(), TOPLEVEL::type::Integer);
}
void OscilEditor::cb_bfmodtype(Fl_Choice* o, void* v) {
  ((OscilEditor*)(o->parent()->parent()->parent()->user_data()))->cb_bfmodtype_i(o,v);
}

void OscilEditor::cb_magtype_i(Fl_Choice* o, void*) {
  //
        send_data(TOPLEVEL::action::forceUpdate, OSCILLATOR::control::magType, o->value(), TOPLEVEL::type::Integer);
}
void OscilEditor::cb_magtype(Fl_Choice* o, void* v) {
  ((OscilEditor*)(o->parent()->user_data()))->cb_magtype_i(o,v);
}

void OscilEditor::cb_useasbase_i(Fl_Button*, void*) {
  //
        if (choice(synth, "", "Yes", "No", "Clear the harmonics settings?\nThis action is not easily reversed and may cause strange Undo/Redo behaviour.") < 2)
            return;
        send_data(TOPLEVEL::action::forceUpdate, OSCILLATOR::control::useAsBaseFunction, autoclearbutton->value() > 0, TOPLEVEL::type::Integer);
}
void OscilEditor::cb_useasbase(Fl_Button* o, void* v) {
  ((OscilEditor*)(o->parent()->user_data()))->cb_useasbase_i(o,v);
}

void OscilEditor::cb_oscilClose_i(Fl_Button*, void*) {
  //
        saveWin(synth, osceditUI->w(), osceditUI->h(), osceditUI->x(), osceditUI->y(), false, "Waveform " + to_string(waveType));
        OSCseen = false;
        osceditUI->hide();
        if ((Fl::event_button() == 3))
        {
            if (forPAD)
                synth->getGuiMaster()->partui->padnoteui->padnotewindow->show();
            else
                synth->getGuiMaster()->partui->adnoteui->ADnoteVoice->show();
        };
}
void OscilEditor::cb_oscilClose(Fl_Button* o, void* v) {
  ((OscilEditor*)(o->parent()->user_data()))->cb_oscilClose_i(o,v);
}

void OscilEditor::cb_clearHarm_i(Fl_Button* o, void*) {
  //
        if (choice(synth, "", "Yes", "No", "Clear the harmonics settings?\n This action can't be reversed and may cause strange Undo/Redo behaviour.") < 2)
            return;
        send_data(TOPLEVEL::action::forceUpdate, OSCILLATOR::control::clearHarmonics, o->value(), TOPLEVEL::type::Integer);
}
void OscilEditor::cb_clearHarm(Fl_Button* o, void* v) {
  ((OscilEditor*)(o->parent()->user_data()))->cb_clearHarm_i(o,v);
}

void OscilEditor::cb_wshbutton_i(Fl_Choice* o, void*) {
  //
          send_data(TOPLEVEL::action::forceUpdate, OSCILLATOR::control::waveshapeType, o->value(), TOPLEVEL::type::Integer);
}
void OscilEditor::cb_wshbutton(Fl_Choice* o, void* v) {
  ((OscilEditor*)(o->parent()->parent()->user_data()))->cb_wshbutton_i(o,v);
}

void OscilEditor::cb_wshpar_i(WidgetPDial* o, void*) {
  //
          send_data(TOPLEVEL::action::forceUpdate, OSCILLATOR::control::waveshapeParameter, o->value(), TOPLEVEL::type::Integer);
}
void OscilEditor::cb_wshpar(WidgetPDial* o, void* v) {
  ((OscilEditor*)(o->parent()->parent()->user_data()))->cb_wshpar_i(o,v);
}

void OscilEditor::cb_autoclearbutton_i(Fl_Light_Button* o, void*) {
  // not used directly now
        (void) o; // suppress warning
        //send_data(TOPLEVEL::action::forceUpdate, OSCILLATOR::control::autoClear, o->value(), TOPLEVEL::type::Integer);
}
void OscilEditor::cb_autoclearbutton(Fl_Light_Button* o, void* v) {
  ((OscilEditor*)(o->parent()->user_data()))->cb_autoclearbutton_i(o,v);
}

void OscilEditor::cb_filtervalue1_i(WidgetPDial* o, void*) {
  //
          send_data(TOPLEVEL::action::forceUpdate, OSCILLATOR::control::filterParameter1, o->value(), TOPLEVEL::type::Integer);
}
void OscilEditor::cb_filtervalue1(WidgetPDial* o, void* v) {
  ((OscilEditor*)(o->parent()->parent()->user_data()))->cb_filtervalue1_i(o,v);
}

void OscilEditor::cb_filterpref_i(Fl_Check_Button2* o, void*) {
  //
          send_data(TOPLEVEL::action::forceUpdate, OSCILLATOR::control::filterBeforeWaveshape, o->value(), TOPLEVEL::type::Integer);
}
void OscilEditor::cb_filterpref(Fl_Check_Button2* o, void* v) {
  ((OscilEditor*)(o->parent()->parent()->user_data()))->cb_filterpref_i(o,v);
}

void OscilEditor::cb_filtervalue2_i(WidgetPDial* o, void*) {
  //
          send_data(TOPLEVEL::action::forceUpdate, OSCILLATOR::control::filterParameter2, o->value(), TOPLEVEL::type::Integer);
}
void OscilEditor::cb_filtervalue2(WidgetPDial* o, void* v) {
  ((OscilEditor*)(o->parent()->parent()->user_data()))->cb_filtervalue2_i(o,v);
}

void OscilEditor::cb_fltbutton_i(Fl_Choice* o, void*) {
  //
          send_data(TOPLEVEL::action::forceUpdate, OSCILLATOR::control::filterType, o->value(), TOPLEVEL::type::Integer);
}
void OscilEditor::cb_fltbutton(Fl_Choice* o, void* v) {
  ((OscilEditor*)(o->parent()->user_data()))->cb_fltbutton_i(o,v);
}

void OscilEditor::cb_sabutton_i(Fl_Choice* o, void*) {
  //
          send_data(TOPLEVEL::action::forceUpdate, OSCILLATOR::control::spectrumAdjustType, o->value(), TOPLEVEL::type::Integer);
}
void OscilEditor::cb_sabutton(Fl_Choice* o, void* v) {
  ((OscilEditor*)(o->parent()->parent()->user_data()))->cb_sabutton_i(o,v);
}

void OscilEditor::cb_sadjpar_i(WidgetPDial* o, void*) {
  //
          send_data(TOPLEVEL::action::forceUpdate, OSCILLATOR::control::spectrumAdjustParameter, o->value(), TOPLEVEL::type::Integer);
}
void OscilEditor::cb_sadjpar(WidgetPDial* o, void* v) {
  ((OscilEditor*)(o->parent()->parent()->user_data()))->cb_sadjpar_i(o,v);
}

void OscilEditor::cb_harmonicshiftcounter_i(Fl_Counter* o, void*) {
  //
          send_data(TOPLEVEL::action::forceUpdate, OSCILLATOR::control::harmonicShift, o->value(), TOPLEVEL::type::Integer);
}
void OscilEditor::cb_harmonicshiftcounter(Fl_Counter* o, void* v) {
  ((OscilEditor*)(o->parent()->parent()->user_data()))->cb_harmonicshiftcounter_i(o,v);
}

void OscilEditor::cb_harmonicshiftpre_i(Fl_Check_Button2* o, void*) {
  //
          send_data(TOPLEVEL::action::forceUpdate, OSCILLATOR::control::shiftBeforeWaveshapeAndFilter, o->value(), TOPLEVEL::type::Integer);
}
void OscilEditor::cb_harmonicshiftpre(Fl_Check_Button2* o, void* v) {
  ((OscilEditor*)(o->parent()->parent()->user_data()))->cb_harmonicshiftpre_i(o,v);
}

void OscilEditor::cb_adhrpow_i(WidgetPDial* o, void*) {
  //
          send_data(TOPLEVEL::action::forceUpdate, OSCILLATOR::control::adaptiveHarmonicsPower, o->value(), TOPLEVEL::type::Integer);
}
void OscilEditor::cb_adhrpow(WidgetPDial* o, void* v) {
  ((OscilEditor*)(o->parent()->parent()->user_data()))->cb_adhrpow_i(o,v);
}

void OscilEditor::cb_adhrbf_i(WidgetPDial* o, void*) {
  //
          send_data(TOPLEVEL::action::forceUpdate, OSCILLATOR::control::adaptiveHarmonicsBase, o->value(), TOPLEVEL::type::Integer);
}
void OscilEditor::cb_adhrbf(WidgetPDial* o, void* v) {
  ((OscilEditor*)(o->parent()->parent()->user_data()))->cb_adhrbf_i(o,v);
}

void OscilEditor::cb_adhrpar_i(mwheel_slider_rev* o, void*) {
  //
          if (Fl::event_button() == 3)
              o->value(50);

          send_data(TOPLEVEL::action::forceUpdate, OSCILLATOR::control::adaptiveHarmonicsParameter, o->value(), TOPLEVEL::type::Integer);
}
void OscilEditor::cb_adhrpar(mwheel_slider_rev* o, void* v) {
  ((OscilEditor*)(o->parent()->parent()->user_data()))->cb_adhrpar_i(o,v);
}

void OscilEditor::cb_adhrtype_i(Fl_Choice* o, void*) {
  //
          send_data(TOPLEVEL::action::forceUpdate, OSCILLATOR::control::adaptiveHarmonicsType, o->value(), TOPLEVEL::type::Integer);
}
void OscilEditor::cb_adhrtype(Fl_Choice* o, void* v) {
  ((OscilEditor*)(o->parent()->user_data()))->cb_adhrtype_i(o,v);
}

void OscilEditor::cb_modpar1_i(WidgetPDial* o, void*) {
  //
          send_data(TOPLEVEL::action::forceUpdate, OSCILLATOR::control::modulationParameter1, o->value(), TOPLEVEL::type::Integer);
}
void OscilEditor::cb_modpar1(WidgetPDial* o, void* v) {
  ((OscilEditor*)(o->parent()->parent()->user_data()))->cb_modpar1_i(o,v);
}

void OscilEditor::cb_modpar2_i(WidgetPDial* o, void*) {
  //
          send_data(TOPLEVEL::action::forceUpdate, OSCILLATOR::control::modulationParameter2, o->value(), TOPLEVEL::type::Integer);
}
void OscilEditor::cb_modpar2(WidgetPDial* o, void* v) {
  ((OscilEditor*)(o->parent()->parent()->user_data()))->cb_modpar2_i(o,v);
}

void OscilEditor::cb_modpar3_i(WidgetPDial* o, void*) {
  //
          send_data(TOPLEVEL::action::forceUpdate, OSCILLATOR::control::modulationParameter3, o->value(), TOPLEVEL::type::Integer);
}
void OscilEditor::cb_modpar3(WidgetPDial* o, void* v) {
  ((OscilEditor*)(o->parent()->parent()->user_data()))->cb_modpar3_i(o,v);
}

void OscilEditor::cb_modtype_i(Fl_Choice* o, void*) {
  //
          send_data(TOPLEVEL::action::forceUpdate, OSCILLATOR::control::modulationType, o->value(), TOPLEVEL::type::Integer);
}
void OscilEditor::cb_modtype(Fl_Choice* o, void* v) {
  ((OscilEditor*)(o->parent()->user_data()))->cb_modtype_i(o,v);
}

void OscilEditor::cb_tosine_i(Fl_Button* o, void*) {
  //
        if (choice(synth, "", "Yes", "No", "Convert to SINE?\nThis action can't be reversed and may cause strange Undo/Redo behaviour.") < 2)
            return;

        send_data(TOPLEVEL::action::forceUpdate, OSCILLATOR::control::convertToSine, o->value(), TOPLEVEL::type::Integer);
}
void OscilEditor::cb_tosine(Fl_Button* o, void* v) {
  ((OscilEditor*)(o->parent()->user_data()))->cb_tosine_i(o,v);
}

void OscilEditor::cb_oscilC_i(Fl_Button*, void*) {
  synth->getGuiMaster()->getPresetsUi()->copy(oscil);
}
void OscilEditor::cb_oscilC(Fl_Button* o, void* v) {
  ((OscilEditor*)(o->parent()->user_data()))->cb_oscilC_i(o,v);
}

void OscilEditor::cb_oscilP_i(Fl_Button*, void*) {
  synth->getGuiMaster()->getPresetsUi()->paste(oscil,this);
}
void OscilEditor::cb_oscilP(Fl_Button* o, void* v) {
  ((OscilEditor*)(o->parent()->user_data()))->cb_oscilP_i(o,v);
}

Fl_Double_Window* OscilEditor::make_window() {
  { Fl_Double_Window* o = osceditUI = new Fl_Double_Window(735, 595, "ADsynth Oscillator Editor");
    osceditUI->labelsize(12);
    osceditUI->callback((Fl_Callback*)cb_osceditUI, (void*)(this));
    { Fl_Box* o = applybox = new Fl_Box(298, 278, 64, 24);
      applybox->box(FL_THIN_UP_BOX);
      applybox->color((Fl_Color)237);
      if (!forPAD) o->hide();
    } // Fl_Box* applybox
    { Fl_Button* o = applybutton = new Fl_Button(301, 281, 58, 18, "Apply");
      applybutton->tooltip("Rebuild PADSynth wavetable to pick up changes");
      applybutton->box(FL_THIN_UP_BOX);
      applybutton->labelfont(1);
      applybutton->labelsize(12);
      applybutton->callback((Fl_Callback*)cb_applybutton);
      if (!forPAD) o->hide();
    } // Fl_Button* applybutton
    { oscildisplaygroup = new Fl_Group(5, 5, 360, 300);
      oscildisplaygroup->box(FL_ENGRAVED_FRAME);
      { Fl_Group* o = waveformgroup = new Fl_Group(10, 85, 350, 190);
        waveformgroup->box(FL_THIN_DOWN_BOX);
        waveformgroup->color(FL_GRAY0);
        waveformgroup->selection_color((Fl_Color)71);
        waveformgroup->labelcolor((Fl_Color)179);
        Oscilloscope *osc=new Oscilloscope(o->x(),o->y(),o->w(),o->h(), 170,"");
        osc->init(oscilSmp, synth);
        waveformgroup->end();
      } // Fl_Group* waveformgroup
      { Fl_Group* o = harmonicgroup = new Fl_Group(10, 30, 350, 50);
        harmonicgroup->box(FL_THIN_DOWN_BOX);
        harmonicgroup->color(FL_GRAY0);
        harmonicgroup->selection_color((Fl_Color)218);
        harmonicgroup->labelcolor(FL_GREEN);
        OscilSpectrum *spc=new OscilSpectrum(o->x(),o->y(),o->w(),o->h(),"");
        spc->init(oscilSmp,0, synth);
        harmonicgroup->end();
      } // Fl_Group* harmonicgroup
      { Fl_Group* o = new Fl_Group(246, 277, 115, 25);
        o->box(FL_ENGRAVED_BOX);
        { Fl_Choice* o = hrndtype = new Fl_Choice(281, 282, 50, 15, "H.rnd");
          hrndtype->tooltip("Harmonic Amplitude Randomness");
          hrndtype->down_box(FL_BORDER_BOX);
          hrndtype->labelsize(10);
          hrndtype->textfont(1);
          hrndtype->textsize(10);
          hrndtype->callback((Fl_Callback*)cb_hrndtype);
          o->add("None");o->add("Powr");o->add("Sine");
        } // Fl_Choice* hrndtype
        { hrnddial = new WidgetPDial(338, 280, 18, 18);
          hrnddial->tooltip("Oscillator\'s harmonic randomness parameter");
          hrnddial->box(FL_OVAL_BOX);
          hrnddial->color(FL_BACKGROUND_COLOR);
          hrnddial->selection_color(FL_INACTIVE_COLOR);
          hrnddial->labeltype(FL_NORMAL_LABEL);
          hrnddial->labelfont(0);
          hrnddial->labelsize(14);
          hrnddial->labelcolor(FL_FOREGROUND_COLOR);
          hrnddial->maximum(127);
          hrnddial->step(1);
          hrnddial->callback((Fl_Callback*)cb_hrnddial);
          hrnddial->align(Fl_Align(FL_ALIGN_BOTTOM));
          hrnddial->when(FL_WHEN_CHANGED);
        } // WidgetPDial* hrnddial
        if (forPAD) o->hide();
        o->end();
      } // Fl_Group* o
      oscildisplaygroup->end();
    } // Fl_Group* oscildisplaygroup
    { oscilname = new Fl_Box(120, 10, 110, 20, "Oscillator");
      oscilname->labelfont(1);
      oscilname->labelsize(12);
    } // Fl_Box* oscilname
    { mwheel_val_slider_rev* o = rndslider = new mwheel_val_slider_rev(140, 287, 100, 14, "Phase Randomness");
      rndslider->tooltip("Oscilator Phase Randomness: smaller than 0 is \"group\", larger than 0 is for\
 each harmonic");
      rndslider->type(5);
      rndslider->box(FL_THIN_DOWN_BOX);
      rndslider->color(FL_BACKGROUND_COLOR);
      rndslider->selection_color(FL_BACKGROUND_COLOR);
      rndslider->labeltype(FL_NORMAL_LABEL);
      rndslider->labelfont(0);
      rndslider->labelsize(10);
      rndslider->labelcolor(FL_FOREGROUND_COLOR);
      rndslider->minimum(-64);
      rndslider->maximum(63);
      rndslider->step(1);
      rndslider->textfont(1);
      rndslider->textsize(11);
      rndslider->callback((Fl_Callback*)cb_rndslider);
      rndslider->align(Fl_Align(FL_ALIGN_TOP));
      rndslider->when(FL_WHEN_CHANGED);
      if (forPAD) o->hide();
    } // mwheel_val_slider_rev* rndslider
    { basefuncdisplaygroup = new Fl_Group(365, 5, 360, 300);
      basefuncdisplaygroup->box(FL_ENGRAVED_FRAME);
      { Fl_Group* o = basewave = new Fl_Group(370, 85, 350, 190);
        basewave->box(FL_THIN_DOWN_BOX);
        basewave->color(FL_GRAY0);
        basewave->selection_color((Fl_Color)71);
        basewave->labelcolor((Fl_Color)179);
        Oscilloscope *osc=new Oscilloscope(o->x(),o->y(),o->w(),o->h(), 170,"");
        osc->init(oscilSmp,1, synth);
        basewave->end();
      } // Fl_Group* basewave
      { bfslider = new WidgetPDial(520, 280, 20, 20);
        bfslider->tooltip("Base Function Parameter");
        bfslider->box(FL_OVAL_BOX);
        bfslider->color(FL_BACKGROUND_COLOR);
        bfslider->selection_color(FL_INACTIVE_COLOR);
        bfslider->labeltype(FL_NORMAL_LABEL);
        bfslider->labelfont(0);
        bfslider->labelsize(14);
        bfslider->labelcolor(FL_FOREGROUND_COLOR);
        bfslider->minimum(-64);
        bfslider->maximum(63);
        bfslider->step(1);
        bfslider->callback((Fl_Callback*)cb_bfslider);
        bfslider->align(Fl_Align(FL_ALIGN_BOTTOM));
        bfslider->when(FL_WHEN_CHANGED);
      } // WidgetPDial* bfslider
      { Fl_Choice* o = bftype = new Fl_Choice(370, 285, 90, 15, "Base Function");
        bftype->down_box(FL_BORDER_BOX);
        bftype->labelsize(10);
        bftype->textfont(1);
        bftype->textsize(11);
        bftype->callback((Fl_Callback*)cb_bftype);
        bftype->align(Fl_Align(FL_ALIGN_TOP));
        o->add("Sine");o->add("Triangle");o->add("Pulse");o->add("Saw");o->add("Power");o->add("Gauss");o->add("Diode");o->add("AbsSine");o->add("PulseSine");o->add("StrchSine");o->add("Chirp");o->add("AbsStrSine");o->add("Chebyshev");o->add("Square");o->add("Spike");o->add("Circle");o->add("HyperSec");o->add("User");
      } // Fl_Choice* bftype
      { basename = new Fl_Box(480, 10, 110, 20, "Base Function");
        basename->box(FL_FLAT_BOX);
        basename->labelfont(1);
        basename->labelsize(12);
      } // Fl_Box* basename
      { Fl_Group* o = baseharm = new Fl_Group(370, 30, 350, 50);
        baseharm->box(FL_THIN_DOWN_BOX);
        baseharm->color(FL_GRAY0);
        baseharm->selection_color((Fl_Color)218);
        baseharm->labelcolor(FL_GREEN);
        OscilSpectrum *spc=new OscilSpectrum (o->x(),o->y(),o->w(),o->h(),"");
        spc->init(oscilSmp,1, synth);
        baseharm->end();
      } // Fl_Group* baseharm
      { parname = new Fl_Box(460, 285, 30, 16, "Par.");
        parname->box(FL_FLAT_BOX);
        parname->labelsize(11);
      } // Fl_Box* parname
      { bfparval = new Fl_Value_Output(490, 285, 28, 15);
        bfparval->labelsize(12);
        bfparval->minimum(-63);
        bfparval->maximum(63);
        bfparval->step(1);
        bfparval->textfont(1);
        bfparval->textsize(12);
        bfparval->align(Fl_Align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE));
      } // Fl_Value_Output* bfparval
      { basefuncmodulation = new Fl_Group(550, 276, 169, 25);
        basefuncmodulation->box(FL_ENGRAVED_BOX);
        { baseFuncPars = new Fl_Group(652, 278, 66, 21);
          { bfmodpar1 = new WidgetPDial(654, 280, 17, 17);
            bfmodpar1->tooltip("Oscillator\'s modulation parameter 1");
            bfmodpar1->box(FL_OVAL_BOX);
            bfmodpar1->color(FL_BACKGROUND_COLOR);
            bfmodpar1->selection_color(FL_INACTIVE_COLOR);
            bfmodpar1->labeltype(FL_NORMAL_LABEL);
            bfmodpar1->labelfont(0);
            bfmodpar1->labelsize(14);
            bfmodpar1->labelcolor(FL_FOREGROUND_COLOR);
            bfmodpar1->maximum(127);
            bfmodpar1->step(1);
            bfmodpar1->callback((Fl_Callback*)cb_bfmodpar1);
            bfmodpar1->align(Fl_Align(FL_ALIGN_BOTTOM));
            bfmodpar1->when(FL_WHEN_CHANGED);
          } // WidgetPDial* bfmodpar1
          { bfmodpar2 = new WidgetPDial(676, 280, 17, 17);
            bfmodpar2->tooltip("Oscillator\'s modulation parameter 2");
            bfmodpar2->box(FL_OVAL_BOX);
            bfmodpar2->color(FL_BACKGROUND_COLOR);
            bfmodpar2->selection_color(FL_INACTIVE_COLOR);
            bfmodpar2->labeltype(FL_NORMAL_LABEL);
            bfmodpar2->labelfont(0);
            bfmodpar2->labelsize(14);
            bfmodpar2->labelcolor(FL_FOREGROUND_COLOR);
            bfmodpar2->maximum(127);
            bfmodpar2->step(1);
            bfmodpar2->callback((Fl_Callback*)cb_bfmodpar2);
            bfmodpar2->align(Fl_Align(FL_ALIGN_BOTTOM));
            bfmodpar2->when(FL_WHEN_CHANGED);
          } // WidgetPDial* bfmodpar2
          { bfmodpar3 = new WidgetPDial(698, 280, 17, 17);
            bfmodpar3->tooltip("Oscillator\'s modulation parameter 3");
            bfmodpar3->box(FL_OVAL_BOX);
            bfmodpar3->color(FL_BACKGROUND_COLOR);
            bfmodpar3->selection_color(FL_INACTIVE_COLOR);
            bfmodpar3->labeltype(FL_NORMAL_LABEL);
            bfmodpar3->labelfont(0);
            bfmodpar3->labelsize(14);
            bfmodpar3->labelcolor(FL_FOREGROUND_COLOR);
            bfmodpar3->maximum(127);
            bfmodpar3->step(1);
            bfmodpar3->callback((Fl_Callback*)cb_bfmodpar3);
            bfmodpar3->align(Fl_Align(FL_ALIGN_BOTTOM));
            bfmodpar3->when(FL_WHEN_CHANGED);
          } // WidgetPDial* bfmodpar3
          baseFuncPars->end();
        } // Fl_Group* baseFuncPars
        { Fl_Choice* o = bfmodtype = new Fl_Choice(599, 281, 50, 15, "B.F.Mod.");
          bfmodtype->tooltip("Base function modulation");
          bfmodtype->down_box(FL_BORDER_BOX);
          bfmodtype->labelsize(10);
          bfmodtype->textfont(1);
          bfmodtype->textsize(10);
          bfmodtype->callback((Fl_Callback*)cb_bfmodtype);
          o->add("None");o->add("Rev");o->add("Sine");o->add("Powr");
        } // Fl_Choice* bfmodtype
        if ((oscil->Pcurrentbasefunc == OSCILLATOR::wave::sine)||(oscil->Pcurrentbasefunc > OSCILLATOR::wave::hyperSec)) basefuncmodulation->deactivate();
        basefuncmodulation->end();
      } // Fl_Group* basefuncmodulation
      basefuncdisplaygroup->end();
    } // Fl_Group* basefuncdisplaygroup
    { Warning = new Fl_Output(224, 8, 248, 20);
      Warning->box(FL_FLAT_BOX);
      Warning->color((Fl_Color)29);
      Warning->textfont(1);
      Warning->textcolor((Fl_Color)1);
      Warning->align(Fl_Align(FL_ALIGN_TEXT_OVER_IMAGE));
    } // Fl_Output* Warning
    { Fl_Choice* o = magtype = new Fl_Choice(70, 280, 65, 20, "Mag.Type");
      magtype->down_box(FL_BORDER_BOX);
      magtype->labelsize(11);
      magtype->textfont(1);
      magtype->textsize(11);
      magtype->callback((Fl_Callback*)cb_magtype);
      o->add("Linear");o->add("-40dB");o->add("-60dB");o->add("-80dB");o->add("-100dB");
    } // Fl_Choice* magtype
    { useasbase = new Fl_Button(5, 313, 85, 20, "Use as base");
      useasbase->tooltip("Use this Oscillator as base function");
      useasbase->box(FL_THIN_UP_BOX);
      useasbase->labelfont(1);
      useasbase->labelsize(11);
      useasbase->callback((Fl_Callback*)cb_useasbase);
    } // Fl_Button* useasbase
    { oscilClose = new Fl_Button(668, 565, 62, 25, "Close");
      oscilClose->tooltip("Right click: also reopen previous");
      oscilClose->box(FL_THIN_UP_BOX);
      oscilClose->callback((Fl_Callback*)cb_oscilClose);
    } // Fl_Button* oscilClose
    { clearHarm = new Fl_Button(670, 505, 55, 15, "Clear");
      clearHarm->box(FL_THIN_UP_BOX);
      clearHarm->labelfont(1);
      clearHarm->labelsize(11);
      clearHarm->callback((Fl_Callback*)cb_clearHarm);
    } // Fl_Button* clearHarm
    { Fl_Group* o = new Fl_Group(135, 308, 150, 30);
      o->box(FL_ENGRAVED_BOX);
      { Fl_Choice* o = wshbutton = new Fl_Choice(165, 313, 55, 20, "Wsh.");
        wshbutton->tooltip("Waveshaping function");
        wshbutton->down_box(FL_BORDER_BOX);
        wshbutton->labelsize(10);
        wshbutton->textfont(1);
        wshbutton->textsize(10);
        wshbutton->callback((Fl_Callback*)cb_wshbutton);
        o->add("None");o->add("Atan");o->add("Asym1");o->add("Powr");o->add("Sine");o->add("Qnts");o->add("Zigzg");o->add("Limt");o->add("LimtU");o->add("");o->add("ILimt");o->add("Clip");o->add("Asym2");o->add("Powr2");o->add("Sgm");
      } // Fl_Choice* wshbutton
      { wshpar = new WidgetPDial(260, 313, 20, 20);
        wshpar->tooltip("Waveshaping Parameter");
        wshpar->box(FL_OVAL_BOX);
        wshpar->color(FL_BACKGROUND_COLOR);
        wshpar->selection_color(FL_INACTIVE_COLOR);
        wshpar->labeltype(FL_NORMAL_LABEL);
        wshpar->labelfont(0);
        wshpar->labelsize(14);
        wshpar->labelcolor(FL_FOREGROUND_COLOR);
        wshpar->minimum(-64);
        wshpar->maximum(63);
        wshpar->step(1);
        wshpar->callback((Fl_Callback*)cb_wshpar);
        wshpar->align(Fl_Align(FL_ALIGN_BOTTOM));
        wshpar->when(FL_WHEN_CHANGED);
      } // WidgetPDial* wshpar
      { wsparval = new Fl_Value_Output(228, 316, 25, 15);
        wsparval->labelsize(12);
        wsparval->minimum(-63);
        wsparval->maximum(63);
        wsparval->step(1);
      } // Fl_Value_Output* wsparval
      o->end();
    } // Fl_Group* o
    { autoclearbutton = new Fl_Light_Button(95, 313, 35, 20, "Clr.");
      autoclearbutton->tooltip("Auto clear when using the oscillator as base function");
      autoclearbutton->box(FL_THIN_UP_BOX);
      autoclearbutton->value(1);
      autoclearbutton->labelfont(1);
      autoclearbutton->labelsize(10);
      autoclearbutton->callback((Fl_Callback*)cb_autoclearbutton);
    } // Fl_Light_Button* autoclearbutton
    { filterGroup = new Fl_Group(285, 308, 155, 30);
      filterGroup->box(FL_ENGRAVED_BOX);
      { filtervalue1 = new WidgetPDial(367, 313, 20, 20);
        filtervalue1->tooltip("Oscillator\'s filter parameter1");
        filtervalue1->box(FL_OVAL_BOX);
        filtervalue1->color(FL_BACKGROUND_COLOR);
        filtervalue1->selection_color(FL_INACTIVE_COLOR);
        filtervalue1->labeltype(FL_NORMAL_LABEL);
        filtervalue1->labelfont(0);
        filtervalue1->labelsize(14);
        filtervalue1->labelcolor(FL_FOREGROUND_COLOR);
        filtervalue1->maximum(127);
        filtervalue1->step(1);
        filtervalue1->callback((Fl_Callback*)cb_filtervalue1);
        filtervalue1->align(Fl_Align(FL_ALIGN_BOTTOM));
        filtervalue1->when(FL_WHEN_CHANGED);
      } // WidgetPDial* filtervalue1
      { filterpref = new Fl_Check_Button2(415, 313, 20, 20, "F");
        filterpref->tooltip("Apply the filter before the waveshaping");
        filterpref->box(FL_NO_BOX);
        filterpref->down_box(FL_DOWN_BOX);
        filterpref->color(FL_BACKGROUND_COLOR);
        filterpref->selection_color(FL_FOREGROUND_COLOR);
        filterpref->labeltype(FL_NORMAL_LABEL);
        filterpref->labelfont(0);
        filterpref->labelsize(10);
        filterpref->labelcolor(FL_FOREGROUND_COLOR);
        filterpref->callback((Fl_Callback*)cb_filterpref);
        filterpref->align(Fl_Align(FL_ALIGN_RIGHT|FL_ALIGN_INSIDE));
        filterpref->when(FL_WHEN_RELEASE);
      } // Fl_Check_Button2* filterpref
      { filtervalue2 = new WidgetPDial(392, 313, 20, 20);
        filtervalue2->tooltip("Oscillator\'s filter parameter2");
        filtervalue2->box(FL_OVAL_BOX);
        filtervalue2->color(FL_BACKGROUND_COLOR);
        filtervalue2->selection_color(FL_INACTIVE_COLOR);
        filtervalue2->labeltype(FL_NORMAL_LABEL);
        filtervalue2->labelfont(0);
        filtervalue2->labelsize(14);
        filtervalue2->labelcolor(FL_FOREGROUND_COLOR);
        filtervalue2->maximum(127);
        filtervalue2->step(1);
        filtervalue2->callback((Fl_Callback*)cb_filtervalue2);
        filtervalue2->align(Fl_Align(FL_ALIGN_BOTTOM));
        filtervalue2->when(FL_WHEN_CHANGED);
      } // WidgetPDial* filtervalue2
      filterGroup->end();
    } // Fl_Group* filterGroup
    { Fl_Choice* o = fltbutton = new Fl_Choice(315, 313, 50, 20, "Filter");
      fltbutton->tooltip("Oscillator\'s filter type");
      fltbutton->down_box(FL_BORDER_BOX);
      fltbutton->labelsize(10);
      fltbutton->textfont(1);
      fltbutton->textsize(10);
      fltbutton->callback((Fl_Callback*)cb_fltbutton);
      o->add("None");o->add("LP1");o->add("HP1a");o->add("HP1b");o->add("BP1");o->add("BS1");o->add("LP2");o->add("HP2");o->add("BP2");o->add("BS2");o->add("Cosn");o->add("Sine");o->add("LSh");o->add("S");
    } // Fl_Choice* fltbutton
    { Fl_Group* o = new Fl_Group(594, 308, 136, 30);
      o->box(FL_ENGRAVED_BOX);
      { Fl_Choice* o = sabutton = new Fl_Choice(634, 313, 60, 20, "Sp.adj.");
        sabutton->tooltip("Oscillator\'s spectrum adjust");
        sabutton->down_box(FL_BORDER_BOX);
        sabutton->labelsize(10);
        sabutton->textfont(1);
        sabutton->textsize(10);
        sabutton->callback((Fl_Callback*)cb_sabutton);
        o->add("None");o->add("Pow");o->add("ThrsD");o->add("ThrsU");
      } // Fl_Choice* sabutton
      { sadjpar = new WidgetPDial(699, 313, 20, 20);
        sadjpar->tooltip("Oscillator\'s spectrum adjust parameter");
        sadjpar->box(FL_OVAL_BOX);
        sadjpar->color(FL_BACKGROUND_COLOR);
        sadjpar->selection_color(FL_INACTIVE_COLOR);
        sadjpar->labeltype(FL_NORMAL_LABEL);
        sadjpar->labelfont(0);
        sadjpar->labelsize(14);
        sadjpar->labelcolor(FL_FOREGROUND_COLOR);
        sadjpar->maximum(127);
        sadjpar->step(1);
        sadjpar->callback((Fl_Callback*)cb_sadjpar);
        sadjpar->align(Fl_Align(FL_ALIGN_BOTTOM));
        sadjpar->when(FL_WHEN_CHANGED);
      } // WidgetPDial* sadjpar
      o->end();
    } // Fl_Group* o
    { Fl_Group* o = new Fl_Group(665, 340, 65, 65);
      o->box(FL_ENGRAVED_BOX);
      { harmonicshiftcounter = new Fl_Counter(670, 365, 55, 15, "Harmonic Shift");
        harmonicshiftcounter->type(1);
        harmonicshiftcounter->labelsize(10);
        harmonicshiftcounter->minimum(-64);
        harmonicshiftcounter->maximum(64);
        harmonicshiftcounter->step(1);
        harmonicshiftcounter->textfont(1);
        harmonicshiftcounter->textsize(10);
        harmonicshiftcounter->callback((Fl_Callback*)cb_harmonicshiftcounter);
        harmonicshiftcounter->align(Fl_Align(129));
      } // Fl_Counter* harmonicshiftcounter
      { harmonicshiftpre = new Fl_Check_Button2(668, 383, 56, 20, "Shift 1st");
        harmonicshiftpre->tooltip("Apply the harmonic shift before the waveshaping and filtering");
        harmonicshiftpre->box(FL_NO_BOX);
        harmonicshiftpre->down_box(FL_DOWN_BOX);
        harmonicshiftpre->color(FL_BACKGROUND_COLOR);
        harmonicshiftpre->selection_color(FL_FOREGROUND_COLOR);
        harmonicshiftpre->labeltype(FL_NORMAL_LABEL);
        harmonicshiftpre->labelfont(0);
        harmonicshiftpre->labelsize(10);
        harmonicshiftpre->labelcolor(FL_FOREGROUND_COLOR);
        harmonicshiftpre->callback((Fl_Callback*)cb_harmonicshiftpre);
        harmonicshiftpre->align(Fl_Align(FL_ALIGN_RIGHT|FL_ALIGN_INSIDE));
        harmonicshiftpre->when(FL_WHEN_RELEASE);
      } // Fl_Check_Button2* harmonicshiftpre
      o->end();
    } // Fl_Group* o
    { adaptiveGroup = new Fl_Group(665, 410, 65, 90);
      adaptiveGroup->box(FL_ENGRAVED_FRAME);
      { adhrpow = new WidgetPDial(700, 460, 25, 25, "pow");
        adhrpow->tooltip("Adaptive harmonics power");
        adhrpow->box(FL_OVAL_BOX);
        adhrpow->color(FL_BACKGROUND_COLOR);
        adhrpow->selection_color(FL_INACTIVE_COLOR);
        adhrpow->labeltype(FL_NORMAL_LABEL);
        adhrpow->labelfont(0);
        adhrpow->labelsize(10);
        adhrpow->labelcolor(FL_FOREGROUND_COLOR);
        adhrpow->maximum(200);
        adhrpow->step(1);
        adhrpow->callback((Fl_Callback*)cb_adhrpow);
        adhrpow->align(Fl_Align(FL_ALIGN_BOTTOM));
        adhrpow->when(FL_WHEN_CHANGED);
      } // WidgetPDial* adhrpow
      { adhrbf = new WidgetPDial(670, 460, 25, 25, "baseF");
        adhrbf->tooltip("Adaptive harmonics base frequency");
        adhrbf->box(FL_OVAL_BOX);
        adhrbf->color(FL_BACKGROUND_COLOR);
        adhrbf->selection_color(FL_INACTIVE_COLOR);
        adhrbf->labeltype(FL_NORMAL_LABEL);
        adhrbf->labelfont(0);
        adhrbf->labelsize(10);
        adhrbf->labelcolor(FL_FOREGROUND_COLOR);
        adhrbf->maximum(255);
        adhrbf->step(1);
        adhrbf->callback((Fl_Callback*)cb_adhrbf);
        adhrbf->align(Fl_Align(FL_ALIGN_BOTTOM));
        adhrbf->when(FL_WHEN_CHANGED);
      } // WidgetPDial* adhrbf
      { adhrpar = new mwheel_slider_rev(667, 444, 60, 13);
        adhrpar->tooltip("Adaptive harmonics parameter");
        adhrpar->type(5);
        adhrpar->box(FL_THIN_DOWN_BOX);
        adhrpar->color(FL_BACKGROUND_COLOR);
        adhrpar->selection_color(FL_BACKGROUND_COLOR);
        adhrpar->labeltype(FL_NORMAL_LABEL);
        adhrpar->labelfont(0);
        adhrpar->labelsize(14);
        adhrpar->labelcolor(FL_FOREGROUND_COLOR);
        adhrpar->maximum(100);
        adhrpar->step(1);
        adhrpar->value(50);
        adhrpar->callback((Fl_Callback*)cb_adhrpar);
        adhrpar->align(Fl_Align(FL_ALIGN_BOTTOM));
        adhrpar->when(FL_WHEN_CHANGED);
      } // mwheel_slider_rev* adhrpar
      adaptiveGroup->end();
    } // Fl_Group* adaptiveGroup
    { Fl_Choice* o = adhrtype = new Fl_Choice(670, 425, 55, 15, "Adpt.Harm.");
      adhrtype->tooltip("The type of the adaptive harmonics");
      adhrtype->down_box(FL_BORDER_BOX);
      adhrtype->labelsize(10);
      adhrtype->textfont(1);
      adhrtype->textsize(10);
      adhrtype->callback((Fl_Callback*)cb_adhrtype);
      adhrtype->align(Fl_Align(129));
      adhrtype->when(FL_WHEN_RELEASE_ALWAYS);
      o->add("OFF");o->add("ON");o->add("Square");o->add("2xSub");o->add("2xAdd");o->add("3xSub");o->add("3xAdd");o->add("4xSub");o->add("4xAdd");
    } // Fl_Choice* adhrtype
    { modulationGroup = new Fl_Group(440, 308, 154, 30);
      modulationGroup->box(FL_ENGRAVED_BOX);
      { modpar1 = new WidgetPDial(524, 314, 18, 18);
        modpar1->tooltip("Oscillator\'s modulation parameter 1");
        modpar1->box(FL_OVAL_BOX);
        modpar1->color(FL_BACKGROUND_COLOR);
        modpar1->selection_color(FL_INACTIVE_COLOR);
        modpar1->labeltype(FL_NORMAL_LABEL);
        modpar1->labelfont(0);
        modpar1->labelsize(14);
        modpar1->labelcolor(FL_FOREGROUND_COLOR);
        modpar1->maximum(127);
        modpar1->step(1);
        modpar1->callback((Fl_Callback*)cb_modpar1);
        modpar1->align(Fl_Align(FL_ALIGN_BOTTOM));
        modpar1->when(FL_WHEN_CHANGED);
      } // WidgetPDial* modpar1
      { modpar2 = new WidgetPDial(546, 314, 18, 18);
        modpar2->tooltip("Oscillator\'s modulation parameter 2");
        modpar2->box(FL_OVAL_BOX);
        modpar2->color(FL_BACKGROUND_COLOR);
        modpar2->selection_color(FL_INACTIVE_COLOR);
        modpar2->labeltype(FL_NORMAL_LABEL);
        modpar2->labelfont(0);
        modpar2->labelsize(14);
        modpar2->labelcolor(FL_FOREGROUND_COLOR);
        modpar2->maximum(127);
        modpar2->step(1);
        modpar2->callback((Fl_Callback*)cb_modpar2);
        modpar2->align(Fl_Align(FL_ALIGN_BOTTOM));
        modpar2->when(FL_WHEN_CHANGED);
      } // WidgetPDial* modpar2
      { modpar3 = new WidgetPDial(569, 314, 18, 18);
        modpar3->tooltip("Oscillator\'s modulation parameter 3");
        modpar3->box(FL_OVAL_BOX);
        modpar3->color(FL_BACKGROUND_COLOR);
        modpar3->selection_color(FL_INACTIVE_COLOR);
        modpar3->labeltype(FL_NORMAL_LABEL);
        modpar3->labelfont(0);
        modpar3->labelsize(14);
        modpar3->labelcolor(FL_FOREGROUND_COLOR);
        modpar3->maximum(127);
        modpar3->step(1);
        modpar3->callback((Fl_Callback*)cb_modpar3);
        modpar3->align(Fl_Align(FL_ALIGN_BOTTOM));
        modpar3->when(FL_WHEN_CHANGED);
      } // WidgetPDial* modpar3
      modulationGroup->end();
    } // Fl_Group* modulationGroup
    { Fl_Choice* o = modtype = new Fl_Choice(470, 315, 50, 15, "Mod.");
      modtype->tooltip("modulation");
      modtype->down_box(FL_BORDER_BOX);
      modtype->labelsize(10);
      modtype->textfont(1);
      modtype->textsize(10);
      modtype->callback((Fl_Callback*)cb_modtype);
      o->add("None");o->add("Rev");o->add("Sine");o->add("Powr");
    } // Fl_Choice* modtype
    { tosine = new Fl_Button(670, 525, 55, 15, "Sine");
      tosine->box(FL_THIN_UP_BOX);
      tosine->labelfont(1);
      tosine->labelsize(11);
      tosine->callback((Fl_Callback*)cb_tosine);
    } // Fl_Button* tosine
    { oscilC = new Fl_Button(670, 545, 25, 15, "C");
      oscilC->box(FL_THIN_UP_BOX);
      oscilC->color((Fl_Color)179);
      oscilC->labelfont(1);
      oscilC->labelsize(11);
      oscilC->labelcolor(FL_BACKGROUND2_COLOR);
      oscilC->callback((Fl_Callback*)cb_oscilC);
    } // Fl_Button* oscilC
    { oscilP = new Fl_Button(700, 545, 25, 15, "P");
      oscilP->box(FL_THIN_UP_BOX);
      oscilP->color((Fl_Color)179);
      oscilP->labelfont(1);
      oscilP->labelsize(11);
      oscilP->labelcolor(FL_BACKGROUND2_COLOR);
      oscilP->callback((Fl_Callback*)cb_oscilP);
    } // Fl_Button* oscilP
    { frame = new Fl_Scroll(5, 340, 660, 250);
      frame->type(1);
      frame->box(FL_ENGRAVED_FRAME);
      { Fl_Pack* o = harmonics = new Fl_Pack(10, 345, 650, 225);
        harmonics->type(1);
        for (int i=0; i<MAX_AD_HARMONICS; ++i){h[i]=new Oscilharmonic(0,0,20,o->h(),"");h[i]->init(oscil,i,oscildisplaygroup,oldosc,cbwidget,applybutton, synth, npart, kititem, engine);}
        harmonics->end();
      } // Fl_Pack* harmonics
      frame->end();
    } // Fl_Scroll* frame
    string tname;
    setWindowTitle();
    waveDW = o->w() * 9 / 10; waveDH = o->h() * 9 / 10;
    o->size_range(waveDW, waveDH, 0, 0, 0, 0, 1);
    osceditUI->end();
    osceditUI->resizable(osceditUI);
  } // Fl_Double_Window* osceditUI
  return osceditUI;
}

void OscilEditor::send_data(int action, int control, float value, int type) {
  //
          int insert = TOPLEVEL::insert::oscillatorGroup;
          if (control == PADSYNTH::control::applyChanges)
              insert = UNUSED;
          type |= TOPLEVEL::type::Write;
          collect_data(synth, value, action, type, control, npart, kititem, engine, insert);
}

void OscilEditor::returns_update(CommandBlock *getData) {
  //
      float value = getData->data.value;
      unsigned char control = getData->data.control;
      //unsigned char eng = getData->data.engine;
      unsigned char insert = getData->data.insert;
  
      //if (eng != engine)
          //return;
  
      int tmp;
      bool set = true;
      bool baseSet = false;
      if (insert == TOPLEVEL::insert::harmonicAmplitude)
      {
          h[control]->mag->value(64 - value);
      }
  
      else if (insert == TOPLEVEL::insert::harmonicPhase)
      {
          h[control]->phase->value(64 - value);
      }
  
      else
      {
          switch (control)
          {
              case OSCILLATOR::control::phaseRandomness:
                  rndslider->value(value);
                  break;
  
              case OSCILLATOR::control::magType:
                  magtype->value(value);
                  break;
  
              case OSCILLATOR::control::harmonicAmplitudeRandomness:
                  hrnddial->value(value);
                  break;
  
              case OSCILLATOR::control::harmonicRandomnessType:
                  hrndtype->value(value);
                  if (value < 0.5f)
                      hrnddial->deactivate();
                  else
                      hrnddial->activate();
                  break;
  
              case OSCILLATOR::control::baseFunctionParameter:
                  bfslider->value(value);
                  bfparval->value(value);
                  baseSet = true;
                  break;
  
              case OSCILLATOR::control::baseFunctionType:
                  bftype->value(value);
                  if (value < OSCILLATOR::wave::triangle || oscil->Pcurrentbasefunc > OSCILLATOR::wave::hyperSec)
                  {
                      bfslider->deactivate();
                      basefuncmodulation->deactivate();
                  }
                  else
                  {
                      bfslider->activate();
                      basefuncmodulation->activate();
                  }
                  baseSet = true;
                  break;
  
              case OSCILLATOR::control::baseModulationParameter1:
                  bfmodpar1->value(value);
                  baseSet = true;
                  redrawoscil();
                  break;
  
              case OSCILLATOR::control::baseModulationParameter2:
                  bfmodpar2->value(value);
                  baseSet = true;
                  redrawoscil();
                  break;
  
              case OSCILLATOR::control::baseModulationParameter3:
                  bfmodpar3->value(value);
                  baseSet = true;
                  redrawoscil();
                  break;
  
              case OSCILLATOR::control::baseModulationType:
                  bfmodtype->value(value);
                  if (value< 0.5f)
                      baseFuncPars->deactivate();
                  else
                      baseFuncPars->activate();
                  baseSet = true;
                  redrawoscil();
                  break;
  
              case OSCILLATOR::control::useAsBaseFunction:
                  bftype->value(OSCILLATOR::wave::hyperSec + 1);
                  tmp = (value != 0);
                  autoclearbutton->value(tmp);
                  if (tmp)
                  {
                      for (int i = 0; i<MAX_AD_HARMONICS; ++i)
                      {
                          h[i]->mag->value(0);
                          h[i]->phase->value(0);
                      }
                      harmonicshiftcounter->value(0);
                      h[0]->mag->value(0);
                      wshbutton->value(0);
                      fltbutton->value(0);
                      sabutton->value(0);
                  }
                  baseSet = true;
                  set = false;
                  break;
  
              case OSCILLATOR::control::waveshapeParameter:
                  wshpar->value(value);
                  wsparval->value(value);
                  break;
  
              case OSCILLATOR::control::waveshapeType:
                  wshbutton->value(value);
                  if (value < 0.5f)
                      wshpar->deactivate();
                  else
                      wshpar->activate();
                  break;
  
              case OSCILLATOR::control::filterParameter1:
                  filtervalue1->value(value);
                  break;
  
              case OSCILLATOR::control::filterParameter2:
                  filtervalue2->value(value);
                  break;
  
              case OSCILLATOR::control::filterBeforeWaveshape:
                  filterpref->value(value != 0);
                  break;
  
              case OSCILLATOR::control::filterType:
                  fltbutton->value((int)value);
                  if (value < 0.5f)
                      filterGroup->deactivate();
                  else
                      filterGroup->activate();
                  break;
  
              case OSCILLATOR::control::modulationParameter1:
                  modpar1->value(value);
                  break;
  
              case OSCILLATOR::control::modulationParameter2:
                  modpar2->value(value);
                  break;
  
              case OSCILLATOR::control::modulationParameter3:
                  modpar3->value(value);
                  break;
  
              case OSCILLATOR::control::modulationType:
                  modtype->value((int)value);
                  if (value < 0.5f)
                      modulationGroup->deactivate();
                  else
                      modulationGroup->activate();
                  break;
  
              case OSCILLATOR::control::spectrumAdjustParameter:
                  sadjpar->value(value);
                  break;
  
              case OSCILLATOR::control::spectrumAdjustType:
                  sabutton->value((int)value);
                  if (value < 0.5f)
                      sadjpar->deactivate();
                  else
                      sadjpar->activate();
                  break;
  
              case OSCILLATOR::control::harmonicShift:
                  harmonicshiftcounter->value((int)value);
                  break;
  
              case OSCILLATOR::control::clearHarmonicShift:
                  harmonicshiftcounter->value(127);
                  break;
  
              case OSCILLATOR::control::shiftBeforeWaveshapeAndFilter:
                  harmonicshiftpre->value(value != 0);
                  break;
  
              case OSCILLATOR::control::adaptiveHarmonicsParameter:
                  adhrpar->value(value);
                  break;
  
              case OSCILLATOR::control::adaptiveHarmonicsBase:
                  adhrbf->value(value);
                  break;
  
              case OSCILLATOR::control::adaptiveHarmonicsPower:
                  adhrpow->value(value);
                  break;
  
              case OSCILLATOR::control::adaptiveHarmonicsType:
                  adhrtype->value((int)value);
                  if (value < 0.5f)
                      adaptiveGroup->deactivate();
                  else
                      adaptiveGroup->activate();
                  break;
  
              case OSCILLATOR::control::clearHarmonics:
                  for (int i = 0; i < MAX_AD_HARMONICS; ++i)
                  {
                      h[i]->mag->value(0);
                      h[i]->phase->value(0);
                  }
                  h[0]->mag->value(-63);
                  // This is somewhat counter-intuitive.
                  // The sliders don't behave the same way as the code!
                  break;
  
              case OSCILLATOR::control::convertToSine:
                  bftype->value(0);
                  for (int i = 0; i < MAX_AD_HARMONICS; ++i)
                      h[i]->refresh();
                  baseSet = true;
                  set = false;
                  break;
  
              default:
                  set = false;
          }
      }
      if (baseSet)
      {
          basewave->redraw();
          baseharm->redraw();
      }
      if (set)
      {
          waveformgroup->redraw();
          harmonicgroup->redraw();
          oldosc->redraw();
      }
}

float OscilEditor::fetchData(float value, int control, int part, int kititem , int engine , int insert , int parameter , int offset , int miscmsg , int request ) {
  //
          return collect_readData(synth, value, control, part, kititem, engine, insert, parameter, offset, miscmsg, request);
}

OscilEditor::OscilEditor(OscilParameters *oscil_, Fl_Widget *oldosc_, Fl_Widget *cbwidget_, Fl_Widget *cbapplywidget_, SynthEngine *_synth, int npart_, int kititem_, int engine_, bool forPAD_ ) {
  //
      synth = _synth;
      npart = npart_;
      kititem = kititem_;
      engine = engine_;
      forPAD = forPAD_;
      oscil = oscil_;
      fft = new fft::Calc(synth->oscilsize);
      oscilSmp = new OscilGen(*fft, NULL, synth, oscil);
      oldosc = oldosc_;
      cbwidget = cbwidget_;
      cbapplywidget=cbapplywidget_;
      make_window();
      refresh();
      if (engine == PART::engine::padSynth)
          waveType = 2;
      else
          waveType = 0;
  
      int fetchW, fetchH, fetchX, fetchY, fetchO;
      loadWin(synth, fetchW, fetchH, fetchX, fetchY, fetchO, "Waveform " + to_string(waveType));
      if (fetchW < waveDW || fetchH < waveDH)
      {
          fetchW = waveDW;
          fetchH = waveDH;
      }
      checkSane(fetchX, fetchY, fetchW, fetchH, waveDW, waveDH);
      osceditUI->resize(fetchX, fetchY, fetchW, fetchH);
  
      osceditUI->show();
      OSCseen = true;
}

OscilEditor::~OscilEditor() {
  //
      if (OSCseen)
          saveWin(synth, osceditUI->w(), osceditUI->h(), osceditUI->x(), osceditUI->y(), true, "Waveform " + to_string(waveType));
      osceditUI->hide();
      delete (osceditUI);
      delete oscilSmp;
      delete fft;
}

void OscilEditor::refresh() {
  //
      magtype->value(oscil->Phmagtype);
      rndslider->value(oscil->Prand-64);
  
      hrndtype->value(oscil->Pamprandtype);
      if (hrndtype->value() == 0)
          hrnddial->deactivate();
      else
          hrnddial->activate();
      hrnddial->value(oscil->Pamprandpower);
  
      if (oscil->Pcurrentbasefunc > OSCILLATOR::wave::hyperSec)
          bftype->value(OSCILLATOR::wave::user);
      else
          bftype->value(oscil->Pcurrentbasefunc);
      if (bftype->value() == OSCILLATOR::wave::sine)
          bfslider->deactivate();
      else
          bfslider->activate();
      bfparval->value(oscil->Pbasefuncpar-64);
      bfslider->value(oscil->Pbasefuncpar-64);
  
      bfmodtype->value(oscil->Pbasefuncmodulation);
      if (bfmodtype->value() == 0)
          baseFuncPars->deactivate();
      else
          baseFuncPars->activate();
      bfmodpar1->value(oscil->Pbasefuncmodulationpar1);
      bfmodpar2->value(oscil->Pbasefuncmodulationpar2);
      bfmodpar3->value(oscil->Pbasefuncmodulationpar3);
  
      wshbutton->value(oscil->Pwaveshapingfunction);
      if (wshbutton->value() == 0)
          wshpar->deactivate();
      else
          wshpar->activate();
      wsparval->value(oscil->Pwaveshaping-64);
      wshpar->value(oscil->Pwaveshaping-64);
  
      fltbutton->value(oscil->Pfiltertype);
      if (fltbutton->value() == 0)
          filterGroup->deactivate();
      else
          filterGroup->activate();
      filtervalue1->value(oscil->Pfilterpar1);
      filtervalue2->value(oscil->Pfilterpar2);
      filterpref->value(oscil->Pfilterbeforews);
  
      modtype->value(oscil->Pmodulation);
      if (modtype->value() == 0)
          modulationGroup->deactivate();
      else
          modulationGroup->activate();
      modpar1->value(oscil->Pmodulationpar1);
      modpar2->value(oscil->Pmodulationpar2);
      modpar3->value(oscil->Pmodulationpar3);
  
      sabutton->value(oscil->Psatype);
      if (sabutton->value() == 0)
          sadjpar->deactivate();
      else
          sadjpar->activate();
      sadjpar->value(oscil->Psapar);
  
      harmonicshiftcounter->value(oscil->Pharmonicshift);
      harmonicshiftpre->value(oscil->Pharmonicshiftfirst);
  
      adhrtype->value(oscil->Padaptiveharmonics);
      if (adhrtype->value() == 0)
          adaptiveGroup->deactivate();
      else
          adaptiveGroup->activate();
      adhrbf->value(oscil->Padaptiveharmonicsbasefreq);
      adhrpow->value(oscil->Padaptiveharmonicspower);
      adhrtype->value(oscil->Padaptiveharmonicspar);
  
      for (int i=0;i<MAX_AD_HARMONICS;i++)
          h[i]->refresh();
  
      oscilSmp->prepare();
      basewave->redraw();
      baseharm->redraw();
      redrawoscil();
}

void OscilEditor::setWindowTitle() {
  //
          string tname;
          string warnType = "";
          if (engine == 2)
          {
              tname = "PadSynth Harmonic Content";
              Warning->hide();
          }
          else
          {
              tname = "AddSynth Voice ";
              int sourceEngine = -1;
              if (engine < PART::engine::addMod1)
              {
                  tname = tname + to_string((engine - PART::engine::addVoice1) + 1);
                  sourceEngine = fetchData(0, ADDVOICE::control::voiceOscillatorSource,npart,kititem, engine);
                  warnType = "Voice " + to_string(sourceEngine + 1);
              }
              else
              {
                  tname = tname + to_string((engine - PART::engine::addMod1) + 1) +  " Modulation";
                  if (fetchData(0, ADDVOICE::control::externalModulator,npart,kititem, engine) == -1)
                  {
                      sourceEngine = fetchData(0, ADDVOICE::control::modulatorOscillatorSource,npart,kititem, engine);
                      warnType = "Modulator " + to_string(sourceEngine + 1);
                  };
              }
              Warning->redraw();
  
              tname += " Oscillator";
              if (sourceEngine > -1)
              {
                  Warning->show();
                  warnType = "WARNING: Editing " + warnType;
                  Warning->value(warnType.c_str());
              }
              else
                  Warning->hide();
          }
          osceditUI->copy_label(synth->getGuiMaster()->setPartWindowTitle(tname).c_str());
}

void OscilEditor::redrawoscil() {
  //
      waveformgroup->redraw();
      harmonicgroup->redraw();
      oldosc->redraw();
      if (cbwidget!=NULL) {
          cbwidget->do_callback();
  ;
  };
}

void OscilEditor::waveRtext() {
  //
          float dScale = osceditUI->w() / float(waveDW * 10 / 9);
          // waveDW factor adjusted because we allow the
          //  window to be smaller than designed
  
          int size = int(10 * dScale);
          int size11 = int(11 * dScale);
          int size12 = int(12 * dScale);
          int size14 = int(14 * dScale);
  
          applybutton->labelsize(size12);
          hrndtype->labelsize(size);
              hrndtype->textsize(size);
          oscilname->labelsize(size12);
          rndslider->labelsize(size);
              rndslider->textsize(size11);
  
          bftype->labelsize(size);
              bftype->textsize(size11);
          basename->labelsize(size12);
          parname->labelsize(size11);
              bfparval->textsize(size12);
          bfmodtype->labelsize(size);
              bfmodtype->textsize(size);
  
          Warning->textsize(size14);
          magtype->labelsize(size11);
              magtype->textsize(size11);
  
          useasbase->labelsize(size11);
          oscilClose->labelsize(size14);
          clearHarm->labelsize(size11);
  
          wshbutton->labelsize(size);
              wshbutton->textsize(size);
              wsparval->textsize(size12);
          autoclearbutton->labelsize(size);
          filterpref->labelsize(size);
          fltbutton->labelsize(size);
              fltbutton->textsize(size);
          sabutton->labelsize(size);
              sabutton->textsize(size);
          harmonicshiftcounter->labelsize(size);
              harmonicshiftcounter->textsize(size);
          harmonicshiftpre->labelsize(size);
  
          adhrpow->labelsize(size);
          adhrbf->labelsize(size);
          adhrpar->textsize(size);
          adhrtype->labelsize(size);
              adhrtype->textsize(size);
  
          modtype->labelsize(size);
              modtype->textsize(size);
  
          tosine->labelsize(size11);
          oscilC->labelsize(size);
          oscilP->labelsize(size);
          frame->scroll_to(0, 0);
          frame->scrollbar_size(12 * dScale);
          harmonics->size(650 * dScale, 235 * dScale);
          for (int i= 0; i < MAX_AD_HARMONICS; i++)
          {
              h[i]->size(20 * dScale, 225 * dScale);
              h[i]->number->labelsize(size11);
          }
  
          osceditUI->redraw();
}
