#region License
/* Copyright (c) 2007 Leslie Sanford
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#endregion
#region Contact
/*
* Leslie Sanford
* Email: jabberdabber@hotmail.com
*/
#endregion
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using Sanford.Multimedia.Midi;
using Sanford.Multimedia.Midi.UI;
using Sanford.Multimedia.Wave;
namespace Sanford.Multimedia.Synth.UI
{
/// <summary>
/// Represents the main window in an application that hosts a Synthesizer.
/// </summary>
public abstract partial class SynthHostForm : Form
{
#region SynthHostForm Members
#region Fields
// File name used for saving configuration data.
private static readonly string ConfigurationFileName = "HostPreferences.dat";
// MIDI input device used for receiving MIDI messages.
private InputDevice midiInputDevice = null;
// The Synthesizer this application is hosting.
private Synthesizer synth;
// Provides a generic user interface to the Synthesizer.
private SynthControlForm synthControlForm1;
// For playing the Synthesizer from the mouse.
private PianoControlForm pianoKeyboardForm1;
// Custom user interface editor provided by derived classes.
private Form editorForm;
// For choosing which MIDI input device to use.
private InputDeviceDialog midiInDeviceDialog = new InputDeviceDialog();
// For choosing which wave output device to use.
private Sanford.Multimedia.Wave.UI.OutputDeviceDialog waveOutDeviceDialog = new Sanford.Multimedia.Wave.UI.OutputDeviceDialog();
// For setting the buffer size.
private BufferSizeDialog bufferSizeDialog = new BufferSizeDialog();
// For setting the sample rate.
private SampleRateDialog sampleRateDialog = new SampleRateDialog();
// For setting the MIDI channel and omni mode.
private MidiChannelDialog midiChannelDialog = new MidiChannelDialog();
// Device ID for the wave output device.
private int wavedeviceId = 0;
// Device ID for the MIDI input device.
private int midiInputdeviceId = 0;
// Indicates whether the current bank has been saved.
private bool saved = false;
// The directory this application originates from. Used for
// saving configuration data.
private string originalDirectory;
#endregion
#region Constructors
/// <summary>
/// Initializes a new instance of the SynthHostForm class.
/// </summary>
protected SynthHostForm()
{
InitializeComponent();
}
#endregion
#region Methods
protected override void OnLoad(EventArgs e)
{
try
{
originalDirectory = Directory.GetCurrentDirectory();
LoadConfiguration();
if(Sanford.Multimedia.Wave.OutputDevice.DeviceCount > 0)
{
waveOutDeviceDialog.DeviceID = wavedeviceId;
synth = CreateSynthesizer(wavedeviceId, bufferSizeDialog.BufferSize, sampleRateDialog.SampleRate);
synth.Error += HandleError;
CreateSynthControlForm();
synthControlToolStripMenuItem.CheckOnClick = true;
synthControlToolStripMenuItem.Checked = true;
CreatePianoKeyboardForm();
pianoKeyboardToolStripMenuItem.CheckOnClick = true;
pianoKeyboardToolStripMenuItem.Checked = true;
if(HasEditor)
{
CreateEditorForm();
editorToolStripMenuItem.CheckOnClick = true;
editorToolStripMenuItem.Checked = true;
}
else
{
editorToolStripMenuItem.CheckOnClick = false;
}
if(InputDevice.DeviceCount > 0)
{
midiInDeviceDialog.InputDeviceID = midiInputdeviceId;
midiInputDevice = new InputDevice(midiInputdeviceId);
midiInputDevice.StartRecording();
midiInputDevice.ChannelMessageReceived += ChannelMessageConnector;
}
else
{
MessageBox.Show("No MIDI input devices available.", "Warning!", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
synth.Play();
}
else
{
DisplayError("No wave devices available.");
Close();
}
}
catch(Sanford.Multimedia.Wave.OutputDeviceException ex)
{
DisplayError(ex.Message);
Close();
}
catch(Sanford.Multimedia.Midi.InputDeviceException ex)
{
DisplayError(ex.Message);
}
finally
{
base.OnLoad(e);
}
}
protected override void OnClosed(EventArgs e)
{
try
{
SaveConfiguration();
}
catch(IOException ex)
{
DisplayError(ex.Message);
}
finally
{
if(midiInputDevice != null)
{
midiInputDevice.Dispose();
}
if(synth != null)
{
synth.Dispose();
}
midiInDeviceDialog.Dispose();
bufferSizeDialog.Dispose();
sampleRateDialog.Dispose();
waveOutDeviceDialog.Dispose();
midiChannelDialog.Dispose();
base.OnClosed(e);
}
}
#region Menu Items
private void openToolStripMenuItem_Click(object sender, EventArgs e)
{
if(openBankFileDialog.ShowDialog() == DialogResult.OK)
{
try
{
string fileName = openBankFileDialog.FileName;
synth.LoadBank(fileName);
saveBankFileDialog.FileName = fileName;
saved = true;
}
catch(IOException ex)
{
DisplayError(ex.Message);
}
catch(FileException ex)
{
DisplayError(ex.Message);
}
}
}
private void saveToolStripMenuItem_Click(object sender, EventArgs e)
{
if(saved)
{
try
{
string fileName = saveBankFileDialog.FileName;
synth.SaveBank(fileName);
}
catch(IOException ex)
{
DisplayError(ex.Message);
}
catch(FileException ex)
{
DisplayError(ex.Message);
}
}
else
{
saveAsToolStripMenuItem_Click(sender, e);
}
}
private void saveAsToolStripMenuItem_Click(object sender, EventArgs e)
{
if(saveBankFileDialog.ShowDialog() == DialogResult.OK)
{
try
{
string fileName = saveBankFileDialog.FileName;
synth.SaveBank(fileName);
saved = true;
}
catch(IOException ex)
{
DisplayError(ex.Message);
}
catch(FileException ex)
{
DisplayError(ex.Message);
}
}
}
private void openProgramToolStripMenuItem_Click(object sender, EventArgs e)
{
if(openProgramFileDialog.ShowDialog() == DialogResult.OK)
{
try
{
string fileName = openProgramFileDialog.FileName;
synth.LoadProgram(fileName);
}
catch(IOException ex)
{
DisplayError(ex.Message);
}
catch(FileException ex)
{
DisplayError(ex.Message);
}
}
}
private void saveProgramAsToolStripMenuItem_Click(object sender, EventArgs e)
{
if(saveProgramFileDialog.ShowDialog() == DialogResult.OK)
{
try
{
string fileName = saveProgramFileDialog.FileName;
synth.SaveProgram(fileName);
}
catch(IOException ex)
{
DisplayError(ex.Message);
}
catch(FileException ex)
{
DisplayError(ex.Message);
}
}
}
private void exitToolStripMenuItem_Click(object sender, EventArgs e)
{
Close();
}
private void midiToolStripMenuItem_Click(object sender, EventArgs e)
{
if(midiInDeviceDialog.ShowDialog() == DialogResult.OK &&
InputDevice.DeviceCount > 0 &&
midiInDeviceDialog.InputDeviceID != midiInputDevice.DeviceID)
{
try
{
InputDevice newInDevice = new InputDevice(midiInDeviceDialog.InputDeviceID);
midiInputDevice.Dispose();
midiInputDevice = newInDevice;
midiInputDevice.StartRecording();
midiInputDevice.ChannelMessageReceived += ChannelMessageConnector;
}
catch(InputDeviceException ex)
{
DisplayError(ex.Message);
}
}
}
private void waveToolStripMenuItem_Click(object sender, EventArgs e)
{
if(waveOutDeviceDialog.ShowDialog() == DialogResult.OK)
{
try
{
synth.SetWaveDevice(waveOutDeviceDialog.DeviceID);
}
catch(Sanford.Multimedia.Wave.OutputDeviceException ex)
{
DisplayError(ex.Message);
}
}
}
private void bufferSizeToolStripMenuItem_Click(object sender, EventArgs e)
{
if(bufferSizeDialog.ShowDialog() == DialogResult.OK)
{
int oldBufferSize = synth.BufferSize;
try
{
synth.SetBufferSize(bufferSizeDialog.BufferSize);
}
catch(ArgumentOutOfRangeException ex)
{
DisplayError(ex.Message);
bufferSizeDialog.BufferSize = oldBufferSize;
}
}
}
private void sampleRateToolStripMenuItem_Click(object sender, EventArgs e)
{
if(sampleRateDialog.ShowDialog() == DialogResult.OK)
{
int oldSampleRate = synth.SampleRate;
try
{
synth.SetSampleRate(sampleRateDialog.SampleRate);
}
catch(Sanford.Multimedia.Wave.OutputDeviceException ex)
{
DisplayError(ex.Message);
sampleRateDialog.SampleRate = oldSampleRate;
}
}
}
private void midiChannelToolStripMenuItem_Click(object sender, EventArgs e)
{
if(midiChannelDialog.ShowDialog() == DialogResult.OK)
{
synth.MidiChannel = midiChannelDialog.MidiChannel - 1;
synth.OmniEnabled = midiChannelDialog.OmniEnabled;
pianoKeyboardForm1.MidiChannel = midiChannelDialog.MidiChannel;
}
}
private void synthControlToolStripMenuItem_Click(object sender, EventArgs e)
{
if(synthControlToolStripMenuItem.Checked)
{
if(synthControlForm1 != null)
{
synthControlForm1.Show();
}
else
{
CreateSynthControlForm();
}
}
else
{
synthControlForm1.Hide();
}
}
private void pianoKeyboardToolStripMenuItem_Click(object sender, EventArgs e)
{
if(pianoKeyboardToolStripMenuItem.Checked)
{
if(pianoKeyboardForm1 != null)
{
pianoKeyboardForm1.Show();
}
else
{
CreatePianoKeyboardForm();
}
}
else
{
pianoKeyboardForm1.Hide();
}
}
private void editorToolStripMenuItem_Click(object sender, EventArgs e)
{
if(HasEditor)
{
if(editorToolStripMenuItem.Checked)
{
if(editorForm != null)
{
editorForm.Show();
}
else
{
CreateEditorForm();
}
}
else
{
editorForm.Hide();
}
}
}
private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
{
SynthHostAboutBox aboutBox = new SynthHostAboutBox();
aboutBox.ShowDialog();
}
#endregion
private void LoadConfiguration()
{
if(File.Exists(ConfigurationFileName))
{
try
{
using(FileStream stream = new FileStream(ConfigurationFileName, FileMode.Open, FileAccess.Read))
{
BinaryReader reader = new BinaryReader(stream);
bufferSizeDialog.BufferSize = reader.ReadInt32();
sampleRateDialog.SampleRate = reader.ReadInt32();
wavedeviceId = reader.ReadInt32();
midiInputdeviceId = reader.ReadInt32();
if (wavedeviceId >= Sanford.Multimedia.Wave.OutputDevice.DeviceCount)
{
wavedeviceId = 0;
}
if (midiInputdeviceId >= InputDevice.DeviceCount)
{
midiInputdeviceId = 0;
}
}
}
catch(IOException ex)
{
DisplayError(ex.Message);
}
}
}
private void SaveConfiguration()
{
if(synth != null)
{
Directory.SetCurrentDirectory(originalDirectory);
using(FileStream stream = new FileStream(ConfigurationFileName, FileMode.Create, FileAccess.Write))
{
BinaryWriter writer = new BinaryWriter(stream);
writer.Write(synth.BufferSize);
writer.Write(synth.SampleRate);
writer.Write(waveOutDeviceDialog.DeviceID);
if(midiInputDevice != null)
{
writer.Write(midiInDeviceDialog.InputDeviceID);
}
else
{
writer.Write(0);
}
writer.Close();
}
}
}
private void CreateSynthControlForm()
{
synthControlForm1 = new SynthControlForm(synth);
synthControlForm1.MdiParent = this;
synthControlForm1.Show();
synthControlForm1.Disposed += delegate(object sender, EventArgs se)
{
synthControlToolStripMenuItem.Checked = false;
synthControlForm1 = null;
};
}
private void CreatePianoKeyboardForm()
{
pianoKeyboardForm1 = new PianoControlForm();
pianoKeyboardForm1.Disposed += delegate(object sender, EventArgs pe)
{
pianoKeyboardToolStripMenuItem.Checked = false;
pianoKeyboardForm1 = null;
};
pianoKeyboardForm1.MdiParent = this;
pianoKeyboardForm1.Show();
pianoKeyboardForm1.NotePlayed += ChannelMessageConnector;
}
private void CreateEditorForm()
{
Debug.Assert(HasEditor);
editorForm = CreateEditor(synth);
editorForm.Disposed += delegate(object sender, EventArgs ee)
{
editorToolStripMenuItem.Checked = false;
editorForm = null;
};
editorForm.MdiParent = this;
editorForm.Show();
}
private void ChannelMessageConnector(object sender, ChannelMessageEventArgs e)
{
synth.ProcessChannelMessage(e.Message);
}
private void HandleError(object sender, ErrorEventArgs e)
{
DisplayError(e.Error.Message);
}
private static void DisplayError(string message)
{
MessageBox.Show(message, "Error!", MessageBoxButtons.OK, MessageBoxIcon.Stop);
}
#endregion
#region Abstract Members
protected abstract Synthesizer CreateSynthesizer(int deviceId, int bufferSize, int sampleRate);
protected abstract Form CreateEditor(Synthesizer synth);
protected abstract bool HasEditor
{
get;
}
#endregion
#endregion
}
}