abcminiuser / python-elgato-streamdeck

Python library to control the Elgato Stream Deck.
Other
903 stars 134 forks source link

key_states() always return [False, False, ..., False] on Windows but registers keys fine on Linux #135

Closed Giraut closed 3 months ago

Giraut commented 7 months ago

This works fine in Linux:

from StreamDeck.DeviceManager import DeviceManager

streamdeck = DeviceManager().enumerate()[0]
streamdeck.open()

while not any(streamdeck.key_states()):
  pass

print("Key pressed")

streamdeck.close()

It never quits in Windows: key_states() never registers any keys and always returns a list of False states.

This is just a test code to highlight the issue, but I have a full application that uploads images to the keys, and it works on Windows as well as Linux. It's only key_states() that doesn't register keys.

Any idea?

Windows 11 Stream Deck Mk2 Python version 3.10.2 streamdeck version 0.9.5 hidapi.dll version 0.14.0

Thanks!

Giraut commented 7 months ago

Update: it has something to do with threading in Windows. This (non-threaded) code works both in Linux and Windows:

from StreamDeck.DeviceManager import DeviceManager

streamdeck = DeviceManager().enumerate()[0]
streamdeck.device.open()
streamdeck._reset_key_stream()

key_states = []
while not any(key_states):
  states = streamdeck.device.read(4 + streamdeck.KEY_COUNT)
  key_states = [bool(s) for s in states[4:]] if states is not None else [False] * streamdeck.KEY_COUNT 

streamdeck.device.close()

So, problem solved as far as I'm concerned, because my application is a one-off and already does run a tight loop to do graphical display updates, so I can poll the Stream Deck's keys myself in the main loop and I don't need the Python streamdeck module's own threading scheme to do it. But it's not a generic solution: it just works for me and for my particular Stream Deck model but it's dirty.

I reckon the module should provide a simple open and a simple function to poll the state of the keys without doing any threading, so the caller can do its own multithreading / multiprocessing any way it sees fit anyway.

abcminiuser commented 3 months ago

This works on my Windows machine, however note that the current 0.9.5 version of the library requires a callback set for the key states to be updated (without a callback set the reader thread will not update the cached key states).

I'm using the stock Python interpreter. It's not a good idea to spinloop like in your example code however - sleeping for a few milliseconds will greatly reduce the CPU usage.

abcminiuser commented 3 months ago

Polling of keys with no callback set is now implemented in 9cbcc113920bda159f1792b886f4a3e98173fd12 .