unit fGuitarTuning;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls, Buttons, Spin, PianoPluginIntf;

type
  TfrmGuitarPlugin = class(TForm)
    GroupBox1: TGroupBox;
    SpeedButton1: TSpeedButton;
    SpeedButton2: TSpeedButton;
    SpeedButton3: TSpeedButton;
    SpeedButton4: TSpeedButton;
    SpeedButton5: TSpeedButton;
    SpeedButton6: TSpeedButton;
    SpeedButton7: TSpeedButton;
    Bevel1: TBevel;
    Bevel2: TBevel;
    Bevel3: TBevel;
    Bevel4: TBevel;
    Bevel5: TBevel;
    Bevel6: TBevel;
    Timer1: TTimer;
    SpinEditCapo: TSpinEdit;
    Label1: TLabel;
    BitBtn1: TBitBtn;
    lbl1: TLabel;
    lbl2: TLabel;
    lbl3: TLabel;
    lbl4: TLabel;
    lbl5: TLabel;
    lbl6: TLabel;
    cbKeyboard: TCheckBox;
    procedure cbKeyboardClick(Sender: TObject);
    procedure BitBtn1Click(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure SpeedButton1Click(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    procedure SetSpeedButtonUp;
    procedure FixSpeedButtonGroupIndex;
    procedure SendMidiEvent(Index: Byte; Capo: Integer = 0; Display: Boolean = False);
    { Private declarations }
  public
    { Public declarations }
  end;

var
  frmGuitarPlugin: TfrmGuitarPlugin;

implementation

{$R *.dfm}

uses PianoPlugin;

procedure TfrmGuitarPlugin.SendMidiEvent(Index: Byte; Capo: Integer; Display: Boolean);
var
  Event, Data1, Data2: Byte;
begin
  case index of
    0: begin // 24: Acoustic Guitar (nylon)
        Event := $C1;
        Data1 := $18;
        Data2 := 0
      end;
    1: begin // e5
        Event := $91;
        Data1 := $40 + Capo;
        Data2 := $50;
        Tag := Data1;
      end;
    2: begin // b4
        Event := $91;
        Data1 := $3B + Capo;
        Data2 := $50;
        Tag := Data1;
      end;
    3: begin // g4
        Event := $91;
        Data1 := $37 + Capo;
        Data2 := $50;
        Tag := Data1;
      end;
    4: begin // d4
        Event := $91;
        Data1 := $32 + Capo;
        Data2 := $50;
        Tag := Data1;
      end;
    5: begin // a3
        Event := $91;
        Data1 := $2D + Capo;
        Data2 := $50;
        Tag := Data1;
      end;
    6: begin // e3
        Event := $91;
        Data1 := $28 + Capo;
        Data2 := $50;
        Tag := Data1;
      end;
    7: begin // Last note off
        Event := $81;
        Data1 := Tag;
        Data2 := $40;
      end;
  end;
  SendMessage(HostHandle, WM_PLUGIN_MIDI,
    MakeLong(Event, MakeWord(Data1, Data2)),
    MakeLong(Integer(Display), $FFFF));
end;

procedure TfrmGuitarPlugin.SpeedButton1Click(Sender: TObject);
begin
  if TSpeedButton(Sender).Down then
  begin
    SendMidiEvent(0);
    GroupBox1.Tag := TSpeedButton(Sender).Tag;
    Timer1.Tag := TSpeedButton(Sender).Tag;
    if GroupBox1.Tag = 0 then
      Timer1.Interval := 500 else
      Timer1.Interval := 2000;
    Timer1.Enabled := True;
  end else
  begin
    SendMidiEvent(7, 0, cbKeyboard.Checked);
    Timer1.Enabled := False;
  end;
end;

procedure TfrmGuitarPlugin.BitBtn1Click(Sender: TObject);
begin
  Close;
end;

procedure TfrmGuitarPlugin.cbKeyboardClick(Sender: TObject);
begin
  if not cbKeyboard.Checked then
    SendMidiEvent(7, 0, True);
end;

procedure TfrmGuitarPlugin.FixSpeedButtonGroupIndex;
var
  i: Integer;
begin
  for i := 1 to 7 do
    (FindComponent('SpeedButton' + IntToStr(i)) as TSpeedButton).GroupIndex := 1;
end;

procedure TfrmGuitarPlugin.SetSpeedButtonUp;
var
  i: Integer;
begin
  for i := 1 to 7 do
    (FindComponent('SpeedButton' + IntToStr(i)) as TSpeedButton).Down := False;
end;

procedure TfrmGuitarPlugin.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  SendMidiEvent(7, 0, cbKeyboard.Checked);
  SetSpeedButtonUp;
  Timer1.Enabled := False;
end;

procedure TfrmGuitarPlugin.FormCreate(Sender: TObject);
begin
  FixSpeedButtonGroupIndex;
end;

procedure TfrmGuitarPlugin.Timer1Timer(Sender: TObject);
begin
  if GroupBox1.Tag = 0 then
  begin
    Timer1.Tag := Timer1.Tag - 1;
    if Timer1.Tag < 1 then Timer1.Tag := 6;
  end;
  SendMidiEvent(7, 0, cbKeyboard.Checked);
  SendMidiEvent(Timer1.Tag, SpinEditCapo.Value, cbKeyboard.Checked);
end;

end.

