MainForm.cs
//**********************************************************
//* MidiOut exaple *
//* Author: D. Zouchinski *
//* http://zouchinski.co.uk *
//* Copyright @ 2011-2012 *
//**********************************************************
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace MidiOutExample
{
public partial class MainForm : Form
{
private MidiOut.Controller controller;
private uint note;
private bool major;
private bool minor;
public MainForm()
{
InitializeComponent();
Rectangle area = Screen.PrimaryScreen.WorkingArea;
this.StartPosition = FormStartPosition.Manual;
this.Location = new Point(area.Left, area.Top);
this.Width = Screen.PrimaryScreen.WorkingArea.Width;
foreach (string device in MidiOut.Controller.GetMidiOutDevices())
cmbDevices.Items.Add(device);
cmbDevices.SelectedIndex = 0;
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
}
private void cmbDevices_SelectedIndexChanged(object sender, EventArgs e)
{
if (controller != null)
{
controller.Dispose();
controller = null;
}
if (cmbDevices.SelectedIndex < 0)
return;
controller = new MidiOut.Controller((uint)cmbDevices.SelectedIndex);
// Update instrument list
cmbChannel.Items.Clear();
cmbChannel.Items.AddRange(Categories());
cmbChannel.SelectedIndex = 0;
}
private uint GetNote(Point location)
{
uint note = (uint)((128 * location.X) / boxKeys.ClientRectangle.Width);
uint octave = note / 12;
uint key = note % 12;
if (location.Y * 3 > boxKeys.ClientRectangle.Height * 2)
{
Rectangle rect = boxKeys.ClientRectangle;
Rectangle keyRect = rect;
keyRect.X = ((int)note * rect.Width) / 128;
keyRect.Width = (((int)note + 1) * rect.Width) / 128 - keyRect.X;
switch (key)
{
case 1:
case 3:
case 6:
case 8:
case 10:
if (location.X - keyRect.X < keyRect.Width / 2)
note -= 1;
else
note += 1;
break;
}
}
return note;
}
private void PlayNote(Point location)
{
note = GetNote(location);
controller.PlayNote(0, note);
if (ModifierKeys == Keys.Shift)
{
controller.PlayNote(0, note + 4);
controller.PlayNote(0, note + 7);
major = true;
}
if (ModifierKeys == Keys.Control)
{
controller.PlayNote(0, note + 3);
controller.PlayNote(0, note + 7);
minor = true;
}
}
private void StopNote()
{
controller.StopNote(0, note);
if (major)
{
controller.StopNote(0, note + 4);
controller.StopNote(0, note + 7);
major = false;
}
if (minor)
{
controller.StopNote(0, note + 3);
controller.StopNote(0, note + 7);
minor = false;
}
}
private void boxKeys_MouseDown(object sender, MouseEventArgs e)
{
if (cmbChannel.SelectedIndex < 0)
return;
if (e.Button != MouseButtons.Left)
return;
boxKeys.Capture = true;
PlayNote(e.Location);
}
private void boxKeys_MouseUp(object sender, MouseEventArgs e)
{
if (cmbChannel.SelectedIndex < 0)
return;
if (e.Button != MouseButtons.Left)
return;
boxKeys.Capture = false;
StopNote();
}
private void boxKeys_MouseMove(object sender, MouseEventArgs e)
{
if (cmbChannel.SelectedIndex < 0)
return;
if (e.Button != MouseButtons.Left)
return;
if (note == GetNote(e.Location))
return;
StopNote();
PlayNote(e.Location);
}
private void boxKeys_Paint(object sender, PaintEventArgs e)
{
Rectangle rect = boxKeys.ClientRectangle;
Graphics dc = e.Graphics;
using (Brush brush = new SolidBrush(Color.White))
dc.FillRectangle(brush, rect);
for (int note = 0; note < 128; note++)
{
Rectangle keyRect = rect;
keyRect.X = (note * rect.Width) / 128;
keyRect.Width = ((note + 1) * rect.Width) / 128 - keyRect.X;
int octave = note / 12;
int key = note % 12;
switch (key)
{
case 0:
case 5:
keyRect.Width += rect.Width / 256;
break;
case 2:
case 7:
case 9:
keyRect.X -= rect.Width / 256;
keyRect.Width += (rect.Width / 256) * 2;
break;
case 4:
case 11:
keyRect.X -= rect.Width / 256;
keyRect.Width += rect.Width / 256;
break;
case 1:
case 3:
case 6:
case 8:
case 10:
keyRect.Height -= keyRect.Height / 3;
break;
}
switch (key)
{
case 0:
case 2:
case 4:
case 5:
case 7:
case 9:
case 11:
using (Pen pen = new Pen(Color.Black))
dc.DrawRectangle(pen, keyRect);
break;
case 1:
case 3:
case 6:
case 8:
case 10:
using (Brush brush = new SolidBrush(Color.Black))
dc.FillRectangle(brush, keyRect);
break;
}
}
}
private void boxKeys_SizeChanged(object sender, EventArgs e)
{
boxKeys.Invalidate();
}
private void cmbChannel_SelectedIndexChanged(object sender, EventArgs e)
{
if (boxKeys.Capture)
{
boxKeys.Capture = false;
StopNote();
}
PopulateInstruments();
}
private void cmbInstrument_SelectedIndexChanged(object sender, EventArgs e)
{
if (boxKeys.Capture)
{
boxKeys.Capture = false;
StopNote();
}
if (cmbChannel.SelectedIndex >= 0 && cmbInstrument.SelectedIndex >= 0)
{
int instrument = cmbChannel.SelectedIndex * 8 + cmbInstrument.SelectedIndex;
controller.SetInstrument(0, (uint)instrument);
}
}
private string[] Categories()
{
List<string> list = new List<string>();
var categories = MidiOut.Controller.GetInstrumentCategories();
foreach (var item in categories)
list.Add(item.Name);
return list.ToArray();
}
private string[] Instruments()
{
if (cmbChannel.SelectedIndex < 0)
return new string[] { };
var categories = MidiOut.Controller.GetInstrumentCategories();
return categories[cmbChannel.SelectedIndex].Instruments;
}
private void PopulateInstruments()
{
cmbInstrument.Items.Clear();
foreach(string item in Instruments())
cmbInstrument.Items.Add(item);
cmbInstrument.SelectedIndex = 0;
}
}
}