Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature img #1

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions sample-page.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"onRelease": "<ActionKey>"
},
"text": {
"fontSize": <int>,
"default": "<str>",
"pressed": "<str>"
},
Expand Down
211 changes: 175 additions & 36 deletions stream-deck.py
Original file line number Diff line number Diff line change
@@ -1,44 +1,183 @@
from stream_deck import Page
from stream_deck.button import Button
#!/usr/bin/env python3


import os
import subprocess
from sre_constants import SUCCESS
import threading

from PIL import Image, ImageDraw, ImageFont

from StreamDeck.DeviceManager import DeviceManager
from StreamDeck.ImageHelpers import PILHelper

from stream_deck import Page, Button


ASSETS_PATH = os.path.join(os.path.dirname(__file__), "Assets")


def render_key_image(deck, icon_filename, font_filename, font_size, label_text):
icon = Image.open(icon_filename)
image = PILHelper.create_scaled_image(deck, icon, margins=[0, 0, 0, 0])
draw = ImageDraw.Draw(image)
font = ImageFont.truetype(font_filename, font_size)

draw.text((image.width / 2, image.height - 5), text=label_text,
font=font, anchor="ms", fill="white")
return PILHelper.to_native_format(deck, image)


def update_key_image(deck, key, *, image, font, font_size, action, text, state):
image = render_key_image(deck, image, font, font_size, text)
# lock access
with deck:
deck.set_key_image(key, image)


def key_change_callback(deck, key, state, page: Page):
button_pressed = Button.from_key(Button, key)
print(button_pressed)
buttons_in_page = []
for button in page.buttonMapping.keys():
buttons_in_page.append(button)

if button_pressed not in buttons_in_page:
print("not a valid button")
return

button_type_key = page.buttonMapping.get(button_pressed)
button_type = page.types.get(button_type_key)

keys_images = button_type.images
keys_events = button_type.events
button_text = button_type.text
button_fonts = button_type.fonts

if state:
image = page.images.get(keys_images.pressed)
action = page.actions.get(keys_events.onPress)
text = button_text.pressed
font = button_fonts.default
else:
image = page.images.get(keys_images.default)
action = page.actions.get(keys_events.onRelease)
text = button_text.default
font = button_fonts.default

print(button_type_key)
print(image)
print(action)
print(text)

update_key_image(deck, key, image=image, font=font,
font_size=font_size, action=action, text=text, state=False)
print("Trying to execute the command")
print(action)
subprocess.call([action])
return


ref_page = {
"buttonMapping": {
"button-1": "play",
"button-2": "pause"
},
"images": {
"play": "playcast-play.png",
"pause": "pause.png",
"update-preview": "/tmp/playcast-client-stream-deck-preview.png"
},
"actions": {
"play": "play.sh"
},
"types": {
"play": {
"events": {
"onPress": "",
"onRelease": ""
},
"text": {
"default": "",
"pressed": ""
},
"images": {
"default": "play",
"pressed": "play"
}
}
"buttonMapping": {
"button-1": "play",
"button-2": "play",
"button-12": "play",
"button-22": "play",
"button-32": "play"
},
"images": {
"play": "/home/rubens/Documents/stream-deck/assets/viacast-logo-light.png",
"play-pressed": "/home/rubens/Documents/stream-deck/assets/viacast-logo-red.png",
"pause": "pause.png",
"update-preview": "/tmp/playcast-client-stream-deck-preview.png"
},
"actions": {
"play": "/home/rubens/Documents/stream-deck/calls/teste.sh"
},
"types": {
"play": {
"events": {
"onPress": "play",
"onRelease": ""
},
"text": {
"default": "Teste",
"pressed": "pressed",
"fontSize": 18
},
"fonts": {
"default": "/home/rubens/Documents/stream-deck/assets/Roboto-Regular.ttf",
"pressed": ""
},
"images": {
"default": "play",
"pressed": "play-pressed"
}
}
}
}


page = Page(**ref_page)
if __name__ == "__main__":
streamdecks = DeviceManager().enumerate()

for button, button_type_key in page.buttonMapping.items():
button_type = page.types.get(button_type_key)
if not button_type:
continue
images = button_type.images
print(button, button_type, images)
print("Found {} Stream Deck(s).\n".format(len(streamdecks)))

for index, deck in enumerate(streamdecks):
# This example only works with devices that have screens.
if not deck.is_visual():
continue

deck.open()
deck.reset()

print("Opened '{}' device (serial number: '{}', fw: '{}')".format(
deck.deck_type(), deck.get_serial_number(), deck.get_firmware_version()
))

# Set initial screen brightness to 30%.
deck.set_brightness(20)

# exit(SUCCESS)
page = Page(**ref_page)

for button, button_type_key in page.buttonMapping.items():

button_type = page.types.get(button_type_key)
if not button_type:
continue
keys_images = button_type.images
keys_events = button_type.events
button_text = button_type.text
button_fonts = button_type.fonts

index = button.get_key()
image = page.images.get(keys_images.default)
action = page.actions.get(keys_events.onPress)
text = button_text.default
font = button_fonts.default
font_size = button_text.fontSize

print(button.get_key())
print(button_type_key)
print(image)
print(action)
print(text)

update_key_image(deck, index, image=image, font=font,
font_size=font_size, action=action, text=text, state=False)

# exit(SUCCESS)

# # Register callback function for when a key state changes.
deck.set_key_callback(
lambda deck, key, state: key_change_callback(deck, key, state, page))

# # Wait until all application threads have terminated (for this example,
# # this is when all deck handles are closed).
for t in threading.enumerate():
try:
t.join()
except RuntimeError:
pass
10 changes: 10 additions & 0 deletions stream_deck/button.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@


class Button(Enum):
BUTTON_NULL = 'button-null'
BUTTON_1 = 'button-1'
BUTTON_2 = 'button-2'
BUTTON_3 = 'button-3'
Expand Down Expand Up @@ -34,3 +35,12 @@ class Button(Enum):
BUTTON_30 = 'button-30'
BUTTON_31 = 'button-31'
BUTTON_32 = 'button-32'

def get_key(self):
return list(Button).index(self) - 1

def from_key(self, key):
try:
return list(Button)[key + 1]
except IndexError:
return Button.BUTTON_NULL
8 changes: 4 additions & 4 deletions stream_deck/page.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@ class Page:

def __init__(self, buttonMapping: Dict[Button, TypeKey], images: Dict[ImageKey, ImagePath], actions: Dict[ActionKey, ActionPath], types: Dict[TypeKey, Type]) -> None:
self.buttonMapping = {
Button(k): v
for k, v in buttonMapping.items()
Button(k): v
for k, v in buttonMapping.items()
}
self.images = images
self.actions = actions
self.types = {
k: Type(**v)
for k, v in types.items()
k: Type(**v)
for k, v in types.items()
}

def __str__(self) -> str:
Expand Down
18 changes: 17 additions & 1 deletion stream_deck/type.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,20 @@ def __str__(self) -> str:
class ButtonText:
default: Optional[str]
pressed: Optional[str]
fontSize: Optional[int]

def __init__(self, default: str, pressed: str, fontSize: int) -> None:
self.default = default
self.pressed = pressed
self.fontSize = fontSize

def __str__(self) -> str:
return dumps(self, default=vars, indent=2)


class ButtonFont:
default: Optional[str]
pressed: Optional[str]

def __init__(self, default: str, pressed: str) -> None:
self.default = default
Expand All @@ -43,12 +57,14 @@ def __str__(self) -> str:
class Type:
events: ButtonEvents
text: ButtonText
fonts: ButtonFont
images: ButtonImages

def __init__(self, events: ButtonEvents, text: ButtonText, images: ButtonImages) -> None:
def __init__(self, events: ButtonEvents, text: ButtonText, images: ButtonImages, fonts: ButtonFont) -> None:
self.events = ButtonEvents(**events)
self.text = ButtonText(**text)
self.images = ButtonImages(**images)
self.fonts = ButtonFont(**fonts)

def __str__(self) -> str:
return dumps(self, default=vars, indent=2)