Skip to content

Commit 1692867

Browse files
Merge pull request #1835 from PaintYourDragon/main
MacroPad Hotkeys: add Consumer Control, mouse, sounds
2 parents 85034e2 + 15d739a commit 1692867

11 files changed

Lines changed: 209 additions & 55 deletions

File tree

Macropad_Hotkeys/code.py

Lines changed: 54 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
"""
2-
A fairly straightforward macro/hotkey program for Adafruit MACROPAD.
3-
Macro key setups are stored in the /macros folder (configurable below),
4-
load up just the ones you're likely to use. Plug into computer's USB port,
5-
use dial to select an application macro set, press MACROPAD keys to send
6-
key sequences.
2+
A macro/hotkey program for Adafruit MACROPAD. Macro setups are stored in the
3+
/macros folder (configurable below), load up just the ones you're likely to
4+
use. Plug into computer's USB port, use dial to select an application macro
5+
set, press MACROPAD keys to send key sequences and other USB protocols.
76
"""
87

98
# pylint: disable=import-error, unused-import, too-few-public-methods
@@ -44,6 +43,9 @@ def switch(self):
4443
macropad.pixels[i] = 0
4544
group[i].text = ''
4645
macropad.keyboard.release_all()
46+
macropad.consumer_control.release()
47+
macropad.mouse.release_all()
48+
macropad.stop_tone()
4749
macropad.pixels.show()
4850
macropad.display.refresh()
4951

@@ -129,15 +131,13 @@ def switch(self):
129131

130132
sequence = apps[app_index].macros[key_number][2]
131133
if pressed:
132-
# the sequence is arbitrary-length
133-
# each item in the sequence is either
134-
# an integer (e.g., Keycode.KEYPAD_MINUS),
135-
# a floating point value (e.g., 0.20)
136-
# or a string.
137-
# Positive Integers ==> key pressed
138-
# Negative Integers ==> key released
139-
# Float ==> sleep in seconds
140-
# String ==> each key in string pressed & released
134+
# 'sequence' is an arbitrary-length list, each item is one of:
135+
# Positive integer (e.g. Keycode.KEYPAD_MINUS): key pressed
136+
# Negative integer: (absolute value) key released
137+
# Float (e.g. 0.25): delay in seconds
138+
# String (e.g. "Foo"): corresponding keys pressed & released
139+
# List []: one or more Consumer Control codes (can also do float delay)
140+
# Dict {}: mouse buttons/motion (might extend in future)
141141
if key_number < 12: # No pixel for encoder button
142142
macropad.pixels[key_number] = 0xFFFFFF
143143
macropad.pixels.show()
@@ -149,13 +149,49 @@ def switch(self):
149149
macropad.keyboard.release(-item)
150150
elif isinstance(item, float):
151151
time.sleep(item)
152-
else:
152+
elif isinstance(item, str):
153153
macropad.keyboard_layout.write(item)
154+
elif isinstance(item, list):
155+
for code in item:
156+
if isinstance(code, int):
157+
macropad.consumer_control.release()
158+
macropad.consumer_control.press(code)
159+
if isinstance(code, float):
160+
time.sleep(code)
161+
elif isinstance(item, dict):
162+
if 'buttons' in item:
163+
if item['buttons'] >= 0:
164+
macropad.mouse.press(item['buttons'])
165+
else:
166+
macropad.mouse.release(-item['buttons'])
167+
macropad.mouse.move(item['x'] if 'x' in item else 0,
168+
item['y'] if 'y' in item else 0,
169+
item['wheel'] if 'wheel' in item else 0)
170+
if 'tone' in item:
171+
if item['tone'] > 0:
172+
macropad.stop_tone()
173+
macropad.start_tone(item['tone'])
174+
else:
175+
macropad.stop_tone()
176+
elif 'play' in item:
177+
macropad.play_file(item['play'])
154178
else:
155-
# Release any still-pressed keys
179+
# Release any still-pressed keys, consumer codes, mouse buttons
180+
# Keys and mouse buttons are individually released this way (rather
181+
# than release_all()) because pad supports multi-key rollover, e.g.
182+
# could have a meta key or right-mouse held down by one macro and
183+
# press/release keys/buttons with others. Navigate popups, etc.
156184
for item in sequence:
157-
if isinstance(item, int) and item >= 0:
158-
macropad.keyboard.release(item)
185+
if isinstance(item, int):
186+
if item >= 0:
187+
macropad.keyboard.release(item)
188+
elif isinstance(item, dict):
189+
if 'buttons' in item:
190+
if item['buttons'] >= 0:
191+
macropad.mouse.release(item['buttons'])
192+
elif 'tone' in item:
193+
macropad.stop_tone()
194+
macropad.consumer_control.release()
159195
if key_number < 12: # No pixel for encoder button
160196
macropad.pixels[key_number] = apps[app_index].macros[key_number][0]
161197
macropad.pixels.show()

Macropad_Hotkeys/macros/linux-firefox.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22

33
from adafruit_hid.keycode import Keycode # REQUIRED if using Keycode.* values
44

5-
app = { # REQUIRED dict, must be named 'app'
5+
app = { # REQUIRED dict, must be named 'app'
66
'name' : 'Linux Firefox', # Application name
7-
'macros' : [ # List of button macros...
7+
'macros' : [ # List of button macros...
88
# COLOR LABEL KEY SEQUENCE
99
# 1st row ----------
1010
(0x004000, '< Back', [Keycode.CONTROL, '[']),
@@ -20,10 +20,10 @@
2020
(0x000040, 'Private', [Keycode.CONTROL, Keycode.SHIFT, 'p']),
2121
# 4th row ----------
2222
(0x101010, 'Ada', [Keycode.CONTROL, 't', -Keycode.CONTROL,
23-
'www.adafruit.com\n']), # adafruit.com in a new tab
24-
(0x000040, 'Dev Mode', [Keycode.F12]), # dev mode
23+
'www.adafruit.com\n']), # adafruit.com in a new tab
24+
(0x000040, 'Dev Mode', [Keycode.F12]), # dev mode
2525
(0x101010, 'Digi', [Keycode.CONTROL, 't', -Keycode.CONTROL,
26-
'digikey.com\n']), # digikey in a new tab
26+
'digikey.com\n']), # digikey in a new tab
2727
# Encoder button ---
2828
(0x000000, '', [Keycode.CONTROL, 'w']) # Close window/tab
2929
]

Macropad_Hotkeys/macros/mac-evernote.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@
2020
(0x004000, 'Nums', [Keycode.SHIFT, Keycode.COMMAND, 'o']),
2121
(0x004000, 'Check', [Keycode.SHIFT, Keycode.COMMAND, 't']),
2222
# 4th row ----------
23-
(0x004000, 'Date', [Keycode.SHIFT, Keycode.COMMAND, 'D' ]),
24-
(0x004000, 'Time', [Keycode.OPTION, Keycode.SHIFT, Keycode.COMMAND, 'D' ]),
23+
(0x004000, 'Date', [Keycode.SHIFT, Keycode.COMMAND, 'D']),
24+
(0x004000, 'Time', [Keycode.OPTION, Keycode.SHIFT, Keycode.COMMAND, 'D']),
2525
(0x004000, 'Divider', [Keycode.SHIFT, Keycode.COMMAND, 'H']),
2626
# Encoder button ---
2727
(0x000000, '', [Keycode.COMMAND, 'w']) # Close window/tab

Macropad_Hotkeys/macros/media.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# MACROPAD Hotkeys example: Consumer Control codes (media keys)
2+
3+
# The syntax for Consumer Control macros is a little peculiar, in order to
4+
# maintain backward compatibility with the original keycode-only macro files.
5+
# The third item for each macro is a list in brackets, and each value within
6+
# is normally an integer (Keycode), float (delay) or string (typed literally).
7+
# Consumer Control codes are distinguished by enclosing them in a list within
8+
# the list, which is why you'll see double brackets [[ ]] below.
9+
# Like Keycodes, Consumer Control codes can be positive (press) or negative
10+
# (release), and float values can be inserted for pauses.
11+
12+
# To reference Consumer Control codes, import ConsumerControlCode like so...
13+
from adafruit_hid.consumer_control_code import ConsumerControlCode
14+
# You can still import Keycode as well if a macro file mixes types!
15+
# See other macro files for typical Keycode examples.
16+
17+
app = { # REQUIRED dict, must be named 'app'
18+
'name' : 'Media', # Application name
19+
'macros' : [ # List of button macros...
20+
# COLOR LABEL KEY SEQUENCE
21+
# 1st row ----------
22+
(0x000000, '', []),
23+
(0x000020, 'Vol+', [[ConsumerControlCode.VOLUME_INCREMENT]]),
24+
(0x202020, 'Bright+', [[ConsumerControlCode.BRIGHTNESS_INCREMENT]]),
25+
# 2nd row ----------
26+
(0x000000, '', []),
27+
(0x000020, 'Vol-', [[ConsumerControlCode.VOLUME_DECREMENT]]),
28+
(0x202020, 'Bright-', [[ConsumerControlCode.BRIGHTNESS_DECREMENT]]),
29+
# 3rd row ----------
30+
(0x000000, '', []),
31+
(0x200000, 'Mute', [[ConsumerControlCode.MUTE]]),
32+
(0x000000, '', []),
33+
# 4th row ----------
34+
(0x202000, '<<', [[ConsumerControlCode.SCAN_PREVIOUS_TRACK]]),
35+
(0x002000, 'Play/Pause', [[ConsumerControlCode.PLAY_PAUSE]]),
36+
(0x202000, '>>', [[ConsumerControlCode.SCAN_NEXT_TRACK]]),
37+
# Encoder button ---
38+
(0x000000, '', [])
39+
]
40+
}

Macropad_Hotkeys/macros/minecraft-messages.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,16 @@
88

99
# NOTE: There appears to be some delay when bringing up the command screen.
1010

11-
DELAY_AFTER_SLASH = 0.80 # required so minecraft has time to bring up command screen
11+
DELAY_AFTER_SLASH = 0.80 # required so minecraft has time to bring up command screen
1212
DELAY_BEFORE_RETURN = 0.10
1313

1414
# NOTE: On PC, characters are sometimes lost due to lag. No simple fix for
1515
# lost keystrokes is known. However, the commands do work most of the time.
1616

1717

18-
app = { # REQUIRED dict, must be named 'app'
19-
'name' : 'Minecraft (/msg)', # Application name
20-
'macros' : [ # List of button macros...
18+
app = { # REQUIRED dict, must be named 'app'
19+
'name' : 'Minecraft (/msg)', # Application name
20+
'macros' : [ # List of button macros...
2121
# COLOR LABEL KEY SEQUENCE
2222
# 1st row ----------
2323
(0x000020, 'list', [
@@ -33,13 +33,13 @@
3333
'list',
3434
DELAY_BEFORE_RETURN, Keycode.RETURN, -Keycode.RETURN]),
3535
# 2nd row ----------
36-
(0x000000, '', []),
37-
(0x000000, '', []),
38-
(0x000000, '', []),
36+
(0x000000, '', []),
37+
(0x000000, '', []),
38+
(0x000000, '', []),
3939
# 3rd row ----------
40-
(0x000000, '', []),
41-
(0x000000, '', []),
42-
(0x000000, '', []),
40+
(0x000000, '', []),
41+
(0x000000, '', []),
42+
(0x000000, '', []),
4343
# 4th row ----------
4444
(0x101010, 'bed', [
4545
'/', DELAY_AFTER_SLASH,

Macropad_Hotkeys/macros/minecraft-pe-effects.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,40 +8,40 @@
88

99
# See https://minecraft.fandom.com/wiki/Effect
1010

11-
DELAY_AFTER_SLASH = 0.80 # required so minecraft has time to bring up command screen
11+
DELAY_AFTER_SLASH = 0.80 # required so minecraft has time to bring up command screen
1212
DELAY_BEFORE_RETURN = 0.10 # give minecraft time to show all the keys pressed...
1313

14-
app = { # REQUIRED dict, must be named 'app'
15-
'name' : 'Minecraft PE (effect)', # Application name
14+
app = { # REQUIRED dict, must be named 'app'
15+
'name' : 'Minecraft PE (effect)', # Application name
1616
#
1717
# /effect <player: target> <effect: Effect>
1818
# [seconds: int] [amplifier: int] [hideParticles: Boolean]
1919
#
20-
'macros' : [ # List of button macros...
20+
'macros' : [ # List of button macros...
2121
# COLOR LABEL KEY SEQUENCE
2222
# 1st row ----------
23-
(0x002000, 'speed', [
23+
(0x002000, 'speed', [
2424
'/', DELAY_AFTER_SLASH,
2525
'effect @s speed 999999999 1 true',
2626
DELAY_BEFORE_RETURN, Keycode.RETURN, -Keycode.RETURN]),
27-
(0x002000, 'str', [
27+
(0x002000, 'str', [
2828
'/', DELAY_AFTER_SLASH,
2929
'effect @s strength 999999999 1 true',
3030
DELAY_BEFORE_RETURN, Keycode.RETURN, -Keycode.RETURN]),
31-
(0x002000, 'haste', [
31+
(0x002000, 'haste', [
3232
'/', DELAY_AFTER_SLASH,
3333
'effect @s haste 999999999 1 true',
3434
DELAY_BEFORE_RETURN, Keycode.RETURN, -Keycode.RETURN]),
3535
# 2nd row ----------
36-
(0x002000, 'jump', [
36+
(0x002000, 'jump', [
3737
'/', DELAY_AFTER_SLASH,
3838
'effect @s jump_boost 999999999 1 true',
3939
DELAY_BEFORE_RETURN, Keycode.RETURN, -Keycode.RETURN]),
4040
(0x000030, 'breath', [
4141
'/', DELAY_AFTER_SLASH,
4242
'effect @s water_breathing 999999999 0 true',
4343
DELAY_BEFORE_RETURN, Keycode.RETURN, -Keycode.RETURN]),
44-
(0x202020, 'darkv', [
44+
(0x202020, 'darkv', [
4545
'/', DELAY_AFTER_SLASH,
4646
'effect @s night_vision 999999999 0 true',
4747
DELAY_BEFORE_RETURN, Keycode.RETURN, -Keycode.RETURN]),
@@ -50,7 +50,7 @@
5050
'/', DELAY_AFTER_SLASH,
5151
'effect @s health_boost 999999999 4 true',
5252
DELAY_BEFORE_RETURN, Keycode.RETURN, -Keycode.RETURN]),
53-
(0x300000, 'regen', [
53+
(0x300000, 'regen', [
5454
'/', DELAY_AFTER_SLASH,
5555
'effect @s regeneration 999999999 4 true',
5656
DELAY_BEFORE_RETURN, Keycode.RETURN, -Keycode.RETURN]),
@@ -63,7 +63,7 @@
6363
'/', DELAY_AFTER_SLASH,
6464
'effect @s resistance 999999999 3 true',
6565
DELAY_BEFORE_RETURN, Keycode.RETURN, -Keycode.RETURN]),
66-
(0x101010, 'invis', [
66+
(0x101010, 'invis', [
6767
'/', DELAY_AFTER_SLASH,
6868
'effect @s invisibility 999999999 0 true',
6969
DELAY_BEFORE_RETURN, Keycode.RETURN, -Keycode.RETURN]),

Macropad_Hotkeys/macros/minecraft-pe-equip.py

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,9 @@
33
# Note: Must enable "full keyboad gameplay" to equip armor automatically.
44
# This is found under "settings", then "keyboard and mouse".
55

6-
# NOTE: There is a line length limit (? ~100 char ?). Exceeding that limit appears
7-
# to result in silent failure. Therefore, the key sequences are split
8-
# across multiple lines.
9-
10-
6+
# NOTE: There is a line length limit (? ~100 char ?). Exceeding that limit
7+
# appears to result in silent failure. Therefore, the key sequences are
8+
# split across multiple lines.
119

1210
from adafruit_hid.keycode import Keycode # REQUIRED if using Keycode.* values
1311

@@ -21,7 +19,7 @@
2119
# macro files before attempting to adjust settings in this one.
2220

2321
DELAY_AFTER_COMMAND = 0.75
24-
DELAY_AFTER_SLASH = 0.80 # required so minecraft has time to bring up command screen
22+
DELAY_AFTER_SLASH = 0.80 # required so minecraft has time to bring up command screen
2523
DELAY_BEFORE_RETURN = 0.10 # give minecraft time to show all the keys pressed...
2624

2725

Macropad_Hotkeys/macros/mouse.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# MACROPAD Hotkeys example: Mouse control
2+
3+
# The syntax for Mouse macros is highly peculiar, in order to maintain
4+
# backward compatibility with the original keycode-only macro files.
5+
# The third item for each macro is a list in brackets, and each value within
6+
# is normally an integer (Keycode), float (delay) or string (typed literally).
7+
# Consumer Control codes were added as list-within-list, and then mouse
8+
# further complicates this by adding dicts-within-list. Each mouse-related
9+
# dict can have any mix of keys 'buttons' w/integer mask of button values
10+
# (positive to press, negative to release), 'x' w/horizontal motion,
11+
# 'y' w/vertical and 'wheel' with scrollwheel motion.
12+
13+
# To reference Mouse constants, import Mouse like so...
14+
from adafruit_hid.mouse import Mouse
15+
# You can still import Keycode and/or ConsumerControl as well if a macro file
16+
# mixes types! See other macro files for typical Keycode examples.
17+
18+
app = { # REQUIRED dict, must be named 'app'
19+
'name' : 'Mouse', # Application name
20+
'macros' : [ # List of button macros...
21+
# COLOR LABEL KEY SEQUENCE
22+
# 1st row ----------
23+
(0x200000, 'L', [{'buttons':Mouse.LEFT_BUTTON}]),
24+
(0x202000, 'M', [{'buttons':Mouse.MIDDLE_BUTTON}]),
25+
(0x002000, 'R', [{'buttons':Mouse.RIGHT_BUTTON}]),
26+
# 2nd row ----------
27+
(0x000000, '', []),
28+
(0x202020, 'Up', [{'y':-10}]),
29+
(0x000000, '', []),
30+
# 3rd row ----------
31+
(0x202020, 'Left', [{'x':-10}]),
32+
(0x000000, '', []),
33+
(0x202020, 'Right', [{'x':10}]),
34+
# 4th row ----------
35+
(0x000000, '', []),
36+
(0x202020, 'Down', [{'y':10}]),
37+
(0x000000, '', []),
38+
# Encoder button ---
39+
(0x000000, '', [])
40+
]
41+
}

Macropad_Hotkeys/macros/numpad.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22

33
from adafruit_hid.keycode import Keycode # REQUIRED if using Keycode.* values
44

5-
app = { # REQUIRED dict, must be named 'app'
5+
app = { # REQUIRED dict, must be named 'app'
66
'name' : 'Numpad', # Application name
7-
'macros' : [ # List of button macros...
7+
'macros' : [ # List of button macros...
88
# COLOR LABEL KEY SEQUENCE
99
# 1st row ----------
1010
(0x202000, '7', ['7']),

0 commit comments

Comments
 (0)