From 5db8249ac998a7518e6af9f8d040fb8464ee09f7 Mon Sep 17 00:00:00 2001 From: Tom Wallroth Date: Sat, 8 Jul 2023 11:58:21 +0200 Subject: [PATCH 1/3] first release of guitar-songs app --- apps/guitarsongs/ChangeLog | 1 + apps/guitarsongs/README.md | 22 +++ apps/guitarsongs/app-icon.js | 1 + apps/guitarsongs/app.js | 157 ++++++++++++++++++++ apps/guitarsongs/app.png | Bin 0 -> 3468 bytes apps/guitarsongs/manage_songs.html | 223 +++++++++++++++++++++++++++++ apps/guitarsongs/metadata.json | 17 +++ apps/guitarsongs/screenshot.png | Bin 0 -> 2285 bytes 8 files changed, 421 insertions(+) create mode 100644 apps/guitarsongs/ChangeLog create mode 100644 apps/guitarsongs/README.md create mode 100644 apps/guitarsongs/app-icon.js create mode 100644 apps/guitarsongs/app.js create mode 100644 apps/guitarsongs/app.png create mode 100644 apps/guitarsongs/manage_songs.html create mode 100644 apps/guitarsongs/metadata.json create mode 100644 apps/guitarsongs/screenshot.png diff --git a/apps/guitarsongs/ChangeLog b/apps/guitarsongs/ChangeLog new file mode 100644 index 000000000..5453557bc --- /dev/null +++ b/apps/guitarsongs/ChangeLog @@ -0,0 +1 @@ +0.01: First Release diff --git a/apps/guitarsongs/README.md b/apps/guitarsongs/README.md new file mode 100644 index 000000000..12af8a9f4 --- /dev/null +++ b/apps/guitarsongs/README.md @@ -0,0 +1,22 @@ +# Guitar Songs + +Upload lyrics and chords to your BangleJS2. Play songs at the camp fire. + +![screenshot](screenshot.png) + +## Usage + +Install the app. Use the App Loader to add songs to the watch. + +You can scroll through the chords by dragging your finger left and right. + +You can scroll the lyrics by dragging it up and down. + +## Attribution + +[Fire icon created by Freepik - Flaticon](https://www.flaticon.com/free-icons/fire) + +## Credits + +Created by: devsnd +Inspired by: NovaDawn999 diff --git a/apps/guitarsongs/app-icon.js b/apps/guitarsongs/app-icon.js new file mode 100644 index 000000000..554372bb0 --- /dev/null +++ b/apps/guitarsongs/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwwg967oABCaHQAYUNDCISBC4wfDC5gQCC4YYPC5BJOC65MFJCQXIGCIXGGAY0MC5K2EC54TCMhoWGC5YHEC5RBIIxREKC4gWHC5QLDFwXu9oXSCAXuDAoXILIYDD7wYBeJhxHC4QwEC6QwEaB4WCGAgXYDIxGKVQwXJLAQXESJYXGCYPjmYXPFYPtFwQXTAAczmc+C6fj+YXNa4QXEn//C43QC5kz/4XBMAPtVIQXM8YWBC4bBDC4xgCC4RFBC5AWGC4guDC55IBC4IuDC4xGHC5peJPAfdCQIAEVAdACglEABVDDAM97vUqgGBkUAggXLGAQXBotUCwM0oAWLC4cz6tUokyGANCIxwABooGBmkzmQuMoQXDDwQXBmgXMI4gGCmRFBoR3PFIYECVYJgOAwtEbQ4AoA")) diff --git a/apps/guitarsongs/app.js b/apps/guitarsongs/app.js new file mode 100644 index 000000000..9a3004374 --- /dev/null +++ b/apps/guitarsongs/app.js @@ -0,0 +1,157 @@ +const chords = { + // name: [name, ...finger_placement, fret], + c: ["C", "0X", "33", "22", "x", "11", "x", 0], + d: ["D", "0X", "0X", "x", "21", "33", "22", 0], + dm: ["Dm", "0x", "0x", "x", "22", "33", "11", 0], + e: ["E", "x", "22", "23", "11", "x", "x", 0], + em: ["Em", "x", "22", "23", "x", "x", "x", 0], + em7: ["Em7", "x", "11", "x", "x", "x", "x", 0], + f: ["F", "0x", "0x", "33", "22", "11", "11", 0], + g: ["G", "32", "21", "x", "x", "x", "33", 0], + am: ["Am", "0X", "x", "21", "22", "23", "x", 0], + a: ["A", "0x", "x", "23", "22", "11", "x", 0], + b7: ["B7", "0x", "22", "11", "23", "x", "24", 0], + cadd9: ["Cadd9", "0x", "32", "21", "x", "33", "34", 0], + dadd11: ["Dadd11", "0x", "33", "22", "x", "11", "x", 3], + csus2: ["Csus2", "0x", "33", "x", "x", "11", "0x", 0], + gadd9: ["Gadd9", "32", "0x", "x", "21", "x", "33", 0], + aadd9: ["Aadd9", "11", "33", "34", "22", "x", "x", 5], + fsharp7add11: ["F#7add11", "21", "43", "44", "32", "x", "x", 0], + d9: ["D9", "0x", "22", "11", "23", "23", "0x", 4], + g7: ["G7", "33", "22", "x", "x", "34", "11", 0], + bflatd: ["Bb/D", "0x", "33", "11", "11", "11", "0x", 3], + e7sharp9: ["E7#9", "0x", "22", "11", "23", "34", "0x", 6], + a11: ["A11", "33", "0x", "34", "22", "11", "0x", 0], + a9: ["A9", "32", "0x", "33", "21", "34", "0x", 3], +} + +const chordCache = {}; +function drawChordCached(chord, x, y, options) { + let image; + if (chordCache[chord[0]]) { + image = chordCache[chord[0]] + } else { + arrbuff = Graphics.createArrayBuffer(60,65,1,{msb:true}); + drawChord(arrbuff, chord, 0, 0, options); + image = {width: arrbuff.getWidth(), height: arrbuff.getHeight(), bpp:arrbuff.getBPP(), buffer: arrbuff.buffer, transparent:0} + chordCache[chord[0]] = image; + } + g.drawImage(image, x, y); +} + + +function drawChord(buffer, chord, x, y, options) { + const stringWidths = options.stringWidths; + const fretHeight = options.fretHeight; + const circleSize = options.circleSize; + const drawFinger = options.drawFinger; + const drawCircleRim = options.drawCircleRim; + + const name = chord[0]; + chord = chord.slice(1); + x += 2; + buffer.setColor(0x1).setFontAlign(-1, -1).drawString(name, x, y); + y += 15; + for (let i = 0; i < 6; i++) { + buffer.drawLine(x + i * stringWidths, y, x + i * stringWidths, y + fretHeight*4); + } + for (let i = 0; i < 5; i++) { + buffer.fillRect(x - 1, y + i * fretHeight - 1, x + stringWidths * 5 + 1, y + i * fretHeight + 1); + } + + for (let i = 0; i < 6; i++) { + const xPos = x + i * stringWidths; + let yPos = y + fretHeight * parseInt(chord[i][0]) - fretHeight/2 + + if (chord[i] === "x") { + buffer.setColor(0x1).drawCircle(xPos, y - 5, 2); + continue; + } + if (chord[i] === "0x") { + buffer.setFontAlign(0, 0); + buffer.setColor(0x1).drawString('x', xPos, y - 5); + continue; + } + buffer.setFontAlign(0, 0); + if (drawFinger) { + buffer.setColor(0x0).fillCircle(xPos, yPos, circleSize); + if (drawCircleRim) { + buffer.setColor(0x1).drawCircle(xPos, yPos, circleSize); + } + buffer.setColor(0x1).drawString(chord[i][1], xPos, yPos); + } else { + buffer.setColor(0x1).fillCircle(xPos, yPos, circleSize); + buffer.setFontAlign(0, -1) + buffer.setColor(0x1).drawString(chord[i][1], xPos, y + fretHeight*4 + 2); + } + } + if (chord[6] !== 0) { + buffer.setFontAlign(-1, -1); + buffer.drawString(chord[6] + 'fr', x + 5 * stringWidths + 2, y); + } +} + +const chordOptions = { + stringWidths: 8, + fretHeight: 10, + circleSize: 2, + drawFinger: false, + drawCircleRim: false, +} + +function drawApp(lyricsLines, chordsDraw, scrollY, chordScrollX) { + const R = Bangle.appRect; + + g.setFont('6x8'); + if (scrollY < 60) { + for (let i=0; i R.y2) break; + g.setFontAlign(-1, -1).drawString(lyricsLines[i], R.x, y); + } +} + +let currentScrollY = 0; +let chordScrollX = 0; +let currentChordScroll = 0; +let lyricsHeight = 0; + +function main(song) { + const lyrics = song.lyrics; + const foundChords = song.chords; + const lyricsLines = lyrics.split('\n'); + const chordsDraw = Object.values(chords).filter(c=>foundChords.includes(c[0])); + + g.clear(); + drawApp(lyricsLines, chordsDraw, currentScrollY, chordScrollX); + lyricsHeight = g.stringMetrics(lyrics).height; + Bangle.on('drag', (event) => { + currentScrollY = Math.min(0, currentScrollY + event.dy); + chordScrollX = Math.max(Math.min(0, chordScrollX + event.dx), -(chordsDraw.length - 3)*60); + g.clear(); + drawApp(lyricsLines, chordsDraw, currentScrollY, chordScrollX); + }) +} + +function mainMenu () { + const songs = ( + require("Storage").readJSON("guitar_songs.json", true) || + [{'name': 'No songs', 'lyrics': 'Em\nPlease upload a song\nAm\nusing the Bangle App Loader', 'chords': ['Am', 'Em']}] + ); + const menu = { + "": {"title": "Guitar Songs"}, + }; + for (let i=0; iTA+aa!>*QK%<348(*pTzeNtY>gJ&1 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 + + + + + + + +
+

List of Songs

+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
NameLyricschordssize
{{song.name}}{{song.lyrics.slice(0, 30)}}{{song.chords.join(' ')}}{{song.lyrics.length + song.name.length}}
+ +
+
+ +
+
+
+ +
+
+ Size on Bangle Flash: {{watchSongsSize}} Bytes +
+ New size: {{localSongsSize}} Bytes +
+
+ +
+
+ +
+ + + + diff --git a/apps/guitarsongs/metadata.json b/apps/guitarsongs/metadata.json new file mode 100644 index 000000000..d0e34fd3a --- /dev/null +++ b/apps/guitarsongs/metadata.json @@ -0,0 +1,17 @@ +{ "id": "guitarsongs", + "name": "Guitar Songs", + "shortName":"Guitar Songs", + "version":"0.01", + "description": "Songs lyrics and guitar chords", + "icon": "app.png", + "screenshots": [{"url": "screenshot.png"}], + "tags": "guitar, song, lyrics, chords", + "supports" : ["BANGLEJS2"], + "interface": "manage_songs.html", + "readme": "README.md", + "storage": [ + {"name":"guitarsongs.app.js","url":"app.js"}, + {"name":"guitarsongs.img","url":"app-icon.js","evaluate":true} + ], + "data": [{"name": "guitar_songs.json"}] +} diff --git a/apps/guitarsongs/screenshot.png b/apps/guitarsongs/screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..c2d7fe2ea58faf7400fe1e0c471a499192756233 GIT binary patch literal 2285 zcmeHJdoMYRS~j~XM*F+>%i5yE=3l2$t;5(y@4m1#*v zZA(2G9h8bBwj^OA)3nuUF^p%>km%B=h_EIihty`~%pdc|{EK91Zu`Z7KN})fFrQ#ZA7w?tgFu`?`}YO_$qGV50S2Q2 zDa9ZVP=N?O6-7!=)y~~*aQRD!K(_NBN0{5|<7IRmNGzVH4aj;pb}*h(e14p&-_k3X zZ-*oji46H^b^pxXH8rX_ppng3Yzrve%rK#@41BTJL|omk)~Rniju!8R|q=opysarwoe7V*^021lR+*ynypS_J~j z{3kiXB0p}euYV91NM{3uUhmNFoSB;gvY2%P<-dJDCNC{B!_~wj-}AlsLLL} zNe?g@Ja`F?-NFa{_B}A{a#|HI^^)iW`QD$9(w@{V=h*sZe)ap@!Lm_lKs3zVFcJ|c!l%5@ZWLR& zZ4omm%#Hw$;AsR>^3O5|-VxU_he!XlE`S;y%#%T_u$Oob#0}b`> zy19ciw39>PH~74JBhxKZ+?rziI!b(ux!n zc&mu#_c6DG&}qcS8j7bX*%IG;BE>6VYUzpzp73%Js5N@F3~Xla&8|nJ`BQ_^BD$z8_rKI%ubMC$_cH+26=o^$HH6t!qrIe1PMbZ!3emT^=jFz?{^M zi_y1jz@}gf4bD8C+Q@2VR!_x?^j?K7nTsp4Ni1cegIk4}mi10`h_hUGu83#7ipooP zKG~wIY2OfI33_&srJ{;$Y@fPyQktvc#Y&M#VX{CByZU70Tz_W$75br{Asluhx|heV zU{aK=ucs(A(mlf>RV{lo#!2D0;u=i8%Y-*f01Itw3XoL{q-_N z+a(g`7$IkHz_wLo8QwJF`yR{lyQuN>jL-i1Pp8|a;FtED{4{j_OQ1Bw)?~XxEF!$B zlG@q@g)tFzx`TA+re|R%ng!jwpHsfm>;X~z*X%m3VcP#@|mH;oQ5vM!e_eG=bvNWw0lZIDk|IZ)uFKq7!LPX!t3-g*sW_ky$T^6Cb6>U;udXGKY6m{ zlavljx*6;M|6L1AZO5qTVTTfNeaS@XLdAQW)()l-RMJZ(V`?WhzKbr73}H13@v>n~ zbD7F3FG8QxA&f%S?nUlPfqWqKfxd$VVr|cX;TC~%pl|*U^oJ7v-xh3|`$U*G5~}Yf R8cr4v;>+-0P7wC$e*uDaBkBME literal 0 HcmV?d00001 From c150e388b6db2f8c7c02d862c6a98b1ae99c76b5 Mon Sep 17 00:00:00 2001 From: Tom Wallroth Date: Sat, 8 Jul 2023 17:06:02 +0200 Subject: [PATCH 2/3] render larger chords --- apps/guitarsongs/ChangeLog | 1 + apps/guitarsongs/app.js | 46 +++++++++++++++++++--------------- apps/guitarsongs/metadata.json | 2 +- 3 files changed, 28 insertions(+), 21 deletions(-) diff --git a/apps/guitarsongs/ChangeLog b/apps/guitarsongs/ChangeLog index 5453557bc..dda3f0fd1 100644 --- a/apps/guitarsongs/ChangeLog +++ b/apps/guitarsongs/ChangeLog @@ -1 +1,2 @@ 0.01: First Release +0.02: WIP diff --git a/apps/guitarsongs/app.js b/apps/guitarsongs/app.js index 9a3004374..89db72c50 100644 --- a/apps/guitarsongs/app.js +++ b/apps/guitarsongs/app.js @@ -1,15 +1,16 @@ const chords = { // name: [name, ...finger_placement, fret], - c: ["C", "0X", "33", "22", "x", "11", "x", 0], - d: ["D", "0X", "0X", "x", "21", "33", "22", 0], + c: ["C", "0x", "33", "22", "x", "11", "x", 0], + d: ["D", "0x", "0x", "x", "21", "33", "22", 0], dm: ["Dm", "0x", "0x", "x", "22", "33", "11", 0], e: ["E", "x", "22", "23", "11", "x", "x", 0], em: ["Em", "x", "22", "23", "x", "x", "x", 0], em7: ["Em7", "x", "11", "x", "x", "x", "x", 0], f: ["F", "0x", "0x", "33", "22", "11", "11", 0], g: ["G", "32", "21", "x", "x", "x", "33", 0], - am: ["Am", "0X", "x", "21", "22", "23", "x", 0], - a: ["A", "0x", "x", "23", "22", "11", "x", 0], + a: ["A", "0x", "x", "21", "22", "23", "x", 0], + am: ["Am", "0x", "x", "23", "22", "11", "x", 0], + a7: ["A7", "0x", "x", "21", "x", "23", "x", 0], b7: ["B7", "0x", "22", "11", "23", "x", "24", 0], cadd9: ["Cadd9", "0x", "32", "21", "x", "33", "34", 0], dadd11: ["Dadd11", "0x", "33", "22", "x", "11", "x", 3], @@ -25,13 +26,24 @@ const chords = { a9: ["A9", "32", "0x", "33", "21", "34", "0x", 3], } +const chordHeight = 85; +const chordWidth = 80; + +const chordOptions = { + stringWidths: 12, + fretHeight: 14, + circleSize: 4, + drawFinger: false, + drawCircleRim: false, +} + const chordCache = {}; function drawChordCached(chord, x, y, options) { let image; if (chordCache[chord[0]]) { image = chordCache[chord[0]] } else { - arrbuff = Graphics.createArrayBuffer(60,65,1,{msb:true}); + arrbuff = Graphics.createArrayBuffer(chordWidth,chordHeight,1,{msb:true}); drawChord(arrbuff, chord, 0, 0, options); image = {width: arrbuff.getWidth(), height: arrbuff.getHeight(), bpp:arrbuff.getBPP(), buffer: arrbuff.buffer, transparent:0} chordCache[chord[0]] = image; @@ -49,8 +61,8 @@ function drawChord(buffer, chord, x, y, options) { const name = chord[0]; chord = chord.slice(1); - x += 2; - buffer.setColor(0x1).setFontAlign(-1, -1).drawString(name, x, y); + x += 3; + buffer.setFont('6x8').setColor(0x1).setFontAlign(-1, -1).drawString(name, x, y); y += 15; for (let i = 0; i < 6; i++) { buffer.drawLine(x + i * stringWidths, y, x + i * stringWidths, y + fretHeight*4); @@ -91,26 +103,20 @@ function drawChord(buffer, chord, x, y, options) { } } -const chordOptions = { - stringWidths: 8, - fretHeight: 10, - circleSize: 2, - drawFinger: false, - drawCircleRim: false, -} + function drawApp(lyricsLines, chordsDraw, scrollY, chordScrollX) { const R = Bangle.appRect; g.setFont('6x8'); - if (scrollY < 60) { + if (scrollY < chordHeight) { for (let i=0; i R.y2) break; g.setFontAlign(-1, -1).drawString(lyricsLines[i], R.x, y); @@ -127,13 +133,13 @@ function main(song) { const foundChords = song.chords; const lyricsLines = lyrics.split('\n'); const chordsDraw = Object.values(chords).filter(c=>foundChords.includes(c[0])); - + const R = Bangle.appRect; g.clear(); drawApp(lyricsLines, chordsDraw, currentScrollY, chordScrollX); lyricsHeight = g.stringMetrics(lyrics).height; Bangle.on('drag', (event) => { currentScrollY = Math.min(0, currentScrollY + event.dy); - chordScrollX = Math.max(Math.min(0, chordScrollX + event.dx), -(chordsDraw.length - 3)*60); + chordScrollX = Math.max(Math.min(0, chordScrollX + event.dx), -(song.chords.length*chordWidth - R.x2)); g.clear(); drawApp(lyricsLines, chordsDraw, currentScrollY, chordScrollX); }) @@ -142,7 +148,7 @@ function main(song) { function mainMenu () { const songs = ( require("Storage").readJSON("guitar_songs.json", true) || - [{'name': 'No songs', 'lyrics': 'Em\nPlease upload a song\nAm\nusing the Bangle App Loader', 'chords': ['Am', 'Em']}] + [{'name': 'No songs', 'lyrics': 'Em\nPlease upload a song\nAm A7\nusing the Bangle App Loader', 'chords': ['Am', 'Em', 'A7']}] ); const menu = { "": {"title": "Guitar Songs"}, diff --git a/apps/guitarsongs/metadata.json b/apps/guitarsongs/metadata.json index d0e34fd3a..cec4be2fd 100644 --- a/apps/guitarsongs/metadata.json +++ b/apps/guitarsongs/metadata.json @@ -1,7 +1,7 @@ { "id": "guitarsongs", "name": "Guitar Songs", "shortName":"Guitar Songs", - "version":"0.01", + "version":"0.02", "description": "Songs lyrics and guitar chords", "icon": "app.png", "screenshots": [{"url": "screenshot.png"}], From 8919208caf78d35e3e79a5082965aa839f90607a Mon Sep 17 00:00:00 2001 From: Tom Wallroth Date: Sun, 9 Jul 2023 20:33:05 +0200 Subject: [PATCH 3/3] use simpler chord format, added many more chords --- apps/guitarsongs/app.js | 152 ++++++++++++++++++++++------- apps/guitarsongs/manage_songs.html | 84 ++++++++-------- 2 files changed, 160 insertions(+), 76 deletions(-) diff --git a/apps/guitarsongs/app.js b/apps/guitarsongs/app.js index 89db72c50..a12fa842b 100644 --- a/apps/guitarsongs/app.js +++ b/apps/guitarsongs/app.js @@ -1,30 +1,103 @@ -const chords = { - // name: [name, ...finger_placement, fret], - c: ["C", "0x", "33", "22", "x", "11", "x", 0], - d: ["D", "0x", "0x", "x", "21", "33", "22", 0], - dm: ["Dm", "0x", "0x", "x", "22", "33", "11", 0], - e: ["E", "x", "22", "23", "11", "x", "x", 0], - em: ["Em", "x", "22", "23", "x", "x", "x", 0], - em7: ["Em7", "x", "11", "x", "x", "x", "x", 0], - f: ["F", "0x", "0x", "33", "22", "11", "11", 0], - g: ["G", "32", "21", "x", "x", "x", "33", 0], - a: ["A", "0x", "x", "21", "22", "23", "x", 0], - am: ["Am", "0x", "x", "23", "22", "11", "x", 0], - a7: ["A7", "0x", "x", "21", "x", "23", "x", 0], - b7: ["B7", "0x", "22", "11", "23", "x", "24", 0], - cadd9: ["Cadd9", "0x", "32", "21", "x", "33", "34", 0], - dadd11: ["Dadd11", "0x", "33", "22", "x", "11", "x", 3], - csus2: ["Csus2", "0x", "33", "x", "x", "11", "0x", 0], - gadd9: ["Gadd9", "32", "0x", "x", "21", "x", "33", 0], - aadd9: ["Aadd9", "11", "33", "34", "22", "x", "x", 5], - fsharp7add11: ["F#7add11", "21", "43", "44", "32", "x", "x", 0], - d9: ["D9", "0x", "22", "11", "23", "23", "0x", 4], - g7: ["G7", "33", "22", "x", "x", "34", "11", 0], - bflatd: ["Bb/D", "0x", "33", "11", "11", "11", "0x", 3], - e7sharp9: ["E7#9", "0x", "22", "11", "23", "34", "0x", 6], - a11: ["A11", "33", "0x", "34", "22", "11", "0x", 0], - a9: ["A9", "32", "0x", "33", "21", "34", "0x", 3], -} +const chords = [ + // name: [name, placement, fingers, fret], + // sourced from https://github.com/spilth/chord_diagrams/blob/main/lib/chord_diagrams/fingerings.csv + ['A', 'x02220', '', 0], + ['B', 'x24442', '', 0], + ['Bb', 'x13331', '', 0], + ['C', 'x32010', '', 0], + ['C#', 'x46664', '', 0], + ['D', 'xx0232', '', 0], + ['D#', 'x68886', '', 0], + ['E', '022100', '', 0], + ['Eb', 'x68886', '', 0], + ['F', '133211', '', 0], + ['F#', '244322', '', 0], + ['G', '320003', '', 0], + ['G#', '466544', '', 0], + ['C5', 'x355xx', '', 0], + ['D5', 'x577xx', '', 0], + ['D#5', 'x688xx', '', 0], + ['C6', 'x32210', '', 0], + ['D6', 'xx0202', '', 0], + ['E6', '022120', '', 0], + ['G6', '320000', '', 0], + ['A7', '002020', '', 0], + ['B7', 'x21202', '', 0], + ['C7', 'x32310', '', 0], + ['C#7', 'x46464', '', 0], + ['D7', 'x00212', '', 0], + ['E7', '020100', '', 0], + ['E7sus4', '020200', '', 0], + ['F7', '131211', '', 0], + ['F#7', '242322', '', 0], + ['G7', '320001', '', 0], + ['G#7', '464544', '', 0], + ['AM7', 'x02120', '', 0], + ['CM7', 'x32000', '', 0], + ['DM7', 'xx0222', '', 0], + ['EM7', 'xx2444', '', 0], + ['FM7', '132211', '', 0], + ['Cadd9', 'x32033', '', 0], + ['Fadd9', 'xx3213', '', 0], + ['Dsus2', 'xx0230', '', 0], + ['Asus2', 'x02200', '', 0], + ['Asus4', 'x02230', '', 0], + ['Dsus4', 'xx0233', '', 0], + ['Esus4', '022200', '', 0], + ['A7sus4', '002030', '', 0], + ['G7sus4', '353533', '', 0], + ['G+', 'x21003', '', 0], + ['Am', '002210', '', 0], + ['Bm', 'x24432', '', 0], + ['Cm', 'x35543', '', 0], + ['C#m', 'x46654', '', 0], + ['Dm', 'x00231', '', 0], + ['Em', '022000', '', 0], + ['Fm', '133111', '', 0], + ['F#m', '244222', '', 0], + ['Gm', '355333', '', 0], + ['G#m', '466444', '', 0], + ['Am7', '002010', '', 0], + ['A#m7', 'x13121', '', 0], + ['Bm7', 'x24232', '', 0], + ['Cm7', 'x35343', '', 0], + ['C#m7', 'x46454', '', 0], + ['Dm7', 'x00211', '', 0], + ['Em7', '020030', '', 0], + ['Fm7', '131111', '', 0], + ['F#m7', '242222', '', 0], + ['Gm7', '353333', '', 0], + ['Am9', 'x05557', '', 0], + ['Bm11', 'x20220', '', 0], + ['F#m11', '202200', '', 0], + ['A/C#', '042220', '', 0], + ['A/E', '00222x', '', 0], + ['A/F#', '202220', '', 0], + ['Bb/A', 'x00331', '', 0], + ['C/B', 'x22010', '', 0], + ['C/E', '032010', '', 0], + ['D/A', 'x04232', '', 0], + ['D/F#', '200232', '', 0], + ['F/A', 'x03211', '', 0], + ['G/B', 'x20003', '', 0], + ['C7/G', '3323xx', '', 0], + ['D7/F#', '200212', '', 0], + ['G7/F', '123003', '', 0], + ['D9/F#', '2x0210', '', 0], + ['Am/D', 'xx0210', '', 0], + ['Am/G', '302210', '', 0], + ['A#m/D#', 'xx1321', '', 0], + ['Dm/F', '10323x', '', 0], + ['Gm/Bb', 'x10333', '', 0], + ['A7/G', '302020', '', 0], + ['G#dim', '4564xx', '', 0], + ['Adim', 'x01212', '', 0], + ['D#dim7', 'xx1212', '', 0], + ['G#dim7', '456464', '', 0], + ['Daug', 'xx0332', '', 0], + ['Aaug', 'x03221', '', 0], + ['Dadd11', 'xx0032', '', 0], +] const chordHeight = 85; const chordWidth = 80; @@ -72,34 +145,39 @@ function drawChord(buffer, chord, x, y, options) { } for (let i = 0; i < 6; i++) { + const placement = chord[0]; + const fingers = chord[1]; const xPos = x + i * stringWidths; - let yPos = y + fretHeight * parseInt(chord[i][0]) - fretHeight/2 + let yPos = y + fretHeight * parseInt(placement[i]) - fretHeight/2 - if (chord[i] === "x") { + if (placement[i] === "0") { buffer.setColor(0x1).drawCircle(xPos, y - 5, 2); continue; - } - if (chord[i] === "0x") { + } else if (placement[i] === "x") { buffer.setFontAlign(0, 0); buffer.setColor(0x1).drawString('x', xPos, y - 5); continue; } buffer.setFontAlign(0, 0); - if (drawFinger) { + if (drawFinger && chord[i].length>1) { buffer.setColor(0x0).fillCircle(xPos, yPos, circleSize); if (drawCircleRim) { buffer.setColor(0x1).drawCircle(xPos, yPos, circleSize); } - buffer.setColor(0x1).drawString(chord[i][1], xPos, yPos); + if (parseInt(fingers[i])) { + buffer.setColor(0x1).drawString(fingers[i], xPos, yPos); + } } else { buffer.setColor(0x1).fillCircle(xPos, yPos, circleSize); buffer.setFontAlign(0, -1) - buffer.setColor(0x1).drawString(chord[i][1], xPos, y + fretHeight*4 + 2); + if (parseInt(fingers[i])) { + buffer.setColor(0x1).drawString(fingers[i], xPos, y + fretHeight*4 + 2); + } } } - if (chord[6] !== 0) { + if (chord[2] !== 0) { buffer.setFontAlign(-1, -1); - buffer.drawString(chord[6] + 'fr', x + 5 * stringWidths + 2, y); + buffer.drawString(chord[2] + 'fr', x + 5 * stringWidths + 2, y); } } @@ -132,7 +210,7 @@ function main(song) { const lyrics = song.lyrics; const foundChords = song.chords; const lyricsLines = lyrics.split('\n'); - const chordsDraw = Object.values(chords).filter(c=>foundChords.includes(c[0])); + const chordsDraw = chords.filter(c=>foundChords.includes(c[0])); const R = Bangle.appRect; g.clear(); drawApp(lyricsLines, chordsDraw, currentScrollY, chordScrollX); diff --git a/apps/guitarsongs/manage_songs.html b/apps/guitarsongs/manage_songs.html index 3f6d91d71..9280d8d96 100644 --- a/apps/guitarsongs/manage_songs.html +++ b/apps/guitarsongs/manage_songs.html @@ -24,17 +24,17 @@ - - {{song.name}} - {{song.lyrics.slice(0, 30)}} - {{song.chords.join(' ')}} - {{song.lyrics.length + song.name.length}} - - - - - - + + {{song.name}} + {{song.lyrics.slice(0, 30)}} + {{song.chords.join(' ')}} + {{song.lyrics.length + song.name.length}} + + + + + +
@@ -80,8 +80,14 @@ return { newChord: '', builtInChords: [ - "C", "D", "Dm", "E", "Em", "Em7", "F", "G", "Am", "A", "B7", "Cadd9", "Dadd11", "Csus2", - "Gadd9", "Aadd9", "F#7add11", "D9", "G7", "Bb/D", "E7#9", "A11", "A9", + 'A', 'B', 'Bb', 'C', 'C#', 'D', 'D#', 'E', 'Eb', 'F', 'F#', 'G', 'G#', 'C5', 'D5', 'D#5', + 'C6', 'D6', 'E6', 'G6', 'A7', 'B7', 'C7', 'C#7', 'D7', 'E7', 'E7sus4', 'F7', 'F#7', 'G7', + 'G#7', 'AM7', 'CM7', 'DM7', 'EM7', 'FM7', 'Cadd9', 'Fadd9', 'Dsus2', 'Asus2', 'Asus4', + 'Dsus4', 'Esus4', 'A7sus4', 'G7sus4', 'G+', 'Am', 'Bm', 'Cm', 'C#m', 'Dm', 'Em', 'Fm', + 'F#m', 'Gm', 'G#m', 'Am7', 'A#m7', 'Bm7', 'Cm7', 'C#m7', 'Dm7', 'Em7', 'Fm7', 'F#m7', + 'Gm7', 'Am9', 'Bm11', 'F#m11', 'A/C#', 'A/E', 'A/F#', 'Bb/A', 'C/B', 'C/E', 'D/A', 'D/F#', + 'F/A', 'G/B', 'C7/G', 'D7/F#', 'G7/F', 'D9/F#', 'Am/D', 'Am/G', 'A#m/D#', 'Dm/F', 'Gm/Bb', + 'A7/G', 'G#dim', 'Adim', 'D#dim7', 'G#dim7', 'Daug', 'Aaug', 'Dadd11', ] } }, @@ -115,36 +121,36 @@ }, template: `
-
-
- -
-
-

Chords in this Song

- +
+
+ +
+
+

Chords in this Song

+ Please add chords by clicking the bubbles below, or use the Auto-Detect Button after having inserted the lyrics. - + {{chord}} - + -

Available Chords

- +

Available Chords

+ {{chord}} -
-
+
+
Please paste the lyrics and chords in the box below. The width of the text area below is twice the width of the BangleJS2 screen. Everything in the gray area cannot be seen on the screen -
+
-
-
-
- Remove empty lines - Auto Detect Chords
-

+
+ Remove empty lines + Auto Detect Chords +
-` +

+
+ ` }); var app = new Vue({ el: '#app',