-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathpixel-buds-a-series-slides-control.py
99 lines (79 loc) · 2.71 KB
/
pixel-buds-a-series-slides-control.py
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
import time
import keyboard
import platform
from config import NEXT_PAGE_KEY, PREV_PAGE_KEY, START_KEY
# dummy class
class ScanCode(object):
PLAY_PAUSE = None
NEXT_TRACK = None
PREV_TRACK = None
class Controller:
scan_code = ScanCode
def __init__(self) -> None:
# For Pixel Buds A-Series, it would send "play/pause media" right after "next/previous track" occurs.
self.lock = False
self.hooks = dict()
self.keys = [self.scan_code.PLAY_PAUSE, self.scan_code.NEXT_TRACK, self.scan_code.PREV_TRACK]
def next_page(self, _ev: keyboard.KeyboardEvent):
if not self.lock:
keyboard.send(NEXT_PAGE_KEY)
self.lock = False
def last_page(self, _ev: keyboard.KeyboardEvent):
self.lock = True # lock "play/pause media" once
keyboard.send(PREV_PAGE_KEY)
def start_presenation(self, _ev: keyboard.KeyboardEvent):
self.lock = True
keyboard.send(START_KEY)
def bind_hook(self):
for code in self.keys:
# clean up old one
if self.hooks.get(code):
keyboard.unhook_key(self.hooks[code])
hook = keyboard.on_press_key(code, self.hook, suppress=True)
self.hooks[code] = hook
def unbind_hook(self):
for code in list(self.hooks.keys()):
keyboard.unhook_key(self.hooks[code])
self.hooks.pop(code)
def hook(self, ev: keyboard.KeyboardEvent):
if ev.scan_code == self.scan_code.PLAY_PAUSE:
self.next_page(ev)
elif ev.scan_code == self.scan_code.NEXT_TRACK:
self.last_page(ev)
elif ev.scan_code == self.scan_code.PREV_TRACK:
self.start_presenation(ev)
else:
# propagate all other keys
keyboard.send(ev.name)
def loop(self):
# return until Ctrl+C
while True:
try:
time.sleep(100)
except KeyboardInterrupt:
return
# Scan Codes for Windows
class Win_ScanCode(ScanCode):
PLAY_PAUSE = -179
NEXT_TRACK = -176
PREV_TRACK = -177
class WindowsController(Controller):
scan_code = Win_ScanCode
class Linux_ScanCode(ScanCode):
PLAY_PAUSE = 200
NEXT_TRACK = 163
PREV_TRACK = 165
class LinuxController(Controller):
scan_code = Linux_ScanCode
if __name__ == "__main__":
if platform.system() == "Windows":
controller = WindowsController()
elif platform.system() == "Linux":
controller = LinuxController()
else:
raise OSError("Unsupported platform '{}'".format(platform.system()))
print("Start hijacking media buttons!")
controller.bind_hook()
controller.loop()
controller.unbind_hook()
print("Exited.")