|
9 | 9 | HEIGHT = 80 |
10 | 10 | BORDER = 1 |
11 | 11 |
|
12 | | - |
13 | | - |
14 | 12 | # create DumbDisplay |
15 | 13 | if DumbDisplay.runningWithMicropython(): |
16 | 14 | # connect using WIFI: |
|
26 | 24 | dd = DumbDisplay(io4Inet()) |
27 | 25 |
|
28 | 26 |
|
29 | | -def SetupKey(octiveOffset: int, noteIdx: int) -> LayerGraphical: |
30 | | - width = WIDTH - 2 * BORDER |
31 | | - xOffset = noteIdx * WIDTH / 2 |
32 | | - #height |
33 | | - #bgColor |
34 | | - isSemi = False |
35 | | - if noteIdx == 1 or noteIdx == 3 or noteIdx == 6 or noteIdx == 8 or noteIdx == 10: |
36 | | - height = HEIGHT / 2 + 10 |
37 | | - bgColor = "black" |
38 | | - isSemi = True |
39 | | - else: |
40 | | - height = HEIGHT |
41 | | - bgColor = "white" |
42 | | - if noteIdx > 4: |
43 | | - xOffset += WIDTH / 2 |
44 | | - customData = chr(ord(" ") + octiveOffset) + chr(ord(" ") + noteIdx) |
45 | | - #customData[0] = '0' + octiveOffset; |
46 | | - #customData[1] = '0' + noteIdx; |
47 | | - #customData[2] = 0; |
48 | | - keyLayer = LayerGraphical(dd, width, height) |
49 | | - keyLayer.customData = customData |
50 | | - keyLayer.backgroundColor(bgColor) |
51 | | - keyLayer.border(BORDER, "gray") |
52 | | - keyLayer.padding(0) |
53 | | - #keyLayer->setFeedbackHandler(FeedbackHandler, "f"); |
54 | | - if isSemi: |
55 | | - #dumbdisplay.reorderLayer(keyLayer, "T"); |
56 | | - pass |
57 | | - else: |
58 | | - if noteIdx == 0: |
59 | | - keyLayer.drawStr(2, HEIGHT - 15, "C", "blue") |
60 | | - l = WIDTH + octiveOffset * 7 * WIDTH + xOffset |
61 | | - t = TOP_HEIGHT |
62 | | - w = width + 2 * BORDER |
63 | | - h = height + 2 * BORDER |
64 | | - keyLayer.pinLayer(l, t, w, h) |
65 | | - return keyLayer |
66 | | - |
67 | | -def SetupButton(label: str) -> LayerLcd: |
68 | | - buttonLayer = LayerLcd(dd, 4, 1) |
69 | | - buttonLayer.writeLine(label, 0, "C") |
70 | | - buttonLayer.border(1, "darkgray", "round") |
71 | | - buttonLayer.noBackgroundColor() |
72 | | - #buttonLayer.setFeedbackHandler(FeedbackHandler, "f"); |
73 | | - return buttonLayer |
74 | | - |
75 | | -dd.recordLayerSetupCommands() |
76 | | - |
77 | | -dd.configPinFrame(9 * WIDTH, TOP_HEIGHT + HEIGHT) |
78 | | - |
79 | | -SetupKey(-1, 11) |
80 | | -for i in range(0, 12): |
81 | | - SetupKey(0, i) |
82 | | -SetupKey(1, 0) |
83 | | - |
84 | | -playLayer = SetupButton("⏯"); |
85 | | -restartLayer = SetupButton("⏮"); |
86 | | -targetLayer = SetupButton("📱"); |
87 | | - |
88 | | -dd.pinAutoPinLayers(AutoPin("H", playLayer, restartLayer, targetLayer).build(), 0, 0, 9 * WIDTH, TOP_HEIGHT) |
89 | | - |
90 | | -dd.playbackLayerSetupCommands("ddmelody") |
| 27 | +def FeedbackHandler(layer, type, x, y): |
| 28 | + #print("FeedbackHandler", melodyApp) |
| 29 | + melodyApp.feedbackHandler(layer, type, x, y) |
| 30 | + |
| 31 | + |
| 32 | +class MelodyApp: |
| 33 | + |
| 34 | + def __init__(self): |
| 35 | + self.play = False |
| 36 | + self.playToSpeaker = False |
| 37 | + self.restart = False |
| 38 | + self.adhocFreq = -1 |
| 39 | + |
| 40 | + dd.recordLayerSetupCommands() |
| 41 | + |
| 42 | + dd.configPinFrame(9 * WIDTH, TOP_HEIGHT + HEIGHT) |
| 43 | + |
| 44 | + self.setupKey(-1, 11) |
| 45 | + for i in range(0, 12): |
| 46 | + self.setupKey(0, i) |
| 47 | + self.setupKey(1, 0) |
| 48 | + |
| 49 | + self.playLayer = self.setupButton("⏯"); |
| 50 | + self.restartLayer = self.setupButton("⏮"); |
| 51 | + self.targetLayer = self.setupButton("📱"); |
| 52 | + |
| 53 | + dd.pinAutoPinLayers(AutoPin("H", self.playLayer, self.restartLayer, self.targetLayer).build(), 0, 0, 9 * WIDTH, TOP_HEIGHT) |
| 54 | + |
| 55 | + dd.playbackLayerSetupCommands("ddmelody") |
| 56 | + |
| 57 | + def run(self): |
| 58 | + while True: |
| 59 | + dd.timeslice() |
| 60 | + if self.adhocFreq != -1: |
| 61 | + # key on DumbDisplay pressed ... play the note/tone of the key press |
| 62 | + self.playTone(self.adhocFreq, 200, self.playToSpeaker) |
| 63 | + self.adhocFreq = -1 |
| 64 | + |
| 65 | + def setupKey(self, octaveOffset: int, noteIdx: int) -> LayerGraphical: |
| 66 | + width = WIDTH - 2 * BORDER |
| 67 | + xOffset = noteIdx * WIDTH / 2 |
| 68 | + #height |
| 69 | + #bgColor |
| 70 | + isSemi = False |
| 71 | + if noteIdx == 1 or noteIdx == 3 or noteIdx == 6 or noteIdx == 8 or noteIdx == 10: |
| 72 | + height = HEIGHT / 2 + 10 |
| 73 | + bgColor = "black" |
| 74 | + isSemi = True |
| 75 | + else: |
| 76 | + height = HEIGHT |
| 77 | + bgColor = "white" |
| 78 | + if noteIdx > 4: |
| 79 | + xOffset += WIDTH / 2 |
| 80 | + #customData = chr(ord(" ") + octiveOffset) + chr(ord(" ") + noteIdx) |
| 81 | + #customData[0] = '0' + octiveOffset; |
| 82 | + #customData[1] = '0' + noteIdx; |
| 83 | + #customData[2] = 0; |
| 84 | + keyLayer = LayerGraphical(dd, width, height) |
| 85 | + keyLayer.octaveOffset = octaveOffset |
| 86 | + keyLayer.noteIdx = noteIdx |
| 87 | + #keyLayer.customData = customData |
| 88 | + keyLayer.backgroundColor(bgColor) |
| 89 | + keyLayer.border(BORDER, "gray") |
| 90 | + keyLayer.padding(0) |
| 91 | + keyLayer.enableFeedback("fa", FeedbackHandler) |
| 92 | + #keyLayer->setFeedbackHandler(FeedbackHandler, "f"); |
| 93 | + if isSemi: |
| 94 | + keyLayer.reorderLayer("T") |
| 95 | + pass |
| 96 | + else: |
| 97 | + if noteIdx == 0: |
| 98 | + keyLayer.drawStr(2, HEIGHT - 15, "C", "blue") |
| 99 | + l = WIDTH + octaveOffset * 7 * WIDTH + xOffset |
| 100 | + t = TOP_HEIGHT |
| 101 | + w = width + 2 * BORDER |
| 102 | + h = height + 2 * BORDER |
| 103 | + keyLayer.pinLayer(l, t, w, h) |
| 104 | + return keyLayer |
| 105 | + |
| 106 | + def setupButton(self, label: str) -> LayerLcd: |
| 107 | + buttonLayer = LayerLcd(dd, 4, 1) |
| 108 | + buttonLayer.writeLine(label, 0, "C") |
| 109 | + buttonLayer.border(1, "darkgray", "round") |
| 110 | + buttonLayer.noBackgroundColor() |
| 111 | + buttonLayer.enableFeedback("f", FeedbackHandler) |
| 112 | + return buttonLayer |
| 113 | + |
| 114 | + def feedbackHandler(self, layer, type, x, y): |
| 115 | + print("clicked") |
| 116 | + if layer == self.playLayer: |
| 117 | + self.play = not self.play |
| 118 | + if self.play: |
| 119 | + self.playLayer.backgroundColor("lightgray") |
| 120 | + else: |
| 121 | + self.playLayer.noBackgroundColor() |
| 122 | + elif layer == self.targetLayer: |
| 123 | + self.playToSpeaker = not self.playToSpeaker |
| 124 | + if self.playToSpeaker: |
| 125 | + self.targetLayer.noBackgroundColor() |
| 126 | + else: |
| 127 | + self.targetLayer.backgroundColor("lightgray") |
| 128 | + elif layer == self.restartLayer: |
| 129 | + self.restart = True |
| 130 | + else: |
| 131 | + octaveOffset = layer.octaveOffset |
| 132 | + noteIdx = layer.noteIdx |
| 133 | + freq = self.getNoteFreq(octaveOffset, noteIdx) |
| 134 | + self.adhocFreq = freq |
| 135 | + |
| 136 | + def getNoteFreq(self, octave, noteIdx): |
| 137 | + n = noteIdx + 12 * octave - 8 |
| 138 | + freq = 440.0 * pow(2, n / 12.0); # 440 is A |
| 139 | + return int(freq + 0.5) |
| 140 | + |
| 141 | + def playTone(self, freq, duration, playToSpeaker): |
| 142 | +# #ifdef SPEAKER_PIN |
| 143 | +# if (playToSpeaker) { |
| 144 | +# PlayTone(freq, duration); |
| 145 | +# return; |
| 146 | +# } |
| 147 | +# #endif |
| 148 | + dd.tone(freq, duration) |
| 149 | + dd.delay_ms(duration) |
| 150 | + |
| 151 | +melodyApp = MelodyApp() |
| 152 | +melodyApp.run() |
0 commit comments