using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using Sanford.Multimedia.Midi; using Sanford.Multimedia.Midi.UI; namespace BinkBonk { public partial class BinkBonk_control: Form { // This class helps store info about the note that is playing. private class NoteInfo { public int instr; public int val; } private OutputDevice outDevice; // Is this always the proper device ID?? private int outDeviceID = 0; private OutputDeviceDialog outDialog; private NoteInfo curNote; private bool midiStarted; private int binkBonkCounter = 0; enum BinkBonkStatus_e { BINK, BONK }; BinkBonkStatus_e binkBonkStatus; static int VELOCITY = 127; public BinkBonk_control() { midiStarted = false; InitializeComponent(); } protected override void OnLoad(EventArgs e) { //updateParamDisplay(); base.OnLoad(e); curNote = new NoteInfo(); binkBonkStatus = BinkBonkStatus_e.BONK; } private void updateNote(int instrValue, int noteValue) { if (!midiStarted) return; // Build up new note candidate NoteInfo newNote = new NoteInfo(); newNote.instr = instrValue; newNote.val = noteValue; // Keep track; should note be restarted after all channel commands? if (newNote.instr != curNote.instr) { // Change instrument patch (aka program) outDevice.Send(new ChannelMessage(ChannelCommand.ProgramChange, 0, newNote.instr, 0)); } // Restart the note based on what was updated... outDevice.Send(new ChannelMessage(ChannelCommand.NoteOff, 0, curNote.val, 0)); outDevice.Send(new ChannelMessage(ChannelCommand.NoteOn, 0, newNote.val, VELOCITY)); curNote = newNote; } private void killNote() { if (!midiStarted) return; outDevice.Send(new ChannelMessage(ChannelCommand.NoteOff, 0, curNote.val, 0)); } private void btn_startMIDI_Click(object sender, EventArgs e) { if (midiStarted) { closeMidiOutput(); } else { // Try to open midi out. If successful, initialize other stuff if (!openMidiOutput()) return; updateNote((int)(this.instrumentSelectA.Value), (int)(this.noteSelectA.Value)); killNote(); } } private void BinkBonk_FormClosing(object sender, FormClosingEventArgs e) { closeMidiOutput(); /* // USE THE FOLLOWING IN A LARGER APPLICATION this.Hide(); e.Cancel = true; */ } private bool openMidiOutput() { outDialog = new OutputDeviceDialog(); if (OutputDevice.DeviceCount == 0) { MessageBox.Show("No MIDI output devices available.", "Error!", MessageBoxButtons.OK, MessageBoxIcon.Stop); return false; } else { try { outDevice = new OutputDevice(outDeviceID); } catch (Exception ex) { MessageBox.Show(ex.Message, "Error!", MessageBoxButtons.OK, MessageBoxIcon.Stop); return false; } } // Flag that MIDI output has successfully initialized midiStarted = true; btn_startMIDI.Text = "Stop MIDI"; btn_startMIDI.BackColor = Color.LightCoral; return true; } private void closeMidiOutput() { // Flag that MIDI out will/has stop(ped) midiStarted = false; btn_startMIDI.Text = "Start MIDI"; btn_startMIDI.BackColor = Color.DarkSeaGreen; try { if (outDevice != null && !outDevice.IsDisposed) outDevice.Dispose(); } catch (Exception e) { } } public void handleEPC(String EPC) { // Learn the current EPC value if (learn_A.Checked) { EPC_A.Text = EPC; learn_A.Checked = false; } else if (learn_B.Checked) { EPC_B.Text = EPC; learn_B.Checked = false; } //if EPC == EPC_A if(EPC.Equals(this.EPC_A.Text)) { if (binkBonkCounter < 2) { binkBonkCounter++; } // If we last BONKed if (binkBonkStatus == BinkBonkStatus_e.BONK && binkBonkCounter > 0) { // Bink this.updateNote((int)(instrumentSelectA.Value), (int)(noteSelectA.Value)); binkBonkStatus = BinkBonkStatus_e.BINK; } } // If EPC == EPC_B if(EPC.Equals(this.EPC_B.Text)) { if (binkBonkCounter > -2) { binkBonkCounter--; } // If we last BINKed if (binkBonkStatus == BinkBonkStatus_e.BINK && binkBonkCounter < 0) { // Bink this.updateNote((int)(instrumentSelectB.Value), (int)(noteSelectB.Value)); binkBonkStatus = BinkBonkStatus_e.BONK; } } } } }