diff --git a/tools/midi2piano/midi2piano.sln b/tools/midi2piano/midi2piano.sln
new file mode 100644
index 00000000000..7636dd66d86
--- /dev/null
+++ b/tools/midi2piano/midi2piano.sln
@@ -0,0 +1,30 @@
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual C# Express 2010
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "midi2piano", "midi2piano\midi2piano.csproj", "{68C84B61-F710-491C-BEE8-5E362C167897}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Debug|Mixed Platforms = Debug|Mixed Platforms
+ Debug|x86 = Debug|x86
+ Release|Any CPU = Release|Any CPU
+ Release|Mixed Platforms = Release|Mixed Platforms
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {68C84B61-F710-491C-BEE8-5E362C167897}.Debug|Any CPU.ActiveCfg = Debug|x86
+ {68C84B61-F710-491C-BEE8-5E362C167897}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
+ {68C84B61-F710-491C-BEE8-5E362C167897}.Debug|Mixed Platforms.Build.0 = Debug|x86
+ {68C84B61-F710-491C-BEE8-5E362C167897}.Debug|x86.ActiveCfg = Debug|x86
+ {68C84B61-F710-491C-BEE8-5E362C167897}.Debug|x86.Build.0 = Debug|x86
+ {68C84B61-F710-491C-BEE8-5E362C167897}.Release|Any CPU.ActiveCfg = Release|x86
+ {68C84B61-F710-491C-BEE8-5E362C167897}.Release|Mixed Platforms.ActiveCfg = Release|x86
+ {68C84B61-F710-491C-BEE8-5E362C167897}.Release|Mixed Platforms.Build.0 = Release|x86
+ {68C84B61-F710-491C-BEE8-5E362C167897}.Release|x86.ActiveCfg = Release|x86
+ {68C84B61-F710-491C-BEE8-5E362C167897}.Release|x86.Build.0 = Release|x86
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/tools/midi2piano/midi2piano.v12.suo b/tools/midi2piano/midi2piano.v12.suo
new file mode 100644
index 00000000000..b1f442d7eb4
Binary files /dev/null and b/tools/midi2piano/midi2piano.v12.suo differ
diff --git a/tools/midi2piano/midi2piano/Form1.Designer.cs b/tools/midi2piano/midi2piano/Form1.Designer.cs
new file mode 100644
index 00000000000..bac3a206301
--- /dev/null
+++ b/tools/midi2piano/midi2piano/Form1.Designer.cs
@@ -0,0 +1,135 @@
+namespace midi2piano
+{
+ partial class Form1
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.OutputTxt = new System.Windows.Forms.TextBox();
+ this.menuStrip1 = new System.Windows.Forms.MenuStrip();
+ this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.importMIDIToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.exitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.copyToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.importDlg = new System.Windows.Forms.OpenFileDialog();
+ this.halpToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.menuStrip1.SuspendLayout();
+ this.SuspendLayout();
+ //
+ // OutputTxt
+ //
+ this.OutputTxt.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.OutputTxt.Location = new System.Drawing.Point(0, 24);
+ this.OutputTxt.Multiline = true;
+ this.OutputTxt.Name = "OutputTxt";
+ this.OutputTxt.ReadOnly = true;
+ this.OutputTxt.ScrollBars = System.Windows.Forms.ScrollBars.Both;
+ this.OutputTxt.Size = new System.Drawing.Size(284, 240);
+ this.OutputTxt.TabIndex = 0;
+ //
+ // menuStrip1
+ //
+ this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.fileToolStripMenuItem,
+ this.copyToolStripMenuItem,
+ this.halpToolStripMenuItem});
+ this.menuStrip1.Location = new System.Drawing.Point(0, 0);
+ this.menuStrip1.Name = "menuStrip1";
+ this.menuStrip1.Size = new System.Drawing.Size(284, 24);
+ this.menuStrip1.TabIndex = 1;
+ this.menuStrip1.Text = "menuStrip1";
+ //
+ // fileToolStripMenuItem
+ //
+ this.fileToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.importMIDIToolStripMenuItem,
+ this.exitToolStripMenuItem});
+ this.fileToolStripMenuItem.Name = "fileToolStripMenuItem";
+ this.fileToolStripMenuItem.Size = new System.Drawing.Size(37, 20);
+ this.fileToolStripMenuItem.Text = "&File";
+ //
+ // importMIDIToolStripMenuItem
+ //
+ this.importMIDIToolStripMenuItem.Name = "importMIDIToolStripMenuItem";
+ this.importMIDIToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.I)));
+ this.importMIDIToolStripMenuItem.Size = new System.Drawing.Size(184, 22);
+ this.importMIDIToolStripMenuItem.Text = "&Import MIDI...";
+ this.importMIDIToolStripMenuItem.Click += new System.EventHandler(this.importMIDIToolStripMenuItem_Click);
+ //
+ // exitToolStripMenuItem
+ //
+ this.exitToolStripMenuItem.Name = "exitToolStripMenuItem";
+ this.exitToolStripMenuItem.Size = new System.Drawing.Size(184, 22);
+ this.exitToolStripMenuItem.Text = "E&xit";
+ this.exitToolStripMenuItem.Click += new System.EventHandler(this.exitToolStripMenuItem_Click);
+ //
+ // copyToolStripMenuItem
+ //
+ this.copyToolStripMenuItem.Name = "copyToolStripMenuItem";
+ this.copyToolStripMenuItem.Size = new System.Drawing.Size(47, 20);
+ this.copyToolStripMenuItem.Text = "&Copy";
+ this.copyToolStripMenuItem.Click += new System.EventHandler(this.copyToolStripMenuItem_Click);
+ //
+ // importDlg
+ //
+ this.importDlg.Filter = "MIDI File|*.midi;*.mid";
+ //
+ // halpToolStripMenuItem
+ //
+ this.halpToolStripMenuItem.Name = "halpToolStripMenuItem";
+ this.halpToolStripMenuItem.Size = new System.Drawing.Size(44, 20);
+ this.halpToolStripMenuItem.Text = "&Halp";
+ this.halpToolStripMenuItem.Click += new System.EventHandler(this.halpToolStripMenuItem_Click);
+ //
+ // Form1
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(284, 264);
+ this.Controls.Add(this.OutputTxt);
+ this.Controls.Add(this.menuStrip1);
+ this.MainMenuStrip = this.menuStrip1;
+ this.Name = "Form1";
+ this.Text = "MIDI2Piano";
+ this.menuStrip1.ResumeLayout(false);
+ this.menuStrip1.PerformLayout();
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.TextBox OutputTxt;
+ private System.Windows.Forms.MenuStrip menuStrip1;
+ private System.Windows.Forms.ToolStripMenuItem fileToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem importMIDIToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem exitToolStripMenuItem;
+ private System.Windows.Forms.OpenFileDialog importDlg;
+ private System.Windows.Forms.ToolStripMenuItem copyToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem halpToolStripMenuItem;
+ }
+}
\ No newline at end of file
diff --git a/tools/midi2piano/midi2piano/Form1.cs b/tools/midi2piano/midi2piano/Form1.cs
new file mode 100644
index 00000000000..727b61f750b
--- /dev/null
+++ b/tools/midi2piano/midi2piano/Form1.cs
@@ -0,0 +1,298 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Windows.Forms;
+
+using Sanford.Multimedia;
+using Sanford.Multimedia.Midi;
+
+namespace midi2piano
+{
+ public partial class Form1 : Form
+ {
+ [STAThread]
+ public static void Main()
+ {
+ Application.EnableVisualStyles();
+ Application.Run(new Form1());
+ }
+
+ public Form1()
+ {
+ InitializeComponent();
+ }
+
+ private void exitToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ Close();
+ }
+
+ struct PNote
+ {
+ public float Length;
+ public string Note;
+
+ public PNote(float length, string note)
+ {
+ Length = length;
+ Note = note;
+ }
+
+ public static readonly PNote Default = new PNote(0, "");
+ }
+
+ private void importMIDIToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ if (importDlg.ShowDialog(this)
+ == System.Windows.Forms.DialogResult.Cancel)
+ return;
+
+ List notes = new List();
+ PNote curNote = PNote.Default;
+ float tempo = 1;
+ float timeSig = 4f;
+
+ // first, we pull midi data
+ Sequence s = new Sequence(importDlg.FileName);
+
+ // quickly see if there's a piano track first
+ // and get the tempo as well
+ int piano = -1;
+ for (int it = 0; it < s.Count; it++)
+ {
+ Track t = s[it];
+ foreach (MidiEvent me in t.Iterator())
+ {
+ switch (me.MidiMessage.MessageType)
+ {
+ case MessageType.Channel:
+ {
+ ChannelMessage m = (ChannelMessage)me.MidiMessage;
+ if (m.Command == ChannelCommand.ProgramChange)
+ if ((GeneralMidiInstrument)m.Data1 == GeneralMidiInstrument.AcousticGrandPiano)
+ {
+ piano = it;
+ }
+ }
+ break;
+ case MessageType.Meta:
+ {
+ MetaMessage m = (MetaMessage)me.MidiMessage;
+ if (m.MetaType == MetaType.Tempo)
+ tempo = (new TempoChangeBuilder(m)).Tempo;
+ else if (m.MetaType == MetaType.TimeSignature)
+ timeSig = new TimeSignatureBuilder(m).Denominator;
+ }
+ break;
+ }
+ if (piano >= 0)
+ break;
+ }
+ if (piano >= 0)
+ break;
+ }
+
+ // didn't find one, so just try 0th track anyway
+ if (piano == -1)
+ piano = 0;
+
+ // now, pull all notes (and tempo)
+ // and make sure it's a channel that has content
+ for (int it = piano; it < s.Count; it++)
+ {
+ Track t = s[it];
+
+ int delta = 0;
+ foreach (MidiEvent me in t.Iterator())
+ {
+ delta += me.DeltaTicks;
+
+ switch (me.MidiMessage.MessageType)
+ {
+ case MessageType.Channel:
+ {
+ ChannelMessage m = (ChannelMessage)me.MidiMessage;
+ switch (m.Command)
+ {
+ case ChannelCommand.NoteOn:
+ if (curNote.Note != "")
+ {
+ curNote.Length = delta / 1000F;
+ delta = 0;
+ notes.Add(curNote);
+ }
+
+ curNote.Note = note2Piano(m.Data1);
+ break;
+ }
+ }
+ break;
+ case MessageType.Meta:
+ {
+ MetaMessage m = (MetaMessage)me.MidiMessage;
+ if (m.MetaType == MetaType.Tempo)
+ tempo = (new TempoChangeBuilder(m)).Tempo;
+ }
+ break;
+ }
+ }
+
+ // make sure we get last note
+ if (curNote.Note != "")
+ {
+ curNote.Length = delta / 1000F;
+ notes.Add(curNote);
+ }
+
+ // we found a track with content!
+ if (notes.Count > 0)
+ break;
+ }
+
+ // compress redundant accidentals/octaves
+ char[] notemods = new char[7];
+ int[] noteocts = new int[7];
+ for (int i = 0; i < 7; i++)
+ {
+ notemods[i] = 'n';
+ noteocts[i] = 3;
+ }
+ for (int i = 0; i < notes.Count; i++)
+ {
+ string noteStr = notes[i].Note;
+ int cur_note = noteStr[0] - 0x41;
+ char mod = noteStr[1];
+ int oct = int.Parse(noteStr.Substring(2));
+
+ noteStr = noteStr.Substring(0, 1);
+ if (mod != notemods[cur_note])
+ {
+ noteStr += new string(mod, 1);
+ notemods[cur_note] = mod;
+ }
+ if (oct != noteocts[cur_note])
+ {
+ noteStr += oct.ToString();
+ noteocts[cur_note] = oct;
+ }
+
+ notes[i] = new PNote(notes[i].Length, noteStr);
+ }
+
+ // now, we find what the "beat" length should be,
+ // by counting numbers of times for each length, and finding statistical mode
+ Dictionary scores = new Dictionary();
+ foreach (PNote n in notes)
+ {
+ if (n.Length != 0)
+ if (scores.Keys.Contains(n.Length))
+ scores[n.Length]++;
+ else
+ scores.Add(n.Length, 1);
+ }
+ float winner = 1;
+ int score = 0;
+ foreach (KeyValuePair kv in scores)
+ {
+ if (kv.Value > score)
+ {
+ winner = kv.Key;
+ score = kv.Value;
+ }
+ }
+ // realign all of them to match beat length
+ for (int i = 0; i < notes.Count; i++)
+ {
+ notes[i] = new PNote(notes[i].Length / winner, notes[i].Note);
+ }
+
+ // compress chords down
+ for (int i = 0; i < notes.Count; i++)
+ {
+ if (notes[i].Length == 0 && i < notes.Count - 1)
+ {
+ notes[i + 1] = new PNote(notes[i + 1].Length, notes[i].Note + "-" + notes[i + 1].Note);
+ notes.RemoveAt(i);
+ i--;
+ }
+ }
+
+ // add in time
+ for (int i = 0; i < notes.Count; i++)
+ {
+ float len = notes[i].Length;
+ notes[i] = new PNote(len, notes[i].Note + (len != 1 ? "/" + (1 / len).ToString("0.##") : ""));
+ }
+
+ // what is the bpm, anyway?
+ int rpm = (int)(28800000 / tempo / winner); // 60 * 1,000,000 * .48 the .48 is because note lengths for some reason midi makes the beat note be .48 long
+
+ // now, output!
+ string line = "";
+ string output = "";
+ int lineCount = 1;
+ foreach (PNote n in notes)
+ {
+ if (line.Length + n.Note.Length + 1 > 51)
+ {
+ output += line.Substring(0, line.Length - 1) + "\r\n";
+ line = "";
+ if (lineCount == 50)
+ break;
+ lineCount++;
+ }
+ line += n.Note + ",";
+ }
+ if (line.Length > 0)
+ output += line.Substring(0, line.Length - 1);
+ OutputTxt.Text = "BPM: " + rpm.ToString() + "\r\n" + output;
+ OutputTxt.SelectAll();
+ }
+
+ public enum NoteNames
+ {
+ C = 0,
+ D = 2,
+ E = 4,
+ F = 5,
+ G = 7,
+ A = 9,
+ B = 11
+ }
+
+ string note2Piano(int n)
+ {
+ string name, arg, octave;
+ name = Enum.GetName(typeof(NoteNames), (NoteNames)(n % 12));
+ if (name == null)
+ {
+ name = Enum.GetName(typeof(NoteNames), (NoteNames)((n + 1) % 12));
+ arg = "b";
+ }
+ else
+ {
+ arg = "n";
+ }
+ octave = (n / 12 - 1).ToString();
+
+ return name + arg + octave;
+ }
+
+ private void copyToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ OutputTxt.SelectAll();
+ OutputTxt.Copy();
+ }
+
+ private void halpToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ MessageBox.Show(this,
+ "This program prefers MIDIs that have a single track, otherwise it picks the first piano track it finds, else the first track. Songs with odd tempos may have their BPM's calculated wrong.",
+ "Halp", MessageBoxButtons.OK, MessageBoxIcon.Information);
+ }
+ }
+}
diff --git a/tools/midi2piano/midi2piano/Form1.resx b/tools/midi2piano/midi2piano/Form1.resx
new file mode 100644
index 00000000000..b76de494d02
--- /dev/null
+++ b/tools/midi2piano/midi2piano/Form1.resx
@@ -0,0 +1,126 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ 17, 17
+
+
+ 132, 17
+
+
\ No newline at end of file
diff --git a/tools/midi2piano/midi2piano/Properties/AssemblyInfo.cs b/tools/midi2piano/midi2piano/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000000..f968b018893
--- /dev/null
+++ b/tools/midi2piano/midi2piano/Properties/AssemblyInfo.cs
@@ -0,0 +1,34 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("midi2piano")]
+[assembly: AssemblyProduct("midi2piano")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyCopyright("Copyright © 2011")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type. Only Windows
+// assemblies support COM.
+[assembly: ComVisible(false)]
+
+// On Windows, the following GUID is for the ID of the typelib if this
+// project is exposed to COM. On other platforms, it unique identifies the
+// title storage container when deploying this assembly to the device.
+[assembly: Guid("9752c562-edc1-40da-8fa1-619df747e0f3")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+[assembly: AssemblyVersion("1.0.0.0")]
diff --git a/tools/midi2piano/midi2piano/Sanford.Multimedia.Midi.dll b/tools/midi2piano/midi2piano/Sanford.Multimedia.Midi.dll
new file mode 100644
index 00000000000..28a707657b3
Binary files /dev/null and b/tools/midi2piano/midi2piano/Sanford.Multimedia.Midi.dll differ
diff --git a/tools/midi2piano/midi2piano/bin/x86/Release/Sanford.Multimedia.Midi.dll b/tools/midi2piano/midi2piano/bin/x86/Release/Sanford.Multimedia.Midi.dll
new file mode 100644
index 00000000000..28a707657b3
Binary files /dev/null and b/tools/midi2piano/midi2piano/bin/x86/Release/Sanford.Multimedia.Midi.dll differ
diff --git a/tools/midi2piano/midi2piano/bin/x86/Release/midi2piano.exe b/tools/midi2piano/midi2piano/bin/x86/Release/midi2piano.exe
new file mode 100644
index 00000000000..7d718cde4db
Binary files /dev/null and b/tools/midi2piano/midi2piano/bin/x86/Release/midi2piano.exe differ
diff --git a/tools/midi2piano/midi2piano/midi2piano.csproj b/tools/midi2piano/midi2piano/midi2piano.csproj
new file mode 100644
index 00000000000..c56cf02d57b
--- /dev/null
+++ b/tools/midi2piano/midi2piano/midi2piano.csproj
@@ -0,0 +1,83 @@
+
+
+
+ Debug
+ x86
+ WinExe
+ Properties
+ midi2piano
+ midi2piano
+ v4.0
+ Client
+
+
+ true
+ full
+ false
+ bin\x86\Debug
+ DEBUG;TRACE;WINDOWS
+ prompt
+ 4
+ true
+ false
+ x86
+
+
+ pdbonly
+ true
+ bin\x86\Release
+ TRACE;WINDOWS
+ prompt
+ 4
+ true
+ false
+ x86
+
+
+
+
+
+
+ False
+
+
+ False
+ .\Sanford.Multimedia.Midi.dll
+
+
+ False
+
+
+
+
+
+ False
+
+
+ 4.0
+ False
+
+
+ 4.0
+ False
+
+
+ False
+
+
+
+
+ Form
+
+
+ Form1.cs
+
+
+
+
+
+ Form1.cs
+
+
+
+
\ No newline at end of file
diff --git a/tools/midi2piano/midi2piano/obj/x86/Debug/DesignTimeResolveAssemblyReferencesInput.cache b/tools/midi2piano/midi2piano/obj/x86/Debug/DesignTimeResolveAssemblyReferencesInput.cache
new file mode 100644
index 00000000000..c1f743de53a
Binary files /dev/null and b/tools/midi2piano/midi2piano/obj/x86/Debug/DesignTimeResolveAssemblyReferencesInput.cache differ
diff --git a/tools/midi2piano/README.txt b/tools/py-midi2piano/README.txt
similarity index 100%
rename from tools/midi2piano/README.txt
rename to tools/py-midi2piano/README.txt
diff --git a/tools/midi2piano/easygui/__init__.py b/tools/py-midi2piano/easygui/__init__.py
similarity index 100%
rename from tools/midi2piano/easygui/__init__.py
rename to tools/py-midi2piano/easygui/__init__.py
diff --git a/tools/midi2piano/midi/__init__.py b/tools/py-midi2piano/midi/__init__.py
similarity index 100%
rename from tools/midi2piano/midi/__init__.py
rename to tools/py-midi2piano/midi/__init__.py
diff --git a/tools/midi2piano/midi/midi.py b/tools/py-midi2piano/midi/midi.py
similarity index 100%
rename from tools/midi2piano/midi/midi.py
rename to tools/py-midi2piano/midi/midi.py
diff --git a/tools/midi2piano/midi2piano.py b/tools/py-midi2piano/midi2piano.py
similarity index 100%
rename from tools/midi2piano/midi2piano.py
rename to tools/py-midi2piano/midi2piano.py
diff --git a/tools/midi2piano/pyperclip/__init__.py b/tools/py-midi2piano/pyperclip/__init__.py
similarity index 100%
rename from tools/midi2piano/pyperclip/__init__.py
rename to tools/py-midi2piano/pyperclip/__init__.py
diff --git a/tools/midi2piano/pyperclip/clipboards.py b/tools/py-midi2piano/pyperclip/clipboards.py
similarity index 100%
rename from tools/midi2piano/pyperclip/clipboards.py
rename to tools/py-midi2piano/pyperclip/clipboards.py
diff --git a/tools/midi2piano/pyperclip/exceptions.py b/tools/py-midi2piano/pyperclip/exceptions.py
similarity index 100%
rename from tools/midi2piano/pyperclip/exceptions.py
rename to tools/py-midi2piano/pyperclip/exceptions.py
diff --git a/tools/midi2piano/pyperclip/windows.py b/tools/py-midi2piano/pyperclip/windows.py
similarity index 100%
rename from tools/midi2piano/pyperclip/windows.py
rename to tools/py-midi2piano/pyperclip/windows.py