streamdeck 0.9.4__tar.gz → 0.9.5__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. {streamdeck-0.9.4 → streamdeck-0.9.5}/CHANGELOG +3 -0
  2. {streamdeck-0.9.4 → streamdeck-0.9.5}/PKG-INFO +8 -2
  3. {streamdeck-0.9.4 → streamdeck-0.9.5}/README.md +7 -1
  4. streamdeck-0.9.5/VERSION +1 -0
  5. {streamdeck-0.9.4 → streamdeck-0.9.5}/src/StreamDeck/DeviceManager.py +3 -0
  6. {streamdeck-0.9.4 → streamdeck-0.9.5}/src/StreamDeck/Devices/StreamDeck.py +228 -11
  7. {streamdeck-0.9.4 → streamdeck-0.9.5}/src/StreamDeck/Devices/StreamDeckMini.py +8 -3
  8. {streamdeck-0.9.4 → streamdeck-0.9.5}/src/StreamDeck/Devices/StreamDeckOriginal.py +8 -3
  9. {streamdeck-0.9.4 → streamdeck-0.9.5}/src/StreamDeck/Devices/StreamDeckOriginalV2.py +8 -3
  10. {streamdeck-0.9.4 → streamdeck-0.9.5}/src/StreamDeck/Devices/StreamDeckPedal.py +8 -3
  11. streamdeck-0.9.5/src/StreamDeck/Devices/StreamDeckPlus.py +479 -0
  12. {streamdeck-0.9.4 → streamdeck-0.9.5}/src/StreamDeck/Devices/StreamDeckXL.py +8 -3
  13. streamdeck-0.9.5/src/StreamDeck/ImageHelpers/PILHelper.py +194 -0
  14. {streamdeck-0.9.4 → streamdeck-0.9.5}/src/StreamDeck/ProductIDs.py +3 -2
  15. {streamdeck-0.9.4 → streamdeck-0.9.5}/src/StreamDeck/Transport/LibUSBHIDAPI.py +22 -135
  16. {streamdeck-0.9.4 → streamdeck-0.9.5}/src/StreamDeck/Transport/Transport.py +1 -1
  17. {streamdeck-0.9.4 → streamdeck-0.9.5}/src/example_animated.py +2 -2
  18. {streamdeck-0.9.4 → streamdeck-0.9.5}/src/example_basic.py +2 -2
  19. {streamdeck-0.9.4 → streamdeck-0.9.5}/src/example_deckinfo.py +15 -6
  20. streamdeck-0.9.5/src/example_plus.py +135 -0
  21. {streamdeck-0.9.4 → streamdeck-0.9.5}/src/example_tileimage.py +2 -2
  22. {streamdeck-0.9.4 → streamdeck-0.9.5}/src/streamdeck.egg-info/PKG-INFO +8 -2
  23. {streamdeck-0.9.4 → streamdeck-0.9.5}/src/streamdeck.egg-info/SOURCES.txt +4 -1
  24. streamdeck-0.9.5/test/test.py +128 -0
  25. streamdeck-0.9.4/VERSION +0 -1
  26. streamdeck-0.9.4/src/StreamDeck/ImageHelpers/PILHelper.py +0 -108
  27. {streamdeck-0.9.4 → streamdeck-0.9.5}/ExampleDeck.jpg +0 -0
  28. {streamdeck-0.9.4 → streamdeck-0.9.5}/LICENSE +0 -0
  29. {streamdeck-0.9.4 → streamdeck-0.9.5}/MANIFEST.in +0 -0
  30. {streamdeck-0.9.4 → streamdeck-0.9.5}/setup.cfg +0 -0
  31. {streamdeck-0.9.4 → streamdeck-0.9.5}/setup.py +0 -0
  32. {streamdeck-0.9.4 → streamdeck-0.9.5}/src/Assets/Apache License 2.0.txt +0 -0
  33. {streamdeck-0.9.4 → streamdeck-0.9.5}/src/Assets/Attribution.txt +0 -0
  34. {streamdeck-0.9.4 → streamdeck-0.9.5}/src/Assets/CC BY-SA 3.0 License.txt +0 -0
  35. {streamdeck-0.9.4 → streamdeck-0.9.5}/src/Assets/CC0 License.txt +0 -0
  36. {streamdeck-0.9.4 → streamdeck-0.9.5}/src/Assets/Elephant_Walking_animated.gif +0 -0
  37. {streamdeck-0.9.4 → streamdeck-0.9.5}/src/Assets/Exit.png +0 -0
  38. {streamdeck-0.9.4 → streamdeck-0.9.5}/src/Assets/Harold.jpg +0 -0
  39. {streamdeck-0.9.4 → streamdeck-0.9.5}/src/Assets/Pressed.png +0 -0
  40. {streamdeck-0.9.4 → streamdeck-0.9.5}/src/Assets/RGB_color_space_animated_view.gif +0 -0
  41. {streamdeck-0.9.4 → streamdeck-0.9.5}/src/Assets/Released.png +0 -0
  42. {streamdeck-0.9.4 → streamdeck-0.9.5}/src/Assets/Roboto-Regular.ttf +0 -0
  43. {streamdeck-0.9.4 → streamdeck-0.9.5}/src/Assets/Simple_CV_Joint_animated.gif +0 -0
  44. {streamdeck-0.9.4 → streamdeck-0.9.5}/src/StreamDeck/Devices/__init__.py +0 -0
  45. {streamdeck-0.9.4 → streamdeck-0.9.5}/src/StreamDeck/ImageHelpers/__init__.py +0 -0
  46. {streamdeck-0.9.4 → streamdeck-0.9.5}/src/StreamDeck/Transport/Dummy.py +0 -0
  47. {streamdeck-0.9.4 → streamdeck-0.9.5}/src/StreamDeck/Transport/__init__.py +0 -0
  48. {streamdeck-0.9.4 → streamdeck-0.9.5}/src/StreamDeck/__init__.py +0 -0
  49. {streamdeck-0.9.4 → streamdeck-0.9.5}/src/example_pedal.py +0 -0
  50. {streamdeck-0.9.4 → streamdeck-0.9.5}/src/streamdeck.egg-info/dependency_links.txt +0 -0
  51. {streamdeck-0.9.4 → streamdeck-0.9.5}/src/streamdeck.egg-info/top_level.txt +0 -0
@@ -1,3 +1,6 @@
1
+ Version 0.9.5:
2
+ - Added support for the StreamDeck Plus.
3
+
1
4
  Version 0.9.4:
2
5
  - Updated Windows HIDAPI backend to attempt to load from the local working directory.
3
6
  - Added detection for MacOS Homebrew installations of the libhidapi back-end library.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: streamdeck
3
- Version: 0.9.4
3
+ Version: 0.9.5
4
4
  Summary: Library to control Elgato StreamDeck devices.
5
5
  Home-page: https://github.com/abcminiuser/python-elgato-streamdeck
6
6
  Author: Dean Camera
@@ -32,6 +32,7 @@ Description: # Python Elgato Stream Deck Library
32
32
  * StreamDeck Mini
33
33
  * StreamDeck XL
34
34
  * StreamDeck Pedal
35
+ * StreamDeck Plus
35
36
 
36
37
 
37
38
  ## Package Installation:
@@ -57,14 +58,18 @@ Description: # Python Elgato Stream Deck Library
57
58
  ## Credits:
58
59
 
59
60
  I've used the reverse engineering notes from
60
- [this GitHub](https://github.com/Lange/node-elgato-stream-deck/blob/master/NOTES.md)
61
+ [this GitHub](https://github.com/alvancamp/node-elgato-stream-deck/blob/master/NOTES.md)
61
62
  repository to implement this library. Thanks Alex Van Camp!
62
63
 
63
64
  Thank you to the following contributors, large and small, for helping with the
64
65
  development and maintenance of this library:
65
66
 
67
+ - [admiral0](https://github.com/admiral0)
66
68
  - [Aetherdyne](https://github.com/Aetherdyne)
69
+ - [benedikt-bartscher](https://github.com/benedikt-bartscher)
70
+ - [brimston3](https://github.com/brimston3)
67
71
  - [BS-Tek](https://github.com/BS-Tek)
72
+ - [Core447](https://github.com/Core447)
68
73
  - [dirkk0](https://github.com/dirkk0)
69
74
  - [dodgyrabbit](https://github.com/dodgyrabbit)
70
75
  - [dubstech](https://github.com/dubstech)
@@ -72,6 +77,7 @@ Description: # Python Elgato Stream Deck Library
72
77
  - [jakobbuis](https://github.com/jakobbuis)
73
78
  - [jmudge14](https://github.com/jmudge14)
74
79
  - [Kalle-Wirsch](https://github.com/Kalle-Wirsch)
80
+ - [karstlok](https://github.com/karstlok)
75
81
  - [Lewiscowles1986](https://github.com/Lewiscowles1986)
76
82
  - [m-weigand](https://github.com/m-weigand)
77
83
  - [matrixinius](https://github.com/matrixinius)
@@ -24,6 +24,7 @@ variants:
24
24
  * StreamDeck Mini
25
25
  * StreamDeck XL
26
26
  * StreamDeck Pedal
27
+ * StreamDeck Plus
27
28
 
28
29
 
29
30
  ## Package Installation:
@@ -49,14 +50,18 @@ directory.
49
50
  ## Credits:
50
51
 
51
52
  I've used the reverse engineering notes from
52
- [this GitHub](https://github.com/Lange/node-elgato-stream-deck/blob/master/NOTES.md)
53
+ [this GitHub](https://github.com/alvancamp/node-elgato-stream-deck/blob/master/NOTES.md)
53
54
  repository to implement this library. Thanks Alex Van Camp!
54
55
 
55
56
  Thank you to the following contributors, large and small, for helping with the
56
57
  development and maintenance of this library:
57
58
 
59
+ - [admiral0](https://github.com/admiral0)
58
60
  - [Aetherdyne](https://github.com/Aetherdyne)
61
+ - [benedikt-bartscher](https://github.com/benedikt-bartscher)
62
+ - [brimston3](https://github.com/brimston3)
59
63
  - [BS-Tek](https://github.com/BS-Tek)
64
+ - [Core447](https://github.com/Core447)
60
65
  - [dirkk0](https://github.com/dirkk0)
61
66
  - [dodgyrabbit](https://github.com/dodgyrabbit)
62
67
  - [dubstech](https://github.com/dubstech)
@@ -64,6 +69,7 @@ development and maintenance of this library:
64
69
  - [jakobbuis](https://github.com/jakobbuis)
65
70
  - [jmudge14](https://github.com/jmudge14)
66
71
  - [Kalle-Wirsch](https://github.com/Kalle-Wirsch)
72
+ - [karstlok](https://github.com/karstlok)
67
73
  - [Lewiscowles1986](https://github.com/Lewiscowles1986)
68
74
  - [m-weigand](https://github.com/m-weigand)
69
75
  - [matrixinius](https://github.com/matrixinius)
@@ -0,0 +1 @@
1
+ 0.9.5
@@ -10,6 +10,7 @@ from .Devices.StreamDeckOriginal import StreamDeckOriginal
10
10
  from .Devices.StreamDeckOriginalV2 import StreamDeckOriginalV2
11
11
  from .Devices.StreamDeckXL import StreamDeckXL
12
12
  from .Devices.StreamDeckPedal import StreamDeckPedal
13
+ from .Devices.StreamDeckPlus import StreamDeckPlus
13
14
  from .Transport.Dummy import Dummy
14
15
  from .Transport.LibUSBHIDAPI import LibUSBHIDAPI
15
16
  from .ProductIDs import USBVendorIDs, USBProductIDs
@@ -38,6 +39,7 @@ class DeviceManager:
38
39
  USB_PID_STREAMDECK_XL = 0x006c
39
40
  USB_PID_STREAMDECK_MK2 = 0x0080
40
41
  USB_PID_STREAMDECK_PEDAL = 0x0086
42
+ USB_PID_STREAMDECK_PLUS = 0x0084
41
43
 
42
44
  @staticmethod
43
45
  def _get_transport(transport):
@@ -108,6 +110,7 @@ class DeviceManager:
108
110
  (USBVendorIDs.USB_VID_ELGATO, USBProductIDs.USB_PID_STREAMDECK_PEDAL, StreamDeckPedal),
109
111
  (USBVendorIDs.USB_VID_ELGATO, USBProductIDs.USB_PID_STREAMDECK_MINI_MK2, StreamDeckMini),
110
112
  (USBVendorIDs.USB_VID_ELGATO, USBProductIDs.USB_PID_STREAMDECK_XL_V2, StreamDeckXL),
113
+ (USBVendorIDs.USB_VID_ELGATO, USBProductIDs.USB_PID_STREAMDECK_PLUS, StreamDeckPlus),
111
114
  ]
112
115
 
113
116
  streamdecks = list()
@@ -8,10 +8,41 @@
8
8
  import threading
9
9
  import time
10
10
  from abc import ABC, abstractmethod
11
+ from enum import Enum
11
12
 
12
13
  from ..Transport.Transport import TransportError
13
14
 
14
15
 
16
+ class TouchscreenEventType(Enum):
17
+ """
18
+ Type of event that has occurred for a Touchscreen.
19
+ """
20
+
21
+ SHORT = 1
22
+ LONG = 2
23
+ DRAG = 3
24
+
25
+
26
+ class DialEventType(Enum):
27
+ """
28
+ Type of event that has occurred for a Dial.
29
+ """
30
+ TURN = 1
31
+ PUSH = 2
32
+
33
+
34
+ class ControlType(Enum):
35
+ """
36
+ Type of control. This is used when returning internal events from a
37
+ StreamDeck subclass.
38
+
39
+ :meta private:
40
+ """
41
+ KEY = 1
42
+ DIAL = 2
43
+ TOUCHSCREEN = 3
44
+
45
+
15
46
  class StreamDeck(ABC):
16
47
  """
17
48
  Represents a physically attached StreamDeck device.
@@ -27,16 +58,29 @@ class StreamDeck(ABC):
27
58
  KEY_FLIP = (False, False)
28
59
  KEY_ROTATION = 0
29
60
 
61
+ TOUCHSCREEN_PIXEL_WIDTH = 0
62
+ TOUCHSCREEN_PIXEL_HEIGHT = 0
63
+ TOUCHSCREEN_IMAGE_FORMAT = ""
64
+ TOUCHSCREEN_FLIP = (False, False)
65
+ TOUCHSCREEN_ROTATION = 0
66
+
67
+ DIAL_COUNT = 0
68
+
30
69
  DECK_TYPE = ""
31
70
  DECK_VISUAL = False
71
+ DECK_TOUCH = False
32
72
 
33
73
  def __init__(self, device):
34
74
  self.device = device
35
75
  self.last_key_states = [False] * self.KEY_COUNT
76
+ self.last_dial_states = [False] * self.DIAL_COUNT
36
77
  self.read_thread = None
37
78
  self.run_read_thread = False
38
79
  self.read_poll_hz = 20
80
+
39
81
  self.key_callback = None
82
+ self.dial_callback = None
83
+ self.touchscreen_callback = None
40
84
 
41
85
  self.update_lock = threading.RLock()
42
86
 
@@ -72,12 +116,11 @@ class StreamDeck(ABC):
72
116
  self.update_lock.release()
73
117
 
74
118
  @abstractmethod
75
- def _read_key_states(self):
119
+ def _read_control_states(self):
76
120
  """
77
121
  Reads the raw key states from an attached StreamDeck.
78
122
 
79
- :rtype: list(bool)
80
- :return: List containing the raw key states.
123
+ :return: dictionary containing states for all controls
81
124
  """
82
125
  pass
83
126
 
@@ -107,18 +150,34 @@ class StreamDeck(ABC):
107
150
  """
108
151
  while self.run_read_thread:
109
152
  try:
110
- new_key_states = self._read_key_states()
111
- if new_key_states is None:
153
+ control_states = self._read_control_states()
154
+ if control_states is None:
112
155
  time.sleep(1.0 / self.read_poll_hz)
113
156
  continue
114
157
 
115
- if self.key_callback is not None:
116
- for k, (old, new) in enumerate(zip(self.last_key_states, new_key_states)):
158
+ if ControlType.KEY in control_states and self.key_callback is not None:
159
+ for k, (old, new) in enumerate(zip(self.last_key_states, control_states[ControlType.KEY])):
117
160
  if old != new:
118
161
  self.key_callback(self, k, new)
162
+ self.last_key_states = control_states[ControlType.KEY]
163
+
164
+ elif ControlType.DIAL in control_states and self.dial_callback is not None:
165
+ if DialEventType.PUSH in control_states[ControlType.DIAL]:
166
+ for k, (old, new) in enumerate(zip(self.last_dial_states,
167
+ control_states[ControlType.DIAL][DialEventType.PUSH])):
168
+ if old != new:
169
+ self.dial_callback(self, k, DialEventType.PUSH, new)
170
+ self.last_dial_states = control_states[ControlType.DIAL][DialEventType.PUSH]
119
171
 
120
- self.last_key_states = new_key_states
121
- except (TransportError):
172
+ if DialEventType.TURN in control_states[ControlType.DIAL]:
173
+ for k, amount in enumerate(control_states[ControlType.DIAL][DialEventType.TURN]):
174
+ if amount != 0:
175
+ self.dial_callback(self, k, DialEventType.TURN, amount)
176
+
177
+ elif ControlType.TOUCHSCREEN in control_states and self.touchscreen_callback is not None:
178
+ self.touchscreen_callback(self, *control_states[ControlType.TOUCHSCREEN])
179
+
180
+ except TransportError:
122
181
  self.run_read_thread = False
123
182
  self.close()
124
183
 
@@ -223,12 +282,21 @@ class StreamDeck(ABC):
223
282
  """
224
283
  return self.KEY_COUNT
225
284
 
285
+ def dial_count(self):
286
+ """
287
+ Retrieves number of physical dials on the attached StreamDeck device.
288
+
289
+ :rtype: int
290
+ :return: Number of physical dials
291
+ """
292
+ return self.DIAL_COUNT
293
+
226
294
  def deck_type(self):
227
295
  """
228
296
  Retrieves the model of Stream Deck.
229
297
 
230
298
  :rtype: str
231
- :return: String containing the model name of the StreamDeck device..
299
+ :return: String containing the model name of the StreamDeck device.
232
300
  """
233
301
  return self.DECK_TYPE
234
302
 
@@ -241,6 +309,15 @@ class StreamDeck(ABC):
241
309
  """
242
310
  return self.DECK_VISUAL
243
311
 
312
+ def is_touch(self):
313
+ """
314
+ Returns whether the Stream Deck can receive touch events
315
+
316
+ :rtype: bool
317
+ :return: `True` if the deck can receive touch events, `False` otherwise
318
+ """
319
+ return self.DECK_TOUCH
320
+
244
321
  def key_layout(self):
245
322
  """
246
323
  Retrieves the physical button layout on the attached StreamDeck device.
@@ -269,6 +346,26 @@ class StreamDeck(ABC):
269
346
  'rotation': self.KEY_ROTATION,
270
347
  }
271
348
 
349
+ def touchscreen_image_format(self):
350
+ """
351
+ Retrieves the image format accepted by the touchscreen of the Stream
352
+ Deck. Images should be given in this format when drawing on
353
+ touchscreen.
354
+
355
+ .. seealso:: See :func:`~StreamDeck.set_touchscreen_image` method to
356
+ draw an image on the StreamDeck touchscreen.
357
+
358
+ :rtype: dict()
359
+ :return: Dictionary describing the various image parameters
360
+ (size, image format).
361
+ """
362
+ return {
363
+ 'size': (self.TOUCHSCREEN_PIXEL_WIDTH, self.TOUCHSCREEN_PIXEL_HEIGHT),
364
+ 'format': self.TOUCHSCREEN_IMAGE_FORMAT,
365
+ 'flip': self.TOUCHSCREEN_FLIP,
366
+ 'rotation': self.TOUCHSCREEN_ROTATION,
367
+ }
368
+
272
369
  def set_poll_frequency(self, hz):
273
370
  """
274
371
  Sets the frequency of the button polling reader thread, determining how
@@ -325,6 +422,94 @@ class StreamDeck(ABC):
325
422
 
326
423
  self.set_key_callback(callback)
327
424
 
425
+ def set_dial_callback(self, callback):
426
+ """
427
+ Sets the callback function called each time there is an interaction
428
+ with a dial on the StreamDeck.
429
+
430
+ .. note:: This callback will be fired from an internal reader thread.
431
+ Ensure that the given callback function is thread-safe.
432
+
433
+ .. note:: Only one callback can be registered at one time.
434
+
435
+ .. seealso:: See :func:`~StreamDeck.set_dial_callback_async` method
436
+ for a version compatible with Python 3 `asyncio`
437
+ asynchronous functions.
438
+
439
+ :param function callback: Callback function to fire each time a button
440
+ state changes.
441
+ """
442
+ self.dial_callback = callback
443
+
444
+ def set_dial_callback_async(self, async_callback, loop=None):
445
+ """
446
+ Sets the asynchronous callback function called each time there is an
447
+ interaction with a dial on the StreamDeck. The given callback should
448
+ be compatible with Python 3's `asyncio` routines.
449
+
450
+ .. note:: The asynchronous callback will be fired in a thread-safe
451
+ manner.
452
+
453
+ .. note:: This will override the callback (if any) set by
454
+ :func:`~StreamDeck.set_dial_callback`.
455
+
456
+ :param function async_callback: Asynchronous callback function to fire
457
+ each time a button state changes.
458
+ :param asyncio.loop loop: Asyncio loop to dispatch the callback into
459
+ """
460
+ import asyncio
461
+
462
+ loop = loop or asyncio.get_event_loop()
463
+
464
+ def callback(*args):
465
+ asyncio.run_coroutine_threadsafe(async_callback(*args), loop)
466
+
467
+ self.set_dial_callback(callback)
468
+
469
+ def set_touchscreen_callback(self, callback):
470
+ """
471
+ Sets the callback function called each time there is an interaction
472
+ with a touchscreen on the StreamDeck.
473
+
474
+ .. note:: This callback will be fired from an internal reader thread.
475
+ Ensure that the given callback function is thread-safe.
476
+
477
+ .. note:: Only one callback can be registered at one time.
478
+
479
+ .. seealso:: See :func:`~StreamDeck.set_touchscreen_callback_async`
480
+ method for a version compatible with Python 3 `asyncio`
481
+ asynchronous functions.
482
+
483
+ :param function callback: Callback function to fire each time a button
484
+ state changes.
485
+ """
486
+ self.touchscreen_callback = callback
487
+
488
+ def set_touchscreen_callback_async(self, async_callback, loop=None):
489
+ """
490
+ Sets the asynchronous callback function called each time there is an
491
+ interaction with the touchscreen on the StreamDeck. The given callback
492
+ should be compatible with Python 3's `asyncio` routines.
493
+
494
+ .. note:: The asynchronous callback will be fired in a thread-safe
495
+ manner.
496
+
497
+ .. note:: This will override the callback (if any) set by
498
+ :func:`~StreamDeck.set_touchscreen_callback`.
499
+
500
+ :param function async_callback: Asynchronous callback function to fire
501
+ each time a button state changes.
502
+ :param asyncio.loop loop: Asyncio loop to dispatch the callback into
503
+ """
504
+ import asyncio
505
+
506
+ loop = loop or asyncio.get_event_loop()
507
+
508
+ def callback(*args):
509
+ asyncio.run_coroutine_threadsafe(async_callback(*args), loop)
510
+
511
+ self.set_touchscreen_callback(callback)
512
+
328
513
  def key_states(self):
329
514
  """
330
515
  Retrieves the current states of the buttons on the StreamDeck.
@@ -336,6 +521,18 @@ class StreamDeck(ABC):
336
521
  """
337
522
  return self.last_key_states
338
523
 
524
+ def dial_states(self):
525
+ """
526
+ Retrieves the current states of the dials (pressed or not) on the
527
+ Stream Deck
528
+
529
+ :rtype: list(bool)
530
+ :return: List describing the current states of each of the dials on
531
+ the device (`True` if the dial is being pressed, `False`
532
+ otherwise).
533
+ """
534
+ return self.last_dial_states
535
+
339
536
  @abstractmethod
340
537
  def reset(self):
341
538
  """
@@ -382,7 +579,7 @@ class StreamDeck(ABC):
382
579
  image being set should be in the correct format for the device, as an
383
580
  enumerable collection of bytes.
384
581
 
385
- .. seealso:: See :func:`~StreamDeck.get_key_image_format` method for
582
+ .. seealso:: See :func:`~StreamDeck.key_image_format` method for
386
583
  information on the image format accepted by the device.
387
584
 
388
585
  :param int key: Index of the button whose image is to be updated.
@@ -391,3 +588,23 @@ class StreamDeck(ABC):
391
588
  color.
392
589
  """
393
590
  pass
591
+
592
+ @abstractmethod
593
+ def set_touchscreen_image(self, image, x_pos=0, y_pos=0, width=0, height=0):
594
+ """
595
+ Draws an image on the touchscreen in a certain position. The image
596
+ should be in the correct format for the devices, as an enumerable
597
+ collection of bytes.
598
+
599
+ .. seealso:: See :func:`~StreamDeck.touchscreen_image_format` method for
600
+ information on the image format accepted by the device.
601
+
602
+ :param enumerable image: Raw data of the image to set on the button.
603
+ If `None`, the touchscreen will be cleared.
604
+ :param int x_pos: Position on x axis of the image to draw
605
+ :param int y_pos: Position on y axis of the image to draw
606
+ :param int width: width of the image
607
+ :param int height: height of the image
608
+
609
+ """
610
+ pass
@@ -5,7 +5,7 @@
5
5
  # www.fourwalledcubicle.com
6
6
  #
7
7
 
8
- from .StreamDeck import StreamDeck
8
+ from .StreamDeck import StreamDeck, ControlType
9
9
  from ..ProductIDs import USBProductIDs
10
10
 
11
11
 
@@ -42,13 +42,15 @@ class StreamDeckMini(StreamDeck):
42
42
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00
43
43
  ] + [0] * (KEY_PIXEL_WIDTH * KEY_PIXEL_HEIGHT * 3)
44
44
 
45
- def _read_key_states(self):
45
+ def _read_control_states(self):
46
46
  states = self.device.read(1 + self.KEY_COUNT)
47
47
  if states is None:
48
48
  return None
49
49
 
50
50
  states = states[1:]
51
- return [bool(s) for s in states]
51
+ return {
52
+ ControlType.KEY: [bool(s) for s in states],
53
+ }
52
54
 
53
55
  def _reset_key_stream(self):
54
56
  payload = bytearray(self.IMAGE_REPORT_LENGTH)
@@ -116,3 +118,6 @@ class StreamDeckMini(StreamDeck):
116
118
 
117
119
  bytes_remaining = bytes_remaining - this_length
118
120
  page_number = page_number + 1
121
+
122
+ def set_touchscreen_image(self, image, x_pos=0, y_pos=0, width=0, height=0):
123
+ pass
@@ -5,7 +5,7 @@
5
5
  # www.fourwalledcubicle.com
6
6
  #
7
7
 
8
- from .StreamDeck import StreamDeck
8
+ from .StreamDeck import StreamDeck, ControlType
9
9
 
10
10
 
11
11
  class StreamDeckOriginal(StreamDeck):
@@ -44,13 +44,15 @@ class StreamDeckOriginal(StreamDeck):
44
44
  key_col = key % self.KEY_COLS
45
45
  return (key - key_col) + ((self.KEY_COLS - 1) - key_col)
46
46
 
47
- def _read_key_states(self):
47
+ def _read_control_states(self):
48
48
  states = self.device.read(1 + self.KEY_COUNT)
49
49
  if states is None:
50
50
  return None
51
51
 
52
52
  states = states[1:]
53
- return [bool(states[s]) for s in map(self._convert_key_id_origin, range(self.KEY_COUNT))]
53
+ return {
54
+ ControlType.KEY: [bool(states[s]) for s in map(self._convert_key_id_origin, range(self.KEY_COUNT))]
55
+ }
54
56
 
55
57
  def _reset_key_stream(self):
56
58
  payload = bytearray(self.IMAGE_REPORT_LENGTH)
@@ -120,3 +122,6 @@ class StreamDeckOriginal(StreamDeck):
120
122
 
121
123
  bytes_remaining = bytes_remaining - this_length
122
124
  page_number = page_number + 1
125
+
126
+ def set_touchscreen_image(self, image, x_pos=0, y_pos=0, width=0, height=0):
127
+ pass
@@ -5,7 +5,7 @@
5
5
  # www.fourwalledcubicle.com
6
6
  #
7
7
 
8
- from .StreamDeck import StreamDeck
8
+ from .StreamDeck import StreamDeck, ControlType
9
9
 
10
10
 
11
11
  class StreamDeckOriginalV2(StreamDeck):
@@ -73,13 +73,15 @@ class StreamDeckOriginalV2(StreamDeck):
73
73
  0x28, 0xa0, 0x0f, 0xff, 0xd9
74
74
  ]
75
75
 
76
- def _read_key_states(self):
76
+ def _read_control_states(self):
77
77
  states = self.device.read(4 + self.KEY_COUNT)
78
78
  if states is None:
79
79
  return None
80
80
 
81
81
  states = states[4:]
82
- return [bool(s) for s in states]
82
+ return {
83
+ ControlType.KEY: [bool(s) for s in states]
84
+ }
83
85
 
84
86
  def _reset_key_stream(self):
85
87
  payload = bytearray(self.IMAGE_REPORT_LENGTH)
@@ -138,3 +140,6 @@ class StreamDeckOriginalV2(StreamDeck):
138
140
 
139
141
  bytes_remaining = bytes_remaining - this_length
140
142
  page_number = page_number + 1
143
+
144
+ def set_touchscreen_image(self, image, x_pos=0, y_pos=0, width=0, height=0):
145
+ pass
@@ -5,7 +5,7 @@
5
5
  # www.fourwalledcubicle.com
6
6
  #
7
7
 
8
- from .StreamDeck import StreamDeck
8
+ from .StreamDeck import StreamDeck, ControlType
9
9
 
10
10
 
11
11
  class StreamDeckPedal(StreamDeck):
@@ -20,13 +20,15 @@ class StreamDeckPedal(StreamDeck):
20
20
  DECK_TYPE = "Stream Deck Pedal"
21
21
  DECK_VISUAL = False
22
22
 
23
- def _read_key_states(self):
23
+ def _read_control_states(self):
24
24
  states = self.device.read(4 + self.KEY_COUNT)
25
25
  if states is None:
26
26
  return None
27
27
 
28
28
  states = states[4:]
29
- return [bool(s) for s in states]
29
+ return {
30
+ ControlType.KEY: [bool(s) for s in states]
31
+ }
30
32
 
31
33
  def _reset_key_stream(self):
32
34
  pass
@@ -47,3 +49,6 @@ class StreamDeckPedal(StreamDeck):
47
49
 
48
50
  def set_key_image(self, key, image):
49
51
  pass
52
+
53
+ def set_touchscreen_image(self, image, x_pos=0, y_pos=0, width=0, height=0):
54
+ pass