Skip to content

Commit ce5268d

Browse files
committed
Implement resume from suspend
1 parent 9b80041 commit ce5268d

File tree

1 file changed

+62
-2
lines changed

1 file changed

+62
-2
lines changed

src/StreamDeck/Devices/StreamDeck.py

Lines changed: 62 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ class StreamDeck(ABC):
7878
DECK_VISUAL = False
7979
DECK_TOUCH = False
8080

81-
def __init__(self, device):
81+
def __init__(self, device, resume_from_suspend: bool = True):
8282
self.device = device
8383
self.last_key_states = [False] * (self.KEY_COUNT + self.TOUCH_KEY_COUNT)
8484
self.last_dial_states = [False] * self.DIAL_COUNT
@@ -200,6 +200,63 @@ def _read(self):
200200
self.run_read_thread = False
201201
self.close()
202202

203+
def _read_with_resume_from_suspend(self):
204+
"""
205+
Read handler for the underlying transport, listening for button state
206+
changes on the underlying device, caching the new states and firing off
207+
any registered callbacks.
208+
"""
209+
while self.run_read_thread:
210+
try:
211+
control_states = self._read_control_states()
212+
if control_states is None:
213+
time.sleep(1.0 / self.read_poll_hz)
214+
continue
215+
216+
if ControlType.KEY in control_states and self.key_callback is not None:
217+
for k, (old, new) in enumerate(zip(self.last_key_states, control_states[ControlType.KEY])):
218+
if old != new:
219+
self.last_key_states[k] = new
220+
self.key_callback(self, k, new)
221+
222+
elif ControlType.DIAL in control_states and self.dial_callback is not None:
223+
if DialEventType.PUSH in control_states[ControlType.DIAL]:
224+
for k, (old, new) in enumerate(zip(self.last_dial_states,
225+
control_states[ControlType.DIAL][DialEventType.PUSH])):
226+
if old != new:
227+
self.last_dial_states[k] = new
228+
self.dial_callback(self, k, DialEventType.PUSH, new)
229+
230+
if DialEventType.TURN in control_states[ControlType.DIAL]:
231+
for k, amount in enumerate(control_states[ControlType.DIAL][DialEventType.TURN]):
232+
if amount != 0:
233+
self.dial_callback(self, k, DialEventType.TURN, amount)
234+
235+
elif ControlType.TOUCHSCREEN in control_states and self.touchscreen_callback is not None:
236+
self.touchscreen_callback(self, *control_states[ControlType.TOUCHSCREEN])
237+
238+
except TransportError:
239+
self.run_read_thread = False
240+
self.close()
241+
242+
if self.reconnect_after_suspend:
243+
if self.connected() and not self.is_open():
244+
# This is the case when resuming from suspend
245+
TIMEOUT = 10
246+
start_time = time.time()
247+
while True:
248+
try:
249+
self.open()
250+
break
251+
except TransportError:
252+
time.sleep(0.1)
253+
254+
if not self.connected():
255+
break
256+
257+
if time.time() - start_time > TIMEOUT:
258+
break
259+
203260
def _setup_reader(self, callback):
204261
"""
205262
Sets up the internal transport reader thread with the given callback,
@@ -233,7 +290,10 @@ def open(self):
233290
self.device.open()
234291

235292
self._reset_key_stream()
236-
self._setup_reader(self._read)
293+
if self.resume_from_suspend:
294+
self._setup_reader(self._read_with_resume_from_suspend)
295+
else:
296+
self._setup_reader(self._read)
237297

238298
def close(self):
239299
"""

0 commit comments

Comments
 (0)