-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcode.py
More file actions
259 lines (216 loc) · 8.78 KB
/
Copy pathcode.py
File metadata and controls
259 lines (216 loc) · 8.78 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
#https://github.com/Dinosaurier101/MacropadHotkey
import time
import os
import displayio
import terminalio
import supervisor
from adafruit_macropad import MacroPad
from adafruit_hid.consumer_control_code import ConsumerControlCode
from adafruit_display_shapes.rect import Rect
from adafruit_display_text import label
### user defined
# select your keyboard layout:
# https://github.com/Neradoc/Circuitpython_Keyboard_Layouts
# also add the keycode_... to your macros if they use Keycode.* values
## QWERTY
# none needed. already included in MacroPad. comment out the rest.
## win_de (QWERTZ)
from keyboard_layout_win_de import KeyboardLayout
from keycode_win_de import Keycode
## win_fr (AZERTY)
# from keyboard_layout_win_fr import KeyboardLayout
# from keycode_win_fr import Keycode
pressed_color = 0xffffff # led color of the pressed key
MACRO_FOLDER = '/macros' # folder where macro files are stored
brightness_default = 0.1 # overall led pixel brightness
### functions
def set_pixels(keynum): # set pixel to background color. -1 for all.
if keynum < 0:
i = 0
while i < 12:
macropad.pixels[i] = colors[i]
i = i + 1
else:
macropad.pixels[keynum] = colors[keynum]
macropad.pixels.show()
def keypress(keynum): # handle key presses
macropad.pixels[keynum] = pressed_color
function = funcs[keynum]
# keys[keynum] is an arbitrary-length list, each item is one of:
# Positive integer (e.g. Keycode.KEYPAD_MINUS): key pressed
# Negative integer: (absolute value) key released
# Float (e.g. 0.25): delay in seconds
# String (e.g. "Foo"): corresponding keys pressed & released
# List []: one or more Consumer Control codes (can also do float delay)
# Dict {}: mouse buttons/motion (might extend in future)
for item in keys[keynum]:
if isinstance(item, int):
if item >= 0:
macropad.keyboard.press(item)
else:
macropad.keyboard.release(-item)
elif isinstance(item, float):
time.sleep(item)
elif isinstance(item, str):
macropad.keyboard_layout.write(item)
elif isinstance(item, list):
for code in item:
if isinstance(code, int):
macropad.consumer_control.release()
macropad.consumer_control.press(code)
if isinstance(code, float):
time.sleep(code)
elif isinstance(item, dict):
if 'buttons' in item:
if item['buttons'] >= 0:
macropad.mouse.press(item['buttons'])
else:
macropad.mouse.release(-item['buttons'])
macropad.mouse.move(item['x'] if 'x' in item else 0,
item['y'] if 'y' in item else 0,
item['wheel'] if 'wheel' in item else 0)
if 'tone' in item:
if item['tone'] > 0:
macropad.stop_tone()
macropad.start_tone(item['tone'])
else:
macropad.stop_tone()
elif 'play' in item:
macropad.play_file(item['play'])
if isinstance(function, str):
#print('str: ', function)
exec(function)
if isinstance(function, list):
#print('list: ',function)
for item in function:
#print(item)
exec(item)
def keyrelease(keynum): # handle key releases
set_pixels(keynum)
for item in keys[keynum]:
if isinstance(item, int):
if item >= 0:
macropad.keyboard.release(item)
elif isinstance(item, dict):
if 'buttons' in item:
if item['buttons'] >= 0:
macropad.mouse.release(item['buttons'])
elif 'tone' in item:
macropad.stop_tone()
macropad.consumer_control.release()
def set_brightness(): # set brightness of pixels and handle stealth mode
global last_brightness
global brightness
last_brightness = brightness
if brightness > 1:
brightness = 1
if brightness < 0:
brightness = 0
if dim == 1:
macropad.pixels.brightness = 0
else:
macropad.pixels.brightness = brightness
macropad.pixels.show()
def switch(): # handle switching between apps
global app_name # global to make it accessable for use in macro-functions
# clear and then read colors, labels, keys, functions from apps
colors.clear()
labels.clear()
keys.clear()
funcs.clear()
app_name = apps[app_num]['name'] # app name as displayed on the top row
a = 0
while a < 12: # split apps[] into smaller, more managable pieces
colors.append(apps[app_num]['macros'][a][0]) # explanation for apps[]... see 'initialisation' section
labels.append(apps[app_num]['macros'][a][1])
keys.append(apps[app_num]['macros'][a][2])
try:
funcs.append(apps[app_num]['macros'][a][3])
except: # enables compatibility with macros without functions (like the original Hotkeys firmware from Adafruit)
funcs.append('')
a = a + 1
# set pixel colors, labels
set_pixels(-1)
group[13].text = app_name
for i in range(12):
group[i].text = labels[i]
macropad.keyboard.release_all()
macropad.consumer_control.release()
macropad.mouse.release_all()
macropad.stop_tone()
macropad.display.refresh()
def import_apps(): # import macros from 'MACRO_FOLDER'
apps.clear()
files = os.listdir(MACRO_FOLDER)
files.sort()
for filename in files:
if filename.endswith('.py') and not filename.startswith('._'):
try: #read all macros from their files and store in 'apps'
module = __import__(MACRO_FOLDER + '/' + filename[:-3])
apps.append(module.app) # module.app is the dict containing the macro
except (SyntaxError, ImportError, AttributeError, KeyError, NameError,
IndexError, TypeError) as err:
print("ERROR in", filename)
import traceback
traceback.print_exception(err, err, err.__traceback__)
if not apps:
group[13].text = 'NO MACRO FILES FOUND'
macropad.display.refresh()
while True:
pass
def display_setup(): # set up display groups
global group
group = displayio.Group()
for key_index in range(12):
x = key_index % 3
y = key_index // 3
group.append(label.Label(terminalio.FONT, text='', color=0xFFFFFF,
anchored_position=((macropad.display.width - 1) * x / 2,
macropad.display.height - 1 -
(3 - y) * 12),
anchor_point=(x / 2, 1.0)))
group.append(Rect(0, 0, macropad.display.width, 12, fill=0xFFFFFF))
group.append(label.Label(terminalio.FONT, text='', color=0x000000,
anchored_position=(macropad.display.width//2, -2),
anchor_point=(0.5, 0.0)))
macropad.display.show(group)
### initialisation
try:
macropad = MacroPad(layout_class=KeyboardLayout, keycode_class=Keycode)
except:
macropad = MacroPad()
macropad.display.auto_refresh = False # don't automatically update screen to prevent flickering
dim = 0 # dim = 1 allows to disable key illumination. set by encoder button.
app_num = 0 # currently selected app/macro
apps = [] # list to store all macros. to access: apps[app number from import]['macros'][key number][0:colors, 1:labels, 2:keys, 3:funcs]
app_name = () # variable to store the currently loaded macro name
colors = [] # list to store the pixel colors of the selected macro
labels = [] # list to store the key labels of the selected macro
keys = [] # list to store the key sequences of the selected macro
funcs = [] # list to store the functions of the selected macro
import_apps()
display_setup()
brightness = brightness_default
set_brightness()
switch()
# Main Loop
while True:
set_brightness()
macropad.encoder_switch_debounced.update()
if macropad.encoder_switch_debounced.pressed:
if dim == 0:
dim = 1
elif dim == 1:
dim = 0
# switch selected app/macro when encoder position changes
app_num_last = app_num
app_num = macropad.encoder % len(apps)
if app_num != app_num_last:
switch()
# handle key presses
key_event = macropad.keys.events.get()
if key_event:
if key_event.pressed:
keypress(key_event.key_number)
if key_event.released:
keyrelease(key_event.key_number)