package com.domemusictechnologies.bpmconverter;


import voltage.controllers.*;
import voltage.core.*;
import voltage.core.Jack.JackType;
import voltage.sources.*;
import voltage.utility.*;
import voltage.processors.*;
import voltage.effects.*;
import java.awt.*;

//[user-imports]   Add your own imports here

import static java.lang.Math.round;    // Round double to nearest integer value

//[/user-imports]


public class BpmConverter extends VoltageModule
//[user-inheritance]
//[/user-inheritance]
{

public BpmConverter( long moduleID, VoltageObjects voltageObjects )
{
   super( moduleID, voltageObjects, "BPM Converter", ModuleType.ModuleType_Utility, 1.0 );

   InitializeControls();


   canBeBypassed = false;
   SetSkin( "60a1f7d759704112be3ea21232e97802" );
}

void InitializeControls()
{

   textLabel1 = new VoltageLabel( "textLabel1", "textLabel1", this, "BPM Converter" );
   AddComponent( textLabel1 );
   textLabel1.SetWantsMouseNotifications( false );
   textLabel1.SetPosition( 0, 0 );
   textLabel1.SetSize( 70, 31 );
   textLabel1.SetEditable( false, false );
   textLabel1.SetJustificationFlags( VoltageLabel.Justification.HorizCentered );
   textLabel1.SetJustificationFlags( VoltageLabel.Justification.VertCentered );
   textLabel1.SetColor( new Color( 255, 255, 255, 255 ) );
   textLabel1.SetBkColor( new Color( 65, 65, 65, 0 ) );
   textLabel1.SetBorderColor( new Color( 0, 0, 0, 0 ) );
   textLabel1.SetBorderSize( 1 );
   textLabel1.SetMultiLineEdit( true );
   textLabel1.SetIsNumberEditor( false );
   textLabel1.SetNumberEditorRange( 0, 100 );
   textLabel1.SetNumberEditorInterval( 1 );
   textLabel1.SetNumberEditorUsesMouseWheel( false );
   textLabel1.SetHasCustomTextHoverColor( false );
   textLabel1.SetTextHoverColor( new Color( 0, 0, 0, 255 ) );
   textLabel1.SetFont( "Verdana", 14, false, false );

   tempoKnob = new VoltageKnob( "Tempo", "Tempo", this, 20.0, 220.0, 120 );
   AddComponent( tempoKnob );
   tempoKnob.SetWantsMouseNotifications( false );
   tempoKnob.SetPosition( 13, 66 );
   tempoKnob.SetSize( 47, 47 );
   tempoKnob.SetSkin( "Moog Rogue Pointer" );
   tempoKnob.SetRange( 20.0, 220.0, 120, false, 0 );
   tempoKnob.SetKnobParams( 215, 145 );
   tempoKnob.DisplayValueInPercent( false );
   tempoKnob.SetKnobAdjustsRing( true );

   tempoDisplay = new VoltageLabel( "Tempo Display", "Tempo Display", this, "120.0 BPM" );
   AddComponent( tempoDisplay );
   tempoDisplay.SetWantsMouseNotifications( false );
   tempoDisplay.SetPosition( 1, 109 );
   tempoDisplay.SetSize( 71, 24 );
   tempoDisplay.SetEditable( false, false );
   tempoDisplay.SetJustificationFlags( VoltageLabel.Justification.HorizCentered );
   tempoDisplay.SetJustificationFlags( VoltageLabel.Justification.VertCentered );
   tempoDisplay.SetColor( new Color( 255, 0, 0, 255 ) );
   tempoDisplay.SetBkColor( new Color( 65, 65, 65, 0 ) );
   tempoDisplay.SetBorderColor( new Color( 0, 0, 0, 0 ) );
   tempoDisplay.SetBorderSize( 1 );
   tempoDisplay.SetMultiLineEdit( false );
   tempoDisplay.SetIsNumberEditor( false );
   tempoDisplay.SetNumberEditorRange( 0, 100 );
   tempoDisplay.SetNumberEditorInterval( 1 );
   tempoDisplay.SetNumberEditorUsesMouseWheel( false );
   tempoDisplay.SetHasCustomTextHoverColor( false );
   tempoDisplay.SetTextHoverColor( new Color( 0, 0, 0, 255 ) );
   tempoDisplay.SetFont( "Verdana", 12, false, false );

   noteLengthKnob = new VoltageKnob( "Note Length", "Note Length", this, 0, 6, 2 );
   AddComponent( noteLengthKnob );
   noteLengthKnob.SetWantsMouseNotifications( false );
   noteLengthKnob.SetPosition( 14, 170 );
   noteLengthKnob.SetSize( 45, 45 );
   noteLengthKnob.SetSkin( "Knurled Plastic White" );
   noteLengthKnob.SetRange( 0, 6, 2, false, 7 );
   noteLengthKnob.SetKnobParams( 215, 145 );
   noteLengthKnob.DisplayValueInPercent( false );
   noteLengthKnob.SetKnobAdjustsRing( true );

   textLabel3 = new VoltageLabel( "textLabel3", "textLabel3", this, "Tempo" );
   AddComponent( textLabel3 );
   textLabel3.SetWantsMouseNotifications( false );
   textLabel3.SetPosition( 13, 48 );
   textLabel3.SetSize( 47, 18 );
   textLabel3.SetEditable( false, false );
   textLabel3.SetJustificationFlags( VoltageLabel.Justification.HorizCentered );
   textLabel3.SetJustificationFlags( VoltageLabel.Justification.VertCentered );
   textLabel3.SetColor( new Color( 255, 255, 255, 255 ) );
   textLabel3.SetBkColor( new Color( 65, 65, 65, 0 ) );
   textLabel3.SetBorderColor( new Color( 0, 0, 0, 0 ) );
   textLabel3.SetBorderSize( 1 );
   textLabel3.SetMultiLineEdit( false );
   textLabel3.SetIsNumberEditor( false );
   textLabel3.SetNumberEditorRange( 0, 100 );
   textLabel3.SetNumberEditorInterval( 1 );
   textLabel3.SetNumberEditorUsesMouseWheel( false );
   textLabel3.SetHasCustomTextHoverColor( false );
   textLabel3.SetTextHoverColor( new Color( 0, 0, 0, 255 ) );
   textLabel3.SetFont( "Verdana", 12, false, false );

   textLabel5 = new VoltageLabel( "textLabel10", "textLabel5", this, "Man" );
   AddComponent( textLabel5 );
   textLabel5.SetWantsMouseNotifications( false );
   textLabel5.SetPosition( 1, 33 );
   textLabel5.SetSize( 24, 18 );
   textLabel5.SetEditable( false, false );
   textLabel5.SetJustificationFlags( VoltageLabel.Justification.HorizCentered );
   textLabel5.SetJustificationFlags( VoltageLabel.Justification.VertCentered );
   textLabel5.SetColor( new Color( 255, 255, 255, 255 ) );
   textLabel5.SetBkColor( new Color( 65, 65, 65, 0 ) );
   textLabel5.SetBorderColor( new Color( 0, 0, 0, 0 ) );
   textLabel5.SetBorderSize( 1 );
   textLabel5.SetMultiLineEdit( false );
   textLabel5.SetIsNumberEditor( false );
   textLabel5.SetNumberEditorRange( 0, 100 );
   textLabel5.SetNumberEditorInterval( 1 );
   textLabel5.SetNumberEditorUsesMouseWheel( false );
   textLabel5.SetHasCustomTextHoverColor( false );
   textLabel5.SetTextHoverColor( new Color( 0, 0, 0, 255 ) );
   textLabel5.SetFont( "Verdana", 9, false, false );

   textLabel10 = new VoltageLabel( "textLabel13", "textLabel10", this, "Host" );
   AddComponent( textLabel10 );
   textLabel10.SetWantsMouseNotifications( false );
   textLabel10.SetPosition( 47, 33 );
   textLabel10.SetSize( 24, 18 );
   textLabel10.SetEditable( false, false );
   textLabel10.SetJustificationFlags( VoltageLabel.Justification.HorizCentered );
   textLabel10.SetJustificationFlags( VoltageLabel.Justification.VertCentered );
   textLabel10.SetColor( new Color( 255, 255, 255, 255 ) );
   textLabel10.SetBkColor( new Color( 65, 65, 65, 0 ) );
   textLabel10.SetBorderColor( new Color( 0, 0, 0, 0 ) );
   textLabel10.SetBorderSize( 1 );
   textLabel10.SetMultiLineEdit( false );
   textLabel10.SetIsNumberEditor( false );
   textLabel10.SetNumberEditorRange( 0, 100 );
   textLabel10.SetNumberEditorInterval( 1 );
   textLabel10.SetNumberEditorUsesMouseWheel( false );
   textLabel10.SetHasCustomTextHoverColor( false );
   textLabel10.SetTextHoverColor( new Color( 0, 0, 0, 255 ) );
   textLabel10.SetFont( "Verdana", 9, false, false );

   textLabel11 = new VoltageLabel( "textLabel14", "textLabel11", this, "Lag" );
   AddComponent( textLabel11 );
   textLabel11.SetWantsMouseNotifications( false );
   textLabel11.SetPosition( 46, 131 );
   textLabel11.SetSize( 26, 17 );
   textLabel11.SetEditable( false, false );
   textLabel11.SetJustificationFlags( VoltageLabel.Justification.HorizCentered );
   textLabel11.SetJustificationFlags( VoltageLabel.Justification.VertCentered );
   textLabel11.SetColor( new Color( 22, 165, 56, 255 ) );
   textLabel11.SetBkColor( new Color( 65, 65, 65, 0 ) );
   textLabel11.SetBorderColor( new Color( 0, 0, 0, 0 ) );
   textLabel11.SetBorderSize( 1 );
   textLabel11.SetMultiLineEdit( false );
   textLabel11.SetIsNumberEditor( false );
   textLabel11.SetNumberEditorRange( 0, 100 );
   textLabel11.SetNumberEditorInterval( 1 );
   textLabel11.SetNumberEditorUsesMouseWheel( false );
   textLabel11.SetHasCustomTextHoverColor( false );
   textLabel11.SetTextHoverColor( new Color( 0, 0, 0, 255 ) );
   textLabel11.SetFont( "Verdana", 10, true, false );

   textLabel13 = new VoltageLabel( "textLabel15", "textLabel13", this, "Off" );
   AddComponent( textLabel13 );
   textLabel13.SetWantsMouseNotifications( false );
   textLabel13.SetPosition( 1, 131 );
   textLabel13.SetSize( 26, 17 );
   textLabel13.SetEditable( false, false );
   textLabel13.SetJustificationFlags( VoltageLabel.Justification.HorizCentered );
   textLabel13.SetJustificationFlags( VoltageLabel.Justification.VertCentered );
   textLabel13.SetColor( new Color( 0, 95, 23, 255 ) );
   textLabel13.SetBkColor( new Color( 65, 65, 65, 0 ) );
   textLabel13.SetBorderColor( new Color( 0, 0, 0, 0 ) );
   textLabel13.SetBorderSize( 1 );
   textLabel13.SetMultiLineEdit( false );
   textLabel13.SetIsNumberEditor( false );
   textLabel13.SetNumberEditorRange( 0, 100 );
   textLabel13.SetNumberEditorInterval( 1 );
   textLabel13.SetNumberEditorUsesMouseWheel( false );
   textLabel13.SetHasCustomTextHoverColor( false );
   textLabel13.SetTextHoverColor( new Color( 0, 0, 0, 255 ) );
   textLabel13.SetFont( "Verdana", 10, true, false );

   textLabel4 = new VoltageLabel( "textLabel4", "textLabel4", this, "Length" );
   AddComponent( textLabel4 );
   textLabel4.SetWantsMouseNotifications( false );
   textLabel4.SetPosition( 2, 151 );
   textLabel4.SetSize( 69, 22 );
   textLabel4.SetEditable( false, false );
   textLabel4.SetJustificationFlags( VoltageLabel.Justification.HorizCentered );
   textLabel4.SetJustificationFlags( VoltageLabel.Justification.VertCentered );
   textLabel4.SetColor( new Color( 0, 0, 0, 255 ) );
   textLabel4.SetBkColor( new Color( 65, 65, 65, 0 ) );
   textLabel4.SetBorderColor( new Color( 0, 0, 0, 0 ) );
   textLabel4.SetBorderSize( 1 );
   textLabel4.SetMultiLineEdit( false );
   textLabel4.SetIsNumberEditor( false );
   textLabel4.SetNumberEditorRange( 0, 100 );
   textLabel4.SetNumberEditorInterval( 1 );
   textLabel4.SetNumberEditorUsesMouseWheel( false );
   textLabel4.SetHasCustomTextHoverColor( false );
   textLabel4.SetTextHoverColor( new Color( 0, 0, 0, 255 ) );
   textLabel4.SetFont( "Verdana", 12, false, false );

   noteLengthDisplay = new VoltageLabel( "textLabel5", "", this, "1/4 note" );
   AddComponent( noteLengthDisplay );
   noteLengthDisplay.SetWantsMouseNotifications( false );
   noteLengthDisplay.SetPosition( 9, 211 );
   noteLengthDisplay.SetSize( 56, 21 );
   noteLengthDisplay.SetEditable( false, false );
   noteLengthDisplay.SetJustificationFlags( VoltageLabel.Justification.HorizCentered );
   noteLengthDisplay.SetJustificationFlags( VoltageLabel.Justification.VertCentered );
   noteLengthDisplay.SetColor( new Color( 255, 0, 0, 255 ) );
   noteLengthDisplay.SetBkColor( new Color( 65, 65, 65, 0 ) );
   noteLengthDisplay.SetBorderColor( new Color( 0, 0, 0, 0 ) );
   noteLengthDisplay.SetBorderSize( 1 );
   noteLengthDisplay.SetMultiLineEdit( false );
   noteLengthDisplay.SetIsNumberEditor( false );
   noteLengthDisplay.SetNumberEditorRange( 0, 100 );
   noteLengthDisplay.SetNumberEditorInterval( 1 );
   noteLengthDisplay.SetNumberEditorUsesMouseWheel( false );
   noteLengthDisplay.SetHasCustomTextHoverColor( false );
   noteLengthDisplay.SetTextHoverColor( new Color( 0, 0, 0, 255 ) );
   noteLengthDisplay.SetFont( "Verdana", 12, false, false );

   noteValueSwitch = new VoltageSwitch( "Note Value", "Note Value", this, 2 );
   AddComponent( noteValueSwitch );
   noteValueSwitch.SetWantsMouseNotifications( false );
   noteValueSwitch.SetPosition( 0, 249 );
   noteValueSwitch.SetSize( 36, 36 );
   noteValueSwitch.SetSkin( "3-State Bar Vertical" );

   textLabel6 = new VoltageLabel( "textLabel6", "textLabel6", this, "Value" );
   AddComponent( textLabel6 );
   textLabel6.SetWantsMouseNotifications( false );
   textLabel6.SetPosition( 0, 230 );
   textLabel6.SetSize( 69, 20 );
   textLabel6.SetEditable( false, false );
   textLabel6.SetJustificationFlags( VoltageLabel.Justification.HorizCentered );
   textLabel6.SetJustificationFlags( VoltageLabel.Justification.VertCentered );
   textLabel6.SetColor( new Color( 0, 0, 0, 255 ) );
   textLabel6.SetBkColor( new Color( 65, 65, 65, 0 ) );
   textLabel6.SetBorderColor( new Color( 0, 0, 0, 0 ) );
   textLabel6.SetBorderSize( 1 );
   textLabel6.SetMultiLineEdit( false );
   textLabel6.SetIsNumberEditor( false );
   textLabel6.SetNumberEditorRange( 0, 100 );
   textLabel6.SetNumberEditorInterval( 1 );
   textLabel6.SetNumberEditorUsesMouseWheel( false );
   textLabel6.SetHasCustomTextHoverColor( false );
   textLabel6.SetTextHoverColor( new Color( 0, 0, 0, 255 ) );
   textLabel6.SetFont( "Verdana", 12, false, false );

   textLabel7 = new VoltageLabel( "textLabel7", "textLabel7", this, "Single" );
   AddComponent( textLabel7 );
   textLabel7.SetWantsMouseNotifications( false );
   textLabel7.SetPosition( 29, 245 );
   textLabel7.SetSize( 39, 16 );
   textLabel7.SetEditable( false, false );
   textLabel7.SetJustificationFlags( VoltageLabel.Justification.Left );
   textLabel7.SetJustificationFlags( VoltageLabel.Justification.VertCentered );
   textLabel7.SetColor( new Color( 255, 255, 255, 255 ) );
   textLabel7.SetBkColor( new Color( 65, 65, 65, 0 ) );
   textLabel7.SetBorderColor( new Color( 0, 0, 0, 0 ) );
   textLabel7.SetBorderSize( 1 );
   textLabel7.SetMultiLineEdit( false );
   textLabel7.SetIsNumberEditor( false );
   textLabel7.SetNumberEditorRange( 0, 100 );
   textLabel7.SetNumberEditorInterval( 1 );
   textLabel7.SetNumberEditorUsesMouseWheel( false );
   textLabel7.SetHasCustomTextHoverColor( false );
   textLabel7.SetTextHoverColor( new Color( 0, 0, 0, 255 ) );
   textLabel7.SetFont( "Verdana", 10, false, false );

   textLabel8 = new VoltageLabel( "textLabel8", "textLabel8", this, "Dotted" );
   AddComponent( textLabel8 );
   textLabel8.SetWantsMouseNotifications( false );
   textLabel8.SetPosition( 29, 258 );
   textLabel8.SetSize( 38, 16 );
   textLabel8.SetEditable( false, false );
   textLabel8.SetJustificationFlags( VoltageLabel.Justification.Left );
   textLabel8.SetJustificationFlags( VoltageLabel.Justification.VertCentered );
   textLabel8.SetColor( new Color( 255, 255, 255, 255 ) );
   textLabel8.SetBkColor( new Color( 65, 65, 65, 0 ) );
   textLabel8.SetBorderColor( new Color( 0, 0, 0, 0 ) );
   textLabel8.SetBorderSize( 1 );
   textLabel8.SetMultiLineEdit( false );
   textLabel8.SetIsNumberEditor( false );
   textLabel8.SetNumberEditorRange( 0, 100 );
   textLabel8.SetNumberEditorInterval( 1 );
   textLabel8.SetNumberEditorUsesMouseWheel( false );
   textLabel8.SetHasCustomTextHoverColor( false );
   textLabel8.SetTextHoverColor( new Color( 0, 0, 0, 255 ) );
   textLabel8.SetFont( "Verdana", 10, false, false );

   textLabel9 = new VoltageLabel( "textLabel9", "textLabel9", this, "Triplet" );
   AddComponent( textLabel9 );
   textLabel9.SetWantsMouseNotifications( false );
   textLabel9.SetPosition( 29, 271 );
   textLabel9.SetSize( 39, 16 );
   textLabel9.SetEditable( false, false );
   textLabel9.SetJustificationFlags( VoltageLabel.Justification.Left );
   textLabel9.SetJustificationFlags( VoltageLabel.Justification.VertCentered );
   textLabel9.SetColor( new Color( 255, 255, 255, 255 ) );
   textLabel9.SetBkColor( new Color( 65, 65, 65, 0 ) );
   textLabel9.SetBorderColor( new Color( 0, 0, 0, 0 ) );
   textLabel9.SetBorderSize( 1 );
   textLabel9.SetMultiLineEdit( false );
   textLabel9.SetIsNumberEditor( false );
   textLabel9.SetNumberEditorRange( 0, 100 );
   textLabel9.SetNumberEditorInterval( 1 );
   textLabel9.SetNumberEditorUsesMouseWheel( false );
   textLabel9.SetHasCustomTextHoverColor( false );
   textLabel9.SetTextHoverColor( new Color( 0, 0, 0, 255 ) );
   textLabel9.SetFont( "Verdana", 10, false, false );

   delayTimeDisplay = new VoltageLabel( "Delay Readout", "Delay Readout", this, "500.00 ms" );
   AddComponent( delayTimeDisplay );
   delayTimeDisplay.SetWantsMouseNotifications( false );
   delayTimeDisplay.SetPosition( 3, 287 );
   delayTimeDisplay.SetSize( 67, 19 );
   delayTimeDisplay.SetEditable( false, false );
   delayTimeDisplay.SetJustificationFlags( VoltageLabel.Justification.HorizCentered );
   delayTimeDisplay.SetJustificationFlags( VoltageLabel.Justification.VertCentered );
   delayTimeDisplay.SetColor( new Color( 79, 255, 0, 255 ) );
   delayTimeDisplay.SetBkColor( new Color( 65, 65, 65, 0 ) );
   delayTimeDisplay.SetBorderColor( new Color( 0, 0, 0, 0 ) );
   delayTimeDisplay.SetBorderSize( 1 );
   delayTimeDisplay.SetMultiLineEdit( false );
   delayTimeDisplay.SetIsNumberEditor( false );
   delayTimeDisplay.SetNumberEditorRange( 0, 100 );
   delayTimeDisplay.SetNumberEditorInterval( 1 );
   delayTimeDisplay.SetNumberEditorUsesMouseWheel( false );
   delayTimeDisplay.SetHasCustomTextHoverColor( false );
   delayTimeDisplay.SetTextHoverColor( new Color( 0, 0, 0, 255 ) );
   delayTimeDisplay.SetFont( "Verdana", 12, false, false );

   outputZeitCV = new VoltageAudioJack( "Zeit CV Out", "Zeit CV Out", this, JackType.JackType_AudioOutput );
   AddComponent( outputZeitCV );
   outputZeitCV.SetWantsMouseNotifications( false );
   outputZeitCV.SetPosition( 17, 301 );
   outputZeitCV.SetSize( 37, 37 );
   outputZeitCV.SetSkin( "Jack Round" );

   overflowLED = new VoltageLED( "Overflow LED", "Overflow LED", this );
   AddComponent( overflowLED );
   overflowLED.SetWantsMouseNotifications( false );
   overflowLED.SetPosition( 56, 314 );
   overflowLED.SetSize( 11, 11 );
   overflowLED.SetSkin( "Red" );

   textLabel12 = new VoltageLabel( "textLabel12", "textLabel12", this, "Dome Music Technologies" );
   AddComponent( textLabel12 );
   textLabel12.SetWantsMouseNotifications( false );
   textLabel12.SetPosition( 3, 341 );
   textLabel12.SetSize( 66, 19 );
   textLabel12.SetEditable( false, false );
   textLabel12.SetJustificationFlags( VoltageLabel.Justification.HorizCentered );
   textLabel12.SetJustificationFlags( VoltageLabel.Justification.VertCentered );
   textLabel12.SetColor( new Color( 255, 255, 255, 255 ) );
   textLabel12.SetBkColor( new Color( 65, 65, 65, 0 ) );
   textLabel12.SetBorderColor( new Color( 0, 0, 0, 0 ) );
   textLabel12.SetBorderSize( 1 );
   textLabel12.SetMultiLineEdit( true );
   textLabel12.SetIsNumberEditor( false );
   textLabel12.SetNumberEditorRange( 0, 100 );
   textLabel12.SetNumberEditorInterval( 1 );
   textLabel12.SetNumberEditorUsesMouseWheel( false );
   textLabel12.SetHasCustomTextHoverColor( false );
   textLabel12.SetTextHoverColor( new Color( 0, 0, 0, 255 ) );
   textLabel12.SetFont( "Verdana", 7, false, false );

   manHostSwitch = new VoltageSwitch( "Manual / Host", "Manual / Host", this, 0 );
   AddComponent( manHostSwitch );
   manHostSwitch.SetWantsMouseNotifications( false );
   manHostSwitch.SetPosition( 23, 35 );
   manHostSwitch.SetSize( 27, 15 );
   manHostSwitch.SetSkin( "2-State Slide Horizontal" );

   switchLag = new VoltageSwitch( "Tempo Lag", "Tempo Lag", this, 1 );
   AddComponent( switchLag );
   switchLag.SetWantsMouseNotifications( false );
   switchLag.SetPosition( 23, 132 );
   switchLag.SetSize( 27, 15 );
   switchLag.SetSkin( "2-State Slide Horizontal" );
}



//-------------------------------------------------------------------------------
//  public void Initialize()

//  Initialize will get called shortly after your module's constructor runs. You can use it to
//  do any initialization that the auto-generated code doesn't handle.
//-------------------------------------------------------------------------------
@Override
public void Initialize()
{
   //[user-Initialize]   Add your own initialization code here
   previousKnobTempo = 220.0;
   
   SetManHostMode();
   if (hostModeEnabled)
   {
      SetTempoFromHost();
   }
   else
   {
      SetTempoValue();
   }
   UpdateTempoDisplay();
   SetNoteLength();
   UpdateNoteLengthDisplay();
   SetNoteValue();
   SetLagValue(switchLag.GetValue());

   CalculateDelayTime();
   slewedDelay = currentDelay;
   previousDelay = currentDelay;
   
   previousOverflowZeit = false;
   
   StartGuiUpdateTimer();

   //[/user-Initialize]
}


//-------------------------------------------------------------------------------
//  public void Destroy()

//  Destroy will get called just before your module gets deleted. You can use it to perform any
//  cleanup that's not handled automatically by Java.
//-------------------------------------------------------------------------------
@Override
public void Destroy()
{
   super.Destroy();
   //[user-Destroy]   Add your own module-getting-deleted code here



   //[/user-Destroy]
}


//-------------------------------------------------------------------------------
//  public boolean Notify( VoltageComponent component, ModuleNotifications notification, double doubleValue, long longValue, int x, int y, Object object )

//  Notify will get called when various events occur - control values changing, timers firing, etc.
//-------------------------------------------------------------------------------
@Override
public boolean Notify( VoltageComponent component, ModuleNotifications notification, double doubleValue, long longValue, int x, int y, Object object )
{
   //[user-Notify]   Add your own notification handling code between this line and the notify-close comment
   switch( notification )
   {
      case Knob_Changed:   // doubleValue is the new VoltageKnob value
      {
         if (component == tempoKnob)
         {
            SetTempoValue();
         }
         else if (component == noteLengthKnob)
         {
            SetNoteLength();
         }
         
      }
      break;
   
      case Slider_Changed:   // doubleValue is the new slider value
      {
      }
      break;
   
      case Button_Changed:   // doubleValue is the new button/toggle button value
      {
      }
      break;
   
      case Switch_Changed:   // doubleValue is the new switch value
      {
         if (component == noteValueSwitch)
         {
            SetNoteValue();
         }
         else if (component == manHostSwitch)
         {
            SetManHostMode();
         }
         else if (component == switchLag)
         {
            SetLagValue(doubleValue);
         }
      }
      break;
   
      case Jack_Connected:   // longValue is the new cable ID
      {
         if (component == outputZeitCV)
         {
            // Just plugged in output cable - set slewed value to current value.
            slewedDelay = currentDelay;
         }
      }
      break;
   
      case Jack_Disconnected:   // All cables have been disconnected from this jack
      {
      }
      break;
   
      case GUI_Update_Timer:   // Called every 50ms (by default) if turned on
      {
         if (currentNoteLength != previousDisplayedLength)
         {
            UpdateNoteLengthDisplay();
         }
         if (currentKnobTempo != previousDisplayedTempo)
         {
            UpdateTempoDisplay();
         }
         if (currentDelay != previousDelay)
         {
            UpdateDelayTimeDisplay();
         }
         if (overflowZeit != previousOverflowZeit)
         {
            UpdateOverflowLED();
         }
      }
      break;
   
      case Object_MouseMove:   // called when mouse is over an object that receives mouse notifications. 'object' parameter is a VoltageMouseKeyFlags object.
      {
      }
      break;
   
      case Object_MouseLeave:  // called when mouse leaves an object that receives mouse notifications. 'object' parameter is a VoltageMouseKeyFlags object.
      {
      }
      break;
   
      case Object_LeftButtonDown:   // called when user left-clicks on an object that receives mouse notifications. 'object' parameter is a VoltageMouseKeyFlags object.
      {
      }
      break;
   
      case Object_LeftButtonUp:   // called when user releases left mouse button on an object that receives mouse notifications. 'object' parameter is a VoltageMouseKeyFlags object.
      {
      }
      break;
   
      case Object_RightButtonDown:   // called when user releases right mouse button on an object that receives mouse notifications. 'object' parameter is a VoltageMouseKeyFlags object.
      {
      }
      break;
   
      case Object_RightButtonUp:   // called when user right-clicks on an object that receives mouse notifications
      {
      }
      break;
   
      case Object_LeftButtonDoubleClick: // called when user left-button double-clicks on an object that receives mouse notifications
      {
      }
      break;
   
      // Less common notifications:
   
      case Named_Timer:   // object contains a String with the name of the timer that has fired
      {
      }
      break;
   
      case Canvas_Painting:   // About to paint canvas.  object is a java.awt.Rectangle with painting boundaries
      {
      }
      break;
   
      case Canvas_Painted:   // Canvas painting is complete
      {
      }
      break;
   
      case Control_DragStart:    // A user has started dragging on a control that has been marked as draggable
      {
      }
      break;
   
      case Control_DragOn:       // This control has been dragged over during a drag operation. object contains the dragged object
      {
      }
      break;
   
      case Control_DragOff:      // This control has been dragged over during a drag operation. object contains the dragged object
      {
      }
      break;
   
      case Control_DragEnd:      // A user has ended their drag on a control that has been marked as draggable
      {
      }
      break;
   
      case Label_Changed:        // The text of an editable text control has changed
      {
      }
      break;
   
      case SoundPlayback_Start:   // A sound has begun playback
      {
      }
      break;
   
      case SoundPlayback_End:     // A sound has ended playback
      {
      }
      break;
   
      case Scrollbar_Position:    // longValue is the new scrollbar position
      {
      }
      break;
   
      case PolyVoices_Changed:    // longValue is the new number of poly voices
      {
      }
      break;
   
      case File_Dropped:     // 'object' is a String containing the file path
      {
      }
      break;
   
      case Preset_Loading_Start:   // called when preset loading begins
      {
      }
      break;
   
      case Preset_Loading_Finish:  // called when preset loading finishes
      {
      }
      break;
   
      case Variation_Loading_Start:    // sent when a variation is about to load
      {
      }
      break;
   
      case Variation_Loading_Finish:   // sent when a variation has just finished loading
      {
      }
      break;
   
      case Tempo_Changed:     // doubleValue is the new tempo
      {
         if (hostModeEnabled)
         {
            SetTempoFromHost();
         }
      }
      break;
   
      case Randomized:     // called when the module's controls get randomized
      {
      }
      break;
   
      case VariationListChanged:   // sent when a variation gets added, deleted, or renamed, or the variations list gets reordered
      {
      }
      break;
   
      case Key_Press:     // sent when module has keyboard focus and a key is pressed; object is a VoltageKeyPressInfo object
      {
      }
      break;
   
      case Reset:    // sent when the module has been reset to default settings
      {
      }
      break;
   
      case Keyboard_NoteOn:   // sent when a note has been pressed on a VoltageKeyboard object. longValue is the note value ( 0-127 )
      {
      }
      break;
   
      case Keyboard_NoteOff:   // sent when a note has been released on a VoltageKeyboard object. longValue is the note value ( 0-127 )
      {
      }
      break;
   
      case Curve_Changed:   // sent when user has edited a curve's value. 'object' will be a VoltageCurve.CurveChangeNotification object.
      {
      }
      break;
   }



   return false;
   //[/user-Notify]
}


//-------------------------------------------------------------------------------
//  public void ProcessSample()

//  ProcessSample is called once per sample. Usually it's where you read
//  from input jacks, process audio, and write it to your output jacks.
//  Since ProcesssSample gets called 48,000 times per second, offload CPU-intensive operations
//  to other threads when possible and avoid calling native functions.
//-------------------------------------------------------------------------------
@Override
public void ProcessSample()
{
   //[user-ProcessSample]   Add your own process-sampling code here

   double tempDbl;

   if ((currentKnobTempo != previousKnobTempo) ||
       (currentNoteLength != previousNoteLength) ||
       (currentNoteValue != previousNoteValue))
   {
      CalculateDelayTime();
   }
   
   if (outputZeitCV.IsConnected())
   {
      // Calculate slewed delay value
      if (lagEnabled)
      {
         tempDbl = currentDelay - slewedDelay;
         slewedDelay = currentDelay - (tempDbl * DELAY_SLEW_FACTOR);
      }
      else
      {
         slewedDelay = currentDelay;
      }
      outputZeitDelay = slewedDelay * 0.001; // Milliseconds to seconds
      outputZeitCV.SetValue(outputZeitDelay);
      
      overflowZeit = (outputZeitDelay > 2.5);
   }
   else
   {
      overflowZeit = false;
   }

   //[/user-ProcessSample]
}


//-------------------------------------------------------------------------------
//  public String GetTooltipText( VoltageComponent component )

//  Gets called when a tooltip is about to display for a control. Override it if
//  you want to change what the tooltip displays - if you want a knob to work in logarithmic fashion,
//  for instance, you can translate the knob's current value to a log-based string and display it here.
//-------------------------------------------------------------------------------
@Override
public String GetTooltipText( VoltageComponent component )
{
   //[user-GetTooltipText]   Add your own code here

   if (component == noteLengthKnob)
   {
      return NoteLengthDisplayedValue;
   }


   return super.GetTooltipText( component );
   //[/user-GetTooltipText]
}


//-------------------------------------------------------------------------------
//  public void EditComponentValue( VoltageComponent component, double newValue, String newText )

//  Gets called after a user clicks on a tooltip and types in a new value for a control. Override this if
//  you've changed the default tooltip display (translating a linear value to logarithmic, for instance)
//  in GetTooltipText().
//-------------------------------------------------------------------------------
@Override
public void EditComponentValue( VoltageComponent component, double newValue, String newText )
{
   //[user-EditComponentValue]   Add your own code here



   //[/user-EditComponentValue]
   super.EditComponentValue( component, newValue, newText );
}


//-------------------------------------------------------------------------------
//  public void OnUndoRedo( String undoType, double newValue, Object optionalObject )

//  If you've created custom undo events via calls to CreateUndoEvent, you'll need to
//  process them in this function when they get triggered by undo/redo actions.
//-------------------------------------------------------------------------------
@Override
public void OnUndoRedo( String undoType, double newValue, Object optionalObject )
{
   //[user-OnUndoRedo]   Add your own code here



   //[/user-OnUndoRedo]
}


//-------------------------------------------------------------------------------
//  public byte[] GetStateInformation()

//  Gets called when the module's state gets saved, typically when the user saves a preset with
//  this module in it. Voltage Modular will automatically save the states of knobs, sliders, etc.,
//  but if you have any custom state information you need to save, return it from this function.
//-------------------------------------------------------------------------------
@Override
public byte[] GetStateInformation()
{
   //[user-GetStateInformation]   Add your own code here



   return null;
   //[/user-GetStateInformation]
}


//-------------------------------------------------------------------------------
//  public void SetStateInformation(byte[] stateInfo)

//  Gets called when this module's state is getting restored, typically when a user opens a preset with
//  this module in it. The stateInfo parameter will contain whatever custom data you stored in GetStateInformation().
//-------------------------------------------------------------------------------
@Override
public void SetStateInformation(byte[] stateInfo)
{
   //[user-SetStateInformation]   Add your own code here



   //[/user-SetStateInformation]
}


//-------------------------------------------------------------------------------
//  public byte[] GetStateInformationForVariations()

//  Gets called when a user saves a variation with this module in it.
//  Voltage Modular will automatically save the states of knobs, sliders, etc.,
//  but if you have any custom state information you need to save, return it from this function.
//-------------------------------------------------------------------------------
@Override
public byte[] GetStateInformationForVariations()
{
   //[user-GetStateInformationForVariations]   Add your own code here



   return GetStateInformation();
   //[/user-GetStateInformationForVariations]
}


//-------------------------------------------------------------------------------
//  public void SetStateInformationForVariations(byte[] stateInfo)

//  Gets called when a user loads a variation with this module in it.
//  The stateInfo parameter will contain whatever custom data you stored in GetStateInformationForVariations().
//-------------------------------------------------------------------------------
@Override
public void SetStateInformationForVariations(byte[] stateInfo)
{
   //[user-SetStateInformationForVariations]   Add your own code here
   SetStateInformation(stateInfo);



   //[/user-SetStateInformationForVariations]
}


// Auto-generated variables
private VoltageSwitch switchLag;
private VoltageSwitch manHostSwitch;
private VoltageLabel textLabel12;
private VoltageLED overflowLED;
private VoltageAudioJack outputZeitCV;
private VoltageLabel delayTimeDisplay;
private VoltageLabel textLabel9;
private VoltageLabel textLabel8;
private VoltageLabel textLabel7;
private VoltageLabel textLabel6;
private VoltageSwitch noteValueSwitch;
private VoltageLabel noteLengthDisplay;
private VoltageLabel textLabel4;
private VoltageLabel textLabel13;
private VoltageLabel textLabel11;
private VoltageLabel textLabel10;
private VoltageLabel textLabel5;
private VoltageLabel textLabel3;
private VoltageKnob noteLengthKnob;
private VoltageLabel tempoDisplay;
private VoltageKnob tempoKnob;
private VoltageLabel textLabel1;


//[user-code-and-variables]    Add your own variables and functions here


// Constants

private final double SINGLE_NOTE_MULTIPLIER = 1.0;
private final double DOTTED_NOTE_MULTIPLIER = 1.5;
private final double TRIPLET_NOTE_MULTIPLIER = 2.0 / 3.0;

private final double MASTER_DELAY_CLOCK_PERIOD = 240000.0;  // 60 whole notes @ 60 BPM.

private final double DELAY_SLEW_FACTOR = 0.99995;         // Roughly 10 seconds RC factor


// Variables

private String BPMDisplayedValue;
private String NoteLengthDisplayedValue;
private String DelayTimeDisplayedValue;
private double currentKnobTempo;
private double previousKnobTempo;
private double previousDisplayedTempo;
private double currentNoteLength;
private double previousNoteLength;
private double previousDisplayedLength;
private double currentNoteValue;
private double previousNoteValue;
private double currentDelay;
private double previousDelay;
private double previousDisplayedDelay;
private double slewedDelay;
private double outputZeitDelay;
private boolean hostModeEnabled;
private boolean overflowZeit;
private boolean previousOverflowZeit;
private boolean lagEnabled;


// Objects

// Functions

private void SetTempoValue()
{
   currentKnobTempo = tempoKnob.GetValue();
   BPMDisplayedValue = String.format("%3.1f BPM", currentKnobTempo);
}

private void SetTempoFromHost()
{
   currentKnobTempo = GetTempo();
   BPMDisplayedValue = String.format("%3.1f BPM", currentKnobTempo);
}

private void UpdateTempoDisplay()
{
   tempoDisplay.SetText(BPMDisplayedValue);
   previousDisplayedTempo = currentKnobTempo;
}

private void SetNoteLength()
{
   int knobPos;
   
   knobPos = (int) round (noteLengthKnob.GetValue());
   
   switch(knobPos)
   {
      case 0:
      {
         NoteLengthDisplayedValue = "Whole note";
         currentNoteLength = 1.0;
      }
      break;
      
      case 1:
      {
         NoteLengthDisplayedValue = "1/2 note";
         currentNoteLength = 0.5;
      }
      break;
      
      case 2:
      {
         NoteLengthDisplayedValue = "1/4 note";
         currentNoteLength = 0.25;
      }
      break;
      
      case 3:
      {
         NoteLengthDisplayedValue = "1/8 note";
         currentNoteLength = 0.125;
      }
      break;
      
      case 4:
      {
         NoteLengthDisplayedValue = "1/16 note";
         currentNoteLength = 0.0625;
      }
      break;
      
      case 5:
      {
         NoteLengthDisplayedValue = "1/32 note";
         currentNoteLength = 0.03125;
      }
      break;
      
      case 6:
      {
         NoteLengthDisplayedValue = "1/64 note";
         currentNoteLength = 0.015625;
      }
      break;
      
   }
   
}

private void UpdateNoteLengthDisplay()
{
   noteLengthDisplay.SetText(NoteLengthDisplayedValue);
   previousDisplayedLength = currentNoteLength;
}

private void SetNoteValue()
{
   int switchPos;
   
   switchPos = (int) round (noteValueSwitch.GetValue());
   
   switch (switchPos)
   {
      case 2:
      {
         // Single timing
         currentNoteValue = SINGLE_NOTE_MULTIPLIER;
      }
      break;
      
      case 1:
      {
         // Dotted timing
         currentNoteValue = DOTTED_NOTE_MULTIPLIER;
      }
      break;
      
      case 0:
      {
         // Triplet timing
         currentNoteValue = TRIPLET_NOTE_MULTIPLIER;
      }
      break;
           
   }
}

private void CalculateDelayTime()
{
   double temp;
   
   // Calculate delay period of one whole beat.
   temp = MASTER_DELAY_CLOCK_PERIOD / currentKnobTempo;
   
   // Now, adjust according to Note Length and Note Value settings.
   currentDelay = temp * currentNoteLength * currentNoteValue;
}

private void UpdateDelayTimeDisplay()
{
   DelayTimeDisplayedValue = String.format("%4.2f ms", currentDelay);
   delayTimeDisplay.SetText(DelayTimeDisplayedValue);
   previousDelay = currentDelay;
}

private void SetManHostMode()
{
   hostModeEnabled = (manHostSwitch.GetValue() > 0.5);
   tempoKnob.SetEnabled(!hostModeEnabled);
   if (hostModeEnabled)
   {
      SetTempoFromHost();
   }
   else
   {
      SetTempoValue();
   }
}

private void UpdateOverflowLED()
{
   if (overflowZeit)
   {
      overflowLED.SetValue(1.0);
   }
   else
   {
      overflowLED.SetValue(0.0);
   }
   
   previousOverflowZeit = overflowZeit;
   
}

private void SetLagValue (double lag)
{
   lagEnabled = (lag > 0.5);
}


//[/user-code-and-variables]
}

 