--- /dev/null
+This project is subject to the terms of the Mozilla Public License, v. 2.0
+(MPL2).
+MPL2 applies per file so there is a license boilerplate in every file pointing
+to the license.
+See http://mozilla.org/MPL/2.0/.
\ No newline at end of file
--- /dev/null
+This web app is mainly targeted at people playing with a MaKeyMaKey -
+see http://makeymakey.com/ - and maps certain keys to piano sounds.
+
+The keys space, left, up, right, down, w, a, s are mapped to C major pitches.
+
+
+This app is running on http://piano.kairo.at/
+
+
+The main repo is http://git-public.kairo.at/?p=makeypiano.git;a=summary but
+it's listed on GitHub at https://github.com/KaiRo-at/makeypiano for convenience
+for potential contributors. See the TODO for tasks that you can help with.
+
+Please don't use GitHub for issue tracking but http://bugzilla.kairo.at/
--- /dev/null
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ - You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+<!DOCTYPE html>
+<html manifest="manifest.appcache">
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <!-- try to force a 1:1 scaling on mobile, see
+ https://developer.mozilla.org/en/Mobile/Viewport_meta_tag -->
+ <meta name="viewport" content="width=device-width, height=device-height, initial-scale=1, maximum-scale=1">
+ <title>MaKey MaKey Piano</title>
+ <script src="js/piano.js" type="application/javascript;version=1.8"></script>
+ <link rel="stylesheet" href="style/piano.css">
+ <link rel="shortcut icon" href="style/pianoIcon16.png" type="image/png">
+</head>
+<body id="body">
+<h1>MaKey MaKey Piano</h1>
+
+<table id="keyboard">
+<tr>
+<td class="key white upper" colspan="2" id="c1-upper"></td>
+<td class="key black" colspan="2"></td>
+<td class="key white upper small" colspan="1" id="d1-upper"></td>
+<td class="key black" colspan="2"></td>
+<td class="key white upper" colspan="2" id="e1-upper"></td>
+<td class="key white upper" colspan="2" id="f1-upper"></td>
+<td class="key black" colspan="2"></td>
+<td class="key white upper small" colspan="1" id="g1-upper"></td>
+<td class="key black" colspan="2"></td>
+<td class="key white upper small" colspan="1" id="a1-upper"></td>
+<td class="key black" colspan="2"></td>
+<td class="key white upper" colspan="2" id="b1-upper"></td>
+<td class="key white upper" colspan="2" id="c2-upper"></td>
+<td class="key black small" colspan="1"></td>
+</tr>
+<tr>
+<td class="key white lower" colspan="3" id="c1-lower"
+ onclick="gPitches.play('c1');">C</td>
+<td class="key white lower" colspan="3" id="d1-lower"
+ onclick="gPitches.play('d1');">D</td>
+<td class="key white lower" colspan="3" id="e1-lower"
+ onclick="gPitches.play('e1');">E</td>
+<td class="key white lower" colspan="3" id="f1-lower"
+ onclick="gPitches.play('f1');">F</td>
+<td class="key white lower" colspan="3" id="g1-lower"
+ onclick="gPitches.play('g1');">G</td>
+<td class="key white lower" colspan="3" id="a1-lower"
+ onclick="gPitches.play('a1');">A</td>
+<td class="key white lower" colspan="3" id="b1-lower"
+ onclick="gPitches.play('b1');">B</td>
+<td class="key white lower" colspan="3" id="c2-lower"
+ onclick="gPitches.play('c2');">C</td>
+</tr>
+</table>
+
+<button id="helptoggle" onclick="toggleHelp();">?</button>
+<div id="helpdesc">
+<p>Connect a <a href="http://makeymakey.com/">MaKey MaKey</a> to Bananas or
+whatever you like, keys will match C major pitches as follows:</p>
+
+<table id="helptable">
+<tr><th>Key</th><th>Pitch</th></tr>
+<tr><td>Space</td><td>C'</td></tr>
+<tr><td>Right</td><td>D'</td></tr>
+<tr><td>Up</td><td>E'</td></tr>
+<tr><td>Left</td><td>F'</td></tr>
+<tr><td>Down</td><td>G'</td></tr>
+<tr><td>W</td><td>A'</td></tr>
+<tr><td>A</td><td>B'</td></tr>
+<tr><td>S</td><td>C''</td></tr>
+</table>
+<div id="helphide"><button onclick="toggleHelp();">Hide Help</button></div>
+</div>
+
+</body>
+</html>
\ No newline at end of file
--- /dev/null
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+var gSounds = {};
+
+window.onload = function() {
+ // Create objects, makes sure that all the audio gets loaded.
+ gSounds.c1 = new Audio("sound/piano_c1.opus");
+ gSounds.d1 = new Audio("sound/piano_d1.opus");
+ gSounds.e1 = new Audio("sound/piano_e1.opus");
+ gSounds.f1 = new Audio("sound/piano_f1.opus");
+ gSounds.g1 = new Audio("sound/piano_g1.opus");
+ gSounds.a1 = new Audio("sound/piano_a1.opus");
+ gSounds.b1 = new Audio("sound/piano_b1.opus");
+ gSounds.c2 = new Audio("sound/piano_c2.opus");
+
+ document.getElementById("body").addEventListener("keydown", eventHandler, false);
+}
+
+var eventHandler = {
+ handleEvent: function(aEvent) {
+ switch (aEvent.type) {
+ case "keydown":
+ // Should use aEvent.key instead of aEvent.which but needs bug 680830.
+ // See https://developer.mozilla.org/en-US/docs/DOM/Mozilla_event_reference/keydown
+ switch (aEvent.which) {
+ case 32: // space
+ gPitches.play("c1");
+ break;
+ case 39: // right
+ gPitches.play("d1");
+ break;
+ case 38: // up
+ gPitches.play("e1");
+ break;
+ case 37: // left
+ gPitches.play("f1");
+ break;
+ case 40: // down
+ gPitches.play("g1");
+ break;
+ case 87: // w
+ gPitches.play("a1");
+ break;
+ case 65: // a
+ gPitches.play("b1");
+ break;
+ case 83: // s
+ gPitches.play("c2");
+ break;
+ default: // not supported
+ console.log("key not supported: " + aEvent.which);
+ break;
+ }
+ }
+ }
+};
+
+var gPitches = {
+ play: function(aPitchName) {
+ gPitches.flash(aPitchName);
+ var pitchSound = new Audio(gSounds[aPitchName].src);
+ pitchSound.play();
+ },
+
+ flash: function(aPitchName) {
+ document.getElementById(aPitchName + "-upper").classList.add("active");
+ document.getElementById(aPitchName + "-lower").classList.add("active");
+ setTimeout(gPitches.unflash, 200, aPitchName);
+ },
+
+ unflash: function(aPitchName) {
+ document.getElementById(aPitchName + "-upper").classList.remove("active");
+ document.getElementById(aPitchName + "-lower").classList.remove("active");
+ }
+};
+
+function toggleHelp() {
+ document.getElementById("helpdesc").classList.toggle("hidden");
+}
--- /dev/null
+CACHE MANIFEST
+
+# 2013-03-30
+manifest.webapp
+js/piano.js
+sound/piano_c1.opus
+sound/piano_d1.opus
+sound/piano_e1.opus
+sound/piano_f1.opus
+sound/piano_g1.opus
+sound/piano_a1.opus
+sound/piano_b1.opus
+sound/piano_c2.opus
+style/piano.css
+style/pianoIcon16.png
+style/pianoIcon32.png
+style/pianoIcon64.png
+style/pianoIcon128.png
+
+NETWORK:
+*
--- /dev/null
+{
+ "name": "MaKey MaKey Piano",
+ "description": "Play piano pitches as a reaction to MaKey MaKey signals.",
+ "launch_path": "/index.html",
+ "appcache_path": "/manifest.appcache"
+ },
+ "developer": {
+ "name": "Robert Kaiser",
+ "url": "http://www.kairo.at/"
+ },
+ "icons": {
+ "16": "/style/pianoIcon16.png",
+ "32": "/style/pianoIcon32.png",
+ "64": "/style/pianoIcon64.png",
+ "128": "/style/pianoIcon128.png"
+ }
+}
--- /dev/null
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+body {
+ font-family: sans-serif;
+ background-color: #222222;
+ color: white;
+ margin: 0;
+ padding: 0;
+}
+
+h1 {
+ display: none;
+}
+
+#keyboard {
+ margin: auto;
+ margin-top: 10em;
+ padding: 0;
+ border: none;
+ width: 48em;
+ height: 20em;
+ border-collapse: collapse;
+ border-spacing: 0 0;
+}
+
+.key {
+ transition: background-color 100ms;
+}
+
+.key.upper,
+.key.black {
+ border: 1px solid black;
+ border-bottom: none;
+ height: 50%;
+ width: 8.33%;
+}
+
+.key.upper.small,
+.key.black.small {
+ width: 4.17%;
+}
+
+.key.lower {
+ border: 1px solid black;
+ border-top: none;
+ vertical-align: bottom;
+ text-align: center;
+ font-size: 2em;
+ font-weight: bold;
+ height: 50%;
+}
+
+.key.white {
+ background-color: white;
+ color: gray;
+}
+
+.key.black {
+ background-color: black;
+ color: gray;
+}
+
+.key.active {
+ background-color: yellow;
+}
+
+#helptoggle {
+ position: absolute;
+ right: 1em;
+ bottom: 1em;
+ font-size: 1.5em;
+}
+
+#helpdesc {
+ position: absolute;
+ left: 0;
+ right: 0;
+ top: 10em;
+ background-color: rgba(204, 204, 204, .95);
+ color: #222222;
+ width: 24em;
+ margin: auto;
+ padding: 1em;
+ border: 1px solid black;
+ border-radius: 1em;
+ z-index: 10;
+}
+
+#helpdesc.hidden {
+ display: none;
+}
+
+#helpdesc > p {
+ margin-top: 0;
+ margin-bottom: 1em;
+}
+
+#helptable,
+#helphide {
+ margin: auto;
+ padding: 0;
+ width: 8em;
+}
+
+#helptable {
+ border: 0;
+ border-collapse: collapse;
+ border-spacing: 0 0;
+}
+
+#helptable td {
+ text-align: center;
+}
+
+#helphide {
+ margin-top: 1em;
+}
+
+#helphide > button {
+ width: 8em;
+}